☰ All modules Tier 1 · IAM GuideCheat sheet cli-sdk-policies ›
Contents
  1. Root user and account protection
  2. IAM users and user groups
  3. IAM roles for AWS services
  4. Policy document structure
  5. Policy conditions and condition keys
  6. Testing and troubleshooting policies
  7. Password policy
  8. MFA devices and enforcement
  9. Access keys and programmatic access
  10. Credential report and last accessed information
  11. IAM Access Analyzer findings and policy generation
  12. Best practices and shared responsibility
  13. Numbers to know
  14. Decision rules
  15. Memory hooks

IAM — Cheat Sheet (DVA-C02)

Verified against AWS documentation on 2026-10-12 · ⚠️ = changed vs older material: learn the value shown here (older practice material may say otherwise; full list in notes/iam-guide.md#changed-vs-older-material) · explanations and examples: notes/iam-guide.md.

Root user and account protection

Topic Current facts Memory hook
Root user Email + password identity with full access; identity-based policies can't attach to it; only an SCP can restrict a member account's root Break glass, don't carry
Root MFA ⚠️ Required for every account type (standalone, management, member); register within 35 days of the first console sign-in attempt No MFA, no root
Root MFA devices Up to 8 of any type; if all are lost, recovery uses the account email and phone number
Root access keys Never create them; for occasional root CLI work use aws login with the root credentials
Root password rules 8–128 characters, ≥ 3 of 4 character types, not the account name or email; the IAM password policy doesn't apply
Root-only tasks, standalone accounts ⚠️ Change account email, root password or root access keys; close or reopen the account (name, contacts, currency, Regions no longer need root)
Root-only tasks, any account Restore a locked-out IAM admin; activate IAM access to Billing; S3 MFA Delete; delete an S3 or SQS policy that denies everyone; RI Marketplace seller; GovCloud sign-up
Centralized root access (Organizations) ⚠️ Since Nov 15, 2024: delete member root password, keys, certificates and MFA; new member accounts then start without root credentials Root on demand
sts:AssumeRoot From the management or delegated IAM admin account (not with root credentials); Regional STS endpoint only; DurationSeconds ≤ 900 (default 900); scope with sts:TaskPolicyArn 15 minutes of root, one task
AssumeRoot task policies IAMAuditRootUserCredentials, IAMCreateRootUserPassword, IAMDeleteRootUserCredentials, S3UnlockBucketPolicy, SQSUnlockQueuePolicy
Detecting root use CloudTrail root sign-in events → EventBridge + SNS or GuardDuty; AWS Config root-account-mfa-enabled and iam-root-access-key-check

IAM users and user groups

Topic Current facts Memory hook
IAM user Long-term identity: console password, ≤ 2 access keys, signing certificates, SSH public keys, service-specific credentials
When to create IAM users ⚠️ Only where federation can't work: workloads that can't use roles, third-party tools, CodeCommit, Keyspaces, break-glass access; people federate Users are the exception
User group Attaches policies to many users; no credentials, can't sign in, can't be a Principal, can't be nested, no built-in all-users group Groups are folders, not people
A user's identity permissions Union of the user's own policies and all its groups' policies; any explicit Deny wins
Same-account vs cross-account access Same account: an identity policy OR a resource policy can allow; cross-account: both sides must allow
IAM name rules Unique per account and case-insensitive; user name 64 chars, group name 128, path 512
IAM ARNs Region field empty (IAM is global): arn:aws:iam::<account>:user/<path><name>; paths only via API, CLI or CloudFormation IAM is global
Deleted and recreated user New unique ID (AIDA…): trust policies naming the old user stop matching; name-based identity policies match the newcomer Same name, new person
DeleteUser with CLI/API First remove password, keys, certificates, SSH keys, service-specific credentials, MFA, inline and managed policies, groups; else DeleteConflict (409) Empty the drawers first
Suspending an IAM user Attach a deny-all policy, optionally time-bound with aws:CurrentTime

IAM roles for AWS services

Topic Current facts Memory hook
IAM role Identity without long-term credentials; assuming it returns temporary credentials for a session Borrowed badge
Role trust policy Resource-based policy on the role: Principal + sts:AssumeRole define who may assume it Trust = who
Role permissions policy Identity-based policy on the role: defines what the session may do Permissions = what
Service principal format <service>.amazonaws.com; several services in one Service array; "Service": "*" not allowed
Service role Assumed by a service on your behalf; you create and edit it (Lambda execution role, CloudFormation and CodeBuild service roles)
Service-linked role Path /aws-service-role/, name AWSServiceRoleFor…; trust and permissions owned by the service and read-only to you; no permissions boundary Look, don't touch
Creating and deleting service-linked roles Usually automatic, else create-service-linked-role (iam:CreateServiceLinkedRole); delete after dependent resources; may exceed the role quota
Role session limits Max session 1–12 h (default 1 h); requests from 900 s; role chaining ≤ 1 h; sessions AWS services assume aren't limited by it
"Role cannot be assumed by Lambda" Fix the trust policy (lambda.amazonaws.com + sts:AssumeRole), not the permissions
RoleLastUsed Returned by get-role: last-used date and Region over the trailing 400 days

Policy document structure

Element Current facts Memory hook
Version "2012-10-17" is current; omitted → 2008-10-17, where policy variables become literal text Always 2012
Statement One per policy (array for several); each statement holds one Effect, one Action/NotAction, one Resource/NotResource
Sid and Id Sid labels a statement (letters and digits only in IAM); Id labels a policy and is allowed only in resource-based policies, never in identity-based ones Id = resource policies only
Effect and default deny Allow or Deny; no matching allow = implicit deny; explicit Deny beats every Allow Deny wins, silence denies
Action prefix:ActionName, case-insensitive, * and ? wildcards, arrays allowed
Resource ARN arn:partition:service:region:account:resource; an incomplete ARN in an identity policy is completed with wildcards
Actions without resource-level permissions Many Describe*/List*, s3:ListAllMyBuckets, dynamodb:ListTables need "Resource": "*"; a specific ARN grants nothing Describe needs a star
S3 ARN shapes s3:ListBucket on arn:aws:s3:::bucket; s3:GetObject/PutObject on arn:aws:s3:::bucket/* Bucket vs bucket/*
Principal Only in resource-based and trust policies; account, user, role, service, federated or *; never a group; in an identity policy → MalformedPolicyDocument
Account as principal "AWS": "111122223333" = arn:aws:iam::111122223333:root = the whole account, not only its root user
NotPrincipal Deny only; not in identity or trust policies, SCPs or RCPs; AWS prefers Deny + ArnNotEquals on aws:PrincipalArn
NotAction With Allow: every unlisted action, including future services; with Deny: "deny everything except" guardrail NotAction + Allow = blank cheque
Managed policy versions ≤ 5 per policy, one default; roll back with set-default-policy-version; CLI/API 6th version → LimitExceeded (409); inline policies have none
Freezing a managed policy Deny both iam:CreatePolicyVersion and iam:SetDefaultPolicyVersion

Policy conditions and condition keys

Topic Current facts Memory hook
Condition combination logic Operators AND, keys AND, values of one key OR, values under a negated operator NOR
Missing condition key Most operators → false; negated operators → true; ...IfExists → true; Null tests presence
aws:MultiFactorAuthPresent Absent for long-term access-key calls → a "deny without MFA" needs BoolIfExists = false IfExists catches keys
aws:MultiFactorAuthAge Seconds since MFA sign-in; present only with temporary credentials
aws:SourceIp Caller's public IP; absent through VPC endpoints (use aws:VpcSourceIp, aws:SourceVpce); calls a service makes for you show the service's address
aws:RequestedRegion IAM calls always resolve to us-east-1 → Region-lock policies must exempt global services with NotAction IAM lives in us-east-1
aws:SecureTransport Always present; Deny when false blocks plain-HTTP requests
ABAC tag keys aws:PrincipalTag/, aws:ResourceTag/, aws:RequestTag/, aws:TagKeys; in .../<key> forms the key is case-insensitive, the value case-sensitive
ForAllValues: qualifier True when the key is missing or empty → add Null = false
Wildcards in conditions Only StringLike/StringNotLike (and ARN operators) expand * and ?; StringEquals treats them literally
One statement, many resource types ec2:RunInstances + ec2:InstanceType → use StringLikeIfExists

Testing and troubleshooting policies

Topic Current facts Memory hook
accessanalyzer validate-policy 100+ grammar and best-practice checks; ERROR, SECURITY_WARNING, WARNING, SUGGESTION; policy types identity, resource, SCP, RCP Lint
Validation in the console JSON editor shows findings for managed and user/role inline policies (not group inline); needs access-analyzer:ValidatePolicy
Custom policy checks check-no-new-access, check-access-not-granted, check-no-public-access; PASS or FAIL (= might allow); charged per check CI gate
Clean validation ≠ least privilege Validation judges syntax and patterns; use custom checks or policy generation to judge access
Implicit vs explicit deny (details: cli-sdk-policies guide) "no <type> policy allows" → add an allow there; "explicit deny in a <type> policy" → change that deny Edit the deny
IAM eventual consistency Writes go to one control plane (us-east-1), then to read-only data planes per Region: create IAM resources in an earlier step, wait, retry with backoff
aws iam wait role-exists Waits until GetRole sees the role; other endpoints may still lag
"This policy does not grant any permissions" Console summary: an action paired with a resource or condition it doesn't support; the policy was still saved

Password policy

Topic Current facts Memory hook
Default password policy No custom policy set: 8–128 characters, ≥ 3 of 4 character types, not the account name or email, never expires
Custom password options Min length 6–128; expiry 1–1,095 days; reuse prevention 1–24 passwords; character-type requirements
Timing of password policy changes Length and character rules at the next change; expiry applies immediately to older passwords
Hard expiry Expired users need an admin reset (iam:UpdateLoginProfile) or a programmatic iam:ChangePassword with active keys
"Allow users to change their own password" Account-level grant of iam:ChangePassword (own user) + iam:GetAccountPasswordPolicy; attaches no policy
Expired console password Blocks console sign-in only; access keys keep working
update-account-password-policy No partial updates: omitted options revert to their parameter defaults (length 6, no expiry, no character rules), not to the default policy Send the whole policy
Password policy scope IAM users only: not root, not access keys; IAM has no lockout setting

MFA devices and enforcement

Topic Current facts Memory hook
MFA devices per user ⚠️ Up to 8 per IAM user and per root user, any mix; one is enough to sign in Eight is enough
MFA types ⚠️ Passkeys and FIDO security keys (phishing-resistant, recommended), virtual TOTP apps, hardware TOTP tokens
Hardware TOTP vendors ⚠️ Thales OTP token or display card bought via AWS's links; GovCloud: Hypersecu
SMS MFA ⚠️ Can no longer be enabled
Passkeys with the CLI Registered in the console only and not passable to STS → use aws login Passkey to CLI? aws login
Sharing a device across identities One FIDO security key can be registered for many identities; each TOTP token or app entry belongs to exactly one user
Virtual MFA serial number The device ARN arn:aws:iam::<account>:mfa/<name>; hardware tokens use the printed serial
enable-mfa-device Two consecutive codes, submitted promptly; out of sync → resync-mfa-device
Adding or removing another MFA device Requires authenticating with an existing device
iam:DeleteVirtualMFADevice explicit-deny error Leftover unassigned virtual device from a cancelled setup → admin deletes it via CLI or API
Enforcing MFA in a policy Deny + NotAction (MFA self-service, sts:GetSessionToken) + BoolIfExists aws:MultiFactorAuthPresent = false

Access keys and programmatic access

Topic Current facts Memory hook
Access key Access key ID (AKIA…) + secret access key shown only at creation; long-term until deleted
Access keys per user 2, not adjustable (the second slot is for rotation)
Temporary credentials ASIA… key ID + secret + session token, with an expiry ASIA = session
Preferred programmatic access ⚠️ aws login, IAM Identity Center (aws configure sso), CloudShell, roles, IAM Roles Anywhere; long-term keys "not recommended" Borrow, don't own
aws login AWS CLI 2.32.0+; root, IAM users or IAM-federated identities; IAM principals need SignInLocalDevelopmentAccess; refreshed every 15 min for up to 12 h
Lost secret access key Delete the key and create a new one (delete one first if the user has two)
Zero-downtime key rotation Create second key → switch apps → check last use → deactivate old → delete Overlap, verify, retire
Access key last used Date, service and Region; first use per 15-minute window; tracked since 2015-04-22
sts get-access-key-info Returns only the owning account ID, not the key's status
Exposed access keys AWS may attach AWSCompromisedKeyQuarantineV3 and open a case → replace the key; don't just detach the policy
Self-managed access keys Allow iam:*AccessKey* on arn:aws:iam::*:user/${aws:username}

Credential report and last accessed information

Topic Current facts Memory hook
Credential report Account-wide CSV for all users incl. root: passwords, both access key slots, MFA, X.509 certificates Who holds what
Credential report frequency At most once every 4 hours (a newer report is returned again)
Credential report gaps No service-specific credentials (CodeCommit Git, Bedrock or CloudWatch Logs API keys); list them with ListServiceSpecificCredentials
Credential report permissions iam:GenerateCredentialReport and iam:GetCredentialReport
Last accessed information ⚠️ Last Accessed tab (formerly Access Advisor) on users, groups, roles, policies; Organizations entities from the management account Who used what
Last accessed coverage Within 4 h; services ≥ 400 days; ⚠️ action-level: S3 (2020), EC2/IAM/Lambda (2021), other services since 2023-05-23; management actions only
Last accessed limits Identity-based policies only; denied attempts included; iam:PassRole never tracked; missing data ≠ unused
Last accessed API generate-service-last-accessed-details --granularity ACTION_LEVEL → JobId → get-service-last-accessed-details
Authoritative record of API calls CloudTrail

IAM Access Analyzer findings and policy generation

Topic Current facts Memory hook
External access analyzer Finds resource-based policies granting access outside the zone of trust (account or organization); Regional, one per Region
External access resource types S3 buckets, IAM role trust policies, KMS keys, Lambda, SQS, Secrets Manager, SNS, EBS and RDS snapshots, ECR, EFS, DynamoDB
Finding timing About 30 min after a policy change; periodic rescan within 24 h; StartResourceScan rescans on demand
Unused access analyzer Paid per role and user per month; unused roles, keys, passwords, services and actions (unused age 1–365 days); not Regional Analyze unused once
Internal access analysis Paid per monitored resource; which principals inside the account or org can reach selected resources; Regional
Policy generation From a CloudTrail trail over ≤ 90 days; service role trusting access-analyzer.amazonaws.com; no data-event actions (S3 object or DynamoDB item calls such as PutItem), no iam:PassRole; kept 7 days in the console Activity → policy
Analyzer types ACCOUNT, ORGANIZATION, ACCOUNT_UNUSED_ACCESS, ORGANIZATION_UNUSED_ACCESS, ACCOUNT_INTERNAL_ACCESS, ORGANIZATION_INTERNAL_ACCESS

Best practices and shared responsibility

Topic Current facts Memory hook
AWS side of IAM security Infrastructure that runs IAM, availability, replication, physical security Security of the cloud
Customer side of IAM security Identities, policies, MFA, credential lifecycle, least privilege, access reviews Security in the cloud
Human users ⚠️ Federate through IAM Identity Center or an IdP and use temporary credentials
Workloads IAM roles; outside AWS: IAM Roles Anywhere, AssumeRoleWithSAML, AssumeRoleWithWebIdentity
Long-term access keys ⚠️ Update when needed (e.g. an employee leaves), guided by last-used data, instead of fixed-schedule rotation
Guardrails SCPs (principals), RCPs (resources) and permissions boundaries limit access but grant nothing Fences, not gates
Policy lifecycle AWS managed policies → customer managed least privilege → generate, validate, remove unused
IAM Identity Center name ⚠️ AWS SSO renamed IAM Identity Center on 2022-07-26; aws configure sso and sso* APIs unchanged

Numbers to know

Item Value Note
IAM users per account 5,000 Not adjustable
IAM groups per account 300 Adjustable to 500
Groups per IAM user 10 Not adjustable
Roles per account 1,000 ⚠️ Adjustable up to 10,000
Managed policies per user 10 Adjustable to 20
Managed policies per group 10 Not adjustable
Managed policies per role 20 ⚠️ Adjustable up to 25
Customer managed policies per account 1,500 ⚠️ Adjustable up to 10,000
Managed policy size 6,144 characters Whitespace not counted
Inline policy size totals User 2,048 · group 5,120 · role 10,240 characters Whitespace not counted
Role trust policy length 2,048 characters ⚠️ Adjustable up to 8,192
Versions per managed policy 5 Not adjustable
Access keys per IAM user 2 Not adjustable
MFA devices per user (IAM or root) 8 ⚠️ Any mix of types
Signing certificates / SSH public keys per user 2 / 5 Not adjustable
Tags per IAM user or role 50
Instance profiles per account 1,000 ⚠️ Adjustable up to 10,000; 1 role per instance profile
IAM name lengths User 64 · role 64 · group 128 · policy 128 · path 512
Role maximum session duration 1–12 h (default 1 h) Requests from 900 s
Role chaining session 1 h maximum
AssumeRoot session ≤ 900 s (default 900) Regional STS endpoint only
Root MFA registration window 35 days From the first console sign-in attempt
Root password 8–128 characters, ≥ 3 of 4 types
Default IAM password policy 8–128 characters, ≥ 3 of 4 types, never expires
Custom minimum password length 6–128 CLI default 6 when omitted
Password expiration 1–1,095 days Applies immediately
Password reuse prevention 1–24 previous passwords
Credential report generation Once every 4 hours
Last accessed data Within 4 h; services ≥ 400 days
Action-level last accessed tracking start S3 2020-04-12 · EC2/IAM/Lambda 2021-04-07 · others 2023-05-23 ⚠️ Management actions only
Access key last-used granularity First use per 15 minutes Tracked since 2015-04-22
RoleLastUsed window Trailing 400 days
Access Analyzer policy generation window ≤ 90 days of CloudTrail Generated policy kept 7 days in the console
Access Analyzer re-analysis About 30 min after a change Periodic rescan within 24 h
Account alias length 3–63 characters Lowercase, not a 12-digit number
Access key ID prefixes AKIA long-term · ASIA temporary
Unique ID prefixes AIDA user · AGPA group · AROA role · ANPA managed policy · AIPA instance profile
IAM error codes MalformedPolicyDocument 400 · NoSuchEntity 404 · DeleteConflict 409 · LimitExceeded 409
Policy language version 2012-10-17 Omitted → 2008-10-17
Region seen for IAM calls us-east-1 Matters for aws:RequestedRegion

Decision rules

Memory hooks