Rego is the declarative policy language used by Open Policy Agent (OPA) for writing and enforcing policies across cloud-native stacks, featuring data-driven rules, comprehensions, and 200+ built-in functions for infrastructure, security, and compliance automation.
Overall
score
97%
Rego is a declarative query language designed for policy-as-code. It is the native policy language for Open Policy Agent (OPA), a general-purpose policy engine that enables unified, context-aware policy enforcement across the entire technology stack.
Open Policy Agent (OPA) provides:
Rego policies are declarative rules written in a high-level language that can express complex logic, perform data transformations, and make authorization decisions based on rich contextual information.
Package Declaration Every Rego file begins with a package declaration that organizes policies into namespaces:
package kubernetes.admission
import rego.v1Packages help organize related policies and prevent naming conflicts. Common package naming conventions:
kubernetes.admission - Kubernetes admission control policiesdocker.authz - Docker authorization policiesterraform.analysis - Terraform plan validationhttpapi.authz - HTTP API authorizationrbac.authz - Role-based access controlabac.authz - Attribute-based access controlRego provides several built-in modules and supports importing external data and helper functions.
Importing Input Data
import input as tfplanAssigns the entire input document to a more descriptive variable name.
Importing External Data
import data.kubernetes.namespaces
import data.kubernetes.ingressesImports external data loaded into OPA for policy evaluation, such as cluster state or configuration.
OPA v1 Compatibility
import rego.v1Enables all Rego v1 keywords (if, contains, in, every) for policies running on OPA 0.55+. In OPA 1.0+, these keywords are part of the language by default and no import is required. Do not use import future.keywords — it is deprecated and cannot be combined with import rego.v1.
Rego includes several built-in libraries for common operations:
time.* - Time and date operationsnet.* - Network operations (CIDR matching, IP parsing)crypto.* - Cryptographic operationsio.jwt.* - JWT token parsing and verificationjson.* - JSON validation and manipulationyaml.* - YAML validationstrings.* - String manipulationregex.* - Regular expression matchingRego policies define rules that evaluate to true or false, or produce values. The most common patterns involve making authorization decisions or validating configurations.
The fundamental pattern for authorization:
package example.authz
import rego.v1
default allow := false
allow if {
input.user == "admin"
}
allow if {
input.method == "GET"
input.user == "viewer"
}Collecting multiple policy violations:
package example.validation
import rego.v1
deny contains msg if {
not input.username
msg := "username is required"
}
deny contains msg if {
count(input.username) < 3
msg := "username must be at least 3 characters"
}Processing and aggregating data:
package example.transform
import rego.v1
active_users := {user |
some user in input.users
user.status == "active"
}
total_cost_by_team[team] := total if {
some team
resources := [r | some r in input.resources; r.team == team]
costs := [r.cost | some r in resources]
total := sum(costs)
}This Knowledge Tile covers eight major themes for using Rego in production environments. Each theme includes detailed examples, best practices, and real-world use cases.
Validate and enforce policies on Kubernetes resources before they are created or updated in the cluster.
Use Cases: Image registry validation, resource requirements, label enforcement, security standards, hostname conflict prevention.
Example: Image Registry Validation
Ensures all container images come from approved corporate registries:
package kubernetes.admission
import rego.v1
deny contains msg if {
input.request.kind.kind == "Pod"
some container in input.request.object.spec.containers
image := container.image
not startswith(image, "hooli.com/")
msg := sprintf("image '%v' comes from untrusted registry", [image])
}Example: Resource Label Requirements
Requires specific labels on Kubernetes resources for proper organization:
package kubernetes.admission
import rego.v1
required_labels := ["app", "team", "environment"]
deny contains msg if {
input.request.kind.kind == "Deployment"
labels := input.request.object.metadata.labels
some required_label in required_labels
not labels[required_label]
msg := sprintf("Deployment missing required label: %v", [required_label])
}Example: Pod Security Standards
Enforces pod security standards like non-root user and read-only filesystem:
package kubernetes.admission
import rego.v1
deny contains msg if {
input.request.kind.kind == "Pod"
some container in input.request.object.spec.containers
not container.securityContext.runAsNonRoot
msg := sprintf("Container %v must run as non-root user", [container.name])
}
deny contains msg if {
input.request.kind.kind == "Pod"
some container in input.request.object.spec.containers
not container.securityContext.readOnlyRootFilesystem
msg := sprintf("Container %v must use read-only root filesystem", [container.name])
}View detailed Kubernetes admission control examples →
Control Docker daemon operations and enforce security policies on container configurations.
Use Cases: Privileged container prevention, volume mount restrictions, seccomp profile enforcement, user-based access control.
Example: Seccomp Profile Enforcement
Prevents containers from running with unconfined seccomp profiles:
package docker.authz
import rego.v1
default allow := false
allow if {
not deny
}
deny if {
seccomp_unconfined
}
seccomp_unconfined if {
"seccomp:unconfined" in input.Body.HostConfig.SecurityOpt
}Example: Privileged Container Prevention
Blocks creation of privileged containers:
package docker.authz
import rego.v1
default allow := false
allow if {
not deny
}
deny if {
input.Body.HostConfig.Privileged == true
}Example: Volume Mount Restrictions
Restricts which host paths can be mounted into containers:
package docker.authz
import rego.v1
default allow := false
allowed_volume_paths := {"/data", "/logs", "/tmp"}
deny if {
some bind in input.Body.HostConfig.Binds
[host_path, _] := split(bind, ":")
not allowed_volume_paths[host_path]
}View detailed container security examples →
Validate Terraform plans and CloudFormation templates before deployment to catch security and compliance issues.
Use Cases: Blast radius control, IAM protection, encryption requirements, required tags enforcement, security group validation.
Example: Blast Radius Control and IAM Protection
Controls the blast radius of infrastructure changes and prevents IAM modifications:
package terraform.analysis
import input as tfplan
import rego.v1
blast_radius := 30
weights := {
"aws_autoscaling_group": {"delete": 100, "create": 10, "modify": 1},
"aws_instance": {"delete": 10, "create": 1, "modify": 1},
}
default authz := false
authz if {
score < blast_radius
not touches_iam
}
score := s if {
all_resources := [x |
some resource_type, crud in weights
del := crud.delete * num_deletes[resource_type]
new := crud.create * num_creates[resource_type]
mod := crud.modify * num_modifies[resource_type]
x := (del + new) + mod
]
s := sum(all_resources)
}
touches_iam if {
all_resources := resources.aws_iam
count(all_resources) > 0
}Example: S3 Bucket Encryption Requirement
Ensures all S3 buckets have encryption enabled:
package terraform.analysis
import input as tfplan
import rego.v1
deny contains msg if {
some r in tfplan.resource_changes
r.type == "aws_s3_bucket"
"create" in r.change.actions
not r.change.after.server_side_encryption_configuration
msg := sprintf("S3 bucket %v does not have encryption enabled", [r.address])
}Example: CloudFormation S3 Bucket Access Control
Enforces security compliance on S3 buckets before CloudFormation deployment:
package system
import rego.v1
main := {
"allow": count(deny) == 0,
"violations": deny,
}
deny contains msg if {
bucket_create_or_update
not bucket_is_private
msg := sprintf("S3 Bucket %s 'AccessControl' attribute value must be 'Private'", [input.resource.id])
}
bucket_create_or_update if {
input.resource.type == "AWS::S3::Bucket"
input.action in {"CREATE", "UPDATE"}
}
bucket_is_private if {
input.resource.properties.AccessControl == "Private"
}View detailed infrastructure as code examples →
Implement fine-grained authorization for REST APIs based on user context, roles, and resource ownership.
Use Cases: Hierarchical authorization, JWT-based access control, method-based permissions, path-based authorization.
Example: Hierarchical Authorization
Context-aware authorization based on organizational hierarchy:
package httpapi.authz
import rego.v1
subordinates := {"alice": [], "charlie": [], "bob": ["alice"], "betty": ["charlie"]}
default allow := false
# Allow users to get their own salaries.
allow if {
input.method == "GET"
input.path == ["finance", "salary", input.user]
}
# Allow managers to get their subordinates' salaries.
allow if {
some username
input.method == "GET"
input.path = ["finance", "salary", username]
username in subordinates[input.user]
}Example: JWT-Based Access Control
JWT-based authentication with role verification:
package httpapi.authz
import rego.v1
default allow := false
# Allow users to get their own salaries.
allow if {
some username
input.method == "GET"
input.path = ["finance", "salary", username]
token.payload.user == username
user_owns_token
}
# Ensure that the token was issued to the user supplying it.
user_owns_token if input.user == token.payload.azp
# Helper to get the token payload.
token := {"payload": payload} if {
[header, payload, signature] := io.jwt.decode(input.token)
}Example: Method-Based Access Control
Restricts HTTP methods based on user permissions:
package httpapi.authz
import data.users
import rego.v1
default allow := false
allow if {
input.method == "GET"
"read" in users[input.user].permissions
}
allow if {
input.method in {"POST", "PUT", "PATCH"}
"write" in users[input.user].permissions
}
allow if {
input.method == "DELETE"
"admin" in users[input.user].permissions
}View detailed HTTP API authorization examples →
Implement sophisticated access control patterns including RBAC, ABAC, and custom authorization logic.
Use Cases: Role-based access control, attribute-based access control, separation of duty, time-based access, location-based access.
Example: Basic RBAC Pattern
Core RBAC implementation with user/role/permission mappings:
package rbac.authz
import rego.v1
# user-role assignments
user_roles := {
"alice": ["engineering", "webdev"],
"bob": ["hr"],
}
# role-permissions assignments
role_permissions := {
"engineering": [{"action": "read", "object": "server123"}],
"webdev": [{"action": "read", "object": "server123"},
{"action": "write", "object": "server123"}],
"hr": [{"action": "read", "object": "database456"}],
}
default allow := false
allow if {
roles := user_roles[input.user]
some r in roles
permissions := role_permissions[r]
some p in permissions
p == {"action": input.action, "object": input.object}
}Example: Separation of Duty Violation Detection
Prevents conflicting role assignments for compliance:
package rbac.authz
import rego.v1
sod_roles := [
["create-payment", "approve-payment"],
["create-vendor", "pay-vendor"],
]
sod_violation contains user if {
some user
some role1 in user_roles[user]
some role2 in user_roles[user]
[role1, role2] in sod_roles
}Example: Time-Based Access Control
Restricts access based on time of day using ABAC:
package abac.authz
import rego.v1
default allow := false
allow if {
input.method == "GET"
is_business_hours
}
is_business_hours if {
[hour, _, _] := time.clock(time.now_ns())
hour >= 9
hour < 17
}View detailed access control model examples →
Automate validation and enforce quality standards in continuous integration and deployment pipelines.
Use Cases: File validation, change detection, test coverage requirements, security scanning, compliance checks.
Example: File Validation Policy
Validates configuration file syntax in CI/CD pipelines:
package files
import rego.v1
# METADATA
# entrypoint: true
deny contains sprintf("%s is an invalid YAML file: %s", [filename, content]) if {
some filename, content in yaml_file_contents
changes[filename].status in {"added", "modified"}
not yaml.is_valid(content)
}
deny contains sprintf("%s is an invalid JSON file: %s", [filename, content]) if {
some filename, content in json_file_contents
changes[filename].status in {"added", "modified"}
not json.is_valid(content)
}
yaml_file_contents[filename] := file_in_pr(filename) if {
some filename in filenames
extension(filename) in {"yml", "yaml"}
}
json_file_contents[filename] := file_in_pr(filename) if {
some filename in filenames
extension(filename) == "json"
}
extension(filename) := ext if {
parts := split(filename, ".")
ext := parts[count(parts) - 1]
}Example: PR Change Detection
Determines which tests to run based on changed files:
package policy["pr-check"]
import rego.v1
go_change_prefixes := [
"build/",
"capabilities/",
"internal/",
]
changes["docs"] if {
some changed_file in input
startswith(changed_file.filename, "docs/")
}
changes["go"] if {
some changed_file in input
some prefix in go_change_prefixes
startswith(changed_file.filename, prefix)
}
changes["wasm"] if {
some changed_file in input
startswith(changed_file.filename, "wasm/")
}Example: Test Coverage Requirements
Enforces minimum test coverage thresholds:
package cicd.coverage
import rego.v1
minimum_coverage := 80
deny contains msg if {
coverage := input.test_results.coverage_percent
coverage < minimum_coverage
msg := sprintf("Test coverage %v%% is below minimum %v%%", [coverage, minimum_coverage])
}View detailed CI/CD pipeline policy examples →
Validate input data, perform transformations, and implement content moderation policies.
Use Cases: Input validation, email validation, content filtering, data aggregation, object filtering, structured error responses.
Example: Comprehensive Input Validation
Validate multiple aspects of input:
package validation
import rego.v1
errors contains msg if {
not input.username
msg := "username is required"
}
errors contains msg if {
count(input.username) < 3
msg := "username must be at least 3 characters"
}
errors contains msg if {
not input.email
msg := "email is required"
}
errors contains msg if {
not contains(input.email, "@")
msg := "email must be valid"
}
valid if {
count(errors) == 0
}Example: Email Validation
Simple email format validation:
package content.validation
import rego.v1
valid_email if {
contains(input.email, "@")
parts := split(input.email, "@")
count(parts) == 2
parts[0] != ""
parts[1] != ""
}Example: Data Aggregation
Aggregate data from multiple sources:
package transform
import rego.v1
total_cost_by_team[team] := total if {
some team
resources := [r | some r in input.resources; r.team == team]
costs := [r.cost | some r in resources]
total := sum(costs)
}
resource_count_by_type[resource_type] := count(resources) if {
some resource_type
resources := [r | some r in input.resources; r.type == resource_type]
}View detailed data validation and transformation examples →
Enforce network security policies and regulatory compliance requirements.
Use Cases: CIDR range validation, egress traffic control, PCI-DSS compliance, data residency, network segmentation.
Example: CIDR Range Validation
Validates IP addresses against allowed CIDR ranges:
package network.policies
import rego.v1
allowed_cidrs := ["10.0.0.0/8", "172.16.0.0/12", "192.168.0.0/16"]
deny contains msg if {
ip := input.source_ip
not is_allowed_ip(ip)
msg := sprintf("IP address %v is not in allowed CIDR ranges", [ip])
}
is_allowed_ip(ip) if {
some cidr in allowed_cidrs
net.cidr_contains(cidr, ip)
}Example: Egress Traffic Control
Controls which external services can be accessed:
package network.egress
import rego.v1
allowed_domains := {"api.github.com", "registry.npmjs.org", "*.amazonaws.com"}
deny contains msg if {
host := input.request.host
not is_allowed_host(host)
msg := sprintf("Egress to %v is not allowed", [host])
}
is_allowed_host(host) if {
some pattern in allowed_domains
glob.match(pattern, ["."], host)
}Example: PCI-DSS Compliance Check
Validates resources against PCI-DSS requirements:
package compliance.pci
import rego.v1
deny contains msg if {
some resource in input.resources
resource.type == "database"
not resource.encrypted
msg := sprintf("Database %v must be encrypted for PCI-DSS compliance", [resource.id])
}
deny contains msg if {
some resource in input.resources
resource.type == "database"
not resource.audit_logging_enabled
msg := sprintf("Database %v must have audit logging for PCI-DSS compliance", [resource.id])
}View detailed network and compliance policy examples →
Document and categorize policies using OPA's built-in metadata annotation system for governance, discovery, and type safety.
Use Cases: Policy cataloging, entrypoint discovery, schema validation, severity classification, compliance framework tagging, documentation generation.
Example: Package-Level Metadata
Document an entire policy module with title, authors, and custom fields:
# METADATA
# title: Kubernetes Admission Control
# description: >-
# Validates Kubernetes resources against organization
# security standards.
# authors:
# - Platform Security Team <security@example.com>
# custom:
# category: kubernetes
# compliance_framework: SOC2
package kubernetes.admission
import rego.v1Example: Entrypoint Rule Annotation
Mark decision rules for auto-discovery with severity classification:
package terraform.analysis
import input as tfplan
import rego.v1
# METADATA
# title: Deny unencrypted S3 buckets
# description: Ensures all S3 buckets have server-side encryption
# entrypoint: true
# custom:
# severity: HIGH
deny contains msg if {
some r in tfplan.resource_changes
r.type == "aws_s3_bucket"
"create" in r.change.actions
not r.change.after.server_side_encryption_configuration
msg := sprintf("S3 bucket %v does not have encryption enabled", [r.address])
}Example: Runtime Metadata Access
Use rego.metadata.rule() for severity-aware violation reporting:
package security.reporter
import rego.v1
# METADATA
# title: Deny privileged containers
# entrypoint: true
# custom:
# severity: HIGH
# category: pod-security
violations contains violation if {
input.request.kind.kind == "Pod"
some container in input.request.object.spec.containers
container.securityContext.privileged == true
annotation := rego.metadata.rule()
violation := {
"severity": annotation.custom.severity,
"message": sprintf("privileged container %v is not allowed", [container.name]),
}
}View detailed metadata annotation examples →
OPA provides first-class support for testing policies. Tests are standard Rego rules prefixed with test_ and run with the opa test command.
Basic Unit Test:
package kubernetes.admission_test
import data.kubernetes.admission
import rego.v1
test_untrusted_image_denied if {
review := {
"request": {
"kind": {"kind": "Pod"},
"object": {
"spec": {
"containers": [
{"image": "hooli.com/nginx"},
{"image": "busybox"}
]
}
}
}
}
expected := "image 'busybox' comes from untrusted registry"
expected in admission.deny with input as review
}Mocking Data and Functions with with:
package api.authz_test
import data.api.authz
import rego.v1
mock_users := {
"alice": {"permissions": ["read", "write", "admin"]},
"bob": {"permissions": ["read"]},
}
test_admin_can_delete if {
authz.allow with input as {"user": "alice", "method": "DELETE"}
with data.users as mock_users
}
test_reader_cannot_delete if {
not authz.allow with input as {"user": "bob", "method": "DELETE"}
with data.users as mock_users
}Parameterized Tests:
package validation_test
import data.validation
import rego.v1
test_email_validation[description] if {
some description, tc in {
"valid email": {"input": {"email": "user@example.com"}, "expected": true},
"missing @": {"input": {"email": "userexample.com"}, "expected": false},
"empty email": {"input": {"email": ""}, "expected": false},
}
result := validation.valid_email with input as tc.input
result == tc.expected
}Run tests with the OPA CLI:
# Run all tests verbosely
opa test . -v
# Run with coverage analysis
opa test --coverage --format=json .
# Filter tests by name
opa test . -v --run "test_admin"View comprehensive policy testing guide →