Rego Language Fundamentals

📖 Introduction

Learning Rego felt unfamiliar at first. I'd been writing Python, TypeScript, and Go — all imperative to some degree. Rego is declarative in a way that took me a few sessions to internalize. It doesn't describe how to check something; it describes what must be true. Once that clicked, writing policies became intuitive.

This article is a ground-up tour of the Rego language. Every concept here is something you'll use when writing real Kubernetes policies later in the series.


🧩 Packages

Every Rego file starts with a package declaration. Packages organize policies into namespaces and determine how rules are referenced.

package myapp.security

When OPA evaluates a policy, results are available under data.<package.path>.<rule>:

data.myapp.security.deny

📥 Input and Data

Rego operates on two special global documents:

  • input — the JSON document sent by the caller (the thing being evaluated)

  • data — JSON loaded into OPA ahead of time (configuration, external data)

package example

# Access fields from input
app_name := input.metadata.name

# Access fields from loaded data
approved_registries := data.config.registries

Both are immutable during evaluation. OPA finds values; it doesn't mutate state.


📐 Rules

Rules are the core building blocks. A rule has a head (what it produces) and a body (the conditions under which it's true).

Simple Boolean Rules

If the body evaluates to true, the rule is defined (truthy). If the body is undefined or false, the rule itself is undefined.

Rules With Values

Default Values

When a rule might be undefined, use default to provide a fallback:

Without the default, querying allow when no rule body matches would return undefined — which is different from false. The default makes intent explicit.


🔁 Iteration

Rego iterates implicitly using variables and the _ wildcard.

Wildcard Iteration

The _ placeholder means "any element, I don't care about the index":

Named Variable Iteration

Use a named variable when you need to reference the same element in multiple expressions:

some for Explicit Iteration

The some keyword makes iteration explicit and is required in certain contexts:

some container in input.spec.containers binds container to each element of the array.


📦 Sets and Set Comprehensions

Rego has native set support. Partial rules that use contains build sets:

You can also use set comprehensions inline:


📋 Object Comprehensions

Build maps (JSON objects) inline:


🔗 Logical AND and OR

AND — Multiple Expressions in One Body

All expressions in a single rule body must be true simultaneously (AND):

OR — Multiple Rule Bodies With the Same Name

If you define multiple rules with the same name, OPA ORs them:

OPA collects all values from all matching rules into the deny set.


🔧 Built-in Functions

OPA provides a rich set of built-in functions. The ones you'll use most in Kubernetes policies:

String Functions

Collection Functions

every — Universal Quantification

every passes only if the condition is true for every element in the collection.


🧮 Functions (User-Defined)

You can define reusable functions in Rego:


🌳 Nested Data Access

Kubernetes resources are deeply nested. Rego handles this cleanly:

If securityContext doesn't exist on a container, c.securityContext.allowPrivilegeEscalation is undefined — and an undefined expression causes the rule body to not match (no false positive, no crash).


🔬 Trying Rego Locally

The fastest way to learn Rego is the interactive REPL:

Or evaluate a policy file against an input file:

Output:


🗺️ Rego Mental Model Summary

spinner
Concept
Purpose

package

Namespace for rules

input

The thing being evaluated

data

Loaded external configuration

default

Fallback when a rule is undefined

contains

Build a set incrementally

_

Wildcard iteration

some ... in ...

Explicit iteration

every ... in ...

Universal quantification


🧭 What's Next

You now know enough Rego to write meaningful policies. The next article covers how OPA runs — the architecture, deployment modes, and how the query flow actually works before we get into Kubernetes-specific usage.

Next: Article 03 — OPA Architecture and Deployment Modes


📎 References

Last updated