All projects

OPA Gatekeeper: about 50 policies, from audit to enforcement

Policy-as-code on three clusters, rolled out per environment, observable, with documented exceptions and gaps.

Company
ID6TM
Period
2026
Stack
  • OPA Gatekeeper
  • Kubernetes
  • ArgoCD
  • Helm
  • Prometheus
  • Policy-as-code

Context

Good practices in a wiki do not stop a risky deployment. The goals were explicit: block bad practices, standardise deployments and reduce the attack surface, on three clusters (production, pre-production, internal tools).

How it is built

  • A custom chart carrying about 50 ConstraintTemplates from the official Gatekeeper library: container security (root, privilege escalation, read-only filesystem, capabilities, seccomp), trusted registries and no :latest, resources, labels and probes, host isolation, exposed services.
  • Deployed by an ArgoCD ApplicationSet (clusters × per-cluster values), templates before constraints in sync waves. The CRD bootstrap gotcha on a fresh cluster is documented.
  • Per-environment enforcement: warn on pre-production, deny on production for the critical policies, one policy at a time.

The audit paid for itself

On pre-production, audit mode surfaced about 2,700 violations. Reading them revealed two misconfigurations that would have blocked the whole cluster in deny mode: an allowed-storage-class list that was empty because Gatekeeper was not syncing that resource, and an allowed-images list left empty. Both were fixed before enforcement.

Exceptions and gaps, written down

  • Exemptions are per namespace and justified inline (runtime security, node exporter, secrets CSI driver, VPN client). No annotation bypass, on purpose: no untraceable escape hatch.
  • Known gaps are documented rather than hidden: Traefik IngressRoute CRDs are not covered by the native ingress templates, and secret values in environment variables are out of Gatekeeper’s reach. That risk is handled by Vault and secret scanning in CI.

Observable

Metrics and five Prometheus alert rules (violations, denies, stale audit, webhook errors, webhook latency) routed to Slack, plus a read-only policy UI with SSO on all three clusters.

Outcome

The platform moved from “recommended” to “enforced” without surprise outages. Next: checks in CI before merge (shift-left) and a policy requiring a NetworkPolicy in every namespace.