Rego#
Rego is the policy language of Open Policy Agent (OPA). A declarative, Datalog-derived language for “is this allowed?” decisions across cloud-native systems.
Used as the policy engine for Kubernetes admission control (OPA Gatekeeper, Kyverno’s competitor), service-mesh authorization (Istio, Envoy via ext_authz), CI/CD (Conftest), Terraform plan validation, microservice authz, and feature flags.
The Policy Mental Model#
OPA’s world has four moving parts: input describes the request, data holds supporting state, policy is the Rego rules that compute decisions, and the decision is whatever value the rules produce at a queried path. Everything else in OPA is plumbing around that core.
Input, a JSON document representing the request to evaluate.
Data, supporting state loaded into OPA (users, roles, allowed hosts).
Policy, Rego rules; produce decisions (true / false / objects).
Decision, the value at a queried path (e.g.
data.authz.allow).
OPA evaluates the policy against input and data, returning
whatever the rules compute.
A Minimal Policy#
package authz
default allow := false
# Allow if the user is in the admins list
allow if {
input.user in data.admins
}
# Allow read for the resource owner
allow if {
input.method == "GET"
input.user == input.resource.owner
}
# Deny everything else (the default)
Building Blocks#
The vocabulary of a Rego file. Packages namespace; rules pair
a head with a body; defaults supply a fallback; not is
negation-as-failure; some and every quantify. Together
these primitives compose into policies that look declarative
even when the underlying logic is intricate.
package <name>, namespace for rules.import <pkg>, bring in another package’s rules.Rules,
head { body }(Rego v0) orhead if { body }(v1).Variables start uppercase; identifiers stay lowercase.
default x := v, the value ofxif no rule matches.not, negation as failure.some x in xs, existential quantification.every x in xs { ... }, universal.
Sets, Lists, and Objects#
# Comprehensions
admin_users := { u | u := data.users[_]; u.role == "admin" }
user_emails := [ u.email | u := data.users[_] ]
role_users := { role: users |
role := data.users[_].role
users := [u.name | u := data.users[_]; u.role == role]
}
Common Use Cases#
The kinds of work where Rego is the standard tool.
Kubernetes admission control via Gatekeeper, service-mesh
authorization through Envoy ext_authz, and Terraform plan
validation via Conftest are the three most common; each
uses the same language with a different input schema.
Kubernetes admission control (Gatekeeper).
package k8spsphardening
violation[{"msg": msg}] if {
input.review.object.kind == "Pod"
some c
c := input.review.object.spec.containers[_]
not c.securityContext.runAsNonRoot
msg := sprintf("container %v must runAsNonRoot", [c.name])
}
Service-to-service authorization (Envoy ext_authz).
package envoy.authz
default allow := false
allow if {
input.attributes.request.http.method == "GET"
input.attributes.request.http.path == "/health"
}
allow if {
token := bearer_token
claims := io.jwt.decode_verify(token, {
"secret": "...", "iss": "auth.example.com"
})
claims.role == "service"
}
Conftest / Terraform plan validation:
package main
deny[msg] if {
resource := input.resource_changes[_]
resource.type == "aws_s3_bucket"
resource.change.after.acl == "public-read"
msg := sprintf("S3 bucket %v is public", [resource.address])
}
Functions and Built-Ins#
Rego ships hundreds of built-in functions.
Built-in |
Use |
|---|---|
|
string predicates |
|
string ops |
|
parse data |
|
HTTP request from policy (carefully) |
|
hashing / cert parsing |
|
JWT validation |
|
IP-range checks |
|
time |
|
regex |
|
access rule metadata |
OPA in Production#
The deployment patterns that make OPA practical at scale. Sidecar gives every service a local policy decision point; library mode embeds OPA in-process; bundles distribute signed policy and data; decision logs ship every evaluation to a SIEM for audit. Latencies are sub-millisecond.
Sidecar, run OPA next to each service, query via REST or gRPC.
Library, some languages embed OPA / Rego directly (Go, Wasm).
Bundles, distribute policy + data as signed bundles to all OPA instances.
Decision logs, ship every decision to a SIEM for audit.
Latencies are typically sub-millisecond for evaluating a request against thousands of rules; OPA pre-compiles policies into a virtual machine.
Tooling#
The CLIs and integrations that surround Rego. The opa
binary handles eval, test, fmt, and bench; Conftest tests
config files; Gatekeeper is the Kubernetes admission
controller; Regal lints; Styra DAS manages OPA at scale.
VS Code extensions round out the authoring story.
opa, the binary.
opa eval,opa test,opa fmt,opa bench.Conftest, test config files (Kubernetes YAML, Terraform plans, Dockerfiles) against Rego.
Gatekeeper – Kubernetes admission controller.
Styra DAS, commercial OPA management.
Regal, Rego linter.
VS Code extension for syntax highlighting and
opa testintegration.
Testing#
Rego has a built-in test framework.
package authz_test
import data.authz
test_admin_can_do_anything if {
authz.allow with input as {"user": "operator", "method": "POST"}
with data.admins as ["operator"]
}
test_unknown_denied if {
not authz.allow with input as {"user": "stranger"}
}
$ opa test policies/ -v
Strengths#
The reasons OPA wins as the cross-cutting policy choice. One language across many decision points, a compiled VM for sub-millisecond evaluation, integrations spanning Kubernetes through Terraform, and signed bundles plus structured decision logs that satisfy auditors.
General-purpose policy, one language, many decision points.
Fast, compiled VM; sub-millisecond evals.
Ecosystem, Kubernetes, Envoy, Terraform, Kafka, OCI registries all have integrations.
Auditable, decisions are deterministic; bundles are signed; decision logs are structured.
Weaknesses#
The flip side. Datalog-flavored declarative semantics confuse imperative-trained developers; variable scoping rules surprise; debugging is primitive next to a real IDE; and the v0/v1 split needs explicit version pinning until the ecosystem fully migrates.
Learning curve, declarative + Datalog-flavored is unfamiliar.
Variable scoping rules surprise newcomers.
Debug story,
traceandprintexist but feel primitive.Two language versions, v0 (default in older OPA) and v1; subtle syntax differences. Pin a version.
Alternatives#
The other policy languages an operator may meet. Sentinel covers HashiCorp products; Cedar is the AWS-developed authorization language; Kyverno is Kubernetes-native; Polar and Casbin compete for application-level authz. Each wins in its niche; Rego remains the cross-cutting bet.
HCL, Sentinel is HashiCorp’s policy language for Terraform / Vault / Nomad; HCL-based.
Cedar, AWS-developed authorization language; simpler than Rego, focused on application authz.
Kyverno, Kubernetes-native; YAML-based policies; popular alternative to Gatekeeper.
OSO Polar, application authz language.
Casbin, lightweight authz library with multiple policy languages.
For Kubernetes-only policy, Kyverno is often easier; for cross-cutting policy across many systems, Rego/OPA is the durable bet.