3. Rego 语言入门(一):Rego 语法基础、关键字、注释、标量类型、复合类型
Rego 是 OPA 的策略语言,专为在复杂 JSON/YAML 数据上表达策略逻辑而设计。它脱胎于 Prolog 与 Datalog,但更贴近云原生场景。本章从零开始,建立你对 Rego 语法骨架的认知。
3.1 语法基础:声明式查询与规则
Rego 是声明式语言:你描述“想要什么”,而非“如何计算”。核心单元是 规则(Rule),每条规则定义一组逻辑条件,返回一个值或布尔结果。
关键概念:Rego 中一切皆表达式,表达式求值结果为
true 或 false。规则本质是“如果条件成立,则结论成立”。
一个最简单的 Rego 规则示例:
# 规则:如果 x 大于 5,则 allowed 为 true
allowed {
x := input.value
x > 5
}
当 input.value 为 10 时,allowed 返回 true;否则为 undefined(即不匹配)。
3.2 关键字(Reserved Keywords)
Rego 保留以下关键字,不可用作变量名或规则名:
| 关键字 | 用途说明 |
|---|---|
package |
定义策略包名,用于模块化 |
import |
导入其他包或数据 |
as |
配合 import 使用,起别名 |
default |
为规则设置默认值,避免 undefined |
not |
逻辑取反 |
with |
模拟数据覆盖,用于测试 |
some |
声明局部变量,用于迭代 |
every |
全称量词,检查集合中所有元素 |
if |
规则条件分隔符(可选,增强可读性) |
contains |
用于定义集合生成规则 |
提示:
if 和 contains 是 Rego v0.48+ 引入的语法糖,使规则更接近自然语言。旧版本使用 = 或隐式 true。
3.3 注释(Comments)
Rego 使用 # 作为单行注释,不支持多行注释块。注释应紧贴被说明的代码,保持策略可读性。
# 这是单行注释
package example
# 检查用户是否属于 admin 组
allow {
input.role == "admin"
}
3.4 标量类型(Scalar Types)
Rego 支持四种标量类型,它们是构建复杂策略的原子单元:
| 类型 | 示例 | 说明 |
|---|---|---|
| 字符串 | "hello"、"v1.2.3" |
双引号包裹,支持转义 |
| 数字 | 42、3.14、-1 |
整数和浮点数,无精度限制 |
| 布尔值 | true、false |
逻辑判断基础 |
| 空值 | null |
表示缺失或空值 |
标量类型可直接用于比较和赋值:
# 标量类型使用示例
version := "1.2.3"
count := 100
is_valid := true
metadata := null
3.5 复合类型(Composite Types)
Rego 提供四种复合类型,用于建模结构化数据(如 Kubernetes 资源、CI 构建产物元数据):
| 类型 | 语法 | 示例 | 特点 |
|---|---|---|---|
| 对象(Object) | {} |
{"name": "app", "ver": 1} |
键值对,键必须是字符串,值任意 |
| 数组(Array) | [] |
[1, 2, 3]、["a", "b"] |
有序列表,索引从 0 开始 |
| 集合(Set) | {} 但元素无重复 |
{"x", "y", "z"} |
无序、唯一元素,无键 |
| 复合嵌套 | 任意组合 | [{"a": [1,2]}, {"b": set()}] |
对象/数组/集合可无限嵌套 |
注意:集合(Set)与空对象字面量语法相同
{},但 Rego 编译器会根据上下文自动区分。空集合写作 set()。
复合类型操作示例:
# 对象访问
artifact := {"name": "app.jar", "size_mb": 45}
artifact.name # 结果为 "app.jar"
# 数组索引
tags := ["stable", "signed", "scanned"]
tags[0] # 结果为 "stable"
# 集合成员检查
allowed_regions := {"us-east-1", "eu-west-1"}
allowed_regions["us-east-1"] # 结果为 true
3.6 类型体系总览图
下图展示了 Rego 类型体系的层级关系,帮助你快速建立全局认知:
3.7 复合类型实战:构建产物元数据建模
在 CI/CD 流水线中,构建产物信息通常以 JSON 形式传入 OPA。下面是一个典型的数据结构,融合了所有复合类型:
# 模拟 input 数据:构建产物元数据
input := {
"artifact": {
"name": "backend-service.jar",
"size_mb": 128,
"checksum": "sha256:abc123..."
},
"build_info": {
"job": "build-backend",
"pipeline_id": "12345",
"tags": ["production", "signed", "scanned"]
},
"allowed_regions": {"us-east-1", "eu-west-1", "ap-southeast-1"},
"vulnerabilities": [
{"cve": "CVE-2024-1234", "severity": "HIGH"},
{"cve": "CVE-2024-5678", "severity": "MEDIUM"}
]
}
对应的 Rego 策略片段:
# 检查产物是否在允许区域部署
deny[msg] {
region := input.build_info.tags[_] # 数组迭代
not input.allowed_regions[region] # 集合成员检查
msg := sprintf("区域 %v 不在允许列表中", [region])
}
# 检查是否存在高危漏洞
deny[msg] {
vuln := input.vulnerabilities[_]
vuln.severity == "HIGH"
msg := sprintf("高危漏洞: %v", [vuln.cve])
}
最佳实践:在编写 Rego 策略前,先画出输入数据的 JSON 结构图,明确哪些字段是对象、数组、集合。这能大幅减少类型误用导致的策略错误。
3.8 本章小结
至此,你已掌握 Rego 的语法骨架:
- 声明式规则:用条件描述策略,而非步骤
- 10 个核心关键字:package、import、default、not、some、every、if、contains、as、with
- 4 种标量类型:字符串、数字、布尔值、null
- 3 种复合类型:对象、数组、集合,支持无限嵌套