By default, CloudFormation 24 acts with a temporary session made from your credentials, so you need dynamodb:CreateTable yourself to deploy a table. With --role-arn, it assumes a service role, trusted by cloudformation.amazonaws.com, and creates resources with the role's permissions. Callers then need only CloudFormation permissions and iam:PassRole on that role, restricted to CloudFormation:
{
"Version": "2012-10-17",
"Statement": [
{"Sid": "BookNestStacks", "Effect": "Allow", "Action": "cloudformation:*",
"Resource": "arn:aws:cloudformation:*:*:stack/booknest-*/*"},
{"Sid": "PassOnlyTheDeployerRole", "Effect": "Allow", "Action": "iam:PassRole",
"Resource": "arn:aws:iam::*:role/booknest-cfn-deployer",
"Condition": {"StringEquals": {"iam:PassedToService": "cloudformation.amazonaws.com"}}}
]
}AWS 24 warns that a stack keeps its service role for every later operation, that the role cannot be removed, and that anyone allowed to update the stack uses it even without iam:PassRole, so a generous role is an escalation path. LocalStack 4.13.1 63,725 checks none of this: a deploy with --role-arn naming a role that does not exist reached CREATE_COMPLETE, where AWS fails at once because the role cannot be assumed.