mirror of
https://github.com/Sea-Haven-Industries/seahaven-org-baseline.git
synced 2026-10-02 03:53:22 +00:00
refactor(iam): consolidate boundary statements under PolicySize cap (#98)
Merge workload secret/DDB/S3 SIDs and trim meal-order extras so the shared lambda execution boundary fits under the 6144-character limit.
This commit is contained in:
parent
44b672ae9a
commit
3605215a28
1 changed files with 56 additions and 133 deletions
|
|
@ -121,26 +121,23 @@ Description: >-
|
|||
# correctly left untouched.
|
||||
#
|
||||
# SIZE BUDGET: an attached managed policy document is capped at 6,144 characters
|
||||
# (whitespace excluded). LambdaExecutionBoundary measures 691 characters across
|
||||
# 4 statements as of 2026-07-31 — the fleet-wide floor only. 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 (they went stale twice inside this branch alone).
|
||||
# (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.
|
||||
#
|
||||
# Headroom is 5,453 characters, roughly TWELVE workloads at ~450 each. That is a
|
||||
# deliberate outcome, not luck: an earlier revision of this branch pre-loaded
|
||||
# per-workload prefixes for all five mgmt SAM stacks and reached 5,457 characters
|
||||
# with 687 left — about one workload of room — before any stack had actually
|
||||
# migrated. Deferring per-workload scope to each migration PR (see the note on
|
||||
# the boundary itself) removed that pressure entirely. If the budget tightens
|
||||
# again as workloads land, the end-state fix is per-workload boundaries
|
||||
# Headroom is 241 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
|
||||
# (seahaven-lambda-execution-boundary-<workload>), which also resolves the
|
||||
# shared-ceiling residual — tracked as INFRA-187, do not improvise it.
|
||||
# shared-ceiling residual — tracked as PLAT-52 / INFRA-187, do not improvise it.
|
||||
# CRITICAL: unlike the 2026-07-27 inline-limit incident,
|
||||
# there is NO restructure available when this cap is reached — a role has exactly
|
||||
# ONE permissions boundary, so statements cannot be spilled into a second attached
|
||||
# managed policy. At the cap the only levers are prefix consolidation and dropping
|
||||
# unused actions.
|
||||
# unused actions. Do not introduce dynamodb:* / s3:* / ses:Send* to reclaim space.
|
||||
#
|
||||
# This template is deployed via lib/deploy-substrate-stack.ts
|
||||
# (cloudformation-include) as stack seahaven-deploy-substrate, once per member
|
||||
|
|
@ -492,71 +489,38 @@ Resources:
|
|||
- ec2:DescribeVpcs
|
||||
Resource: "*"
|
||||
|
||||
# ── afi-backup-monitor (PLAT-56) — prod-only exact secret ARNs ───────
|
||||
# Derived from live stack parameters + secrets created in seahaven-prod
|
||||
# 2026-08-05. No secret:afi-* patterns. Omitted in seahaven-dev via
|
||||
# IsProdAccount (same template deploys to both accounts).
|
||||
# ── Shared workload data-plane (PLAT-93 PolicySize consolidation) ───
|
||||
# Per-workload secret/DDB/S3 SIDs were merged so meal-order-manager
|
||||
# (PLAT-70) can fit under the 6,144-character managed-policy cap
|
||||
# without introducing new action wildcards. Exact secret ARNs only.
|
||||
# End-state isolation remains PLAT-52 / INFRA-187.
|
||||
#
|
||||
# WorkloadSecrets covers: afi-backup-monitor (PLAT-56),
|
||||
# front-integrations (PLAT-72), procurement-ingest (PLAT-86),
|
||||
# meal-order-manager (PLAT-70).
|
||||
- !If
|
||||
- IsProdAccount
|
||||
- Sid: AfiBackupMonitorSecrets
|
||||
- Sid: WorkloadSecrets
|
||||
Effect: Allow
|
||||
Action:
|
||||
- secretsmanager:GetSecretValue
|
||||
Resource:
|
||||
- arn:aws:secretsmanager:us-east-1:011934824531:secret:afi-api-key-w0E02a
|
||||
- arn:aws:secretsmanager:us-east-1:011934824531:secret:afi-slack-webhook-T4oR3G
|
||||
- !Ref AWS::NoValue
|
||||
|
||||
# ── front-integrations (PLAT-72) — prod-only exact secret ARNs + DDB ─
|
||||
# Derived from live SAM template + secrets created in seahaven-prod
|
||||
# 2026-08-05. No secret:front-integrations/* patterns.
|
||||
- !If
|
||||
- IsProdAccount
|
||||
- Sid: FrontIntegrationsSecrets
|
||||
Effect: Allow
|
||||
Action:
|
||||
- secretsmanager:GetSecretValue
|
||||
Resource:
|
||||
- arn:aws:secretsmanager:us-east-1:011934824531:secret:front-integrations/front-api-token-UXKv0U
|
||||
- arn:aws:secretsmanager:us-east-1:011934824531:secret:front-integrations/slack-bot-token-giGfA7
|
||||
- arn:aws:secretsmanager:us-east-1:011934824531:secret:front-integrations/google-service-account-dqv3Bo
|
||||
- !Ref AWS::NoValue
|
||||
- !If
|
||||
- IsProdAccount
|
||||
- Sid: FrontIntegrationsDynamoDB
|
||||
Effect: Allow
|
||||
Action:
|
||||
- dynamodb:GetItem
|
||||
- dynamodb:PutItem
|
||||
- dynamodb:UpdateItem
|
||||
- dynamodb:DeleteItem
|
||||
- dynamodb:Query
|
||||
- dynamodb:Scan
|
||||
- dynamodb:BatchGetItem
|
||||
- dynamodb:BatchWriteItem
|
||||
- dynamodb:DescribeTable
|
||||
- dynamodb:ConditionCheckItem
|
||||
Resource:
|
||||
- !Sub "arn:aws:dynamodb:us-east-1:${AWS::AccountId}:table/front-sla-alerts"
|
||||
- !Sub "arn:aws:dynamodb:us-east-1:${AWS::AccountId}:table/front-sla-alerts/index/*"
|
||||
- !Ref AWS::NoValue
|
||||
|
||||
# ── procurement-ingest (PLAT-86) — prod-only exact secrets + data plane ─
|
||||
# Derived from live CDK stacks in seahaven-prod 2026-08-06. Exact secret
|
||||
# ARNs only (no secret:procurement-* / workorder-ingest/* wildcards).
|
||||
- !If
|
||||
- IsProdAccount
|
||||
- Sid: ProcurementIngestSecrets
|
||||
Effect: Allow
|
||||
Action:
|
||||
- secretsmanager:GetSecretValue
|
||||
Resource:
|
||||
- arn:aws:secretsmanager:us-east-1:011934824531:secret:procurement-ingest/web-ui-auth-token-ApAMmr
|
||||
- arn:aws:secretsmanager:us-east-1:011934824531:secret:workorder-ingest/shoc-webhook-hmac-puYTcB
|
||||
- arn:aws:secretsmanager:us-east-1:011934824531:secret:meal-order-manager/slack-bot-token-ZGmSGw
|
||||
- !Ref AWS::NoValue
|
||||
|
||||
# WorkloadDynamoDB: enumerated union of front-integrations CRUD +
|
||||
# procurement-ingest CRUD/stream actions. Meal-order table ARNs appended.
|
||||
# Stream actions on non-stream tables are inert at the ceiling.
|
||||
- !If
|
||||
- IsProdAccount
|
||||
- Sid: ProcurementIngestDynamoDB
|
||||
- Sid: WorkloadDynamoDB
|
||||
Effect: Allow
|
||||
Action:
|
||||
- dynamodb:GetItem
|
||||
|
|
@ -576,6 +540,8 @@ Resources:
|
|||
# it is a silent no-op. Runtime stream consumers use the
|
||||
# stream ARN via DescribeStream/GetRecords above.
|
||||
Resource:
|
||||
- !Sub "arn:aws:dynamodb:us-east-1:${AWS::AccountId}:table/front-sla-alerts"
|
||||
- !Sub "arn:aws:dynamodb:us-east-1:${AWS::AccountId}:table/front-sla-alerts/index/*"
|
||||
- !Sub "arn:aws:dynamodb:us-east-1:${AWS::AccountId}:table/purchase-orders"
|
||||
- !Sub "arn:aws:dynamodb:us-east-1:${AWS::AccountId}:table/purchase-orders/*"
|
||||
- !Sub "arn:aws:dynamodb:us-east-1:${AWS::AccountId}:table/verified-sites"
|
||||
|
|
@ -590,10 +556,16 @@ Resources:
|
|||
- !Sub "arn:aws:dynamodb:us-east-1:${AWS::AccountId}:table/work-orders/*"
|
||||
- !Sub "arn:aws:dynamodb:us-east-1:${AWS::AccountId}:table/work-order-comments"
|
||||
- !Sub "arn:aws:dynamodb:us-east-1:${AWS::AccountId}:table/work-order-comments/*"
|
||||
- !Sub "arn:aws:dynamodb:us-east-1:${AWS::AccountId}:table/meal-order-manager-orders"
|
||||
- !Sub "arn:aws:dynamodb:us-east-1:${AWS::AccountId}:table/meal-order-manager-orders/index/*"
|
||||
- !Ref AWS::NoValue
|
||||
|
||||
# ── procurement-ingest remaining data plane + meal-order S3 (PLAT-86/70) ─
|
||||
# WorkloadS3 keeps the prior ProcurementIngestS3 action list and appends
|
||||
# meal-order form/reports bucket ARNs (same object CRUD shape).
|
||||
- !If
|
||||
- IsProdAccount
|
||||
- Sid: ProcurementIngestS3
|
||||
- Sid: WorkloadS3
|
||||
Effect: Allow
|
||||
Action:
|
||||
- s3:GetObject*
|
||||
|
|
@ -607,6 +579,10 @@ Resources:
|
|||
- !Sub "arn:aws:s3:::po-ingest-emails-${AWS::AccountId}/*"
|
||||
- !Sub "arn:aws:s3:::workorder-ingest-emails-${AWS::AccountId}"
|
||||
- !Sub "arn:aws:s3:::workorder-ingest-emails-${AWS::AccountId}/*"
|
||||
- !Sub "arn:aws:s3:::meal-order-manager-form-${AWS::AccountId}"
|
||||
- !Sub "arn:aws:s3:::meal-order-manager-form-${AWS::AccountId}/*"
|
||||
- !Sub "arn:aws:s3:::meal-order-manager-reports-${AWS::AccountId}"
|
||||
- !Sub "arn:aws:s3:::meal-order-manager-reports-${AWS::AccountId}/*"
|
||||
- !Ref AWS::NoValue
|
||||
- !If
|
||||
- IsProdAccount
|
||||
|
|
@ -651,6 +627,8 @@ Resources:
|
|||
- arn:aws:bedrock:us-east-2::foundation-model/anthropic.claude-haiku-4-5-20251001-v1:0
|
||||
- arn:aws:bedrock:us-west-2::foundation-model/anthropic.claude-haiku-4-5-20251001-v1:0
|
||||
- !Ref AWS::NoValue
|
||||
# site-alerts publish shared by procurement-ingest alarms and
|
||||
# meal-order-manager (PLAT-70); no separate MealOrder SNS statement.
|
||||
- !If
|
||||
- IsProdAccount
|
||||
- Sid: ProcurementIngestSns
|
||||
|
|
@ -692,61 +670,15 @@ Resources:
|
|||
- !Sub "arn:aws:cloudfront::${AWS::AccountId}:distribution/*"
|
||||
- !Ref AWS::NoValue
|
||||
|
||||
# ── meal-order-manager (PLAT-70) — prod-only exact secret ARN + data plane ─
|
||||
# Derived from meal-order-manager template.yaml + secrets created in
|
||||
# seahaven-prod 2026-08-07. Exact ARN only (no secret:meal-order-* patterns).
|
||||
- !If
|
||||
- IsProdAccount
|
||||
- Sid: MealOrderManagerSecrets
|
||||
Effect: Allow
|
||||
Action:
|
||||
- secretsmanager:GetSecretValue
|
||||
Resource:
|
||||
- arn:aws:secretsmanager:us-east-1:011934824531:secret:meal-order-manager/slack-bot-token-ZGmSGw
|
||||
- !Ref AWS::NoValue
|
||||
- !If
|
||||
- IsProdAccount
|
||||
- Sid: MealOrderManagerDynamoDB
|
||||
Effect: Allow
|
||||
Action:
|
||||
- dynamodb:GetItem
|
||||
- dynamodb:PutItem
|
||||
- dynamodb:UpdateItem
|
||||
- dynamodb:DeleteItem
|
||||
- dynamodb:Query
|
||||
- dynamodb:Scan
|
||||
- dynamodb:BatchGetItem
|
||||
- dynamodb:BatchWriteItem
|
||||
- dynamodb:DescribeTable
|
||||
- dynamodb:ConditionCheckItem
|
||||
Resource:
|
||||
- !Sub "arn:aws:dynamodb:us-east-1:${AWS::AccountId}:table/meal-order-manager-orders"
|
||||
- !Sub "arn:aws:dynamodb:us-east-1:${AWS::AccountId}:table/meal-order-manager-orders/index/*"
|
||||
- !Ref AWS::NoValue
|
||||
- !If
|
||||
- IsProdAccount
|
||||
- Sid: MealOrderManagerS3
|
||||
Effect: Allow
|
||||
Action:
|
||||
- s3:GetObject*
|
||||
- s3:GetBucket*
|
||||
- s3:List*
|
||||
- s3:PutObject*
|
||||
- s3:DeleteObject*
|
||||
- s3:AbortMultipartUpload
|
||||
Resource:
|
||||
- !Sub "arn:aws:s3:::meal-order-manager-form-${AWS::AccountId}"
|
||||
- !Sub "arn:aws:s3:::meal-order-manager-form-${AWS::AccountId}/*"
|
||||
- !Sub "arn:aws:s3:::meal-order-manager-reports-${AWS::AccountId}"
|
||||
- !Sub "arn:aws:s3:::meal-order-manager-reports-${AWS::AccountId}/*"
|
||||
- !Ref AWS::NoValue
|
||||
# ── meal-order-manager (PLAT-70) — statements not covered above ─────
|
||||
# Secrets → WorkloadSecrets; DynamoDB → WorkloadDynamoDB; S3 → WorkloadS3;
|
||||
# SNS → ProcurementIngestSns. Trimmed to identity-policy needs.
|
||||
- !If
|
||||
- IsProdAccount
|
||||
- Sid: MealOrderManagerSsm
|
||||
Effect: Allow
|
||||
Action:
|
||||
- ssm:GetParameter
|
||||
- ssm:GetParameters
|
||||
Resource:
|
||||
- !Sub "arn:aws:ssm:us-east-1:${AWS::AccountId}:parameter/meal-order-manager/*"
|
||||
- !Ref AWS::NoValue
|
||||
|
|
@ -765,26 +697,17 @@ Resources:
|
|||
Effect: Allow
|
||||
Action:
|
||||
- ses:SendRawEmail
|
||||
- ses:SendEmail
|
||||
Resource: "*"
|
||||
- !Ref AWS::NoValue
|
||||
- !If
|
||||
- IsProdAccount
|
||||
- Sid: MealOrderManagerSns
|
||||
Effect: Allow
|
||||
Action:
|
||||
- sns:Publish
|
||||
Resource:
|
||||
- !Sub "arn:aws:sns:us-east-1:${AWS::AccountId}:site-alerts"
|
||||
- !Ref AWS::NoValue
|
||||
|
||||
# ── FURTHER PER-WORKLOAD DATA-PLANE STATEMENTS ──────────────────────
|
||||
# Floor above + afi-backup-monitor (PLAT-56) + front-integrations
|
||||
# (PLAT-72) + procurement-ingest (PLAT-86) + seahaven-site (PLAT-91)
|
||||
# + meal-order-manager (PLAT-70).
|
||||
# Additional stacks add their own statements here, derived from THEIR
|
||||
# OWN template, in their own PR, deployed to UPDATE_COMPLETE before
|
||||
# first workload deploy. WIDENING PATH in the header still governs.
|
||||
# Floor above + consolidated WorkloadSecrets/DynamoDB/S3 (PLAT-93) +
|
||||
# procurement remainder + seahaven-site (PLAT-91) + meal-order extras
|
||||
# (PLAT-70). Prefer extending existing Resource lists over new SIDs.
|
||||
# Additional stacks add statements here, derived from THEIR OWN
|
||||
# template, in their own PR, deployed to UPDATE_COMPLETE before first
|
||||
# workload deploy. Measure SIZE BUDGET before merging. WIDENING PATH
|
||||
# in the header still governs.
|
||||
#
|
||||
# WHY the floor stayed empty of data-plane (decided 2026-07-30, Adam):
|
||||
# The security win of INFRA-186 comes from DELETION, not enumeration.
|
||||
|
|
@ -795,10 +718,10 @@ Resources:
|
|||
#
|
||||
# The end-state fix for the shared-ceiling residual (one boundary =
|
||||
# every SAM/Terraform workload reaches every other's data plane once
|
||||
# they land) is per-workload boundaries — tracked as INFRA-187. Do not
|
||||
# improvise it: both guardrail policies pin ONE literal boundary ARN
|
||||
# inside StringEquals conditions, and loosening that to a wildcard
|
||||
# weakens the gate.
|
||||
# they land) is per-workload boundaries — tracked as PLAT-52 /
|
||||
# INFRA-187. Do not improvise it: both guardrail policies pin ONE
|
||||
# literal boundary ARN inside StringEquals conditions, and loosening
|
||||
# that to a wildcard weakens the gate.
|
||||
# ---------------------------------------------------------------------------
|
||||
# Shared CloudFormation execution role (SAM stacks) — INFRA-97 scoped
|
||||
#
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue