2. OPA 基础概念
2.1 OPA(Open Policy Agent)是什么
OPA 是一个开源的、通用策略引擎,它将策略决策与业务逻辑的执行分离。在云原生生态中,OPA 被广泛用于实现微服务、Kubernetes、CI/CD 管道等场景的细粒度访问控制和合规性检查。其核心设计理念是:策略即代码(Policy as Code)。
核心定位:OPA 不负责执行策略(如允许/拒绝请求),而是根据输入数据和策略规则,输出决策结果(如 allow/deny)。这种解耦使得策略可以独立于应用进行管理、测试和版本控制。
OPA 的工作流程通常包含以下步骤:
- 接收查询:外部系统(如 API 网关、Kubernete API Server)向 OPA 发送一个查询请求,包含需要评估的上下文数据(如用户身份、请求资源、操作类型)。
- 加载策略:OPA 从本地文件系统、API 或配置管理服务加载用 Rego 语言编写的策略规则。
- 加载数据:OPA 可以加载外部数据(如角色列表、资源标签)作为策略评估的上下文。
- 执行评估:OPA 引擎将查询、策略和数据作为输入,执行规则逻辑,生成决策结果。
- 返回决策:OPA 将决策结果(通常是 JSON 格式)返回给调用方,调用方根据决策执行后续操作(如放行或拒绝请求)。
2.2 策略即代码(Policy as Code)
策略即代码是将传统上写在配置文件、硬编码逻辑或人工审批流程中的策略,转化为可编程、可版本控制、可测试的代码。OPA 通过 Rego 语言实现了这一理念,带来了以下关键优势:
| 维度 | 传统策略管理 | 策略即代码(OPA) |
|---|---|---|
| 可读性 | 分散在配置文件、硬编码逻辑中,难以理解 | 使用声明式 Rego 语言,接近自然语言,易于阅读 |
| 版本控制 | 通常无版本管理,变更难以追溯 | 策略文件可纳入 Git 等版本控制系统,支持回滚和审计 |
| 可测试性 | 依赖集成测试或手动验证 | 支持单元测试和模拟数据测试,确保策略正确性 |
| 复用性 | 策略与特定系统耦合,难以跨项目复用 | 策略与执行环境解耦,可被多个系统共享 |
| 自动化 | 策略变更通常需要人工审批和部署 | 策略变更可通过 CI/CD 管道自动测试和部署 |
实践建议:在日志平台组件拓扑权限设计中,将权限规则(如“只有运维人员可以读取审计日志”)编写为 Rego 策略,并存储在 Git 仓库中。每次策略变更都触发 CI 管道运行测试用例,确保不会意外扩大权限。
2.3 Rego 语言简介
Rego 是 OPA 专用的声明式查询语言,灵感来源于 Datalog。它专注于表达“如果……那么……”形式的规则,非常适合定义访问控制、合规性检查和数据过滤逻辑。Rego 的核心概念包括:
- 规则(Rules):定义策略决策的基本单元,格式为
rule_name := expression。 - 查询(Queries):向 OPA 引擎提出的问题,如
data.example.allow。 - 文档模型(Document Model):OPA 将输入、数据和策略输出都视为嵌套的 JSON 文档,Rego 规则通过点号访问这些文档的字段。
- 迭代(Iteration):Rego 使用
some关键字遍历集合,无需显式循环。 - 默认值(Default):使用
default关键字为规则设置默认值,避免未定义情况。
以下是一个简单的 Rego 策略示例,用于控制对日志组件的访问:
package logplatform.auth
# 默认拒绝所有请求
default allow := false
# 允许管理员执行任何操作
allow {
input.user.role == "admin"
}
# 允许运维人员读取日志,但不能删除
allow {
input.user.role == "operator"
input.operation == "read"
}
# 允许审计人员读取审计日志
allow {
input.user.role == "auditor"
input.operation == "read"
input.resource.type == "audit_log"
}
上述策略定义了三个规则:
- 第一条规则:如果用户角色是
admin,则允许所有操作。 - 第二条规则:如果用户角色是
operator且操作是read,则允许。 - 第三条规则:如果用户角色是
auditor、操作是read且资源类型是audit_log,则允许。
当 OPA 收到查询时,它会评估所有规则,并将结果合并。如果任何一条规则返回 true,则 allow 为 true;否则为 false。
常见误区:Rego 规则是声明式的,不是命令式的。不要试图在规则中编写循环或顺序逻辑。Rego 的求值引擎会自动处理规则之间的依赖关系和迭代。初学者常犯的错误是尝试使用
for 循环或 if-else 链,这在 Rego 中是不必要的。