The evaluation chain

Lesson 1 of 5 in Policy Evaluation.

This is the page the rest of the domain rests on. Almost every authorization question on the exam — "why was this denied", "will this be allowed", "which policy do I change" — is answered by walking the same chain, and the engineers who fail Domain 4 are usually the ones reasoning from one policy at a time.

Two rules, in order.

Rule 1: an explicit Deny anywhere wins, immediately. A matching "Effect": "Deny" in any applicable policy — identity policy, resource policy, permissions boundary, session policy, SCP, RCP, or VPC endpoint policy — ends the evaluation. Not outvoted, not weighed: ended. It does not matter how many Allows exist, or which account the Deny lives in.

Rule 2: with no explicit deny, the request must survive every layer that applies, and an explicit Allow must exist somewhere that grants it. The default is implicit deny, so silence is refusal. Then:

  • Organization policies (SCPs, and RCPs on the resource side) must permit it. They never grant.
  • The permissions boundary on the principal, if there is one, must permit it. It never grants.
  • The session policy, if one was passed, must permit it. It never grants.
  • And an Allow must come from the identity-based policy — or, for a service that supports one, from the resource-based policy.

Read the two rules together and the mental model falls out: one layer grants; all the others can only veto. Finding the veto is the whole job.

How a single request is decided

  1. Request arrives; context assembled (principal, action, resource, conditions)
  2. Does any applicable policy explicitly Deny?

    Identity policy, resource policy, permissions boundary, session policy, SCP, RCP, VPC endpoint policy. Any one of them is enough.

  3. DENIED — explicit deny
  4. Do the organization policies allow it?

    SCPs cap principals in member accounts; RCPs cap access to resources. Neither grants. The management account is unaffected by both.

  5. DENIED — the organization ceiling excludes it
  6. If a permissions boundary applies, does it allow it?

    Effective permissions are identity policy ∩ boundary. A boundary alone grants nothing.

  7. DENIED — outside the boundary
  8. If a session policy was passed, does it allow it?

    Intersection again. Invisible in IAM after the fact — check the code that called AssumeRole.

  9. DENIED — outside the session policy
  10. Is there an Allow in the identity policy — or, for resource-policy services, in the resource policy?

    Same account: either can supply the Allow. Cross-account: the identity policy in the caller’s account AND the resource policy in the owner’s account must both allow.

  11. DENIED — implicit deny, nothing granted it
  12. ALLOWED

Four subtleties live inside those two rules, and each one is an exam question.

A capping policy that says nothing says no. This catches people because it inverts the usual intuition. An identity policy that omits an action is silent, and silence plus another Allow elsewhere can still work. But a permissions boundary or session policy that omits an action removes it, because the effective permission is an intersection. A principal with an AdministratorAccess identity policy and a boundary allowing only s3:* can do S3 and nothing else.

SCPs and boundaries never grant. Attach a boundary allowing s3:* to a role with no identity policy and the role can do nothing at all. "The SCP allows it" is never a complete explanation of why something worked.

Same account: either policy can supply the Allow. For services with a resource-based policy, a bucket policy naming a principal in the same account is sufficient on its own — no identity policy needed. This is the special case, and it stops being true the moment the request crosses an account boundary.

Cross-account: both accounts, independently. AWS runs two evaluations and allows the request only if both return Allow. An explicit deny in either account denies it.

Worked example 1 — denied by the boundary, even though the identity policy allows it

Role DevAdmin has AdministratorAccess attached. It also has a permissions boundary:

{
  "Version": "2012-10-17",
  "Statement": [{
    "Effect": "Allow",
    "Action": ["s3:*", "logs:*", "cloudwatch:*"],
    "Resource": "*"
  }]
}

The developer runs ec2:RunInstances. Denied.

The identity policy allows it. There is no Deny anywhere. But effective permissions are identity policy ∩ boundary, and ec2:RunInstances is absent from the boundary — so it is outside the intersection. This is the "my policy clearly says Allow" puzzle, and the answer is almost always a boundary or a session policy.

Worked example 2 — denied by an SCP the account administrator cannot see

An administrator in a member account has AdministratorAccess and tries to create an unencrypted EBS volume. An SCP on the OU reads:

{
  "Version": "2012-10-17",
  "Statement": [{
    "Effect": "Deny",
    "Action": "ec2:CreateVolume",
    "Resource": "*",
    "Condition": {
      "Bool": { "ec2:Encrypted": "false" }
    }
  }]
}

Denied — explicit deny, rule 1, end of evaluation. Nothing in the member account can override it, including the account's own root user. The error gives no hint that an SCP was responsible, which is why organization policy is the first thing to check when an administrator reports being denied.

Worked example 3 — allowed by a resource policy alone, in the same account

A Lambda execution role has an identity policy with logs:* only — nothing about S3. The bucket reports in the same account has:

{
  "Version": "2012-10-17",
  "Statement": [{
    "Effect": "Allow",
    "Principal": { "AWS": "arn:aws:iam::111122223333:role/report-writer" },
    "Action": "s3:PutObject",
    "Resource": "arn:aws:s3:::reports/*"
  }]
}

PutObject is allowed. Within one account, either the identity policy or the resource policy can supply the grant.

Now move the bucket to another account, keeping both policies identical. The same call is denied — the caller's identity policy must also allow s3:PutObject on that ARN. One account boundary, opposite outcome, same policies.

Worked example 4 — two Allows and a Deny

A role's identity policy allows s3:* on arn:aws:s3:::finance/*. A second attached policy reads:

{
  "Version": "2012-10-17",
  "Statement": [{
    "Effect": "Deny",
    "Action": "s3:DeleteObject",
    "Resource": "*",
    "Condition": {
      "BoolIfExists": { "aws:MultiFactorAuthPresent": "false" }
    }
  }]
}

A role session created without MFA calls DeleteObject. Denied — the explicit deny matches, and nothing outranks it. The same session can still GetObject and PutObject, because the Deny names one action. This is the shape of a well-written guardrail: narrow action, broad resource, explicit condition.

Key terms: Policy evaluation logic, Explicit deny, Implicit deny, Permissions boundary, Session policy, Resource-based policy

Interactive checkpoint quiz (2 questions) — open this page in a browser to take it.