Free AWS IAM Policy Explainer
Paste an IAM, bucket or trust policy to see what each statement allows or denies, with risky grants flagged by severity.
What is an AWS IAM Policy Explainer?
AWS IAM policies are JSON documents that decide who can do what in an AWS account. They’re easy to get subtly wrong. This explainer reads a policy statement by statement, says in plain language what each one allows or denies, and flags the patterns that grant more than intended.
It follows the IAM JSON policy element reference for Version, Statement, Sid, Effect, Principal, Action, Resource, their Not forms, and Condition. Structural mistakes IAM would reject are errors. Valid but risky grants, such as administrator access, iam:PassRole on every role or a public principal, are findings ranked by severity.
Key Features
Each Statement in Plain Language
Actions, resources, principals and conditions are listed per statement, with wildcards spelled out as every action or every resource.
Risky Grants Flagged
Administrator access, PassRole on any role, service-wide wildcards, Allow with NotAction and anonymous principals are ranked high, medium or low.
Syntax Errors IAM Would Reject
A wrong Effect, a malformed action, a missing Resource, duplicate Sids and unknown condition operators are reported with the statement number.
Identity, Resource and Trust Policies
Policies with a Principal, such as bucket and role trust policies, are read without requiring Resource, as IAM reads them.
Your Account Details Stay Local
Account IDs, bucket names and role ARNs are parsed in the browser and never uploaded.
Perfect for everyone
- Cloud engineers writing IAM policies
- Security teams reviewing access
- Developers reading a policy someone else wrote
- Anyone preparing for an AWS audit
How to Use the AWS IAM Policy Explainer
Paste the policy, read each statement, and fix what’s flagged.
Copy the Policy JSON
Take it from the IAM console’s JSON tab, a Terraform or CloudFormation file, or aws iam get-policy-version output. Paste just the policy document.
Read Each Statement
Explain lists every statement with its effect, actions, resources, principals and conditions in plain language.
Review the Findings
High findings grant far more than most roles need. Medium and low findings are worth tightening. Switch to Findings only for a quick review.
Tighten and Re-Check
Replace wildcards with specific actions and ARNs, then paste the policy again. Confirm with IAM Access Analyzer before deploying.
IAM Policies, Explained
We ran each policy below through the explainer in the chip’s mode and copied the result exactly, errors included. Work out what each policy grants first, then reveal the explanation.
“{"Version":"2012-10-17","Statement":[{"Sid":"ReadLogs","Effect":"Allow","Action":["s3:GetObject","s3:ListBucket"],"Resource":["arn:aws:s3:::acme-logs","arn:aws:s3:::acme-logs/*"]}]}”
“{"Version":"2012-10-17","Statement":{"Effect":"Allow","Action":"*","Resource":"*"}}”
“{"Version":"2012-10-17","Statement":[{"Effect":"Allow","Action":["ec2:RunInstances","iam:PassRole"],"Resource":"*"}]}”
“{"Version":"2012-10-17","Statement":[{"Effect":"Allow","Principal":{"Service":"lambda.amazonaws.com"},"Action":"sts:AssumeRole"}]}”
“{"Version":"2012-10-17","Statement":[{"Effect":"Allow","Principal":"*","Action":"s3:GetObject","Resource":"arn:aws:s3:::acme-site/*"}]}”
“{"Version":"2012-10-17","Statement":[{"Effect":"Allow","NotAction":"iam:*","Resource":"*"}]}”
“{"Version":"2012-10-17","Statement":[{"Sid":"Read","Effect":"Allow","Action":"s3:GetObject","Resource":"arn:aws:s3:::acme/*"},{"Sid":"NoDeleteWithoutMfa","Effect":"Deny","Action":"s3:DeleteObject","Resource":"*","Condition":{"BoolIfExists":{"aws:MultiFactorAuthPresent":"false"}}}]}”
“{"Version":"2012-10-17","Statement":[{"Effect":"Permit","Action":"s3:GetObject","Resource":"*"}]}”
“{"Version":"2012-10-17","Statement":[{"Effect":"Allow","Action":"s3:GetObject"}]}”
“{"Version":"2012-10-17","Statement":[{"Effect":"Allow","Action":"s3 GetObject","Resource":"*"}]}”
The Elements of an IAM Policy
Every IAM policy is built from the same handful of elements. These ten explain how AWS reads them.
Version
Always 2012-10-17 for new policies. The older 2008-10-17 language, used when Version is missing, doesn’t support policy variables.
“Which Version should a new policy use?”
Statement
One statement object or a list of them. Each statement is evaluated on its own, then the results are combined.
“Can Statement be a single object?”
Effect
Exactly Allow or Deny. Anything not explicitly allowed is denied by default.
“What happens to an action no statement mentions?”
Action and NotAction
Actions are written service:Action, such as s3:GetObject, with * wildcards. NotAction means every action except those listed.
“Does s3:Get* match s3:GetObjectAcl?”
Resource and NotResource
The ARNs the statement applies to. A bucket and its objects are different resources, so listing objects needs both forms.
“Does arn:aws:s3:::logs cover objects inside the bucket?”
Principal
Who the statement applies to, used only in resource-based and trust policies. Identity policies apply to whoever they’re attached to.
“Can an identity policy have a Principal?”
Condition
Extra tests on request context, such as source IP, MFA, tags or time. All conditions in a statement must be true.
“Do multiple condition keys in one statement combine with AND or OR?”
Sid
An optional label for a statement. Within a policy, each Sid must be unique.
“Can two statements share a Sid?”
Explicit Deny Wins
A Deny that matches overrides every Allow, in any attached policy, SCP or boundary. It’s the strongest statement there is.
“Allow s3:* and Deny s3:DeleteObject. Can the role delete?”
IfExists and Set Operators
Adding IfExists to an operator makes it pass when the key is absent. ForAnyValue and ForAllValues compare multi-valued keys such as tag lists.
“What does BoolIfExists do when the key is missing?”
Kinds of IAM Policy
The same JSON shape is used in several places, and where it’s attached changes how it’s read.
Identity-Based Policies
Attached to users, groups or roles, and say what that identity can do. They have no Principal and must name Resources.
Resource-Based Policies
Attached to resources such as S3 buckets, SQS queues and KMS keys, and say who can use them. They need a Principal.
Trust Policies
Attached to a role, and say who can assume it with sts:AssumeRole. They name a Principal and usually have no Resource.
Permissions Boundaries
Set the maximum an identity policy can grant. An action must be allowed by both the boundary and the identity policy.
Service Control Policies
Set guardrails across an AWS Organizations account. They never grant access on their own, only limit it.
Session Policies
Passed when assuming a role to narrow that session further. The effective access is the overlap with the role’s own policies.
IAM Policy Mistakes
These are the most common ways a policy grants more, or less, than intended.
Wildcard Actions on Wildcard Resources
Action * on Resource * is full admin, and s3:* on * covers every bucket in the account. Start from the actions the code really calls.
PassRole on Every Role
iam:PassRole on * lets someone hand an admin role to a service they control. Scope it to the specific role ARNs.
Forgetting Object ARNs
arn:aws:s3:::bucket covers the bucket, not its objects. GetObject needs arn:aws:s3:::bucket/* to work.
Allow With NotAction
It grants every action except those listed, including new actions AWS adds later. Prefer listing allowed actions.
Public Principals Without Conditions
Principal * makes a resource public. Pair it with conditions such as aws:SourceVpce or aws:PrincipalOrgID unless it truly is public.
Typos in Condition Operators
StringEqual instead of StringEquals makes the whole policy invalid. Copy operator names from the documentation.
Missing Version
Without Version 2012-10-17, policy variables such as aws:username are read literally. Always include it.
Assuming Allow Overrides Deny
An explicit Deny anywhere wins, including in SCPs and permission boundaries. Check those when an allowed action still fails.
Least-Privilege Patterns
Ways to grant exactly what a workload needs, and nothing more.
Start From Access Activity
IAM Access Advisor and CloudTrail show which actions a role actually used. Generate a policy from that history rather than guessing.
Scope Resources to ARNs
Name the exact bucket, table or queue ARNs, with wildcards only for object paths such as bucket/uploads/*.
Use Conditions to Narrow Access
aws:SourceVpce, aws:PrincipalOrgID and aws:ResourceTag keys limit where and on what an action is allowed.
Separate Read and Write
Give most services a read-only role, and a separate role for the few that write. Breaches of the reader can’t change data.
Guard PassRole With Specific ARNs
When a deploy role must pass roles, list them, and add iam:PassedToService to restrict which service can receive them.
Prefer Roles Over Users
Roles give temporary credentials that expire, while user access keys last until someone rotates them.
When to Explain a Policy
Whenever a policy is about to be attached, or nobody remembers what one does.
Reviewing a Pull Request
Paste the policy from a Terraform or CloudFormation change to see what it really grants before approving.
Understanding an Inherited Role
Read each statement of a role nobody documented, and spot what can be removed.
Debugging Access Denied
Check whether the action and resource are actually covered, or whether a Deny or condition blocks them.
Preparing for a Security Audit
Find administrator grants, public principals and PassRole wildcards before an auditor does.
Writing a Least-Privilege Policy
Draft the policy, read it back in plain language, and confirm nothing broader slipped in.
Checking a Bucket Policy
Confirm that only the intended accounts, roles or CloudFront distribution can read a bucket.
Learning IAM
Change one element at a time and watch the explanation and findings respond.