I’ve written KMS key policies dozens of times. I still make the same three mistakes.
Mistake 1: forgetting the root principal
A KMS key policy that doesn’t include the root principal (arn:aws:iam::ACCOUNT_ID:root) can lock you out of the key. The root principal allows IAM policies to delegate key access — without it, only the key policy itself can grant access.
{
"Sid": "Enable IAM User Permissions",
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::123456789012:root"
},
"Action": "kms:*",
"Resource": "*"
}
This is not the same as giving root unlimited key access. It enables IAM delegation. Miss it once and you’ll never miss it again.
Mistake 2: using kms:* in service policies
When granting an AWS service permission to use a key, scoping to kms:* is almost always too broad. The service needs kms:GenerateDataKey and kms:Decrypt. Nothing else.
Mistake 3: cross-account without the external account IAM policy
Cross-account KMS usage requires two grants: one in the key policy (allowing the external account’s principal) and one in the external account’s IAM policy (allowing the specific role). Either alone is insufficient.