策略语法基础:策略语言的基本结构、关键字与语法规则
在云原生安全基线核验中,策略即代码(Policy as Code)是核心实践。不同的策略引擎(如 OPA、Kyverno)使用不同的策略语言,但都遵循声明式、可组合的语法范式。本章将系统梳理 Rego(OPA 语言)、Kyverno 策略(基于 YAML 的 DSL)以及通用策略语言的基本结构、关键字与语法规则,帮助你在编写和调试策略时快速定位语法错误。
3.1 策略语言核心概念对比
下表从语言类型、策略结构、规则定义方式、变量作用域四个维度对比三种主流策略语言,便于建立整体认知。
| 维度 | Rego (OPA) | Kyverno (YAML DSL) | 通用策略语言参考 |
|---|---|---|---|
| 语言类型 | 声明式逻辑编程语言(类 Datalog) | 声明式 YAML 配置(基于 Kubernetes 资源) | 声明式规则引擎(如 JSON/YAML + 条件表达式) |
| 策略结构 | package + import + rules | apiVersion + kind + metadata + spec | 规则集 + 条件 + 动作 |
| 规则定义 | 规则名 := 表达式 { 条件 } | match + validate / mutate / generate | if-then 或 when-then 结构 |
| 变量作用域 | 局部变量(:= 赋值)、全局变量(data) | 模板变量({{ request.object.spec }}) | 上下文变量(context.xxx) |
3.2 Rego 语言基本结构与关键字
Rego 是 OPA 的原生策略语言,其核心结构由 包(package)、导入(import)、规则(rule) 三部分组成。规则是 Rego 的基本计算单元,每条规则返回一个布尔值、集合或对象。
3.2.1 基本结构示例
package kubernetes.admission
import data.kubernetes.resources as k8s
# 规则:禁止使用 latest 标签
deny[msg] {
input.request.kind.kind == "Pod"
container := input.request.object.spec.containers[_]
container.image == "nginx:latest"
msg := sprintf("容器 %v 使用了 latest 标签,请指定固定版本", [container.name])
}
3.2.2 核心关键字与语法规则
- package:声明策略所属的命名空间,用于组织策略和避免命名冲突。
- import:导入外部数据或规则,支持别名(as)和通配符(*)。
- 规则头:
规则名 := 表达式(完整规则)或规则名[变量] { 条件 }(部分规则)。 - 迭代器:
some i或_用于遍历数组/集合,如input.spec.containers[_]。 - 赋值:
:=用于局部变量赋值,==用于相等比较,=用于统一(unification)。 - 内置函数:
sprintf、count、regex.match等,用于字符串处理、集合运算和正则匹配。
常见语法陷阱:Rego 中
= 和 := 容易混淆。:= 只能用于首次赋值,后续引用必须使用 == 或 =。例如 x := 1; x == 2 是合法比较,但 x := 1; x := 2 会引发编译错误。
3.3 Kyverno 策略结构与语法规则
Kyverno 策略使用 Kubernetes 原生 YAML 格式,通过 match 和 validate/mutate/generate 块定义规则。其语法更贴近 Kubernetes 用户习惯,但同样需要严格遵循 YAML 缩进和字段约束。
3.3.1 基本结构示例
apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
name: disallow-latest-tag
spec:
validationFailureAction: Audit
rules:
- name: require-image-tag
match:
resources:
kinds:
- Pod
validate:
message: "镜像标签不能为 latest"
pattern:
spec:
containers:
- image: "!*:latest"
3.3.2 核心关键字与语法规则
- apiVersion / kind:固定为
kyverno.io/v1和ClusterPolicy(集群范围)或Policy(命名空间范围)。 - spec.rules:规则列表,每个规则包含
name、match、validate/mutate/generate。 - match:定义策略适用的资源类型、标签选择器、命名空间等。
- validate.pattern:使用 Kubernetes 风格的
pattern或anyPattern进行字段匹配,支持通配符*和否定!。 - validate.deny:使用
conditions块编写更复杂的条件表达式,支持key、operator、value。 - 模板变量:
{{ request.object.spec.containers[].image }}用于引用请求中的字段。
YAML 缩进错误:Kyverno 策略中
match、validate 等字段的缩进层级必须严格对齐。常见错误是将 validate 与 match 放在同一层级,导致策略解析失败。建议使用 YAML 校验工具(如 yamllint)预先检查。
3.4 策略语法结构总览图
下图展示了 Rego 和 Kyverno 两种策略语言的语法结构对比,帮助理解声明式策略的通用组织模式。
3.5 通用语法规则与调试要点
无论使用哪种策略语言,以下语法规则是编写可调试策略的基础:
- 声明式优先:策略只描述“应该是什么”,不描述“如何执行”。避免在策略中编写循环或复杂控制流。
- 数据不可变:策略引擎通常不允许修改输入数据,所有转换通过 mutate 或 copy 语义实现。
- 规则组合:多个规则通过逻辑与(AND)或逻辑或(OR)组合,Rego 使用
;和|,Kyverno 使用conditions块。 - 错误处理:策略引擎遇到语法错误时,通常返回明确的错误行号和原因。常见错误包括:未闭合的括号、缩进不一致、未定义的变量、类型不匹配。
调试建议:在编写策略时,先使用最小化输入(如单个 Pod 的 JSON 表示)进行单元测试。Rego 可使用
opa eval 命令配合 --input 参数;Kyverno 可使用 kyverno apply 命令进行本地验证。将策略拆分为多个小规则,逐条验证,能显著降低语法错误的排查难度。
3.6 策略语法错误分类与排查流程
下图总结了策略语法错误的常见类型及排查步骤,帮助你在实际调试中快速定位问题。