HCA SCP Consolidation — Summary
Background
Started with 14 SCP files (13 custom + FullAWSAccess). Root cannot be used for
attachment — unmanaged accounts sit there too, so anything attached at root risks
collateral impact outside this project's scope. All attachment happens at
Level-1 OUs (or below); each OU/account inherits from its parent OU, not from root
directly, for anything root doesn't already carry.
FullAWSAccess is inherited from root and does not count against any OU's
attachment quota. CT-managed guardrails (aws-guardrails-*) are never touched —
no attach, detach, or edit — Control Tower owns their lifecycle entirely.
AWS raised the per-node SCP cap from 5→10 and the size cap from 5,120→10,240 characters on 2026-05-15. All numbers below reflect the current (raised) limits.
What got consolidated
10 custom SCPs → 3 merged documents, grouped by function. 1 tagging policy kept standalone (large, mid-rollout, changes independently of security rules).
hca-security-baseline.json
Merged from:
Deny_ability_to_disrupt_GuardDutyDeny_disabling_CloudWatch_or_altering_its_configurationProtect_security_settingsLeaveOrg
hca-data-protection.json
Merged from:
Deny_unencrypted_EBS_volume_creationDeny_public_RDS_creationS3_SSl_Policy
hca-resource-lifecycle.json
Merged from:
deny-delete-actionsDeny_ec2_imdsv_1
hca-tagging-policy.json
Not merged with the above — kept as its own document. Cleaned up from the
original (kebab-cased all tag keys for consistency: AppOwner → app-owner,
AvailabilityTier → availability-tier, BusinessUnit → business-unit,
CostCenter → cost-center, DataClassification → data-classification,
Project → project). Originally split into two files to fit the old
5,120-byte cap; re-merged into one file once the 10,240-byte cap confirmed it
fits (9,347 bytes pretty-printed). Still unattached anywhere — mid-rollout.
Requires one Deny statement per required tag by design — AWS evaluates
multiple condition keys under one operator with AND logic, so a single
statement checking several tags for Null would only fire when every tag is
missing at once, not when any one is. Splitting per-tag is what makes "deny if
any required tag is missing" actually work.
Net result
Before: 10 custom SCPs consuming up to 6 slots per OU (varies). After: 4 documents (3 merged + 1 tagging), same enforcement, fewer slots.
CT guardrail footprint (informational — not something to attach/detach)
Snapshot from the org structure pull, for the 8 project-scoped OUs. Shows what Control Tower already occupies at each OU, so remaining headroom is clear before attaching the 4 files above to a new OU.
| OU | CT guardrails present | CT slot count |
|---|---|---|
| Data | utQMHg, hiQAAt, kwDsmG, GEFrgv, PrFwNu |
5 |
| Sandbox | yvlcHf, utQMHg, URVMlf, PrFwNu |
4 |
| Integration | ipsuXu, PrFwNu, rDMgmy |
3 |
| Security | Vzvcwh, utQMHg, chQKXg, GEFrgv |
4 |
| Legacy | utQMHg, qFyGLz, yuPdpk, GEFrgv, PrFwNu |
5 |
| DR | onCsAG, AozcGY, utQMHg, GEFrgv, PrFwNu |
5 |
| Finance | QaqgVP, PrFwNu, fgKDjS |
3 |
| Platform | HeQGNC, utQMHg, wUAwns, PrFwNu |
4 |
Three guardrails recur across most OUs:
aws-guardrails-PrFwNu(p-vswc3nsu,GRREGIONDENY) — 7 of 8 OUsaws-guardrails-utQMHg(p-dp5q0qb6) — 6 of 8 OUsaws-guardrails-GEFrgv(p-vhl7fpu9) — 4 of 8 OUs, same content asutQMHg(known duplicate pair, flagged separately — not actioned here)
Each OU also carries 2 additional CT guardrails unique to it (not shared with any other project OU), likely part of Control Tower's per-OU baseline set applied at registration.
Slot math for attaching the 4 consolidated files to a NEW OU
Assuming a new OU picks up a similar CT baseline (FullAWSAccess free +
~3-5 CT guardrail slots, actual count depends on what Control Tower assigns):
10 (cap)
− 0 FullAWSAccess (inherited from root, free)
− 3–5 CT guardrails (varies, set by Control Tower at registration)
− 3 hca-security-baseline / hca-data-protection / hca-resource-lifecycle
− 1 hca-tagging-policy
———
= 1–3 slots free, depending on the new OU's CT guardrail count
Confirm the new OU's actual CT footprint (via list-policies-for-target)
before attaching, since the count isn't fixed across OUs.