产品展示

  • 首页 i(name 高效且精细的授权,依托 Amazon DynamoDB 扩展 数据库博客

高效且精细的授权,依托 Amazon DynamoDB 扩展 数据库博客

2026-01-27 15:05:08

大规模高效精细授权,基于亚马逊 DynamoDB

关键要点

在本文中,我们讨论了如何使用亚马逊 DynamoDB 构建高效、可扩展且可靠的精细授权解决方案

Okta 的客户身份云CIC提供强大的访问管理解决方案。FGA 是基于关系的访问控制ReBAC,具备弹性、精细的授权能力。使用 DynamoDB 的好处包括低延迟、高可用性以及简化的运维管理。FGA 如何实现跨区域的一致性和高效授权。

由 Jonathan Whitaker、Adrian Tam、Jakub Hertyk 和 Sahil Thapar于2024年3月22日发布。

在数字安全领域,Okta是一家身份和访问管理企业,已成为关键的参与者。Okta 云平台为全球数千家企业和应用程序提供服务,并为员工和客户身份使用案例提供访问管理解决方案。

Okta 客户身份云CIC提供强大的访问管理解决方案,例如精细授权FGA,以支持面向客户的应用程序和网站。FGA 是一项多区域软件即服务SaaS,能够在任何规模上实现灵活的精细授权。它基于基于关系的访问控制ReBAC,是角色基础访问控制RBAC和基于属性的访问控制ABAC授权模型的演变。

在本文中,我们讨论了 Okta 如何使用 亚马逊 DynamoDB 作为关键值存储,以构建高度可扩展、有效且可靠的业务关键集成。DynamoDB 是一款无服务器、NoSQL 的完全托管数据库,提供毫秒级的单数字性能。我们还将探讨 Okta 如何设计 DynamoDB 表,以实现每秒数百万个请求RPS,并在 AWS 区域间进行多活复制。

什么是 Okta FGA?

Okta FGA 是一款权限引擎,能够灵活处理复杂的授权政策,而不会妨碍这些政策的开发和执行。FGA 使平台能够轻松为其应用程序添加精细授权。它包括一个工具生态系统,包括 API、CLI 和各种跨多种语言的 SDK。

应用程序委托 FGA 在关键代码路径中做出授权决策,因此可用性和延迟是 FGA 的关键特征。我们的可用性目标为四个99999 的正常运行时间,以最小化停机时间。FGA 追求 p99 延迟不超过 50 毫秒,确保我们的客户在最苛刻的性能要求下也能体验到低延迟。与 FGA 集成的应用应能够跨区域执行访问政策。例如,如果某人在 useast1 撤销对某个资源的权限,那么对该资源的权限撤销应能在 uswest2 中执行,反之亦然。您需要能够跨区域执行政策,以实现快速的本地读写性能。

鉴于 FGA 的特性,我们在选择支持 FGA 的数据库时考虑了几个因素:

高可用性可扩展性,能够管理数百万的 RPS 和数十亿的行数据跨区域的多活复制低延迟完全托管

我们的团队熟悉开源关系数据库,并在构建 FGA 时将其评估为起点。然而,我们发现我们的规模会因为应用程序分片而增加操作复杂性。DynamoDB 提供了对几乎任何规模工作负载的无缝可扩展性,因此我们不必担心用户基础增长时性能下降,或者因扩展、版本升级和修补而导致的维护中断。它提供了写透缓存,这对满足我们的性能目标尤为重要。通过 DynamoDB 全球表,一个完全托管的多区域和多活数据库选项,我们可以为用户提供高可用性和无缝的灾难恢复。

FGA设计概述

FGA 基于 AWS 基础设施构建,由 应用负载均衡器ALB、AWS Fargate 和亚马逊 DynamoDB 组成。

应用负载均衡器是一项完全托管的第七层负载均衡服务,可以将传入流量负载均衡到多个目标上,例如 亚马逊弹性计算云Amazon EC2实例。

Fargate 是一个无服务器、按需收费的计算引擎,让您能专注于构建应用,而无需管理服务器。

以下图示展示了解决方案架构。

我们在多区域部署 FGA 服务。这些部署由 DynamoDB 全球表提供支持,提供主动主动架构,因此在 useast1 的写入对 uswest2 的读取是可见的,反之亦然。这种架构提供高可用性,并允许我们在区域之间执行访问控制。由于 FGA 是按区域部署的,我们还能够在同一地区服务客户应用,从而减少它们对 FGA 执行授权查询的延迟。

通过极少的基础设施实现这一设计。 从运营的角度来看,使用 DynamoDB 部署和管理多区域架构是相对简单的,因为数据平面可以视为一个单独的逻辑数据库,这样我们就减少了管理区域复制的负担。

FGA 查询和 DynamoDB 表设计

FGA API 包含多种关系查询,可用于做出授权决策:

检查 特定用户是否可以访问特定资源?列出对象 特定用户可以访问哪些资源?

评估 FGA 查询涉及由两个因素驱动的迭代遍历算法:由开发人员编写的授权模型和建立资源对象与主体用户之间关系的关系元组。评估 FGA 查询的过程类似于在树形数据结构中评估路径。我们迭代评估模型的关系规则,并遵循关系元组类似于图中的边。FGA 以高度并行的方式评估评估树中的不同分支。如果存在通往树中关系的解析路径,便可知用户拥有正确的权限。

quickq机场

FGA 模型是一个声明性的规范,使用 FGA 领域特定语言DSL,独特地描述应用程序的授权模型,并特定于应用程序及其定义的实体。关系元组是应用程序在与授权决策相关的事件和行为发生时写入 FGA 的事实。例如,假设您正在构建一个项目管理应用;您的 FGA 模型可能如下所示:

javascriptmodel schema 11

type user

type epic relations define creator [user] define editor [user] or creator define viewer [user] or editor

type story relations define epic [epic] define creator [user] define editor [user] or creator or editor from epic define viewer [user] or editor or viewer from epic

type task relations define parent [epic story] define creator [user] define editor [user] or creator or editor from parent define viewer [user] or editor or viewer from parent

该应用具备 Epic、Story 和 Task 等实体。当创建一个 epic 实体时,可以写入一个关系元组,建立 user 和其创建的 epic 之间的关系。例如,关系元组 (object epicsomeepic relation creator user userjon) 确立了 userjon 是 ID 为 someepic 的 epic 实体的创建者。作为 epic 实体的创建者,您可以编辑该实体第9行,并且如果可以编辑关系,则可以查看该实体第10行。您可以在实体之间定义层次关系,这允许关系被继承。如果您可以查看某个任务的父对象,则也可以查看该任务第24行。例如,关系元组 (taska parent storysomestory) 和 (storysomestory viewer userjon) 使 userjon 可以查看 taska,因为 userjon 可以查看父故事 somestory,如下面的图所示。

通过结合这些建模规则和关系元组,开发者可以以非常灵活和精细的方式表达复杂政策。

FGA DynamoDB 表架构设计

为 DynamoDB 设计表架构与使用关系数据库有所不同。当设计关系数据库架构时,通常从定义数据模型开始,然后推导出所需的 SQL 查询模式。然而,开发高效的 DynamoDB 架构开始于首先定义所需的查询模式,然后从中推导出表架构结构。在这个架构设计阶段,遵循 设计和建筑的最佳实践 尤为重要,因为这有助于提升系统整体性能。因为我们希望实现的性能目标,这些考虑显得尤为重要。单个 FGA 查询可能需要多个 DynamoDB 查询来解析关系树的不同分支,因此我们向 DynamoDB 发起的查询必须高度优化。

我们不惜一切代价避免表扫描和低效过滤,并通过使用 单表设计 避免多个表的吞吐量容量规划。我们的单表设计架构可以提供更好的突发容量,并将键分散到更多分区,从而减少因容量不足而导致的限流。这些需求使单表设计非常适合我们的用例。

基于我们的表设计考虑,团队开始定义数据查询模式,以最有效地利用分区键PK、排序键SK和全球二级索引GSI特性。以下是我们提出的一些主要查询模式还有其他模式,但这些是主要关注点。

对于关系元组,我们有以下模式:

通过 storeid、object、relation 和 user 直接查找单个关系元组PK、SK列出 storeid 中匹配特定对象的所有元组GSI1列出 storeid 中特定用户和对象类型过滤的所有对象和关系GSI2列出特定 storeid 的所有元组GSI3列出 storeid 中按对象类型、关系和用户过滤的所有元组GSI4

对于授权模型,我们使用以下模式:

通过 storeid 和 modelid 直接查找单个模型PK、SK

以下表总结了这些查询模式的字段和值。

实体/项目字段值模板元组PKTUPLE{storeid}{object}#{relation}{usertype}SK{user}object{object}relation{relation}user{user}GSI1PKTUPLE{storeid}{object}GSI1SK{relation}#{user}GSI2PKTUPLE{storeid}{user}{objecttype}GSI2SK{relation}#{object}GSI3PKTUPLE{storeid}GSI3SK{object}#{relation}@{user}GSI4PKTUPLE{storeid}{objecttype}{relation}GSI4SK{user}{object}授权模型PKAUTHZMODEL{storeid}SK{modelid}serializedmodel{serialized model}

使用此架构设计,我们能够从不同角度查询 FGA 关系元组,以满足前向查询Check和反向查询ListObjects模式。Check 查询使用元组项的直接 PK 和 SK直接查找,而 ListObjects 则使用 GSI4 进行反向查找。其他 GSIGSI1、GSI2、GSI3用于 读取 API,这使开发者能够使用各种过滤规则在系统中查找元组。

基准测试

我们通过运行 基准测试 来测试我们的系统,以处理真实大规模流量,每秒进行 100 万个 Check 请求,并且 FGA 关系元组的数量超过 1000 亿。我们基于社交网络模型合成一个 FGA 模型,用户可以发布内容,其他用户可以与之互动。

我们能够在仅两天内完成高规模基准测试。FGA 工作负载主要受 CPU 约束,因此 Fargate 工作负载的横向扩展使我们得以实现高吞吐率。由于主键使 DynamoDB 能够均匀写入分片,因此无需调整我们的 DynamoDB 架构,而表架构、单表设计和 GSI 架构的开发使我们能够在表的大小和吞吐量的情况下,实现常量时间、低延迟的查询性能。

FGA 能够支持大规模流量,并保持低延迟。它在未启用内部缓存机制的情况下,能够以 p95 延迟低于 20 毫秒的速度服务 105 万个 Check 请求。每个 FGA Check 查询涉及多个对 DynamoDB 的查询,以评估 Check 解析树的不同分支,因此在峰值吞吐量下,我们对 DynamoDB 的请求数达到了好几个百万 RPS,观察到的错误率为零。

以下图展示了基准请求速率每秒。

以下图展示了基准检查延迟结果。检查请求由多个调用 DynamoDB 及处理来自 DynamoDB 查询的结果组成。

检查请求由多个调用 DynamoDB 及处理来自 DynamoDB 查询的结果组成。

高效且精细的授权,依托 Amazon DynamoDB 扩展 数据库博客

学到的经验

一个重要的经验是数据库连接管理。建立新数据库连接的成本很高,会影响 p95 和 p99 延迟。微调每个主机的最大连接数可减少连接波动,从而改善延迟。

对于这些高要求的工作负载,我们了解到在使用按需容量模式时需要对 DynamoDB 表进行预热。因为基准测试的上升期较短在我们的案例中少于 8 分钟。我们将 DynamoDB 切换到预置容量模式,预置所需的最大 RCU 和 WCU,然后再次切换回按需模式。如果没有预热,DynamoDB 查询会出现限流,因为吞吐量超过了之前峰值吞吐量的双倍的默认容量。了解查询负载的峰值需求是认清如何在生产应用中应对吞吐量峰值的重要因素。

最后,我们学会在预算规划时考虑 GSI 的成本。GSI 的预置吞吐量设置与其基表的设置分开。对 GSI 的查询或更新消耗索引的读写能力单位,而不是基表的能力。因此,即使基表的配置足够,针对基表的查询或写入活动可能会被限流。在预热阶段,我们同时消耗了主表和表的 GSI 的 RCU。

结论

在本文中,我们看到了 Okta 如何利用 DynamoDB实现多区域授权服务,具备低延迟和高可扩展性,并且无需额外的运维开销。可用性、耐久性和容错性内置于 DynamoDB 中,消除了您需要为这些能力架构应用程序的需求。基于这些能力,我们的开发团队将与传统方法相比,节省了几个月的工作时间,后者需投入大量精力来部署、配置和微调自管理数据库服务。这节省的时间使我们能够将工程师的专业技能重新投入到核心开发中,而不是将资源用于维护服务基础设施。