All topics
Cloud · Learning hub

IAM notes for developers

Master IAM with a curated set of 3 developer notes — core concepts, patterns, and interview prep. Maintained by the DevRecall team.

Save this stack to your DevRecallMore Cloud notes
IAM

Policies & Permission Boundaries

AWS IAM: Policies & Permission Boundaries Policy Structure { "Version": "2012-10-17", "Statement": [ { "Sid": "AllowS3ReadOnSpecificBucket", "Effect": "Allow",

AWS IAM: Policies & Permission Boundaries

Policy Structure

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "AllowS3ReadOnSpecificBucket",
      "Effect": "Allow",
      "Action": [
        "s3:GetObject",
        "s3:ListBucket"
      ],
      "Resource": [
        "arn:aws:s3:::my-bucket",
        "arn:aws:s3:::my-bucket/*"
      ]
    },
    {
      "Sid": "DenyDeleteEverywhere",
      "Effect": "Deny",
      "Action": [
        "s3:DeleteObject",
        "s3:DeleteBucket"
      ],
      "Resource": "*"
    },
    {
      "Sid": "AllowEC2InRegion",
      "Effect": "Allow",
      "Action": "ec2:*",
      "Resource": "*",
      "Condition": {
        "StringEquals": {
          "aws:RequestedRegion": "us-east-1"
        }
      }
    },
    {
      "Sid": "AllowResourcesOwnedByUser",
      "Effect": "Allow",
      "Action": "dynamodb:*",
      "Resource": "arn:aws:dynamodb:*:*:table/my-table-${aws:username}"
    }
  ]
}

Common Condition Keys

"Condition": {
  "StringEquals": { "aws:RequestedRegion": "us-east-1" },
  "StringLike": { "s3:prefix": "home/${aws:username}/*" },
  "StringNotEquals": { "aws:PrincipalAccount": "123456789012" },
  "Bool": { "aws:MultiFactorAuthPresent": "true" },
  "NumericLessThan": { "aws:MultiFactorAuthAge": "3600" },
  "IpAddress": { "aws:SourceIp": "203.0.113.0/24" },
  "NotIpAddress": { "aws:SourceIp": "203.0.113.0/24" },
  "ArnEquals": { "aws:PrincipalArn": "arn:aws:iam::123456789012:user/alice" },
  "DateGreaterThan": { "aws:CurrentTime": "2024-01-01T00:00:00Z" }
}

Policy Types

1. Identity-based policies (most common)
   - Attached to users, groups, or roles
   - Managed policies: AWS-managed or customer-managed (reusable)
   - Inline policies: embedded in single identity (avoid — hard to manage)

2. Resource-based policies
   - Attached to resources (S3 bucket policy, SQS, KMS key policy)
   - Grant cross-account access without assuming a role
   - Example: S3 bucket policy allowing specific external account

3. Permission boundaries
   - Maximum permissions a user/role can have
   - Does NOT grant access by itself — must ALSO have identity-based policy
   - Use case: allow devs to create roles but limit what roles they can create

4. Service Control Policies (SCP) — AWS Organizations
   - Applied at Organization/OU/Account level
   - Maximum permissions for ENTIRE account
   - Override nothing at account level — all accounts need both SCP + identity policy

5. Session policies
   - Passed when assuming a role or federating
   - Further restrict temporary credentials

Evaluation order:
  Deny in SCP → explicit Deny in any policy → Allow in all relevant policies

Policy Creation & Management

# Create customer-managed policy
aws iam create-policy   --policy-name S3ReadMyBucket   --policy-document file://policy.json

# Attach to user/group/role
aws iam attach-user-policy   --user-name alice   --policy-arn arn:aws:iam::123456789012:policy/S3ReadMyBucket

# List policies
aws iam list-policies --scope Local   # customer-managed
aws iam list-policies --scope AWS     # AWS-managed
aws iam list-attached-user-policies --user-name alice

# Simulate policy evaluation
aws iam simulate-principal-policy   --policy-source-arn arn:aws:iam::123456789012:user/alice   --action-names s3:GetObject   --resource-arns arn:aws:s3:::my-bucket/file.txt

# IAM Access Analyzer — detect overly permissive policies
aws accessanalyzer create-analyzer   --analyzer-name account-analyzer   --type ACCOUNT
IAM

Best Practices & Advanced Features

AWS IAM: Best Practices & Advanced Features IAM Best Practices Never use root account: create an admin IAM user or use IAM Identity Center. Lock root credential

AWS IAM: Best Practices & Advanced Features

IAM Best Practices

  • Never use root account: create an admin IAM user or use IAM Identity Center. Lock root credentials away.

  • Principle of least privilege: start with minimum permissions, add only what's needed. Use Access Analyzer to find unused permissions.

  • Use roles, not access keys: EC2, Lambda, ECS, etc. can assume roles — no long-lived credentials on instances.

  • Rotate access keys regularly: audit with aws iam generate-credential-report. Keys older than 90 days are a risk.

  • Enable MFA everywhere: require MFA for console access and for assuming sensitive roles via Condition: aws:MultiFactorAuthPresent.

  • Use IAM Identity Center (SSO): centrally manage human access to multiple accounts using your existing identity provider (Okta, Azure AD).

  • Tag IAM resources: helps with cost allocation, auditing, and ABAC (attribute-based access control).

  • Monitor with CloudTrail: all IAM API calls are logged. Set up alerts for root login, policy changes, access key creation.

IAM Identity Center (SSO)

IAM Identity Center replaces per-account IAM users for human access:

Setup:
  1. Enable IAM Identity Center in AWS Organizations management account
  2. Connect identity provider (built-in, Azure AD, Okta, Google Workspace)
  3. Create permission sets (like IAM roles)
  4. Assign users/groups to accounts with permission sets

Benefits:
  - Single sign-on across all AWS accounts
  - No long-lived credentials — temporary credentials via portal or CLI
  - Centralized access review
  - Integrates with standard SAML 2.0 / OIDC IdPs

CLI access with SSO:
  aws configure sso
  aws sso login --profile my-profile
  aws s3 ls --profile my-profile

ABAC — Attribute-Based Access Control

// Grant access based on resource tags matching user tags
// User has tag: Department=Engineering
// Policy: allow access to resources tagged Department=Engineering

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": ["ec2:StartInstances", "ec2:StopInstances"],
      "Resource": "arn:aws:ec2:*:*:instance/*",
      "Condition": {
        "StringEquals": {
          "ec2:ResourceTag/Department": "${aws:PrincipalTag/Department}"
        }
      }
    },
    {
      "Effect": "Allow",
      "Action": "ec2:DescribeInstances",
      "Resource": "*"
    }
  ]
}

Credentials Chain & SDK Behavior

# AWS SDK credential lookup order:
# 1. Environment variables: AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY, AWS_SESSION_TOKEN
# 2. AWS profile (~/.aws/credentials + ~/.aws/config)
# 3. Web identity token (EKS pods via OIDC)
# 4. EC2 instance metadata (role attached to instance)
# 5. ECS task role

# Configure profiles
aws configure --profile dev
# Stored in ~/.aws/credentials and ~/.aws/config
# Use: AWS_PROFILE=dev aws s3 ls
#      aws s3 ls --profile dev

# Assume role profile (auto-refreshes credentials)
# ~/.aws/config:
# [profile prod-readonly]
# role_arn = arn:aws:iam::123456789012:role/ReadOnly
# source_profile = default
# mfa_serial = arn:aws:iam::111122223333:mfa/alice
# role_session_name = alice-prod-session
# duration_seconds = 3600

# Use: aws s3 ls --profile prod-readonly
# SDK will auto-refresh every hour

# Credential report (CSV of all users + key ages)
aws iam generate-credential-report
aws iam get-credential-report --output text --query Content | base64 -d
IAM

Users, Groups & Roles

AWS IAM: Users, Groups & Roles IAM (Identity and Access Management) controls who can do what in AWS. The core entities are: Users (people/apps), Groups (collect

AWS IAM: Users, Groups & Roles

IAM (Identity and Access Management) controls who can do what in AWS. The core entities are: Users (people/apps), Groups (collections of users), Roles (assumed by services or users), and Policies (permission documents).

Users & Groups

# Create user
aws iam create-user --user-name alice

# Create access keys (for programmatic access)
aws iam create-access-key --user-name alice
# Returns: AccessKeyId + SecretAccessKey (save SecretAccessKey — shown only once!)

# Create login profile (console password)
aws iam create-login-profile   --user-name alice   --password "TempPass123!"   --password-reset-required

# Create group and add user
aws iam create-group --group-name Developers
aws iam add-user-to-group --user-name alice --group-name Developers

# Attach policy to group
aws iam attach-group-policy   --group-name Developers   --policy-arn arn:aws:iam::aws:policy/PowerUserAccess

# List users/groups
aws iam list-users
aws iam list-groups
aws iam list-groups-for-user --user-name alice
aws iam list-attached-group-policies --group-name Developers

# Enable MFA for user
aws iam create-virtual-mfa-device   --virtual-mfa-device-name alice-mfa   --outfile QRCode.png   --bootstrap-method QRCodePNG
# Scan QR code, then:
aws iam enable-mfa-device   --user-name alice   --serial-number arn:aws:iam::123456789012:mfa/alice-mfa   --authentication-code1 123456   --authentication-code2 654321

Roles

Roles are assumed temporarily and provide credentials automatically. Use roles instead of long-lived access keys wherever possible.

# Create role (EC2 service can assume this role)
aws iam create-role   --role-name EC2-S3-ReadRole   --assume-role-policy-document '{
    "Version": "2012-10-17",
    "Statement": [{
      "Effect": "Allow",
      "Principal": {"Service": "ec2.amazonaws.com"},
      "Action": "sts:AssumeRole"
    }]
  }'

# Attach policy to role
aws iam attach-role-policy   --role-name EC2-S3-ReadRole   --policy-arn arn:aws:iam::aws:policy/AmazonS3ReadOnlyAccess

# Create instance profile and add role (needed for EC2)
aws iam create-instance-profile --instance-profile-name EC2-S3-ReadProfile
aws iam add-role-to-instance-profile   --instance-profile-name EC2-S3-ReadProfile   --role-name EC2-S3-ReadRole

# Attach instance profile to EC2 instance
aws ec2 associate-iam-instance-profile   --instance-id i-1234567890abcdef0   --iam-instance-profile Name=EC2-S3-ReadProfile

# Cross-account role (trust another account to assume)
# Trust policy for cross-account:
# {
#   "Principal": {"AWS": "arn:aws:iam::ACCOUNT_B:root"},
#   "Action": "sts:AssumeRole",
#   "Effect": "Allow"
# }

# Assume a role (get temporary credentials)
aws sts assume-role   --role-arn arn:aws:iam::123456789012:role/EC2-S3-ReadRole   --role-session-name my-session
# Returns: AccessKeyId, SecretAccessKey, SessionToken (valid 1 hour)

Keep your IAM knowledge sharp.

Save this stack to your personal DevRecall — add your own notes, track what you're learning, and share what you know with the community.

Get started — free forever