chore(template): drop dead IAM grants and standardize on AWS::Partition#541
Merged
Conversation
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>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Housekeeping pass on
template.yamlafter 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)S3ListBucketPolicy.internal/repository/s3.goonly issuesGetObjectandPutObjecton the single state object;ListBucket/ListObjectsV2/HeadObjectare never called, so the statement and itss3:prefixcondition were unreachable.KMSGetDataPolicy.kms:GenerateDataKeyPairis 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 renamedKMSStateObjectPolicy.secretsmanager:GetResourcePolicyaction.pkg/aws/secretsmanager.goonly callsGetSecretValue.SSMGetParameterPolicy→SecretsManagerGetSecretValuePolicy(the old name was a copy-paste from a different AWS service).KMSDecryptPolicy→KMSStateObjectPolicyto reflect that it covers all SSE-KMS operations on the state object (Decrypt, Encrypt, GenerateDataKey), not just decryption.KMS key policy
AllowAWSLambdaToRetrieveKMSKey. Its principal wasService: lambda.amazonaws.com, but at runtime KMS sees the function's assumed-role ARN — not the Lambda service principal — when S3 forwardskms:*calls on the role's behalf. The statement granted nothing at runtime; the real grant isAllowIAMThisAccount(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
arn:aws:…ARNs witharn:${AWS::Partition}:…:KMSKeyAllowIAMThisAccountprincipalBucketBucketEncryption.KMSMasterKeyIDBucketPolicyAllowAWSLambdaFunctionprincipal${AWS::Partition}. The template is now deployable in non-commercial AWS partitions (GovCloud, China) without manual edits.Test plan
sam validate --lint -t template.yamlpasses.s3:GetObject/s3:PutObject/secretsmanager:GetSecretValue(plus the S3-forwardedkms:Decrypt/kms:GenerateDataKey).Follow-up to #540.
🤖 Generated with Claude Code