Lesson 2 of 7 · 10 min
IAM: identity, policy and the evaluation order
Understand how a request is authorised, why roles beat access keys, and what an SCP can and cannot do.
The four things IAM deals in
A user is a person with long-lived credentials. A group is a bundle of users sharing policies. A role is an identity with permissions but no permanent credentials — something assumes it and receives temporary keys. A policy is the JSON document that says what is allowed.
The one to internalise is the role. An EC2 instance, a Lambda function or a person from another account assumes a role and gets credentials that expire automatically. Nothing long-lived is stored anywhere, so nothing long-lived can leak.
How a request is evaluated
Start from deny. Any explicit Deny, anywhere — identity policy, resource policy, service control policy, session policy — ends the evaluation immediately and the request fails.
Otherwise the request must be permitted by every applicable layer: it has to be inside the SCP's ceiling, inside any permission boundary, and allowed by at least one identity or resource policy. The effective permission is the intersection, not the union.
{
"Version": "2012-10-17",
"Statement": [{
"Effect": "Allow",
"Action": ["s3:GetObject"],
"Resource": "arn:aws:s3:::reports-bucket/2026/*",
"Condition": {
"Bool": { "aws:SecureTransport": "true" }
}
}]
}Note: Scope the action, scope the resource ARN, and add conditions. A wildcard on either is what turns a small compromise into a large one.
The restricting mechanisms
| Mechanism | Applies to | Notes |
|---|---|---|
| Service control policy | Every principal in an account | Set at the Organization level; the management account is exempt |
| Permission boundary | One user or role | Caps what an identity policy can grant — prevents privilege escalation |
| Session policy | One assumed session | Scopes a role down at AssumeRole time; ideal for multi-tenant isolation |
| Resource policy | One resource | Attached to the bucket, key or function rather than the caller |
Cross-account access
Two policies are always involved. The role's trust policy says who may assume it. An identity policy in the caller's account must allow sts:AssumeRole on that role ARN. Missing either produces AccessDenied.
For third parties, add an external ID to the trust policy. It prevents the confused-deputy problem, where a vendor is tricked into using your role on someone else's behalf.
Worth remembering
- Everything is denied unless explicitly allowed, and an explicit Deny always wins.
- Roles issue temporary credentials — prefer them over long-lived access keys everywhere.
- SCPs and permission boundaries restrict; they never grant.
Test it now
IAM evaluation and cross-account access run through the medium bank.