Identity, Permission, Trust and Resource Policies
Four kinds of policy appear in a typical design, and confusing them is the usual reason an access decision is not what was expected.
Identity-based policies
Section titled “Identity-based policies”Attached to IAM users, groups or roles. They define what those identities may do across AWS services.
{ "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Action": [ "ec2:StartInstances", "ec2:StopInstances" ], "Resource": "*", "Condition": { "StringEquals": { "aws:ResourceTag/Environment": "Production" } } }, { "Effect": "Allow", "Action": [ "ec2:DescribeInstances" ], "Resource": "*" } ]}Attached to a user or group, this permits starting and stopping instances tagged
Environment=Production, and describing all of them. ec2:DescribeInstances is in a separate
statement because it does not support resource-level permissions or the resource tag
condition — a detail that catches people out when a single-statement version silently
denies everything.
Role policies
Section titled “Role policies”Every IAM role carries two kinds of policy, doing different jobs.
Trust policy — exactly one
Section titled “Trust policy — exactly one”
- Defines who may assume the role
- Sometimes called the trust relationship policy
- Uses the
sts:AssumeRoleaction (orsts:AssumeRoleWithSAML/sts:AssumeRoleWithWebIdentityfor federation) - Must include a
Principalelement
{ "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Principal": { "Service": "lambda.amazonaws.com" }, "Action": "sts:AssumeRole" } ]}Permission policies — one or more
Section titled “Permission policies — one or more”- Define what the role may do
- List allowed or denied actions and resources
- No
Principalelement; the principal is the role itself - Several can be attached to one role, and they combine
{ "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Action": [ "s3:GetObject", "s3:PutObject" ], "Resource": "arn:aws:s3:::my-bucket/*" } ]}The short version: the trust policy answers who may use this role, the permission policy answers what this role may do. Both are required. A role with no trust policy cannot be created; a role with no permission policy can be assumed but can do nothing.
Resource-based policies
Section titled “Resource-based policies”Attached to a resource — an S3 bucket, an SQS queue, an SNS topic, a KMS key, a Lambda
function — rather than to an identity. A resource-based policy must declare a Principal
saying who may access the resource.
{ "Version": "2012-10-17", "Statement": [ { "Sid": "AllowCrossAccountAccess", "Effect": "Allow", "Principal": { "AWS": "arn:aws:iam::123456789012:role/CrossAccountRole" }, "Action": [ "s3:GetObject", "s3:PutObject" ], "Resource": "arn:aws:s3:::my-bucket/*" } ]}A role’s trust policy is itself a resource-based policy — the resource being the role.
How they combine
Section titled “How they combine”A realistic arrangement uses several at once:
- A developer has an identity-based policy permitting them to assume particular roles.
- Those roles have permission policies defining which services and resources they reach.
- Some of the target resources have resource-based policies that allow access from those roles, particularly where the resource is in another account.
The request succeeds only where the identity-based policy allows it, no explicit deny applies anywhere, and — for a cross-account call — the resource’s own policy accepts the caller. See IAM policy types and evaluation for the full evaluation logic.