SCP Consolidation - HCA AWS Organization
Purpose
This project defines the Service Control Policy (SCP) structure for the HCA AWS Organization. It groups guardrail logic into a small set of purpose-built documents, keeping every OU comfortably under AWS's per-target attachment limit while leaving room to add rules later without a rework.
Structure
policies/
├── custom-managed/ Attached at project-scoped OUs
│ ├── hca-security-baseline.json
│ ├── hca-data-protection.json
│ ├── hca-resource-lifecycle.json
│ └── hca-tagging-standards.json
└── root-level/ Attached at the organization root
└── hca-org-governance.json
Strategy
Policies are grouped by function. Each file in custom-managed/ bundles
guardrails that share a common theme. An OU only needs a handful of
attachments to get full coverage, instead of one attachment per individual
rule.
Scope follows blast radius. Anything that must apply to every account in
the organization, with no OU-level exceptions, lives in root-level/ and is
attached once at root. Rules specific to this project's OUs live in
custom-managed/ and are attached at each of those OUs individually. This
keeps root's footprint small and makes sure project-specific policies never
reach accounts outside this project's scope.
Control Tower guardrails are out of scope. AWS Control Tower manages its
own SCPs independently (the aws-guardrails-* policies). These sit outside
this project and are never edited, merged, or reattached here. Control Tower
owns their lifecycle end to end.
Each enforcement rule gets its own statement. Where a policy checks
several conditions, such as multiple required tags, every condition is
written as a separate, Sid-tagged statement rather than combined into one.
AWS evaluates multiple condition keys inside a single statement using AND
logic, so combining checks that should each independently trigger a Deny
would quietly weaken enforcement. Keeping them separate makes each rule's
behavior explicit and correct.
Files are sized with room to grow. Every document leaves meaningful byte
headroom under the SCP size limit, so new statements can be added without an
immediate restructure. hca-org-governance.json currently holds a single
rule and is meant to be the home for future org-wide governance statements
as they come up.
Policy summaries
custom-managed/hca-security-baseline.json
Protects core security tooling from being disabled or altered. Covers GuardDuty detector and filter changes, CloudWatch alarm and dashboard deletion, and account-level security settings such as Access Analyzer, EBS default encryption, and S3 public access block.
custom-managed/hca-data-protection.json
Enforces baseline data-handling rules. EBS volumes must be created encrypted, RDS instances and clusters cannot be made publicly accessible, and all S3 requests must use SSL/TLS.
custom-managed/hca-resource-lifecycle.json
Blocks deletion of critical infrastructure, including EC2 instances, EBS volumes and snapshots, RDS instances and clusters, Redshift clusters, and core VPC networking components. Also requires IMDSv2 on all new EC2 instances and launch templates.
custom-managed/hca-tagging-standards.json
Requires a baseline set of tags on resource-creation calls across EC2, RDS,
S3, Lambda, ECS, EKS, ElastiCache, DynamoDB, SQS, SNS, Secrets Manager, KMS,
ELB, and Auto Scaling. The enforced tags are application-name,
environment, team, owner, assignment-group, project,
availability-tier, data-classification, cost-center-opex,
cost-center-capex, business-unit, and app-owner. The environment tag
also has its value checked against an approved list: prod, pre-prod,
non-prod, staging, qa, dev, and sandbox. Tag keys and requirements
are kept in sync with the tagging module's baseline tags and the
corresponding OPA policy.
root-level/hca-org-governance.json
Holds organization-wide governance rules, attached at root so they reach every account without exception. It currently enforces one rule: member accounts cannot leave the organization. The file is structured to hold additional org-wide governance statements as they're identified.
Attachment guidance
custom-managed/ policies are attached at each project-scoped OU that
requires them. Before attaching, confirm the OU's current attachment count
against AWS's per-target SCP limit, since Control Tower guardrails already
take up part of that quota at every OU.
root-level/hca-org-governance.json is attached once, at the organization
root, and is inherited by every account beneath it.