2. 核心概念:策略、规则、数据、输入、输出——OPA的五大核心要素详解
Open Policy Agent (OPA) 的核心是一个通用的策略引擎,它将策略决策与策略执行解耦。要深入理解 OPA 的工作机制,必须掌握其五大核心要素:策略 (Policies)、规则 (Rules)、数据 (Data)、输入 (Input) 和 输出 (Output)。这五个要素构成了 OPA 策略评估的完整闭环。
核心理解:OPA 的本质是一个“策略计算器”。它接收 输入(来自外部的请求)和 数据(预加载的上下文信息),依据 策略(由 规则 构成)进行逻辑运算,最终产生一个 输出(决策结果)。
2.1 五大要素关系总览
下图展示了 OPA 核心要素之间的数据流与依赖关系。策略引擎是中心枢纽,输入和数据是原材料,策略是计算逻辑,输出是最终产品。
2.2 要素详解与对比
每个要素在 OPA 生态中扮演着独特的角色。下表从定义、来源、格式和示例四个维度进行对比,帮助快速建立认知。
| 要素 | 定义 | 来源 / 加载方式 | 数据格式 | 典型示例 |
|---|---|---|---|---|
| 策略 (Policies) | 用 Rego 语言编写的规则集合,定义了决策逻辑 | 通过 OPA API 或文件系统加载,通常存储在 .rego 文件中 | Rego 源代码 | allow { input.role == "admin" } |
| 规则 (Rules) | 策略中的基本逻辑单元,由条件和表达式组成 | 内嵌在策略文件中,是策略的组成部分 | Rego 表达式 | deny[msg] { ... } |
| 数据 (Data) | 预加载到 OPA 中的结构化信息,作为策略评估的上下文 | 通过 API 推送、文件加载或服务发现注入 | JSON / YAML | {"users": {"alice": {"role": "admin"}}} |
| 输入 (Input) | 每次策略查询时传入的请求参数,代表待评估的即时事件 | 由调用方在查询 OPA 时通过 API 请求体传入 | JSON | {"user": "alice", "action": "delete"} |
| 输出 (Output) | 策略引擎根据输入、数据和策略计算得出的决策结果 | OPA 引擎自动生成,返回给调用方 | JSON (布尔值、对象或数组) | {"allow": true, "deny": []} |
2.3 要素深度解析
2.3.1 策略 (Policies) 与 规则 (Rules)
策略是 OPA 的“大脑”,而规则是构成大脑的“神经元”。策略文件(.rego)包含多条规则,每条规则定义了一个具体的决策逻辑片段。
- 策略文件:通常以
package关键字开头,用于组织和管理规则。例如package kubernetes.admission。 - 规则类型:
- 完整规则 (Complete Rules):返回一个布尔值或单个值。例如
allow := true。 - 部分规则 (Partial Rules):返回一个集合或对象。例如
deny[msg] { ... }生成一个拒绝消息列表。
- 完整规则 (Complete Rules):返回一个布尔值或单个值。例如
- 默认值:使用
default关键字为规则设置默认值,避免未定义导致的意外行为。
# 示例策略文件:example.rego
package system
# 默认拒绝所有请求
default allow = false
# 完整规则:如果用户是管理员,则允许
allow {
input.role == "admin"
}
# 部分规则:生成拒绝消息
deny[msg] {
not input.role == "admin"
msg = sprintf("用户 %v 没有管理员权限", [input.user])
}
2.3.2 数据 (Data) 与 输入 (Input)
数据和输入是策略评估的“燃料”。理解它们的区别至关重要:数据是静态的上下文,输入是动态的请求。
关键区别:
- 数据 (Data):生命周期长,由运维人员或系统预先加载。例如:集群节点列表、用户角色映射、全局配置参数。在 Rego 中通过
data变量访问。 - 输入 (Input):生命周期短,每次策略查询时临时传入。例如:当前请求的 HTTP 方法、请求体内容、用户身份令牌。在 Rego 中通过
input变量访问。
以下示例展示了如何在策略中同时使用数据和输入:
# 假设数据中已加载了用户角色信息
# data = {"users": {"alice": {"role": "admin"}, "bob": {"role": "viewer"}}}
# 策略规则:检查输入中的用户是否在数据中拥有特定角色
allow {
# 从数据中查找用户角色
role := data.users[input.user].role
# 检查角色是否满足条件
role == "admin"
}
2.3.3 输出 (Output)
输出是 OPA 策略评估的最终结果。它通常是一个 JSON 对象,包含决策结果和相关信息。在准入控制场景中,输出决定了请求是被允许还是拒绝。
- 标准输出结构:OPA 默认返回所有规则的值。例如,如果策略中有
allow和deny规则,输出将包含这两个字段。 - 自定义输出:可以通过 Rego 的
object或自定义规则来构造更复杂的输出结构,包含详细的拒绝原因、警告信息或审计日志。
# 策略输出示例
{
"allow": false,
"deny": [
"用户 bob 没有管理员权限",
"请求的命名空间 'production' 不在允许列表中"
],
"warnings": [
"用户 bob 的令牌将在 5 分钟后过期"
]
}
2.4 要素协同工作流程
为了更直观地展示五大要素如何协同工作,下图以 Kubernetes 准入控制为例,展示了从请求发起、策略评估到决策返回的完整流程。
2.5 最佳实践与避坑指南
常见误区:
- 混淆 Data 与 Input:将频繁变化的请求参数作为 Data 加载,或将长期有效的配置作为 Input 传入。正确做法:静态配置用 Data,动态请求用 Input。
- 规则未定义默认值:当规则不满足任何条件时,OPA 返回
undefined,可能导致意外行为。始终使用default关键字设置安全默认值。 - 忽略输出结构:在准入控制场景中,Kubernetes API Server 期望特定的输出格式。确保策略输出包含
allow和deny字段。
设计建议:
- 分层组织策略:将通用规则(如认证)与业务规则(如资源配额)放在不同的 package 中,便于维护和复用。
- 利用 Data 缓存:对于频繁查询的配置(如黑名单),通过 OPA 的 Data API 预加载,避免每次请求都查询外部数据源。
- 输出结构化:设计包含
allowed、denied、warnings和audit字段的输出,方便调用方进行后续处理。