Reading30 min read·Module 1High exam weight

Service Control Policies (SCPs) & Organizations

Key concepts

  • SCPs set permission boundaries

  • SCPs don't grant permissions

  • Organizational units (OUs)

  • Policy inheritance

  • Deny lists vs allow lists

The Morning Theo Almost Bought a Supercomputer

Six weeks after the photo bucket incident, Theo has been rehabilitated. Trailbase now runs three AWS accounts: production, development, and a sandbox where Theo holds AdministratorAccess and is encouraged to break things. One Friday he decides his trail-photo classifier needs more muscle, opens the EC2 launch wizard, and picks a p4d.24xlarge, a GPU monster that costs more per day than Theo earns in a month. He reaches the review screen before Mara glances over and asks what, exactly, he is about to click.

Here is the uncomfortable part: nothing inside the sandbox account could have stopped him. Theo is an administrator there, and IAM policies live inside the account, within reach of that administrator. Any fence Dana builds with IAM, admin-Theo can edit or delete. A guardrail that binds an administrator has to be anchored somewhere the administrator cannot reach, which means above the account itself. That is the job of AWS Organizations, the free service that gathers multiple AWS accounts under one management umbrella, and of Service Control Policies (SCPs), the policies attached to that umbrella which define the maximum permissions available inside each account. Back in lesson 1 you learned the evaluation ladder: explicit deny beats allow, and SCPs cap everything from above. This lesson is about that cap.

Key Principle

SCPs set the maximum available permissions. They grant nothing on their own. Effective permissions are the intersection of IAM policies and SCPs: if either side denies an action, the action is denied. Theo can hold AdministratorAccess inside the sandbox forever; the SCP above him decides what that title is actually worth.

Exam Tip

Two exemptions carry a disproportionate number of SAA-C03 points: SCPs never affect the management account, and they never affect service-linked roles. When a scenario says an admin was somehow able to do a denied thing, check whether they were in the management account.


One Account Becomes Many

Why did Trailbase split into three accounts at all? Because the account is the strongest isolation boundary AWS offers. A runaway experiment in the sandbox cannot touch production data, blow through production quotas, or appear in production bills. Once you have more than one account, though, someone has to manage the pile, and that is what AWS Organizations does.

Dana creates the organization from a fourth, deliberately empty account. That account becomes the management account: it owns the organization, pays the consolidated bill, and holds the power to create accounts and attach policies. Every other account joins as a member account. Dana keeps the management account as empty as her root credentials vault, and for the same reason: it is exempt from the very guardrails it hands out, so anything running inside it runs unguarded.

SCPs and Organizations Hierarchy
Figure 1: AWS Organizations hierarchy showing how SCPs are inherited through OUs

AWS Organizations

AWS Organizations is a free service for centrally managing multiple AWS accounts. It provides consolidated billing (a single payment method for all accounts), centralized account creation and management, policy-based governance through SCPs and other policy types, and programmatic account automation.

Its hierarchy has four pieces. The organization is the container for everything. The Root sits at the top of the hierarchy; AWS overloads the word here, since the Root of an organization is a container while the root user is a sign-in identity inside a single account. Organizational units (OUs) are logical groupings of accounts, and the accounts themselves are ordinary AWS accounts: one management account plus members.

Trailbase groups its accounts into organizational units, or OUs: folders in the hierarchy that exist so you can attach policy once and have it apply to every account inside. Production sits in a Workloads OU, development in an SDLC OU, and Theo's playground in a Sandbox OU. The point of the grouping becomes clear the moment Dana writes her first guardrail.


SCPs: The Fence Admins Cannot Move

Monday morning, Dana attaches a policy to the Sandbox OU that denies ec2:RunInstances whenever the requested instance type is large. Theo still has AdministratorAccess. He can still create users, delete buckets, and rearrange the sandbox however he likes. But when he retries the p4d.24xlarge launch, AWS refuses, and no amount of IAM editing inside the account will change that answer, because the refusal comes from a layer he cannot see, let alone modify.

That policy is a Service Control Policy. An SCP works purely by subtraction: it defines the outer boundary of what identities in an account can ever do, and the actual grants still come from IAM policies inside that boundary. Attach an SCP allowing s3:* to an account containing a user with zero IAM policies, and that user can still do nothing. The SCP opened the gate; nobody inside handed the user a key. The JSON is the same policy language you learned in lesson 1, and since 2025 it is the full language.

Service Control Policies

SCPs are organization policies that define the maximum permissions for member accounts. They are boundary policies that set limits without granting anything, they are inherited down through the OU hierarchy, their effect is cumulative (all applicable SCPs must allow an action), and they use the same JSON syntax as IAM policies.

SCPs can control API actions (Allow/Deny), resources (with full ARN support as of 2025), and conditions such as source IP, tags, and regions.

New SCP Capabilities (2025)

AWS now supports full IAM policy language in SCPs:

  • Conditions: Use any IAM condition keys
  • Resource ARNs: Specify individual resources
  • NotAction with Allow: More flexible allow statements
  • NotResource: Exclude specific resources
  • Wildcards: Use * anywhere in action strings

This enables much more granular control than before. Older exam prep material that says SCPs cannot target specific resource ARNs is out of date.

Q

An IAM user in a member account has the AdministratorAccess managed policy attached, yet every attempt to launch an EC2 instance is denied. What is the MOST likely cause?

AUser MFA is not enabled
BAn SCP above the account denies EC2 actions
CThe instance type exceeds an account quota
DThe user needs an explicit Allow in a resource-based policy

Inheritance: Guardrails Flow Downhill

Where you attach an SCP decides who it binds, and the rule is simple: policies flow down the tree. Attach at the Root and every OU and account inherits it. Attach to the Workloads OU and only the accounts under Workloads feel it. For an action to succeed, every SCP on the path from the Root down to the account must allow it. Evaluation is an intersection, so a child OU can never re-allow something a parent denied.

SCP Inheritance Model

SCPs attached to the root apply to every OU and account. SCPs attached to an OU apply to all child OUs and accounts beneath it, and SCPs attached directly to an account apply to that account alone. For an action to be permitted, all applicable SCPs must allow it.

The resulting formula: Effective Permissions = Root SCPs ∩ OU SCPs ∩ Account SCPs ∩ IAM Policies. If any SCP in the path denies an action, the action is denied regardless of IAM policies.

Watch it work at Trailbase. After the operations team once terminated a production instance during a deploy scare, Dana added a termination deny at the Production OU, with an MFA-protected exception role exempted by ARN condition for the rare legitimate case. The production account now inherits two layers of policy without a single policy attached to the account itself:

SCP Inheritance Example

LevelSCPEffect
RootAllow: ec2:*, s3:*, rds:*Maximum permissions for org
Production OUDeny: ec2:TerminateInstancesCannot terminate instances
Account A (in Production)No additional SCPsInherits: Allow EC2/S3/RDS, Cannot terminate
Q

Multiple SCPs apply to an account: one at the root, one on its OU, and one attached directly to the account. How does AWS combine them?

AThe most specific SCP wins
BThe most recently attached SCP wins
CEvery applicable SCP must allow the action (AND logic)
DAny single allowing SCP grants access (OR logic)

The Exemptions Everyone Forgets

A month in, Dana notices something odd in CloudTrail: an action her root-level SCP denies was performed anyway, from the management account. This is by design, and it is the single most tested SCP fact on the exam.

SCP Limitations

SCPs do NOT apply to:

  • Management account: Always exempt from SCPs
  • Service-linked roles: Used by AWS services internally
  • Resource-based policies: SCPs only affect principals in the organization, so a bucket policy granting access to an outside principal is evaluated on its own terms
  • Actions performed by AWS services on your behalf

These exemptions are frequently tested on the exam.

The management account exemption exists so an organization can never lock itself out of its own steering wheel, and it is exactly why Dana keeps that account empty of workloads. The service-linked role exemption matters for the same reason in miniature: Auto Scaling, for example, acts through a service-linked role, and an SCP that appeared to block EC2 launches would silently fail to stop scaling events. Priya, reviewing Trailbase's setup during her audit, called the empty management account the best decision in the whole architecture.

Q

Which of the following is NOT affected by Service Control Policies?

AIAM users in member accounts
BIAM roles in member accounts
CThe management account
DCross-account access into member accounts

Two Ways to Run the Guardrails

Every new organization ships with a managed SCP called FullAWSAccess attached everywhere, which allows everything. From that starting point you have two strategies, and choosing between them is a classic exam decision.

SCP Evaluation Flow
Figure 2: How SCPs are evaluated with IAM policies to determine effective permissions

Deny List Strategy (Recommended)

Start with Allow, add explicit Denies. Keep the FullAWSAccess policy, which allows everything, then attach explicit Deny statements for the actions you want blocked. New AWS services are automatically available the day they launch, the policy set stays simple to maintain, and anyone can read exactly what is blocked. This is the right choice for most organizations.

Allow List Strategy

Only allow explicitly permitted actions. Remove the FullAWSAccess policy and allow specific services and actions; everything else is implicitly denied. The cost is real: every new AWS service must be added by hand, legitimate workloads risk being blocked, and maintenance is heavier. Reserve this for highly regulated industries such as finance and healthcare that require strict control.

Trailbase picks the deny list, and so should almost everyone: the team wants each new AWS service usable on day one, with a short, readable list of forbidden actions. The allow list earns its cost only where a regulator demands that nothing unapproved can ever run.


The Trailbase Guardrail Set

Over the following quarter, Dana and Mara build up five deny-list policies. Each one exists because something happened, or nearly happened, and together they cover the patterns the exam draws from.

The first came from cost review. Development instances kept appearing in far-flung regions where nobody looked at the console, and European hiker data has GDPR residency requirements anyway. So Trailbase pins the whole organization to three approved regions, with an exemption for the admin role so a global operation can never strand them. One caveat for real deployments: global services such as IAM, Route 53, and CloudFront issue their calls through specific regions, so region-pinning SCPs need carve-outs for them.

JSONDeny All Actions Outside Approved Regions
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "DenyUnapprovedRegions",
      "Effect": "Deny",
      "Action": "*",
      "Resource": "*",
      "Condition": {
        "StringNotEquals": {
          "aws:RequestedRegion": [
            "us-east-1",
            "us-west-2",
            "eu-west-1"
          ]
        },
        "ArnNotLike": {
          "aws:PrincipalARN": "arn:aws:iam::*:role/OrganizationAdminRole"
        }
      }
    }
  ]
}

The second policy came straight from Priya's audit findings. CloudTrail is the log that caught nothing during the root-credentials era because there was nothing to attribute; now that it attributes everything, the log itself must be untouchable, even by account admins. The same goes for AWS Config, the service recording each resource's configuration history. Attached at the Root, the policy holds for every account Trailbase will ever create, which is the exam answer whenever a scenario says no user in any account may disable CloudTrail:

JSONPrevent Disabling CloudTrail and Config
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "ProtectCloudTrail",
      "Effect": "Deny",
      "Action": [
        "cloudtrail:DeleteTrail",
        "cloudtrail:StopLogging",
        "cloudtrail:UpdateTrail"
      ],
      "Resource": "*"
    },
    {
      "Sid": "ProtectConfig",
      "Effect": "Deny",
      "Action": [
        "config:DeleteConfigRule",
        "config:DeleteConfigurationRecorder",
        "config:DeleteDeliveryChannel",
        "config:StopConfigurationRecorder"
      ],
      "Resource": "*"
    }
  ]
}

The third enforces encryption. Mara's data pipelines write hiker analytics to S3, and rather than trusting every script to remember the encryption header, the organization denies any unencrypted upload. The Null condition reads as "if the encryption header is absent":

JSONRequire S3 Encryption
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "DenyUnencryptedS3Objects",
      "Effect": "Deny",
      "Action": "s3:PutObject",
      "Resource": "*",
      "Condition": {
        "Null": {
          "s3:x-amz-server-side-encryption": "true"
        }
      }
    }
  ]
}

The fourth protects the protections. S3 Block Public Access is the account-level switch that keeps buckets private, and this policy stops anyone below the security admin role from flipping it:

JSONPrevent Public S3 Buckets
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "DenyPublicBucketACL",
      "Effect": "Deny",
      "Action": [
        "s3:PutBucketPublicAccessBlock",
        "s3:DeletePublicAccessBlock"
      ],
      "Resource": "*",
      "Condition": {
        "ArnNotLike": {
          "aws:PrincipalARN": "arn:aws:iam::*:role/SecurityAdminRole"
        }
      }
    }
  ]
}

The fifth closes the loop on lesson 1. Every member account still has root credentials, and each one is a standing risk. Recall that inside an account, root sits above every IAM policy; inside an organization, an SCP sits above member-account root, so it can do what IAM never could and neutralize that root user entirely.

JSONDeny Root User Actions (Except Specific)
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "DenyRootUser",
      "Effect": "Deny",
      "Action": "*",
      "Resource": "*",
      "Condition": {
        "StringLike": {
          "aws:PrincipalArn": "arn:aws:iam::*:root"
        }
      }
    }
  ]
}

Designing the OU Tree

With the policies written, the remaining question is where they hang, which means designing the OU tree. AWS publishes a recommended structure, and its guiding rule is to organize by function and compliance need rather than by the company reporting chart:

Recommended OU Structure

OUPurposeSCP Focus
SecurityLog Archive, Audit, Security ToolsProtect security resources, deny deletions
InfrastructureNetworking, Shared ServicesProtect shared resources, limit modifications
Workloads/ProductionProduction applicationsDeny dangerous actions, require encryption
Workloads/SDLCDev, Test, StagingMore permissive, allow experimentation
SandboxDeveloper experimentationBudget limits, region restrictions, minimal guardrails
PolicyStagingTest new SCPs before rolloutTest policies safely
TransitionalMigrating/acquired accountsTemporary permissive policies

Two entries deserve a story each. PolicyStaging exists because an SCP typo can take down production in every account at once; Dana tests each new policy against throwaway accounts in that OU before promoting it. Transitional exists for the day Trailbase acquires a smaller trail-mapping startup whose account arrives with unknown workloads: it joins the organization under temporarily permissive policies instead of being strangled by production guardrails on day one.

SCP and OU Best Practices
  1. Use the deny list strategy: Start permissive, add explicit denies
  2. Test before applying: Use a PolicyStaging OU first
  3. Attach at the OU level: Easier to manage at scale than per-account attachments
  4. Create exception roles: Never paint yourself into a corner
  5. Protect security services: CloudTrail, Config, GuardDuty
  6. Monitor with CloudTrail: Audit SCP-denied actions
  7. Organize OUs by function and compliance need, keep the hierarchy shallow (AWS supports 5 levels; 2 or 3 is usually enough), separate production from non-production, and document every policy
Q

A company wants to verify that a new SCP will not break production workloads before rolling it out broadly. What is the recommended approach?

AAttach it to the root and watch CloudTrail for denies
BAttach it to the management account first
CAttach it to a PolicyStaging OU containing test accounts
DSCPs cannot be tested before deployment

Trailbase, Governed

The p4d incident ends as a slide in the onboarding deck. Theo keeps his sandbox admin rights and his salary. The organization now has guardrails that no admin can loosen, an audit trail no admin can silence, and a management account that stays empty precisely because it answers to nothing. Priya signs off on the audit.

Exam Tip

SAA-C03 SCP questions follow a template: some identity has generous IAM permissions yet an action fails, or a requirement says an action must be impossible for everyone, including admins, across all accounts. Both point to SCPs. Then check the twist: management account and service-linked roles are exempt, and all SCPs on the path must allow the action.

Exam Scenarios

ScenarioSolutionWhy
Prevent all users from disabling CloudTrailSCP denying cloudtrail:StopLogging at rootSCPs are preventive guardrails that cannot be overridden
Allow EC2 in us-east-1 onlySCP with region conditionConditions can restrict to specific regions
User has IAM admin access but cannot launch EC2SCP is denying EC2 actionsSCPs limit maximum permissions, even for admins
Management account can still perform denied actionExpected behaviorSCPs do not affect the management account
Need to test new SCP before productionApply to PolicyStaging OU firstTest impact on non-production accounts
Lambda function denied by SCP but it uses service-linked roleService-linked roles are exemptSCPs do not affect service-linked roles
Acquired company needs temporary permissive accessPlace in Transitional OUMinimal restrictions during migration
Consolidate billing across 10 accountsAWS Organizations consolidated billingSingle payment method for all member accounts

Common Pitfalls

Locking Yourself Out

An SCP that denies iam:* or organizations:* too broadly can leave nobody able to undo it, and recovery may require AWS Support. Always keep a break-glass exception role exempted by condition, and stage every policy in the PolicyStaging OU before it touches real accounts.

Trusting SCPs to Guard the Management Account

The management account is never affected by SCPs, so any workload running there runs without guardrails. Keep that account empty, restrict who can access it, and rely on tightly scoped IAM policies for the few humans who sign in.

Expecting a Child Allow to Beat a Parent Deny

Inheritance is cumulative AND logic flowing downward. Every SCP on the path from root to account must allow an action, so an allow attached lower in the tree can never restore what a parent denied. Plan the hierarchy before attaching anything: broad allows at the root, targeted denies below.

Allow Lists in Fast-Moving Environments

With an allow list strategy, every new AWS service is blocked until someone updates the SCP, which turns the security team into a bottleneck. Reserve allow lists for regulated environments that genuinely require them, and automate the updates if you must run one.


Quick Reference

SCP Service Limits

LimitValue
Maximum SCPs per organization1,000
Maximum SCPs per OU or account5
Maximum SCP document size5,120 characters
Maximum OU nesting depth5 levels

SCP vs IAM Policies

AspectSCPIAM Policy
PurposeSet maximum permissionsGrant permissions
ScopeOrganization/OU/AccountUser/Group/Role
Grants AccessNo - only restrictsYes
Affects Management AccountNoYes
Affects Service-Linked RolesNoLimited
InheritanceYes - through OU hierarchyNo automatic inheritance
SHCommon AWS Organizations CLI Commands
# List all SCPs in organization
aws organizations list-policies --filter SERVICE_CONTROL_POLICY

# Get SCP content
aws organizations describe-policy --policy-id p-abc123def

# Create new SCP
aws organizations create-policy \
  --name "DenyUnapprovedRegions" \
  --description "Prevents use of unapproved regions" \
  --type SERVICE_CONTROL_POLICY \
  --content file://scp-deny-regions.json

# Attach SCP to OU
aws organizations attach-policy \
  --policy-id p-abc123def \
  --target-id ou-root-example

# Detach SCP from OU
aws organizations detach-policy \
  --policy-id p-abc123def \
  --target-id ou-root-example

# List OUs in organization
aws organizations list-organizational-units-for-parent \
  --parent-id r-abc1

# Move account to different OU
aws organizations move-account \
  --account-id 123456789012 \
  --source-parent-id ou-source \
  --destination-parent-id ou-destination
TEXTUseful SCP Condition Keys
aws:RequestedRegion       - Restrict by AWS region
aws:PrincipalArn         - Match principal ARN pattern
aws:PrincipalOrgID       - Ensure principal is in org
aws:PrincipalTag/*       - Match principal tags
aws:ResourceTag/*        - Match resource tags
aws:SourceIp             - Restrict by source IP
ec2:InstanceType         - Restrict instance types
s3:x-amz-server-side-encryption - Require encryption


Further Reading

Related services

OrganizationsIAM