Separate the seal key from the key that encrypts node volumes - #56
Conversation
They were one key, and `terraform destroy` scheduled it.
storage.tf warns that a snapshot is encrypted under the auto-unseal key
and that the key "must not be scheduled for deletion when a cluster is
torn down". The root volume used the same key, so a teardown put it on a
seven-day timer -- and with it every snapshot ever taken with that key,
including snapshots from clusters that no longer existed. The document
said one thing and the code did the other.
Now two keys:
<cluster>-vault-autounseal 30 day window
Vault's seal, and the snapshot bucket's SSE. Deliberately the same
key for both, because reading a snapshot needs this key for the
object and this key for the keyring sealed inside it. One thing to
keep alive is a rule an operator can follow; two is a rule they will
half-follow.
<cluster>-vault-data 7 day window
Root volumes only. They go when the instance goes, so losing the key
costs nothing that was not already leaving.
teardown-cloud.sh now names both and says which one to cancel, since the
whole hazard is that they look alike in the console.
The assertions are split by what each layer can actually answer.
terraform test checks configuration -- two keys, distinct descriptions,
the windows that make the split worth having -- because its mock gives
every aws_kms_key the same arn, so comparing arns there passes or fails
for both at once and proves nothing. tests/README.md says exactly that
about mocked values and the first version of this test ignored it. The
arn comparison lives in tests/cloud-apply-emulated, where the API mints
real ones.
Verified in WSL: fmt clean, 28 assertions pass.
Closes #55.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
The emulated apply asserted a resource count written when the profile had one KMS key. Splitting the seal key from the node volume key made it two, and the count was not updated with them. Both of the assertions that matter passed against the real API in the same run -- the two keys are distinct, and the root volume is not on the seal key -- so this is the expectation being stale, not the change being wrong. Second time a hardcoded count in this file has gone out of date after a deliberate change; the counts are there to catch resources appearing or vanishing unnoticed, and that is worth the occasional edit. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Green, and one commit landed after the description above27/27,
|
Closes #55.
They were one key, and
terraform destroyscheduled it.storage.tfwarns that a snapshot is encrypted under the auto-unseal key and that it "must not be scheduled for deletion when a cluster is torn down". The root volume used the same key — so a teardown put it on a seven-day timer, and with it every snapshot ever taken with that key, including from clusters that no longer existed. The document said one thing and the code did the other.Two keys
<cluster>-vault-autounseal<cluster>-vault-dataThe bucket stays on the seal key deliberately. Reading a snapshot needs this key for the object and this key for the keyring Vault sealed inside it — so exactly one thing has to outlive a teardown. One rule an operator can follow; two is a rule they will half-follow.
teardown-cloud.shnow names both keys and says which one to cancel, since the whole hazard is that they look alike in the console.The assertions are split by what each layer can answer
terraform testchecks configuration — two keys, distinct descriptions, the windows that make the split worth having.It does not compare arns, because the mock gives every
aws_kms_keythe same one:So
!=can never hold and==passes trivially. My first version asserted exactly that and failed —tests/README.mdwarns about it in as many words, and I ignored it.The arn comparison lives in
tests/cloud-apply-emulatedinstead, where the API mints real ones: the two keys differ, and the root volume is not on the seal key.Verified
terraform fmtclean, 28 passed / 0 failed in WSL.Still not settled by any of this
Whether the ASG service-linked role needs explicit key-policy grants once a restrictive policy replaces the default. moto does not enforce IAM, so that half still waits for a real apply — as noted in #55.
🤖 Generated with Claude Code