OPA in CI/CD Pipelines

πŸ“– Introduction

Admission control at the Kubernetes API server is a last line of defense, not the only one. By the time a developer runs kubectl apply and gets a policy violation, they've already built the image, written the YAML, opened a PR, merged it, and triggered a deployment. Blocking at admission is correct β€” but discovering violations at that point is expensive.

Shift-left enforcement means catching policy violations earlier: in the developer's editor, in CI on every pull request, and in CD before a new bundle reaches production. This article shows how to integrate OPA and Conftest into a CI/CD pipeline so policy violations surface where they're cheapest to fix.


πŸ—ΊοΈ Where Policy Enforcement Belongs

spinner

Each gate:

  • Pre-commit: instant feedback, opt-in

  • CI: mandatory, blocks merge

  • CD: policy bundle is itself versioned and tested before deployment

  • Admission: runtime safeguard, catches anything that bypassed earlier gates


πŸ”§ Pre-commit Hook with Conftest

The fastest way to enable local policy checking:

# .pre-commit-config.yaml
repos:
  - repo: https://github.com/open-policy-agent/conftest
    rev: v0.50.0
    hooks:
      - id: conftest-not-exist
        name: conftest
        language: golang
        entry: conftest test
        files: \.(yaml|yml)$
        args: ["--policy", "./policy"]

Or a simpler shell script at .git/hooks/pre-commit:


πŸ—οΈ CI Pipeline: GitHub Actions

A complete GitHub Actions workflow covering:

  1. OPA unit tests on the policies themselves

  2. Conftest check on all Kubernetes manifests

  3. Conftest check on Terraform plans


πŸ“‹ Conftest Policies for Kubernetes Manifests

Conftest policies differ from Gatekeeper policies because input is the raw manifest, not wrapped in an admission review.

policy/kubernetes/approved-registries.rego:

policy/kubernetes/resource-limits.rego:

Use warn for non-blocking guidance, deny for hard requirements.


πŸ—οΈ CI Pipeline: Policy Bundle Deployment

When policy changes are merged, the bundle must be rebuilt and published. A separate workflow handles this:

This creates a verifiable, traceable link between a Git commit and a deployed policy bundle.


πŸ”¬ Testing Terraform Plans with Conftest


πŸ“Š Reporting in Pull Requests

In GitHub Actions, policy failures surface as workflow failures and block merge (if branch protection is configured). For clearer reporting, use the JSON output format:


🧭 Series Wrap-Up

This article completes the OPA 101 series. Here's what we covered:

Article
Topic

01

OPA concepts, policy decoupling, when to use it

02

Rego language β€” syntax, rules, iteration, functions

03

OPA architecture β€” deployment modes, bundle pull, decision logging

04

Gatekeeper β€” installation, ConstraintTemplates, Constraints

05

Kubernetes policies β€” registries, labels, resource limits, pod security

06

Bundles β€” building, serving, versioning, production distribution

07

Testing β€” opa test, Conftest, coverage

08

CI/CD β€” shift-left enforcement, GitHub Actions, Terraform validation

Recommended next steps:


πŸ“Ž References

Last updated