Introduction to Open Policy Agent
π Introduction
When I started running Kubernetes on a personal k3s cluster at home, I didn't think much about policy. I was focused on getting services running, understanding controllers, and learning the networking model. Policy felt like an enterprise concern β something for compliance teams in large organizations, not something I needed for a homelab or a side project.
That changed when I started sharing clusters. A few workloads from different experiments running side-by-side. Suddenly I had questions I couldn't answer cleanly:
Who gets to create what in which namespace?
Should any container be allowed to run as root?
Which image registries are trusted?
I could have written admission webhook logic by hand. But the more I read, the more I kept running into Open Policy Agent. It's not just an admission webhook β it's a general-purpose policy engine. And the more I understood it, the more I realized it solves a category of problems I'd been hacking around for years.
This article covers what OPA is, the thinking behind it, and the core concepts you need before writing any policy.
π― What is Open Policy Agent?
Open Policy Agent (OPA, pronounced "oh-pa") is an open source, general-purpose policy engine. It graduated from the Cloud Native Computing Foundation (CNCF) in 2021.
The core idea is policy decoupling: separate the decision of what's allowed from the mechanism that enforces it. Your application (or infrastructure tool) asks OPA a question. OPA evaluates the question against policies and data and returns a decision. The application acts on that decision.
This separation means:
Policies live outside the application code β they can be updated, tested, and deployed independently
One policy engine can serve multiple systems (Kubernetes, Envoy, Terraform, custom APIs)
Decisions are auditable β every query can be logged
π§© Core Concepts
1. Policy as Code
In OPA, policies are written in a language called Rego (pronounced "ray-go"). Rego is declarative β you describe what should be true, not how to check it.
This policy lives in a .rego file. It can be version-controlled, reviewed in pull requests, and tested like any other code.
2. Input and Data
When something queries OPA, it sends a JSON document as input. OPA also has access to a data document β external data loaded into OPA ahead of time (like a list of approved registries, or team ownership mappings).
3. Policy Decisions Are Flexible
OPA doesn't just return true or false. The output is arbitrary JSON. You can return an allow/deny decision, a list of violations, a set of reasons, a mutated object β whatever the consuming system needs.
4. OPA is Domain-Agnostic
OPA knows nothing about Kubernetes, Terraform, or any specific system. It takes JSON in, evaluates policies, returns JSON out. The integrations are adapters that translate between OPA's interface and the tool's specific format.
π Why Policy Decoupling Matters
The traditional approach hardcodes policy logic inside applications or scripts:
When policy is embedded in each system:
Changing a rule requires updating multiple codebases
There's no single place to audit what's allowed
Testing policy means testing application code
Policy drift is inevitable
With OPA:
All policy lives in one place (or a managed bundle)
Changes go through a normal code review process
Policies are independently testable
Enforcement is consistent across systems
ποΈ Where OPA Is Used
OPA integrates with many systems in the cloud-native stack:
Kubernetes
Admission controller (via Gatekeeper or standalone webhook)
Envoy
External authorization filter
Terraform
Validate plans before apply (via Conftest)
CI/CD
Policy gates on container images, manifests, configs
Custom APIs
Authorization decisions embedded as a library or sidecar
Kafka
Topic-level access control
This series focuses primarily on Kubernetes with some CI/CD coverage β the most common entry points in practice.
π¦ How OPA Fits into a Kubernetes Platform
In a Kubernetes-based platform, OPA typically sits as an admission controller. Every request to create or update a resource goes through the API server, which calls OPA (via a validating or mutating webhook). OPA evaluates the request against policies and returns allow or deny.
The developer gets immediate, clear feedback at the point of impact β not hours later in a security scan.
π OPA vs Related Tools
A few clarifications on where OPA sits relative to tools you may already know:
Kyverno
K8s-native policy
Alternative to OPA Gatekeeper; K8s-specific, YAML-based policies
PSA (Pod Security Admission)
K8s built-in
Covers a narrow slice of pod security; OPA handles broader policies
Falco
Runtime security
Detects policy violations at runtime; OPA prevents them at admission
Conftest
Policy testing CLI
Uses OPA/Rego under the hood; good for CI/CD pipelines
Gatekeeper
K8s OPA integration
The standard way to deploy OPA on Kubernetes
OPA and Kyverno are the two dominant choices for general Kubernetes policy. This series covers OPA because Rego gives you more programmability and OPA applies beyond Kubernetes.
βοΈ Installing OPA CLI
Before writing any Rego, get the opa CLI:
The CLI lets you evaluate policies locally, run tests, inspect bundles, and start an OPA server β essential for the development loop.
Quick sanity check:
π§ What's Next
This was the conceptual foundation. The next article goes hands-on with Rego β the policy language you'll use to write every policy in this series.
Next: Article 02 β Rego Language Fundamentals
π References
Last updated