Identity & Access Management
IAM, Identity Center, permission boundaries, and least privilege principles
AWS Identity & Access Management Fundamentals
Master AWS Identity & Access Management (IAM) with free flashcards and interactive practice to solidify your understanding. This lesson covers IAM users, groups, roles, policies, multi-factor authentication, and security best practicesโessential concepts for securing AWS resources and passing AWS certification exams.
Welcome ๐
Welcome to the foundation of AWS security! Identity & Access Management (IAM) is the service that controls who can access what in your AWS environment. Whether you're managing a single developer account or a multi-team enterprise infrastructure, IAM is your first line of defense and the cornerstone of AWS security architecture.
Think of IAM as the security guard, keycard system, and access logs for your AWS accountโall rolled into one powerful service. Every AWS resource interaction goes through IAM's permission checks, making it absolutely critical to understand.
๐ก Did you know? IAM is one of the few AWS services that's completely freeโthere's no charge for creating users, groups, roles, or policies, no matter how many you have!
Core Concepts ๐
What is IAM?
IAM (Identity & Access Management) is a web service that helps you securely control access to AWS resources. IAM enables you to manage authentication (who can sign in) and authorization (what they can do) for your AWS account.
๐ฏ IAM's Core Purpose
| Authentication | Verify identity ("Who are you?") |
| Authorization | Grant permissions ("What can you do?") |
| Audit | Track activity ("What did you do?") |
The Four Pillars of IAM ๐๏ธ
IAM revolves around four fundamental components:
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โ IAM COMPONENT HIERARCHY โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโค โ โ โ ๐ค USERS โ Individual people or apps โ โ โ โ โ โโโโ ๐ฅ GROUPS (collection of users) โ โ โ โ โ โโโโ ๐ POLICIES (permissions) โ โ โ โ โ โโโโ ๐ญ ROLES โ โ (temporary access) โ โ โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
1. IAM Users ๐ค
An IAM user represents a person or application that interacts with AWS. Each user has:
- Unique credentials (username/password for console, access keys for API/CLI)
- Individual permissions (what they can do)
- Permanent identity (exists until deleted)
Real-world analogy: Think of an IAM user like an employee badge at a companyโit uniquely identifies someone and determines which doors they can open.
{
"UserName": "alice-developer",
"UserId": "AIDACKCEVSQ6C2EXAMPLE",
"Arn": "arn:aws:iam::123456789012:user/alice-developer",
"CreateDate": "2024-01-15T10:30:00Z"
}
Best Practice: Create individual IAM users for each personโnever share credentials! Even in small teams, each developer should have their own user account.
2. IAM Groups ๐ฅ
An IAM group is a collection of users. Groups let you manage permissions for multiple users at once.
Key characteristics:
- Groups contain users (not other groups)
- Users can belong to multiple groups
- Groups cannot be nested
- Groups don't have credentialsโonly users do
Example Organization:
โโโโโโโโโโโโโโโ โโโโโโโโโโโโโโโ โโโโโโโโโโโโโโโ
โ Developers โ โ Admins โ โ Analysts โ
โโโโโโโโโโโโโโโค โโโโโโโโโโโโโโโค โโโโโโโโโโโโโโโค
โ โข Alice โ โ โข Bob โ โ โข Carol โ
โ โข David โ โ โข Alice โ โ โข Eve โ
โ โข Frank โ โ โ โ โ
โโโโโโโโโโโโโโโ โโโโโโโโโโโโโโโ โโโโโโโโโโโโโโโ
โ โ โ
[Read/Write [Full Access] [Read Only
EC2, S3] Analytics]
Best Practice: Organize users into groups based on job function (Developers, QA, Operations) rather than projects. Attach policies to groups, not individual users.
3. IAM Policies ๐
An IAM policy is a JSON document that defines permissions. Policies answer the question: "What actions are allowed or denied on which resources?"
Policy structure:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"s3:GetObject",
"s3:PutObject"
],
"Resource": "arn:aws:s3:::my-bucket/*"
}
]
}
Policy components:
| Component | Purpose | Example |
|---|---|---|
| Effect | Allow or Deny | "Allow", "Deny" |
| Action | What operations | "s3:GetObject", "ec2:StartInstances" |
| Resource | Which AWS resources | "arn:aws:s3:::bucket-name/*" |
| Condition (optional) | When it applies | IP address, time of day, MFA |
Types of policies:
Managed Policies (AWS or customer-managed)
- Standalone policies you can attach to multiple users/groups/roles
- Reusable and centrally managed
- Example:
AmazonS3ReadOnlyAccess
Inline Policies
- Embedded directly in a single user, group, or role
- Deleted when the identity is deleted
- Use sparinglyโmanaged policies are preferred
๐ง Memory Device: "PARC" - Policy, Action, Resource, Conditionโthe four elements that define access control.
4. IAM Roles ๐ญ
An IAM role is an identity with permissions that can be assumed temporarily. Unlike users, roles don't have permanent credentials.
When to use roles:
ROLE USE CASES โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โ EC2 Instance needs S3 access โ โ โโโโ Attach IAM role to instance โ โ โโโโ No hardcoded credentials! โ โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโค โ Lambda function needs DynamoDB access โ โ โโโโ Lambda execution role โ โ โโโโ Automatic credential rotation โโ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโค โ Cross-account access โ โ โโโโ Dev account โ Prod account โ โ โโโโ Users assume role temporarily โโ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโค โ Federated users (SSO, Active Directory)โ โ โโโโ External identity provider โ โ โโโโ Map to IAM roles automaticallyโโ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
Real-world analogy: A role is like a visitor badge at a company. You're not a permanent employee, but you can temporarily assume visitor privileges to access specific areas. When you leave, the badge goes back.
{
"RoleName": "EC2-S3-Access-Role",
"AssumeRolePolicyDocument": {
"Version": "2012-10-17",
"Statement": [{
"Effect": "Allow",
"Principal": {"Service": "ec2.amazonaws.com"},
"Action": "sts:AssumeRole"
}]
}
}
Trust policy vs Permission policy:
- Trust policy (AssumeRolePolicyDocument): Who can assume this role?
- Permission policy: What can the role do?
Authentication Methods ๐
AWS supports multiple authentication mechanisms:
| Method | Use Case | Security Level |
|---|---|---|
| Username/Password | AWS Management Console | โญโญ (Basic) |
| Access Keys | CLI, SDK, API calls | โญโญ (Basic) |
| MFA | Console + Access keys | โญโญโญโญ (High) |
| SSO/Federation | Enterprise identity systems | โญโญโญโญโญ (Highest) |
Access Keys (Programmatic Access)
Access keys consist of:
- Access Key ID: Like a username (e.g.,
AKIAIOSFODNN7EXAMPLE) - Secret Access Key: Like a password (e.g.,
wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY)
## Configure AWS CLI with access keys
$ aws configure
AWS Access Key ID: AKIAIOSFODNN7EXAMPLE
AWS Secret Access Key: wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY
Default region name: us-east-1
Default output format: json
โ ๏ธ Critical Security Warning: Never commit access keys to version control (GitHub, GitLab). Use environment variables or AWS credential files with restricted permissions.
Multi-Factor Authentication (MFA) ๐ก๏ธ
MFA adds an extra layer of security by requiring:
- Something you know (password)
- Something you have (MFA device)
MFA device options:
- Virtual MFA apps (Google Authenticator, Authy, Microsoft Authenticator)
- Hardware tokens (YubiKey, Gemalto)
- SMS text message (least secure, not recommended)
{
"Effect": "Deny",
"Action": "*",
"Resource": "*",
"Condition": {
"BoolIfExists": {"aws:MultiFactorAuthPresent": "false"}
}
}
This policy denies all actions unless MFA is presentโenforcing MFA for sensitive operations.
Permission Evaluation Logic ๐งฎ
When a user attempts an action, AWS evaluates permissions in this order:
PERMISSION EVALUATION FLOWCHART
โโโโโโโโโโโโโโโโโโโ
โ Request made โ
โโโโโโโโโโฌโโโโโโโโโ
โ
โโโโโโโโโโโโโโโโโโโ
โ Explicit DENY? โโโโโYesโโโโ โ DENIED
โโโโโโโโโโฌโโโโโโโโโ
โ No
โ
โโโโโโโโโโโโโโโโโโโ
โ Explicit ALLOW? โโโโโNoโโโโโ โ DENIED
โโโโโโโโโโฌโโโโโโโโโ (Implicit Deny)
โ Yes
โ
โโโโโโโโโโโโโโโโโโโ
โ โ
ALLOWED โ
โโโโโโโโโโโโโโโโโโโ
Key principle: Explicit Deny always wins!
๐ง Memory Device: "DADI" - Deny Always Dominates, then check for Implicit deny (default).
Detailed Examples ๐ป
Example 1: Creating a Developer with S3 Access
Scenario: You need to give a new developer read/write access to a specific S3 bucket but no access to other AWS services.
Step 1: Create the IAM user
## Using AWS CLI
aws iam create-user --user-name john-developer
Step 2: Create a custom policy
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "ListBucket",
"Effect": "Allow",
"Action": ["s3:ListBucket"],
"Resource": "arn:aws:s3:::project-assets-bucket"
},
{
"Sid": "ReadWriteObjects",
"Effect": "Allow",
"Action": [
"s3:GetObject",
"s3:PutObject",
"s3:DeleteObject"
],
"Resource": "arn:aws:s3:::project-assets-bucket/*"
}
]
}
Step 3: Attach the policy
aws iam put-user-policy \
--user-name john-developer \
--policy-name S3ProjectBucketAccess \
--policy-document file://s3-policy.json
Why this works:
- First statement allows listing bucket contents
- Second statement allows reading, writing, and deleting objects
- Notice the different Resource ARNs: bucket vs. bucket/*
- No other AWS services are accessible
Example 2: EC2 Instance Accessing DynamoDB
Scenario: An EC2 instance running your application needs to read/write to a DynamoDB table. You should never store credentials on the instance.
Step 1: Create an IAM role for EC2
{
"Version": "2012-10-17",
"Statement": [{
"Effect": "Allow",
"Principal": {"Service": "ec2.amazonaws.com"},
"Action": "sts:AssumeRole"
}]
}
This trust policy allows EC2 service to assume the role.
Step 2: Create permission policy for DynamoDB
{
"Version": "2012-10-17",
"Statement": [{
"Effect": "Allow",
"Action": [
"dynamodb:GetItem",
"dynamodb:PutItem",
"dynamodb:UpdateItem",
"dynamodb:Query"
],
"Resource": "arn:aws:dynamodb:us-east-1:123456789012:table/UserData"
}]
}
Step 3: Attach role to EC2 instance
aws iam create-role --role-name EC2-DynamoDB-Role \
--assume-role-policy-document file://trust-policy.json
aws iam put-role-policy --role-name EC2-DynamoDB-Role \
--policy-name DynamoDB-Access \
--policy-document file://dynamodb-policy.json
aws ec2 associate-iam-instance-profile \
--instance-id i-1234567890abcdef0 \
--iam-instance-profile Name=EC2-DynamoDB-Role
What happens:
- EC2 instance automatically receives temporary credentials
- Credentials rotate automatically every few hours
- Application uses AWS SDK without hardcoded keys
- If instance is compromised, credentials expire quickly
Example 3: Cross-Account Access
Scenario: Your production account (Account A: 111111111111) needs to allow developers from the development account (Account B: 222222222222) to deploy code.
In Production Account (111111111111):
{
"Version": "2012-10-17",
"Statement": [{
"Effect": "Allow",
"Principal": {"AWS": "arn:aws:iam::222222222222:root"},
"Action": "sts:AssumeRole",
"Condition": {
"StringEquals": {
"sts:ExternalId": "unique-external-id-12345"
}
}
}]
}
This trust policy allows Account B to assume a role in Account A.
Permission policy (what developers can do in prod):
{
"Version": "2012-10-17",
"Statement": [{
"Effect": "Allow",
"Action": [
"s3:PutObject",
"lambda:UpdateFunctionCode",
"cloudformation:UpdateStack"
],
"Resource": [
"arn:aws:s3:::prod-deployment-bucket/*",
"arn:aws:lambda:us-east-1:111111111111:function:prod-*",
"arn:aws:cloudformation:us-east-1:111111111111:stack/prod-*"
]
}]
}
In Development Account (222222222222):
Developers assume the role:
aws sts assume-role \
--role-arn "arn:aws:iam::111111111111:role/ProdDeploymentRole" \
--role-session-name "deployment-session" \
--external-id "unique-external-id-12345"
They receive temporary credentials valid for 1-12 hours.
๐ก Pro tip: The ExternalId prevents the "confused deputy" problemโit ensures only authorized accounts can assume the role, even if the role ARN is known.
Example 4: Enforcing MFA for Sensitive Operations
Scenario: Allow developers to view resources but require MFA for any modification or deletion.
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "AllowViewingResources",
"Effect": "Allow",
"Action": [
"ec2:Describe*",
"s3:List*",
"s3:Get*",
"rds:Describe*"
],
"Resource": "*"
},
{
"Sid": "RequireMFAForModifications",
"Effect": "Allow",
"Action": [
"ec2:StartInstances",
"ec2:StopInstances",
"ec2:TerminateInstances",
"s3:PutObject",
"s3:DeleteObject",
"rds:DeleteDBInstance"
],
"Resource": "*",
"Condition": {
"Bool": {"aws:MultiFactorAuthPresent": "true"}
}
},
{
"Sid": "DenyAllWithoutMFA",
"Effect": "Deny",
"NotAction": [
"iam:CreateVirtualMFADevice",
"iam:EnableMFADevice",
"iam:GetUser",
"iam:ListMFADevices",
"iam:ListVirtualMFADevices",
"iam:ResyncMFADevice"
],
"Resource": "*",
"Condition": {
"BoolIfExists": {"aws:MultiFactorAuthPresent": "false"}
}
}
]
}
How this works:
- First statement: Read-only access always allowed
- Second statement: Modifications require MFA=true
- Third statement: Denies everything except MFA setup if MFA is absent
This forces users to enable MFA before doing anything destructive.
Common Mistakes โ ๏ธ
1. Using Root Account for Daily Operations
โ Wrong approach:
## Logging in as root@mycompany.com every day
aws s3 ls --profile root
โ Correct approach:
- Create IAM users with appropriate permissions
- Enable MFA on root account
- Store root credentials securely (password manager)
- Only use root for account-level tasks (billing, account closure)
Why: The root account has unrestricted access to everything. If compromised, an attacker can delete your entire AWS infrastructure, rack up massive bills, or steal all data.
2. Hardcoding Access Keys in Code
โ Wrong approach:
import boto3
## NEVER DO THIS!
client = boto3.client(
's3',
aws_access_key_id='AKIAIOSFODNN7EXAMPLE',
aws_secret_access_key='wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY'
)
โ Correct approach:
import boto3
## Uses IAM role credentials automatically
client = boto3.client('s3')
## Or uses AWS CLI configuration
client = boto3.client('s3') # Reads from ~/.aws/credentials
Why: Hardcoded credentials in code often end up in version control (Git), leaked on GitHub, or exposed in logs. Use IAM roles for services, environment variables, or credential files with restricted permissions.
3. Overly Permissive Policies
โ Wrong approach:
{
"Effect": "Allow",
"Action": "*",
"Resource": "*"
}
This grants full access to everythingโworse than root!
โ Correct approach:
{
"Effect": "Allow",
"Action": [
"s3:GetObject",
"s3:PutObject"
],
"Resource": "arn:aws:s3:::specific-bucket/specific-path/*"
}
Principle of Least Privilege: Grant only the minimum permissions needed to perform a task. Start restrictive and add permissions as needed, not the other way around.
4. Not Rotating Access Keys
โ Wrong approach:
- Creating access keys and using them forever
- Never checking key age
- Keeping old keys "just in case"
โ Correct approach:
## Check key age
aws iam list-access-keys --user-name john-developer
## Create new key
aws iam create-access-key --user-name john-developer
## Update applications with new key
## Test thoroughly
## Delete old key
aws iam delete-access-key --user-name john-developer --access-key-id AKIAOLD...
Best practice: Rotate access keys every 90 days. Enable AWS Config rule access-keys-rotated to get automatic compliance checks.
5. Confusing Identity-Based vs Resource-Based Policies
Identity-based policies: Attached to users, groups, or roles
{
"Effect": "Allow",
"Action": "s3:GetObject",
"Resource": "arn:aws:s3:::my-bucket/*"
}
Attached to: User/Group/Role โ "What can this identity do?"
Resource-based policies: Attached to resources (S3 buckets, SQS queues)
{
"Effect": "Allow",
"Principal": {"AWS": "arn:aws:iam::123456789012:user/alice"},
"Action": "s3:GetObject",
"Resource": "arn:aws:s3:::my-bucket/*"
}
Attached to: Resource โ "Who can access this resource?"
Key difference: Resource-based policies specify a Principal (who); identity-based policies don't (they're attached to the "who").
6. Forgetting About Implicit Deny
โ Wrong assumption: "If I don't explicitly deny something, it's allowed."
โ Reality: By default, everything is denied! You must explicitly allow actions.
DEFAULT STATE: โ DENIED
โ
Add ALLOW policy โ โ
ALLOWED
โ
Add DENY policy โ โ DENIED (deny wins)
Security Best Practices ๐ก๏ธ
๐ IAM Security Checklist
| Practice | Why It Matters |
|---|---|
| โ Enable MFA on root account | Prevents account takeover |
| โ Create individual IAM users | Accountability and audit trail |
| โ Use groups for permissions | Easier management at scale |
| โ Grant least privilege | Minimize damage from compromise |
| โ Use roles for applications | No hardcoded credentials |
| โ Enable CloudTrail logging | Track all IAM actions |
| โ Rotate credentials regularly | Limit window of exposure |
| โ Use policy conditions | Context-aware access control |
| โ Review permissions quarterly | Remove unused access |
| โ Use AWS Organizations SCPs | Guardrails across accounts |
IAM Policy Simulator ๐งช
AWS provides a Policy Simulator tool to test policies before deploying:
https://policysim.aws.amazon.com/
Use it to:
- Test if a user can perform a specific action
- Understand why an action was denied
- Validate new policies before attaching them
- Debug permission issues
๐ง Try this: Paste one of the example policies into the Policy Simulator and test different actions. Change "Allow" to "Deny" and see how evaluation changes.
Key Takeaways ๐ฏ
๐ Quick Reference Card
| Concept | Summary |
|---|---|
| IAM User | Permanent identity with credentials (person/app) |
| IAM Group | Collection of users; manages permissions at scale |
| IAM Role | Temporary identity; assumed by users/services |
| IAM Policy | JSON document defining permissions (PARC) |
| Effect | Allow or Deny (Deny always wins) |
| Principal | Who (used in resource-based policies) |
| Action | What operation (service:Operation) |
| Resource | Which AWS resource (ARN) |
| Condition | When/how (IP, MFA, time, etc.) |
| MFA | Two-factor authentication for extra security |
| Access Keys | ID + Secret for programmatic access |
| Trust Policy | Who can assume a role |
| Least Privilege | Minimum permissions needed |
| Implicit Deny | Default state; must explicitly allow |
Core principles to remember:
- Authentication vs Authorization: Who you are vs. what you can do
- Explicit Deny > Explicit Allow > Implicit Deny: Permission evaluation order
- Use Roles for Services: Never hardcode credentials
- Least Privilege Always: Start with minimal access, add as needed
- IAM is Free: No excuse not to implement proper security
- Enable MFA Everywhere: Especially on root and privileged accounts
- Groups for Management: Attach policies to groups, not individual users
- Regular Audits: Review and remove unused permissions quarterly
๐ง Final Memory Device - "IAM SECURE":
- Identify users uniquely
- Allow least privilege
- MFA everywhere
- Separate duties (groups)
- Eliminate root usage
- Check policies with simulator
- Use roles for services
- Rotate credentials
- Enable CloudTrail logging
๐ Further Study
Official AWS Documentation:
- IAM User Guide - Comprehensive reference
- IAM Best Practices - Security recommendations
- IAM Policy Reference - Complete policy syntax guide
Hands-on Practice:
- AWS IAM Policy Simulator - Test policies interactively
- AWS Security Labs - Free hands-on security workshops
Congratulations! You've completed the IAM fundamentals lesson. Understanding IAM is critical for every AWS service you'll useโit's the foundation of cloud security. Practice creating users, groups, roles, and policies in your AWS account (free tier) to solidify these concepts. Remember: security is not an afterthoughtโit's the first thought! ๐