AWS IAM Security Architecture — Overview
IAM is the largest exam domain on SCS-C03 (20%) and appears heavily on SAP-C02. This post covers the layered access control model: SCPs (organization guardrails) → Permission Boundaries (delegation limits) → Identity Policies (actual permissions) → Resource Policies (resource-level control). Understanding policy evaluation order and interaction is critical.
Service Control Policies (SCPs)
| Feature | Details |
|---|---|
| What they do | Set maximum available permissions for ALL principals in an account (including root!). Cannot grant permissions — only restrict. |
| Applied to | OUs or individual accounts (inherited from parent OU → child OU → account) |
| Do NOT affect | Management account (always exempt), service-linked roles, CloudFront key pairs |
| Strategy: Deny list | Start with FullAWSAccess, add explicit Deny statements for restricted actions (most common approach) |
| Strategy: Allow list | Remove FullAWSAccess, explicitly allow only approved services (more restrictive, harder to manage) |
Common SCP Patterns (Exam Favorites)
- Prevent leaving Organization: Deny
organizations:LeaveOrganization - Prevent disabling CloudTrail: Deny
cloudtrail:StopLogging,cloudtrail:DeleteTrail - Prevent deleting GuardDuty: Deny
guardduty:DeleteDetector,guardduty:DisassociateFromMasterAccount - Restrict regions: Deny all actions unless
aws:RequestedRegionis in allowed list (with exceptions for global services) - Require encryption: Deny
s3:PutObjectunlesss3:x-amz-server-side-encryptionis present - Prevent root user access: Deny all actions when
aws:PrincipalArnmatches root (doesn’t affect management account)
Permission Boundaries
- Purpose: Allow administrators to delegate user/role creation safely. The boundary sets maximum permissions that any identity policy can grant.
- Intersection model: Effective permissions = Identity Policy ∩ Permission Boundary. If boundary doesn’t allow s3:*, even AdministratorAccess policy can’t grant S3.
- Use case: DevOps team can create roles for their applications, but boundary ensures they can’t create roles with more permissions than they have themselves (privilege escalation prevention).
- Exam trap: Permission boundaries ONLY affect identity-based policies. Resource policies (like S3 bucket policy) bypass the boundary check.
ABAC (Attribute-Based Access Control)
| Approach | How | Best For |
|---|---|---|
| RBAC (traditional) | One policy per role per resource. Explicit ARNs in policies. | Small, static environments |
| ABAC (tag-based) | Policy uses conditions: aws:ResourceTag/Project = ${aws:PrincipalTag/Project} |
Dynamic, large environments. No policy changes when new resources are created. |
- ABAC advantage: One policy works for all projects/teams. Tag a user with
Project=Alpha, resources withProject=Alpha→ access granted automatically. - ABAC + SCPs: Use SCP to require tags on resource creation (
aws:RequestTagmust includeProject) - Session tags: SAML federation can pass tags (department, team) from IdP → IAM role → ABAC policy evaluation
IAM Policy Evaluation Logic
For same-account requests:
- Explicit Deny? → DENIED (anywhere in any policy = final denial)
- SCP allows? → If SCP doesn’t allow, DENIED
- Resource policy allows? → If resource policy grants access (same-account), ALLOWED (skip remaining checks)
- Permission boundary allows? → If boundary set and doesn’t include action, DENIED
- Session policy allows? → If session policy set and doesn’t include action, DENIED
- Identity policy allows? → If identity policy grants, ALLOWED. Otherwise, implicit DENIED.
For cross-account requests:
- BOTH sides must allow: Account A’s identity policy (or resource policy) must allow AND Account B’s resource policy must allow
- Exception: If Account B’s resource policy specifies Account A’s role ARN directly, Account A’s identity policy is not needed
- SCPs apply to the requesting principal’s account
Session Policies & Roles Anywhere
- Session policies: Passed when assuming role (AssumeRole API). Further restricts the role’s permissions for that session only. Effective = Role Policy ∩ Session Policy.
- IAM Roles Anywhere: Workloads OUTSIDE AWS (on-premises servers) can get temporary credentials by presenting a certificate from a registered CA trust anchor. Eliminates long-term access keys for hybrid workloads.
- Amazon Verified Permissions: Fine-grained authorization for applications using Cedar policy language. Externalize authorization logic from application code.
Exam Tips
| Exam | Key Points |
|---|---|
| SCS-C03 | “Prevent region usage” → SCP with aws:RequestedRegion. “Delegate role creation safely” → Permission Boundaries. “Dynamic access based on tags” → ABAC. “Cross-account access” → both identity + resource policy (or resource policy alone). “Management account” = exempt from SCPs. “Explicit Deny always wins”. “Permission boundary doesn’t affect resource policies”. |
AWS Certification Exam Practice Questions
Question 1:
A company wants to allow their development team to create IAM roles for Lambda functions, but prevent them from creating roles with more permissions than their own (privilege escalation). The solution must not require security team approval for each role creation. Which approach achieves this?
- Create an SCP denying iam:CreateRole for the development OU
- Require developers to attach a specific permission boundary to any role they create, enforced by a condition in their IAM policy
- Create a Lambda execution role and require all functions use only this role
- Use AWS Service Catalog to manage approved role configurations
Show Answer
Answer: B — Permission boundaries solve the delegation problem. The developer’s policy allows iam:CreateRole, iam:AttachRolePolicy BUT with a condition: iam:PermissionsBoundary must equal the approved boundary ARN. Any role they create is automatically limited to the boundary’s permissions — they cannot escalate. SCP (A) blocks all role creation. Single role (C) doesn’t scale. Service Catalog (D) requires approval overhead.
Question 2:
An organization wants to ensure NO AWS account (except the management account) can disable CloudTrail or leave the organization, regardless of what IAM permissions exist in those accounts. How should this be implemented?
- Remove iam:* from all accounts to prevent admin access
- Apply an SCP at the organization root denying cloudtrail:StopLogging, cloudtrail:DeleteTrail, and organizations:LeaveOrganization
- Create AWS Config rules to detect and auto-remediate these actions
- Create EventBridge rules in each account to block these API calls
Show Answer
Answer: B — SCPs are preventive controls that set maximum available permissions. A Deny in an SCP overrides any Allow in any identity policy, even AdministratorAccess. Applied at the root OU, it affects all member accounts. The management account is automatically exempt (cannot SCP itself). Config rules (C) and EventBridge (D) are detective/reactive — they detect after the fact, not prevent. Removing iam:* (A) breaks everything.
Question 3:
A company uses SAML federation from their on-premises Active Directory. They need engineers tagged with “Department=Engineering” in AD to only access EC2 instances tagged with “Department=Engineering” — without creating separate policies per department. Which approach provides this?
- Create separate IAM roles per department, each with hardcoded resource ARNs
- Use SAML session tags to pass Department attribute, then use ABAC policy with aws:PrincipalTag/Department condition matching aws:ResourceTag/Department
- Use permission boundaries per department limiting resource access
- Create resource policies on each EC2 instance allowing specific department groups
Show Answer
Answer: B — ABAC with session tags: The SAML IdP passes the Department attribute as a session tag during federation. The IAM policy condition checks aws:ResourceTag/Department == ${aws:PrincipalTag/Department}. One policy works for ALL departments. New departments automatically work without policy changes — just tag users and resources. This scales infinitely without per-department roles (A) or policies.
Question 4:
Account B has an S3 bucket with a bucket policy allowing Account A’s role to PutObject. However, when Account A’s role tries to upload, it gets AccessDenied. The role has s3:* in its identity policy. Account A has an SCP that allows all S3 actions. What is the most likely cause?
- The bucket policy needs to specify the role ARN, not the account
- Account B’s SCP is blocking the PutObject action
- Account A’s permission boundary on the role doesn’t include s3:PutObject
- S3 requires the request to include server-side encryption headers
Show Answer
Answer: C — For cross-account access where the identity policy allows the action, a permission boundary on the role will still restrict it. Even though the identity policy has s3:* and the SCP allows it, the boundary creates an additional intersection. If the boundary doesn’t include s3:PutObject, the effective permission is denied. Note: if only the resource policy (bucket policy) grants access and the identity policy doesn’t have the action, boundaries don’t apply — but here the identity policy also has s3:*.
Question 5:
A company has on-premises servers that need to call AWS APIs (S3, DynamoDB) without storing long-term access keys on the servers. The servers have certificates issued by the company’s private CA. Which solution eliminates long-term credentials?
- Create an IAM user with access keys, rotate keys every 90 days
- Set up a Site-to-Site VPN and use the VPC’s IAM capabilities
- Configure IAM Roles Anywhere with the company’s private CA as trust anchor, servers present certificates to get temporary credentials
- Use AWS SSO (IAM Identity Center) with SAML for machine-to-machine auth
Show Answer
Answer: C — IAM Roles Anywhere enables workloads outside AWS to obtain temporary credentials by presenting an X.509 certificate. Register your CA as a trust anchor, create a profile with the desired IAM role. Servers present their certificate → Roles Anywhere validates against the CA → issues temporary STS credentials. No long-term keys stored. SSO/Identity Center (D) is for human users, not machine-to-machine.
Related Posts
- Multi-Account Architecture (Organizations & Control Tower)
- Zero Trust Architecture
- Data Encryption Architecture (KMS & CloudHSM)
- Centralized Logging Architecture
- DDoS & Edge Protection Architecture
References
- Permission Boundaries — AWS Docs
- Service Control Policies — AWS Docs
- ABAC for AWS — AWS Docs
- Least Privilege with StackSets — AWS Security Blog
Frequently Asked Questions
What is the difference between SCPs and Permission Boundaries?
SCPs apply to an entire AWS account (all principals within it). They set the maximum permissions for the account. Permission Boundaries apply to a specific IAM user or role. They limit what that specific principal can do. SCPs are set by the Organization admin; boundaries are set by the account admin. Both use the intersection model — effective permissions must be allowed by both.
Does the management account get restricted by SCPs?
No. The management account is always exempt from SCPs. This is by design — you can’t accidentally lock yourself out of the Organization. Because of this, best practice is to NOT run workloads in the management account. Use it only for Organization management, billing, and account creation.
How does ABAC scale better than RBAC?
With RBAC, you need N policies for N projects/teams (one policy per team specifying resource ARNs). With ABAC, you need ONE policy that uses tag conditions. When a new project starts, just tag the resources and users — no policy changes. The policy Condition: aws:ResourceTag/Project == ${aws:PrincipalTag/Project} automatically works for all current and future projects.