Skip to content
AWS aws iam 5 min read

Organizations & SCPs

As a company grows on AWS, one account is rarely enough. You end up with separate accounts for production, staging, security tooling, and individual teams. AWS Organizations is the service that lets you manage all of those accounts as one family, with central billing and shared rules. Service Control Policies (SCPs) are the rules part: account-wide guardrails that set the maximum permissions anyone in an account can ever have. This page explains how the two work together and how to write SCPs that stop expensive or dangerous mistakes before they happen.

What is AWS Organizations?

AWS Organizations is a free service for managing multiple AWS accounts from one place. You create an organization, which has one management account (the account that pays the bills and controls the whole org) and any number of member accounts.

Accounts are arranged in a tree using Organizational Units (OUs) — folders that group accounts so you can apply the same rules to all of them. A typical layout looks like this:

Root
├── OU: Security        (log-archive account, audit account)
├── OU: Production       (prod-app, prod-data)
└── OU: Sandbox          (dev-alice, dev-bob)

The main benefits are consolidated billing (one invoice, volume discounts shared across accounts), central account creation, and policy-based controls like SCPs.

When to use this: as soon as you have more than one AWS account, or you expect to. Isolating workloads in separate accounts is the strongest blast-radius boundary AWS offers. When not to: a single hobby project in one account does not need an organization yet.

What is a Service Control Policy (SCP)?

An SCP (Service Control Policy) is a JSON document that defines a permission ceiling for an account or OU. It looks almost identical to an IAM policy, but it behaves very differently.

The single most important rule to memorize:

An SCP never grants permission. It only filters. The actual permissions a user has are the intersection of what their IAM policies allow AND what the SCPs allow. If either side says no, the answer is no.

Three more gotchas that trip up almost everyone:

  • SCPs do not affect the management account. Guardrails you attach apply only to member accounts. Keep nothing but billing and org management in the management account.
  • An SCP Deny overrides everything, including an IAM Allow written by a full account administrator. You cannot escape an SCP from inside the account.
  • You still need IAM policies that grant access. An SCP that allows everything does not magically give a user permissions.

When to use SCPs: to enforce non-negotiable, organization-wide rules — “no one may turn off our audit logging,” “we only operate in eu-west-1.” When not to: for per-user, day-to-day permissions. That is the job of ordinary IAM policies inside each account.

SCP strategies — Allow list vs Deny list

StrategyHow it worksWhen to use
Deny list (default)Start from the AWS-managed FullAWSAccess SCP (allows everything), then attach SCPs that Deny specific things.Most teams. Easy to start, block risky actions as you find them.
Allow listRemove FullAWSAccess and explicitly Allow only approved services.Highly regulated environments that must whitelist a small service set.

Start with a deny list. Allow lists are powerful but easy to get wrong, and a missing Allow silently breaks workloads.

Enabling SCPs

SCPs are a feature you must turn on once for the whole organization, from the management account.

Console steps:

  1. Sign in to the management account and open the AWS Organizations console.
  2. In the left nav choose Policies.
  3. Choose Service control policies, then Enable service control policies.

AWS CLI:

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

Output:

{
    "Root": {
        "Id": "r-ab12",
        "Arn": "arn:aws:organizations::111122223333:root/o-aa111bb222/r-ab12",
        "Name": "Root",
        "PolicyTypes": [
            { "Type": "SERVICE_CONTROL_POLICY", "Status": "ENABLED" }
        ]
    }
}

A common guardrail SCP

Here is a realistic, frequently used SCP. It does two things every security team wants: it denies leaving an approved Region (so resources can’t be created where you don’t monitor them or where data residency rules forbid), and it denies disabling CloudTrail (CloudTrail is the audit log of every API call — turning it off blinds your security team).

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "DenyOutsideApprovedRegions",
      "Effect": "Deny",
      "NotAction": [
        "iam:*",
        "sts:*",
        "organizations:*",
        "cloudfront:*",
        "route53:*",
        "support:*"
      ],
      "Resource": "*",
      "Condition": {
        "StringNotEquals": {
          "aws:RequestedRegion": ["eu-west-1", "us-east-1"]
        }
      }
    },
    {
      "Sid": "DenyDisablingCloudTrail",
      "Effect": "Deny",
      "Action": [
        "cloudtrail:StopLogging",
        "cloudtrail:DeleteTrail",
        "cloudtrail:UpdateTrail"
      ],
      "Resource": "*"
    }
  ]
}

Why NotAction for the Region block? Some services are global and only “live” in us-east-1 (such as IAM and CloudFront). If you blanket-deny everything outside your Regions, you accidentally break those global services. NotAction exempts them while still blocking everything else.

Creating and attaching the SCP

Console steps:

  1. Save the JSON above to a file, e.g. region-and-trail-guardrail.json.
  2. In Organizations → Policies → Service control policies, choose Create policy.
  3. Paste the JSON, give it a name like Guardrail-RegionAndCloudTrail, and choose Create policy.
  4. Open the target OU or account, go to the Policies tab, choose Attach, and select your policy.

AWS CLI:

# 1. Create the policy
aws organizations create-policy \
  --name "Guardrail-RegionAndCloudTrail" \
  --description "Block non-approved Regions and CloudTrail tampering" \
  --type SERVICE_CONTROL_POLICY \
  --content file://region-and-trail-guardrail.json

# 2. Attach it to the Production OU
aws organizations attach-policy \
  --policy-id p-examplescp1 \
  --target-id ou-ab12-prod1234

Output:

{
    "Policy": {
        "PolicySummary": {
            "Id": "p-examplescp1",
            "Arn": "arn:aws:organizations::111122223333:policy/o-aa111bb222/service_control_policy/p-examplescp1",
            "Name": "Guardrail-RegionAndCloudTrail",
            "Type": "SERVICE_CONTROL_POLICY",
            "AwsManaged": false
        }
    }
}

Cost note: AWS Organizations and SCPs are completely free. There is no charge for creating policies or attaching them. The real “cost saving” is indirect — a Region guardrail prevents an engineer from accidentally launching expensive instances in a Region you forgot to monitor, which is a common source of surprise bills.

Best practices

  • Keep the management account empty. Run no workloads there; SCPs cannot protect it, so it must hold only billing and org administration.
  • Start with a deny list built on FullAWSAccess, and add targeted Deny statements as your security needs grow.
  • Test in a Sandbox OU first. Attach a new SCP to a test OU and confirm nothing breaks before rolling it out to Production.
  • Protect your audit trail. Always deny cloudtrail:StopLogging and cloudtrail:DeleteTrail so no one can hide their tracks.
  • Use NotAction carefully when restricting Regions so you don’t break global services like IAM, CloudFront, and Route 53.
  • Remember SCPs only filter — keep granting day-to-day access through normal IAM policies inside each account.
  • Document each SCP’s intent in its description so future engineers know why a guardrail exists before they try to remove it.
Last updated June 15, 2026
Was this helpful?