Cloud Audit

Cloud infrastructure audit and multi-cloud design

Cloud Audit: Resource Inventory

Drop — AWS Resource Inventory

Date: 2026-02-19 Region: eu-west-1 (Ireland) Account: Drop production Auditor: infra-lead (CloudForge cloud-audit team) MC Task: #1443


Executive Summary

Drop runs a minimal AWS footprint: one App Runner service fronting a PostgreSQL RDS instance, with container images stored in ECR. Total estimated cost is $48-60/month.

Three CRITICAL security findings require immediate action:

  1. RDS database is publicly accessible with security group open to the entire internet (0.0.0.0/0 on port 5432)
  2. Database storage is unencrypted
  3. Plaintext secrets (DATABASE_URL with password, JWT_SECRET) in App Runner environment variables

No WAF, no CloudFront, no CloudWatch monitoring, no Route53 DNS management, and Secrets Manager is provisioned but empty.


Resource Table

Resource Type ID / Name Region Status Key Config
App Runner Service drop-web eu-west-1 RUNNING 1 vCPU, 2 GB RAM, port 3000
RDS PostgreSQL 16.6 drop-db eu-west-1a Available db.t3.micro, 20 GB gp3, single-AZ
ECR Repository drop-web eu-west-1 Active ScanOnPush: TRUE, Encryption: AES256
Security Group SG drop-db-sg eu-west-1 In use Inbound: 0.0.0.0/0 : 5432
VPC Default eu-west-1 Active 172.31.0.0/16
IAM User User john-deploy Global Active Programmatic access
IAM Role Role AppRunnerECRAccessRole Global Active ECR pull permissions
Secrets Manager (empty) eu-west-1 Provisioned 0 secrets stored
CloudWatch NOT CONFIGURED No alarms, no dashboards
CloudFront NOT PROVISIONED No CDN
WAF NOT PROVISIONED No web application firewall
Route53 NOT PROVISIONED DNS managed externally
S3 NOT PROVISIONED No buckets

Architecture Diagram

                         INTERNET
                            |
                            | HTTPS (public ingress)
                            v
                   +------------------+
                   |   App Runner     |
                   |   drop-web       |
                   |                  |
                   |  1 vCPU / 2 GB   |
                   |  Port 3000       |
                   |  ECR source      |
                   |                  |
                   |  ENV (plaintext):|
                   |  - DATABASE_URL  |
                   |  - JWT_SECRET    |
                   +--------+---------+
                            |
                            | VPC Connector (egress)
                            |
              +-------------+-------------+
              |       Default VPC         |
              |     172.31.0.0/16         |
              |                           |
              |   +-------------------+   |
              |   |  drop-db-sg       |   |
              |   |  0.0.0.0/0:5432   |   |
              |   +--------+----------+   |
              |            |              |
              |   +--------v----------+   |
              |   |   RDS             |   |
              |   |   drop-db         |   |
              |   |                   |   |
              |   |   PostgreSQL 16.6 |   |
              |   |   db.t3.micro     |   |
              |   |   20 GB gp3       |   |
              |   |   single-AZ (a)   |   |
              |   |                   |   |
              |   |   Public: YES     |   |
              |   |   Encrypted: NO   |   |
              |   |   Backup: 7 days  |   |
              |   |   DeletionProt: ON|   |
              |   |   Monitoring: OFF |   |
              |   +-------------------+   |
              +---------------------------+

        +----------+          +---------------------+
        |   ECR    |          |   Secrets Manager   |
        | drop-web |          |   (EMPTY)           |
        | ScanPush |          +---------------------+
        +----------+

        +----------+          +---------------------+
        |   IAM    |          |   MISSING           |
        | john-    |          |   CloudWatch        |
        |  deploy  |          |   CloudFront        |
        | ECR Role |          |   WAF / Route53 / S3|
        +----------+          +---------------------+

Security Findings

CRITICAL

# Finding Resource Risk Remediation
C1 Database publicly accessible RDS drop-db Direct internet access to PostgreSQL. Any attacker can attempt connections. Set PubliclyAccessible=false. App Runner already uses VPC Connector for egress — RDS only needs private subnet access.
C2 Security group allows 0.0.0.0/0 on port 5432 drop-db-sg Combined with C1, the database is wide open to brute-force and exploitation from any IP on Earth. Restrict inbound rule to App Runner VPC Connector security group only. Remove 0.0.0.0/0 CIDR.
C3 Plaintext secrets in App Runner env vars App Runner drop-web DATABASE_URL contains full connection string with password. JWT_SECRET in plaintext. Anyone with console/API access sees credentials. Visible in CloudTrail, config exports, and deployment logs. Migrate secrets to AWS Secrets Manager (already provisioned, currently empty). Reference via App Runner secret ARN configuration. Rotate both DATABASE_URL password and JWT_SECRET after migration.
C4 Database storage unencrypted RDS drop-db Data at rest is not encrypted. Violates baseline security posture and most compliance frameworks (SOC2, GDPR, PCI). Enable storage encryption. Note: cannot enable on existing instance — requires snapshot, restore to encrypted instance, DNS/connection swap. Plan downtime window.

HIGH

# Finding Resource Risk Remediation
H1 Single-AZ deployment RDS drop-db AZ failure = full database outage. No automatic failover. Enable Multi-AZ for production. Cost increase ~$14/mo for db.t3.micro.
H2 No monitoring or alerting CloudWatch (missing) No CPU, memory, connection, or storage alarms. No visibility into failures, performance degradation, or security events. Silent failures. Configure CloudWatch alarms: CPU > 80%, FreeStorageSpace < 2 GB, DatabaseConnections > 80%, FreeableMemory < 200 MB. Enable Enhanced Monitoring on RDS.
H3 No WAF WAF (missing) No protection against OWASP Top 10 attacks (SQLi, XSS, SSRF, etc.) at the edge. App Runner public endpoint is directly exposed. Deploy AWS WAF with managed rule groups (AWSManagedRulesCommonRuleSet, AWSManagedRulesSQLiRuleSet). Attach to CloudFront distribution (see H4).

MEDIUM

# Finding Resource Risk Remediation
M1 No CDN / CloudFront CloudFront (missing) All traffic hits App Runner origin directly. No edge caching, no DDoS protection (Shield Standard), higher latency for distant users. Deploy CloudFront distribution in front of App Runner. Enables WAF attachment, caching, and Shield Standard.
M2 Default VPC VPC 172.31.0.0/16 Default VPC has broad routing, public subnets by default, and no network segmentation. Not suitable for production workloads. Create custom VPC with private subnets for RDS, public subnets for NAT Gateway / ALB if needed. Migrate RDS to private subnet.
M3 No DNS management Route53 (missing) DNS managed outside AWS. No health checks, no failover routing, no alias records for AWS resources. Consider Route53 for DNS if domain is Drop-owned. Enables health-check-based routing and simpler AWS integration.
M4 TCP health check only App Runner drop-web TCP checks confirm port is open but not that the application is healthy. A process could accept connections while returning 500s. Configure HTTP health check on a dedicated /health endpoint that verifies database connectivity.

LOW

# Finding Resource Risk Remediation
L1 No S3 buckets S3 (missing) If the app needs file storage in future, ensure encryption-at-rest (SSE-S3 or SSE-KMS), versioning, and public access block from day one. Provision with secure defaults when needed.
L2 IAM user john-deploy IAM Long-lived access keys. No indication of key rotation policy or MFA. Audit key age. Enable MFA. Consider OIDC federation for CI/CD instead of IAM user. Rotate keys on a 90-day schedule.

Cost Breakdown

Service Specification Estimated Monthly Cost
App Runner 1 vCPU, 2 GB, always running $29 - $36
RDS db.t3.micro, 20 GB gp3, single-AZ $15 - $18
ECR Image storage (~1-5 GB) $0.50 - $1.00
Data Transfer Minimal (< 10 GB/mo estimate) $1 - $2
Secrets Manager 0 secrets (currently unused) $0
Total $46 - $57/mo

Cost Notes


Gaps Analysis

Category Current State Target State Priority
Secrets management Plaintext env vars Secrets Manager with rotation CRITICAL
Network security Public RDS + open SG Private subnet + restricted SG CRITICAL
Encryption at rest Disabled AES-256 (KMS or default) CRITICAL
Monitoring None CloudWatch alarms + dashboards HIGH
High availability Single-AZ Multi-AZ RDS HIGH
Edge security No WAF / CDN CloudFront + WAF HIGH
Network architecture Default VPC Custom VPC with segmentation MEDIUM
Health checks TCP only HTTP application-level MEDIUM
IAM hygiene Long-lived keys OIDC + key rotation + MFA MEDIUM
DNS External Route53 (optional) LOW
Backup/DR 7-day automated only Cross-region snapshot copy LOW

Recommendations (Priority Order)

Phase 1 — Immediate (Week 1) — CRITICAL Security

  1. Lock down RDS network access

    • Set PubliclyAccessible=false on drop-db
    • Update drop-db-sg: remove 0.0.0.0/0, allow only App Runner VPC Connector SG
    • Verify App Runner can still connect via VPC Connector
  2. Migrate secrets to Secrets Manager

    • Create secrets: drop/database-url, drop/jwt-secret
    • Update App Runner service to reference secret ARNs
    • Remove plaintext env vars from App Runner config
    • Rotate database password and JWT secret post-migration
  3. Enable RDS encryption

    • Snapshot current instance
    • Restore snapshot with encryption enabled
    • Update connection string to new endpoint
    • Verify, then delete old unencrypted instance
    • Requires brief downtime — schedule maintenance window

Phase 2 — Short Term (Week 2-3) — HIGH Priority

  1. Configure CloudWatch monitoring

    • RDS alarms: CPU, storage, connections, memory
    • App Runner alarms: request count, error rate, latency
    • SNS topic for alert notifications
    • Enable RDS Enhanced Monitoring
  2. Enable Multi-AZ RDS

    • Modify instance to Multi-AZ
    • Near-zero downtime (AWS handles failover setup)
  3. Deploy CloudFront + WAF

    • CloudFront distribution pointing to App Runner
    • WAF with AWS managed rule sets (Common, SQLi, Known Bad Inputs)
    • Update DNS to point to CloudFront

Phase 3 — Medium Term (Month 2) — Hardening

  1. Custom VPC migration

    • Design VPC: 2 private subnets (RDS), 2 public subnets (NAT if needed)
    • Migrate RDS to private subnets
    • Update App Runner VPC Connector
  2. HTTP health checks

    • Implement /health endpoint in Drop application (DB connectivity check)
    • Configure App Runner HTTP health check path
  3. IAM improvements

    • Audit john-deploy key age
    • Enable MFA on IAM user
    • Consider GitHub Actions OIDC for CI/CD (eliminates long-lived keys)

Risk Matrix

Risk Likelihood Impact Severity Mitigation
Database breach via public access + open SG HIGH CRITICAL CRITICAL Phase 1: Lock down network (C1, C2)
Credential leak from plaintext env vars MEDIUM CRITICAL CRITICAL Phase 1: Secrets Manager (C3)
Data exposure from unencrypted storage LOW HIGH HIGH Phase 1: Enable encryption (C4)
Database outage (single-AZ failure) LOW HIGH HIGH Phase 2: Multi-AZ (H1)
Silent application failure (no monitoring) MEDIUM MEDIUM HIGH Phase 2: CloudWatch (H2)
Application-layer attack (no WAF) MEDIUM HIGH HIGH Phase 2: WAF (H3)
DDoS / performance degradation (no CDN) LOW MEDIUM MEDIUM Phase 2: CloudFront (M1)
Lateral movement via default VPC LOW MEDIUM MEDIUM Phase 3: Custom VPC (M2)
IAM key compromise LOW HIGH MEDIUM Phase 3: Key rotation + OIDC (L2)

Appendix: Raw Resource Details

App Runner — drop-web

Service:         drop-web
Status:          RUNNING
Region:          eu-west-1
Source:          ECR (container image)
CPU:             1 vCPU
Memory:          2 GB
Port:            3000
Ingress:         Public
Egress:          VPC Connector
Health Check:    TCP
Environment:     DATABASE_URL (plaintext, contains password)
                 JWT_SECRET (plaintext)

RDS — drop-db

Engine:          PostgreSQL 16.6
Instance Class:  db.t3.micro
Storage:         20 GB gp3
AZ:              eu-west-1a (single-AZ)
VPC:             Default (172.31.0.0/16)
Public Access:   TRUE
Encrypted:       FALSE
Deletion Prot:   TRUE
Backup:          7-day automated
Monitoring:      DISABLED

ECR — drop-web

Repository:      drop-web
Scan on Push:    TRUE
Encryption:      AES256 (default)

Security Groups — drop-db-sg

Inbound Rules:
  - Protocol: TCP
    Port: 5432
    Source: 0.0.0.0/0  (ALL TRAFFIC)

IAM

User:   john-deploy     (programmatic access, deployment)
Role:   AppRunnerECRAccessRole  (App Runner → ECR pull)

Secrets Manager

Secrets stored: 0 (service provisioned but unused)

Cloud Audit: Multi-Cloud Design

Drop — Multi-Cloud Architecture Design

Date: 2026-02-19 Auditor: solution-arch (CloudForge cloud-audit team) MC Task: #1443


Executive Summary

Drop is 85% cloud-portable thanks to Docker containerization and PostgreSQL. Main AWS lock-in: App Runner (easily replaceable). Recommendation: stay on AWS, optimize current setup, design Terraform with abstraction for future portability.


1. Provider Comparison Matrix

Service AWS (Current) Azure GCP
Compute App Runner ($25-35/mo) Container Apps ($20-30/mo) Cloud Run ($15-25/mo)
Database RDS PostgreSQL ($15-18/mo) Azure DB for PG ($15-20/mo) Cloud SQL ($12-18/mo)
Registry ECR ($1-2/mo) ACR ($5/mo) Artifact Registry ($1-2/mo)
Secrets Secrets Manager ($0.40/secret) Key Vault ($0.03/10k ops) Secret Manager ($0.06/10k ops)
CDN CloudFront ($0-5/mo) Front Door ($35+/mo) Cloud CDN ($0-5/mo)
WAF AWS WAF ($5+/mo) Azure WAF ($20+/mo) Cloud Armor ($5+/mo)
Monitoring CloudWatch ($3-10/mo) Azure Monitor ($5-15/mo) Cloud Monitoring ($0-8/mo)
Total estimate $50-75/mo $100-130/mo $35-60/mo

2. Portable Architecture

                    Cloudflare (DNS + CDN + WAF)  ← Cloud-agnostic edge
                              |
                              | HTTPS
                              v
                    ┌──────────────────┐
                    │  CaaS Platform   │  ← App Runner / Container Apps / Cloud Run
                    │  ┌──────────┐   │
                    │  │ Docker   │   │  ← Identical image everywhere
                    │  │ Next.js  │   │
                    │  │ :3000    │   │
                    │  └──────────┘   │
                    └────────┬────────┘
                             │ DATABASE_URL
                    ┌────────┴────────┐
                    │  Managed PG     │  ← RDS / Azure DB / Cloud SQL
                    └─────────────────┘

Abstraction Strategy

Layer Approach
Compute Docker image to any CaaS. No platform SDK
Database Standard PostgreSQL via DATABASE_URL
Secrets Terraform abstracts provider. App reads env vars
DNS/CDN/WAF Cloudflare (cloud-agnostic, free tier)
Monitoring Sentry (errors) + structured logs to any aggregator
CI/CD GitHub Actions (already cloud-agnostic)

3. Migration Paths

AWS to Azure (3-5 days)

  1. Push image to ACR
  2. Create Azure DB for PostgreSQL Flexible Server
  3. pg_dump/pg_restore data migration
  4. Deploy to Azure Container Apps
  5. Update Cloudflare DNS
  6. Write Azure Terraform modules

AWS to GCP (2-3 days)

  1. Push image to Artifact Registry
  2. Create Cloud SQL PostgreSQL
  3. pg_dump/pg_restore
  4. Deploy to Cloud Run (most similar to App Runner)
  5. Update Cloudflare DNS
  6. Write GCP Terraform modules

Lock-In Assessment

Component Lock-In Notes
App Runner LOW Standard Docker, replaceable
RDS PostgreSQL LOW Standard PG, any managed PG works
ECR LOW Standard OCI registry
VPC Connector MEDIUM AWS-specific networking
IAM Roles MEDIUM AWS-specific auth model
Secrets Manager LOW App reads env vars regardless

4. Recommendation: Stay AWS, Optimize

Rationale:

Immediate Actions

  1. Security fixes (encrypt RDS, restrict SG, use Secrets Manager)
  2. Add Cloudflare free tier (DNS, CDN, WAF — cloud-agnostic)
  3. Terraform all resources (reproducibility)
  4. Add CloudWatch basic alarms ($3-5/mo)

Future Migration Triggers


5. 12-Month Cost Projection

Scenario Monthly Annual
Current (no changes) $50-75 $600-900
Optimized AWS $55-80 $660-960
AWS + Cloudflare $55-80 $660-960
Azure equivalent $100-130 $1,200-1,560
GCP equivalent $35-60 $420-720

Cloud Audit: App Cloud Readiness

Drop Application Cloud-Readiness Audit

MC Task: #1443 Date: 2026-02-19 Auditor: software-arch (CloudForge team) Application: Drop Fintech Payment App (Next.js 15 + SQLite/PostgreSQL dual-driver)

NOTE (2026-03-03): This audit was performed on 2026-02-19. ADR-014 (2026-03-03) removed SQLite and the dual-driver architecture. Drop now uses PostgreSQL 16 exclusively in all environments. SQLite concerns noted in this audit are resolved. The better-sqlite3 dependency has been removed.


1. Twelve-Factor Compliance

I. Codebase — PASS

II. Dependencies — PASS

III. Config — PASS

IV. Backing Services — PASS

V. Build, Release, Run — PASS

VI. Processes — PARTIAL

VII. Port Binding — PASS

VIII. Concurrency — PARTIAL

IX. Disposability — PASS

X. Dev/Prod Parity — PASS

XI. Logs — PARTIAL

XII. Admin Processes — PASS


2. Containerization Quality

Multi-Stage Build — EXCELLENT

Image Size

Security

Layer Caching

Missing


3. Database Portability

Dual-Driver Architecture — STRONG

SQL Translation Layer

SQLite Idiom PostgreSQL Translation Location
? placeholders $1, $2, ... db.ts:47-50
INSERT OR IGNORE INTO INSERT INTO ... ON CONFLICT DO NOTHING db.ts:56, 104-118
INSERT OR REPLACE INTO INSERT INTO ... ON CONFLICT (col) DO UPDATE SET db.ts:58, 120-134
datetime('now') CURRENT_TIMESTAMP db.ts:60
INTEGER PRIMARY KEY AUTOINCREMENT SERIAL PRIMARY KEY db.ts:278 vs 530
hex(randomblob(32)) encode(gen_random_bytes(32), 'hex') db.ts:248 vs 504

Transaction Support

Migrations

Indexes


4. Config Externalization

Environment Variables

Category Variables Source
Core JWT_SECRET, JWT_EXPIRY, NODE_ENV .env.example:12-14
Database DATABASE_URL db.ts:9
Service Mode NEXT_PUBLIC_SERVICE_MODE, DROP_MODE .env.example:8
Auth (BankID) BANKID_CLIENT_ID/SECRET/URLS, BANKID_MOCK .env.example:19-29
Payments PISP_API_URL/KEY, AISP_API_URL/KEY .env.example:32-40
Cards STRIPE_SECRET_KEY, STRIPE_PUBLISHABLE_KEY .env.example:43-47
KYC SUMSUB_APP_TOKEN, SUMSUB_SECRET_KEY .env.example:50-52
Monitoring SENTRY_DSN, SENTRY_TRACES_SAMPLE_RATE .env.example:63-74
Feature Flags 8x NEXT_PUBLIC_FF_* .env.example:77-87
Exchange EXCHANGE_RATE_API_KEY/URL .env.example:55-59

Secrets Management

Feature Flags


5. CI/CD Quality

Pipeline Structure (ci.yml)

lint-test (parallel)          docker-scan (sequential, needs lint-test)
  -- npm ci                     -- docker build
  -- eslint                     -- Trivy scan (table, exit-code=1 on HIGH/CRITICAL)
  -- tsc --noEmit               -- Trivy SARIF -> GitHub Security
  -- vitest run
  -- npm audit (production)

Reproducibility

Security Scanning

Testing

Deployment


6. Overall Score and Top 5 Improvements

Overall Cloud-Readiness Score: 7.5 / 10

The application demonstrates strong cloud-native fundamentals:

Top 5 Improvements (Priority Order)

1. Eliminate Build Tools from Production Image (HIGH)

2. Add Structured Logging (HIGH)

3. Add CI Coverage Enforcement and E2E Tests (MEDIUM)

4. Automate Schema Parity Check (MEDIUM)

5. Add Deployment Pipeline and Environment Promotion (MEDIUM)

Honorable Mentions


Appendix: File Reference

File Purpose
src/drop-app/src/lib/db.ts Dual-driver database abstraction (SQLite + PostgreSQL)
src/drop-app/Dockerfile 3-stage multi-stage build
src/drop-app/.env.example Environment variable documentation (87 lines)
src/drop-app/fly.toml Fly.io deployment config (Stockholm region)
src/drop-app/docker-compose.production.yml Self-hosted production config
src/drop-app/package.json Dependencies and scripts
.github/workflows/ci.yml CI pipeline (lint, test, type-check, Trivy)
src/drop-app/migrations/0001_initial-schema.ts PostgreSQL migration (node-pg-migrate)
src/drop-app/next.config.ts Next.js config (standalone output, security headers)
src/drop-app/src/middleware.ts Edge middleware (CSRF, CSP nonce)
src/drop-app/src/lib/middleware.ts Server middleware (rate limiting, auth, validation, audit)
src/drop-app/src/app/api/health/route.ts Health endpoint (real DB check)
src/drop-app/src/lib/env.ts Environment validation at startup

Cloud Audit: Validation Report

Drop — Validation + Security + Cost Report

Date: 2026-02-19 Auditor: cloud-tester (CloudForge cloud-audit team) MC Task: #1443


Executive Summary

Drop's AWS infrastructure has 3 CRITICAL and 4 HIGH security findings requiring immediate remediation. Current spend is ~$50-75/mo, well-optimized for scale. The application is cloud-portable (7.5/10) and the recommended path is to stay on AWS with security hardening + Terraform IaC.


1. Security Posture Assessment

Current vs Improved

Area Current State After Remediation Risk Reduction
Secrets Plaintext in App Runner env vars AWS Secrets Manager CRITICAL → LOW
RDS Access Publicly accessible, SG open 0.0.0.0/0 Private, VPC-only access CRITICAL → LOW
Encryption RDS unencrypted at rest AES-256 encryption enabled CRITICAL → RESOLVED
Monitoring None (no CloudWatch) Basic alarms + Performance Insights HIGH → LOW
WAF None Cloudflare WAF (free tier) HIGH → LOW
CDN None (direct App Runner URL) Cloudflare CDN HIGH → LOW
SSL/TLS App Runner managed cert Cloudflare + App Runner MEDIUM → LOW
IAM Single user (john-deploy) Least-privilege roles MEDIUM → LOW

Security Findings Summary

# Severity Finding Remediation Effort
S1 CRITICAL RDS publicly accessible with SG allowing 0.0.0.0/0:5432 Set publicly_accessible=false, restrict SG to VPC CIDR 1 hour
S2 CRITICAL Database password in plaintext App Runner env var Migrate to Secrets Manager, update App Runner to read from SM 2 hours
S3 CRITICAL JWT_SECRET in plaintext App Runner env var Migrate to Secrets Manager 1 hour
S4 HIGH RDS storage not encrypted at rest Enable encryption (requires snapshot + restore for existing DB) 2-4 hours
S5 HIGH No monitoring or alerting configured Add CloudWatch alarms for CPU, memory, DB connections 1 hour
S6 HIGH No WAF protection Add Cloudflare WAF (free tier) 30 min
S7 HIGH No CDN (direct App Runner URL exposed) Add Cloudflare CDN 30 min
S8 MEDIUM Sentry DSN in plaintext (not secret, but cleanup) Move to Secrets Manager for consistency 30 min
S9 MEDIUM Docker image has build tools in runner (attack surface) Remove python3/make/g++ from runner stage 1 hour
S10 MEDIUM No structured logging (incident investigation gaps) Add pino/winston with JSON output 2 days
S11 LOW ECR image tag mutability (tag overwrite risk) Set image_tag_mutability = IMMUTABLE 5 min
S12 LOW No lifecycle policy for ECR images Add policy to clean old images 15 min

Compliance Checklist

Item Status Notes
GDPR data tables (consents, data_access_requests) PASS Schema includes consent tracking, DSAR, right to erasure
Audit logging PASS audit_log table with IP, user_agent, request_id
AML/KYC compliance PASS aml_alerts, str_reports, screening_results tables
Encryption at rest FAIL RDS storage unencrypted
Encryption in transit PARTIAL App Runner HTTPS, but RDS sslmode=no-verify
Secrets management FAIL Plaintext in env vars
Access control PARTIAL Single IAM user, no MFA enforcement
Backup & recovery PASS RDS 7-day automated backups
DeletionProtection PASS Enabled on RDS

2. Cost Comparison

Current AWS Spend

Resource Monthly Cost Notes
App Runner (1 vCPU, 2GB) $25-35 Always-on, no auto-stop
RDS db.t3.micro $15-18 Single-AZ, 20GB gp3
ECR $1-2 Image storage
VPC Connector $5 Flat fee
Data transfer $2-5 Low traffic
Total $48-65

Optimized AWS (after fixes)

Resource Monthly Cost Change
App Runner $25-35 No change
RDS (encrypted) $15-18 No cost increase
ECR $1-2 No change
Secrets Manager (3 secrets) $1.20 +$1.20
CloudWatch (basic alarms) $3-5 +$3-5
Cloudflare (free tier) $0 Free CDN/WAF/DNS
Total $52-70 +$4-7

Multi-Cloud Equivalent

Provider Monthly Annual vs Current
AWS (optimized) $52-70 $624-840 +$4-7/mo
Azure $100-130 $1,200-1,560 +$50-65/mo
GCP $35-60 $420-720 -$5-15/mo

Verdict: AWS is cost-effective. GCP saves ~$10/mo but migration effort not justified at current scale.


3. Risk Matrix

Risk Probability Impact Current Mitigation Recommended
Data breach via public RDS HIGH CRITICAL DeletionProtection only Restrict SG, disable public access
Secret exposure MEDIUM CRITICAL None (plaintext) Secrets Manager + rotation
Service downtime LOW HIGH App Runner auto-scaling Add health checks, CloudWatch alarms
Data loss LOW CRITICAL 7-day RDS backups Add cross-region backup copy
Cost overrun LOW MEDIUM None Add AWS Budgets alarm at $100
Vendor lock-in LOW MEDIUM Docker + PostgreSQL Terraform abstraction modules
DDoS attack MEDIUM HIGH None Cloudflare WAF + rate limiting
Compliance failure MEDIUM HIGH Tables exist, no encryption Enable encryption, structured logging

4. Implementation Roadmap

Phase 1: Security Fixes (Immediate — Day 1)

Phase 2: IaC Migration (Week 1)

Phase 3: Monitoring & Observability (Week 2)

Phase 4: Edge Security (Week 2-3)

Phase 5: RDS Encryption (Week 3)

Phase 6: Multi-Cloud Readiness (Month 2+)


5. Recommendations Summary

Priority Action Status
P0 (NOW) Fix RDS public access + SG Terraform module created
P0 (NOW) Move secrets to Secrets Manager Terraform module created
P1 (Week 1) Enable RDS encryption Requires snapshot/restore
P1 (Week 1) Deploy Terraform IaC Modules ready
P2 (Week 2) Add monitoring (CloudWatch + Performance Insights) In Terraform
P2 (Week 2) Add Cloudflare CDN/WAF Manual setup
P3 (Month 1) Add structured logging Application code change
P3 (Month 1) Add graceful shutdown handler Application code change
P4 (Month 2+) Multi-cloud Terraform modules As needed

Overall Assessment: Drop's infrastructure is functional but needs immediate security hardening. The Terraform IaC created by this audit provides a complete, reproducible foundation. Total investment: ~1 week of engineering time, ~$5/mo additional cost, significant risk reduction.