Skip to content

Keyboard shortcuts

Go

  • Scope — the control cataloggm
  • Plan — your last certification classgp
  • Collect — the recipe indexgc
  • The control you are workinggw
  • Startgh

Move

  • Next rowj
  • Previous rowk
  • Previous in this run[
  • Next in this run]
  • Filter this page's list/
  • Search everythingK

Act

  • Copy this page's permalinky
  • Toggle dark moded
  • This sheet?

Rows are whatever the current page lists — controls on Scope, recipes on Plan and Collect.

Control index

The enforced half of who may change what: the service control policy type actually enabled in the organization root, the customer-authored SCPs and the roots, OUs and accounts each one is attached to, and the permissions boundary carried by every principal your own tagging marks as a change authority

The API supplies the facts, but a human judgement against a documented baseline turns them into evidence.

partial — needs judgementclicontinuousAWS OrganizationsAWS IAM

Fetch

$ aws organizations describe-organization
$ aws organizations list-roots
$ aws organizations list-policies --filter SERVICE_CONTROL_POLICY
$ aws organizations describe-policy --policy-id <CUSTOMER_AUTHORED_SCP_ID>
$ aws organizations list-targets-for-policy --policy-id <CUSTOMER_AUTHORED_SCP_ID>
$ aws iam get-account-authorization-details --filter User Role

Expected output

All six responses are collected unprojected, so every field below is the name AWS returns and the name the assertions address. The first three calls take no argument; calls four and five take a policy id that MUST be one of the AwsManaged false ids returned by call three — a human substitution the assertion grammar cannot make, and the reason the placeholder is named CUSTOMER_AUTHORED_SCP_ID rather than POLICY_ID. Call six must be issued with MANAGEMENT-ACCOUNT credentials: Organizations operations may also be called from a member account designated as a delegated administrator, and a collection run there returns that member account's principals while reading exactly like the management account's. From describe-organization, an Organization object with Id, Arn, MasterAccountId, MasterAccountEmail and FeatureSet, which is ALL or CONSOLIDATED_BILLING; AvailablePolicyTypes is also returned and is DEPRECATED by AWS, which documents that it omits every policy type other than SCPs and directs you to ListRoots instead. From list-roots, Roots[] with Id, Arn, Name and PolicyTypes[], each entry carrying Type and a Status that is ENABLED, PENDING_ENABLE or PENDING_DISABLE — there is no DISABLED value, because a policy type that is off is ABSENT from the list rather than reported as off. From list-policies, Policies[] with Id, Arn, Name, Description, Type and AwsManaged, a boolean that is true for policies you cannot edit; AWS attaches the managed FullAWSAccess policy to every root, OU and account when it is created, so the list is never empty on an organization with SCPs enabled and its length says nothing about whether anyone has authored a restriction. From describe-policy, a Policy object with a PolicySummary carrying the same six fields as a list entry, and Content — the policy document itself, returned as a JSON-formatted STRING that must be parsed before any statement in it can be read. From list-targets-for-policy, Targets[] with TargetId, Arn, Name and a Type of ACCOUNT, ORGANIZATIONAL_UNIT or ROOT. From get-account-authorization-details, UserDetailList[] and RoleDetailList[] with UserName/RoleName, CreateDate, Tags, the attached and inline policy lists, and PermissionsBoundary — an optional AttachedPermissionsBoundary object carrying PermissionsBoundaryType and PermissionsBoundaryArn, absent entirely on a principal that has none.

Assertions — what makes it a pass

Assertions for The enforced half of who may change what: the service control policy type actually enabled in the organization root, the customer-authored SCPs and the roots, OUs and accounts each one is attached to, and the permissions boundary carried by every principal your own tagging marks as a change authority: the field checked, the condition it must satisfy, the rows it applies to, and the controls a pass proves.
FieldMust beForProves
describe-organization.Organization.FeatureSeteq "ALL"The organization has all features enabled. SCPs are available only in an organization with all features enabled; on CONSOLIDATED_BILLING every policy this recipe collects is inert. Mandatory, and therefore uninformative, in GovCloud.every rowCM-05
list-roots.Roots[0].PolicyTypes[?Type=='SERVICE_CONTROL_POLICY'] | [0].StatusexistsThe SCP policy type appears in the root at all. A policy type that is off is absent from PolicyTypes[] rather than carrying a DISABLED status — the enum has no such value — so the clause below passes vacuously over an organization where SCPs were never enabled. The pipe is load-bearing: without it the [0] indexes each matched string rather than the filtered list, and the expression is empty whether the entry is present or not.every rowCM-05
list-roots.Roots[].PolicyTypes[?Type=='SERVICE_CONTROL_POLICY'].Statuseq "ENABLED"The SCP policy type is enabled rather than mid-transition; PENDING_DISABLE is an organization on its way to enforcing nothing.every rowCM-05
list-policies.Policies[?AwsManaged==`false`] | [0].IdexistsAt least one SCP in the organization was authored by you. AWS attaches the managed FullAWSAccess policy to every root, OU and account at creation, so a non-empty Policies[] is the default state of a working organization and not a restriction anyone wrote. The pipe is load-bearing for the same reason as the root clause above.every rowCM-05
list-targets-for-policy.Targets[0].TargetIdexistsThe customer-authored SCP passed to call five is attached to a root, an OU or an account. This clause proves attachment ONLY because the command is bound to an AwsManaged false id: run against any policy id it is satisfied by FullAWSAccess, which AWS attaches to every root, OU and account at creation. Binding it is a human step — the grammar compares a field to a constant, never one command's output to another's — so a collector that substitutes an arbitrary policy id has produced a green result about the AWS default.every rowCM-05
get-account-authorization-details.RoleDetailList[?not_null(Tags[?Key=='ChangeAuthority' && Value=='true'] | [0]) && !PermissionsBoundary]count_eq 0No role your own tagging marks as a change authority is missing a permissions boundary — the per-principal ceiling that applies inside the management account, where SCPs do not reach. Written as an OFFENDER LIST rather than as 'every role has a boundary', because a field projection over a list DROPS the rows that lack the field instead of reporting them false, so the every-row form silently answers about the compliant rows only. Zero on an estate that tags no roles, so read it beside the tag count. The call must be run with management-account credentials or it describes a different account's roles.every rowCM-05

Authored opinion, like the commands. Units live in the operator name — max-age-days is days, and nothing here is converted for you.

Map — what it proves

  • recipe1
Key Security Indicators
NIST 800-53 controls
  • recipean authored recipe collects evidence for this control
  • KSI onlya Key Security Indicator reaches it, but no recipe is authored yet
  • orphanno Key Security Indicator reaches it — a person writes it up instead

What else these families can fetch:CM 14/34

GovCloud

AWS Organizations is available in both AWS GovCloud (US) Regions and SCPs are one of the policy types a GovCloud organization may use, alongside RCPs, tag policies and declarative policies for EC2 and S3; backup, chat application and AI services opt-out policies cannot be created there. Organization, root, OU, account, policy and IAM ARNs use partition arn:aws-us-gov. Three GovCloud facts change how this recipe is run rather than what it means. All features are MANDATORY — the consolidated billing feature set is not offered — so FeatureSet reads ALL in every GovCloud organization and the first assertion is satisfied by the Region rather than by a decision anyone made. The SECOND call is the one with a Region constraint: AWS restricts any operation that references the organization root, naming ListRoots as its example, to the AWS GovCloud (US-West) Region, so list-roots must be issued against us-gov-west-1 regardless of where the workload runs. The other five calls carry no such restriction. And a GovCloud organization is INDEPENDENT of the commercial organization its accounts are paired with: SCPs attached in the commercial organization do not restrict the GovCloud accounts, and an assessor handed a commercial organization's policy list has been handed evidence about a different boundary.

Notes & assertions

CM-5 asks for physical AND logical access restrictions associated with changes that are defined, documented, approved and enforced. This recipe reaches one adjective and one verb. The adjective it does not reach is PHYSICAL. No AWS API returns anything about physical access to the hardware a change is made on; under the shared responsibility model that half belongs to the IaaS provider and is inherited — read it from the provider's own authorization package and the FedRAMP customer responsibility matrix, not from this output. A collection that presents these six calls as CM-5 evidence without saying so has answered half a control and labelled it whole. The verb it does reach is ENFORCE, and it reaches it properly: an SCP is not a description of a restriction, it is the restriction, evaluated by AWS on every request from every member account, and list-targets-for-policy is the difference between a policy that exists and a policy that applies to something. Two gaps keep this partial, not one. The first is approval — that the enforced set IS the documented and approved set is a comparison against a change-management record, and no call returns it. The second is subject matter, and it is the easier one to miss: the assertions below show THAT a customer-authored SCP is enforced, never WHAT it restricts. An SCP denying mechanicalturk:* satisfies every clause here exactly as well as one denying ec2:ModifyInstanceAttribute. The fourth call exists to close that by putting the policy document in the evidence — Content is returned as a JSON string and must be parsed — but no assertion can grade a policy document, so the phrase that makes this CM-5 rather than AC-3, 'associated with changes', stays a human read. Both gaps are reconciliations against your own records; the reconciliation is the CM-5 artifact and this output is the column it is reconciled against. Four ways this evidence is vacuous if it is read naively. Three are behaviour AWS documents in as many words; the fourth is an inference from a field being a list, flagged as such rather than dressed up as a citation. A policy type that has never been enabled is ABSENT from Roots[].PolicyTypes rather than present with a Status of DISABLED — the enum has no such value — so a clause of the form 'every SCP policy type entry is ENABLED' is true over an organization where SCPs were never turned on at all, which is why one assertion tests that the entry exists before another reads it. AWS attaches the managed FullAWSAccess policy to EVERY root, OU and account when it is created, so both a non-empty Policies[] and a non-empty Targets[] are the default state of a working organization rather than a restriction anyone wrote — which is why one assertion counts only the AwsManaged false subset, and why calls four and five are bound to a customer-authored policy id instead of any policy id. FeatureSet CONSOLIDATED_BILLING makes SCPs unavailable outright, so on such an organization every policy in the list is inert. And an SCP attached to nothing returns an empty Targets[]: that one AWS does not state, it follows from Targets being a list, and the assertion that rests on it should be read as an inference. The scope edge that matters most to an assessor is that SCPs do not restrict the management account. AWS states this three times on its own page and lists it first among the tasks SCPs cannot restrict: SCPs affect only member accounts, including member accounts designated as delegated administrators, and they have no effect on users or roles in the management account. The account with the broadest reach over the organization is the one account this evidence says nothing about, and its change restrictions have to come from identity-based policy and permission boundaries inside it — which is what the sixth call collects, and why the sixth call has to be run there. SCPs also do not affect service-linked roles at all, and they do not affect principals from accounts outside the organization even when a resource-based policy in your account grants those principals access. Read an SCP for what it is: a ceiling, never a grant. AWS is explicit that no permissions are granted by an SCP and that effective permissions are the intersection of what the SCP allows with what identity-based and resource-based policies allow — a principal with no IAM permissions has no access under the most permissive SCP in the world. Where a permissions boundary is also present, AWS documents that the boundary, the SCP and the identity-based policy must ALL allow the action, which is why the sixth call is collected beside the first five rather than instead of them. One failure mode worth writing into the assessment because it is silent and total: disabling the SCP policy type in a root automatically detaches every SCP from every OU, account and organization in that root, and re-enabling it does not restore the attachments — the root reverts to FullAWSAccess alone and the previous attachments are lost and not automatically recoverable. After such an event list-policies still returns every authored policy, unchanged, while nothing is enforced anywhere. The Roots[].PolicyTypes reading and the Targets[] reading are what separate those two worlds, and a collection that skips them cannot tell them apart. The permissions-boundary assertion is scoped by your own tagging rather than written as a claim over the account, for the same reason as in the AC-02 (02) recipe: no AWS call knows which of your roles are supposed to be the change authorities. It passes without saying anything on an estate that tags none, so treat the tagging standard as a written control with a manual sample rather than as coverage. What actually happened, as opposed to what was permitted, is a different recipe: CloudTrail's non-read-only event history, collected under CM-03 alongside the Config resource timeline and the Systems Manager change-request records. This one is about the restriction; that one is about the change.

References

This AWS mapping is authored opinion (overlay v3.0.0), versioned separately from the dataset and written against ruleset 2026.07.14.01. The upstream FedRAMP dataset names none of these tools.

The Change Management run (7)

  • automatable
  • partial — needs judgement
  • narrative — no API proves this

Every authored recipe filed under CMT, in the order the plan works them. The mark says how much of the evidence the command produces on its own.