土法炼钢兴趣小组的算法知识备份

【身份与访问控制工程】Zanzibar 风格权限系统:Google 的全球授权引擎

文章导航

分类入口
architecturesecurity
标签入口
#zanzibar#authorization#google#relation-based#spicedb#auth0-fga#consistency#zookie#rebac

目录

很少有技术论文像 Zanzibar: Google’s Consistent, Global Authorization System(Pang et al., USENIX ATC 2019)这样,在开源社区产生如此直接和广泛的影响——Auth0 OpenFGA、SpiceDB(AuthZed)、Permify、Ory Keto 等新一代授权系统全部以 Zanzibar 为蓝本。

但论文的 10 页正文留给实现者很多空白。本文聚焦于 Zanzibar 的核心设计决策和工程实现中的关键取舍。

一、关系元组(Relation Tuple):Zanzibar 的原子数据

Zanzibar 的数据模型只有一个核心概念:关系元组。它的语法是:

⟨namespace:object_id #relation user⟩

例如:

⟨doc:readme.txt #viewer user:zhangsan⟩       — zhangsan 是 readme.txt 的 viewer
⟨doc:readme.txt #owner group:eng-leads⟩       — eng-leads 组的成员是 readme.txt 的 owner
⟨group:eng-leads #member user:lisi⟩           — lisi 是 eng-leads 组的 member

Zanzibar 的查询就是:给定这些关系元组和 namespace 的配置,判断 ⟨user, relation, object⟩ 是否成立。

这个模型的简洁性是它的核心力量——不需要维护 RBAC 的角色表,不需要维护 ABAC 的属性表达式。所有权限都表示为图上的三元组。

二、Namespace Config:图上的路径规则

光有元组不够。user:zhangsandoc:readme.txtviewer,但系统怎么知道”owner 也是 viewer”、“在 eng-leads 组的成员也是文档的 owner”?这就是 Namespace Config(命名空间配置)的作用。

name: doc
relations:
  viewer:
    union:
      this: {}                         # 直接 viewer
      computed_userset:
        relation: editor               # editor 也是 viewer
      tuple_to_userset:                # doc 的 owner 是 group → group 的 member 也是 viewer
        tupleset:
          relation: owner
          computed_userset:
            relation: member
      tuple_to_userset:                # doc 的 folder → folder 的 viewer 也是 doc 的 viewer
        tupleset:
          relation: parent_folder
          computed_userset:
            relation: viewer
  editor:
    union:
      this: {}
      computed_userset:
        relation: owner                # owner 也是 editor
  owner:
    this: {}
  parent_folder:
    this: {}

Namespace Config 相当于定义了一个小型的”关系代数解释器”——它描述了每种关系的推导规则:

给定元组集合和 namespace config,Zanzibar 对每个 Check 请求做图搜索——从用户节点出发,沿元组和 config 定义的边探索,直到找到到达目标对象+关系的路径,或者穷尽所有路径。

三、Consistency Model:Zookie 的真正含义

Zanzibar 论文最被引用的一句话是”支持全局一致性和低延迟”。但这里的”一致性”是一个精细的定义,不是”每次读取都是最新数据”这种强一致性。

3.1 Zookie:不透明一致性令牌

Zanzibar 在每个写操作后返回一个称为 Zookie 的不透明令牌(类似于 Spanner 的 TrueTime timestamp 的编码)。后续的 Check 请求可以附带这个 Zookie,Zanzibar 保证 Check 看到的数据不早于 Zookie 对应的时间点。这称为”Read-at-least-as-recent-as”一致性。

写:   ACL change ⟨doc:x #viewer user:A⟩ → remove
返回: Zookie_123 (编码了写操作的时间戳)

读:   Check ⟨user:A, viewer, doc:x⟩ with Zookie_123
保证: 返回 "denied"(必定反映 remove 操作之后的状态)

不附带 Zookie 的 Check 请求可能看到稍微过时的缓存数据。论文中提到 Zanzibar 在保持全局一致性(附带 Zookie)时 p99 延迟 < 100ms,在优先延迟时(不附带 Zookie)p99 < 10ms。

3.2 为什么要有 Zookie

不附带 Zookie 的 Check 会出现”幽灵权限”问题——用户刚刚被你移除了文档的访问权限,但 Check 仍返回 true,因为它命中了一个还没失效的缓存。反过来也会出现——用户刚被加为 viewer,但 Check 返回 false。

但实际上大多数 Check 请求不需要 Zookie。Google Photos 的用户在分享相册后,被分享者可能过了一两秒才看到——这是可接受的。需要 Zookie 的场景是那些”写后必须生效”的——如权限变更后用户重试操作,期望立即反映变更。

工程含义:如果你的应用场景容许 1-3 秒的权限变更延迟(绝大多数 SaaS 场景),你可以使用无 Zookie 的 Check,享受更好的性能和更低的延迟。Zookie 的一致性成本对大多数业务是不必要的。

四、开源的 Zanzibar 实现对比

系统 语言 存储后端 一致性模型 成熟度
SpiceDB Go CockroachDB / PostgreSQL / MySQL / Spanner Zookie 等效(ZedToken) CNCF Sandbox,AuthZed 商业支持
OpenFGA Go PostgreSQL / MySQL 无 Zookie(最终一致性) CNCF Sandbox,Auth0/Okta 支持
Permify Go PostgreSQL 无 Zookie 较新,Schema DSL 更简洁
Ory Keto Go PostgreSQL / MySQL 无 Zookie Ory 生态的一部分

选型参考: - 需要严格一致性 → SpiceDB(唯一提供 Zookie 等效机制的开源实现)。 - 需要最大生态支持 → OpenFGA(Okta 旗下,DSL 与 Zanzibar 论文最接近,有官方 SDK 支持 10+ 语言)。 - 已经在用 Ory Hydra/Kratos → Ory Keto(统一生态)。 - 偏好更简洁的 DSL → Permify(Schema 语法比 Zanzibar 的 namespace config 更接近自然语言)。

五、自己实现 Zanzibar 时要面对的工程问题

5.1 图遍历的性能

Zanzibar 的核心操作是图搜索——从用户节点出发,按 namespace config 定义的规则探索路径。问题在于:路径深度可能不可控。

一个 namespace config 包含 tuple_to_userset 的链条:user → group1 → group2 → group3 → ...。无限的成员组嵌套会导致路径搜索发散。Zanzibar 论文中提到了”config-driven depth limits”——每个 namespace 可以指定最大搜索深度。在生产实现中,这个限制的默认值通常设为 50-100。

5.2 Subject Set 展开

group:eng-leads #member 是一个 subject set(主体集合)——包含所有满足 ⟨group:eng-leads #member *⟩ 的主体。当查询 user:zhangsan 是不是 doc:readme.txtviewer,而 viewer 包含 group:eng-leads 的 member,Zanzibar 需要检查 user:zhangsan 是否属于 group:eng-leadsmember。这是一个递归展开。

大的 group(几万到几十万成员)在展开时需要高效的数据结构。Zanzibar 使用”跨越边”索引技术(Leapfrog Triejoin,用于 Spanner 的查询引擎),但开源实现大多采用更简单的方案——B-Tree 索引 + 递归查询。

5.3 Wildcard 权限

Zanzibar 支持 user:*(所有用户都是 viewer)。这对公开文档很有用,但在图搜索中引入了一个全局集合——无论什么用户,都命中这个条件。实现的工程处理是短路求值:如果发现了 user:* 的匹配规则且用户无排除规则,直接返回 true


上一篇RBAC、ABAC、ReBAC:权限模型怎么选 下一篇OPA、Cedar 与策略引擎落地

同主题继续阅读

把当前热点继续串成多页阅读,而不是停在单篇消费。

2026-06-13 · architecture / security

【身份与访问控制工程】IAM 全景:为什么这是高价值赛道

从 2020 年 SolarWinds 到 2024 年 Okta 支持系统泄露,身份基础设施的安全失败反复证明一件事:IAM 不是 IT 支撑系统,而是安全架构的承重墙。本文建立现代 IAM 的全景地图——从认证协议、令牌体系、权限模型到身份治理与平台选型,给出 5 个贯穿全系列的核心问题。

2026-06-17 · architecture / security

【身份与访问控制工程】RBAC、ABAC、ReBAC:权限模型怎么选

RBAC 简单但会角色爆炸,ABAC 灵活但策略管理失控时更可怕,ReBAC 表达力强但引入了图遍历的性能约束。三种模型不是'选一个升级另一个'的线性关系,而是在表达能力、管理成本和性能三者之间做工程权衡。本文从每种模型的本质数据结构出发,拆解选型框架。

2026-06-18 · architecture / security

【身份与访问控制工程】OPA、Cedar 与策略引擎落地

OPA 是 CNCF 的策略引擎标准答案,Rego 是它的策略语言;Cedar 是 AWS 开源的新竞争者,基于 Rust 的 WASM 编译执行、语法更接近 SQL。两者在架构模式(sidecar vs 中心化)、策略语言设计哲学和性能特征上有根本差异。本文从策略引擎的架构模式出发,拆解 OPA Rego 的核心语义与性能限制、Cedar 的设计取舍,以及策略即代码(Policy as Code)在 CI/CD 中的落地。

2026-06-19 · architecture / security

【身份与访问控制工程】B2B SaaS 多租户权限设计

多租户权限系统是 IAM 中工程复杂度最高的场景之一——每个租户想要自己的角色、自己的组织树、自己的审批流和完全隔离的数据。这四种需求会互相冲突。本文从租户隔离模型出发,拆解四层权限架构、租户级 RBAC 的扩展方案、组织树与数据权限的联动,以及跨租户授权(如第三方服务商访问客户数据)的架构设计。


By .