DevTools Hub

Search tools

Search for a developer tool

IAM Policy Basics

Part of the AWS Toolkit

Every AWS request — a user opening a console page, a Lambda function reading from a queue, a CI pipeline deploying a stack — gets checked against a set of policies before it's allowed to happen. A policy is a JSON document that says what's permitted; understanding the handful of pieces it's built from explains most of what looks confusing about IAM from the outside.

The shape of a policy document

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "AllowS3Read",
      "Effect": "Allow",
      "Action": ["s3:GetObject", "s3:ListBucket"],
      "Resource": ["arn:aws:s3:::my-bucket", "arn:aws:s3:::my-bucket/*"]
    }
  ]
}
  • Version — the policy language version, not a revision number. 2012-10-17 is the current one and should be in every new policy; an older 2008-10-17 policy silently can't use newer features like policy variables.
  • Statement — an array of individual permission rules. Most policies have one, but there's no limit beyond the document's overall size.
  • Sid — an optional label for a statement, useful only for humans reading the policy later.
  • Effect"Allow" or "Deny", exactly. Nothing else is valid here.
  • Action — one or more service:ActionName strings, like s3:GetObject, that the statement applies to.
  • Resource — one or more ARNs the statement applies to, or "*" for everything. See What Is an ARN? if the format there isn't familiar yet.

Action has a NotAction counterpart, and Resource has NotResource — each pair is mutually exclusive within one statement, and a Condition block can narrow any of this further (a specific IP range, a required tag, a time window). The full mechanics of conditions are covered in IAM Policy Viewer's own reference.

Identity-based vs. resource-based

A policy attaches to one of two kinds of thing. An identity-based policy attaches to a user, group, or role — its permissions belong to whoever the identity is. A resource-based policy attaches directly to a resource — an S3 bucket policy, an SNS topic policy, an IAM role's trust policy — and it's the only place you'll see a Principal element, since a resource-based policy has to say who is being granted access, where an identity-based policy's principal is just implicitly whoever it's attached to.

Managed vs. inline

Separately from where a policy attaches, there's how it's stored. AWS managed policies are pre-written and maintained by AWS itself — you can attach them but not edit them, and AWS occasionally updates one, which then applies to everything it's attached to. Customer managed policies are the same idea, but you write and own them, reusable across many identities in your account. Inline policies are embedded directly in one specific user, group, or role — not reusable, and deleted automatically if that identity is deleted. AWS generally recommends managed policies for anything you'll reuse, keeping inline policies for the rare case where a permission genuinely belongs to exactly one identity and should never accidentally end up attached anywhere else.

How AWS decides allow or deny

Per AWS's own evaluation logic reference, the rule set boils down to three lines:

  • Everything is denied by default.
  • An explicit Allow somewhere is required to permit a request.
  • An explicit Deny anywhere always overrides an explicit Allow.

That's the core of it, and it's enough to reason about a single identity-based policy correctly. Once permissions boundaries, service control policies, or resource-based policies from another account enter the picture, the real evaluation order gets considerably more layered — worth knowing that layer exists, but outside the scope of getting one policy document right.

None of this says what a "correct" set of permissions actually is for a given identity — that's the separate question Least Privilege Explained covers.

Try it yourself

Paste a policy into IAM Policy Viewer for a statement-by-statement plain-English breakdown, or build one from scratch with IAM Policy Generator. Both run entirely in your browser.

Related tools