Skip to content

Latest commit

 

History

History
238 lines (188 loc) · 7.71 KB

File metadata and controls

238 lines (188 loc) · 7.71 KB

IAM — Identity and Access Management

What Is It?

IAM is the gatekeeper of your AWS account. Every API call made to AWS goes through IAM authorization. Think of it as a bouncer at a club — it checks your ID (authentication) and your guest list (authorization) before letting you do anything.


Core Concepts

1. Users, Groups, Roles, Policies

Entity What it is Real-World Analogy
User A person or service with long-term credentials An employee badge
Group Collection of users sharing the same permissions A department (e.g., "Developers")
Role Temporary identity assumed by AWS services or users A contractor's day pass
Policy JSON document defining permissions A rulebook

2. Policy Types

AWS Account
├── Identity-based policies  → attached to User/Group/Role
├── Resource-based policies  → attached to S3 bucket, SQS queue, etc.
├── Permission boundaries    → max permissions a role/user can have
├── SCP (Service Control Policies) → org-level guardrails
└── Session policies         → passed at assume-role time

Policy Evaluation Logic

Explicit DENY → wins always
↓
SCP allows? → No = DENY
↓
Resource policy allows? → Yes = ALLOW (cross-account)
↓
Identity policy allows? → Yes = ALLOW
↓
Default = DENY

Policy Anatomy — Real Example

Scenario: A Lambda function needs to read from DynamoDB table orders and write to S3 bucket order-backups.

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "ReadOrdersTable",
      "Effect": "Allow",
      "Action": [
        "dynamodb:GetItem",
        "dynamodb:Query",
        "dynamodb:Scan"
      ],
      "Resource": "arn:aws:dynamodb:us-east-1:123456789:table/orders"
    },
    {
      "Sid": "WriteToBackupBucket",
      "Effect": "Allow",
      "Action": [
        "s3:PutObject"
      ],
      "Resource": "arn:aws:s3:::order-backups/*"
    }
  ]
}

Key: The Lambda execution role has this policy attached — Lambda assumes the role, gets temporary credentials, makes API calls. No hardcoded secrets.


IAM Roles — Deep Dive

Trust Policy vs Permission Policy

Every role has TWO policies:

Trust Policy (who can assume this role):

{
  "Version": "2012-10-17",
  "Statement": [{
    "Effect": "Allow",
    "Principal": {
      "Service": "lambda.amazonaws.com"
    },
    "Action": "sts:AssumeRole"
  }]
}

Permission Policy (what the role can do): the JSON above.

Cross-Account Access

Scenario: Account A's Lambda needs to read Account B's DynamoDB.

Account A: Lambda → assumes RoleA → calls sts:AssumeRole on RoleB (Account B)
Account B: RoleB trust policy allows Account A, permission policy allows DynamoDB reads

STS (Security Token Service)

STS issues temporary credentials (AccessKeyId + SecretAccessKey + SessionToken).

Key APIs

API Use Case
AssumeRole Switch to another role (same or cross-account)
AssumeRoleWithWebIdentity Federation with Google/Facebook/Cognito
AssumeRoleWithSAML Federation with corporate SSO (ADFS, Okta)
GetSessionToken MFA enforcement, temporary escalation
GetFederationToken Create temp creds for broker-based federation

Credential duration: 15 min – 12 hours for AssumeRole (36 hours max with DurationSeconds override for some scenarios).


IAM Conditions — Advanced

{
  "Condition": {
    "StringEquals": {
      "aws:RequestedRegion": "us-east-1"
    },
    "Bool": {
      "aws:MultiFactorAuthPresent": "true"
    },
    "IpAddress": {
      "aws:SourceIp": "203.0.113.0/24"
    }
  }
}

Common condition keys for exam:

  • aws:RequestedRegion — restrict actions to specific region
  • aws:SourceVpc / aws:SourceVpce — enforce VPC endpoint usage
  • s3:prefix — restrict S3 access to specific folder prefix
  • dynamodb:LeadingKeys — user can only access their own DynamoDB items

Row-Level Security in DynamoDB Example

{
  "Condition": {
    "ForAllValues:StringEquals": {
      "dynamodb:LeadingKeys": ["${aws:userid}"]
    }
  }
}

This means user johndoe can only read DynamoDB rows where the partition key equals johndoe. Perfect for multi-tenant apps.


Permission Boundaries

Problem: You want developers to be able to create IAM roles for their Lambda functions, but you don't want them to create roles with admin access.

Solution: Permission Boundary

{
  "Effect": "Allow",
  "Action": ["iam:CreateRole", "iam:AttachRolePolicy"],
  "Resource": "*",
  "Condition": {
    "StringEquals": {
      "iam:PermissionsBoundary": "arn:aws:iam::123456789:policy/DevBoundary"
    }
  }
}

Now developers CAN create roles, but those roles can NEVER exceed DevBoundary.


Good Practices

Practice Why
Use IAM Roles over IAM Users for services Roles use temporary credentials, no rotation needed
Apply least privilege Minimize blast radius if credentials leak
Use Groups to assign permissions Easier to manage: change group, all members updated
Enable MFA for all human users Root account + all privileged users
Rotate access keys every 90 days Limit exposure window for long-term credentials
Use AWS Organizations SCPs as guardrails Prevent entire accounts from doing dangerous things
Tag IAM roles with team/purpose Enables auditing and cost allocation

Bad Practices

Anti-Pattern Why It's Bad Fix
Hardcoding AWS credentials in code Keys in GitHub = compromised instantly Use IAM roles + instance profiles
Using root account for daily work Root bypasses all policies, no MFA sometimes Create admin IAM user, lock root
"Action": "*" on "Resource": "*" Gives full AWS access Write specific actions and resources
Sharing IAM users across team members Can't audit who did what One user per person
Long-term credentials for EC2/Lambda Credentials sit in memory/disk EC2 instance profile, Lambda execution role
No permission boundary on developer IAM Developer can grant themselves admin Set permission boundaries

Exam Tips

  1. IAM is global — not regional. Users and roles exist across all regions.
  2. Inline vs Managed Policies: AWS Managed = AWS maintains them. Customer Managed = you control. Inline = embedded in entity (not reusable, deleted with entity).
  3. When you see "403 Forbidden" on exam — think: missing IAM permission OR S3 bucket policy conflict OR resource policy conflict.
  4. Cross-account S3: bucket policy must explicitly allow the other account; AND the IAM user/role in the other account must also have permission.
  5. sts:AssumeRole appears in almost every cross-account or service-to-service question.
  6. PassRole: When creating a service (e.g., Lambda), you need iam:PassRole to give the role TO the service.
  7. Access Analyzer: Tells you which resources are exposed to external accounts — comes up in security questions.

Common Exam Scenarios

Q: A developer's Lambda gets AccessDenied when calling DynamoDB. What's the fix? → Add DynamoDB permissions to the Lambda execution role (not the developer's IAM user).

Q: You need EC2 to call S3 without storing credentials. How? → Attach an IAM instance profile (role) to the EC2 instance.

Q: Developer created an IAM user for an app running on EC2. How to improve security? → Remove the IAM user, use an EC2 instance profile with an IAM role instead.

Q: How to allow users to see only their own S3 "folder"? → Use an IAM policy with condition s3:prefix = ${aws:username}/.