Compliance Frameworks
BETA// Beta Mapping Disclaimer
Framework mappings are currently in beta. These references are generated based on technical specifications and common industry alignments. Mappings may be incomplete or inaccurate; always consult with a qualified auditor for official compliance validation.
Overview
Establish and maintain a baseline set of Service Control Policies from the Management account to enforce preventative guardrails across the organization.
Recommended foundational SCPs for a landing zone:
- Deny leaving the AWS Organization (organizations:LeaveOrganization)
- Deny disabling or deleting CloudTrail trails
- Deny disabling AWS Config or deleting Config recorders and delivery channels
- Deny disabling Security Hub or GuardDuty
- Deny root user actions (except account-level tasks that require root)
- Deny creation of IAM users and long-lived credentials in member accounts
- Restrict deployments to approved AWS regions only
- Deny disabling EBS encryption by default
- Deny making S3 buckets or objects public at the account level
- Deny deletion of VPC Flow Logs
- Deny modification of designated security roles (e.g. LandingZoneAdminRole)
- Deny sharing resources outside the organization via RAM
SCPs are attached at the organization root or specific OUs from the Management account and act as permission boundaries - they do not grant permissions but restrict the maximum permissions available to all principals in the target scope, including account root users. The FullAWSAccess SCP is attached by default at the root; all custom SCPs are Deny-based additions on top of this. Each SCP in the list above is defined and maintained as a separate policy to keep individual policies readable and to allow targeted attachment at OU level where a guardrail applies to only a subset of accounts. Individual controls across this library (AWS-IAM-001 through AWS-IAM-006) define the specific policy content for their respective SCPs. This control governs the framework - ensuring SCP feature is enabled, policies are attached, and coverage is reviewed regularly.
SCPs are the only control mechanism in AWS that applies to all principals in an account including the root user and cannot be circumvented by any IAM policy in the member account. They form the outermost permission boundary of the landing zone. Without them, any member account administrator can disable logging, leave the organization, or deploy to unapproved regions - actions that IAM policies and Config rules detect after the fact but cannot prevent.
Remediation Strategy
Enable SCP policy type on the organization root if not already active. Draft each SCP from the list in the description as a separate named policy. Test each policy in a sandbox OU. Attach to the appropriate target - root for universal guardrails, specific OUs for scoped restrictions.
Enable the SERVICE_CONTROL_POLICY policy type on the organization root if not already enabled.
Create each foundational SCP as a named policy in the Management account.
Attach each SCP to a sandbox OU and run test workloads to verify no legitimate actions are blocked.
Promote to the target OU or organization root after validation.
Review SCP coverage quarterly and update as new AWS services or regions are adopted.
Enforcement Logic
Verify that the SCP policy type is enabled on the organization root and that at least one non-AWS-managed SCP is attached. List policies attached to each OU to confirm coverage. An organization with only the default FullAWSAccess SCP and no custom policies has no preventative guardrails.
ROOT_ID=$(aws organizations list-roots \
--query "Roots[0].Id" --output text)
# Check SCP type is enabled
aws organizations list-roots \
--query "Roots[0].PolicyTypes[?Type=='SERVICE_CONTROL_POLICY'].Status" \
--output text
# Count custom (non-AWS-managed) SCPs at root
aws organizations list-policies-for-target \
--target-id "${ROOT_ID}" \
--filter SERVICE_CONTROL_POLICY \
--query "length(Policies[?AwsManaged==\`false\`])" \
--output text
# List SCPs per OU
aws organizations list-organizational-units-for-parent \
--parent-id "${ROOT_ID}" \
--query "OrganizationalUnits[*].{Id:Id,Name:Name}" \
--output text | while read ID NAME; do
COUNT=$(aws organizations list-policies-for-target \
--target-id "${ID}" \
--filter SERVICE_CONTROL_POLICY \
--query "length(Policies[?AwsManaged==\`false\`])" \
--output text)
echo "OU=${NAME} custom_scps=${COUNT}"
doneThe Management account is implicitly exempt from all SCPs - AWS does not apply SCPs to the Management account regardless of where they are attached. This is an AWS platform constraint, not a configurable exception.
Emergency break-glass scenarios may require temporary detachment of a specific SCP from an account. This must be performed via a named break-glass role in the Management account, logged to CloudTrail, and the SCP must be re-attached.
SCPs do not affect the Management account - any guardrail that should also apply to the Management account must be enforced via IAM policies or Config rules within that account directly. The default FullAWSAccess SCP must remain attached at the root alongside custom Deny SCPs; removing it would deny all actions everywhere. Each SCP has a maximum size of 5120 characters - keep individual policies focused on one guardrail category to stay within this limit and to make targeted OU-level attachment practical. The list-policies-for-target API call returns only directly attached SCPs; inherited policies from parent OUs require traversing the OU hierarchy.