mirror of
https://github.com/Sea-Haven-Industries/seahaven-org-baseline.git
synced 2026-09-30 06:53:17 +00:00
docs(readme): document the deploy substrate's escalation controls
The substrate section described what the stack contains but not the three Deny statements that make the boundary gate hold, so a future editor could remove or weaken them without knowing what they defend. Records why DenySelfMutation is required (the role holds unconditioned DetachRolePolicy on * and could detach the Deny-carrying policy from itself), how to verify a change by simulation, the prod/dev caveat that simulation cannot see this role's inline policies, and the rollback-wedge recovery the mgmt README already carried.
This commit is contained in:
parent
9c1d083f3f
commit
83d0d0eb0d
1 changed files with 30 additions and 0 deletions
30
README.md
30
README.md
|
|
@ -142,6 +142,36 @@ of the substrate — they are provisioned per repo at migration/onboarding time
|
|||
so an account never carries trust relationships for repos that do not deploy
|
||||
to it.
|
||||
|
||||
**Escalation controls on `github-cfn-execution-role`.** Every `iam:CreateRole`,
|
||||
`AttachRolePolicy` and `PutRolePolicy` is conditioned on the target carrying
|
||||
`seahaven-lambda-execution-boundary`. That condition alone is not sufficient,
|
||||
so the attached `seahaven-cfn-exec-iam-management` managed policy also carries
|
||||
three explicit Deny statements:
|
||||
|
||||
- `DenyBoundaryTampering` — no removing a boundary from any role or user.
|
||||
Granting the delete under the same `StringEquals` condition self-defeats the
|
||||
gate, because for a delete the condition key resolves to the boundary already
|
||||
on the target.
|
||||
- `DenyBoundaryPolicyEdit` — no rewriting any `seahaven-*` managed policy.
|
||||
- `DenySelfMutation` — the role cannot modify or delete itself or any
|
||||
`githubdeploy-*` role. Without it the control is one API call from being
|
||||
undone: `IAMRoleReadAndDelete` grants `iam:DetachRolePolicy` on `Resource:
|
||||
"*"` unconditioned, so the role could detach the very policy carrying these
|
||||
Denies.
|
||||
|
||||
Verify a change to these with `aws iam simulate-principal-policy` against the
|
||||
role's own ARN (expect `explicitDeny`) and against a `<stack>-<Function>Role-`
|
||||
name (expect `allowed`, no regression for normal SAM deploys). Note that
|
||||
simulation currently does **not** see this role's *inline* policies in
|
||||
seahaven-prod or seahaven-dev — read those back with `get-role-policy` instead.
|
||||
|
||||
Known consequence of `DenyBoundaryTampering`: a CloudFormation rollback of an
|
||||
update that *adds* a boundary to an existing role wedges in
|
||||
`UPDATE_ROLLBACK_FAILED`. Recovery is an administrator action, not a pipeline
|
||||
retry — `aws cloudformation continue-update-rollback --stack-name <stack>
|
||||
--resources-to-skip <RoleLogicalId>`. Unreachable while every SAM role is
|
||||
created with the boundary already attached.
|
||||
|
||||
**Onboarding a future account as a deploy target:**
|
||||
|
||||
1. CDK-bootstrap the account (`npx cdk bootstrap aws://<account>/us-east-1`
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue