09.06 · AWS

AWS IAM

Users, groups, roles, policies — and the policy evaluation algorithm that decides whether your request goes through.

AWS IAM is the access-control system at the heart of every AWS account. It controls who can do what to which resources, under what conditions. The vocabulary — user, group, role, policy — will look familiar from any RBAC system; the wrinkles are where AWS-specific behavior lives, and where most misconfigurations happen.

This page covers the IAM primitives, the policy evaluation algorithm step by step, and the layers above per-account IAM (AWS Organizations, Service Control Policies, permission boundaries) that constrain what an account-level admin can do.

The four primitives

Identity

IAM User

A long-lived identity for a person or external service. Has a username, optional console password, optional access keys (long-lived programmatic credentials).

Modern best practice: avoid IAM users for humans entirely — use SSO via IAM Identity Center (federated) instead. IAM users are still valid for services that can't federate; rotate their keys often or use IAM Roles Anywhere with X.509 certs.

Container

IAM Group

A collection of users. Permissions attached to the group apply to every user in it. Not a security boundary, not an identity itself — just an administrative convenience for managing user permissions.

Limit: a user can be in up to 10 groups; an account can have 300 groups. Mostly a footnote — almost all serious permissioning has moved to roles + SSO.

Identity

IAM Role

An identity that can be assumed. No long-lived credentials — instead, a trust policy defines who can assume the role, and a permissions policy defines what they can do once assumed. STS mints temporary credentials at assumption time.

This is the workhorse of modern AWS IAM. EC2 instances use instance profile roles. Lambda functions execute as roles. Federated users assume roles. Cross-account access uses roles.

Document

IAM Policy

A JSON document that says what is allowed or denied. Identity policies attach to users/groups/roles. Resource policies attach to resources (S3 buckets, KMS keys, Lambda functions).

Every API call is evaluated against every relevant policy. The structure: Effect (Allow/Deny), Action (which API), Resource (which thing), Condition (when this applies).

A policy, annotated

Here's a real-shaped IAM policy that grants read access to a specific S3 prefix, only when the request comes from a known VPC endpoint. The structure is the same for every policy in AWS:

{ "Version": "2012-10-17", // always 2012-10-17 (the policy language version) "Statement": [ { "Sid": "AllowReadsFromVpcEndpoint", // optional, human-readable "Effect": "Allow", // Allow or Deny "Action": [ // which API calls "s3:GetObject", "s3:ListBucket" ], "Resource": [ // which resources (ARNs) "arn:aws:s3:::acme-prod-reports", "arn:aws:s3:::acme-prod-reports/2026/*" ], "Condition": { // when this applies "StringEquals": { "aws:SourceVpce": "vpce-0abc1234" } } } ] }

Read this top-to-bottom: allow these S3 actions, on these resources, only when the request originated from this VPC endpoint. Change Allow to Deny and the same statement becomes a guard rather than a grant — and Deny wins ties, which matters for the evaluation algorithm below.

Policy evaluation — the algorithm

When you make an API call, AWS evaluates every policy that could apply: identity policies on the caller, resource policies on the target, SCPs from AWS Organizations, permission boundaries, session policies. The algorithm to decide Allow or Deny is fixed and worth memorizing:

IAM policy evaluation logic
1
Default is implicit Deny. If nothing says Allow, the answer is Deny. New roles get no permissions; resources are private unless a policy opens them.
2
Any explicit Deny — anywhere — wins. If any applicable policy says "Effect": "Deny" for this action, the answer is Deny. End of evaluation. This is why Deny statements are the strongest tool in IAM — they cannot be overridden by an Allow elsewhere.
3
Service Control Policies (SCPs) act as a filter. If the account is in an AWS Organizations OU with SCPs, the request must pass them. An SCP doesn't grant permissions; it can only deny. Used by central security teams to set "no one in this account can disable CloudTrail," even if their IAM admin says otherwise.
4
Permission boundaries act as a ceiling. If a role has a permission boundary attached, the effective permissions are the intersection of the role's policies and the boundary. Useful for letting devs create their own roles without granting them more power than the parent permission set.
5
Identity policies plus resource policies are unioned. Within the boundary, the request is allowed if at least one identity policy or one resource policy explicitly allows it. (For cross-account requests, both an identity policy on the caller's side AND a resource policy on the resource's side must allow it.)
6
Session policies further restrict assumed-role sessions. When AssumeRole is called with an inline policy, the session's effective permissions are the intersection of the role's policies, the boundary, AND the session policy. Used by tools like AWS Identity Center to issue narrow sessions.
Mnemonic that works. Deny beats Allow. Default is Deny. Boundaries and SCPs only subtract, never add. If a request seems mysteriously denied, walk the list in this order — the answer is almost always there.

AWS Organizations — the layer above

A single AWS account is rarely the right unit for a real organization. AWS Organizations lets you arrange many accounts into a tree (organization → organizational units → accounts), apply central policies, and consolidate billing. The structure looks like this:

AWS Organizations hierarchy
Management account
The root of the organization. Owns billing for all member accounts. Houses AWS Organizations, IAM Identity Center, and audit log destinations. Tightly locked down — nothing else runs here.
Organizational Unit (OU)
A folder of accounts. SCPs attach to OUs so a policy can apply to every account in a subtree at once. Common shapes: Security, Sandbox, Workloads/Prod, Workloads/NonProd.
Member account
Where workloads actually run. A typical company has dozens to hundreds — one per workload, per environment (prod/staging/dev), or per team. Each is a separate IAM scope; cross-account access requires explicit role assumption.
SCPs (Service Control Policies)
JSON documents attached to the org, OUs, or specific accounts. They filter what IAM in those accounts can do. Example: an SCP that denies iam:CreateUser across the whole org forces everyone to use SSO instead.
IAM Identity Center (formerly SSO)
Federates your IdP (Okta, Entra, Google, native directory) and grants permission sets across multiple member accounts. The recommended way for humans to get into AWS in 2026.

Permission boundaries — delegation without giving away the farm

A common need: let your developers create roles for their workloads without letting them escalate by creating a role with admin privileges. The answer is permission boundaries.

A permission boundary is a policy you attach to a role (or a user) that defines the maximum permissions that role can ever have. Anyone who creates new roles under this delegation must also attach the boundary — and even if they write a permissive role policy, the effective permissions are the intersection. The boundary caps what they can grant.

{ "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Action": [ "s3:*", "dynamodb:*", "logs:*" ], "Resource": "*" }, { "Effect": "Deny", // the boundary's teeth "Action": [ "iam:*", "organizations:*", "kms:DeleteKey" ], "Resource": "*" } ] }

A developer with this boundary can create a role with any combination of S3, DynamoDB, and CloudWatch Logs permissions, but they cannot grant iam:* or touch the org — even if they write that into a role policy, the boundary's Deny wins.

SCPs vs Boundaries vs Policies — which does what

These three things look similar but operate at different layers. Quick disambiguation:

The point

AWS IAM is a layered system where every decision filters through Deny-wins evaluation. Memorize the algorithm in section 4: default Deny, any explicit Deny wins, SCP filters, boundary caps, identity-or-resource policy union. That single mental model explains every "why can't I do this?" you'll ever ask in AWS.

For real environments, the modern shape is: humans federate via Identity Center, services run as roles (never users), SCPs at the OU level enforce non-negotiables, permission boundaries delegate role creation safely, and policies should always be the smallest grant that gets the job done.

References

Formatted in APA 7. Alphabetized by first author's last name.

  1. Amazon Web Services. (n.d.-a). AWS Identity and Access Management user guide. https://docs.aws.amazon.com/IAM/latest/UserGuide/
  2. Amazon Web Services. (n.d.-b). AWS Organizations user guide. https://docs.aws.amazon.com/organizations/latest/userguide/
  3. Amazon Web Services. (n.d.-c). Policy evaluation logic. AWS IAM User Guide. https://docs.aws.amazon.com/IAM/latest/UserGuide/reference_policies_evaluation-logic.html
  4. Amazon Web Services. (n.d.-d). Service control policies (SCPs). AWS Organizations User Guide. https://docs.aws.amazon.com/organizations/latest/userguide/orgs_manage_policies_scps.html
  5. Amazon Web Services. (n.d.-e). Permissions boundaries for IAM entities. AWS IAM User Guide. https://docs.aws.amazon.com/IAM/latest/UserGuide/access_policies_boundaries.html