Open Policy Agent (OPA) is a general-purpose policy engine that enables unified policy enforcement across your entire stack — Kubernetes admission control, API authorization, Terraform plans, and more.
What Is OPA?
OPA is a CNCF graduated project that decouples policy decision-making from your application. You write policies in Rego (a declarative language), and OPA evaluates them against any JSON data to make allow/deny decisions.
Key Features:
- General-purpose policy engine
- Rego policy language
- REST API for policy evaluation
- Kubernetes admission control (Gatekeeper)
- Partial evaluation for optimization
- Bundle API for policy distribution
- Decision logging
- WebAssembly compilation
Quick Start
# Install OPA
brew install opa
# Start OPA server
opa run --server --addr :8181
# Or Docker
docker run -d -p 8181:8181 openpolicyagent/opa:latest run --server
Write Policies in Rego
# policy.rego
package authz
import rego.v1
default allow := false
# Allow admins to do anything
allow if {
input.user.role == "admin"
}
# Allow users to read their own data
allow if {
input.method == "GET"
input.path[0] == "users"
input.path[1] == input.user.id
}
# Allow managers to read team members
allow if {
input.method == "GET"
input.path[0] == "users"
input.user.role == "manager"
input.path[1] in input.user.team_members
}
OPA REST API
import requests
OPA = "http://localhost:8181/v1"
# Upload policy
policy = open("policy.rego").read()
requests.put(f"{OPA}/policies/authz", data=policy,
headers={"Content-Type": "text/plain"})
# Evaluate policy
result = requests.post(f"{OPA}/data/authz/allow", json={
"input": {
"user": {"id": "user-42", "role": "admin"},
"method": "DELETE",
"path": ["users", "user-99"]
}
}).json()
print(f"Allowed: {result['result']}") # True (admin)
# Check non-admin
result = requests.post(f"{OPA}/data/authz/allow", json={
"input": {
"user": {"id": "user-42", "role": "user"},
"method": "GET",
"path": ["users", "user-42"]
}
}).json()
print(f"Allowed: {result['result']}") # True (own data)
result = requests.post(f"{OPA}/data/authz/allow", json={
"input": {
"user": {"id": "user-42", "role": "user"},
"method": "GET",
"path": ["users", "user-99"]
}
}).json()
print(f"Allowed: {result['result']}") # False
Kubernetes with Gatekeeper
# Require all pods to have resource limits
apiVersion: templates.gatekeeper.sh/v1
kind: ConstraintTemplate
metadata:
name: k8srequiredlimits
spec:
crd:
spec:
names:
kind: K8sRequiredLimits
targets:
- target: admission.k8s.gatekeeper.sh
rego: |
package k8srequiredlimits
violation[{"msg": msg}] {
container := input.review.object.spec.containers[_]
not container.resources.limits.cpu
msg := sprintf("Container %v has no CPU limit", [container.name])
}
violation[{"msg": msg}] {
container := input.review.object.spec.containers[_]
not container.resources.limits.memory
msg := sprintf("Container %v has no memory limit", [container.name])
}
OPA with Python Middleware
from flask import Flask, request, jsonify
import requests
app = Flask(__name__)
def check_authz(user, method, path):
result = requests.post("http://opa:8181/v1/data/authz/allow", json={
"input": {"user": user, "method": method, "path": path.split("/")[1:]}
}).json()
return result.get("result", False)
@app.before_request
def authorize():
user = get_current_user() # From JWT/session
if not check_authz(user, request.method, request.path):
return jsonify({"error": "Forbidden"}), 403
Resources
- OPA Docs
- OPA GitHub — 9.5K+ stars
- Rego Playground
Need to scrape web data for your policy engine? Check out my web scraping tools on Apify — production-ready actors for Reddit, Google Maps, and more. Questions? Email me at spinov001@gmail.com
Top comments (0)