AWS IAM Security
When to Use
- Designing IAM roles, policies, and permission structures
- Troubleshooting
AccessDenied errors in AWS
- Implementing multi-account permission guardrails with SCPs
- Using permission boundaries for delegated administration
- Setting up cross-account access with IAM roles
- Using IAM Access Analyzer to identify external resource exposure
- Preparing for AWS SCS-C02, SAP-C02, or DVA-C02 exams
Core Jobs
1. IAM Policy Types
| Policy Type |
Attached To |
Purpose |
| Identity policy |
IAM user, group, role |
Grant permissions to the principal |
| Resource policy |
AWS resource (S3, KMS, Lambda, etc.) |
Grant/deny access from specific principals |
| SCP (Service Control Policy) |
AWS Organizations OU or account |
Set maximum permissions for member accounts |
| Permission boundary |
IAM user or role |
Maximum permissions for that IAM entity |
| Session policy |
AssumeRole call |
Limit permissions for a specific session |
| ACL |
S3, VPC (legacy) |
Cross-account resource access (legacy; avoid) |
Key insight: Multiple policy types can apply simultaneously. The effective permissions = intersection of what ALL applicable policies allow.
2. Policy Evaluation Logic
Evaluation order (AWS processes in this order):
- Explicit DENY — from ANY policy in the evaluation context → immediately DENY (overrides everything)
- SCP — if in AWS Organizations, SCP must ALLOW the action (default deny if no SCP allows)
- Resource-based policy — check if the resource policy allows the principal
- IAM permission boundary — the boundary must allow the action
- Identity policy — the attached identity policy must allow the action
- Session policy — the session policy must allow the action
Simplified rule: Explicit DENY wins → then all remaining policies must ALLOW → any missing allow = implicit DENY.
Cross-account access: Both the identity policy in Account A (allow sts:AssumeRole) AND either the role's trust policy in Account B must allow the access. Resource policies in Account B alone can grant access to Account A principals for some services (S3, KMS, SQS).
3. Roles vs Users
| Aspect |
IAM Role |
IAM User |
| Credentials |
Temporary (STS-issued, 1–12h) |
Long-term access keys |
| Identity |
Assumed by any trusted principal |
Fixed individual |
| Best for |
Services, cross-account, federated access |
Break-glass admin, legacy CLI |
| Key rotation |
Automatic (STS expiry) |
Manual (must rotate) |
| Recommendation |
Always prefer roles |
Minimize users; use SSO instead |
Use roles for:
- EC2 instances accessing S3, DynamoDB (instance profile)
- Lambda functions (execution role)
- Cross-account access (assume role in another account)
- Federated access (SAML, OIDC, AWS SSO/Identity Center)
4. SCPs (Service Control Policies)
- Applied to AWS Organizations OUs or individual accounts
- Act as a guardrail — set the maximum permissions for all principals in scope
- SCPs do NOT grant permissions; they restrict what can be granted by IAM policies
- Default:
FullAWSAccess SCP applied to root (allows everything); tighten by adding deny SCPs
SCP deny strategy (preferred):
{
"Effect": "Deny",
"Action": ["ec2:TerminateInstances"],
"Resource": "*",
"Condition": {"StringNotEquals": {"aws:RequestedRegion": ["us-east-1", "us-west-2"]}}
}
SCP allow-list strategy: remove FullAWSAccess and explicitly allow only approved services. Stronger but more management overhead.
SCPs apply to: all IAM users and roles in the account (including root user's service calls). SCPs do NOT apply to the management (root) account of the Organization.
5. Permission Boundaries
- Set the maximum permissions for a specific IAM user or role
- Used for delegated administration: allow team leads to create roles but only within approved boundary
- Identity policy AND permission boundary must BOTH allow an action (intersection)
- Boundary does NOT grant permissions alone — it only limits what identity policies CAN grant
Example: Developer creates Lambda execution roles, but cannot escalate beyond their own permissions:
{
"Effect": "Allow",
"Action": ["iam:CreateRole", "iam:AttachRolePolicy"],
"Resource": "*",
"Condition": {"StringEquals": {"iam:PermissionsBoundary": "arn:aws:iam::ACCOUNT:policy/DevBoundary"}}
}
6. Cross-Account Access Pattern
- Account B creates IAM role with trust policy allowing Account A principals:
{
"Principal": {"AWS": "arn:aws:iam::ACCOUNT_A:role/app-role"},
"Action": "sts:AssumeRole"
}
- Account A grants its principal permission to
sts:AssumeRole for the Account B role
- Application calls
sts:AssumeRole → receives temporary credentials for Account B role
- Uses temporary credentials to make API calls in Account B
ExternalId: Required for third-party cross-account access (prevents confused deputy attacks). Third party provides ExternalId in AssumeRole call; role trust policy conditions on ExternalId.
7. IAM Access Analyzer
- Identifies resources shared with external principals (outside your account/organization)
- Analyzes: S3 buckets, KMS keys, IAM roles, Lambda functions, SQS queues, Secrets Manager secrets, SNS topics
- Types of analyzers: Account (external sharing from account) or Organization (cross-account within org)
- Policy validation: checks IAM policies for syntax errors and best practices
- Policy generation: analyze CloudTrail to generate least-privilege policy from actual usage
- Findings: Active, Archived, Resolved
Key Concepts
- Principal — entity making the API call: IAM user, IAM role, AWS service, federated identity
- Explicit DENY — always wins, regardless of any other allow policy; used for guardrails
- Implicit DENY — default behavior; no allow = deny
- Trust policy — JSON policy attached to an IAM role defining who can assume it; separate from permission policies
- IAM Identity Center (SSO) — centralized access management for multiple AWS accounts; replaces per-account IAM users
- ABAC (Attribute-Based Access Control) — use tags to control access (
aws:ResourceTag/team = ${aws:PrincipalTag/team})
- Service-linked roles — pre-defined by AWS service; cannot modify the trust policy; created automatically
- Instance profile — container for an IAM role attached to EC2 instances (EC2-specific mechanism)
Checklist
Output Format
- 🔴 Critical — long-term access keys on shared services/EC2 (should use instance profiles); overly permissive policies (
Action: "*", Resource: "*"); no SCPs in multi-account setup (no guardrails)
- 🟡 Warning — IAM users for programmatic access (prefer roles + Identity Center); no permission boundary for delegated role creation; IAM Access Analyzer not enabled
- 🟢 Suggestion — ABAC with resource tags for scalable access control; policy generation from CloudTrail for least-privilege; IAM policy simulation before deploying
Exam Tips
- Explicit DENY always wins regardless of any allow — this is the most important IAM evaluation rule
- SCP does NOT grant permissions; it limits what member accounts CAN grant with their own IAM policies
- Cross-account: role in Account B + trust policy allowing Account A +
sts:AssumeRole call from Account A
- Permission boundary = developer can only create roles within the boundary (delegation pattern without privilege escalation risk)
- IAM Access Analyzer = finds resources shared externally (S3, KMS, IAM roles, etc.); also validates policy syntax and generates least-privilege policies from CloudTrail
- Service roles (e.g., Lambda execution role) = created and managed by you; service-linked roles = pre-defined by AWS service, automatic creation, limited modification
- SCPs apply to management account? NO — SCPs do NOT apply to the AWS Organizations management (root) account itself
- Session policies (passed in
AssumeRole call) = further restrict the role's permissions for that specific session only
1---2name: iam-security3description: Use when designing IAM policies, troubleshooting access denied errors, implementing SCPs, permission boundaries, cross-account roles, or using IAM Access Analyzer. Covers AWS SCS-C02, SAP-C02, and DVA-C02 identity domains.4---56# AWS IAM Security78## When to Use9- Designing IAM roles, policies, and permission structures10- Troubleshooting `AccessDenied` errors in AWS11- Implementing multi-account permission guardrails with SCPs12- Using permission boundaries for delegated administration13- Setting up cross-account access with IAM roles14- Using IAM Access Analyzer to identify external resource exposure15- Preparing for AWS SCS-C02, SAP-C02, or DVA-C02 exams1617## Core Jobs1819### 1. IAM Policy Types2021| Policy Type | Attached To | Purpose |22|-------------|------------|---------|23| **Identity policy** | IAM user, group, role | Grant permissions to the principal |24| **Resource policy** | AWS resource (S3, KMS, Lambda, etc.) | Grant/deny access from specific principals |25| **SCP (Service Control Policy)** | AWS Organizations OU or account | Set maximum permissions for member accounts |26| **Permission boundary** | IAM user or role | Maximum permissions for that IAM entity |27| **Session policy** | AssumeRole call | Limit permissions for a specific session |28| **ACL** | S3, VPC (legacy) | Cross-account resource access (legacy; avoid) |2930**Key insight**: Multiple policy types can apply simultaneously. The effective permissions = intersection of what ALL applicable policies allow.3132### 2. Policy Evaluation Logic3334**Evaluation order** (AWS processes in this order):35361. **Explicit DENY** — from ANY policy in the evaluation context → immediately DENY (overrides everything)372. **SCP** — if in AWS Organizations, SCP must ALLOW the action (default deny if no SCP allows)383. **Resource-based policy** — check if the resource policy allows the principal394. **IAM permission boundary** — the boundary must allow the action405. **Identity policy** — the attached identity policy must allow the action416. **Session policy** — the session policy must allow the action4243**Simplified rule**: Explicit DENY wins → then all remaining policies must ALLOW → any missing allow = implicit DENY.4445**Cross-account access**: Both the identity policy in Account A (allow sts:AssumeRole) AND either the role's trust policy in Account B must allow the access. Resource policies in Account B alone can grant access to Account A principals for some services (S3, KMS, SQS).4647### 3. Roles vs Users4849| Aspect | IAM Role | IAM User |50|--------|---------|---------|51| Credentials | Temporary (STS-issued, 1–12h) | Long-term access keys |52| Identity | Assumed by any trusted principal | Fixed individual |53| Best for | Services, cross-account, federated access | Break-glass admin, legacy CLI |54| Key rotation | Automatic (STS expiry) | Manual (must rotate) |55| Recommendation | Always prefer roles | Minimize users; use SSO instead |5657**Use roles for**:58- EC2 instances accessing S3, DynamoDB (instance profile)59- Lambda functions (execution role)60- Cross-account access (assume role in another account)61- Federated access (SAML, OIDC, AWS SSO/Identity Center)6263### 4. SCPs (Service Control Policies)6465- Applied to AWS Organizations OUs or individual accounts66- Act as a guardrail — set the **maximum permissions** for all principals in scope67- SCPs do NOT grant permissions; they restrict what can be granted by IAM policies68- Default: `FullAWSAccess` SCP applied to root (allows everything); tighten by adding deny SCPs6970**SCP deny strategy** (preferred):71```json72{73 "Effect": "Deny",74 "Action": ["ec2:TerminateInstances"],75 "Resource": "*",76 "Condition": {"StringNotEquals": {"aws:RequestedRegion": ["us-east-1", "us-west-2"]}}77}78```7980**SCP allow-list strategy**: remove `FullAWSAccess` and explicitly allow only approved services. Stronger but more management overhead.8182**SCPs apply to**: all IAM users and roles in the account (including root user's service calls). SCPs do NOT apply to the management (root) account of the Organization.8384### 5. Permission Boundaries8586- Set the **maximum permissions** for a specific IAM user or role87- Used for **delegated administration**: allow team leads to create roles but only within approved boundary88- Identity policy AND permission boundary must BOTH allow an action (intersection)89- Boundary does NOT grant permissions alone — it only limits what identity policies CAN grant9091**Example**: Developer creates Lambda execution roles, but cannot escalate beyond their own permissions:92```json93{94 "Effect": "Allow",95 "Action": ["iam:CreateRole", "iam:AttachRolePolicy"],96 "Resource": "*",97 "Condition": {"StringEquals": {"iam:PermissionsBoundary": "arn:aws:iam::ACCOUNT:policy/DevBoundary"}}98}99```100101### 6. Cross-Account Access Pattern1021031. **Account B** creates IAM role with trust policy allowing Account A principals:104```json105{106 "Principal": {"AWS": "arn:aws:iam::ACCOUNT_A:role/app-role"},107 "Action": "sts:AssumeRole"108}109```1102. **Account A** grants its principal permission to `sts:AssumeRole` for the Account B role1113. Application calls `sts:AssumeRole` → receives temporary credentials for Account B role1124. Uses temporary credentials to make API calls in Account B113114**ExternalId**: Required for third-party cross-account access (prevents confused deputy attacks). Third party provides ExternalId in AssumeRole call; role trust policy conditions on ExternalId.115116### 7. IAM Access Analyzer117118- Identifies resources shared with external principals (outside your account/organization)119- Analyzes: S3 buckets, KMS keys, IAM roles, Lambda functions, SQS queues, Secrets Manager secrets, SNS topics120- Types of analyzers: **Account** (external sharing from account) or **Organization** (cross-account within org)121- **Policy validation**: checks IAM policies for syntax errors and best practices122- **Policy generation**: analyze CloudTrail to generate least-privilege policy from actual usage123- Findings: Active, Archived, Resolved124125## Key Concepts126127- **Principal** — entity making the API call: IAM user, IAM role, AWS service, federated identity128- **Explicit DENY** — always wins, regardless of any other allow policy; used for guardrails129- **Implicit DENY** — default behavior; no allow = deny130- **Trust policy** — JSON policy attached to an IAM role defining who can assume it; separate from permission policies131- **IAM Identity Center (SSO)** — centralized access management for multiple AWS accounts; replaces per-account IAM users132- **ABAC (Attribute-Based Access Control)** — use tags to control access (`aws:ResourceTag/team` = `${aws:PrincipalTag/team}`)133- **Service-linked roles** — pre-defined by AWS service; cannot modify the trust policy; created automatically134- **Instance profile** — container for an IAM role attached to EC2 instances (EC2-specific mechanism)135136## Checklist137138- [ ] IAM users replaced with roles + IAM Identity Center (SSO) where possible?139- [ ] No long-term access keys on EC2/Lambda (use instance profiles and execution roles)?140- [ ] SCPs applied to restrict regions and services in member accounts?141- [ ] Permission boundaries configured for delegated admin scenarios?142- [ ] ExternalId required in trust policies for third-party cross-account roles?143- [ ] IAM Access Analyzer enabled to detect unexpected external resource sharing?144- [ ] Access policies follow least-privilege (generated from CloudTrail usage)?145- [ ] No wildcard (`*`) in Action or Resource in production policies?146147## Output Format148149- 🔴 **Critical** — long-term access keys on shared services/EC2 (should use instance profiles); overly permissive policies (`Action: "*"`, `Resource: "*"`); no SCPs in multi-account setup (no guardrails)150- 🟡 **Warning** — IAM users for programmatic access (prefer roles + Identity Center); no permission boundary for delegated role creation; IAM Access Analyzer not enabled151- 🟢 **Suggestion** — ABAC with resource tags for scalable access control; policy generation from CloudTrail for least-privilege; IAM policy simulation before deploying152153## Exam Tips154155- **Explicit DENY always wins** regardless of any allow — this is the most important IAM evaluation rule156- **SCP does NOT grant permissions**; it limits what member accounts CAN grant with their own IAM policies157- **Cross-account**: role in Account B + trust policy allowing Account A + `sts:AssumeRole` call from Account A158- **Permission boundary** = developer can only create roles within the boundary (delegation pattern without privilege escalation risk)159- **IAM Access Analyzer** = finds resources shared externally (S3, KMS, IAM roles, etc.); also validates policy syntax and generates least-privilege policies from CloudTrail160- **Service roles** (e.g., Lambda execution role) = created and managed by you; **service-linked roles** = pre-defined by AWS service, automatic creation, limited modification161- **SCPs apply to management account? NO** — SCPs do NOT apply to the AWS Organizations management (root) account itself162- **Session policies** (passed in `AssumeRole` call) = further restrict the role's permissions for that specific session only