Policy as Code for IaC
Policy as Code for IaC
Infrastructure-as-Code gives teams the power to provision anything — and that is exactly the problem. Without guardrails, a developer can open port 22 to the world, spin up an unencrypted RDS instance, or deploy a public S3 bucket holding customer PII, all via a clean terraform apply. Policy as Code (PaC) is the practice of encoding those guardrails as machine-readable, version-controlled policy files and enforcing them automatically inside the CI/CD pipeline — before a single API call reaches your cloud provider. At Google, Meta, and Amazon, PaC gates every infrastructure change. A plan that violates policy is blocked, not just warned; the engineer gets a structured rejection with the exact rule reference and remediation steps.
The Three Major Tools
Three tools dominate the Terraform PaC space, and they occupy different positions in the trust model:
- Open Policy Agent (OPA) + Conftest — a general-purpose policy engine from the CNCF. Policies are written in the Rego language. You feed it a Terraform plan JSON and evaluate it against Rego rules. Open source, cloud-agnostic, widely adopted in Kubernetes admission control too.
- Sentinel — HashiCorp's proprietary policy framework, built directly into Terraform Cloud/Enterprise. Policies are written in the Sentinel language and run as a native gate between
planandapply. Best-in-class integration with the HCP platform but requires TFC/TFE. - Checkov — a static analysis scanner by Bridgecrew (acquired by Palo Alto). It parses Terraform HCL directly (no plan needed) and checks against 1,000+ built-in policies for AWS, Azure, and GCP misconfigurations. Fast, zero-config, and integrates into any CI pipeline as a linter step.
terraform plan (pre-apply gate). Sentinel enforces organization-wide hard policy in Terraform Enterprise. Layering tools catches different classes of violation at the cheapest point in the pipeline.
The Gated Pipeline Architecture
The diagram below shows how policy gates sit inside a production-grade Terraform CI pipeline. Each gate is a hard failure — a non-zero exit code fails the pipeline and blocks merge or apply.
apply.Checkov: Shift-Left Static Scanning
Checkov is the fastest feedback loop. Run it locally before you even open a PR, and again in CI on every push. It requires no plan — it reads your .tf files directly.
.checkov.baseline file. It documents accepted risk and prevents finding-fatigue from inherited debt. Every suppression in the baseline should have a corresponding Jira/GitHub issue reference in a comment so the debt is tracked, not hidden.
OPA + Conftest: Plan-Level Policy
Checkov misses runtime decisions that only appear in the plan: whether a security group rule is 0.0.0.0/0, whether an instance type is on the approved list, whether a tag is missing. OPA evaluates the full terraform show -json plan, giving you access to every resource change including computed values.
Keep policies in a dedicated policy/ directory inside your infra-live repo, versioned alongside the infrastructure code. Large teams publish policies to a shared OPA bundle server (S3 + OPA bundle API) so all squads consume the same central ruleset without copying files.
Sentinel: Hard Policy in Terraform Enterprise
If your organization uses Terraform Cloud or Enterprise, Sentinel is the native answer. It runs automatically after every plan in a workspace, before operators can approve an apply. Sentinel policies have three enforcement levels: advisory (log only), soft-mandatory (blockable by a human override), and hard-mandatory (cannot be overridden — ever). Compliance teams love hard-mandatory for rules like "no resource may be created without an Owner tag" or "all S3 buckets must have versioning enabled."
Structuring Policies for Scale
At big-tech scale, policies live in their own repository (infra-policies) with its own CI, versioning, and review process. The key practices:
- Test your policies. OPA ships with
opa test; Sentinel has a testing framework. A broken policy that fires on valid configs is as damaging as no policy at all — it trains engineers to bypass gates. - Separate WARN from BLOCK. New policies should start as warnings for two weeks. This gives teams time to fix existing violations before the rule becomes a hard failure. Track the warning period in the policy file header as a comment.
- Tag every policy with a control ID. Link each Rego/Sentinel rule to a SOC 2, CIS, or internal control number. This makes audit evidence collection a
conftest test --output jsoncommand rather than a manual spreadsheet exercise. - Version your policy bundles. Consumers (workspaces, pipelines) pin to a specific bundle version. Policy changes go through PRs with CODEOWNERS review from the security team before release.
With Checkov catching misconfigurations at the HCL level, OPA evaluating the full plan, and Sentinel enforcing organization-wide hard rules in the platform, you have defense-in-depth for your infrastructure supply chain. The result: engineers move fast, compliance teams sleep at night, and audit evidence is a git log away.