AWS Identity and Access Management (IAM)
Chapter 3: AWS Identity and Access Management (IAM)
Section titled “Chapter 3: AWS Identity and Access Management (IAM)”Mastering Security and Access Control in AWS
Section titled “Mastering Security and Access Control in AWS”3.1 Overview
Section titled “3.1 Overview”IAM is the foundation of AWS security, enabling you to control who can do what in your AWS environment.
IAM Core Components+------------------------------------------------------------------+| || +------------------------+ || | IAM Service | || +------------------------+ || | || +--------------------+--------------------+ || | | | || v v v || +----------+ +----------+ +----------+ || | Users | | Groups | | Roles | || | | | | | | || | - People | | - User | | - AWS | || | who | | groups | | services| || | login | | - Policy | | - Cross- | || | | | attach | | account | || +----------+ +----------+ +----------+ || | | | || +--------------------+--------------------+ || | || v || +------------------------+ || | Policies | || | | || | - Identity-based | || | - Resource-based | || | - Permission | || | boundaries | || +------------------------+ || |+------------------------------------------------------------------+3.2 IAM Principals
Section titled “3.2 IAM Principals”Principal Types
Section titled “Principal Types” IAM Principals Hierarchy+------------------------------------------------------------------+| || IAM Principals || ============================================================ || || 1. Root User (Account Owner) || +----------------------------------------------------------+ || | - Created with AWS account | || | - Has full access to all resources | || | - Should NOT be used for daily tasks | || | - Enable MFA immediately! | || +----------------------------------------------------------+ || || 2. IAM Users || +----------------------------------------------------------+ || | - Represent people or applications | || | - Have long-term credentials (username/password) | || | - Can have access keys for programmatic access | || | - Should be in groups for easier management | || +----------------------------------------------------------+ || || 3. IAM Roles || +----------------------------------------------------------+ || | - Temporary credentials | || | - No long-term credentials | || | - Assumed by users, services, or applications | || | - Cross-account access | || +----------------------------------------------------------+ || || 4. Federated Users || +----------------------------------------------------------+ || | - External identity providers | || | - AWS SSO (IAM Identity Center) | || | - SAML 2.0 (Active Directory, Okta, etc.) | || | - Web Identity (Amazon Cognito, Google, Facebook) | || +----------------------------------------------------------+ || |+------------------------------------------------------------------+3.3 IAM Users Deep Dive
Section titled “3.3 IAM Users Deep Dive”User Management Architecture
Section titled “User Management Architecture” IAM User Structure+------------------------------------------------------------------+| || +------------------------+ || | IAM User | || | (developer@company) | || +------------------------+ || | || +-----------------+-----------------+ || | | || v v || +----------------+ +----------------+ || | Console Login | | Access Keys | || | | | | || | - Username | | - Access Key ID| || | - Password | | - Secret Key | || | - MFA (rec.) | | | || +----------------+ +----------------+ || | | || v v || +----------------+ +----------------+ || | AWS Console | | CLI/SDK/API | || | (Web UI) | | (Programmatic) | || +----------------+ +----------------+ || || User Security Best Practices: || +----------------------------------------------------------+ || | 1. Require MFA for console access | || | 2. Enforce password policy | || | 3. Rotate access keys regularly | || | 4. Use groups instead of attaching policies to users | || | 5. Remove unused users and credentials | || +----------------------------------------------------------+ || |+------------------------------------------------------------------+User Creation Flow
Section titled “User Creation Flow” IAM User Creation Process+------------------------------------------------------------------+| || Step 1: Create User || +----------------------------------------------------------+ || | aws iam create-user \ | || | --user-name developer-john \ | || | --path /developers/ | || +----------------------------------------------------------+ || | || v || Step 2: Configure Login Profile || +----------------------------------------------------------+ || | aws iam create-login-profile \ | || | --user-name developer-john \ | || | --password TempPassword123! \ | || | --password-reset-required | || +----------------------------------------------------------+ || | || v || Step 3: Create Access Keys (Optional) || +----------------------------------------------------------+ || | aws iam create-access-key \ | || | --user-name developer-john | || +----------------------------------------------------------+ || | || v || Step 4: Add to Group || +----------------------------------------------------------+ || | aws iam add-user-to-group \ | || | --user-name developer-john \ | || | --group-name Developers | || +----------------------------------------------------------+ || | || v || Step 5: Enable MFA || +----------------------------------------------------------+ || | aws iam enable-mfa-device \ | || | --user-name developer-john \ | || | --serial-number arn:aws:iam::123456789012:mfa/john \ | || | --authentication-code1 123456 \ | || | --authentication-code2 789012 | || +----------------------------------------------------------+ || |+------------------------------------------------------------------+3.4 IAM Groups
Section titled “3.4 IAM Groups”Group-Based Access Management
Section titled “Group-Based Access Management” IAM Groups Structure+------------------------------------------------------------------+| || +------------------------+ || | Organization | || +------------------------+ || | || +----------+----------+----------+----------+ || | | | | | || v v v v v || +--------+ +--------+ +--------+ +--------+ +--------+ || | Admins | | DevOps | |Develop-| | DBA | |Auditors| || | | | | | ers | | | | | || +--------+ +--------+ +--------+ +--------+ +--------+ || | | | | | || v v v v v || +--------+ +--------+ +--------+ +--------+ +--------+ || |Admin | |EC2, | |EC2, | |RDS, | |Read- | || |Policy | |S3, | |S3, | |Dynamo- | |Only | || | | |Lambda, | |Lambda | |DB | |Policy | || | | |CloudFor-| | | | | | | || | | |mation | | | | | | | || +--------+ +--------+ +--------+ +--------+ +--------+ || || Benefits of Groups: || +----------------------------------------------------------+ || | - Easier policy management | || | - Consistent permissions across team members | || | - Quick onboarding/offboarding | || | - Audit-friendly | || +----------------------------------------------------------+ || |+------------------------------------------------------------------+3.5 IAM Roles
Section titled “3.5 IAM Roles”Role Types and Use Cases
Section titled “Role Types and Use Cases” IAM Role Types+------------------------------------------------------------------+| || 1. AWS Service Roles || +----------------------------------------------------------+ || | Service: EC2 | || | Role: EC2InstanceProfile | || | Purpose: Allow EC2 to access S3, DynamoDB, etc. | || | | || | +--------+ +--------+ +--------+ | || | | EC2 | --> | Role | --> | S3 | | || | +--------+ +--------+ +--------+ | || +----------------------------------------------------------+ || || 2. Cross-Account Roles || +----------------------------------------------------------+ || | Account A (Dev) Account B (Prod) | || | +--------+ +--------+ | || | | Dev | Assume | Prod | | || | | User | -----------> | Role | | || | +--------+ Role +--------+ | || | | || | Use Case: Dev team needs read access to Prod resources | || +----------------------------------------------------------+ || || 3. AWS Service-Linked Roles || +----------------------------------------------------------+ || | Predefined by AWS services | || | Cannot be modified | || | Examples: | || | - AWSServiceRoleForEC2Spot | || | - AWSServiceRoleForAutoScaling | || | - AWSServiceRoleForRDS | || +----------------------------------------------------------+ || || 4. Web Identity Roles || +----------------------------------------------------------+ || | External Identity Provider | || | +--------+ +--------+ | || | | Google | Federate | AWS | | || | | User | -----------> | Role | | || | +--------+ via OIDC +--------+ | || +----------------------------------------------------------+ || |+------------------------------------------------------------------+Role Assumption Flow
Section titled “Role Assumption Flow” Role Assumption Process+------------------------------------------------------------------+| || Step 1: User/Service Requests Role || +----------------------------------------------------------+ || | User: developer@company | || | Wants to assume: CrossAccountAdminRole | || +----------------------------------------------------------+ || | || v || Step 2: STS Verify Permissions || +----------------------------------------------------------+ || | Check: Does user have sts:AssumeRole permission? | || | Check: Does role trust policy allow this user? | || +----------------------------------------------------------+ || | || v || Step 3: Generate Temporary Credentials || +----------------------------------------------------------+ || | Returns: | || | - AccessKeyId: AKIAIOSFODNN7EXAMPLE | || | - SecretAccessKey: wJalrXUtnFEMI/K7MDENG/... | || | - SessionToken: AQoDYXdzEJr... | || | - Expiration: 2026-02-16T12:00:00Z | || +----------------------------------------------------------+ || | || v || Step 4: Use Temporary Credentials || +----------------------------------------------------------+ || | User can now access resources defined in role policy | || | Credentials expire after session duration | || +----------------------------------------------------------+ || |+------------------------------------------------------------------+3.6 IAM Policies
Section titled “3.6 IAM Policies”Policy Types
Section titled “Policy Types” IAM Policy Types+------------------------------------------------------------------+| || 1. Identity-Based Policies (Attached to Principals) || +----------------------------------------------------------+ || | Managed Policies (AWS or Customer) | || | +----------------------------------------------------+ | || | | - Reusable across users/roles | | || | | - Version controlled | | || | | - AWS Managed: AdministratorAccess, PowerUser... | | || | +----------------------------------------------------+ | || | | || | Inline Policies | || | +----------------------------------------------------+ | || | | - Embedded in user/role/group | | || | | - Deleted when principal is deleted | | || | | - Use for one-off permissions | | || | +----------------------------------------------------+ | || +----------------------------------------------------------+ || || 2. Resource-Based Policies (Attached to Resources) || +----------------------------------------------------------+ || | Examples: | || | - S3 Bucket Policy | || | - SQS Queue Policy | || | - Lambda Function Policy | || | - SNS Topic Policy | || | | || | Can specify WHO can access the resource | || +----------------------------------------------------------+ || || 3. Permission Boundaries || +----------------------------------------------------------+ || | - Sets maximum permissions for a principal | || | - Used with SCPs for permission boundaries | || | - Does NOT grant permissions | || +----------------------------------------------------------+ || || 4. Service Control Policies (SCPs) || +----------------------------------------------------------+ || | - AWS Organizations feature | || | - Sets permission guardrails | || | - Applied to OUs or accounts | || +----------------------------------------------------------+ || |+------------------------------------------------------------------+Policy Document Structure
Section titled “Policy Document Structure”{ "Version": "2012-10-17", // Policy version (always use this) "Id": "S3ReadPolicy", // Optional identifier "Statement": [ // Array of statements { "Sid": "AllowS3ReadAccess", // Optional statement ID "Effect": "Allow", // Allow or Deny "Principal": { // Who the policy applies to "AWS": "arn:aws:iam::123456789012:user/developer" }, "Action": [ // What actions "s3:GetObject", "s3:ListBucket" ], "Resource": [ // Which resources "arn:aws:s3:::my-bucket", "arn:aws:s3:::my-bucket/*" ], "Condition": { // Optional conditions "IpAddress": { "aws:SourceIp": "192.0.2.0/24" } } } ]}Policy Evaluation Logic
Section titled “Policy Evaluation Logic” Policy Evaluation Flow+------------------------------------------------------------------+| || Start: Request Made || | || v || +---------------------+ || | Explicit Deny? | || | (Any policy) | || +----------+----------+ || | || +------------+------------+ || | | || v v || (Yes) (No) || | | || v v || +----------+ +---------------------+ || | DENY | | Explicit Allow? | || | Request | +----------+----------+ || +----------+ | || +---------+---------+ || | | || v v || (Yes) (No) || | | || v v || +----------+ +------------------+ || | ALLOW | | Default Deny | || | Request | | (Implicit) | || +----------+ +------------------+ || || Order of Evaluation: || 1. Explicit DENY in any policy -> DENY || 2. Explicit ALLOW in any policy -> ALLOW || 3. No explicit ALLOW -> IMPLICIT DENY || |+------------------------------------------------------------------+3.7 Common Policy Patterns
Section titled “3.7 Common Policy Patterns”Pattern 1: Read-Only Access
Section titled “Pattern 1: Read-Only Access”{ "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Action": [ "s3:Get*", "s3:List*" ], "Resource": [ "arn:aws:s3:::my-bucket", "arn:aws:s3:::my-bucket/*" ] } ]}Pattern 2: MFA-Required Policy
Section titled “Pattern 2: MFA-Required Policy”{ "Version": "2012-10-17", "Statement": [ { "Sid": "AllowAllWithMFA", "Effect": "Allow", "Action": "*", "Resource": "*", "Condition": { "Bool": { "aws:MultiFactorAuthPresent": "true" } } }, { "Sid": "DenyWithoutMFA", "Effect": "Deny", "NotAction": [ "iam:GetUser", "iam:ListMFADevices", "iam:EnableMFADevice" ], "Resource": "*", "Condition": { "Bool": { "aws:MultiFactorAuthPresent": "false" } } } ]}Pattern 3: IP-Based Restriction
Section titled “Pattern 3: IP-Based Restriction”{ "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Action": "*", "Resource": "*", "Condition": { "IpAddress": { "aws:SourceIp": [ "192.0.2.0/24", "203.0.113.0/24" ] } } } ]}Pattern 4: Time-Based Access
Section titled “Pattern 4: Time-Based Access”{ "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Action": "*", "Resource": "*", "Condition": { "DateGreaterThan": { "aws:CurrentTime": "2026-02-01T09:00:00Z" }, "DateLessThan": { "aws:CurrentTime": "2026-02-01T18:00:00Z" } } } ]}Pattern 5: Cross-Account Access
Section titled “Pattern 5: Cross-Account Access”// Trust Policy (in Account B - Prod){ "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Principal": { "AWS": "arn:aws:iam::ACCOUNT-A-ID:root" }, "Action": "sts:AssumeRole", "Condition": { "StringEquals": { "sts:ExternalId": "unique-external-id" } } } ]}
// Permission Policy (in Account B - Prod){ "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Action": [ "s3:GetObject", "s3:ListBucket" ], "Resource": [ "arn:aws:s3:::prod-bucket", "arn:aws:s3:::prod-bucket/*" ] } ]}3.8 IAM Security Best Practices
Section titled “3.8 IAM Security Best Practices” IAM Security Checklist+------------------------------------------------------------------+| || 1. Root Account Security || +----------------------------------------------------------+ || | [ ] Lock away root credentials | || | [ ] Enable MFA on root account | || | [ ] Don't use root for daily tasks | || | [ ] Delete root access keys | || +----------------------------------------------------------+ || || 2. User Management || +----------------------------------------------------------+ || | [ ] Use groups for permission assignment | || | [ ] Require MFA for console access | || | [ ] Enforce strong password policy | || | [ ] Rotate credentials regularly | || | [ ] Remove unused users | || +----------------------------------------------------------+ || || 3. Role Management || +----------------------------------------------------------+ || | [ ] Use roles for cross-account access | || | [ ] Use roles for EC2/Lambda services | || | [ ] Implement external ID for third-party | || | [ ] Set appropriate session duration | || +----------------------------------------------------------+ || || 4. Policy Management || +----------------------------------------------------------+ || | [ ] Follow least privilege principle | || | [ ] Use managed policies for reuse | || | [ ] Use conditions for additional security | || | [ ] Regular policy review and audit | || +----------------------------------------------------------+ || || 5. Monitoring & Auditing || +----------------------------------------------------------+ || | [ ] Enable CloudTrail | || | [ ] Use IAM Access Analyzer | || | [ ] Set up IAM credential reports | || | [ ] Monitor for unused permissions | || +----------------------------------------------------------+ || |+------------------------------------------------------------------+Least Privilege Implementation
Section titled “Least Privilege Implementation” Least Privilege Approach+------------------------------------------------------------------+| || BAD: Too Permissive || +----------------------------------------------------------+ || | { | || | "Effect": "Allow", | || | "Action": "*", <-- Allows EVERYTHING! | || | "Resource": "*" <-- On ALL resources! | || | } | || +----------------------------------------------------------+ || || GOOD: Least Privilege || +----------------------------------------------------------+ || | { | || | "Effect": "Allow", | || | "Action": [ | || | "s3:GetObject", <-- Only specific actions | || | "s3:ListBucket" | || | ], | || | "Resource": [ | || | "arn:aws:s3:::my-bucket", <-- Only specific bucket| || | "arn:aws:s3:::my-bucket/*" | || | ] | || | } | || +----------------------------------------------------------+ || || Process to Determine Least Privilege: || +----------------------------------------------------------+ || | 1. Start with no permissions | || | 2. Identify required actions | || | 3. Add minimum required permissions | || | 4. Test and iterate | || | 5. Use IAM Access Analyzer to verify | || +----------------------------------------------------------+ || |+------------------------------------------------------------------+3.9 IAM Access Analyzer
Section titled “3.9 IAM Access Analyzer” IAM Access Analyzer+------------------------------------------------------------------+| || Purpose: Identify resources shared with external entities || || +----------------------------------------------------------+ || | Access Analyzer | || | | || | Scans: | || | - S3 Bucket Policies | || | - IAM Roles (trust policies) | || | - KMS Key Policies | || | - Lambda Function Policies | || | - SQS Queue Policies | || | | || | Findings: | || | +------------------+------------------+ | || | | Resource | Shared With | | || | +------------------+------------------+ | || | | s3://my-bucket | Account: 999999 | | || | | Role: CrossAcct | Account: 888888 | | || | | KMS: my-key | Public: * | <-- ALERT! | || | +------------------+------------------+ | || +----------------------------------------------------------+ || || Actions: || +----------------------------------------------------------+ || | 1. Review findings | || | 2. Verify intended or unintended | || | 3. Remediate unintended access | || | 4. Archive resolved findings | || +----------------------------------------------------------+ || |+------------------------------------------------------------------+3.10 Practical Commands
Section titled “3.10 Practical Commands”AWS CLI - IAM Operations
Section titled “AWS CLI - IAM Operations”# List all usersaws iam list-users --query 'Users[*].UserName' --output table
# Create a new useraws iam create-user --user-name developer-john
# Create access keys for a useraws iam create-access-key --user-name developer-john
# Create a groupaws iam create-group --group-name Developers
# Add user to groupaws iam add-user-to-group --user-name developer-john --group-name Developers
# Attach managed policy to groupaws iam attach-group-policy \ --group-name Developers \ --policy-arn arn:aws:iam::aws:policy/PowerUserAccess
# Create a role with trust policyaws iam create-role \ --role-name EC2InstanceRole \ --assume-role-policy-document file://trust-policy.json
# Create instance profileaws iam create-instance-profile --instance-profile-name EC2InstanceProfile
# Add role to instance profileaws iam add-role-to-instance-profile \ --role-name EC2InstanceRole \ --instance-profile-name EC2InstanceProfile
# Assume a roleaws sts assume-role \ --role-arn arn:aws:iam::123456789012:role/CrossAccountRole \ --role-session-name "DevSession"
# Get credential reportaws iam get-credential-report --query 'Content' --output text | base64 --decode
# List MFA devicesaws iam list-mfa-devices --user-name developer-john
# Enable MFA deviceaws iam enable-mfa-device \ --user-name developer-john \ --serial-number arn:aws:iam::123456789012:mfa/john-device \ --authentication-code1 123456 \ --authentication-code2 789012Python/boto3 Example
Section titled “Python/boto3 Example”import boto3import json
# Initialize IAM clientiam = boto3.client('iam')
# Create a useruser = iam.create_user(UserName='developer-john')print(f"Created user: {user['User']['UserName']}")
# Create a groupgroup = iam.create_group(GroupName='Developers')
# Attach policy to groupiam.attach_group_policy( GroupName='Developers', PolicyArn='arn:aws:iam::aws:policy/PowerUserAccess')
# Add user to groupiam.add_user_to_group( UserName='developer-john', GroupName='Developers')
# Create access keyskeys = iam.create_access_key(UserName='developer-john')print(f"Access Key ID: {keys['AccessKey']['AccessKeyId']}")print(f"Secret Access Key: {keys['AccessKey']['SecretAccessKey']}")
# Create a roletrust_policy = { "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Principal": { "Service": "ec2.amazonaws.com" }, "Action": "sts:AssumeRole" } ]}
role = iam.create_role( RoleName='EC2InstanceRole', AssumeRolePolicyDocument=json.dumps(trust_policy))
# List all usersusers = iam.list_users()for user in users['Users']: print(f"User: {user['UserName']}, Created: {user['CreateDate']}")3.11 IAM Troubleshooting
Section titled “3.11 IAM Troubleshooting”Common Issues and Solutions
Section titled “Common Issues and Solutions” IAM Troubleshooting Guide+------------------------------------------------------------------+| || Issue 1: "Access Denied" Error || +----------------------------------------------------------+ || | Possible Causes: | || | - Missing policy | || | - Explicit deny | || | - Condition not met | || | - Resource ARN incorrect | || | | || | Debug Steps: | || | 1. Check IAM policy simulator | || | 2. Review CloudTrail for denied calls | || | 3. Verify resource ARNs | || | 4. Check conditions | || +----------------------------------------------------------+ || || Issue 2: "Not authorized to assume role" || +----------------------------------------------------------+ || | Possible Causes: | || | - Missing sts:AssumeRole permission | || | - Trust policy doesn't include user | || | - External ID mismatch | || | | || | Debug Steps: | || | 1. Check user has sts:AssumeRole | || | 2. Verify trust policy Principal | || | 3. Check for ExternalId condition | || +----------------------------------------------------------+ || || Issue 3: EC2 instance can't access S3 || +----------------------------------------------------------+ || | Possible Causes: | || | - No instance profile attached | || | - Role doesn't have S3 permissions | || | - S3 bucket policy denies access | || | | || | Debug Steps: | || | 1. Check instance has IAM role attached | || | 2. Verify role has S3 permissions | || | 3. Check S3 bucket policy | || +----------------------------------------------------------+ || |+------------------------------------------------------------------+3.12 Why This Matters in DevOps/SRE
Section titled “3.12 Why This Matters in DevOps/SRE”IAM is the single most critical AWS service for DevOps and SRE. Every permission error, every security breach, and every compliance audit starts and ends with IAM.
IAM in DevOps Daily Work+------------------------------------------------------------------+| || DevOps IAM Responsibilities: || || 1. CI/CD Pipeline Permissions || +----------------------------------------------------------+ || | - CodeBuild/GitHub Actions need IAM roles | || | - Least privilege for deployment roles | || | - Separate roles for build vs deploy stages | || +----------------------------------------------------------+ || || 2. Infrastructure Automation || +----------------------------------------------------------+ || | - Terraform/CloudFormation need broad permissions | || | - Use permission boundaries to limit scope | || | - Cross-account deployment roles | || +----------------------------------------------------------+ || || 3. Incident Response || +----------------------------------------------------------+ || | - Revoking compromised credentials immediately | || | - Creating break-glass access procedures | || | - Auditing IAM changes via CloudTrail | || +----------------------------------------------------------+ || || 4. Team Onboarding/Offboarding || +----------------------------------------------------------+ || | - Automating user creation with correct group membership| || | - Enforcing MFA enrollment | || | - Immediate access revocation when someone leaves | || +----------------------------------------------------------+ || |+------------------------------------------------------------------+3.13 Linux Systems Perspective
Section titled “3.13 Linux Systems Perspective”IAM Management from Arch Linux
Section titled “IAM Management from Arch Linux”# Install required tools on Arch Linuxsudo pacman -S aws-cli-v2 jqyay -S aws-vault # Secure credential management
# aws-vault setup (recommended over plain credentials)aws-vault add default# Enter Access Key ID: ...# Enter Secret Access Key: ...
# Use aws-vault for all operations (credentials never touch disk)aws-vault exec default -- aws sts get-caller-identity
# IAM audit script - find users without MFA#!/bin/bash# Save as ~/bin/iam-audit.shecho "=== IAM Security Audit ==="echo "Timestamp: $(date -u)"echo ""
# Users without MFAecho "--- Users WITHOUT MFA ---"aws iam generate-credential-report > /dev/null 2>&1sleep 3aws iam get-credential-report \ --query 'Content' --output text | \ base64 --decode | \ awk -F, 'NR>1 && $4=="true" && $8=="false" {print $1}'
# Users with old access keys (>90 days)echo ""echo "--- Access Keys Older Than 90 Days ---"CUTOFF=$(date -u -d '90 days ago' '+%Y-%m-%dT%H:%M:%S')for user in $(aws iam list-users --query 'Users[*].UserName' --output text); do aws iam list-access-keys --user-name "$user" \ --query "AccessKeyMetadata[?CreateDate<'$CUTOFF'].[UserName,AccessKeyId,CreateDate]" \ --output text 2>/dev/nulldone
# Unused access keys (not used in 90 days)echo ""echo "--- Unused Access Keys ---"for user in $(aws iam list-users --query 'Users[*].UserName' --output text); do for key in $(aws iam list-access-keys --user-name "$user" --query 'AccessKeyMetadata[*].AccessKeyId' --output text); do last_used=$(aws iam get-access-key-last-used --access-key-id "$key" --query 'AccessKeyLastUsed.LastUsedDate' --output text) if [ "$last_used" == "None" ] || [ "$last_used" \< "$CUTOFF" ]; then echo "User: $user, Key: $key, Last Used: $last_used" fi donedoneAutomating IAM with systemd
Section titled “Automating IAM with systemd”# Systemd timer to rotate access keys automatically[Unit]Description=IAM Access Key Rotation Reminder
[Service]Type=oneshotExecStart=/usr/local/bin/check-key-age.shUser=akash
# /etc/systemd/system/iam-key-rotation.timer[Unit]Description=Check IAM key age weekly
[Timer]OnCalendar=Mon *-*-* 09:00:00Persistent=true
[Install]WantedBy=timers.target
# Enable timersudo systemctl enable --now iam-key-rotation.timer3.14 Real-World Production Scenarios
Section titled “3.14 Real-World Production Scenarios”Scenario 1: Credential Leak Incident Response
Section titled “Scenario 1: Credential Leak Incident Response” Credential Leak Response Playbook+------------------------------------------------------------------+| || Detection: AWS access key found in public GitHub repo || || IMMEDIATE ACTIONS (first 5 minutes): || +----------------------------------------------------------+ || | 1. Deactivate the exposed access key | || | aws iam update-access-key \ | || | --access-key-id AKIAEXAMPLE \ | || | --status Inactive --user-name leaked-user | || | | || | 2. Check CloudTrail for unauthorized API calls | || | aws cloudtrail lookup-events \ | || | --lookup-attributes \ | || | AttributeKey=AccessKeyId,\ | || | AttributeValue=AKIAEXAMPLE | || | | || | 3. Revoke all sessions for the user | || | (Attach deny-all inline policy) | || +----------------------------------------------------------+ || || INVESTIGATION (next 30 minutes): || +----------------------------------------------------------+ || | 1. Check what resources were accessed/created | || | 2. Look for new IAM users/roles created by attacker | || | 3. Check for cryptocurrency mining instances | || | 4. Review S3 buckets for data exfiltration | || | 5. Check for Lambda functions (common attack vector) | || +----------------------------------------------------------+ || || REMEDIATION: || +----------------------------------------------------------+ || | 1. Delete the compromised access key | || | 2. Create new key and rotate in applications | || | 3. Delete any unauthorized resources | || | 4. Enable GuardDuty if not already active | || | 5. Write postmortem and update procedures | || +----------------------------------------------------------+ || |+------------------------------------------------------------------+Scenario 2: Least Privilege for CI/CD Pipeline
Section titled “Scenario 2: Least Privilege for CI/CD Pipeline”// Terraform deployment role - least privilege{ "Version": "2012-10-17", "Statement": [ { "Sid": "TerraformStateAccess", "Effect": "Allow", "Action": [ "s3:GetObject", "s3:PutObject", "s3:DeleteObject" ], "Resource": "arn:aws:s3:::terraform-state-bucket/*" }, { "Sid": "TerraformStateLock", "Effect": "Allow", "Action": [ "dynamodb:GetItem", "dynamodb:PutItem", "dynamodb:DeleteItem" ], "Resource": "arn:aws:dynamodb:*:*:table/terraform-locks" }, { "Sid": "DeploymentPermissions", "Effect": "Allow", "Action": [ "ec2:*", "ecs:*", "ecr:*", "elasticloadbalancing:*", "autoscaling:*", "cloudwatch:*", "logs:*", "sns:*" ], "Resource": "*", "Condition": { "StringEquals": { "aws:RequestedRegion": ["us-east-1", "us-west-2"] } } }, { "Sid": "DenyDangerous", "Effect": "Deny", "Action": [ "iam:CreateUser", "iam:DeleteUser", "iam:CreateAccessKey", "organizations:*" ], "Resource": "*" } ]}3.15 Troubleshooting Guide
Section titled “3.15 Troubleshooting Guide”| Issue | Cause | Solution |
|---|---|---|
| ”Access Denied” on API call | Missing permission in policy | Use IAM Policy Simulator or CloudTrail to identify |
| Cannot assume role | Trust policy doesn’t allow your principal | Check the role’s trust policy |
| Instance can’t access S3 | No instance profile attached | Attach IAM role via instance profile |
| MFA not working | Clock skew on MFA device | Resync MFA device in IAM console |
| Cross-account access denied | External ID mismatch or missing | Verify external ID in trust policy |
| Policy too large | Exceeds 6,144 character limit | Use managed policies or split into multiple policies |
# Debug IAM issues from terminal
# Check your current identityaws sts get-caller-identity
# Simulate a policy (test permissions without executing)aws iam simulate-principal-policy \ --policy-source-arn arn:aws:iam::123456789012:user/developer \ --action-names s3:GetObject \ --resource-arns arn:aws:s3:::my-bucket/file.txt
# Check what permissions a role hasaws iam list-attached-role-policies --role-name MyRoleaws iam list-role-policies --role-name MyRole # inline policies
# Find the last time an access key was usedaws iam get-access-key-last-used --access-key-id AKIAEXAMPLE
# Decode authorization failure messageaws sts decode-authorization-message --encoded-message "<encoded message>" | jq '.DecodedMessage | fromjson'3.16 Common Mistakes & Anti-Patterns
Section titled “3.16 Common Mistakes & Anti-Patterns” IAM Anti-Patterns+------------------------------------------------------------------+| || ❌ Mistake 1: Using Root Account for Daily Work || +----------------------------------------------------------+ || | Problem: Root has unrestricted access, no MFA enforced | || | Impact: Single compromise = full account takeover | || | Fix: Create admin IAM user, lock root, enable MFA | || +----------------------------------------------------------+ || || ❌ Mistake 2: Wildcard Permissions (Action: "*") || +----------------------------------------------------------+ || | Problem: Giving "*" on actions or resources | || | Impact: Blast radius of compromise is entire account | || | Fix: Use IAM Access Analyzer to scope down permissions | || +----------------------------------------------------------+ || || ❌ Mistake 3: Long-lived Access Keys || +----------------------------------------------------------+ || | Problem: Access keys that never rotate, shared in Slack | || | Impact: Keys leak into repos, logs, or chat history | || | Fix: Use IAM roles + STS, rotate keys every 90 days | || +----------------------------------------------------------+ || || ❌ Mistake 4: Not Using Permission Boundaries || +----------------------------------------------------------+ || | Problem: Delegated admins can escalate their own perms | || | Impact: Users can grant themselves more access | || | Fix: Set permission boundaries on all delegated users | || +----------------------------------------------------------+ || || ❌ Mistake 5: Embedding Credentials in Application Code || +----------------------------------------------------------+ || | Problem: AWS keys hardcoded in source code | || | Impact: Keys exposed in version control | || | Fix: Use IAM roles, Secrets Manager, or env variables | || +----------------------------------------------------------+ || |+------------------------------------------------------------------+3.17 Interview Questions
Section titled “3.17 Interview Questions”Conceptual Questions
Section titled “Conceptual Questions”-
Q: Explain the IAM policy evaluation logic.
- A: AWS evaluates all policies. (1) If any policy has an explicit DENY, the request is denied. (2) If any policy has an explicit ALLOW, the request is allowed. (3) If no policy explicitly allows, the request is implicitly denied. Additionally, SCPs from Organizations and permission boundaries further constrain what’s allowed.
-
Q: What’s the difference between IAM users and IAM roles?
- A: Users have long-term credentials (passwords, access keys) for people/applications. Roles provide temporary credentials via STS and are assumed by services, cross-account access, or federated users. In DevOps, prefer roles over users whenever possible.
-
Q: How do you implement least privilege at scale?
- A: Start with zero permissions and add as needed. Use IAM Access Analyzer to identify unused permissions. Use CloudTrail to audit actual API calls. Implement permission boundaries. Use AWS managed policies as starting points. Review permissions quarterly.
Scenario-Based Questions
Section titled “Scenario-Based Questions”-
Q: An EC2 instance needs to access an S3 bucket in another account. How?
- A: Two approaches: (1) Resource-based: Add a bucket policy in Account B allowing the EC2 role ARN from Account A. (2) Role-based: Create a cross-account role in Account B with S3 permissions; have the EC2 instance assume that role via STS. The role-based approach is preferred for centralized control.
-
Q: A developer accidentally committed AWS credentials to GitHub. What do you do?
- A: Immediately: (1) Deactivate the key, (2) Check CloudTrail for unauthorized usage, (3) Revoke all active sessions. Then: (4) Delete the key and create a new one, (5) Clean up any unauthorized resources, (6) Remove credentials from git history using
git filter-branchor BFG, (7) Enable GuardDuty, (8) Conduct postmortem.
- A: Immediately: (1) Deactivate the key, (2) Check CloudTrail for unauthorized usage, (3) Revoke all active sessions. Then: (4) Delete the key and create a new one, (5) Clean up any unauthorized resources, (6) Remove credentials from git history using
3.18 Exam Tips
Section titled “3.18 Exam Tips”- Root Account: Never use for daily tasks; always enable MFA
- IAM Users vs Roles: Users for people, roles for services and temporary access
- Policy Evaluation: Explicit deny > Explicit allow > Implicit deny
- Least Privilege: Always grant minimum required permissions
- Groups: Use groups to manage permissions, not individual users
- MFA: Required for sensitive operations, can be enforced via policy
- Cross-Account: Use roles, not users, for cross-account access
- Instance Profiles: Required for EC2 to assume roles
- Access Analyzer: Identifies resources shared externally
Next Chapter
Section titled “Next Chapter”Last Updated: March 2026