How it works
The explanation, with examples you can run.
The order, simplified
- Is there a matching
"Effect": "Deny"in any applicable policy? Then deny. Nothing can override it. - Is the account in an organization with SCPs or resource control policies? The action must be allowed by them; if not, deny.
- Does the principal have a permissions boundary, or the session a session policy? The action must be inside it; if not, deny.
- Does an identity-based or resource-based policy allow it? Then allow.
- Otherwise, deny (the implicit deny from the start).
Guard rails never grant anything; they only cut the maximum. An SCP that allows s3:* does not let anyone use S3 until an identity or resource policy also does. Real IAM has more detail (cross-account requests need an allow on both sides, a few resource policies that name a principal directly behave differently with boundaries, and conditions can make any statement not apply), but this order explains nearly every surprise.
Try it
A toy evaluator for single-account requests with an SCP. Wildcards (*) match any characters, as in IAM. Change the policies and see which step decides.
Press Run to see what your code prints, in order.
Runs in this browser, in an isolated frame with no access to this page. console.log, info, warn and error are shown; code runs as a classic script, so use an async function for await.
Run with Node, it prints:
s3:GetObject reports/2026/q1.csv -> ALLOWs3:DeleteObject reports/2025/q4.csv -> DENY (explicit deny)s3:ListBucket reports/x -> DENY (not allowed by the SCP)s3:GetObject payroll/jan.csv -> DENY (implicit: nothing allowed it)The third request is the one people trip over: the role's own policy says s3:*, but the organization's SCP never allowed listing.
Debugging a denial
- The error message often says which policy type denied the request ("with an explicit deny in a service control policy", "because no identity-based policy allows").
- The IAM policy simulator and
aws iam simulate-principal-policyevaluate a request without making it. - CloudTrail records the denied call, the principal and the error code.
- Check the resource side too: bucket policies, KMS key policies and queue policies are frequent sources of explicit denies, and a KMS key policy must allow use of the key even when the bucket allows the read.
Check yourself
3 questions. Get them all right to finish this topic.
0 of 3 right so far. Get all three to finish this topic.