2. OPA 基础:核心概念、Rego 语言入门与策略模型
Open Policy Agent (OPA) 是一个开源的、通用策略引擎,它将策略从软件的业务逻辑中解耦出来。OPA 提供了一种统一的、声明式的语言——Rego,用于定义策略,并通过 REST API 或 Golang 库等方式被应用程序调用。理解 OPA 的核心概念、Rego 语法以及策略模型,是后续与 Loki 协同实现安全权限与查询优化的前提。
2.1 OPA 核心概念
OPA 的策略决策过程围绕几个关键概念展开,理解这些概念是掌握 OPA 的基础。
| 概念 | 说明 | 类比 |
|---|---|---|
| Policy (策略) | 用 Rego 语言编写的规则集合,定义了“允许”或“拒绝”的逻辑。 | 法律条文 |
| Data (数据) | OPA 加载的 JSON 文档,作为策略决策的上下文。可以是静态文件或外部数据源。 | 案件事实 |
| Input (输入) | 每次策略查询时,由调用方提供的 JSON 文档,代表需要被评估的请求。 | 当前案件 |
| Decision (决策) | OPA 根据策略、数据和输入计算出的结果,通常是一个 JSON 对象(如 {"allow": true})。 |
法官判决 |
| Query (查询) | 向 OPA 发起的请求,包含 Input,期望返回 Decision。 | 提起诉讼 |
关键理解: OPA 本身不存储业务数据,它只负责基于 Data 和 Input 执行 Policy 并返回 Decision。这种分离使得策略可以独立于应用进行管理和更新。
2.2 Rego 语言入门
Rego 是 OPA 的专用查询语言,它受 Datalog 启发,是一种声明式语言。这意味着你只需要描述“想要什么”,而不是“如何做”。
2.2.1 基本语法
- 规则 (Rules):策略的基本单元,格式为
rule_name := expression。 - 文档 (Documents):Rego 中的变量和规则结果都被视为文档,可以是标量、对象、数组等。
- 迭代 (Iteration):使用
some关键字或隐式迭代来遍历集合。 - 默认值 (Default):使用
default关键字为规则设置默认值,避免未定义错误。
# 一个简单的 Rego 规则
package example.authz
# 默认拒绝
default allow = false
# 允许管理员访问
allow {
input.role == "admin"
}
# 允许拥有特定资源的用户访问
allow {
input.role == "user"
input.resource == data.allowed_resources[_]
}
2.2.2 常用内置函数
| 函数 | 用途 | 示例 |
|---|---|---|
io.jwt.decode |
解码 JWT | io.jwt.decode(input.) |
glob.match |
Glob 模式匹配 | glob.match("*.log", [], input.file) |
regex.match |
正则表达式匹配 | regex.match("^/api/v[0-9]+", input.path) |
object.get |
安全地获取对象属性 | object.get(input, ["user", "name"], "unknown") |
time.now_ns |
获取当前时间戳(纳秒) | time.now_ns() |
2.3 策略模型
OPA 的策略模型通常遵循“分层”或“模块化”的设计思想,以提高可维护性和复用性。一个典型的策略模型包含以下层次:
- 基础层 (Base Layer):定义全局默认规则,如“默认拒绝”。
- 业务层 (Business Layer):实现具体的业务逻辑,如“只有管理员可以删除用户”。
- 数据层 (Data Layer):引用外部数据源,如“用户角色列表”或“资源访问白名单”。
最佳实践: 将策略按 Package 进行组织,每个 Package 对应一个独立的策略模块。例如,
package app.rbac 负责基于角色的访问控制,package app.audit 负责审计日志策略。
2.4 策略与数据分离
OPA 的一个核心优势是策略与数据的完全分离。策略代码(Rego)通常存储在版本控制系统中,而数据(如用户列表、权限矩阵)可以来自多种数据源:
- 静态文件:通过 OPA 的
--data参数加载 JSON 或 YAML 文件。 - 外部 API:通过
opa exec或opa run的--bundle模式拉取远程数据。 - 数据库:通过自定义的 Sidecar 或 Adapter 将数据库查询结果同步到 OPA 的 Data 文档中。
- Loki:在后续章节中,我们将探讨如何将 Loki 的日志查询结果作为 OPA 的 Data 源,实现基于日志的实时权限校验。
注意: 虽然 OPA 可以加载大量数据,但应避免将整个数据库导入 OPA。最佳实践是只加载与策略决策直接相关的数据子集,并利用 OPA 的 Bundle 功能进行增量更新。