Skip to content

fix(infra): stop Terraform clobbering app runtime secret on every apply#269

Open
arielr-lt wants to merge 1 commit into
mainfrom
fix/encryption-key-tf-clobber
Open

fix(infra): stop Terraform clobbering app runtime secret on every apply#269
arielr-lt wants to merge 1 commit into
mainfrom
fix/encryption-key-tf-clobber

Conversation

@arielr-lt

Copy link
Copy Markdown
Collaborator

Problem

The app runtime secret (ctdl-xtra/<env>/app) is managed out-of-band in AWS Secrets Manager — by the Update app env vars workflow and by manual ops — but aws_secretsmanager_secret_version.app rewrote the entire JSON blob from local.app_secret_values on every terraform apply.

Because ENCRYPTION_KEY is sourced from random_password.encryption_key, any apply that recreated/refreshed that resource silently rotated the key. The app uses it for AES-256-CBC, so all DB rows encrypted under the previous key became undecryptable.

This is exactly what bit production: the live key had drifted to a random value and encrypted DB secrets could no longer be decrypted (restored manually by setting the correct ENCRYPTION_KEY back into Secrets Manager + rolling api/worker).

Fix

Add lifecycle { ignore_changes = [secret_string] } to aws_secretsmanager_secret_version.app in test, sandbox, and production. Terraform now seeds the secret on first creation only and never overwrites runtime values afterward — Secrets Manager + the Update app env vars workflow are the single source of truth.

Trade-off / follow-up

secret_string is now fully ignored, so infra-derived values (DATABASE_URL, REDIS_URL) are no longer auto-propagated by Terraform. If the RDS endpoint or db_password/redis_password change, the secret must be updated out-of-band (via the workflow) to match. This matches the existing operational model where that workflow already owns runtime env. Worth a short runbook note.

Verification

  • terraform fmt clean on changed files.
  • Reviewers should run terraform plan per env and confirm the only secret-related change is the in-place lifecycle update (no secret_string replacement).

🤖 Generated with Claude Code

The app runtime secret (ctdl-xtra/<env>/app) is managed out-of-band in
Secrets Manager via the "Update app env vars" workflow, but
aws_secretsmanager_secret_version.app rewrote the whole blob from
local.app_secret_values on every apply. That regenerated
random_password.encryption_key, changing ENCRYPTION_KEY and orphaning all
data already encrypted under the previous key (caused the prod DB-secret
decryption failures).

Add lifecycle { ignore_changes = [secret_string] } to all three envs so
Terraform seeds the secret on first creation only and never overwrites
runtime values afterward.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant