Abstract
Security and compliance teams have long relied on manual review gates and post-deploy audits to enforce organizational standards. Policy-as-code with Open Policy Agent (OPA) and Conftest moves those checks left into the CI pipeline, where they run automatically on every pull request against Terraform plans, Kubernetes manifests, Helm charts, and Dockerfile configurations. The result is enforcement that is consistent, version-controlled, and fast enough to give developers feedback within seconds rather than days.
What OPA and Conftest Actually Do
OPA is a general-purpose policy engine that evaluates rules written in Rego, a declarative language designed for structured data. It does not assume any particular input format: you feed it JSON and it evaluates your policy against that JSON. Conftest is a wrapper that handles the input parsing for common DevOps artifacts. Running conftest test deployment.yaml will pull in any Rego policies from a policy/ directory, convert the YAML to JSON internally, and evaluate each policy in turn. Exit code 1 signals a violation, which a CI system treats as a failed check. Policies live in Git alongside the infrastructure code they govern, so changes to policy go through the same review process as changes to application code.
Practical Policy Examples
A typical starter policy for Kubernetes enforces that every Deployment sets CPU and memory limits, since unbounded containers are a common source of node pressure. In Rego, this reads as a denial rule that fires when any container in input.spec.template.spec.containers omits resources.limits. A second common policy prohibits the latest image tag, which breaks reproducibility and makes rollbacks unreliable. Terraform policies are equally straightforward: deny any aws_s3_bucket resource where acl is set to public-read or public-read-write. Conftest can pull shared policy bundles from OCI registries using conftest pull oci://registry.example.com/policies:v1.3, so platform teams can publish a canonical policy set that all product teams consume without duplicating Rego files across repositories.
Integration Points in a CI Pipeline
In GitHub Actions, Conftest installs in under 10 seconds via the instrumenta/conftest-action community action or a direct binary download from the GitHub releases page. A typical workflow runs terraform plan -out tfplan && terraform show -json tfplan > tfplan.json && conftest test tfplan.json before the apply step. For Kubernetes, it runs after helm template renders the manifests, catching violations before the chart ever reaches a cluster. The key integration detail is that Conftest should run against rendered output, not source templates, so that variable substitution and default values are already resolved when the policy evaluates.
Governance Without Gatekeeping
The cultural challenge with policy-as-code is calibrating strictness. Policies that block too aggressively become a frustration that developers work around, often by disabling the check entirely. A useful pattern is to deploy new policies in warn mode first using Conftest’s --fail-on-warn flag set to false, collect a few weeks of violation data, communicate the findings to teams, then flip to enforcement. This mirrors how linters are typically adopted in application code: show the violations before you block the build, build the habit, then lock it in.