KMS Key Policies & IAM Principals
KMS Key Policies are the primary access control mechanism for AWS KMS keysβunlike most other resource policies in AWS, a KMS key cannot be accessed by any principal unless the key policy explicitly allows it! ποΈπ‘οΈ
Understanding how the key policy delegates authority to IAM or grants direct access to principals is one of the most high-yield topics on the DVA-C02 exam.
Key Takeawaysβ
Let's take notes on the default key policy behavior, principal targets, and decision paths.
π The Default KMS Key Policy & The "Root" Trapβ
When you create a Customer Managed Key (CMK) via the console, AWS injects a default key policy statement that looks like this:
{
"Sid": "Enable IAM User Permissions",
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::123456789012:root"
},
"Action": "kms:*",
"Resource": "*"
}
π¨ The DVA-C02 Exam Trap (:root Principal Nuance):β
- What this do: In AWS IAM logic, specifying the
:rootas a principal doesn't mean only the root account user gets access. Instead, it means "trust this entire AWS account," as long as they have proper IAM permissions. - The Golden Rule: Without this statement (or an explicit IAM allow statement in the key policy), IAM identity policies attached to users or roles are completely useless for accessing the KMS key!
ποΈ KMS KEY ACCESS EVALUATION PATHWAY:
βββ 1. Direct Access: Principal listed explicitly in KMS Key Policy? βββΊ ALLOWED β
(IAM Policy NOT required)
βββ 2. Delegated Access: Account `:root` allowed in KMS Key Policy?
βββ YES βββΊ Check IAM Identity Policy βββΊ Has `kms:Encrypt`/`Decrypt`? βββΊ ALLOWED β
βββ NO βββΊ IAM Identity Policy ignored! βββββββββββββββββββββββββββββββΊ DENIED β
π― Principal Types in KMS Key Policiesβ
You can target various IAM principals directly inside a key policy statement using the "Principal" block:
{
"Effect": "Allow",
"Principal": {
"AWS": [
"arn:aws:iam::123456789012:root",
"arn:aws:iam::123456789012:user/Zoro",
"arn:aws:iam::123456789012:role/S3WriteRole",
"arn:aws:sts::123456789012:assumed-role/S3WriteRole/session-name",
"arn:aws:iam::123456789012:role/federated-user/user-name"
],
"Service": [
"s3.amazonaws.com",
"ecs.amazonaws.com",
"elasticloadbalancing.amazonaws.com"
],
"Federated": [
"cognito-identity.amazonaws.com",
"arn:aws:iam::123456789012:saml-provider/Okta"
]
},
"Action": ["kms:Encrypt", "kms:Decrypt"],
"Resource": "*"
}
| Principal Structure | Syntax Example | Key Takeaway |
|---|---|---|
| AWS Account Delegation | "AWS": "arn:aws:iam::123456789012:root" | Delegates authorization decisions to IAM Identity Policies in account 123456789012. |
| Specific IAM Role | "AWS": "arn:aws:iam::123456789012:role/AppRole" | Grants access directly to anyone assuming that IAM Role. |
| Assumed Role Session | "AWS": "arn:aws:sts::123456789012:assumed-role/RoleName/Session" | Locks down access to a single active session of an assumed role. |
| Federated User | "Federated": "cognito-identity.amazonaws.com" | Direct permission mapping for external or Web Identity users. |
| AWS Service Principal | "Service": "lambda.amazonaws.com" | Allows an AWS service to interact directly with the key (often combined with kms:ViaService conditions). |
Exam Tipsβ
- The Mysterious KMS Access Denied Scenario: If a developer attached a policy allowing
kms:Decryptdirectly to a Lambda function's IAM execution role, but the function still receivesAccessDeniedExceptionwhen decryptingβthe root cause is that the KMS Key Policy does not have the:rootdelegation statement or does not explicitly list the Lambda Role ARN as a Principal! - Cross-Account KMS Key Access π: When sharing a Customer Managed Key (CMK) across AWS accounts (e.g., Account A sharing a key with Account B to decrypt an S3 bucket or EBS snapshot):
- Account A (Owner): The KMS Key Policy must explicitly grant Account B (
arn:aws:iam::AccountB:root) permission to use the key. - Account B (Consumer): An IAM identity policy inside Account B must explicitly allow the user/role to invoke
kms:Decrypttargeting Account A's KMS Key ARN!
- Account A (Owner): The KMS Key Policy must explicitly grant Account B (