Safeguard
Cloud Security

How to set up AWS Organizations Service Control Policies

A practical, command-by-command guide to AWS Organizations SCP setup — from enabling policy types to real guardrail examples, rollout, and troubleshooting.

Karan Patel
Cloud Security Engineer
8 min read

If you're responsible for a growing AWS footprint, you already know that IAM policies alone don't stop a developer from spinning up resources in an unapproved region, disabling CloudTrail, or leaving your organization entirely. That's the gap Service Control Policies (SCPs) close. A solid AWS Organizations SCP setup lets you enforce account-wide guardrails centrally, so no single account — no matter who has admin rights inside it — can violate your security baseline.

This guide walks through a complete AWS Organizations SCP setup from scratch: enabling the feature, structuring your organizational units, writing real service control policy examples, attaching and testing policies, and troubleshooting the deny-by-default behavior that trips up most first-time implementers. By the end, you'll have working guardrails deployed across a multi-account environment and a repeatable process for adding more.

Step 1: Prerequisites for Your AWS Organizations SCP Setup

Before writing a single policy, confirm your organization is configured to support SCPs at all.

You need:

  • An AWS Organizations management account with all features enabled (not "consolidated billing" mode — SCPs require the full feature set).
  • Organization admin permissions, or a delegated administrator account for Organizations.
  • A clear picture of your account structure — root, OUs, and member accounts.

Check your current mode with the CLI:

aws organizations describe-organization

Look for "FeatureSet": "ALL" in the output. If it returns CONSOLIDATED_BILLING, you'll need to enable all features first:

aws organizations enable-all-features

Every account in the organization must accept this change (an email invitation is sent automatically), so budget time for that before moving on — you cannot attach SCPs until every account has confirmed.

Step 2: Enable the Service Control Policy Type

Even with all features on, SCPs are a policy type that has to be explicitly turned on for the organization:

aws organizations enable-policy-type \
  --root-id r-abcd \
  --policy-type SERVICE_CONTROL_POLICY

Grab your root ID first if you don't have it handy:

aws organizations list-roots

Verify it took effect:

aws organizations list-roots \
  --query 'Roots[0].PolicyTypes'

You should see SERVICE_CONTROL_POLICY with "Status": "ENABLED".

Step 3: Design an OU Structure That Matches Your Governance Model

SCPs are only as effective as the account structure they're layered onto. Most teams organizing for aws multi account governance land on something like:

Root
├── Security-OU        (log archive, audit accounts)
├── Infrastructure-OU   (shared networking, tooling)
├── Workloads-OU
│   ├── Production-OU
│   ├── Staging-OU
│   └── Sandbox-OU
└── Suspended-OU        (offboarded / quarantined accounts)

This matters because SCPs inherit down the tree — a policy on Root applies everywhere, a policy on Production-OU applies only to accounts nested under it. Put your strictest, non-negotiable guardrails (region restrictions, root user lockdown) at the root, and reserve environment-specific rules (like blocking expensive instance types in sandbox) for lower-level OUs.

Create OUs via CLI or the console:

aws organizations create-organizational-unit \
  --parent-id r-abcd \
  --name "Production-OU"

Step 4: Write Your First SCP — Common Guardrail Patterns

Here are several service control policy examples that cover the most common guardrails teams ask for. Remember: SCPs never grant permissions — they only set the outer boundary of what IAM policies inside an account can allow.

Deny actions outside approved regions:

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "DenyOutsideApprovedRegions",
      "Effect": "Deny",
      "NotAction": [
        "iam:*",
        "organizations:*",
        "route53:*",
        "cloudfront:*",
        "support:*"
      ],
      "Resource": "*",
      "Condition": {
        "StringNotEquals": {
          "aws:RequestedRegion": ["us-east-1", "us-west-2"]
        }
      }
    }
  ]
}

Prevent root user activity:

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "DenyRootUser",
      "Effect": "Deny",
      "Action": "*",
      "Resource": "*",
      "Condition": {
        "StringLike": {
          "aws:PrincipalArn": "arn:aws:iam::*:root"
        }
      }
    }
  ]
}

Block accounts from leaving the organization or disabling CloudTrail:

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "ProtectOrgAndAudit",
      "Effect": "Deny",
      "Action": [
        "organizations:LeaveOrganization",
        "cloudtrail:StopLogging",
        "cloudtrail:DeleteTrail"
      ],
      "Resource": "*"
    }
  ]
}

Save each as its own file and create the policy:

aws organizations create-policy \
  --name "DenyOutsideApprovedRegions" \
  --description "Restrict services to us-east-1 and us-west-2" \
  --type SERVICE_CONTROL_POLICY \
  --content file://deny-region.json

Step 5: Attach Policies to OUs and Accounts

With the policy created, attach it to the appropriate OU (or a single account, if you're piloting first):

aws organizations attach-policy \
  --policy-id p-examplepolicyid \
  --target-id ou-abcd-11111111

Best practice for any scp guardrails tutorial worth following: pilot on one non-production account or a sandbox OU before rolling out org-wide. SCP mistakes can lock out legitimate access instantly, including for admins, so a staged rollout with a rollback plan matters more here than with almost any other AWS control.

Step 6: Layer Policies Deliberately

Because SCPs are additive restrictions (the effective permission set is the intersection of every SCP in the hierarchy plus IAM), avoid stacking broad Deny * statements without carve-outs. A common mistake is attaching a full-service deny policy to Root and then discovering it blocks the very IAM or Organizations calls needed to manage the guardrails themselves. Always exclude iam, organizations, sts, and support actions from broad region- or service-based denies unless you mean to block those too.

Keep an inventory of every attached SCP and which OU it lives on — a simple spreadsheet or, better, infrastructure-as-code (Terraform's aws_organizations_policy resource, or AWS CloudFormation) so policies are versioned and reviewable like any other code change.

Step 7: Test and Validate Before Wide Rollout

Before attaching a new SCP broadly, validate it against real API calls using the IAM policy simulator or by testing directly in a sandbox account:

aws organizations list-policies-for-target \
  --target-id 111122223333 \
  --filter SERVICE_CONTROL_POLICY

This shows every SCP currently affecting an account — useful for confirming a new policy is actually attached and for debugging conflicts between inherited policies.

Troubleshooting and Verification

"AccessDenied" errors appear even though IAM allows the action. This is expected SCP behavior — SCPs set the ceiling, and IAM still needs an explicit allow underneath. Check both layers: run list-policies-for-target on the account to see the full SCP stack, then confirm the IAM policy for the calling principal also allows the action.

A new SCP doesn't seem to apply. Confirm it's attached to the correct target with aws organizations list-targets-for-policy --policy-id <id>. Remember that SCPs apply to an account's root user and all IAM principals within it, but never to the management account itself — SCPs never restrict the organization's management account.

Policy exceeds the size limit. SCPs are capped at 5,120 characters. Split large policies by function (region restriction, service restriction, root lockdown) rather than combining everything into one document — this also makes them easier to review and roll back independently.

Locked out after attaching a policy. Detach immediately from the management account or via the root using an account that still has access (this is why piloting on a single account first, not the root, is worth the extra step). Keep a documented "break-glass" account excluded from restrictive SCPs for exactly this scenario.

Verifying org-wide compliance. Periodically audit effective policies across every account, not just what's attached at each OU, since inheritance can produce combinations that are easy to lose track of as the organization grows. AWS Config aggregators and CloudTrail organization trails both help confirm guardrails are actually being enforced, not just present on paper.

How Safeguard Helps

Writing and attaching SCPs is only half the job — the harder, ongoing problem is knowing whether your guardrails still match your actual environment as accounts, OUs, and workloads multiply. Safeguard continuously maps your AWS Organizations structure and the effective policy set on every account, flagging drift the moment an SCP is loosened, detached, or overridden by a newer policy that reintroduces a gap you thought was closed.

Because Safeguard is built for software supply chain security, it pays particular attention to the accounts and OUs that touch your build and release pipeline — CI/CD runners, artifact registries, deployment roles — correlating SCP guardrails with the permissions actually exercised by those principals. That means you find out if a pipeline account can still reach an unapproved region or an unrestricted IAM action long before an auditor or an attacker does.

Safeguard also keeps an audit-ready history of every SCP change across your organization, which maps directly to the change-management evidence SOC 2 and similar frameworks expect, so your multi-account governance program produces its own compliance trail without extra manual tracking. If you're rolling out SCPs for the first time or hardening an existing setup, Safeguard gives you the visibility to confirm your guardrails are doing what you designed them to do — across every account, every time.

Never miss an update

Weekly insights on software supply chain security, delivered to your inbox.