The AWS Shared Responsibility Model
Before touching any IAM configuration, you need to understand who is responsible for what. AWS operates under a Shared Responsibility Model that divides security duties between AWS and the customer.
AWS responsibility ("Security OF the Cloud"): AWS manages the physical data centers, the hardware, the hypervisor, and the managed service infrastructure. You cannot patch an Amazon RDS database engine's underlying operating system — AWS does that. You cannot physically access a server — AWS controls that.
Customer responsibility ("Security IN the Cloud"): You control IAM configurations, security group rules, encryption settings, application code, and operating system patches on EC2 instances. If you leave an S3 bucket publicly accessible, that is your responsibility, not AWS's.
The line shifts depending on the service type:
- Infrastructure services (EC2, EBS, VPC): You manage the OS, firewall rules, and encryption. AWS manages the physical layer.
- Container services (RDS, EMR, Elastic Beanstalk): AWS manages the OS and platform. You manage network access, credentials, and firewall rules.
- Abstracted services (S3, DynamoDB, Lambda): AWS manages nearly everything beneath the API. You manage IAM policies, encryption configuration, and data classification.
💡 Exam Trap: A question asks who is responsible for patching the operating system on an RDS instance. The answer is AWS — because RDS is a managed service. But if the question asks about an EC2 instance, patching the OS is YOUR responsibility. The key word is "managed."
AWS Global Infrastructure
Regions are geographically isolated clusters of data centers. Each Region (e.g., us-east-1, eu-west-1) is fully independent with its own power, networking, and connectivity. You choose a Region for data residency, latency, or compliance reasons.
Availability Zones (AZs) are one or more discrete data centers within a Region, each with redundant power, networking, and connectivity. AZs within a Region are connected with low-latency links but are physically separated to protect against localized failures. Most Regions have three or more AZs. AZ identifiers (e.g., us-east-1a) are mapped differently per account — your us-east-1a might be a different physical data center than another account's us-east-1a. AWS uses AZ IDs (e.g., use1-az1) for consistent cross-account mapping.
Edge Locations are points of presence used by Amazon CloudFront, AWS WAF, and Route 53 for caching and traffic management closer to end users.
💡 Exam Trap: IAM is a global service — it does not belong to any single Region. When you create an IAM user, that user can operate in any Region. However, some services like S3 bucket names are globally unique, while the bucket data resides in a specific Region.
AWS Identity and Access Management (IAM) — Core Concepts
IAM is the service that controls who (authentication) can do what (authorization) in your AWS account. It is free, global, and eventually consistent.
Root User: When you first create an AWS account, you get a root user tied to the email address used for signup. The root user has unrestricted access to everything in the account. Best practice: use the root user only for account-level tasks that require it (e.g., changing the account support plan, closing the account, enabling MFA on root, creating the first IAM administrator). Then lock it away.
Tasks that ONLY the root user can perform include:
- Changing account-level settings (account name, email, root password)
- Restoring IAM user permissions (when no other administrator exists)
- Activating IAM access to the Billing and Cost Management console
- Closing the AWS account
- Configuring an S3 bucket for MFA Delete
- Changing or canceling the AWS Support plan
IAM Users represent individual people or applications. Each IAM user has a unique name within the account and can authenticate via a password (console) or access keys (programmatic). An AWS account can have up to 5,000 IAM users.
💡 Exam Trap: The 5,000 IAM user limit per account is a hard limit. If you have 10,000 employees, you cannot create 10,000 IAM users. This is a key driver for using IAM roles with federation instead of individual IAM users.
IAM Groups are collections of IAM users. You attach policies to groups, and every user in that group inherits those permissions. Groups simplify permission management — instead of attaching a policy to 50 users individually, attach it to one group. Key constraints:
- A user can belong to up to 10 groups.
- Groups cannot be nested (no group inside a group).
- Groups are not an "identity" — you cannot reference a group as a principal in a resource-based policy. You cannot log into AWS as a group.
IAM Roles are identities with permissions that are not permanently assigned to a person. Instead, a role is assumed by anyone (or any service) that needs temporary credentials. When you assume a role, AWS Security Token Service (STS) gives you temporary credentials that expire. Roles are used for:
- EC2 instances that need to call AWS APIs (instance profiles)
- Lambda functions that need AWS permissions
- Cross-account access
- Federated users from external identity providers
- AWS services that act on your behalf
IAM Policies are JSON documents that define permissions. There are several types:
- AWS Managed Policies: Created and maintained by AWS (e.g.,
AmazonS3ReadOnlyAccess). You cannot modify them. - Customer Managed Policies: Policies you create. You can version them (up to 5 versions per policy). Reusable across multiple users, groups, and roles.
- Inline Policies: Embedded directly into a single user, group, or role. They are deleted when the entity is deleted. Use sparingly — for strict one-to-one permission relationships.
An IAM policy document structure:
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "AllowS3ListBucket",
"Effect": "Allow",
"Action": "s3:ListBucket",
"Resource": "arn:aws:s3:::my-bucket",
"Condition": {
"StringEquals": {
"s3:prefix": ["home/${aws:username}/"]
}
}
}
]
}
Key fields:
- Version: Always use
"2012-10-17". The older"2008-10-17"version does not support policy variables like${aws:username}. - Effect:
AlloworDeny. If not explicitly allowed, access is denied by default (implicit deny). - Action: The API action (e.g.,
s3:GetObject,ec2:RunInstances). Wildcards are allowed:s3:*. - Resource: The ARN (Amazon Resource Name) of the resource.
"*"means all resources. - Condition: Optional constraints (IP range, time, MFA, tags, etc.).
Policy Evaluation Logic
When a principal makes a request, AWS evaluates all applicable policies in this order:
- Explicit Deny wins. If any policy says
"Effect": "Deny"for the action, it is denied — no exceptions. - Organization SCP boundary. If an SCP does not allow the action, it is denied — even if IAM policies allow it.
- Resource-based policies can grant access on their own for same-account access. For cross-account access, both the identity-based policy AND the resource-based policy must allow it.
- IAM permission boundary limits the maximum permissions an IAM entity can have.
- Session policies limit the permissions of a role session.
- Identity-based policies (managed and inline) are evaluated. An explicit
Allowhere grants access only if none of the above boundaries deny it. - Implicit Deny. If nothing explicitly allows the action, it is denied.
Decision Flow for Policy Evaluation
💡 Exam Trap: An explicit
Denyalways overrides an explicitAllow. If a user has a policy that allowss3:*and another policy (or SCP) that deniess3:DeleteBucket, the user CANNOT delete buckets. There is no "priority" amongAllowstatements that can override aDeny.
Multi-Factor Authentication (MFA)
MFA adds a second layer of authentication. AWS supports:
- Virtual MFA devices: Authenticator apps like Google Authenticator. Each virtual device produces a six-digit code that rotates every 30 seconds.
- U2F security keys: Physical keys (e.g., YubiKey) that plug into a USB port. Supports FIDO U2F standard.
- Hardware MFA devices: Key fob devices that display a rotating code.
Best practices:
- Enable MFA on the root user immediately after account creation.
- Enable MFA for all IAM users with console access, especially those with elevated privileges.
- You can enforce MFA using IAM policy conditions:
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "DenyAllExceptMFA",
"Effect": "Deny",
"NotAction": [
"iam:CreateVirtualMFADevice",
"iam:EnableMFADevice",
"iam:ListMFADevices",
"iam:ResyncMFADevice",
"sts:GetSessionToken"
],
"Resource": "*",
"Condition": {
"BoolIfExists": {
"aws:MultiFactorAuthPresent": "false"
}
}
}
]
}
💡 Exam Trap: The condition key
aws:MultiFactorAuthPresentonly exists in the request context when using temporary credentials (STS). It does NOT exist for long-term access keys. UseBoolIfExists(notBool) to handle the case where the key might not be present.
IAM Access Keys
Access keys are for programmatic access (CLI, SDKs). Each user can have a maximum of two active access keys — this allows rotation without downtime (create new key, update applications, deactivate old key, delete old key).
# Create access keys
aws iam create-access-key --user-name developer1
# List access keys
aws iam list-access-keys --user-name developer1
# Rotate: deactivate old key after new key is deployed
aws iam update-access-key --user-name developer1 \
--access-key-id AKIAIOSFODNN7EXAMPLE \
--status Inactive
Best practice: use IAM roles (which provide temporary credentials via STS) instead of long-term access keys wherever possible — especially for EC2, Lambda, and other AWS services.
IAM Roles and AWS Security Token Service (STS)
When you assume a role, AWS STS returns temporary security credentials consisting of:
- Access Key ID
- Secret Access Key
- Session Token
- Expiration timestamp
These credentials automatically expire. Default session duration for role assumption via AssumeRole is 1 hour, configurable up to 12 hours per role.
# Assume a role
aws sts assume-role \
--role-arn arn:aws:iam::123456789012:role/CrossAccountRole \
--role-session-name my-session
# The output includes temporary credentials
# AccessKeyId, SecretAccessKey, SessionToken, Expiration
Trust Policy: Every IAM role has a trust policy that specifies who can assume it. This is a resource-based policy on the role itself:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::111111111111:root"
},
"Action": "sts:AssumeRole",
"Condition": {
"Bool": {
"aws:MultiFactorAuthPresent": "true"
}
}
}
]
}
This trust policy says: "Account 111111111111 is allowed to assume this role, but only if MFA has been used."
Role Chaining: When one role assumes another role, the maximum session duration is limited to 1 hour — regardless of the role's configured maximum. This is a hard limit for chained sessions.
💡 Exam Trap: Role chaining (Role A assumes Role B) limits the session to 1 hour maximum. This is different from a direct
AssumeRolecall which can go up to 12 hours. If the exam describes a scenario where chained roles need sessions longer than 1 hour, it cannot be done through role chaining alone.
Cross-Account Access
A common pattern is granting access between AWS accounts. The approach uses IAM roles:
- Account B (resource account) creates an IAM role with a trust policy allowing Account A.
- Account A (requesting account) creates an IAM policy allowing its users to assume the role in Account B.
- A user in Account A calls
sts:AssumeRolewith the role ARN from Account B, receives temporary credentials, and operates in Account B.
This is preferable to sharing access keys between accounts because:
- No long-term credentials are shared.
- Access can be revoked instantly by modifying the trust policy.
- All activity is logged under the assumed role session in CloudTrail.
Role Switching in the Console
IAM users can switch roles in the AWS Management Console without signing out. The console stores up to five recently used roles for easy switching. When you switch roles, you temporarily give up your original user permissions and operate under the role's permissions.
Resource-Based Policies
Some AWS services support policies attached directly to the resource (rather than to the identity accessing it). Examples:
- S3 Bucket Policies — control who can access a specific bucket
- SQS Queue Policies — control who can send/receive messages
- SNS Topic Policies — control who can publish/subscribe
- KMS Key Policies — control who can use an encryption key (KMS key policies are mandatory — a KMS key must have a key policy)
- Lambda Function Policies — control who can invoke the function
Key difference from identity-based policies: resource-based policies specify a Principal field (who the policy applies to). Identity-based policies do not have a Principal because they are attached to the identity itself.
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "AllowCrossAccountRead",
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::111111111111:root"
},
"Action": "s3:GetObject",
"Resource": "arn:aws:s3:::shared-bucket/*"
}
]
}
💡 Exam Trap: For cross-account access using a resource-based policy (like an S3 bucket policy), the requesting account does NOT need to assume a role. The resource-based policy alone can grant access. But with identity-based policies alone for cross-account scenarios, you MUST use a role. This distinction matters on the exam.
IAM Permission Boundaries
A permission boundary is a managed policy that sets the maximum permissions an IAM user or role can have. The boundary does not grant permissions by itself — it only limits what identity-based policies can grant.
Effective permissions = Intersection of (identity-based policy) AND (permission boundary)
Use case: Delegated administration. You allow a developer to create IAM roles for Lambda, but attach a permission boundary so the roles they create can never exceed a certain set of permissions.
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"s3:GetObject",
"s3:PutObject",
"dynamodb:GetItem",
"dynamodb:PutItem"
],
"Resource": "*"
}
]
}
If this is set as a permission boundary, even if the user's identity-based policy allows ec2:*, the user cannot access EC2 — because it falls outside the boundary.
Multi-Account Strategy with AWS Organizations
AWS Organizations lets you centrally manage multiple AWS accounts. You create an organization with a management account (formerly called the master account) that governs member accounts.
Organizational Units (OUs): Accounts are grouped into OUs — which are hierarchical containers. You can nest OUs within OUs to create a tree structure reflecting your business (e.g., Root → Production OU → Application A OU, Application B OU).
Service Control Policies (SCPs): SCPs are policies attached to the organization root, OUs, or individual accounts. They define the maximum available permissions for accounts under them. SCPs do NOT grant permissions — they restrict what IAM policies in those accounts are allowed to grant.
Important SCP behaviors:
- SCPs affect all users and roles in the account, including the root user of that account. However, SCPs do not affect the management account.
- SCPs do not affect service-linked roles.
- If you attach an SCP that denies
ec2:TerminateInstancesto an OU, no one in any account under that OU can terminate EC2 instances — even with fullAdministratorAccess.
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "DenyLeaveOrg",
"Effect": "Deny",
"Action": "organizations:LeaveOrganization",
"Resource": "*"
},
{
"Sid": "DenyDisableCloudTrail",
"Effect": "Deny",
"Action": [
"cloudtrail:StopLogging",
"cloudtrail:DeleteTrail"
],
"Resource": "*"
}
]
}
💡 Exam Trap: SCPs do NOT apply to the management account. Even if you attach a restrictive SCP to the root of the organization, the management account itself is unaffected. Best practice: do not run workloads in the management account — use it only for governance.
AWS Control Tower
AWS Control Tower automates the setup of a multi-account environment following AWS best practices. It builds on top of AWS Organizations and provides:
- Landing Zone: A pre-configured, multi-account environment with baseline security and governance.
- Guardrails (Controls): Pre-packaged governance rules. They come in two types:
- Preventive guardrails: Implemented via SCPs. They prevent actions (e.g., "Disallow changes to S3 bucket encryption").
- Detective guardrails: Implemented via AWS Config rules. They detect noncompliance (e.g., "Detect whether MFA is enabled for root").
- Account Factory: Automates provisioning of new AWS accounts using standardized templates.
- Dashboard: Provides visibility into compliance status across all accounts.
AWS IAM Identity Center (formerly AWS SSO)
IAM Identity Center is the recommended service for managing workforce access across multiple AWS accounts and business applications. It provides:
- Single sign-on (SSO): Users sign in once and access all assigned AWS accounts and applications.
- Built-in identity store or integration with external identity providers (Microsoft Active Directory, Okta, Azure AD) via SAML 2.0.
- Permission Sets: Templates that define what a user can do in an assigned AWS account. Behind the scenes, a permission set creates an IAM role in the target account.
- Multi-account permissions: Assign users or groups to multiple AWS accounts with different permission sets per account.
Federating External Directories with IAM
Federation allows users from external identity providers (IdPs) to access AWS resources without creating IAM users for each one. This solves the 5,000 IAM user limit and avoids managing separate credentials in AWS.
SAML 2.0 Federation: Your corporate identity provider (e.g., Active Directory Federation Services) authenticates the user and sends a SAML assertion to AWS. AWS STS exchanges the assertion for temporary credentials. The user assumes an IAM role mapped to their SAML attributes.
Web Identity Federation: For mobile or web app users (e.g., logging in with Google, Facebook, or Amazon), the app gets a token from the web IdP, then calls sts:AssumeRoleWithWebIdentity. However, AWS recommends using Amazon Cognito instead of direct web identity federation — Cognito handles the complexity and supports unauthenticated (guest) access.
Custom Identity Broker: If your IdP does not support SAML, you build a custom broker application. The broker authenticates users against your identity store, then calls sts:AssumeRole or sts:GetFederationToken to get temporary credentials.
When to use each:
- IAM Identity Center: Workforce access to multiple AWS accounts and business apps. Preferred solution for employees.
- SAML 2.0 with IAM: Legacy integration when IAM Identity Center is not feasible.
- Amazon Cognito: Customer-facing applications (web/mobile) where end users need to access AWS resources.
- Custom broker: Environments with non-SAML identity stores.
💡 Exam Trap: If the exam says "employees need access to multiple AWS accounts through a single login," the answer is IAM Identity Center (SSO). If it says "mobile app users need to upload photos to S3," the answer is Amazon Cognito. Do not confuse workforce SSO with customer-facing identity.
Principle of Least Privilege
Grant only the permissions necessary to perform a task — nothing more. Strategies:
- Start with AWS managed policies for common job functions, then tighten using customer-managed policies.
- Use IAM Access Analyzer to identify unused permissions and generate least-privilege policies based on actual usage recorded in CloudTrail.
- Use policy conditions to restrict access by IP, time of day, MFA status, tags, or requested Region.
- Review permissions regularly with IAM credential reports and Access Advisor (which shows service-level last-accessed data).
# Generate a credential report
aws iam generate-credential-report
aws iam get-credential-report --output text --query Content | base64 --decode
# View last-accessed data for a role
aws iam generate-service-last-accessed-details \
--arn arn:aws:iam::123456789012:role/AppRole
Summary of When to Use What
| Scenario | Solution |
|---|---|
| Employees accessing multiple AWS accounts | IAM Identity Center |
| EC2 instance calling AWS APIs | IAM Role with instance profile |
| Lambda function accessing DynamoDB | IAM execution role |
| Partner company accessing your S3 bucket | Cross-account IAM role |
| Mobile app users uploading to S3 | Amazon Cognito |
| 10,000 corporate users need AWS access | Federation with SAML or IAM Identity Center |
| Prevent any account from deleting CloudTrail | SCP in AWS Organizations |
| Delegate IAM admin with guardrails | Permission boundaries |
| Emergency root access only | Root user with MFA, locked away |
