IAM β Identity & Access Management
Exam Weight: Domain 2 (Security) β 26% of exam
Key Theme: "Who can do what, on which resources, under what conditions?"
π° What Is IAM?β
IAM controls who (authentication) can do what (authorization) on which AWS resources. Every AWS API call goes through IAM for permission checks.
Analogy: IAM is like building security. Users are employees with badges. Groups are departments (engineering, finance). Roles are temporary visitor passes. Policies are the rules posted on each door saying who can enter.
Core Conceptsβ
| Component | Description | Example |
|---|---|---|
| User | Long-term credentials for a person/application | Developer Jane |
| Group | Collection of users with shared permissions | "BackendDevs" group |
| Role | Temporary credentials assumed by services/users | Lambda execution role |
| Policy | JSON document defining permissions | "Allow S3 read" |
IAM Principalsβ
A principal is an entity that can make API calls:
- IAM Users
- IAM Roles (assumed by services, users, or federated identities)
- AWS Services (e.g., Lambda, EC2)
- Federated users (SAML, OIDC, Cognito)
- Root account (avoid!)
Policy Structureβ
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "AllowS3ReadWrite",
"Effect": "Allow",
"Action": ["s3:GetObject", "s3:PutObject"],
"Resource": "arn:aws:s3:::my-bucket/*",
"Condition": {
"IpAddress": { "aws:SourceIp": "10.0.0.0/24" },
"StringEquals": { "s3:x-amz-server-side-encryption": "aws:kms" }
}
}
]
}
Policy Elementsβ
| Element | Required | Description |
|---|---|---|
| Version | β | Always "2012-10-17" |
| Statement | β | Array of permission rules |
| Effect | β | Allow or Deny |
| Action | β | API actions (e.g., s3:GetObject) |
| Resource | β * | ARN of resources (* = all) |
| Principal | Resource policies only | Who is allowed/denied |
| Condition | β Optional | When the rule applies |
Common Condition Keysβ
| Key | Purpose | Example |
|---|---|---|
aws:SourceIp | Restrict by IP | Office IP ranges only |
aws:PrincipalTag | Attribute-based access (ABAC) | department = engineering |
aws:RequestedRegion | Restrict by region | Only us-east-1 |
aws:MultiFactorAuthPresent | Require MFA | true |
s3:prefix | S3 key prefix | Only logs/ prefix |
Policy Typesβ
1. Identity-Based Policiesβ
Attached to users, groups, or roles:
| Subtype | Description |
|---|---|
| AWS Managed | Created by AWS (e.g., AmazonS3ReadOnlyAccess) |
| Customer Managed | Created by you β reusable across entities |
| Inline | Embedded directly in a single user/role β not reusable |
2. Resource-Based Policiesβ
Attached to the resource (S3 bucket, SQS queue, Lambda, KMS key):
{
"Effect": "Allow",
"Principal": { "AWS": "arn:aws:iam::987654321098:root" },
"Action": "s3:GetObject",
"Resource": "arn:aws:s3:::shared-bucket/*"
}
Key difference: Resource policies have a Principal element; identity policies don't.
3. Permission Boundariesβ
Set the maximum permissions an entity can have β does not grant permissions:
Identity Policy: Allow s3:*, dynamodb:*, lambda:*
Permission Boundary: Allow s3:*, dynamodb:*
Effective: Allow s3:*, dynamodb:* (lambda:* denied by boundary)
Use case: Safely delegate IAM admin to junior devs β they can create roles but only within the boundary.
4. Service Control Policies (SCPs)β
Account-level restrictions via AWS Organizations:
- Apply to entire accounts or OUs
- Restrict what even root can do
- Do NOT grant permissions β only restrict
5. Session Policiesβ
Passed inline during AssumeRole β limits that specific session only.
Policy Evaluation Logicβ
1. Is there an explicit DENY? β DENY β (game over)
2. Is there an SCP that doesn't allow? β DENY β
3. Is there a Permission Boundary? β Must also allow
4. Is there a Resource-Based Policy? β If allows cross-account, sufficient*
5. Is there an Identity-Based Policy? β Must allow
6. None of the above allow? β DENY β (implicit deny)
* Resource-based policies can independently grant cross-account access
without the caller's identity policy needing to allow it.
An explicit "Effect": "Deny" overrides ANY Allow β from any policy, anywhere in the evaluation chain.
Same-Account vs Cross-Accountβ
| Scenario | What's needed |
|---|---|
| Same account | Identity policy OR resource policy (either one) |
| Cross-account | Identity policy AND resource policy (both needed) |
| Exception | If resource policy specifies the principal (not just account), identity policy can be skipped |
IAM Roles & STSβ
AssumeRole Flowβ
Your App/Service
β
STS:AssumeRole(RoleArn, SessionName, Duration, ExternalId?)
β
Temporary Credentials (AccessKey + SecretKey + SessionToken)
β
Call AWS APIs with temp credentials (auto-expire)
Key STS APIsβ
| API | Use Case | Max Duration |
|---|---|---|
AssumeRole | Cross-account or same-account | 1h default, up to 12h |
AssumeRoleWithWebIdentity | OIDC federation (Cognito, Google) | 1h default, up to 12h |
AssumeRoleWithSAML | Corporate SSO (AD/LDAP) | 1h default, up to 12h |
GetSessionToken | MFA-protected API calls | Up to 36h |
GetFederationToken | Temporary access for federated users | Up to 36h |
Cross-Account Role Assumptionβ
Account A (Source) Account B (Target)
ββββββββββββββββββββ ββββββββββββββββββββββββββββ
β EC2 Instance ββAssumeRoleββΆβ CrossAccountRole β
β with Role A β β Trust Policy: β
β β β Principal: Account A β
β βββTempCredsβββ Permissions: β
β β β s3:GetObject on bucket β
ββββββββββββββββββββ ββββββββββββββββββββββββββββ
Java SDK β Assuming a Roleβ
StsClient stsClient = StsClient.create();
AssumeRoleResponse response = stsClient.assumeRole(AssumeRoleRequest.builder()
.roleArn("arn:aws:iam::123456789012:role/CrossAccountRole")
.roleSessionName("my-session")
.durationSeconds(3600)
.externalId("unique-external-id") // Prevents confused deputy
.build());
Credentials creds = response.credentials();
// Create S3 client with assumed role credentials
S3Client s3 = S3Client.builder()
.credentialsProvider(StaticCredentialsProvider.create(
AwsSessionCredentials.create(
creds.accessKeyId(),
creds.secretAccessKey(),
creds.sessionToken())))
.build();
Common Exam Scenariosβ
Scenario 1: Lambda accessing DynamoDBβ
Answer: Create IAM execution role with DynamoDB permissions. Attach to Lambda. Never use access keys.
Scenario 2: EC2 in Account A reads S3 in Account Bβ
Answer: Create role in Account B with S3 permissions + trust policy for Account A. EC2 calls AssumeRole.
Scenario 3: Third-party SaaS accessβ
Answer: Use AssumeRole with ExternalId condition β prevents confused deputy attack.
Scenario 4: Developer needs temporary admin accessβ
Answer: Create admin role with MFA condition. Developer assumes role with MFA token via GetSessionToken first.
π Best Practicesβ
- β IAM Roles for EC2/Lambda β never hardcode credentials
- β Least privilege β start with nothing, add as needed
- β MFA for privileged users and API calls
- β Permission Boundaries for delegated IAM admin
- β Rotate access keys regularly (or avoid them entirely)
- β AWS Organizations + SCPs for multi-account governance
- β Use tags for ABAC (Attribute-Based Access Control)
- β Never use root account for daily operations
- β Never embed credentials in source code
- β Never share IAM users β one user per person
π― DVA-C02 Exam Tipsβ
- Explicit Deny always wins over any Allow
- Cross-account needs BOTH identity + resource policy
- Same-account needs EITHER identity OR resource policy
- ExternalId prevents confused deputy attack
- Permission Boundary = max permissions (doesn't grant)
- SCP = organization-level guardrails (doesn't grant)
- Roles > Users for services (temporary > long-term creds)
- Session duration: AssumeRole default 1h, max 12h
- MFA condition:
aws:MultiFactorAuthPresent: true - Resource policies have
Principal; identity policies don't
π§ͺ Practice Questionsβ
Q1. Lambda needs S3 read access. Most secure approach?
A) Store access keys in env variables
B) Hardcode credentials
C) Attach IAM execution role with S3 read permissions
D) Use root credentials
β Answer & Explanation
C β IAM execution roles provide auto-rotating temporary credentials. Keys and root are anti-patterns.
Q2. Identity policy allows s3:* but user gets AccessDenied on delete. Most likely cause?
A) S3 needs root for delete
B) SCP explicitly denies s3:DeleteBucket
C) Missing resource policy
D) s3:* doesn't include delete
β Answer & Explanation
B β SCPs sit above identity policies. An explicit Deny in an SCP overrides any Allow.
Q3. Third-party needs read access. Security team worried about confused deputy. What to add?
A) aws:SourceIp condition
B) sts:ExternalId condition
C) Permission Boundary
D) SCP
β Answer & Explanation
B β ExternalId is the standard defense against confused deputy. Third party must supply this ID when assuming the role.
Q4. Same-account: Lambda has identity policy allowing S3. No bucket policy. Will it work?
A) No β both policies needed
B) Yes β same account needs only ONE policy
C) No β bucket policy always required
D) Only for public buckets
β Answer & Explanation
B β In the same account, an Allow in EITHER identity OR resource policy is sufficient. Cross-account requires both.