KMS Key Policies
Required KMS permissions for Shamir share keys, enclave attestation, and DynamoDB encryption
Use the Terraform examples for normal deployments. This page is an advanced reference for reviewing or hand-writing KMS permissions.
Containment Chamber uses KMS in two different ways, and the permissions are intentionally different.
Permission Model
Section titled “Permission Model”| Key class | Used by | Required KMS actions | Attestation-gated? |
|---|---|---|---|
| Shamir share keys | Containment Chamber KMS client | kms:Encrypt, kms:Decrypt; Terraform also grants kms:DescribeKey |
Decrypt only in Nitro mode |
| DynamoDB table-encryption keys | DynamoDB encryption at rest | kms:Encrypt, kms:Decrypt, kms:DescribeKey, kms:GenerateDataKey*, kms:ReEncrypt*, kms:CreateGrant |
No |
Do not mix these two models. GenerateDataKey*, ReEncrypt*, and CreateGrant are DynamoDB SSE permissions; Containment Chamber does not call those APIs for Shamir shares.
Shamir Share Keys
Section titled “Shamir Share Keys”The application KMS client only exposes two operations:
Encryptwraps newly created or rotated Shamir shares.Decryptunwraps Shamir shares to reconstruct the chamber master key.
In Nitro mode, Decrypt is performed by AttestedKmsClient: every decrypt request includes a fresh NSM attestation document and a per-request RSA recipient key. KMS returns CiphertextForRecipient, which is decrypted inside the enclave.
Terraform grants DescribeKey alongside Encrypt and Decrypt for operational compatibility, but the Rust KMS client does not call DescribeKey.
Nitro Key Policy Shape
Section titled “Nitro Key Policy Shape”For each Shamir share key in Nitro mode:
{ "Version": "2012-10-17", "Statement": [ { "Sid": "AllowEnclaveDecryptWithAttestation", "Effect": "Allow", "Principal": { "AWS": "arn:aws:iam::ACCOUNT_ID:role/containment-chamber-signer" }, "Action": ["kms:Decrypt", "kms:DescribeKey"], "Resource": "*", "Condition": { "StringEqualsIgnoreCase": { "kms:RecipientAttestation:PCR8": "<signing certificate PCR8>", "kms:RecipientAttestation:ImageSha384": [ "<current PCR0 / ImageSha384>", "<previous PCR0 / ImageSha384 during rollout>" ] } } }, { "Sid": "AllowSignerEncryptForWrapping", "Effect": "Allow", "Principal": { "AWS": "arn:aws:iam::ACCOUNT_ID:role/containment-chamber-signer" }, "Action": ["kms:Encrypt", "kms:DescribeKey"], "Resource": "*" } ]}Add kms:RecipientAttestation:PCR3 when you want to bind decrypt to the parent instance IAM role.
Cross-Account Keys
Section titled “Cross-Account Keys”For cross-account Shamir keys, KMS requires both sides:
- The key policy in the key-owning account must allow the signer role.
- The signer role’s IAM policy in the caller account must allow
kms:Encrypt,kms:Decrypt, andkms:DescribeKeyon those external key ARNs.
The multi-account Terraform examples create both sides.
DynamoDB Table-Encryption Keys
Section titled “DynamoDB Table-Encryption Keys”DynamoDB server-side encryption with a customer-managed KMS key is separate from the chamber master-key Shamir wrap. DynamoDB calls KMS at the service layer on behalf of the caller.
The signer role needs the standard DynamoDB SSE KMS set on table-encryption keys:
[ "kms:Encrypt", "kms:Decrypt", "kms:DescribeKey", "kms:GenerateDataKey*", "kms:ReEncrypt*", "kms:CreateGrant"]These table-encryption keys must not be gated by kms:RecipientAttestation; DynamoDB requests do not carry Nitro attestation documents.
What Not To Do
Section titled “What Not To Do”Next Steps
Section titled “Next Steps”- AWS Setup — signing certificate, PCR measurements, and Terraform examples
- AWS IAM Permissions — DynamoDB table permissions and signer-state permissions
- Enclave Operations — PCR rotation and KMS attestation troubleshooting

