Skip to content

hirsimaki-markus/ghostdrop

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

1 Commit
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

ghostdrop 👻

Upload view — ghostdrop title, limits, file selector

E2E encrypted, serverless, ephemeral full-stack file-drop demo on AWS. Upload a file in the browser and get a link; open the link elsewhere to download and decrypt. Built with React + Vite; infra and deployment via Terraform and the Makefile.


Quick start

After cloning, run help to see commands, then install and run the app:

/ghostdrop$ make help

  ┌─ Prerequisites ──────────────────────────────────────────────┐
  │ make install         Install app dependencies (for local)    │ <-- run this once
  │ make terraform-init  Initialize Terraform (for publish only) │
  └──────────────────────────────────────────────────────────────┘

  ┌─ Local (No backend; use browser storage) ────────────────────┐
  │ make local     Run web app in dev mode (hot reload)          │ <-- then this
  └──────────────────────────────────────────────────────────────┘

  ┌─ Remote deploy (Backend: API + S3 + CloudFront + WAF*) ──────┐
  │ make publish    Build SPA with API base, deploy              │
  │ make unpublish  Destroy deployed infra                       │
  │                                                              │
  │ *WAF: Nordic whitelist (FI, SE, NO, DK, IS) on CloudFront    │
  └──────────────────────────────────────────────────────────────┘

Run make install once, then make local. The app opens at http://localhost:5173. Constants and commands are defined in the Makefile.


Requirements

  • Local (make local): Node.js 20.19+ (see app/.nvmrc). Use nvm if needed: nvm install then nvm use.
  • Deploy (make publish / make unpublish): Node.js 20.19+, Terraform, AWS CLI, and AWS credentials (AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY, AWS_REGION).

Architecture

Deployed stack:

  • S3 (SPA) — Static site. No public access; only CloudFront via Origin Access Control (OAC). Unknown paths → index.html for fragment routing.
  • S3 (uploads) — Encrypted blobs. No public access; access only via presigned URLs from the Lambdas. Lifecycle: delete after 24h; abort incomplete multipart uploads after 24h. Keys: uploads/<uuid>.
  • CloudFront — In front of the SPA bucket. Security headers (CSP, X-Frame-Options, X-Content-Type-Options). Optional WAF (Nordic whitelist). Caching: default TTL; make publish invalidates so the new build is visible.
  • Lambda (upload signer) — Presigned POST for the uploads bucket. Enforces max size and path; short-lived. Via API Gateway.
  • Lambda (download signer) — Presigned GET for a given object ID (and size check). Via API Gateway.
  • API Gateway (HTTP API)POST /upload-url and POST /download-url. CORS restricted to CloudFront origin; rate limits.
     Browser (SPA)
          |
    1. Load app → CloudFront → S3 (SPA)
          |
    2. POST /upload-url → API Gateway → upload-signer → presigned POST → SPA
    3. SPA POSTs file → S3 (uploads)
          |
    4. POST /download-url → API Gateway → download-signer → presigned GET → SPA
    5. SPA GETs file → S3 (uploads)

Upload flow: User opens the CloudFront link. They pick a file; the browser encrypts it (AES-GCM, random key and nonce). The SPA gets a presigned POST from the upload-signer Lambda via API Gateway, then POSTs the encrypted bytes to the uploads bucket. The SPA builds a download link whose fragment holds the object ID, decryption key, nonce, and filename. Key and nonce stay in the fragment and are never sent to the server.

Download flow: User opens a link with a fragment. The SPA parses it (key, nonce, object ID, name), calls the download-signer Lambda for a presigned GET, fetches the ciphertext from S3, decrypts in the browser, and saves. Files in the bucket expire after 24h.


Project layout

Path Description
app/ React SPA (Vite). Entry: app/index.html, app/src/main.tsx.
terraform/ Infra (S3, Lambdas, API Gateway, CloudFront, WAF). Constants in the Makefile are passed via TF_VAR_* and VITE_*.
design_docs/ Design and requirements. See Documentation below.

Documentation

  • initial_plan.md — Product and infra overview: components, flows, deployment goal, Lambdas, S3, security, notes.
  • spa-design.md — SPA design: crypto, URL fragment format, upload/download flows, API contract, UX, constraints.

Terraform state

State is stored locally (e.g. terraform/terraform.tfstate). No remote backend or state locking. The project is meant to be deployed and torn down at will; a single operator can reproduce the stack from this repo and AWS credentials.


Later work

  • Geoblocking — WAF Nordic whitelist (FI, SE, NO, DK, IS) on CloudFront; see Makefile help. Affects only the SPA; API and S3 are not behind WAF.
  • Budget notifications — AWS Budget + SNS when cost exceeds a threshold.

About

AWS native serverless filedrop demo

Resources

License

Stars

1 star

Watchers

0 watching

Forks

Releases

No releases published

Packages

 
 
 

Contributors