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.

spinner

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).

spinner

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:

spinner

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:

System
How OPA Is Used

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.

spinner

The developer gets immediate, clear feedback at the point of impact β€” not hours later in a security scan.


A few clarifications on where OPA sits relative to tools you may already know:

Tool
Category
Relationship to OPA

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