Skip to content

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.

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.

The application KMS client only exposes two operations:

  • Encrypt wraps newly created or rotated Shamir shares.
  • Decrypt unwraps 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.

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.

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, and kms:DescribeKey on those external key ARNs.

The multi-account Terraform examples create both sides.

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.