From 7c43c867e3b794c013a9f863b959face9901c5c6 Mon Sep 17 00:00:00 2001 From: Adam Moussa Date: Mon, 10 Aug 2026 15:42:12 -0400 Subject: [PATCH 1/2] fix(iam): allow execute-api Invoke for meal-order weekly-menu boundary --- lib/deploy-substrate/deploy-substrate.template.yaml | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/lib/deploy-substrate/deploy-substrate.template.yaml b/lib/deploy-substrate/deploy-substrate.template.yaml index fa9712e..fb02518 100644 --- a/lib/deploy-substrate/deploy-substrate.template.yaml +++ b/lib/deploy-substrate/deploy-substrate.template.yaml @@ -682,6 +682,19 @@ Resources: Resource: - !Sub "arn:aws:ssm:us-east-1:${AWS::AccountId}:parameter/meal-order-manager/*" - !Ref AWS::NoValue + # Weekly-menu OIDC role (githubdeploy-meal-order-manager-weekly-menu) + # invokes IAM-authenticated HttpApi publish routes. Identity policy + # pins the API id; boundary uses method/path only (PLAT-100). + - !If + - IsProdAccount + - Sid: MealOrderManagerExecuteApi + Effect: Allow + Action: + - execute-api:Invoke + Resource: + - !Sub "arn:aws:execute-api:us-east-1:${AWS::AccountId}:*/*/GET/api/publish/settings" + - !Sub "arn:aws:execute-api:us-east-1:${AWS::AccountId}:*/*/POST/api/publish/menu" + - !Ref AWS::NoValue - !If - IsProdAccount - Sid: MealOrderManagerLambdaInvoke From 81cc8eb4f925a28acfa8e104104359b3b2377757 Mon Sep 17 00:00:00 2001 From: Adam Moussa Date: Mon, 10 Aug 2026 15:57:08 -0400 Subject: [PATCH 2/2] fix(iam): consolidate meal-order boundary Sid under PolicySize cap --- .../deploy-substrate.template.yaml | 50 ++++++++----------- 1 file changed, 21 insertions(+), 29 deletions(-) diff --git a/lib/deploy-substrate/deploy-substrate.template.yaml b/lib/deploy-substrate/deploy-substrate.template.yaml index fb02518..fc97b8e 100644 --- a/lib/deploy-substrate/deploy-substrate.template.yaml +++ b/lib/deploy-substrate/deploy-substrate.template.yaml @@ -121,13 +121,15 @@ Description: >- # correctly left untouched. # # SIZE BUDGET: an attached managed policy document is capped at 6,144 characters -# (whitespace excluded). LambdaExecutionBoundary measures 5903 characters across -# 16 statements as of 2026-08-07 (PLAT-93 consolidation after the meal-order -# PolicySize rollback). Measure before widening — len(json.dumps(doc, -# separators=(',',':'))) on the synthesized PolicyDocument with -# ${AWS::AccountId} resolved, and UPDATE THESE TWO NUMBERS in the same edit. +# (whitespace excluded). LambdaExecutionBoundary measures 5986 characters across +# 15 statements as of 2026-08-10 (PLAT-100: MealOrderManagerSsm+LambdaInvoke +# consolidated with execute-api:Invoke; SES kept separate because Resource:"*" +# must not share a statement with execute-api:Invoke. Was 5903/16 after PLAT-93). +# Measure before widening — len(json.dumps(doc, separators=(',',':'))) on the +# synthesized PolicyDocument with ${AWS::AccountId} resolved, and UPDATE THESE +# TWO NUMBERS in the same edit. # -# Headroom is 241 characters. Statement consolidation (shared WorkloadSecrets / +# Headroom is 158 characters. Statement consolidation (shared WorkloadSecrets / # WorkloadDynamoDB / extended WorkloadS3 Resource lists; no new action wildcards) # is the only remaining lever short of per-workload boundaries. If the budget # tightens again, the end-state fix is per-workload boundaries @@ -670,40 +672,30 @@ Resources: - !Sub "arn:aws:cloudfront::${AWS::AccountId}:distribution/*" - !Ref AWS::NoValue - # ── meal-order-manager (PLAT-70) — statements not covered above ───── + # ── meal-order-manager (PLAT-70 / PLAT-100) — not covered above ───── # Secrets → WorkloadSecrets; DynamoDB → WorkloadDynamoDB; S3 → WorkloadS3; - # SNS → ProcurementIngestSns. Trimmed to identity-policy needs. + # SNS → ProcurementIngestSns. SSM + Lambda Invoke + execute-api share + # one Sid (scoped Resources only) so PolicySize stays under 6,144 — + # a standalone execute-api Sid is ~243 chars against 241 headroom and + # would fail UPDATE with LimitExceeded. SES stays in its own Sid: + # Resource:"*" must not share a statement with execute-api:Invoke + # (that would allow Invoke on every API in the account). + # Weekly-menu OIDC identity policy pins the API id; boundary pins + # method/path only. - !If - IsProdAccount - - Sid: MealOrderManagerSsm + - Sid: MealOrderManager Effect: Allow Action: - ssm:GetParameter - Resource: - - !Sub "arn:aws:ssm:us-east-1:${AWS::AccountId}:parameter/meal-order-manager/*" - - !Ref AWS::NoValue - # Weekly-menu OIDC role (githubdeploy-meal-order-manager-weekly-menu) - # invokes IAM-authenticated HttpApi publish routes. Identity policy - # pins the API id; boundary uses method/path only (PLAT-100). - - !If - - IsProdAccount - - Sid: MealOrderManagerExecuteApi - Effect: Allow - Action: + - lambda:InvokeFunction - execute-api:Invoke Resource: + - !Sub "arn:aws:ssm:us-east-1:${AWS::AccountId}:parameter/meal-order-manager/*" + - !Sub "arn:aws:lambda:us-east-1:${AWS::AccountId}:function:meal-order-manager-*" - !Sub "arn:aws:execute-api:us-east-1:${AWS::AccountId}:*/*/GET/api/publish/settings" - !Sub "arn:aws:execute-api:us-east-1:${AWS::AccountId}:*/*/POST/api/publish/menu" - !Ref AWS::NoValue - - !If - - IsProdAccount - - Sid: MealOrderManagerLambdaInvoke - Effect: Allow - Action: - - lambda:InvokeFunction - Resource: - - !Sub "arn:aws:lambda:us-east-1:${AWS::AccountId}:function:meal-order-manager-*" - - !Ref AWS::NoValue - !If - IsProdAccount - Sid: MealOrderManagerSes