天天看点

SpiceDB 上的 ABAC:启用 Netflix 的复杂身份类型(译文: Netflix)

作者:闪念基因
SpiceDB 上的 ABAC:启用 Netflix 的复杂身份类型(译文: Netflix)

介绍

Netflix 的授权团队最近发起了一项工作,将基于属性的访问控制 (ABAC) 支持添加到 AuthZed 的开源 Google Zanzibar授权系统SpiceDB中。Netflix 需要 SpiceDB 中的属性支持以支持核心 Netflix 应用程序身份构造。这篇文章讨论了为什么 Netflix 希望在 SpiceDB 中支持 ABAC,Netflix 如何与 AuthZed 合作,最终结果——SpiceDB 注意事项,以及 Netflix 如何利用这一新功能。

Netflix 一直在寻求安全性、人体工程学或效率方面的改进,这扩展到了授权工具。Google Zanzibar令 Netflix 兴奋不已,因为它可以更轻松地为委托人可以访问的资源生成授权决策对象和反向索引。

去年,在试验 Zanzibar 授权方法时,Netflix 发现了 SpiceDB,这是开源的 Google Zanzibar 启发的权限系统,并构建了一个原型来试验建模。该原型揭示了在 SpiceDB 中实现基于属性的访问控制所需的权衡,这使得它不太适合 Netflix 对应用程序身份的核心要求。

为什么 Netflix 想要警告关系?

Netflix 应用程序身份基本上是基于属性的:例如,数据处理器的一个实例在带有公共分片的测试环境中的 eu-west-1 中运行。

授权这些身份不仅通过应用程序名称完成,而且通过指定要匹配的特定属性来完成。应用程序所有者可能想要制定类似“欧盟数据处理组的应用程序成员可以访问 PI 解密密钥”的策略。这是 SpiceDB 中的一种正常关系。但是,出于合规性原因,他们可能还想指定一项政策,只允许从敏感分片内在欧盟运行的数据处理器实例访问 PI 密钥。EU-data-processors 换句话说,如果除了应用程序名称之外,某些身份属性(如 region==eu)匹配,则身份只应被视为具有“是组成员”。这是一个 Caveated SpiceDB 关系。

注意事项之前的 Netflix 建模挑战

SpiceDB 作为一个基于关系的访问控制 (ReBAC) 系统,期望针对对象之间特定关系的存在执行授权检查。用户符合这种模式——他们有一个单一的用户 ID 来描述他们是谁。如上所述,Netflix 应用程序不适合这种模型。它们的属性用于在不同程度上限定权限范围。

Netflix 在尝试将其现有政策模型融入关系时遇到了重大困难。为此,Netflix 的设计需要:

  • 一种基于事件的机制,可以获取有关应用程序自动缩放组的信息。自动缩放组不是最低级别的粒度,但它相对接近我们通常看到应用授权策略的最低级别。
  • 获取描述自动缩放组的属性并将它们写为单独的关系。那就是对于数据处理器,Netflix 需要编写描述区域、环境、帐户、应用程序名称等的关系。
  • 在 authZ 检查时,提供要检查的身份的属性,例如“us-west-2 中的应用程序栏能否访问此文档”。然后 SpiceDB 负责确定哪些关系映射回自动缩放组,例如名称、环境、区域等。
  • 从数据库中删除陈旧关系的清理过程。

这个设计有什么问题?除了复杂之外,还有一些具体的事情让 Netflix 感到不舒服。最突出的是它不能适应关系数据的缺失,例如,如果一个新的自动缩放组开始并向 SpiceDB 报告它的存在尚未发生,自动缩放组成员将缺少运行所需的权限。所有这一切都意味着 Netflix 将不得不编写和修剪具有显着新鲜度要求的关系状态。这将与其现有的基于政策的系统大相径庭。

在解决这个问题时,Netflix 跳进 SpiceDB Discord 讨论可能的解决方案,并发现了一个开放的社区问题:caveated relationships proposal。

SpiceDB 警告的开始

SpiceDB 社区已经探索过将 SpiceDB 与 Open Policy Agent (OPA) 集成,并得出结论认为它与 Zanzibar 的全球水平可扩展性和强一致性的核心承诺相去甚远。在 Netflix 的支持下,AuthZed 团队考虑了一种基于属性的访问控制的桑给巴尔本地方法。

这些要求被捕获并作为警告关系提案发布在 GitHub 上,以征求 SpiceDB 社区的反馈。通过SpiceDB Discord 服务器上的评论、反应和对话,社区的兴奋和兴趣变得显而易见。显然,在将 SpiceDB 与基于策略的方法相协调时,Netflix 并不是唯一面临挑战的公司,因此 Netflix 决定提供帮助!通过赞助该项目,Netflix 能够帮助 AuthZed 确定工程工作的优先级,并加速将 Caveats 添加到 SpiceDB。

构建 SpiceDB 的注意事项

SpiceDB 快速介绍

SpiceDB模式语言为如何构建、遍历和解释 SpiceDB 的关系图制定授权决策制定了规则。SpiceDB 关系,例如document:readme writer user:emilia,被存储为表示数据存储区(如 CockroachDB 或 PostgreSQL)中的图形的关系。SpiceDB 遍历图形并将其分解为子问题。这些子问题通过一致性哈希分配,并分派到运行 SpiceDB 的集群中的一个节点。随着时间的推移,每个节点缓存子问题的一个子集以支持分布式缓存,减少数据存储负载,并实现 SpiceDB 的水平可扩展性。

SpiceDB 警告设计

策略的根本挑战在于,它们的输入参数可以更改集中式关系数据存储所理解的授权结果。如果 SpiceDB 缓存已被策略变量“污染”的子问题,则这些子问题被其他请求重用的可能性会降低,从而严重影响缓存命中率。正如您所怀疑的那样,这会危及系统的支柱之一:其扩展能力。

一旦您承认向分布式缓存添加输入参数效率不高,您自然会倾向于第一个问题:如果您将这些输入保留在缓存子问题之外会怎样?它们仅在请求时已知,所以让我们将它们添加为子问题中的变量!与从数据存储中获取关系相比,传播这些变量、组装它们和执行逻辑的成本相形见绌。

下一个问题是:如何将政策决策整合到关系图中?SpiceDB 模式语言的核心概念是关系和权限;这些是开发人员如何定义他们的关系的形状以及如何遍历它们。自然地,作为一个图,在边缘或节点添加策略逻辑是合适的。这至少留下了两个明显的选择:关系级别的策略或权限级别的策略。

在对两个选项进行迭代以了解人体工程学和表现力之后,选择是关系级别的策略。毕竟,SpiceDB 是一个基于关系的访问控制 (ReBAC) 系统。关系级别的策略允许您参数化每个关系,这导致了“这种关系存在,但有一个警告!”的说法。通过这种方法,SpiceDB 可以像这样进行请求时关系否决:

definition human {} 

caveat the_answer(received int ) { 
  received == 42
 } 
definition the_answer_to_life_the_universe_and_everything {
  关系人类:具有 the_answer 权限的人类
  启蒙 = 人类           

Netflix 和 AuthZed 也讨论了静态与动态警告的概念。开发人员会在 SpiceDB 模式中定义静态 Caveat 表达式,而动态 Caveats 会在运行时定义表达式。讨论围绕类型化编程语言与动态编程语言展开,但考虑到 SpiceDB 的模式语言是为类型安全而设计的,继续使用静态警告似乎与整体设计相一致。为了支持运行时提供的策略,选择是引入表达式作为 Caveat 的参数。保持 SpiceDB 模式易于理解是做出此决定的关键驱动因素。

对于定义 Caveats,主要要求是提供一种表达式语言,它对部分计算的表达式具有一流的支持。谷歌的 CEL似乎是一个显而易见的选择:一种在线性时间内进行评估的 protobuf 原生表达式语言,对可以在边缘运行的部分结果提供一流的支持,并且不是图灵完备的。CEL 表达式是类型安全的,因此它们不会在运行时引起那么多错误,并且可以作为已编译的 protobuf 存储在数据存储中。鉴于近乎完美的需求匹配,它确实让你想知道自白皮书以来谷歌的桑给巴尔做了什么!

CAVEATED要执行该逻辑,除了ALLOW和之外, SpiceDB 还必须返回第三个响应DENY,以表明 CheckPermission 请求的结果取决于计算未解析的 CEL 表达式链。

SpiceDB 注意事项需要允许在评估之前存储静态输入变量,以表示 Netflix 应用程序身份的多维特性。今天,这被称为“Caveat context”,由 SpiceDB Schema 中写入的值以及关系和客户提供的值定义。将构建时间变量视为模板化 CEL 表达式的扩展,并且它们优先于请求时间参数。这是一个例子:

警告 the_answer(received int , expected int ) { 
  received == expected 
}           

最后,为了处理存在多个 Caveated 子问题的场景,决定是在评估之前收集最终的 CEL 表达式树。最终评估的结果可以是ALLOW、DENY或CAVEATED。通配符和 SpiceDB API 的事情变得更加棘手,但让我们把它留到另一篇文章!如果响应是CAVEATED,则客户端会收到正确评估表达式所需的缺失变量列表。

总结!主要的设计决策是:

  • 在关系级别而不是权限级别定义的注意事项
  • 使注意事项与 SpiceDB Schema 的类型安全性质保持一致
  • 支持调用者提供的类型正确的值
  • 使用 Google 的 CEL 定义 Caveat 表达式
  • 引入新的结果类型:CAVEATED

SpiceDB 警告如何更改授权 Netflix 身份?

SpiceDB Caveats通过允许 Netflix 像过去一样为应用程序指定授权策略来简化这种方法。系统不需要将授权世界的整个状态作为关系持久化,系统可以拥有在授权检查时使用的身份的关系和属性。

现在 Netflix 可以编写一个类似于 的警告match_fine,如下所述,它采用预期属性的列表,例如区域、帐户等。只要授权检查的上下文具有观察到的帐户,该警告将允许关系指定的特定应用程序, stack, detail, region, and extended attribute values 与预期对应项中的值相匹配。这个游乐场有模式、关系等的实时版本,可以用来进行实验。

定义 app {}

警告 match_fine( 
  expected_accounts list< string >, 
  expected_regions list< string >, 
  expected_stacks list< string >, 
  expected_details list< string >, 
  expected_ext_attrs map <any>, 
  observed_account string , 
  observed_region string , 
  observed_stack string , 
  observed_detail string , 
  observed_ext_attrs map <any> 
) { 
  observed_account in expected_accounts &&
  expected_regions 中的 observed_region && 
  expected_stacks 中的 observed_stack && 
  expected_details 中的 observed_detail && 
  expected_ext_attrs.isSubtreeOf(observed_ext_attrs) 
}

定义电影 { 
  relation replicator: app with match_fine 
  permission replicate = replicator 
}           

使用这个 SpiceDB 模式,我们可以编写一个关系来限制对复制器应用程序的访问。它应该只允许运行时

  • 它在highrisk或birdie帐户中
  • ANDus-west-1要么us-east-1
  • 并且它有堆栈bg
  • 并且它有细节casser
  • 并且它的扩展属性包含键值对 'foo: bar'
movie:newspecial#replicator@app:mover[match_fine:{ "expected_accounts" :[ "highrisk" , "birdie" ], "expected_regions" :[ "us-west-1" , "us-east-1" ], " expected_stacks" :[ "bg" ], "expected_details" :[ "casser" ], "expected_ext_attrs" :{ "foo" : "bar" }}]           

通过 playground,我们还可以做出可以反映我们从 CheckPermission API 中看到的行为的断言。这些断言清楚地表明我们的警告按预期工作。

assertTrue: 
- 'movie:newspecial#replicate@app:mover with {"observed_account": "highrisk", "observed_region": "us-west-1", "observed_stack": "bg", "observed_detail": "casser" , "observed_ext_attrs": {"foo": "bar"}}'
 assertFalse: 
- 'movie:newspecial#replicate@app:mover with {"observed_account": "lowrisk", "observed_region": "us-west-1" , "observed_stack": "bg", "observed_detail": "casser", "observed_ext_attrs": {"foo": "bar"}}' - 'movie:newspecial#replicate@app:purger
 with {"observed_account": "高风险”, ”observed_region": "us-west-1", "observed_stack": "bg", "observed_detail": "casser", "observed_ext_attrs": {"foo": "bar"}}'           

关闭

Netflix 和 AuthZed 都对合作的成果感到兴奋。Netflix 有另一个可以使用的授权工具,而 SpiceDB 用户有另一个选项来执行丰富的授权检查。弥合基于策略的授权和 ReBAC 之间的差距是一个强大的范例,它已经使那些希望基于 Zanzibar 的实施实现其授权堆栈现代化的公司受益。

致谢

  • 克里斯沃尔夫
  • 乔伊·肖尔
  • 维克多·罗尔丹·贝当科特
  • 切斯顿·李

补充阅读

  • 什么是谷歌桑给巴尔
  • 带注释的谷歌桑给巴尔论文
  • SpiceDB,一个开源的,受谷歌 Zanzibar 启发的授权系统
  • 谷歌的 CEL
  • SpiceDB词汇表
  • Top-3 最常用的 SpiceDB 警告模式 (authzed.com)
  • SpiceDB 如何回答权限
  • Netflix 复杂身份示例架构

作者:Chris Wolfe、Joey Schorr和Victor Roldán Betancort

出处:https://netflixtechblog.com/abac-on-spicedb-enabling-netflixs-complex-identity-types-c118f374fa89

继续阅读