4. 授权策略设计与集中管理
授权策略是权限系统的“法律条文”:它规定谁在什么条件下能对哪些资源执行什么操作。策略设计一旦失控,常见后果是权限蔓延、审计困难、变更风险高。本节围绕策略语言、策略存储、PDP/PEP 分离、集中式与分布式架构对比,以及策略版本管理与灰度发布展开,目标是让策略从“散落在代码里的 if-else”变成可管理、可审计、可回滚的工程资产。
策略语言:从自然语言到可判定表达式
策略语言的核心任务是把授权规则表达成机器可判定的形式。常见选择有三类:声明式策略语言(如 Rego、Cedar)、基于属性的表达式(如 ABAC 中的条件表达式)、以及关系模型(如 ReBAC 的关系图查询)。选择时重点看三点:表达力是否覆盖业务场景、是否可静态分析、是否有成熟的决策引擎与测试工具。
以 Rego 为例,一条“财务专员仅在工作日 9:00–18:00 可审批金额不超过 5 万元的报销单”的策略可以写成:
allow if {
input.user.role == "finance_specialist"
input.action == "approve"
input.resource.type == "expense_report"
input.resource.amount <= 50000
time.weekday(time.now_ns()) >= 1
time.weekday(time.now_ns()) <= 5
time.hour(time.now_ns()) >= 9
time.hour(time.now_ns()) < 18
}
这段策略的输入是 input(用户、动作、资源属性),输出是布尔决策。注意 amount <= 50000 是数值比较,time.weekday 返回 1–7,周一为 1。策略语言必须能明确表达“默认拒绝”:只有 allow 为真才放行,否则拒绝。这比“默认允许再逐条排除”安全得多。
策略存储:集中式仓库与版本化
策略不能只存在于某个服务的配置文件里。推荐做法是把策略集中存放在策略仓库中,通常是一个 Git 仓库或专用的策略存储服务。Git 仓库的好处是天然具备版本、分支、评审和回滚能力;专用存储服务则更适合高频更新和运行时查询。
策略存储需要解决三个问题:唯一事实源(所有 PDP 从同一处加载策略)、版本标识(每次发布有明确的版本号或 commit hash)、加载一致性(多个 PDP 实例加载到同一版本)。实践中常用“策略包 + 版本号”的方式:策略包是一个目录,包含若干 .rego 文件和测试文件,发布时打上语义化版本,例如 authz-policy@2.3.1。
PDP 与 PEP 分离:决策与执行的解耦
PDP(Policy Decision Point,策略决策点)负责根据策略和输入计算出“允许/拒绝”,PEP(Policy Enforcement Point,策略执行点)负责在真实请求路径上拦截并执行决策。两者分离的价值在于:策略变更不需要修改业务代码,PEP 只关心“问 PDP 要一个决策”,PDP 只关心“根据策略算一个决策”。
典型调用链是:客户端请求 → PEP 拦截 → 组装 input(用户、动作、资源、环境)→ 调用 PDP → PDP 返回 allow/deny 及原因 → PEP 放行或拒绝。PEP 通常以 SDK、Sidecar 或网关插件形式存在。PDP 可以是本地库(低延迟)或远程服务(集中管理)。
集中式与分布式授权架构对比
集中式架构下,所有 PDP 调用同一个远程决策服务,策略只存一份,变更立即生效,审计日志集中。缺点是决策服务成为关键路径,网络延迟和可用性风险集中。分布式架构下,每个服务或节点本地运行 PDP,策略包定期同步,决策延迟低,但版本一致性难保证,策略更新有传播延迟。
| 维度 | 集中式 | 分布式 |
|---|---|---|
| 决策延迟 | 含网络往返,通常 5–20ms | 本地计算,通常 <1ms |
| 策略一致性 | 强,单一事实源 | 最终一致,存在传播窗口 |
| 可用性风险 | 决策服务故障影响面大 | 单节点故障影响面小 |
| 变更生效速度 | 立即 | 取决于同步周期,秒级到分钟级 |
| 适用场景 | 策略频繁变更、强审计要求 | 高吞吐、低延迟、策略稳定 |
实际生产常采用混合模式:核心交易链路用本地 PDP 保证低延迟,管理后台和低频操作走集中式 PDP 保证一致性。无论哪种模式,策略版本号都必须随决策结果一起记录,否则故障排查时无法判断“当时用的是哪版策略”。
策略版本管理与灰度发布
策略变更的风险不亚于代码变更。推荐流程是:策略即代码——策略文件进 Git,走 Pull Request 评审,CI 中运行策略单元测试,合并后打版本标签。发布时先灰度:将新版本策略加载到一小部分 PDP 实例,观察决策差异和拒绝率变化,确认无误后再全量。
灰度发布的关键是可对比。可以在 PDP 中同时加载新旧两版策略,对同一请求分别计算,记录差异日志(shadow mode)。例如新策略将某接口的拒绝率从 0.3% 提升到 2.1%,就需要人工确认这 1.8% 的增量是预期收紧还是误伤。确认后再切换流量。
policy.rego、policy_test.rego 和 CHANGELOG.md。测试文件覆盖允许、拒绝、边界条件三类用例。版本号遵循语义化版本:主版本表示不兼容的决策语义变更,次版本表示新增规则,修订版本表示修复。
总结来看,授权策略设计的核心是把“谁能做什么”从散落的代码逻辑中抽离为可版本化、可测试、可灰度的策略资产。PDP/PEP 分离让决策与执行各司其职,集中式与分布式架构的选择取决于延迟、一致性和可用性的权衡,而版本管理与灰度发布则是策略变更安全落地的最后一道防线。