Skip to content

ADR-030: Secrets management — AWS Secrets Manager

Status Accepted
Date 2026-04-10
Deciders CTO, Head of Architecture
Affects repos bank-core, bank-kyc, bank-aml, bank-payments, bank-credit, bank-risk-platform, bank-platform, bank-app

Status

Accepted — 2026-04-10

Context

Lambda functions across all system domains require secure access to credentials: Neon Postgres connection strings, Cognito client secrets, external API keys, and signing keys. ADR-022 deferred the secrets management tool choice. Credentials must not appear in environment variables, source code, or logs. DT-001 requires an audit trail on all secret access and automatic rotation for credentials.

Decision

AWS Secrets Manager is the secrets store for all production credentials.

Access pattern: Each Lambda's IAM execution role grants secretsmanager:GetSecretValue scoped to its own domain path only. No Lambda may access another domain's secrets.

Path naming convention:

/bank/{env}/{domain}/{service}/{name}

e.g.  /bank/prod/payments/neon/connection-string
      /bank/prod/kyc/eidv-provider/api-key
      /bank/prod/platform/cognito/client-secret

Caching: AWS Lambda Powertools SecretsProvider caches values in the execution environment — one API call per cold start, not per invocation. TTL configurable per secret (default 5 minutes).

Neon rotation: Neon supports multiple database roles per project. Secrets Manager rotation Lambda cycles the active role on schedule without connection downtime — the inactive role is updated and tested, then promoted as primary.

Non-secret config (endpoints, environment identifiers, non-sensitive feature values) uses AWS Systems Manager Parameter Store (free standard tier). Parameter Store holds no credentials — the distinction is enforced in code review and pipeline policy.

Rejected alternatives

Option Reason rejected
AWS Parameter Store (for secrets) No built-in rotation — rotation Lambda required, which recreates the maintenance burden
HashiCorp Vault Always-on process; conflicts with serverless model; significant operational overhead
Environment variables No rotation, no audit trail, exposed in Lambda console — non-compliant with DT-001

Consequences

DT-001 rotation and audit trail requirements satisfied without custom code. Secret access auditable via CloudTrail per domain. IAM path scoping enforces domain isolation — a compromised Lambda cannot read another domain's credentials. Cost ~$0.40/secret/month, negligible at launch secret count.


ADR Title Relationship
ADR-022 CI/CD and deployment strategy resolves the deferred secrets management decision from ADR-022
ADR-024 Database hosting — Neon serverless Postgres Neon connection string rotation via Secrets Manager
ADR-025 API layer — HTTP API Gateway and SST Lambda IAM execution roles constrain secret path access
---

Signoff record

Date Name Role Status
2026-04-10 Ross Millen CTO Approved
2026-04-10 Ross Millen Head of Architecture Approved
2026-04-10 Ross Millen Head of Data Approved


All ADRs Compiled 2026-05-22 from source/entities/adrs/ADR-030.yaml