UprootSecurityUprootSecurity

Phase 2 · AWS IAM · Lesson 2 of 4

AWS IAM Policy Evaluation Logic

Article

·

15 min

·

+8 pts

When a principal makes an API call in AWS, the IAM engine evaluates every applicable policy to decide whether the request is allowed or denied. This evaluation is not intuitive. Policies interact in ways that surprise even experienced engineers, and a misunderstanding of the evaluation order is one of the most common root causes of both security gaps and access issues in AWS environments.

This lesson walks through the exact evaluation logic. If the previous lesson gave you the building blocks, this lesson explains the machine that assembles them.

The evaluation flowchart

Every AWS IAM request passes through the same evaluation pipeline. The order matters — each step can terminate the evaluation early.

┌──────────────────────────┐
│   API Request Received   │
│   (Principal + Action    │
│    + Resource)           │
└───────────┬──────────────┘
            │
            ▼
┌──────────────────────────┐      ┌──────────┐
│  1. Explicit Deny?       │─Yes─►│  DENIED  │
│  Any policy (any type)   │      └──────────┘
│  explicitly denies this  │
│  action?                 │
└───────────┬──────────────┘
            │ No
            ▼
┌──────────────────────────┐      ┌──────────┐
│  2. SCP Check            │─No──►│  DENIED  │
│  (If account is in an    │      └──────────┘
│  Organization)           │
│  Does the SCP allow it?  │
└───────────┬──────────────┘
            │ Yes / N/A
            ▼
┌──────────────────────────┐      ┌──────────┐
│  3. Resource-based Policy│─Yes─►│ ALLOWED  │
│  Does the resource       │      │ (same    │
│  policy grant access?    │      │ account) │
└───────────┬──────────────┘      └──────────┘
            │ No grant
            ▼
┌──────────────────────────┐      ┌──────────┐
│  4. Permission Boundary  │─No──►│  DENIED  │
│  (If one is set)         │      └──────────┘
│  Does the boundary       │
│  allow this action?      │
└───────────┬──────────────┘
            │ Yes / N/A
            ▼
┌──────────────────────────┐      ┌──────────┐
│  5. Session Policy       │─No──►│  DENIED  │
│  (If role was assumed    │      └──────────┘
│  with a session policy)  │
│  Does it allow?          │
└───────────┬──────────────┘
            │ Yes / N/A
            ▼
┌──────────────────────────┐      ┌──────────┐
│  6. Identity-based Policy│─No──►│  DENIED  │
│  Does the user/role      │      │(implicit)│
│  policy grant access?    │      └──────────┘
└───────────┬──────────────┘
            │ Yes
            ▼
       ┌──────────┐
       │ ALLOWED  │
       └──────────┘

AWS IAM policy evaluation order: explicit deny always wins, then each policy layer narrows what is allowed

Let us walk through each step.

Step 1: Explicit deny — game over

Before anything else, AWS checks every applicable policy — identity-based, resource-based, SCPs, permission boundaries, session policies — for an explicit deny that matches the requested action and resource. If any policy anywhere contains an explicit "Effect": "Deny" that matches, the request is denied. Full stop. No other policy can override an explicit deny.

This is the single most important rule in AWS IAM: explicit deny always wins. It does not matter if the principal has AdministratorAccess. It does not matter if the resource-based policy says allow. An explicit deny in any policy terminates evaluation.

This is why deny policies are so powerful for compliance. An SCP that denies cloudtrail:StopLogging cannot be overridden by any IAM policy in any account in the organization.

Step 2: SCP check

If the account is a member of an AWS Organization, the SCP attached to the account's OU (and all parent OUs up to the root) must allow the action. SCPs are evaluated as an intersection — the action must be allowed by every SCP in the chain from the root OU down to the account.

Remember: SCPs restrict but never grant. An SCP that allows s3:* does not give anyone S3 access. It means S3 actions are not blocked at the organization level. The principal still needs an identity-based policy that explicitly grants the action.

If the SCP does not include the requested action in its allow list (and the SCP uses an allow-list model), the request is denied even if the principal has full administrator permissions within the account.

Step 3: Resource-based policy

If the resource being accessed has a resource-based policy (like an S3 bucket policy or an SQS queue policy) that explicitly grants access to the requesting principal, the request can be allowed at this step — within the same account. This is notable because it means a resource-based policy can grant access even if the principal has no identity-based policy allowing the action.

For cross-account requests, the behavior differs. Both the resource-based policy in the target account and the identity-based policy in the source account must allow the action (unless the resource policy grants access to the entire source account rather than a specific principal).

Step 4: Permission boundary

If the principal has a permission boundary set, the requested action must be allowed by the boundary. A permission boundary defines the maximum permissions that identity-based policies can grant. If the boundary does not include the action, the request is denied regardless of what the identity-based policy says.

Permission boundaries only affect identity-based policy evaluation. They do not restrict access granted by resource-based policies.

Step 5: Session policy

If the principal assumed a role using AssumeRole and passed a session policy, the action must be allowed by both the session policy and the role's identity-based policies. The session policy acts as a further restriction on the role's permissions for that specific session.

Session policies are used when you want to grant a role with broad permissions but scope down what a specific caller can do with it. They are less common but important in multi-tenant architectures.

Step 6: Identity-based policy

Finally, if no explicit deny was found, the SCP allows, the permission boundary allows, and no session policy restricts, AWS checks the principal's identity-based policies (managed policies and inline policies attached to the user, group, or role). If an identity-based policy grants the action, the request is allowed. If not, the request is denied by default.

This final default denial is called the implicit deny. AWS denies everything by default. You must explicitly allow every action you want a principal to perform.

The golden rule

Default deny, explicit deny always wins, everything else is an intersection of what all applicable policies allow. If you remember nothing else from this lesson, remember this: effective permissions are not what any single policy says — they are the intersection of what every applicable policy layer permits, minus anything any layer explicitly denies.

Concrete examples

Abstract rules become clear with concrete scenarios.

Example 1: SCP blocks override identity-based allow

A developer's IAM role in Account B has AmazonS3FullAccess attached. However, Account B is in an OU with an SCP that only allows ec2:*, iam:*, and sts:* — S3 is not in the SCP's allow list.

Result: DENIED. The SCP does not allow S3 actions, so the request is blocked at step 2 regardless of the role's identity-based policy. The developer's S3 full access policy is effectively meaningless in this account.

Example 2: Resource-based policy grants access without identity-based policy

An IAM user in Account A has no S3 permissions at all — zero identity-based policies. But an S3 bucket in Account A has a bucket policy that explicitly grants s3:GetObject to that user's ARN.

Result: ALLOWED (within the same account). The resource-based policy grants access at step 3. For same-account access, a resource-based policy that names the principal can grant access even without a corresponding identity-based policy.

Example 3: Permission boundary limits administrator access

A role has AdministratorAccess attached (all actions on all resources). But the role also has a permission boundary that only allows s3:* and dynamodb:*.

Result: Only S3 and DynamoDB actions are allowed. The permission boundary at step 4 limits the effective permissions to the intersection of the boundary and the identity-based policy. AdministratorAccess grants ec2:RunInstances, but the boundary does not include EC2 actions, so EC2 requests are denied.

Example 4: Explicit deny overrides everything

A role has AdministratorAccess. The account has no SCPs. No permission boundary. But the role has an additional inline policy with an explicit deny on iam:CreateUser.

Result: iam:CreateUser is DENIED. Even though AdministratorAccess allows all actions, the explicit deny in the inline policy is caught at step 1 and terminates evaluation. The admin can do everything except create IAM users.

Quick check

An IAM role has a managed policy allowing s3:PutObject on all buckets. The role has a permission boundary that allows only s3:GetObject and s3:ListBucket. The account has no SCPs. What happens when the role tries to put an object in S3?

Quick check

Account 222222222222 is in an OU with an SCP that allows all actions (FullAWSAccess). A user in Account 111111111111 tries to access an S3 bucket in Account 222222222222. The bucket policy grants s3:GetObject to the user's ARN. The user has no S3 permissions in their own account's identity-based policies. Is the request allowed?

Why this matters for GRC

Understanding policy evaluation logic is not academic for GRC engineers. It directly determines how you assess whether controls are effective:

  • Can a developer bypass an SCP? No — SCPs are evaluated before identity-based policies. This is why SCPs are your strongest compliance evidence.
  • Is AdministratorAccess really unlimited? Not if permission boundaries or SCPs are in place. The effective permissions depend on all applicable layers.
  • Can a resource owner grant access that circumvents identity controls? Within the same account, a resource-based policy can grant access independently. This means S3 bucket policies, KMS key policies, and SQS queue policies need their own review — they are a separate access path.
  • Does an explicit deny in a preventive control guarantee the action is blocked? Yes. Explicit deny in any policy cannot be overridden. This is the foundation of preventive controls in AWS.

When you write control narratives, you can reference the specific evaluation step that enforces the control. "CloudTrail deletion is prevented by an SCP attached to the root OU, which is evaluated at step 2 of the IAM evaluation pipeline before any identity-based policy is checked." That level of specificity is what separates a strong control narrative from a vague one.

AWS IAM Policy Evaluation Logic — UprootSecurity Bootcamp