A service role that may create roles can create one more powerful than itself. A permissions boundary, a managed policy set as a role's ceiling, stops that. The deployer may create booknest-* roles only if they carry booknest-boundary, created by the same template, which allows item reads and writes and log writes:
- Sid: RolesOnlyInsideTheBoundary
Effect: Allow
Action: [iam:CreateRole, iam:PutRolePolicy, iam:AttachRolePolicy,
iam:DetachRolePolicy, iam:DeleteRolePolicy]
Resource: !Sub arn:aws:iam::${AWS::AccountId}:role/booknest-*
Condition:
StringEquals: {iam:PermissionsBoundary: !Ref Boundary}
- Sid: ManageBookNestRoles
Effect: Allow
Action: [iam:GetRole, iam:GetRolePolicy, iam:DeleteRole, iam:PassRole]
Resource: !Sub arn:aws:iam::${AWS::AccountId}:role/booknest-*infra/reader-role.yaml creates a catalog-reading Lambda 24 role with that PermissionsBoundary:
aws cloudformation deploy --stack-name booknest-deployer --template-file deployer-role.yaml \
--capabilities CAPABILITY_NAMED_IAM
ROLE=$(aws iam get-role --role-name booknest-cfn-deployer --query Role.Arn --output text)
aws cloudformation deploy --stack-name booknest-reader --template-file reader-role.yaml \
--capabilities CAPABILITY_NAMED_IAM --role-arn "$ROLE"
aws iam get-role --role-name booknest-catalog-reader --output text \
--query 'Role.PermissionsBoundary.PermissionsBoundaryArn'
aws cloudformation describe-stacks --stack-name booknest-reader --query 'Stacks[0].RoleARN'... Successfully created/updated stack - booknest-deployer ... Successfully created/updated stack - booknest-reader arn:aws:iam::000000000000:policy/booknest-boundary null
The boundary is attached, and RoleARN is null: LocalStack 63,725 records no service role even when it exists. On AWS 24 (not run here), dropping PermissionsBoundary makes iam:CreateRole fail with AccessDenied. Also deny iam:DeleteRolePermissionsBoundary, or the boundary can be removed afterwards.