Free — no signup required

Service Control Policies (SCPs): The Guardrails

3 min read

The "No" Button That Overrides Everyone

IAM policies define what a principal (user, role) is allowed to do within an account. Service Control Policies (SCPs) define the maximum permissions available to any principal in an account — including the root user. SCPs do not grant permissions; they filter them.

Think of SCPs as a ceiling. IAM policies can only grant permissions up to that ceiling. If the SCP ceiling is at floor level, no IAM policy in the world can grant access above it.

How Permission Evaluation Works

The evaluation logic is an intersection (logical AND) across the entire hierarchy:

Effective Permission = IAM Policy ∩ SCP (OU) ∩ SCP (Parent OU) ∩ SCP (Root)

Concrete example:

Root SCP:        Allow *  (FullAWSAccess — the default)
Prod OU SCP:     Deny: s3:DeleteBucket
Account IAM:     AdministratorAccess (Allow *)

Developer tries: aws s3 rb s3://my-bucket --force

IAM evaluation:  ALLOW (AdministratorAccess covers s3:DeleteBucket)
SCP evaluation:  DENY  (Prod OU SCP explicitly denies s3:DeleteBucket)
Final result:    DENIED

The SCP denial wins regardless of IAM. There is no override, no escalation path, no break-glass for this specific action.

The Allow-List Trap

SCPs support two modes: deny-list and allow-list.

Deny-list (recommended): Keep FullAWSAccess attached (which allows everything to pass through), then add explicit Deny statements for dangerous actions. This is the default Control Tower approach.

Allow-list: Remove FullAWSAccess and replace it with an explicit Allow for specific services. This implicitly denies everything not listed.

The allow-list trap: if you attach an SCP that only says Allow: ec2:*, you have silently denied S3, RDS, Lambda, IAM, and every other service. Teams will start getting mysterious AccessDenied errors with no obvious cause, because the denial comes from the SCP layer — not from their IAM policies.

Common production SCPs (deny-list pattern): a typical deny-list SCP for a production OU stacks several targeted denials on top of the default FullAWSAccess allow — blocking organizations:LeaveOrganization so no account can secede from the org, blocking cloudtrail:StopLogging, cloudtrail:DeleteTrail, and cloudtrail:UpdateTrail so the audit trail can't be tampered with, and denying regional API calls outside approved regions.

The DenyRegionLockout SCP uses NotAction to allow global services (IAM, STS) while blocking all regional API calls outside approved regions. This prevents data residency violations and reduces the attack surface for credential compromise.

Interview Tip

A common interview question is: "Can an AWS account root user bypass an SCP?" The answer is no — SCPs apply to the root user of member accounts. However, the root user of the Management Account is not subject to SCPs. This is why the Management Account should have zero workloads and extremely restricted human access. Follow-up: "How do you protect the Management Account root user?" Answer: hardware MFA, no access keys, and a break-glass procedure documented in a runbook.

This is one of 18 chapters

Get every chapter — Kubernetes, Terraform, SRE, distributed systems, and more — with fast daily review built in.

See pricing