2. OPA 基础:OPA 简介、Rego 语言核心概念与策略即代码
在云原生安全准入控制体系中,OPA(Open Policy Agent)已成为事实上的策略引擎标准。本章将深入剖析 OPA 的设计哲学、Rego 语言的核心语法,以及“策略即代码”这一核心理念如何重塑安全治理模式。
2.1 OPA 简介:通用策略引擎
OPA 是一个开源的、与平台无关的策略引擎,它将策略决策从具体业务逻辑中解耦。OPA 不负责执行策略(如拒绝请求),而是回答“这个请求是否被允许?”的问题。
核心设计原则: OPA 采用“决策请求-策略评估”的分离架构。任何系统(Kubernetes、API 网关、CI/CD 流水线)都可以向 OPA 发送结构化查询(Input),OPA 结合策略(Policy)和数据(Data)返回决策结果(Decision)。
OPA 的工作流程可概括为以下步骤:
- 输入(Input): 外部系统(如 Kubernetes API Server)将准入请求(如 Pod 创建请求)转换为 JSON 格式发送给 OPA。
- 策略评估: OPA 使用 Rego 语言编写的策略规则,对输入进行逻辑判断。
- 数据查询: 策略执行过程中,OPA 可查询外部数据源(如允许的镜像仓库列表、用户角色信息)。
- 决策输出: OPA 返回
allow(允许)、deny(拒绝)或带有详细原因的violation信息。
2.2 Rego 语言核心概念
Rego 是 OPA 的原生查询语言,专为在复杂嵌套结构(如 JSON/YAML)上定义策略而设计。Rego 并非通用编程语言,而是一种声明式逻辑语言,其核心是“规则”和“查询”。
2.2.1 基本语法与规则
Rego 中的基本单元是 规则(Rule)。一个规则定义了一个决策或一个中间值。
# 定义一个简单的 allow 规则
package kubernetes.admission
# 如果 input 中的 role 是 "admin",则允许
allow {
input.role == "admin"
}
# 如果用户属于 "ops" 团队,也允许
allow {
input.team == "ops"
}
上述代码中:
package用于组织策略,避免命名冲突。allow是规则名,OPA 默认将规则名作为决策结果。{ ... }内的表达式必须全部为true,该规则才成立。- 多个同名规则(如两个
allow)之间是 逻辑或(OR) 关系。
2.2.2 迭代与推导
Rego 的强大之处在于对集合的迭代和推导能力,无需显式编写循环。
# 检查容器镜像是否来自允许的仓库
deny[msg] {
container := input.containers[_]
not startswith(container.image, "registry.example.com/")
msg := sprintf("容器 %v 使用了未授权的镜像仓库: %v", [container.name, container.image])
}
关键点解析:
input.containers[_]:[_]是迭代语法,遍历containers数组中的每个元素。deny[msg]:生成一个包含违规信息的集合。如果集合非空,表示存在违规。sprintf:Rego 内置的字符串格式化函数。
2.2.3 内置函数与数据查询
Rego 提供了丰富的内置函数,用于字符串处理、时间比较、加密计算等。同时,OPA 支持通过 data 关键字查询外部数据。
| 类别 | 函数/语法 | 说明 |
|---|---|---|
| 字符串 | startswith(str, prefix) |
检查字符串是否以指定前缀开头 |
| 集合 | array.concat(a, b) |
合并两个数组 |
| 时间 | time.now_ns() |
获取当前时间(纳秒) |
| 数据查询 | data.allowed_registries[_] |
从 OPA 的数据文档中查询允许的仓库列表 |
最佳实践: 将动态配置(如允许的镜像列表、用户角色)作为 Data 注入 OPA,而非硬编码在 Rego 策略中。这样策略与配置分离,更新配置无需修改策略代码。
2.3 策略即代码(Policy as Code)
“策略即代码”是将安全策略、合规规则和治理要求以代码形式进行版本管理、测试、部署和审计的实践。OPA 和 Rego 是实现这一理念的理想工具。
2.3.1 与传统策略管理的对比
| 维度 | 传统策略管理 | 策略即代码(OPA) |
|---|---|---|
| 存储形式 | 文档、Wiki、PDF | Git 仓库中的 Rego 文件 |
| 变更流程 | 邮件审批、手动配置 | Pull Request + CI 测试 + 自动部署 |
| 可测试性 | 难以自动化测试 | 支持单元测试和集成测试 |
| 审计追溯 | 依赖操作日志 | Git 历史 + 策略版本标签 |
| 执行一致性 | 依赖人工理解 | 机器自动执行,结果一致 |
2.3.2 策略即代码的流水线集成
在 DevSecOps 流水线中,策略即代码的典型工作流如下:
- 开发: 安全工程师在 Git 仓库中编写 Rego 策略。
- 测试: CI 阶段运行
opa test命令,验证策略逻辑正确性。 - 打包: 将策略编译为 OPA Bundle(.tar.gz 文件)。
- 部署: 将 Bundle 分发到 OPA 实例或作为 Sidecar 注入。
- 执行: 运行时,OPA 加载最新策略,对每个准入请求进行实时评估。
常见陷阱: 不要将 OPA 策略写成“万能规则”。策略应保持原子性,每个规则只关注一个安全维度(如镜像来源、特权容器、网络策略)。过度复杂的规则难以测试和维护。