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 的策略模型通常遵循“分层”或“模块化”的设计思想,以提高可维护性和复用性。一个典型的策略模型包含以下层次:

  1. 基础层 (Base Layer):定义全局默认规则,如“默认拒绝”。
  2. 业务层 (Business Layer):实现具体的业务逻辑,如“只有管理员可以删除用户”。
  3. 数据层 (Data Layer):引用外部数据源,如“用户角色列表”或“资源访问白名单”。
最佳实践: 将策略按 Package 进行组织,每个 Package 对应一个独立的策略模块。例如,package app.rbac 负责基于角色的访问控制,package app.audit 负责审计日志策略。
OPA 策略决策流程 OPA 策略决策流程 Input (请求) Data (数据) Policy (策略) Decision (决策) OPA 引擎将 Input 和 Data 作为输入,执行 Policy 规则,最终输出 Decision。

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 功能进行增量更新。
策略与数据分离架构 策略与数据分离架构 策略仓库 (Git) Rego 代码 数据源 JSON / API / DB OPA 引擎 策略 + 数据 应用 查询决策 策略与数据独立管理,通过 OPA 引擎融合,为应用提供统一的决策服务。