Cloud Computing Tutorial · Identity and Security · Lesson 7 of 24

How Policies Are Evaluated

Explicit deny, allow and implicit deny: how AWS evaluates IAM policies, conditions, and organisation guardrails.

Create a free account to save this page, take notes and track your progress. Sign in

The evaluation logic

For each request, AWS collects every policy that applies (identity policies, resource policies, permission boundaries, organisation service control policies) and decides:

  1. An explicit deny anywhere wins: the request is denied.
  2. Otherwise, if some policy allows it (and every guardrail layer permits it), it's allowed.
  3. Otherwise it's denied by default (implicit deny).
Explicit deny beats allow; nothing matching means denyTry it yourself
import fnmatch

def matches(stmt, action, resource):
    return any(fnmatch.fnmatch(action, a) for a in stmt["Action"]) and fnmatch.fnmatch(resource, stmt["Resource"])

def evaluate(policies, action, resource):
    stmts = [s for p in policies for s in p if matches(s, action, resource)]
    if any(s["Effect"] == "Deny" for s in stmts):
        return "DENY (explicit)"
    if any(s["Effect"] == "Allow" for s in stmts):
        return "ALLOW"
    return "DENY (implicit)"

identity = [{"Effect": "Allow", "Action": ["s3:*"], "Resource": "arn:aws:s3:::acme-*"}]
guardrail = [{"Effect": "Deny", "Action": ["s3:DeleteBucket"], "Resource": "*"}]

for action, resource in [("s3:GetObject", "arn:aws:s3:::acme-logs/a.txt"),
                         ("s3:DeleteBucket", "arn:aws:s3:::acme-logs"),
                         ("ec2:RunInstances", "arn:aws:ec2:eu-west-1:1:instance/*")]:
    print(f"{action:18} -> {evaluate([identity, guardrail], action, resource)}")

Output

s3:GetObject       -> ALLOW
s3:DeleteBucket    -> DENY (explicit)
ec2:RunInstances   -> DENY (implicit)

Conditions

Statements can have conditions: only from the company network, only with MFA, only for resources tagged with the caller's team, only in approved regions.

{
  "Effect": "Deny",
  "Action": "*",
  "Resource": "*",
  "Condition": { "StringNotEquals": { "aws:RequestedRegion": ["eu-west-1", "eu-central-1"] } }
}

As a service control policy this denies every action outside two EU regions for the whole organisation, whatever the account's own policies say. Azure Policy and Google Cloud organisation policies provide similar guardrails.

Test yourself

An identity policy allows s3:* and an organisation SCP denies s3:DeleteBucket. Can the user delete a bucket?

  1. Yes, the identity policy allows it
  2. No, the explicit deny wins
  3. Only with MFA
  4. Only for empty buckets
Show answer

Answer: No, the explicit deny wins

An explicit deny in any applicable policy overrides every allow.

Was this page helpful?