vault

13 — Network Model

docs/13-Network-Model.mdtype: architecture-targetupdated: 2026-05-03

Network Model

Target state. The current MVP is documented in 02-Architecture and deploys through the AWS dev Terraform stack for speed of delivery. This page is the AWS-native network/SG model that lands with the AWS refactor — see 11-Target-Architecture and 12-Environments. Production never runs outside AWS.

Network zones

Zone What lives here Internet-facing?
Public Route 53, CloudFront, AWS WAF, AWS Shield, API Gateway, NAT Gateway Yes (controlled)
Private App Subnet App + worker containers on EC2, CoSigner parent EC2 No
Private Data Subnet Postgres (data + pg-boss queues), S3 internal buckets No

Key directional rules

  • Route 53 → CloudFront + AWS WAF → API Gateway → internal ALB → private app.
  • Public never speaks to data subnet directly.
  • Private services reach providers via NAT egress only.
  • CoSigner has its own outbound (Fireblocks) and no public inbound.

Public components

Route 53

  • Authoritative DNS for the zone.
  • Health checks + failover routing for multi-AZ / multi-region (Prod).

CloudFront + AWS WAF + AWS Shield

  • CDN for static + cached responses; HTTPS termination at the edge.
  • AWS WAF web ACL: managed rule sets (OWASP, anonymous IP, bot control) + rate-based rules per IP / per session.
  • AWS Shield Standard always on; Shield Advanced enabled for Prod.
  • First control layer for user / merchant / admin traffic.

API Gateway

  • Public entry into AWS for HTTP.
  • VPC Link to internal ALB.

NAT Gateway

  • Outbound-only egress for private workloads.
  • All provider calls (Fireblocks, TRES, Sumsub, Elliptic, Mercuryo, CEX.IO, Resend) leave through this.

S3 (static delivery)

  • Origin for CloudFront. No direct public access (Origin Access Control only).

Private components

Component Purpose
internal ALB Routes API Gateway traffic into private app layer
App containers (EC2) User / merchant / admin API
Worker containers (EC2) Background jobs, async integration
Fireblocks CoSigner (EC2 + Nitro Enclave) Signing-policy enforcement
pg-boss (on Postgres) Queue, retry, scheduling
PostgreSQL Primary data store
Postgres rate_limits Rate-limit windows + login lockout
S3 internal buckets Exports, logs, generated artifacts
Secrets Manager / KMS Credentials, encryption-at-rest
CloudWatch / CloudTrail / GuardDuty / Security Hub (Prod) Observability + audit + threat

Security groups

SG-ALB

  • Used by: internal Application Load Balancer.
  • Inbound: from API Gateway / VPC Link only.
  • Outbound: to SG-APP only.
  • Rule: no broad public access; routes through controlled entry.

SG-APP

  • Used by: application containers on EC2.
  • Inbound: from SG-ALB only.
  • Outbound: to SG-WORKER, SG-DB, NAT (provider egress).
  • Rule: minimum ports, minimum peers.

SG-WORKER

  • Used by: pg-boss worker containers on EC2.
  • Inbound: from controlled internal sources only (no public).
  • Outbound: to SG-DB, NAT, S3.
  • Rule: workers must not be reachable from the public internet.

SG-COSIGNER

  • Used by: Fireblocks CoSigner parent EC2 (with Nitro Enclave).
  • Inbound: from controlled internal app/worker paths only as required.
  • Outbound: only to Fireblocks endpoints + required dependencies.
  • Rule: tightest restriction. CoSigner is not general-purpose compute.

SG-DB

  • Used by: PostgreSQL.
  • Inbound: from SG-APP and SG-WORKER only.
  • Outbound: none required.
  • Rule: never publicly reachable.

Allowed peer matrix

SG-ALB SG-APP SG-WORKER SG-COSIGNER SG-DB
From API GW
From SG-ALB
From SG-APP ✓ (where needed) ✓ (where needed)
From SG-WORKER ✓ (where needed)
From Public
From SG-COSIGNER

A blank cell means the peer is not allowed. CoSigner only emits outbound to Fireblocks — it never accepts public inbound and only accepts narrow internal inbound.

General rules

No public DB or cache access

The database must never be reachable from the public internet — full stop. Backed by SG rules + private-subnet placement.

CoSigner isolation

Tighter than every other workload. Treat it as a single-purpose dependency, not a general compute target.

Minimal-path design

Every SG exposes the minimum ports to the minimum peers. New rules require explicit justification at review time.

NAT-only egress

Workloads in private subnets reach providers exclusively through the NAT Gateway. No direct internet routes from private services.

Environment usage

Environment Network model
Dev Same conceptual SGs, reduced scale, simplified peering
Test Full logical model, production-like enforcement
Prod Full model + strongest review/audit posture

See 12-Environments for HA/DR profile per env.

Admin access path

Admin traffic uses a separate posture from user/merchant:

admin user
    |
    v
AWS IAM Identity Center (SSO + MFA)
    |
    v
CloudFront + AWS WAF (admin ruleset, IP allowlist)
    |
    v
admin-subdomain entry (private API GW route)
    |
    v
internal ALB (SG-ALB)
    |
    v
admin app containers (SG-APP)
  • AWS IAM Identity Center provides SSO + MFA + group-based access.
  • A dedicated AWS WAF web ACL on the admin distribution applies a stricter ruleset (IP allowlist, geo restriction, lower rate-limit thresholds).
  • VPN / PrivateLink option for ops-grade access where required.
  • No shared entry path with user/merchant traffic.

Drawbacks

  • The SG matrix is strict by design — adding new internal services requires explicit SG changes, slowing experimentation.
  • NAT-only egress costs money and concentrates blast radius if NAT misbehaves; mitigated by Multi-AZ NAT in Prod.

Open Questions

Cross-references