Skip to content

fix(aws): narrow the CloudFormation KMS key/* grant to another account's keys - #90

Closed
tim-thacker-nullify wants to merge 1 commit into
feat/cfn-managed-eks-scan-review-r4from
fix/cfn-narrow-kms-key-wildcard
Closed

tim-thacker-nullify wants to merge 1 commit into
feat/cfn-managed-eks-scan-review-r4from
fix/cfn-narrow-kms-key-wildcard

Conversation

@tim-thacker-nullify

@tim-thacker-nullify tim-thacker-nullify commented Sep 15, 2026 •

Copy link
Copy Markdown
Member

Claude

KMSAccessPolicy granted arn:<partition>:kms:<region>:<account>:key/* next to NullifyKMSKeyArn unconditionally, so a customer who pasted a key ARN from their own account handed the role every KMS key in that account and region. #89 narrows Terraform to derive the wildcard only when the ARN's account differs from the deploying account; this brings the CloudFormation template in line.

  • the policy is two statements: the supplied ARN always, and key/* in the ARN's account and region under StringNotEquals on aws:PrincipalAccount
  • aws:PrincipalAccount is the account owning the role, always the deploying account, so the statement applies exactly when the ARN's account is not it
  • NullifyKMSKeyArn's description, the KMSPolicyResource output description and the template README describe the gate

Not deploy-time parity

Terraform drops the wildcard from the policy document. CloudFormation cannot: condition functions accept only Fn::FindInMap, Ref and other condition functions, so the Fn::Select/Fn::Split that parses the account out of the ARN cannot appear inside Fn::Equals, and no Condition can gate a statement or an Fn::If resource list on it. AWS::LanguageExtensions adds Fn::ForEach, Fn::Length and Fn::ToJsonString only.

The wildcard resource therefore stays in the rendered document and is gated per request instead. Effective permissions match Terraform; the policy JSON does not.

Resulting grant

NullifyKMSKeyArn Effective resources
Nullify alias ARN (...:111122223333:alias/x, stack in 999988887777) the alias ARN (inert: IAM never resolves it) plus arn:aws:kms:<region>:111122223333:key/*
Nullify key ARN (...:111122223333:key/mrk-...) that key plus arn:aws:kms:<region>:111122223333:key/*
Customer's own key ARN (...:999988887777:key/..., stack in 999988887777) that key alone

Unverified

🤖 Generated with Claude Code


View with [code]smith Autofix with [code]smith
Need help on this PR? Tag @codesmith-bot with what you need. Autofix is disabled.

…t's keys

KMSAccessPolicy granted arn:<partition>:kms:<region>:<account>:key/* next to
NullifyKMSKeyArn unconditionally, so a customer who pastes a key ARN from their
own account handed the role every KMS key in that account and region. Terraform
now derives the wildcard only when the ARN's account differs from the deploying
account.

- the policy is two statements: the supplied ARN always, and key/* in the ARN's
  account and region under StringNotEquals on aws:PrincipalAccount, which holds
  only when that account is not the one the stack is deployed into
- the check is a request-time IAM condition, not a template Condition, because
  CloudFormation allows only Ref, Fn::FindInMap and other conditions inside
  Fn::Equals, so an account parsed out of the ARN with Fn::Select cannot be
  compared with AWS::AccountId at deploy time
- a Nullify alias ARN keeps its key/* grant, which IAM needs because it never
  resolves an alias ARN for key operations
- NullifyKMSKeyArn's description, the KMSPolicyResource output description and
  the template README describe the gate and why it is evaluated per request

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@tim-thacker-nullify

Copy link
Copy Markdown
Member Author

Claude

Collapsed into #64 at f9903ac after passing adversarial review; all of this PR's commits are now in #64.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant