docs(iam): clarify boundary rollback recovery

This commit is contained in:
Adam Moussa 2026-08-03 14:36:17 -04:00
parent 8d85b2c396
commit 5d68ab3507
No known key found for this signature in database

View file

@ -338,30 +338,17 @@ Resources:
StringEquals:
"iam:PermissionsBoundary": !Sub "arn:aws:iam::${AWS::AccountId}:policy/seahaven-lambda-execution-boundary"
# Boundary management — SET the boundary only. DELETE is NOT
# granted: for a delete, the iam:PermissionsBoundary condition key
# reflects the boundary CURRENTLY attached to the target role, so
# a StringEquals condition on the boundary ARN MATCHES exactly the
# roles the gate protects. Granting delete under that condition
# lets this role create a boundary-gated role with an inline *:*
# policy, strip the boundary, and pass the now-unbounded role to
# Lambda — defeating the primary escalation control. Verified live
# against the mgmt copy 2026-07-27 (simulate-principal-policy:
# iam:DeleteRolePermissionsBoundary = allowed).
# Boundary management is SET-only. Granting delete would let this
# role create a boundary-gated role, strip the boundary, then pass an
# unconstrained role to Lambda. SAM creation and teardown need only
# PutRolePermissionsBoundary and DeleteRole.
#
# OPERATIONAL CONSEQUENCE — read before debugging a stuck stack.
# SAM does not need the delete for the common paths: it SETS the
# boundary on roles it creates, and stack teardown calls DeleteRole.
# But there IS one path that now fails by design: updating an
# existing AWS::IAM::Role to REMOVE its PermissionsBoundary property
# makes CloudFormation call DeleteRolePermissionsBoundary, which is
# denied. If rollback also fails, the stack reaches
# UPDATE_ROLLBACK_FAILED and needs out-of-band admin recovery (remove
# the boundary directly, skip the resource during rollback, or
# replace the role by renaming its logical id). A successful rollback
# reaches UPDATE_ROLLBACK_COMPLETE and can accept a corrective update.
# Removing the boundary from a SAM function is a security regression
# anyway, so failing loudly here is the intent.
# Removing a boundary therefore fails by design. A failed rollback
# reaches UPDATE_ROLLBACK_FAILED and needs admin recovery by skipping
# or replacing the role. A successful rollback reaches the stable
# UPDATE_ROLLBACK_COMPLETE state and can accept a corrective update.
# Removing a SAM function boundary is a security regression, so
# failing loudly is intentional.
- Sid: IAMPutPermissionsBoundary
Effect: Allow
Action: