AWS IAM Security Architecture – SCPs, Permission Boundaries & ABAC

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.

AWS Access Control Layers (Evaluation Order)
Layer 1: Organization SCPs (Deny Guardrails)
Maximum permissions for ALL principals in the account. Cannot GRANT — only RESTRICT.
Layer 2: Resource Control Policies (RCPs)
Control what external principals can do with resources in the account.
Layer 3: Permission Boundaries (Delegation Safety)
Maximum permissions a SPECIFIC principal can have. Set by admin, limits what identity policy can grant.
Layer 4: Identity Policies (IAM Policies)
Actual permissions granted to the user/role. INTERSECTS with boundaries and SCPs.
Layer 5: Resource Policies
Attached to resources (S3 bucket, KMS key, SQS queue). Can grant cross-account access directly.
Result: Effective permissions = SCP ∩ RCP ∩ Boundary ∩ Identity Policy (∪ Resource Policy for cross-account)

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:RequestedRegion is in allowed list (with exceptions for global services)
  • Require encryption: Deny s3:PutObject unless s3:x-amz-server-side-encryption is present
  • Prevent root user access: Deny all actions when aws:PrincipalArn matches 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 with Project=Alpha → access granted automatically.
  • ABAC + SCPs: Use SCP to require tags on resource creation (aws:RequestTag must include Project)
  • Session tags: SAML federation can pass tags (department, team) from IdP → IAM role → ABAC policy evaluation

IAM Policy Evaluation Logic

For same-account requests:

  1. Explicit Deny? → DENIED (anywhere in any policy = final denial)
  2. SCP allows? → If SCP doesn’t allow, DENIED
  3. Resource policy allows? → If resource policy grants access (same-account), ALLOWED (skip remaining checks)
  4. Permission boundary allows? → If boundary set and doesn’t include action, DENIED
  5. Session policy allows? → If session policy set and doesn’t include action, DENIED
  6. 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?

  1. Create an SCP denying iam:CreateRole for the development OU
  2. Require developers to attach a specific permission boundary to any role they create, enforced by a condition in their IAM policy
  3. Create a Lambda execution role and require all functions use only this role
  4. 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?

  1. Remove iam:* from all accounts to prevent admin access
  2. Apply an SCP at the organization root denying cloudtrail:StopLogging, cloudtrail:DeleteTrail, and organizations:LeaveOrganization
  3. Create AWS Config rules to detect and auto-remediate these actions
  4. 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?

  1. Create separate IAM roles per department, each with hardcoded resource ARNs
  2. Use SAML session tags to pass Department attribute, then use ABAC policy with aws:PrincipalTag/Department condition matching aws:ResourceTag/Department
  3. Use permission boundaries per department limiting resource access
  4. 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?

  1. The bucket policy needs to specify the role ARN, not the account
  2. Account B’s SCP is blocking the PutObject action
  3. Account A’s permission boundary on the role doesn’t include s3:PutObject
  4. 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?

  1. Create an IAM user with access keys, rotate keys every 90 days
  2. Set up a Site-to-Site VPN and use the VPC’s IAM capabilities
  3. Configure IAM Roles Anywhere with the company’s private CA as trust anchor, servers present certificates to get temporary credentials
  4. 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

References

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.

Posted in AWS

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.