All Tools View Categories About Contact Privacy

IAM Policy Simulator (logic-based)

Paste a policy, build a test request, and see the Allow/Deny decision — a local, logic-based approximation.

Not the real AWS IAM Policy Simulator. This runs entirely in your browser and does not call AWS. It does not model SCPs, permission boundaries, or resource-based-policy interactions, and evaluates only StringEquals, StringNotEquals, StringLike, and Bool conditions against the context you provide below.
Decision:
Reminder: local, logic-based simulation only — not AWS's real evaluation engine. No SCPs, permission boundaries, or resource-based-policy interactions modeled. Only StringEquals/StringNotEquals/StringLike/Bool conditions are evaluated.
StatementSidEffectCondition

About IAM Policy Simulator (logic-based)

Reading a multi-statement IAM policy and mentally tracing through what a specific action + resource + condition-context combination would actually resolve to is slow and error-prone, especially once Deny statements and Condition blocks are involved. IAM Policy Simulator (logic-based) lets you paste a policy document, describe one request — an action, a resource ARN, and any condition-key context values you want to supply — and see the resulting decision, which statements actually applied, and exactly what was uncertain, all computed locally with the same core evaluation logic AWS itself follows.

The evaluation walks every statement in the document and, for each one, checks whether its Action/NotAction matches the requested action (case-insensitive glob matching, since AWS treats action names case-insensitively) and whether its Resource/NotResource matches the requested resource ARN (case-sensitive glob matching, since ARNs are case-sensitive). A statement that matches both is then checked against its Condition block, if it has one, using the context key/value pairs you supplied through the "Add context key" rows. Statements matching on Action and Resource but whose condition definitively evaluates to false are excluded; among what remains, an explicit Deny always wins over any Allow — the single most important rule in real AWS policy evaluation, and the one this tool implements faithfully. If nothing applies at all, the result is Implicit Deny, matching AWS's default-deny posture.

The condition evaluation is deliberately narrow and says so plainly: only four operators are actually evaluated — StringEquals, StringNotEquals, StringLike, and Bool. Any other operator (IpAddress, DateGreaterThan, ArnLike, NumericLessThan, and the rest of AWS's much larger operator set) is treated the same way as a condition key you never supplied a value for: as unevaluatable. Crucially, an unevaluatable condition does not silently resolve to true or false — the statement is conservatively marked as possibly applicable, its condition result comes back indeterminate rather than a guess, and a caveat is added to the results explicitly naming which key or operator could not be evaluated. This matters because a policy simulator that silently assumes an unknown condition is satisfied (or unsatisfied) gives you false confidence; this one tells you precisely where its answer is uncertain and why, so you can supply the missing context and get a definitive read.

What this tool does not do deserves equal emphasis, prominently, not buried in a footnote: it is not the real AWS IAM Policy Simulator and does not call any AWS API. It evaluates exactly one policy document against one request in isolation — it has no model of Service Control Policies, permission boundaries, resource-based policy combination (an S3 bucket policy plus an IAM identity policy plus a VPC endpoint policy, evaluated together), session policies, or cross-account trust relationships, all of which materially affect what actually happens in a real AWS account. It also has no catalog of real AWS actions or services — an Action or Resource string is matched purely as a wildcard pattern, with no validation that the action or service name is real. Treat this as a fast, local, first-pass sanity check on a single policy document's own internal logic — a way to catch "wait, does my Deny statement actually cover this case?" while writing or reviewing a policy — not as a substitute for AWS's actual evaluation engine or for testing against a real account before granting production access.

The request-builder UI mirrors this scope: one action field, one resource field, and a dynamic list of context key/value rows you add one at a time, since this tool has no real caller identity or request metadata to draw from — you supply exactly the condition-relevant facts you want evaluated, and nothing more is assumed. The matched-statements table shows every statement whose Action and Resource matched, its effect, and whether its condition was satisfied, not satisfied, or indeterminate, so the reasoning behind the final decision is fully visible rather than a single opaque verdict.

Features

  • Paste one policy document and build one test request — action, resource, and dynamic context rows.
  • Explicit Deny always wins over Allow, matching real AWS evaluation order.
  • Implicit Deny when no statement applies.
  • Evaluates exactly 4 condition operators — StringEquals, StringNotEquals, StringLike, Bool — honestly, with everything else marked unevaluatable.
  • Missing context produces a caveat, never a silent guess.
  • Matched-statements table showing effect and condition-evaluation status per statement.
  • Persistent scope notice in the results area, not just in the docs — this is a local approximation, not the real AWS simulator.
  • Dynamic "Add context key" rows for building request context.
  • Sample policy and sample request demonstrating Allow, Deny-wins, and a missing-context caveat.
  • One-click clear.
  • 100% client-side — nothing is uploaded.

How to Use

  1. Paste your policy JSON, or click the sample.
  2. Fill in the request — an action like s3:GetObject and a resource ARN.
  3. Add context key/value rows for any condition keys your policy's Condition blocks reference (e.g. aws:MultiFactorAuthPresent = true).
  4. Click Simulate.
  5. Read the decision badge — Allow, Deny, or Implicit Deny.
  6. Check the matched-statements table to see which statements applied and why.
  7. Read any caveats — they name exactly which context was missing.
  8. Add the missing context and re-run for a definitive answer.

Examples

Example 1 — plain Allow. A single-statement policy allowing s3:GetObject on arn:aws:s3:::my-bucket/*, tested against action s3:GetObject and resource arn:aws:s3:::my-bucket/report.pdf with no context needed, decides Allow.

Example 2 — explicit Deny wins. A policy with an Allow * statement and a separate Deny s3:DeleteObject statement, tested against action s3:DeleteObject, decides Deny — the matched-statements table shows both statements matched, and the Deny took precedence.

Example 3 — missing-context caveat. A policy that Allows an action only when aws:MultiFactorAuthPresent is true, tested with no context rows filled in, decides Allow (conservatively, since the condition could not be disproven) but shows a caveat naming aws:MultiFactorAuthPresent as the unsupplied key — add a context row with that key set to false and the decision flips to Implicit Deny.

Example 4 — Implicit Deny. Testing an action no statement's Action field matches at all (e.g. iam:CreateUser against an S3-only policy) decides Implicit Deny with an empty matched-statements table.

Example 5 — unevaluatable operator. A Condition using IpAddress (not one of the 4 evaluated operators) always produces a caveat regardless of context supplied, since this tool cannot evaluate that operator at all.

Benefits

  • Traces multi-statement Allow/Deny interaction instantly instead of by hand.
  • Never silently guesses on an unevaluatable condition — always surfaces a caveat.
  • Shows its work — every matched statement and its condition status, not just a verdict.
  • Honest, persistent scope notice — never presented as equivalent to AWS's real simulator.
  • Fast local iteration while writing or reviewing a policy.
  • Private — policy and request context never leave your browser.

Frequently Asked Questions

Is this the real AWS IAM Policy Simulator?
No. This is a small, local, logic-based approximation that runs entirely in your browser. It does not call the AWS IAM Policy Simulator API or any AWS service. It reimplements the core evaluation idea — match Action, match Resource, evaluate Condition, explicit Deny beats Allow, no match means implicit deny — but it is not AWS's actual policy evaluation engine, and it will not catch everything the real simulator (or real AWS) would.
What does it NOT model that the real AWS evaluation engine does?
Several important things: Service Control Policies (SCPs) in AWS Organizations, permission boundaries, resource-based policy interactions (like S3 bucket policies combined with IAM identity policies), session policies, VPC endpoint policies, and cross-account trust evaluation. This tool evaluates exactly one policy document against one request — nothing about how multiple policies combine.
Which Condition operators does it actually evaluate?
Exactly four: <code>StringEquals</code>, <code>StringNotEquals</code>, <code>StringLike</code>, and <code>Bool</code>. Any other operator in a Condition block — <code>IpAddress</code>, <code>DateGreaterThan</code>, <code>ArnLike</code>, <code>NumericLessThan</code>, and so on — is treated the same as a missing context key: unevaluatable, producing a caveat rather than a silent true or false.
What happens when a condition key is not in the context I provided?
The statement is not silently dropped or silently assumed to match. Its condition result comes back indeterminate (neither true nor false), the statement is conservatively treated as possibly applicable, and a caveat is added to the results explicitly naming which condition key(s) were missing — so you know exactly which piece of context to add if you want a definitive answer instead of a "maybe".
How is the final decision computed once statements are matched?
Among statements whose Action and Resource match the request, any whose condition evaluated to definitively false are dropped. Among what remains, if any Deny statement applies, the decision is Deny — explicit Deny always wins, exactly matching real AWS behavior on this one point. If no Deny applies but at least one Allow does, the decision is Allow. If nothing applies at all, the decision is Implicit Deny, matching AWS's default-deny behavior for identity-based policies.
Does it check Action names or Resource ARNs against real AWS services?
No. Action and Resource matching is pure glob-style wildcard string matching (<code>*</code> and <code>?</code>) — Action matching is case-insensitive (matching how AWS treats action names), Resource matching is case-sensitive (matching how AWS treats ARNs). It never checks whether <code>s3:GetObject</code> is a real S3 action or whether the resource ARN is well-formed for the service.
What is the context I provide used for?
It is a flat set of key/value pairs representing request attributes AWS would normally supply automatically at evaluation time — like the caller's source IP, whether MFA was present, a request tag, or a principal tag. You build this yourself with the context rows, since this tool has no real request to inspect.
What if my policy has a Principal but I am simulating an identity-based request?
Resource matching falls back to treating a Principal-only statement (one with no Resource/NotResource) as resource-based and applicable regardless of the requested resource string — this mirrors how bucket-policy-style statements can omit Resource. It is a simplification, not a full identity-vs-resource-policy evaluation model.
Can this replace testing against a real AWS account?
No — treat it as a fast local sanity check while writing or reviewing a single policy document, not as a substitute for AWS's own Policy Simulator, IAM Access Analyzer, or an actual test call against a real AWS account before granting production access.
Is my policy JSON or the request I build sent anywhere?
No — the entire simulation, including the context rows you build, runs locally in your browser.