Skip to content

chore(template): drop dead IAM grants and standardize on AWS::Partition#541

Merged
christiangda merged 2 commits into
mainfrom
chore/template-cleanups
May 26, 2026
Merged

chore(template): drop dead IAM grants and standardize on AWS::Partition#541
christiangda merged 2 commits into
mainfrom
chore/template-cleanups

Conversation

@christiangda
Copy link
Copy Markdown
Contributor

@christiangda christiangda commented May 26, 2026

Summary

Housekeeping pass on template.yaml after the #533 / #540 work surfaced several IAM grants that were never reached or never matched at runtime. No runtime behavior change — every removal is unreachable code or a misleading no-op grant.

What changes

Lambda role (CustomLambdaPolicy)

  • Drop S3ListBucketPolicy. internal/repository/s3.go only issues GetObject and PutObject on the single state object; ListBucket / ListObjectsV2 / HeadObject are never called, so the statement and its s3:prefix condition were unreachable.
  • Drop KMSGetDataPolicy. kms:GenerateDataKeyPair is an asymmetric-key API; the state CMK is the default symmetric key, so the action could never be invoked against it. The needed symmetric action (kms:GenerateDataKey) is already in the renamed KMSStateObjectPolicy.
  • Drop secretsmanager:GetResourcePolicy action. pkg/aws/secretsmanager.go only calls GetSecretValue.
  • Rename SSMGetParameterPolicySecretsManagerGetSecretValuePolicy (the old name was a copy-paste from a different AWS service).
  • Rename KMSDecryptPolicyKMSStateObjectPolicy to reflect that it covers all SSE-KMS operations on the state object (Decrypt, Encrypt, GenerateDataKey), not just decryption.

KMS key policy

  • Drop AllowAWSLambdaToRetrieveKMSKey. Its principal was Service: lambda.amazonaws.com, but at runtime KMS sees the function's assumed-role ARN — not the Lambda service principal — when S3 forwards kms:* calls on the role's behalf. The statement granted nothing at runtime; the real grant is AllowIAMThisAccount (the standard delegate-to-IAM pattern) combined with the role's identity-based policy. Removing the dead statement makes the grant model unambiguous.

Partition portability

  • Replace four hardcoded arn:aws:… ARNs with arn:${AWS::Partition}:…:
    • KMSKey AllowIAMThisAccount principal
    • Bucket BucketEncryption.KMSMasterKeyID
    • BucketPolicy AllowAWSLambdaFunction principal
  • The rest of the template already used ${AWS::Partition}. The template is now deployable in non-commercial AWS partitions (GovCloud, China) without manual edits.

Test plan

  • sam validate --lint -t template.yaml passes.
  • CFN stack update (no-op for resources; IAM diff visible in the change set: 5 statements removed, 4 ARNs rewritten, 2 Sids renamed).
  • Trigger one scheduled invocation post-update and confirm sync still completes successfully (i.e. the removed grants really were unreachable).
  • Confirm CloudTrail still shows the role calling only s3:GetObject / s3:PutObject / secretsmanager:GetSecretValue (plus the S3-forwarded kms:Decrypt / kms:GenerateDataKey).

Follow-up to #540.

🤖 Generated with Claude Code

Housekeeping pass on template.yaml after the #533 / fix-permissions
work surfaced several never-reached or never-matched grants. No
runtime behavior change.

Lambda role (CustomLambdaPolicy):

* Drop S3ListBucketPolicy. internal/repository/s3.go only issues
  GetObject and PutObject on the single state object; ListBucket /
  ListObjectsV2 / HeadObject are never called, so the statement and
  its s3:prefix condition were unreachable.
* Drop KMSGetDataPolicy. kms:GenerateDataKeyPair is an asymmetric-key
  API; the state CMK is the default symmetric key, so the action
  could never be invoked against it. The needed symmetric action
  (kms:GenerateDataKey) is already in the renamed KMSStateObjectPolicy.
* Drop secretsmanager:GetResourcePolicy. pkg/aws/secretsmanager.go
  only calls GetSecretValue.
* Rename SSMGetParameterPolicy -> SecretsManagerGetSecretValuePolicy
  (the old name was a copy-paste from a different service).
* Rename KMSDecryptPolicy -> KMSStateObjectPolicy to reflect that it
  now covers all SSE-KMS operations on the state object (Decrypt,
  Encrypt, GenerateDataKey).

KMS key policy:

* Drop AllowAWSLambdaToRetrieveKMSKey. Its principal was the lambda
  service (Service: lambda.amazonaws.com), but at runtime KMS sees
  the function's assumed-role ARN — not the Lambda service — when S3
  forwards the kms:* calls on the role's behalf. The statement
  granted nothing at runtime; the real grant is AllowIAMThisAccount
  combined with the role's identity-based policy. Removing the dead
  statement makes the grant model unambiguous.

Partition portability:

* Replace four hardcoded "arn:aws:..." ARNs with "arn:${AWS::Partition}:...":
  - KMSKey AllowIAMThisAccount principal
  - Bucket BucketEncryption.KMSMasterKeyID
  - BucketPolicy AllowAWSLambdaFunction principal
  - (The rest of the template already used ${AWS::Partition}.)

docs/Whats-New.md updated with a new "Template housekeeping" entry.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@christiangda christiangda self-assigned this May 26, 2026
@christiangda christiangda added this pull request to the merge queue May 26, 2026
Merged via the queue into main with commit 8b02808 May 26, 2026
6 checks passed
@christiangda christiangda deleted the chore/template-cleanups branch May 26, 2026 08:33
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