From 67e25f53d5bee384ec748c4d5b9e732ce6b62ddd Mon Sep 17 00:00:00 2001 From: Adam Moussa Date: Wed, 10 Jun 2026 13:58:13 -0400 Subject: [PATCH] Fix boundary gaps found in GPT-4.1 cross-review MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Three issues from the mandatory IAM cross-review (BLOCK/FIX): 1. Add KMS statement — PaymentsDashboard DynamoDB table and payments-dashboard CloudWatch log groups use CMKs. Without kms:Decrypt + kms:GenerateDataKey in the boundary, those Lambda calls fail at the KMS layer at runtime. Scoped to account keys only. 2. Add table/*/index/* to DynamoDB resource — dynamodb:Query on a GSI requires the index ARN; covering only table/* silently denied GSI queries at the boundary. 3. Fix EC2 ENI statement — remove AssignPrivateIpAddresses / UnassignPrivateIpAddresses (EFA-only, not part of Lambda ENI lifecycle); add DescribeSubnets + DescribeSecurityGroups + DescribeVpcs which are required by the Lambda service during VPC attachment and are present in AWSLambdaVPCAccessExecutionRole. 4. Add SES configuration-set/* resource — ses:SendRawEmail requires permission on the configuration set if one is passed at send time. Refs: INFRA-103 --- oidc-deploy-roles.yaml | 32 ++++++++++++++++++++++++++++---- 1 file changed, 28 insertions(+), 4 deletions(-) diff --git a/oidc-deploy-roles.yaml b/oidc-deploy-roles.yaml index 2754733..27d01b5 100644 --- a/oidc-deploy-roles.yaml +++ b/oidc-deploy-roles.yaml @@ -118,19 +118,23 @@ Resources: Resource: "*" # ── VPC / ENI management (payments-dashboard VPC functions) ──────── - # ec2:Describe* are required even for non-VPC Lambdas as the ENI - # lifecycle actions need them. + # Matches AWSLambdaVPCAccessExecutionRole exactly. + # AssignPrivateIpAddresses / UnassignPrivateIpAddresses are for EFA + # and secondary IPs — not part of the Lambda ENI lifecycle — omitted. - Sid: Ec2Eni Effect: Allow Action: - ec2:CreateNetworkInterface - ec2:DescribeNetworkInterfaces - ec2:DeleteNetworkInterface - - ec2:AssignPrivateIpAddresses - - ec2:UnassignPrivateIpAddresses + - ec2:DescribeSubnets + - ec2:DescribeSecurityGroups + - ec2:DescribeVpcs Resource: "*" # ── DynamoDB (afterhours, payments, meal-order, front-integrations) ─ + # Table/* covers base-table operations; table/*/index/* is required for + # Query/Scan on Global Secondary Indexes. - Sid: DynamoDB Effect: Allow Action: @@ -146,6 +150,7 @@ Resources: - dynamodb:ConditionCheckItem Resource: - !Sub "arn:aws:dynamodb:us-east-1:${AWS::AccountId}:table/*" + - !Sub "arn:aws:dynamodb:us-east-1:${AWS::AccountId}:table/*/index/*" # ── S3 (payments-dashboard read, meal-order-manager CRUD) ────────── - Sid: S3 @@ -216,6 +221,25 @@ Resources: - ses:SendRawEmail Resource: - !Sub "arn:aws:ses:us-east-1:${AWS::AccountId}:identity/*" + - !Sub "arn:aws:ses:us-east-1:${AWS::AccountId}:configuration-set/*" + + # ── KMS (CMK-encrypted resources) ───────────────────────────────── + # Required for Lambda functions that read/write CMK-encrypted AWS + # resources. Verified live state: + # - PaymentsDashboard DynamoDB table: CMK key/0b660af3 (KMS:ENABLED) + # - payments-dashboard CloudWatch log groups: CMK key/b748750c + # Secrets Manager + SQS queues in these stacks use AWS-managed keys + # (aws/secretsmanager, aws/sqs) which do not require explicit kms:* + # actions in the execution role policy. The CMK keys are scoped to + # this account to prevent cross-account KMS calls. + - Sid: KMS + Effect: Allow + Action: + - kms:Decrypt + - kms:GenerateDataKey + - kms:DescribeKey + Resource: + - !Sub "arn:aws:kms:us-east-1:${AWS::AccountId}:key/*" # --------------------------------------------------------------------------- # Shared CloudFormation execution role (SAM stacks)