CoursesOPA & RegoIntermediate

Conftest for config & IaC

Policy on YAML, Terraform, Dockerfiles.

Advanced14 min · lesson 7 of 12

Conftest applies OPA/Rego policy to structured configuration files — YAML, JSON, HCL/Terraform, Dockerfiles, INI, and more — and is the go-to way to enforce policy in CI. It parses the file into JSON, evaluates your deny (and warn) rules against it as input, and exits non-zero on any violation, so a pull request that adds a public bucket or a privileged pod fails the pipeline. The policies are ordinary Rego, reusable across everything Conftest can parse.

CONFTEST IN CI
1config file
YAML / Terraform / Dockerfile
2parse to JSON
becomes the input document
3evaluate rules
deny = block, warn = advisory
4exit code
non-zero on deny -> CI job fails
Conftest parses config to JSON, runs your Rego, and exits non-zero on a deny so the pipeline fails.
terminal
$ conftest test deployment.yaml
FAIL - deployment.yaml - main - container app is privileged
FAIL - deployment.yaml - main - memory limit is not set
2 tests, 0 passed, 2 failures
$ echo $?
1 # non-zero -> the CI job fails

Policy across the stack

The strength is one policy language over the whole toolchain: the same Conftest run can check Kubernetes manifests, a Terraform plan (converted to JSON), a Dockerfile, and a Helm render — enforcing consistent rules (“images from our registry,” “no :latest,” “encryption on”) everywhere config lives. Policies are distributed as bundles (even via OCI), so a platform team ships one policy library that every repo pulls and runs in CI.

terminal
# gate a Terraform plan: render to JSON, then test it
$ terraform show -json plan.bin > plan.json
$ conftest test plan.json --policy policy/
# pull a shared policy bundle and test against it
$ conftest pull oci://registry.internal/policies:v2 && conftest test .
warn vs deny — and gate on the right one
Conftest treats deny rules as failures (non-zero exit) and warn rules as advisories (still exit zero). A policy written as warn will show in output but not block the merge — a common reason “the policy runs but bad config still ships.” Use warn for advisory nudges and deny for anything that must block, and confirm the CI job actually fails on a deny.