KMS & envelope encryption
Data keys, key policies, rotation, and the kill switch.
KMS is not a vault you push plaintext through — that would not scale and would route every byte through the service. It manages small wrapping keys, and the pattern that makes it work at any data size is envelope encryption. Understanding it changes how you reason about rotation, revocation, and who can actually read your data.
Envelope encryption, concretely
You ask KMS for a data key and get two forms of the same key: a plaintext copy you use locally to encrypt the payload, and a ciphertext copy only KMS can unwrap. You encrypt the data, discard the plaintext key, and store the wrapped key beside the ciphertext. To read, you send the wrapped key back and KMS unwraps it if your identity is allowed. Bulk data never touches KMS — only tiny keys do — so a single CMK protects terabytes.
# A bucket reader who lacks kms:Decrypt sees only ciphertext. Access to the# store and use of the key are separate permissions — that decoupling is the point.{"Sid": "AppMayDecrypt", "Effect": "Allow","Principal": { "AWS": "arn:aws:iam::222222222222:role/report-svc" },"Action": ["kms:Decrypt","kms:GenerateDataKey"],"Resource": "*","Condition": { "StringEquals": { "kms:ViaService": "s3.eu-west-1.amazonaws.com" } }}# Disabling this CMK instantly makes all data it protects unreadable — a kill# switch a provider-owned SSE-S3 key can never give you.
Rotation, grants, and CMK vs default
Because only the wrapped data keys reference the CMK, rotating the master adds a new key version while old ciphertext still decrypts — no bulk re-encryption. Prefer customer-managed keys over SSE-S3/default keys: you get the key policy, rotation control, audit of every decrypt, and the disable switch. For narrow, temporary programmatic access use a KMS grant rather than widening the key policy, and separate the key admin from the data admin so no single compromised role can both read the store and decrypt it.