SCPs, RCPs, and declarative policies

Lesson 3 of 5 in The Multi-Account Foundation.

This is the page to know cold. A service control policy sets the maximum available permissions for the accounts it covers. It is a filter, not a grant: an SCP that "allows" s3:* gives nobody anything. For a call to succeed in a member account it must be allowed by the SCP chain and by an identity-based policy (and, for a cross-account or resource-policy call, by the resource policy too). Remove the permission from the SCP and the most generous AdministratorAccess in the account becomes decoration.

Four exemptions are worth memorising, because each one is a question.

SCPs do not restrict the management account. Users and roles there are unaffected by any SCP, whatever you attach, which is the sharpest reason the management account stays empty.

SCPs do not restrict service-linked roles. AWS services must keep working regardless of your policy, so an SCP denying ec2:* does not stop an Auto Scaling service-linked role from acting.

SCPs do restrict the account root user in member accounts. "Use the root user to get around the SCP" is always wrong.

FullAWSAccess is attached by default to the root, every OU and every account. While it is attached you are running a deny-list model: everything is permitted except what a Deny takes away. Detach it and you have switched the whole subtree to an allow-list model, where only explicitly allowed actions survive — powerful, and the fastest way to break an organization before lunch.

Inheritance is intersection. An account's effective ceiling is the intersection of every SCP along its path — root, each OU down the tree, and the account itself. A permission must survive every level. This has a consequence candidates get wrong: attaching a more permissive SCP to a child OU cannot restore what a parent took away. There is no override, no precedence, no "closest wins". If the root's SCP omits dynamodb:*, nothing below the root can use DynamoDB, period.

The two strategies in policy terms:

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "DenyLeavingTheOrganization",
      "Effect": "Deny",
      "Action": ["organizations:LeaveOrganization"],
      "Resource": "*"
    },
    {
      "Sid": "ProdRegionsOnly",
      "Effect": "Deny",
      "NotAction": ["iam:*", "sts:*", "cloudfront:*", "route53:*", "support:*"],
      "Resource": "*",
      "Condition": {
        "StringNotEquals": { "aws:RequestedRegion": ["eu-west-1", "eu-central-1"] }
      }
    }
  ]
}

That is a deny-list SCP, and it shows the syntax rule the exam likes: all the nuance lives in Deny. An Allow statement in an SCP must use "Resource": "*" and cannot carry a Condition, so Region restrictions, tag requirements and MFA requirements are expressed as denials. Note the NotAction exclusions — global services report a home Region of us-east-1, and a naive Region deny locks you out of IAM and CloudFront. SCPs are capped at 5,120 characters and five policies per target, which is why organizations run a small number of carefully composed policies rather than one per rule.

An SCP has one blind spot, and it is structural: it constrains principals in your organization. It has nothing to say about a principal in someone else's account calling your bucket, because that caller is not in your organization and no SCP of yours applies to them. For years the only answer was a resource policy on every single resource, maintained correctly, forever.

Resource control policies close that side. An RCP attaches to the root, an OU or an account exactly like an SCP, but it caps access to resources in the accounts it covers — for any caller, including principals from outside your organization and anonymous ones. Same mental model, mirrored: it never grants, RCPFullAWSAccess is attached by default, it does not apply to resources in the management account, and it does not affect requests made by service-linked roles.

The canonical RCP is the organization data perimeter:

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "OnlyOurOrgAndAwsServices",
      "Effect": "Deny",
      "Principal": "*",
      "Action": ["s3:*", "sts:AssumeRole", "kms:*", "sqs:*", "secretsmanager:*"],
      "Resource": "*",
      "Condition": {
        "StringNotEqualsIfExists": { "aws:PrincipalOrgID": "o-exampleorgid" },
        "BoolIfExists": { "aws:PrincipalIsAWSService": "false" }
      }
    }
  ]
}

One policy at the root and every covered resource in every account — including buckets created tomorrow by a team that has never read your standards — rejects callers from outside the organization. The one caveat to carry into the exam room: RCPs cover a specific list of services, not everything. They launched with Amazon S3, AWS STS, AWS KMS, Amazon SQS and AWS Secrets Manager and the list has grown since, so an RCP is only the answer when the service in the stem is on it — check the current list rather than assuming total coverage the way you can with an SCP.

The organization policy types — what each caps, what it attaches to, and whether it can ever grant. All four need all-features mode and the policy type enabled on the root first.
Policy typeWhat it capsAttaches toCan it grant?Reach

Service control policy (SCP)

What your principals may do — the maximum available permissions in covered accounts

Root · OU · account

No — it only filters what identity policies can allow

All principals in member accounts, including their root users. Not the management account; not service-linked roles

Resource control policy (RCP)

What may be done to your resources — by any caller, including principals outside the organization

Root · OU · account

No — same filter semantics, mirrored onto resources

A specific list of services, not all of them — S3, STS, KMS, SQS and Secrets Manager at launch, extended since. Not resources in the management account; not service-linked roles

Declarative policy

A service configuration baseline — the setting stays as you declared it, and keeps applying as the service ships new features and APIs

Root · OU · account

No — it enforces configuration, not permissions

Supported configuration attributes, centred on Amazon EC2 and its VPC/EBS settings as of Oct 2026 (allowed AMIs, public-access blocks, IMDS defaults, serial console)

AI services opt-out policy

Whether covered AWS AI services may store and use your content to improve those services

Root · OU · account

No — it is a consent setting, per service or all services

The AI services AWS lists as covered; set once at the root rather than per account

Tag policy

The shape of tag keys and values — standardizing capitalization and allowed values

Root · OU · account

No — and it does not require a tag to be present

Reports non-compliant tagging; enforcement for a resource type can be switched on, but mandatory tagging is an IAM condition job

Two of those deserve a sentence more. Declarative policies answer a problem SCPs genuinely cannot: a configuration baseline that does not rot. If you deny the API that disables EBS encryption by default, you have blocked today's API — and next year's new API, or new console path, walks around it. A declarative policy states the intended configuration ("public access to AMIs is blocked", "only these AMI owners are allowed", "instance metadata defaults to IMDSv2") and AWS keeps enforcing that intent as the service evolves, reporting the enforced state per account. The exam phrasing to recognise is "must remain enforced even as new service features are released".

AI services opt-out policies are the easy mark and worth the free point: a data-governance requirement that content processed by AWS AI services must not be stored or used for service improvement is one organization policy attached at the root, not a support ticket and not a per-service console setting.

Key terms: Service control policy (SCP), Resource control policy (RCP), Declarative policy, AI services opt-out policy, Allow-list strategy (SCP), Policy inheritance (effective permissions)

Interactive checkpoint quiz (3 questions) — open this page in a browser to take it.