谷歌桑给巴尔简介
在本文中,我们将研究 Zanzibar,它是 Google 使用的全球授权系统,用于处理数百种服务和产品的授权,包括 YouTube、云端硬盘、日历、云和地图。
谷歌早在 2019 年就发布了 Zanzibar,并在短时间内迅速引起关注。事实上,Airbnb 和 Carta 等一些公司已开始将其原有的授权架构迁移到 Zanzibar 风格的系统。
除了大型科技公司的转变外,基于桑给巴尔的解决方案也随着时间的推移而增多。所有信息均已披露:Permify是一个基于桑给巴尔的授权系统。
在本文中,我们将探讨桑给巴尔与其他许可系统的不同之处,以及自该论文发表以来公司一直采用桑给巴尔风格的解决方案的原因。
阅读原文本身就很有趣,但我想简化一下桑给巴尔的论文,用简洁的语言解释一下为什么、是什么以及如何实现的。我喜欢从原因入手。所以,让我们来查一下为什么谷歌需要桑给巴尔。
为什么需要桑给巴尔?
正如我们所了解的,Google 使用 Zanzibar 来处理其产品的授权。但授权是什么?简单来说,它是控制谁可以在应用程序中执行、拥有或访问系统的过程。授权系统可以根据应用程序和用户的需求而分支。最终,随着业务的增长,由于各种原因,授权将成为一个难以解决的问题。
我们写了一篇文章,从三个核心方面阐述了授权为何如此困难:建模、架构和执行。
建模的问题在于,大多数情况下,它一开始很简单,但随着时间的推移,由于用户需求的增长和永无止境的需求,会变得越来越丑陋。尤其是,对于不断变化的环境,以及单个应用程序的多种不同用例,创建权限非常困难。
就谷歌而言,他们拥有大量需要不同权限的应用程序和服务;例如,Drive 有自己的共享授权,Youtube 有私有/公共视频访问控制,谷歌云主要依赖于基于角色的访问控制 (RBAC) 等。因此,谷歌需要一个灵活的建模结构,以便在一个公共的地方创建和扩展不同访问控制方法的组合。
关于执行,这很有挑战性,因为它发生在如此多的地方。访问检查通常包含来自不同服务或应用程序的数据。因此,快速可靠的决策变得越来越困难。
在 Google 中,不同应用之间的资源访问检查非常常见。例如,Google 日历可能拥有 Google Meets 的正确授权。因此,对于 Google 而言,拥有一个统一的授权系统至关重要,这样可以使应用更容易地进行互操作。
这种插值实际上从执行层面深入到架构问题。处理授权的常见架构方法是为每个与数据库直接连接的应用程序构建一个权限系统。由于授权是系统的关键部分,并且是单点故障,授权系统上的一个错误或仅仅是一个简单的失误都可能导致安全欺诈,向用户显示误报或漏报结果。
此外,当你拥有多个应用程序时,维护多个授权机制会变得更加困难。因此,这些系统通常被设计为抽象实体、库或集中式引擎,以满足许多单独的应用程序和服务的需求。
谷歌在构建 Zanzibar 之前也采用了这种方法。他们有一个通用的授权库,可在其应用程序和服务中使用,作为集中式权限引擎。
“一个权限系统统领一切!”这句口号很棒,但将权限系统从应用程序中抽象出来却有一个很大的弊端。这些库或权限引擎不存储数据。它们只是充当一个引擎来管理诸如执行访问检查之类的功能。而这些功能本身就存在利弊。
例如,为了进行访问检查并计算决策,您需要从数据库和其他服务加载授权数据和关系。在这种情况下,性能和可扩展性方面存在巨大的缺陷。
鉴于谷歌需要计算来自全球不同环境和应用程序的数十亿条访问检查,加载和处理授权数据尤为困难。考虑到这一点,这些检查必须快速、一致且始终可用。因此,在谷歌规模的范围内,缺乏数据管理的统一授权系统很容易出错。
Google 需要一个超级快速、安全且可扩展的解决方案,同时还要确保所有应用程序的一致性和可靠性。实际上,让我们通过论文中的引述来了解 Zanzibar 系统的主要目标:
正确性:必须确保访问控制决策的一致性以尊重用户意图。
灵活性:它必须支持消费者和企业应用程序所需的丰富的访问控制策略。
低延迟:它必须快速响应,因为授权检查通常处于用户交互的关键路径上。低延迟对于提供搜索结果尤为重要,因为搜索结果通常需要数十到数百次检查。
高可用性:它必须可靠地响应请求,因为如果没有明确的授权,客户端服务将被迫拒绝其用户访问。
规模庞大:它需要保护数十亿用户共享的数十亿个对象。它必须部署在全球各地,靠近其客户及其最终用户。
我们将探讨桑给巴尔是如何实现这些目标的。首先,让我们先了解一下桑给巴尔是什么。
桑给巴尔是什么?
Zanzibar 是一种授权服务,它将权限存储为 ACL 样式的关系,并根据这些关系执行访问决策。Zanzibar 统一授权,以服务于各个应用程序和服务。
如上所述,统一授权系统具有诸多优势。但是,将授权从核心应用程序中抽象出来面临着一个巨大的挑战:数据管理。毫不奇怪,Zanzibar 对此有一套独特的解决方案。
数据模型
抽象授权数据可以消除每次执行操作时的数据加载问题。想象一下一个简单的访问控制问题:“用户 X 可以查看文档 Y 吗?” 传统上,我们必须检查策略或访问规则,然后加载决策所需的数据。而在 Zanzibar,您已经将所有必需信息存储为关系元组,以便快速做出决策。
使用 Zanzibar 时,您需要告知 Zanzibar 与授权数据相关的活动。假设我们有一条规则强制执行“只有文档创建者才能查看文档”。听起来合理吗?在这种情况下,您需要向 Zanzibar 提供系统中与文档创建相关的操作。例如“用户 X 创建了文档 Y”、“用户 Z 创建了文档 T”等等。然后,Zanzibar 会将这些信息作为关系元组存储在集中式数据源中。
Airbnb 的一位软件工程师 Alon Yao 写了一篇文章,介绍了 Airbnb 如何将其原有的授权系统迁移到名为 Himenji 的类似桑给巴尔风格的系统。以下是他们处理授权数据同步的方法。
我们创建了 Himeji,一个基于 Zanzibar 的中心化授权系统,该系统从数据层调用。它存储权限数据,并作为中心化数据来源执行检查。我们不是在读取时进行扇出,而是在资源发生变更时写入所有权限数据。考虑到我们的读取负载较高,我们在写入时进行扇出,而不是读取时。
关系元组类似于对象用户或对象对象关系的单个 ACL 集合,其形式为“用户 U 与对象 O 之间存在关系 R”。Zanzibar 将这些关系元组的形式表示为:
⟨tuple⟩ ::= ⟨object⟩'#'⟨relation⟩'@'⟨user⟩
⟨对象⟩ ::= ⟨命名空间⟩':'⟨对象 ID⟩
⟨用户⟩ ::= ⟨用户 ID⟩ | ⟨用户集⟩
⟨用户集⟩ ::= ⟨对象⟩'#'⟨关系⟩
虽然乍一看很复杂,但实际上相当简单。让我们解构一个元组“object#relation@user”
在我们的文档示例中,当用户 1 创建文档 2 时,您需要发送对象和主题关系。如果 Zanzibar 系统是一个人,您会说:“嘿,Zanzibar 用户 1 是文档 2 的所有者”。然后,此数据存储为 document:2#owner@user:1
用户也可以像团队成员一样是用户集。这允许在访问决策中使用嵌套的组关系。例如,假设我们想在一个系统中将成员与文档的查看者关系分组,则可以根据以下方式创建关系元组:
doc:1#viewer@group:2#member。
因此,桑给巴尔衍生系统统一并将关系元组的集合存储为授权数据。
访问控制检查
考虑到像谷歌这样的大规模系统,正如你所预料的那样,会创建大量的关系元组。目前,Zanzibar 管理着数万亿个元组,其中包含数千个命名空间。因此,所有这些关系元组和授权模型组合起来,构建了一个关系图,主要用于访问控制检查。
在 Zanzibar,评估访问决策的过程就像对这张有向图的遍历一样。例如,如果我们问“用户 1 是否是文档 1 的所有者?”,如果用户 1 和文档 1 之间的所有者关系在有向图上可以访问,Zanzibar 就会得出结论:用户 1 已获得授权。
这种关系该如何存储并呈现在图中呢?简单来说,当用户 1 创建文档 1 时,应用程序客户端应该将数据发送给 writeAPI。我们将在下面查找 write 函数。
功能
Zanzibar 有五个核心方法,分别是:读取、写入、监视、检查和扩展。扩展和检查是与授权相关的函数。其他函数则与授权数据和关系元组更相关。
如果我们需要对每种方法进行快速解释;
读取(2.4.1),允许直接查询图形数据,它可以用来过滤授权数据、存储的关系元组。
写入 (2.4.2)基本上允许您将关系元组写入数据存储。在基于标准关系数据库并实现了 Zanzibar 系统的应用程序中,关系元组可以在同一流程中同时写入应用程序的数据库和 Zanzibar 系统。
观察(2.4.3),我们可以从它的名字中了解其功能,它用于观察图形数据中关系元组的变化。
检查 (2.4.4)可能是最明显的一种。检查用于强制执行。在基于桑给巴尔的系统中,您可以以“主体 S 是否拥有资源 R 的权限 P”的形式检查访问权限。需要指定主体和资源。检查引擎将通过遍历关系图来计算决策。
扩展(2.4.5),用于提高访问权限的可观察性和合理性。它以给定资源权限的树状结构返回桑给巴尔的用户集,该集合的形式为。
数据一致性
Zanzibar 是一项持续访问并经过数百万次访问检查的服务,因此必须确保其安全性。对于这种主动管理数据的系统而言,安全性主要与存储和管理数据的一致性相关。
这些不一致的数据可能会导致授权检查出现误报或误报结果。因此,如果发生某些架构更新或关系变更,所有使用 Zanzibar 的应用程序都应根据更新结果更新其缓存,以防止出现误报或误报结果。
Zanzibar 通过快照读取的方法避免了这个问题。本质上,它确保在一致的时间点对执行情况进行评估,从而避免出现不一致的情况。Zanzibar 团队开发了名为 Zookies 的令牌,它包含一个时间戳,用于在访问检查中进行比较,以确保执行情况的快照至少与资源版本的时间戳一样新鲜。
提供大规模低延迟
Zanzibar 存储着超过两万亿条 ACL,每秒执行数百万次授权检查。虽然这些数字巨大,但考虑到 YouTube、云端硬盘、日历等 Google 产品都使用 Zanzibar,这在意料之中。由于使用 Zanzibar 的产品是分布式的,因此任何对象的授权执行都可能来自世界任何地方。因此,Zanzibar 不会在不同地理位置传播 ACL 数据。
因此,Zanzibar 将所有 ACL 数据复制到数十个地理分布的数据中心,并将负载分散到全球数千台服务器上。更具体地说,论文中有一节名为“经验”(参见 2.4.1),其中提到 Zanzibar “使用 Spanner 将负载分散到全球数十个集群中超过 10,000 台服务器上。Spanner 是 Google 的可扩展、多版本、全球分布且同步复制的数据库。”
毫无疑问,Zanzibar 运用了各种技术来实现这种全球分布式环境中的低延迟和高可用性目标。它有一个有效的缓存机制,可以从本地复制的数据中获取结果。更多关于缓存的信息,请参阅论文:
它通过缓存最终结果和中间结果,以及对同时发生的请求进行重复数据删除,来处理规范化数据上的热点问题。此外,它还应用了诸如对冲请求和优化深度嵌套集合计算等技术,并限制了非规范化操作。
结果如何?超过 95% 的访问检查在 10 毫秒内做出响应,并且在 3 年内保持了超过 99.999% 的可用性。
结论
Google 的 Zanzibar 的主要目标是创建一个快速、安全且始终可用的全球级权限系统。作为基于 Zanzibar 的开源授权服务Permify ,我们致力于让每个人都能在自己的应用和服务中使用 Zanzibar 并从中受益。
鏂囩珷鏉ユ簮锛�https://dev.to/egeaytin/why-google-build-zanzibar--3kp5