Skip to content

Latest commit

 

History

History
125 lines (108 loc) · 7.58 KB

File metadata and controls

125 lines (108 loc) · 7.58 KB

Production configuration in AWS Secrets Manager

AWS Secrets Manager is PointUp's approved operational configuration source. The configuration helper targets the verified AWS account 462455771080, region us-east-1, and only these names:

Secret name JSON fields
pointup/production/clerk CLERK_SECRET_KEY, CLERK_PUBLISHABLE_KEY
pointup/production/database DATABASE_URL, MIGRATION_DATABASE_URL

Run scripts/deployment/configure-secrets.mjs in Linux/WSL with Node 20+ and AWS CLI v2 and Python 3. Authenticate with the approved AWS session/profile. Supply configuration through a secure operator-controlled process environment: CLERK_SECRET_KEY, NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY, and optionally both DATABASE_URL and MIGRATION_DATABASE_URL. The public key input is stored as CLERK_PUBLISHABLE_KEY for the deployment build loader. Supply a complete Clerk pair, a complete database pair, or both. Do not paste values into chat, commit them, or place literal values in shell history or workflow command arguments.

# Approved values must already exist in this process environment.
node scripts/deployment/configure-secrets.mjs
# After inspecting the nonsecret dry-run result:
node scripts/deployment/configure-secrets.mjs --apply

The default dry run validates configuration, checks STS account identity, and reads secret metadata to report create/new-version actions. It creates no resources and sends no application credentials to AWS. Explicit --apply creates missing secrets or adds an AWSCURRENT value version to existing secrets. It preflights all selected metadata before writing. Each AWS secret version write is atomic; multiple secret writes are not a transaction. On a partial write failure, review AWS metadata and version state before deciding how to recover. Existing secrets scheduled for deletion and unexpected identity/region are rejected.

AWS CLI receives JSON through file:///proc/self/fd/N, pointing to an inherited, sealed Linux anonymous memory file descriptor. A fixed Python 3 bridge reads Node's socket-backed stdin, bounds and validates the JSON, writes a seekable memfd, seals it against writes/resizing, and passes only that descriptor to AWS CLI. Each file reopen starts a fresh read, supporting CLI parameter-file handling that consumes input more than once; a /dev/stdin pipe does not provide this. The descriptor path contains no credential values. The anonymous file has no filesystem directory entry or temporary disk payload and closes after the request; ordinary OS memory/swap and same-user process inspection remain host protections.

The bridge permits only STS identity and Secrets Manager describe/create/put operations. It never puts secret payloads in temporary files or command arguments, suppresses raw AWS responses and errors, and removes application credential variables from the child CLI environment. It disables CLI paging/auto prompts and endpoint overrides. Use a trusted AWS CLI installation/profile; an untrusted executable or credential process can compromise the AWS session. Native Windows execution is intentionally unsupported: Linux memfd_create, sealing and procfs are required; run this transport inside WSL. Offline regressions reopen and read the same underlying anonymous descriptor twice and verify its seals. Real CLI qualification uses only public STS identity JSON, never a secret-write probe.

Secret validation checks live Clerk key formats, presence, PostgreSQL/TLS shape, and the same Supabase project for application and migration connections. It does not log URLs, hostnames, usernames or values, and it does not attest provider-side key validity or database connectivity. No fake/empty secret is provisioned when configuration is missing. Production acceptance still needs actual Clerk sign-in and database/migration checks.

Application DATABASE_URL may use the Supabase transaction pooler on port 6543. MIGRATION_DATABASE_URL must use direct or session mode on port 5432. Both require TLS (sslmode=require, verify-ca or verify-full). Supabase documents direct connections for migrations and explains the pooler connection modes in its PostgreSQL connection guide. The helper intentionally supports hosted Supabase direct/shared-pooler endpoints; self-hosted or alternative endpoint formats require a reviewed validation change.

Provisioning these secrets does not switch databases or deploy application code. The existing CDK-managed RDS credentials and migration route remain separate. External Supabase application/migration URL selectors are prepared in CDK; the rollout driver explicitly refuses external activation pending provider backup/recovery evidence and live migration verification. See supabase-deployment.md. Import the Clerk secret by its actual ARN and select the CLERK_SECRET_KEY JSON field for runtime injection; fetch CLERK_PUBLISHABLE_KEY through the approved deployment role before the web build. Do not put either secret's raw content in CDK context, generated templates, or release artifacts.

Grant operators only needed STS/Secrets Manager actions and scoped secret access. The deployment role needs read access to selected secrets, not write access. For a custom KMS key, grant required KMS permissions separately; new secrets use AWS's default Secrets Manager encryption key. AWS's create-secret reference describes JSON input and encryption options. Never use long-lived static AWS credentials in CI; use the existing OIDC role and nonsecret secret ARN references.

The Deploy workflow loads only the public Clerk build key into GITHUB_ENV through load-clerk-build-config.mjs, then imports the same secret ARN into runtime tasks. The GitHub OIDC role has one scoped GetSecretValue grant for pointup/production/clerk-??????; it cannot read the database secret payload. Configure the actual ARN as the repository variable CLERK_SECRET_ARN.

Reuse the existing GitHub OIDC provider

The approved account already has the GitHub issuer provider: arn:aws:iam::462455771080:oidc-provider/token.actions.githubusercontent.com. Pass it through existingProviderArn when preparing the one-time deployment-role stack; this imports the existing provider and synthesizes no new provider resource.

# Source preparation only; inspect the template before an authorized deployment.
cd infra
CDK_DEFAULT_ACCOUNT=462455771080 CDK_DEFAULT_REGION=us-east-1 \
  npx cdk synth GithubOidc -c deploymentMode=oidc -c githubRepo=jckail/point_bot \
  -c existingProviderArn=arn:aws:iam::462455771080:oidc-provider/token.actions.githubusercontent.com

The import accepts only the exact GitHub issuer ARN, with an account matching the concrete deployment account and a partition matching the concrete AWS region. Malformed, foreign-account, wrong-partition and unresolved-environment imports fail before synthesis. Fresh accounts can omit this context to retain provider creation. Never omit it when that account already has the GitHub issuer provider.

The role trust remains restricted to audience sts.amazonaws.com and subject repo:jckail/point_bot:environment:production; import does not broaden trust or permissions or alter the existing provider. Before deployment, verify the live provider's URL and client IDs, and configure the GitHub production environment with appropriate branch/reviewer protections. Merely importing an ARN does not verify the provider metadata, environment setup, or ability to assume the role. A synthesis check is not evidence of AWS resource deployment.