Architecture note4 lab guides4 lab guides
IAM · Identity and Access Management
Policy evaluation logic, roles over users, and privilege escalation hunting.
Outcome
- Create an IAM user, generate an access key, and explain why users are for humans not workloads
- Create a group, add a user, and explain why groups are not principals
- Create a role with a trust policy and explain the difference between trust policy (who) and permission policy (what)
- Explain why you cannot put a group ARN in a
Principalfield - Describe the difference between a role and a user in terms of credential lifetime
- Write a valid JSON policy with
Sid,Effect,Action,Resource, and explain each field - Create a customer-managed policy, attach it to both a group and a role, and check
AttachmentCount - Create a new policy version, set it as default, and roll back to the previous version
- Attach an inline policy to a role and explain why it won't show up in
list-attached-role-policies - Explain the 5-version limit and how to handle it in a CI pipeline
- Name the three policy types and the one legitimate use case for inline policies
- Write a valid JSON policy with
- Draw the IAM evaluation flowchart from memory (explicit deny → SCP → identity allow → resource allow → boundary)
- Use
iam:SimulatePrincipalPolicyto test a user's effective permissions against specific actions and resources - Use
iam:SimulateCustomPolicyto test a policy document without attaching it to anything - Add an explicit deny inline policy and confirm via simulate that it overrides a group-level allow
- Explain the difference between
implicitDenyandexplicitDenyin simulate output and in CloudTrail - Explain the same-account vs cross-account resource policy evaluation difference
- Write an IP restriction using
Deny+NotIpAddress+aws:SourceIp - Explain why
aws:SourceIpdoesn't apply to calls from AWS services and what to use instead - Write an MFA-required policy using
BoolIfExists: falseand explain whyBool: falseis insufficient - Write a region restriction using
StringNotEquals+aws:RequestedRegionwithNotActionfor global services - Write an ABAC policy using
aws:ResourceTagandaws:PrincipalTag - Explain the difference between
StringEqualsandStringLikewith wildcards - Explain why
Bool: falsesilently fails for absent condition keys and whatBoolIfExistsdoes instead
- Write an IP restriction using
- Call
sts:AssumeRole: export the three credential components, and verify the assumed identity - Explain what the
SessionTokenis and why all three components are required together - Pass a session policy to
assume-roleand verify it restricts permissions below the role's policy - Explain why a session policy can only restrict, never expand permissions
- Hit the
MaxSessionDurationlimit and update the role to allow a longer session - Explain the two-sided door: trust policy (who can knock) vs permission policy (what they can do inside)
- Call
- Describe the trust policy configuration for cross-account role assumption
- Explain when the trust policy should list an account root vs a specific role ARN
- Perform a two-hop role chain (caller → source role → target role) and verify identity at each step
- Explain the confused deputy problem with a concrete scenario
- Create a role with an External ID condition and confirm that missing/wrong IDs fail
- Explain where External ID should be stored and who generates it
- Create an EC2 service role and explain why an instance profile is required (Lambda/ECS don't need one)
- Name the correct service principal for EC2, Lambda, and ECS task roles
- Explain how credentials get into the execution environment for each service (IMDS, env vars, task endpoint)
- Register a GitHub OIDC provider and create a role with a repo-scoped trust condition
- Explain how to scope the GitHub trust to
mainbranch only vs all branches - Describe what
permissions: id-token: writedoes in a GitHub Actions workflow
- Attach a permission boundary to a role and confirm it blocks actions the identity policy allows
- Explain the intersection semantics: effective = identity policy ∩ boundary
- Explain why a broad boundary with an empty identity policy still results in
implicitDeny - Explain why
iam:PassRoleexists (privilege escalation prevention) with a concrete attack scenario - Write a scoped
iam:PassRolepolicy restricted by ARN pattern ANDiam:PassedToServicecondition - Explain why
iam:PassRoleonResource: *without a condition is a high-severity finding
- Draw the five-layer evaluation chain from memory in order
- Explain at which layer explicit Deny kills the request regardless of other layers
- Explain the difference between SCPs with
Allow(sets ceiling) vsDeny(hard block) - Explain which principal SCPs do NOT apply to (management account root user)
- Simulate SCP + identity policy interaction using
simulate-custom-policywith--permissions-boundary-policy-input-list - When given an
AccessDeniederror, describe the order in which you'd check each layer
- Create an Access Analyzer with type
ACCOUNTand explain what zone of trust means - Generate a finding by attaching a public S3 bucket policy and verify the finding JSON structure
- Explain the difference between
RESOLVED(policy changed) andARCHIVED(acknowledged) findings - Use
validate-policyto lint a policy document before deploying it - Pass the correct
--policy-typetovalidate-policyand explain why mixing them gives errors - Explain the difference between external access analysis and unused access analysis
- Create an Access Analyzer with type
- Call
generate-service-last-accessed-detailswithSERVICE_LEVELandACTION_LEVELgranularity - Identify which services show
lastAuthenticated: nulland explain what that means - Write a tightened policy using only the actions confirmed as used
- Validate the tightened policy with
validate-policyand verify withsimulate-custom-policy - Explain the difference between service-level and action-level last-accessed data
- Describe a quarterly process for applying this workflow to production roles
- Call
- Start a policy generation job with
generate-policyand poll for completion - Read the generated policy and identify at least two things that would need manual review
- List five gaps that policy generation cannot address (future paths, denied calls, cross-region, etc.)
- Validate a generated policy with
validate-policybefore using it
- Start a policy generation job with
- Generate and download the credential report using the CLI
- Parse it to find users with access keys older than 90 days
- Parse it to find users with console access but no MFA
- Check the root account's key and MFA status and explain why root keys should never exist
- Use
get-account-summaryto get an aggregate IAM inventory snapshot - Find orphaned (unattached) customer-managed policies
- Use
lookup-eventsto find recentAssumeRoleandiam.amazonaws.comevents - Read a raw CloudTrail event JSON and extract: caller ARN, event name, target resource, source IP
- Deliberately generate an
AccessDeniedevent and locate it in CloudTrail - Read the
errorMessageand identify which layer (identity, resource, SCP, boundary) caused the denial - Describe the six-step AccessDenied debugging workflow from memory
- Explain why you should never fix AccessDenied by adding
Action: * / Resource: *
- Use
- Name five common IAM privilege escalation paths and explain why each works
- Identify that
iam:PassRoleonResource: *withoutiam:PassedToServiceis a high-severity escalation path - Use
simulate-principal-policyto detect a full escalation chain (PassRole + CreateFunction + InvokeFunction) - Write a fixed PassRole policy scoped to both a role ARN pattern AND a specific service
- Explain why
iam:CreatePolicyVersiononResource: *is an escalation path
- Explain the difference between trusting
arn:aws:iam::ACCOUNT:rootvs a specific role ARN - Demonstrate that any principal in a trusted account can pivot to the target role when root is trusted
- Update a trust policy from account-root to specific-role and verify the narrowing
- Explain why ExternalId should always accompany cross-account trust for third-party integrations
- Describe how a compromised Lambda role in Account A can reach prod data in Account B via a broad trust
- Explain the difference between trusting
- List the four trust condition levels for GitHub OIDC from broadest to narrowest
- Explain the security difference between
StringLike: repo:org/*andStringEquals: repo:org/repo:environment:production - Update a GitHub role trust from org-wide to environment-scoped and verify the change
- Apply a permission boundary to a GitHub role and explain why it matters even after fixing the trust
- Explain what GitHub environment protection rules add on top of the IAM trust condition
- Create a CloudWatch metric filter that counts IAM write events from CloudTrail logs
- Create an alarm that fires on the first IAM change within a 5-minute period
- Write a baseline snapshot of IAM roles (trust policies, managed policies, boundaries)
- Run drift detection against the baseline and identify an added managed policy
- Describe how you would run this detection on a nightly Lambda schedule
- Execute all six IR steps in order: contain, scope, blast radius, evict, review, close
- Disable a compromised access key and verify the status change
- Look up all CloudTrail events for a username in the last 12 hours
- Apply the
aws:TokenIssueTimedeny policy to revoke active STS sessions - Explain why deleting an access key does NOT revoke active STS sessions derived from it
- Explain what information to include in the incident summary (key, timeline, resources, next actions)