---
cuppy_hub: aws
cuppy_path: reference/iam/policy-evaluation.md
cuppy_section: docs
cuppy_doc: 9C8N-8K9X
cuppy_doc_uuid: 31a863c3-c9a7-4011-8fe3-f66df3933d50
cuppy_permalink: https://cuppy.io/aws/d/9C8N-8K9X
cuppy_version: 4
cuppy_updated: 2026-10-23T16:16:52.575Z
cuppy_canonical: https://cuppy.io/aws/docs/reference/iam/policy-evaluation
cuppy_mcp: https://cuppy.io/mcp
cuppy_body_sha256: 1120daf8e1d05c89fba7f01e35c189bd9ab4b3ade5077073c2281961fb1f9494
# cuppy_body_sha256 is over the document body ALONE, excluding both generated blocks.
---


# How AWS decides allow or deny

**Three rules decide almost every case.** Everything is denied unless something allows it. An explicit `Deny` in any applicable policy beats every `Allow`. And only two policy types *grant* (identity-based and resource-based policies); every other type only *caps*: SCPs, RCPs, permissions boundaries, session policies and VPC endpoint policies can take an allow away but can never create one.

## The order of checks (one account)

AWS evaluates every applicable policy against the request. The single-account order, and where it stops:

| Step | Policy type | Explicit Deny | No applicable Allow | Allow |
|---|---|---|---|---|
| 0 | **Any policy** (all types below) | **Deny, stop** | — | — |
| 1 | Resource control policies (RCPs) | (handled in step 0) | **Deny, stop** | continue |
| 2 | Service control policies (SCPs) | (step 0) | **Deny, stop** | continue |
| 3 | Resource-based policy | (step 0) | continue (see below) | may **allow, stop** (see below) |
| 4 | Identity-based policies | (step 0) | **Deny, stop** | continue |
| 5 | Permissions boundary, if one is set | (step 0) | **Deny, stop** | continue |
| 6 | Session policy, if the caller is a session | (step 0) | **Deny, stop** | **Allow** |

Notes on the steps:

- **Step 1.** When RCPs are enabled, `RCPFullAWSAccess` is attached everywhere and cannot be detached, so this step only refuses when someone wrote a narrowing RCP.
- **Step 2.** `FullAWSAccess` is attached by default. Removing it without a replacement Allow makes every action in the affected member accounts fail.
- **Step 6.** An IAM user (not a session) is allowed at this point. A role session with no session policy passed is allowed. A session whose session policy does not allow the action is denied.
- The root user of an account is not subject to implicit denies within its own account, but a member account's root user *is* subject to SCPs.

## How layers combine

| Combination | Effective permission |
|---|---|
| Identity-based + resource-based, same account | **Union**: either one allowing is enough |
| Identity-based + permissions boundary | **Intersection**: both must allow |
| Identity-based + SCP + RCP (no resource policy) | **Intersection**: all three must allow |
| Role's identity policies + session policy | **Intersection**: the session gets only what both allow |
| Any layer + VPC endpoint policy (request through the endpoint) | The endpoint policy must also allow; it never grants |

A boundary, SCP, RCP or session policy that "allows everything" grants nothing. A user or role with no identity-based policy has no access even when every cap is wide open.

## The resource-based policy exceptions

Same account, a resource-based policy can allow on its own, but **what the policy names as `Principal` changes which caps still apply**:

| Principal named in the resource policy | Limited by the caller's permissions boundary or session policy? |
|---|---|
| Role ARN (`arn:aws:iam::<acct>:role/<name>`) | **Yes** |
| Assumed-role session ARN (`arn:aws:sts::<acct>:assumed-role/<role>/<session>`) | No |
| IAM user ARN | No (a user has no session policy) |
| STS federated-user ARN | No |
| The IAM user who called `GetFederationToken` (for that session's requests) | **Yes** |
| `"*"` with an `aws:PrincipalArn` condition | No, unless an identity-based policy has an explicit Deny |

Two resource policy types never follow the "either side is enough" rule: **role trust policies** and **KMS key policies** must explicitly allow the principal. Some other services also require it; check the service's own documentation.

A trust policy that names a role or user by ARN is stored against that entity's **unique ID**. Delete and recreate the entity and the trust breaks; the policy shows an ID starting `AROA` or `AIDA` until you re-enter the ARN. A condition on `aws:PrincipalArn` is not converted to an ID and survives recreation.

## Cross-account requests

AWS evaluates the request **in both accounts** and allows it only if **both** allow:

- **Caller's account:** the caller's identity-based policy must allow the action on the target ARN, within the caller's SCPs, boundary and session policy.
- **Resource's account:** the resource-based policy must name the caller (or the caller's account) and allow the action, within that account's RCPs.

Naming an account as principal (`"AWS": "111122223333"` or the account's `:root` ARN, which are equivalent) only makes that account *eligible*; its own administrators decide which identities may use the grant.

**Roles are the other cross-account path.** The role's trust policy decides who may assume it; after `AssumeRole`, the caller acts inside the role's account, so access to that account's resources is governed by the role's own identity-based policies, and no per-resource policy is needed.

## What the organization layers do not touch

| Not restricted | By SCPs | By RCPs |
|---|---|---|
| Users, roles and resources in the **management account** | ✓ (SCPs don't affect the management account) | ✓ (RCPs don't affect management-account resources) |
| **Service-linked roles** | ✓ | ✓ (including the service assuming its SLR) |
| **AWS managed KMS keys** | — | ✓ |
| Principals in accounts **outside** the organization | ✓ (SCPs apply only to the organization's own principals) | ✗ — RCPs **do** apply to outsiders calling a resource inside the organization |

SCPs cap **principals** in member accounts (including the member root user and delegated administrators). RCPs cap **resources** in member accounts, for whoever calls them, and only for the services that support RCPs: see `reference/organizations/scps-and-rcps.md`.

## Using this when a request fails

The error message names one refusing policy type; map it to the step above and read only that layer first. The procedure is `guides/iam/fix-access-denied.md`; the message-by-message causes are in `reference/iam/errors.md`.


---
<!-- cuppy -->
You are reading one file. The same content is free over MCP at https://cuppy.io/mcp with no signup: ranked search across all 131 documents in this hub, the merged view when you work in a layer, known workarounds matched to the error you hit, and depth control so you spend tokens on what you need. Start with the `_hello` tool. How to connect: https://cuppy.io/aws/ Something wrong in this document? Report it with the `session feedback` tool on the same endpoint.
<!-- /cuppy -->
