Using OPA Rego to enforce Helm conventions across teams
2026-02-22 · Dana Kimura
OPA and Rego are underused for Helm validation. Here's the pattern I've settled on for enforcing conventions without blocking legitimate variation.
The problem with helm lint
helm lint catches schema errors and some obvious problems. It doesn't know anything about your organisation's conventions — required labels, disallowed image registries, mandatory resource limits, namespace naming rules.
You can add these checks to a CI script as a series of kubectl and jq commands, but the result is brittle and hard to audit. Rego policies are declarative, testable, and composable in a way that ad hoc shell scripts aren't.
Structure of a CrestHelm policy
Policies receive the rendered Kubernetes manifests (from helm template) as input. A policy that requires CPU limits on all containers looks like:
package cresthelm.limits
deny[msg] {
container := input.spec.containers[_]
not container.resources.limits.cpu
msg := sprintf("container %s has no CPU limit", [container.name])
}
CrestHelm collects all deny results across all loaded policies and reports them in the same format as helm lint output, so they slot into existing CI pipelines without changes.
Testing policies
Rego's built-in unit test framework (opa test) works directly with CrestHelm policy bundles. The repository's starter bundle has tests for every included policy; adding tests to custom policies is a prerequisite for merging them, enforced by CrestHelm's own CI pipeline.