IAM and access management
Users, groups, roles, policies, how AWS evaluates permissions, temporary credentials via STS, multiple accounts with Organizations and IAM Identity Center.
- DomainSecure architectures
- 12 diagrams
- 10 scenarios
- 9 services
5-minute essentials
- By default every request is denied (implicit deny); you need at least one matching Allow, and an explicit Deny in any policy beats every Allow.Reading a permissions question: look for Deny first, then SCP, then resource / identity policy, permissions boundary, session policy.
- User = long-term identity (password, access key); role = an identity you "borrow" with temporary credentials from STS.AWS recommends roles and federation over long-term access keys; applications on EC2 / Lambda / ECS always use roles.
- EC2 gets permissions through an instance profile (a role attached to the instance); the SDK fetches temporary credentials from instance metadata automatically.The answer "store access keys in a config file on EC2" is always wrong.
- A role has a trust policy (who can assume it) and a permission policy (what it can do once assumed).To let account B into account A: create a role in A that trusts B; the person in B needs sts:AssumeRole permission on that role. For third parties, add an External ID.
- Resource-based policies (bucket policy, key policy, queue policy, etc.) have a Principal element and allow cross-account access without assuming a role.Cross-account with a resource policy: the caller keeps its own permissions; with a role: the caller switches to the role's permissions.
- An Organizations SCP sets a permission ceiling for users / roles in member accounts and grants nothing; it does not apply to the management account or service-linked roles."Prevent every account from turning off CloudTrail / using Regions outside an allowed list" → an SCP with Deny attached to an OU or the root.
- A permissions boundary sets a ceiling for one specific user / role; effective permissions = the intersection of the identity policy and the boundary.Let developers create roles themselves without escalating privileges: require new roles to have the boundary attached.
- IAM Identity Center: single sign-on to multiple accounts in Organizations, permissions assigned through permission sets, can connect to an external IdP (Entra ID, Okta, etc.).Employees use their company account to reach many AWS accounts: Identity Center is the modern answer, instead of creating IAM users in each account.
- A Cognito user pool is a user directory (sign-up, sign-in, MFA, social login); an identity pool exchanges that identity for temporary AWS credentials.A mobile / web app whose customers access S3 or DynamoDB directly: Cognito, not IAM users.
- Protect the root user: enable MFA, create no access keys, and use it only for the few tasks that require it.Daily work uses users / roles with least privilege; root is only for tasks like changing the support plan or closing the account.
- A role's temporary credentials last 1–12 hours depending on configuration; role chaining (assuming another role from a role) is limited to 1 hour.A session cut off after 1 hour even though 12 hours was set: usually caused by role chaining.
- IAM Access Analyzer finds resources shared outside the zone of trust (account / organization) and validates policies before you apply them."Find buckets, keys and roles that allow outside access" → Access Analyzer.
- Policy Conditions: aws:SourceIp, aws:MultiFactorAuthPresent, aws:RequestedRegion, aws:PrincipalOrgID, tags (ABAC), etc.Tag-based permissions (ABAC) need fewer policies as projects grow; aws:PrincipalOrgID shares with a whole organization without listing each account.
Diagrams
How AWS evaluates a request
Step by step
- A Deny in any applicable policy → DENY immediately.
- The organization's SCP / RCP does not allow → DENY.
- No Allow from any identity or resource policy → DENY (implicit deny).
- The permissions boundary and session policy (if present) must also allow → ALLOW.
EC2 calls S3 with a role, no access key needed
Step by step
- The role is attached to EC2 via an instance profile; permissions live in the role's permission policy.
- The SDK reads temporary credentials from instance metadata automatically (IMDSv2).
- Calls S3 with temporary credentials; no long-term key exists on the instance.
A person in account B uses a role in account A
Permissions boundary: effective permissions are the intersection
An SCP sets the ceiling for a whole OU
Step by step
- Accounts are placed in OUs; SCPs are attached at the root or an OU.
- Every account in the Prod OU inherits the SCP: no one (even that account's root user) can use Regions outside the list.
IAM Identity Center: one sign-in, many accounts
Step by step
- Employees sign in with their corporate account; groups sync to Identity Center (SCIM).
- Each group has a different permission set per account; when someone leaves, disable them in the IdP.
SAML 2.0 federation into the console
Cognito: app customers access S3
IAM Access Analyzer finds external access
Step by step
- Access Analyzer analyzes the policies of buckets, keys, roles, queues, etc.
- A bucket policy granting an account outside the organization → generates a finding to review and fix.
ABAC: tag-based permissions, one policy for all projects
Step by step
- Both roles share one policy; the condition compares the role's project tag with the resource's project tag.
- The Heart role can act only on resources with project = heart; Star's instances are denied.
- Create a new instance tagged project = heart: the Heart team has access immediately, nobody edits a policy.
Sign in to RDS with IAM, no password
Choosing how to grant AWS access
Step by step
- EC2, Lambda, ECS: attach a role (instance profile, execution role, task role); never embed access keys in code.
- Customers of a web / mobile app: Cognito user pool for sign-in, identity pool to exchange for temporary AWS credentials.
- Employees: for many accounts use IAM Identity Center (single sign-on); for one account with a corporate IdP use SAML 2.0 federation via STS.
- Another AWS account or a partner: a role with a trust policy for that account; for third parties add an External ID.
Quick comparisons
Policy types
| Type | Attached to | Grants permissions? | Use when |
|---|---|---|---|
| Identity-based | User, group, role | Yes | Grant permissions to identities in the account |
| Resource-based | Bucket, key, queue, topic, role (trust), etc. | Yes (including cross-account) | Let a principal in another account into a resource |
| Permissions boundary | User, role | No, only sets a ceiling | Delegate role creation without privilege escalation |
| SCP (Organizations) | Root, OU, account | No, only sets a ceiling | Guardrail for a whole account / OU |
| RCP (Organizations) | Root, OU, account | No, only sets a ceiling | Guardrail on resources in the organization |
| Session policy | Assume-role / federation session | No, only sets a ceiling | Narrow permissions for a single session |
Cross-account access
| Assume role | Resource-based policy | |
|---|---|---|
| How it works | The caller switches to the permissions of a role in the target account | The resource itself grants access to a principal in another account |
| Permissions in the home account | Set aside during the session | Kept (e.g. copying from bucket A to bucket B in one operation) |
| Supported services | All services | Only services with resource policies (S3, SQS, SNS, KMS, Lambda, etc.) |
| Third party | Add an External ID to prevent the confused deputy problem | Use the aws:SourceAccount / SourceArn conditions |
Identity by audience
| Who | Use | Notes |
|---|---|---|
| Employees, multiple accounts | IAM Identity Center (+ corporate IdP) | Permission set → role in each account |
| Employees, one account, with AD | SAML 2.0 federation → AssumeRoleWithSAML | Or Identity Center connected to AD |
| Applications on EC2 / ECS / Lambda | Role (instance profile, task role, execution role) | Never store access keys |
| Customers of a web / mobile app | Cognito user pool + identity pool | Social login, MFA |
| Servers outside AWS | IAM Roles Anywhere (X.509 certificates) | Replaces long-term access keys |
| Emergency situations | Break-glass IAM user with MFA | Lock down tightly, monitor |
Organizations and Control Tower
| Organizations | Control Tower | |
|---|---|---|
| What it is | Groups accounts into an OU tree, consolidated billing, SCP / RCP | Builds a multi-account landing zone following best practices |
| Guardrails | You write your own SCPs | Built-in controls (preventive = SCP, detective = Config) |
| Use when | You need flexible control | You need to stand up a standards-compliant multi-account environment quickly |
Exam scenarios
1An application on EC2 needs to read an S3 bucket.
Show answer
Right: A role with s3:GetObject on the bucket, attached to EC2 via an instance profile
The SDK fetches temporary credentials from metadata; AWS rotates them automatically.
Wrong: Create an IAM user and store the access key in a config file on the instance
Long-term keys leak easily and you must rotate them yourself.
Wrong: A bucket policy allowing every principal
Opens the bucket to the whole world.
2A user has the AdministratorAccess policy but still cannot turn off CloudTrail in a member account.
Show answer
Right: An SCP denies cloudtrail:StopLogging at the OU / root
An SCP sets the ceiling for every user and role (including root) of member accounts; Deny beats every Allow.
Wrong: Missing the cloudtrail:StopLogging permission
AdministratorAccess already includes it; the permission is blocked at a higher layer.
3An auditing firm (third party) needs to read resources in your account.
Show answer
Right: A role their account assumes, with a trust policy requiring an External ID
Temporary credentials that can be revoked; the External ID prevents the confused deputy problem.
Wrong: Create an IAM user and send them the access key
Long-term keys end up outside your control.
4Let developers create Lambda roles themselves but not roles with more privileges than their own.
Show answer
Right: Permissions boundary: allow iam:CreateRole only when the new role has the specified boundary attached
The new role's effective permissions never exceed the boundary.
Wrong: Just tell developers not to attach AdministratorAccess
Nothing prevents it.
Wrong: SCP
An SCP applies to the whole account and does not distinguish who created a role.
5500 employees sign in with Microsoft Entra ID accounts to reach 40 AWS accounts.
Show answer
Right: IAM Identity Center connected to Entra ID, assigning permission sets to groups per account
Single sign-on, group-based permissions; when someone leaves, disabling them in the IdP removes access.
Wrong: Create an IAM user for each person in each account
20,000 users, unmanageable, plus long-term keys.
6A mobile app lets users sign in with Google and upload photos to their own folder in S3.
Show answer
Right: Cognito user pool (Google sign-in) + identity pool issuing a temporary role; policy restricts the prefix by user ID
Each person gets temporary permissions only on their own folder.
Wrong: Embed an access key in the app
Anyone who unpacks the app can get the key.
7You need to know which buckets, KMS keys and roles allow access from accounts outside the organization.
Show answer
Right: IAM Access Analyzer with the organization as the zone of trust
Analyzes policies automatically and reports a finding for each outside access path.
Wrong: Read each policy manually
Cannot keep up with many resources and is easy to miss something.
8Share a bucket with every account in the organization, including accounts created later.
Show answer
Right: A bucket policy with the aws:PrincipalOrgID condition equal to the organization ID
New accounts in the organization get access automatically; outside accounts do not.
Wrong: List each account ID in the bucket policy
You must edit the policy every time there is a new account.
9A script assumes role A, then from A assumes role B with DurationSeconds of 4 hours, and fails.
Show answer
Right: Role chaining limits the session to a maximum of 1 hour
For a longer session: assume B directly with the original identity.
Wrong: Role B has a max session duration of 1 hour
Possible, but here the reason is certainly role chaining.
10MFA must be required to delete objects in an important bucket.
Show answer
Right: A policy that Denies s3:DeleteObject when aws:MultiFactorAuthPresent is not true (and consider MFA Delete when versioning is enabled)
The MFA condition applies to exactly the action to protect.
Wrong: Only enable MFA for console sign-in
It does not bind individual API operations.
Quick picks
What do you use to grant / limit permissions?
| When you need | Use |
|---|---|
| An application on EC2 / Lambda / ECS needs to call AWS | Role (instance profile, execution role, task role) · see diagram |
| A person in another account needs access | Role + trust policy (third party: External ID) · see diagram |
| Let another account use a resource | Resource-based policy (bucket / key / queue policy) · see diagram |
| Forbid an action for a whole account / OU | SCP · see diagram |
| Limit the permission ceiling of one user / role | Permissions boundary · see diagram |
| Employees sign in once to many accounts | IAM Identity Center · see diagram |
| Sign in with corporate AD to one account | SAML 2.0 federation · see diagram |
| Customers of a web / mobile app | Cognito user pool + identity pool · see diagram |
| Find resources shared externally | IAM Access Analyzer · see diagram |
| Understand why a request was denied | Follow the policy evaluation order · see diagram |
Common pitfalls
- Storing access keys on EC2 or in code instead of using a role.
- Thinking an SCP grants permissions: an SCP only sets a ceiling; you still need an identity policy.
- Thinking an SCP can restrict the management account: it does not apply to the management account.
- Forgetting that an explicit Deny beats every Allow, even AdministratorAccess.
- Letting a third party assume a role without an External ID.
- Using root for daily work, or creating access keys for root.
- Using IAM users for an application's customers (that is Cognito's job).
- Mixing up a user pool (sign-in) with an identity pool (exchange for AWS credentials).
- Listing each account in a bucket policy instead of using aws:PrincipalOrgID.
- Thinking a permissions boundary grants extra permissions.
- Forgetting that role chaining limits the session to 1 hour.
Services in this module
IAMwho can do what
STStemporary credentials
IAM Identity Centersingle sign-on (SSO)
Organizationsmanage multiple accounts
Control Towermulti-account landing zone setup
Access AnalyzerIAM access analysis
Cognitosign-in for app users
Directory Servicemanaged Active Directory
Resource Access Managershare resources across accounts
Numbers that change (checked against AWS docs)
- Defaults: 20 managed policies per role (max 25), 10 per user (max 20), 10 per group; 1,000 roles per account (max 10,000). checked 2026-10-16 ↗
- A managed policy is at most 6,144 characters; total inline policy size: user 2,048, group 5,120, role 10,240 characters (excluding whitespace). checked 2026-10-16 ↗
- A role session ranges from 15 minutes up to 12 hours depending on max session duration; the default is 1 hour if unspecified. checked 2026-10-16 ↗
- Role chaining limits the session to a maximum of 1 hour, regardless of the role's max session duration. checked 2026-10-16 ↗
- Evaluation order: explicit Deny → RCP → SCP → resource-based → identity-based → permissions boundary → session policy; an explicit Deny beats every Allow. checked 2026-10-16 ↗
- SCPs grant no permissions, do not apply to users / roles of the management account or to service-linked roles; they do apply to the root user of member accounts. checked 2026-10-16 ↗
- An SCP is at most 10,240 characters; at most 10 SCPs attached directly to the root, each OU and each account; OUs nest up to 5 levels. checked 2026-10-16 ↗
- Organizations allows at most 10 accounts by default (can be raised via Service Quotas). checked 2026-10-16 ↗
- ABAC: one policy allows an action when the principal's tag matches the resource's tag; adding new resources needs no policy change. checked 2026-10-19 ↗
- RDS IAM database authentication: a token signed with Signature V4 that lasts 15 minutes, for MariaDB, MySQL, PostgreSQL; the connection is encrypted with SSL/TLS. checked 2026-10-19 ↗