Lab 02 — IAM policy evaluation¶
In one sentence
Watch each layer of IAM policy evaluation — permissions boundary, session policy, ABAC conditions, Access Analyzer — allow or deny a real request, and learn to read from the error message which layer said no.
The idea¶
Request ──► 1. Explicit Deny anywhere? (SCP · RCP · resource · identity · boundary · session) ──► DENY
2. Organizations SCP / RCP allow? no ──► DENY
3. Resource-based policy allows? (same account: can grant access by itself)
4. Identity-based policy allows? no ──► DENY
5. Permissions boundary allows? no ──► DENY
6. Session policy allows? no ──► DENY
──► ALLOW
Effective permissions = identity ∩ boundary ∩ session ∩ SCP (and any Deny wins)
The delegated-admin trick from Part A — the dev may create roles only if they carry the boundary:
"Condition": {
"StringEquals": { "iam:PermissionsBoundary": "arn:aws:iam::111111111111:policy/sec2-boundary" }
}
What happened in the lab run¶
Part A — delegated admin with a permissions boundary (as sec2-dev-role)¶
| Action | Result |
|---|---|
CreateRole without the boundary |
❌ "no identity-based policy allows" — the Allow's condition didn't match → implicit deny |
CreateRole with sec2-boundary + inline policy granting EC2/SSM on * |
✅ |
DeleteRolePermissionsBoundary on that role |
❌ "explicit deny in an identity-based policy" |
Part B — effective permissions = identity ∩ boundary (as sec2-app-reader)¶
| # | Call | Identity | Boundary | Result |
|---|---|---|---|---|
| 1 | s3 list-buckets |
✅ | ✅ | ✅ |
| 2 | ec2 describe-instances |
✅ | ❌ | ❌ "no permissions boundary allows" |
| 3 | ssm get-parameter /sec2/alpha/… |
✅ | ✅ /sec2/* |
✅ |
| 4 | ssm get-parameter /sec2-outside/flag |
✅ | ❌ | ❌ "no permissions boundary allows" |
Part C — session policy (dev role assumed with a policy allowing only s3:ListAllMyBuckets)¶
| Call | Role | Session | Result |
|---|---|---|---|
s3 list-buckets |
✅ | ✅ | ✅ |
iam list-roles |
✅ | ❌ | ❌ "no session policy allows" |
something the role doesn't have (e.g. sns:ListTopics) |
❌ | ✅ | ❌ — a session policy can only narrow |
Part D — ABAC with session tags (aws:PrincipalTag/project = aws:ResourceTag/project)¶
| Session | Parameter | Result |
|---|---|---|
tagged project=alpha |
/sec2/alpha/db-password |
✅ |
tagged project=alpha |
/sec2/beta/db-password |
❌ |
| no tag | /sec2/alpha/db-password |
❌ |
caller picks project=beta itself |
— | ⚠️ nothing stops it: whoever has sts:TagSession chooses the tag values |
Part E — IAM Access Analyzer¶
| Test | Result |
|---|---|
validate-policy on the bad policy |
✅ ERROR INVALID_ACTION (s3:GetObjects) + SECURITY_WARNING PASS_ROLE_WITH_STAR_IN_RESOURCE |
Third bug: s3:GetObject on the bucket ARN instead of bucket/* |
⚠️ not reported — valid syntax, but it never matches an object |
SQS queue with Principal: "*" |
✅ ACTIVE finding, isPublic: true |
Queue restricted to the org (aws:PrincipalOrgID) |
⚠️ finding still ACTIVE, no longer public — an ACCOUNT analyzer treats other org accounts as external |
| Policy removed | ✅ finding RESOLVED |
Key lessons¶
- Effective permissions are an intersection. An Allow in an SCP, boundary or session policy grants nothing — the identity (or resource) policy must also allow it, and every ceiling on the path must too.
- The error message names the layer: "no identity-based policy allows", "no permissions boundary allows", "no session policy allows", "explicit deny in …". Read it before you change anything.
- Delegating role creation safely needs two pieces: an Allow conditioned on
iam:PermissionsBoundary, and an explicit Deny on removing the boundary or editing the boundary policy. - ABAC scales (no policy change per project) but is only as safe as the tags: tags must come from the IdP or be constrained, and principals must not be able to retag themselves or resources.
- Access Analyzer's zone of trust is its type, not your intent. Syntax validation passing ≠ the policy works.
Exam notes¶
- Same account: a resource-based policy can grant access by itself (no identity policy needed) — but an explicit Deny, SCP, or boundary still applies. Cross-account needs both sides.
- Boundaries never grant; they set a ceiling for users/roles. Identity ∩ boundary.
- Privilege escalation paths to watch in answer choices: create a role without a boundary, remove the
boundary (
DeleteRolePermissionsBoundary/PutRolePermissionsBoundary), edit the boundary policy (CreatePolicyVersion/SetDefaultPolicyVersion), attach an admin managed policy,iam:PassRoleon*to EC2/Lambda. - Session policies are accepted by
AssumeRole,AssumeRoleWithSAML,AssumeRoleWithWebIdentityandGetFederationToken(--policy/--policy-arns). Typical use: a broker hands out narrowed creds. - ABAC keys:
aws:PrincipalTag/<key>=aws:ResourceTag/<key>; enforce tags at creation withaws:RequestTag/<key>+aws:TagKeys. Passing session tags needssts:TagSessionin the trust policy; constrain values withaws:RequestTagthere. Transitive session tags survive role chaining. - Deny
iam:TagRole/ssm:AddTagsToResource(etc.) to principals, or they grant themselves access. - "Validate policies in CI/CD before deployment" → Access Analyzer
ValidatePolicy, or custom policy checksCheckNoNewAccess/CheckNoPublicAccess(small charge per call). - Analyzer types:
ACCOUNT= anything outside this account is external;ORGANIZATION= only outside the org is external, and it can only be created in the management account or a delegated admin. Intended sharing → archive the finding or create an archive rule. - When a CLI profile is set, it wins over temp-credential environment variables.
Review questions¶
Question 1
A user's identity policy allows s3:*. Their boundary allows only s3:GetObject. The SCP allows everything. Can they call s3:PutObject?
Show answer
No. Effective permissions are the intersection of identity policy, boundary and SCP. The boundary
doesn't include s3:PutObject, so the request fails with "no permissions boundary allows". The SCP
allowing everything only means the SCP isn't the layer blocking it — an SCP never grants anything.
Question 2
A developer has iam:CreateRole and iam:AttachRolePolicy on *. Name two ways they could escalate privileges, and the controls that stop each one.
Show answer
(a) Create a role that trusts themselves and attach AdministratorAccess, then assume it. Stop it by
allowing CreateRole only with the iam:PermissionsBoundary condition, and restricting which policies may
be attached (iam:PolicyARN condition on AttachRolePolicy). (b) Attach an admin policy to a role they
can already use or pass — e.g. an existing role, or a new role passed to EC2/Lambda with iam:PassRole,
then run code as it. Stop it with the same boundary requirement plus scoping iam:PassRole to specific role
ARNs (and iam:PassedToService). In both cases add an explicit Deny on removing the boundary
(DeleteRolePermissionsBoundary) and on editing the boundary policy (CreatePolicyVersion,
SetDefaultPolicyVersion), or they just lift the ceiling.
Question 3
Can a session policy grant access the role's identity policy doesn't have?
Show answer
No. The session's permissions are the intersection of the role's identity policy and the session
policy, so it can only narrow. In the lab, adding sns:ListTopics in the session policy still failed.
(A resource-based policy that names the session ARN directly is the one edge case where access isn't
limited by the session policy.)
Question 4
An SCP denies ec2:TerminateInstances. An admin in the management account terminates an instance. Does it succeed?
Show answer
Yes. SCPs never apply to principals in the management account, even when attached to the root. That's why AWS recommends keeping workloads out of the management account and protecting it tightly. (SCPs also don't restrict service-linked roles.)
Question 5
Your company adds a new project every week. Which access approach avoids writing a new IAM policy each time, and which two condition keys does it rely on?
Show answer
ABAC (attribute-based access control). One policy compares aws:PrincipalTag/project with
aws:ResourceTag/project; a new project just needs tagged principals and resources. Pair it with
aws:RequestTag / aws:TagKeys to force correct tags at creation, and source principal tags from the IdP
so users can't pick their own.
Question 6
Security wants alerts whenever a resource gets shared with any account outside the company. Which tool and analyzer type, and from which account?
Show answer
IAM Access Analyzer with an ORGANIZATION analyzer (zone of trust = the org), created in a
delegated administrator account for Access Analyzer (or the management account, but delegated admin is
the best practice). Findings flow to EventBridge / Security Hub for alerting. An ACCOUNT analyzer would
also flag sharing between your own accounts — noise for this requirement.
My first attempt: 2 / 6
Weak spots: effective permissions are an intersection (an SCP allowing an action isn't enough) ·
privilege escalation via CreateRole / AttachRolePolicy / PassRole · ABAC condition keys · Access
Analyzer organization zone of trust.