Skip to content

IAM Policy Types and Evaluation

  1. Identity-based policies
    • Attached to IAM users, groups or roles
    • Define what actions the identity may perform, on which resources
    • AWS managed, customer managed, or inline
  2. Resource-based policies
    • Attached directly to a resource — an S3 bucket, an SQS queue, a KMS key, an IAM role’s trust policy
    • Define who may access the resource and what they may do
    • Always inline on the resource, and they must include a Principal element
  3. Permissions boundaries
    • Set the maximum permissions an identity can have
    • Grant nothing on their own — the effective permissions are the intersection of the boundary and the identity-based policy
    • Used to delegate administration safely: a developer may create roles, but not roles more powerful than the boundary allows
  4. Service control policies and resource control policies
  5. Session policies
    • Passed when a role is assumed, to narrow that particular session below the role’s own permissions
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "AllowObjectAccessFromOfficeRange",
"Effect": "Allow",
"Action": ["s3:GetObject", "s3:PutObject"],
"Resource": "arn:aws:s3:::example-bucket/*",
"Condition": {
"IpAddress": {
"aws:SourceIp": "203.0.113.0/24"
}
}
}
]
}
  • Allow grants the listed actions.
  • Deny refuses them.
  • An explicit Deny anywhere always wins, in any policy type.
  • Namespaced by service: s3:, ec2:, kms:
  • Wildcards are permitted: s3:* for every action in a service, s3:Get* for every Get action, s3:*Object for every action ending in Object
  • A wildcard in Action combined with a wildcard in Resource is the shape most likely to be flagged in a review, and usually the shape that should be narrowed
  • Identified by ARN: arn:partition:service:region:account-id:resource-type/resource-id
  • Wildcards may match several resources
  • The resource must be one the action actually applies to — s3:ListBucket acts on the bucket ARN, s3:GetObject on the object ARN, and mixing them is the most common reason a bucket policy silently does nothing

Common operators:

  • Strings: StringEquals, StringNotEquals, StringLike
  • Numbers: NumericEquals, NumericGreaterThan
  • Dates: DateEquals, DateGreaterThan, DateLessThan
  • Booleans: Boolaws:MultiFactorAuthPresent is the common one
  • Addresses: IpAddress, NotIpAddress
  • ARNs: ArnEquals, ArnLike

Condition keys come from AWS global context (aws:SourceIp, aws:RequestedRegion, aws:PrincipalOrgID, aws:PrincipalTag/*, aws:ResourceTag/*) and from the individual services.

For a request within a single account:

  1. Everything is denied by default — an implicit deny.
  2. An explicit allow in any applicable policy overrides the implicit deny.
  3. An explicit deny in any applicable policy overrides every allow.
  4. All applicable policies are evaluated together, not in sequence. Identity-based policies, resource-based policies, permissions boundaries, session policies, SCPs and RCPs all participate.

For a cross-account request, both accounts must allow it: the identity-based policy in the calling account, and the resource-based policy (or an assumed role’s trust and permission policies) in the account that owns the resource.

An EC2 instance reading and writing two buckets

Section titled “An EC2 instance reading and writing two buckets”

Attached to the role in the instance profile:

{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"s3:GetObject",
"s3:PutObject"
],
"Resource": [
"arn:aws:s3:::product-data/*",
"arn:aws:s3:::production-logs/*"
]
}
]
}

Attached to the bucket, in the account that owns it:

{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "AllowPartnerAccountRead",
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::123456789012:role/PartnerReadRole"
},
"Action": "s3:GetObject",
"Resource": "arn:aws:s3:::example-bucket/*"
}
]
}

Naming the specific role rather than the account root narrows the grant to the one identity that should hold it, instead of delegating to the other account’s administrators.

  1. Grant the least privilege that works: specific actions, specific resource ARNs.
  2. Attach policies to groups and roles, not to individual users.
  3. Use roles for applications and AWS services rather than access keys.
  4. Use conditions to add context — MFA present, request from a known network, resource carrying the right tag, request in an approved Region.
  5. Review policies against what is actually used. IAM service last accessed data and IAM Access Analyzer both turn this into a concrete list.
  6. Test with the IAM policy simulator before attaching, and check the results of a change against a real caller afterwards.