src/config/service-control-policies/ contains the Service Control Policies that govern what actions are allowed across your AWS Organization. The landing zone ships five ready-made SCPs covering the most critical guardrails, all attached by default. You can use them as-is, modify their content, or add your own.
SCPs are attached in organization-structure.ts at the root, OU, or account level. AWS Organizations enforces a maximum of 10 SCPs per attachment point.
Shipped SCPs
| SCP | Default attachment | What it enforces |
|---|---|---|
criticalSecurityGuardrailsSCP | Root | Denies leaving the organization, creating IAM users and access keys, disabling EBS encryption by default, and modifying the account password policy |
denyAllOutsidePrimaryAndSecondaryRegionsSCP | Root | Restricts all AWS API calls to your configured primary and secondary regions; exempts global services (IAM, Route 53, CloudFront, etc.) and landing-zone roles |
protectTaggedCloudFormationStacksSCP | Root | Denies deleting CloudFormation stacks tagged with your organization name (organization: <organizationName>), protecting landing-zone managed stacks from accidental deletion |
protectSecurityHubConfigurationSCP | Security account | Prevents modification of Security Hub configuration in the delegated administrator account: disabling standards, deleting members, changing org configuration |
lockdownSuspendedAccountsSCP | Suspended OU | Denies all AWS actions in accounts that have been moved to the Suspended OU |
Exempt principals
A guardrail that denies an action still has to let the landing zone, and you, operate. src/config/service-control-policies/administrator-principals.ts is the single place those exemptions are defined, and the guardrails that support exemptions use its shared allowlists.
It exports three lists:
| Function | Used by | Covers |
|---|---|---|
securityServiceAdministratorPrincipalArns() | Region guardrail, Security Hub protection | SSO administrators, the Security Hub service role, the landing zone's own roles, and your external admins |
landingZoneAdministratorPrincipalArns() | CloudFormation stack protection | SSO administrators plus the landing zone's own roles and your external admins |
suspendedAccountExemptPrincipalArns() | Suspended-account lockdown | The principals that must keep access while an account is suspended |
The allowlists cover landing-zone administration and deployment roles, including GitHubActionsServiceRole, plus your configured external administrators. Set externalAdmins in landing-zone-settings.ts to include them in the shared exemptions.
Edit this file when you have a break-glass or automation role that must survive the guardrails. Because the guardrails share these lists, adding a principal once applies it to every SCP that uses that list.
The region guardrail also exempts global services (IAM, Route 53, CloudFront, AWS Organizations, billing, KMS, S3, STS, support, and others with no regional API boundary). When you add secondaryRegions to landing-zone-settings.ts and redeploy, it includes those regions in the allow list automatically.
Authoring a custom SCP
Create a new file (or add to an existing one) in src/config/service-control-policies/. This example denies bucket deletion using the supported s3:DeleteBucket action. It does not prevent object deletion:
export const denyS3BucketDeletionSCP: ServiceControlPolicy = {
content: {
Version: '2012-10-17',
Statement: [
{
Sid: 'DenyS3BucketDeletion',
Effect: 'Deny',
Action: 's3:DeleteBucket',
Resource: 'arn:aws:s3:::*',
},
],
},
description: 'Prevents deletion of S3 buckets',
policyName: 'DenyS3BucketDeletion',
policyType: PolicyType.SERVICE_CONTROL_POLICY,
};
Export it from src/config/service-control-policies/index.ts:
export * from './your-new-guardrails';
Then append it to the target OU’s serviceControlPolicies array in organization-structure.ts. Preserve existing policies and leave the OU’s accounts and other fields unchanged:
// Inside the target OU, append to its existing array:
serviceControlPolicies: [
// Keep existing SCP entries here.
denyS3BucketDeletionSCP,
],
Things to know
- Maximum 10 directly attached SCPs per attachment point (root, OU, or account). AWS raised this limit from 5 to 10 in May 2026. Inherited SCPs do not count against this quota. With
FullAWSAccessattached, an attachment point has room for at most 9 additional SCPs. - Check existing attachments before deploying. Synthesis validates the SCPs configured in
organizationStructureand rejects policy documents over 10,240 characters. It does not account forFullAWSAccessor other policies attached outside that configuration, so a passing synth does not guarantee the deployed attachment count stays within the quota. - The shipped SCPs use explicit denies. SCPs can contain allow or deny statements, but they never grant permissions by themselves.
- AWS attaches
FullAWSAccessby default when SCPs are enabled. It counts toward the attachment limit. Keep an allow policy at each level when using these deny-based guardrails; removing all applicable allows blocks access. - Test in a non-production OU first: attach a new SCP to a development account before applying it at the root or to production accounts.