如何使用 Amazon Verified Permissions 和 Amazon Neptune
使用 Amazon Verified Permissions 和 Amazon Neptune 实现基于关系的访问控制
关键要点
本文中,我们将探讨如何使用 Amazon Verified Permissions 和 Amazon Neptune 实现基于关系的访问控制 (ReBAC)。ReBAC 通过利用用户与资源之间的关系来做出访问决策,能够比传统的基于角色的访问控制 (RBAC) 和基于属性的访问控制 (ABAC) 提供更细致的访问管理。我们还将探讨如何在实际应用中设计 Cedar 策略和构建授权请求的结构。
外部化自定义应用的授权是一个安全策略,即将访问控制决策管理与应用程序逻辑分开。与将授权规则嵌入应用程序代码不同,这些规则被定义为策略,由单独的系统进行评估以做出授权决策。这种分离增强了应用程序的安全性,以符合持续实时授权的零信任原则,简化安全策略的管理,并启用多个应用程序间的一致策略执行。 Amazon Verified Permissions 是一项可扩展的权限管理和细粒度授权服务,您可以使用它来外部化应用程序授权。
在实施授权系统时,您可能会考虑两种常见的访问控制模型: 基于角色的访问控制 (RBAC) 和 基于属性的访问控制 (ABAC)。RBAC 根据用户在组织中的角色分配权限,通过将权限分组到与工作职能相对应的角色中简化了访问管理。而 ABAC 则基于与用户、资源及上下文相关的一组属性授予权限,从而允许做出更细粒度和动态的授权决策。然而,随着系统日益复杂并且数据之间的联系增多尤其是在社交网络、协作环境和多租户应用程序等环境中RBAC 和 ABAC 的局限性就显现出来了。这些模型通常无法有效捕捉实体之间的关系。基于关系的访问控制 (ReBAC) 提供了一种更细致的方式,以用户与资源之间的关系为基础做出允许的操作决策,从而比其他模型更有效地处理场景。
在本文中,我们将向您展示如何使用 Verified Permissions 和 Amazon Neptune,这是 AWS 上一款托管的无服务器图数据库,来实现 ReBAC。
什么是基于关系的访问控制?
ReBAC 的核心原则是,授权决策基于请求访问的主体与正在访问的资源之间的关系。这些关系可以有多种类型所有权、协作或成员关系形成层级结构。ReBAC 的例子可在多个领域发现,包括社交媒体网站、项目管理工具和内容管理系统。例如,在社交媒体应用中,ReBAC 可用于根据帖子发布者、其联系人与内容本身之间的关系,控制谁可以查看、评论或分享一条帖子。
从概念上讲,角色是一种关系,关系是属性的子集。
ReBAC 的优势
在某些类型的应用中,关系是动态变化的。例如,在协作或社交媒体应用中,像 贡献者 或 共同所有者 等关系在用户与资源之间不断建立。与传统访问控制模型相比,ReBAC 在这些用例中提供以下优势:
优势描述细粒度访问控制ReBAC 在个体资源级别上授予访问权限,基于用户与该资源的关系。例如,用户可以更新他们具有贡献者关系的个人相册。可扩展性与适应性关系会动态变化。当关系变化时,访问权限会自动更新。例如,当贡献者关系被移除时,该用户将不再拥有访问权限。支持层级结构ReBAC 可以处理层次关系。例如,贡献者关系可以在相册层级中继承,允许用户更新与其有关系的相册中的照片。ReBAC 中常见的关系模型
以下是构建应用程序及其授权系统时需要考虑的一些常见关系模型:
资源所有权:基于用户是否 拥有 该资源,授予访问或操作资源的权限。例如,如果您是 GitHub 仓库的所有者,则可以删除该仓库。资源层级:基于主体对父资源的权限,授予访问或操作资源的权限。例如,GitHub 仓库的贡献者可以关闭属于该仓库的问题。用户层级:与 AWS 身份与访问管理 (IAM) 的用户组类似。属于某个组的主体将拥有授予该组的权限。plaintext图 1 ReBAC 中的常见关系模型
在关系模型中,直接关系代表用户与资源之间的明确、具体的链接,例如,某个员工拥有他们的报销单,或某个文件是某个文件夹的成员。这些连接是直接且易于定义的。
然而,关系模型常常超出这些直接链接,包含层级结构。这些间接关系本质上更为复杂。例如,团队经理可能能够访问他们下属所提交的所有报销单,即使他们并不直接拥有这些报销单。类似地,文件夹的拥有者可能能够访问所有在其子文件夹中的文件,无论是谁创建的这些文件。
这些间接关系是根据一系列直接关系得出的。它们形成一种关系链,虽然没有明确的定义,但通过层级结构隐含存在。由于其复杂性和潜在的深远影响,这些间接关系在设计授权系统时需要细致考虑。
在本文中,我们将重点讨论使用资源所有权、资源层级和这些模型中的关系层级所实现的关系模型。
示例场景
考虑一个让用户管理和分享其宠物视频的视频应用。Alice 和 Bob 是该环境中的单独用户,因此他们仅拥有对自己目录或视频的访问权限。由于 Alice 和 Bob 直接拥有他们的资源,因此他们对这些资源具有直接的 OWNER 关系,如图 2 中的实线所示。aliceCatVideomp4 是存储在 aliceVideoDirectory 目录中的视频资源。这两个资源之间存在 MemberOf 关系。
plaintext图 2 Alice 直接拥有她的资源
Charlie 对根目录 petVideosDirectory 具有直接的 OWNER 关系。由于 aliceVideoDirectory 是 petVideosDirectory 的子目录,因此 Charlie 继承了对 aliceVideoDirectory 及其内部视频资源 aliceCatVideomp4 的 OWNER 关系。此间接的 OWNER 关系通过资源之间的 MemberOf 关系继承,并在图 3 中表现为虚线。
plaintext图 3 Charlie 通过 MemberOf 关系间接拥有资源的关系
在实施此场景的访问控制时,RBAC 和 ABAC 提供了不同的方法。在 RBAC 中,您可以定义如 OWNER 和 VIEWER 等角色,并通过 OWNER 角色授予 Charlie 对每个资源的完全访问权限。尽管这种方法最初简单,但随着应用程序的增长,可能会变得不够灵活,并导致角色繁多。例如,您可能想为每种宠物 (如猫或狗) 的不同资源 (如照片或视频) 管理单独的角色。在 ABAC 中,您可能会将诸如 OWNER 和 VIEWER 的属性分配给用户,并授予每个用户对具有特定属性的资源的权限。这种方法提供了更大的灵活性,但细粒度控制的设置与管理相对复杂。随着应用程序层级变得更加复杂,两个模型都面临着在保持适当的访问控制同时保持可扩展性的挑战。
ReBAC 通过执行一个使用主体与资源之间的直接和间接关系的访问控制模型来解决这些限制。在示例场景中,当 Charlie 请求访问视频资源 aliceCatVideomp4 时,应用程序遍历 Neptune 中的关系图以检索通过 MemberOf 关系继承的 OWNER 关系,并做出授权决策。
ReBAC 应用概述
在该解决方案中,关系数据存储在 Neptune 中。在请求 Verified Permissions 的授权决策之前,应用程序运行一个 Neptune 查询,遍历关系图以检索与资源具有特定关系的主体集合。然后,应用程序构造一个授权请求,使用此查询的结果填充请求中的实体数据。
在 Cedar 架构中,资源有一个属性以关系为名包含与资源具有该关系的主体集合。在我们的示例应用中,类型为 Video 的实体有一个名为 OWNER 的属性,其中包含与视频直接或间接有关的用户的集合。每种潜在关系都由独特的资源属性表示,并且需要专门的查询来获取拥有该关系的主体集合。
请参见 GitHub 仓库 获取逐步指导。在本文中,我们将重点关注解决方案的关键概念。
架构
plaintext图 4 解决方案架构
如图 4 所示,解决方案架构包括以下内容:
用户通过 Amazon Cognito 进行身份验证并获得访问令牌和 ID 令牌。用户通过提供的令牌访问 Amazon API Gateway。一个应用程序 AWS Lambda 函数遍历 Neptune 中的关系图,并返回与资源具有特定关系的主体集合。应用程序 Lambda 函数通过将关系数据放入实体字段来构造请求并将请求传递给 Verified Permissions。Verified Permissions 作为策略决策点 (PDP),评估 Cedar 策略以作出授权决策。应用程序 Lambda 函数充当策略执行点 (PEP),根据 Verified Permissions 返回的授权决策来允许或拒绝 API 访问。Neptune 中的数据建模和查询
实体之间的关系在 Neptune 中作为属性图创建和存储。属性图是一组具有各自属性键值对的顶点和边。顶点表示我们示例中的实体,如用户、目录和视频,边则代表顶点之间的方向关系。每条边都有一个标签,表示关系的类型。
Neptune 支持多种图查询语言,包括 Gremlin、openCypher 和 SPARQL,以访问图。在本解决方案中,我们使用 Gremlin 作为图查询语言。有关 Gremlin 的更多信息,请参见 Apache TinkerPop 的文档。您可以使用 Neptune 图笔记本 来与 Neptune 图进行交互。
您可以使用以下查询可视化关系图 (图 5)。我们使用 elementMap() 来包含属性,以表示顶点或边。
gremlin
1小时试用加速器可视化关系图并提取每个顶点和边的属性
gremlin p vouteinvgV()outE()inV()path()by(elementMap(namedirectoryIdvideoIdownerNameownerIduserIdisPublic)order()by(keys))
plaintext图 5 Neptune 中的关系图
以下代码片段显示了如何在关系图中添加一个表示 entity 的顶点和表示关系的边。静态属性如 ownerId、ownerName 和 isPublic 被定义为顶点的属性。在我们的示例中,我们将定义两种关系MEMBEROF 和 OWNER来标示资源与资源之间以及资源与用户之间的直接关系。
gremlin
添加视频顶点 (例如:aliceCatVideovertex)
gaddV(video)property(name aliceCatVideomp4)property(videoId aliceCatVideoid)property(ownerId aliceid)property(ownerName alice)property(isPublic False)
添加关系边
gV(aliceCatVideovertex)addE(MEMBEROF)to(aliceVideosDirvertex)gV(alicevertex)addE(OWNER)to(aliceCatVideovertex)
为所有主体和资源标识符分配全球唯一标识符 (UUID) 是最佳实践。此外,最佳实践还应避免在主体或资源的唯一标识符中包含个人识别信息、机密或敏感信息。
要遍历关系图以获取资源顶点的拥有者顶点,您可以使用以下查询。此查询返回与资源顶点 aliceCatVideomp4 具有直接 OWNER 关系的顶点。
gremlin
获取特定视频的直接拥有者
gV()hasLabel(video)has(name aliceCatVideomp4)in(OWNER)values(‘name’)
您可以使用以下查询发现通过资源之间的 MemberOf 关系继承的 OWNER 关系。该查询从一个视频顶点开始遍历关系图,并返回在路径上到根目录 petVideosDirectory 的每个资源顶点的 OWNER 顶点。它在去除重复后输出拥有者集合。这个查询揭示了在文件系统层次结构中继承的 OWNER,并将其包含在授权请求的实体列表中。

gremlin
获取特定视频的直接和间接拥有者
gV()hasLabel(video)has(videoIdvideoid)union(in(OWNER)repeat(out(MEMBEROF))until(has(name petVideosDirectory))in(OWNER))dedup()values(userId)toList()
Cedar 策略设计
Verified Permissions 使用 Cedar 策略语言 来定义细粒度权限。授权响应的默认决定是 DENY。第一条策略允许主体在仅当同一主体被包含在资源拥有者集合时,对 petVideosDirectory 中的资源执行 OwnerActions 动作组中的操作。
plaintext// 资源拥有者及相关人员可以访问资源permit ( principal action in [PetVideosAppActionOwnerActions] resource in PetVideosAppDirectoryltpetVideosDirectoryUUIDgt) when { resource has owner ampamp principal in resourceowner }
第二条策略是 ABAC 策略,仅当资源具有静态属性 isPublic 且其值为 true 时,允许主体在 petVideosDirectory 中的资源上执行 PublicActions 动作组中的操作。
plaintext// 允许对资源的公众访问permit ( principal action in [PetVideosAppActionPublicActions] resource in PetVideosAppDirectoryltpetVideosDirectoryUUIDgt) when { resource has isPublic ampamp resourceisPublic == true }
使用这种 Cedar 设计模式结合关系图的 ReBAC 实现需要仔细构建查询。Verified Permissions 将基于 Cedar 架构验证 Cedar 策略的正确性,但无法验证 Neptune 查询是否正确遍历图,返回正确的具有引用关系的主体集合。
在设计策略和查询时,请遵循以下指南:
每个 Cedar 策略管理特定关系的行为,在本例中为 OWNER。针对您的用例中的每个关系使用独特的 Cedar 策略。为您的用例中的每个关系定义动作组。每个在 Cedar 策略中提到的新关系都需要自己的查询,应用程序需要运行此查询,如果该关系与授权请求相关。策略编写者必须与应用程序开发者密切合作,以确保应用程序获取所有与授权请求相关的数据。间接关系可能难以直观理解,也容易出错。这里通过 MEMBEROF 关系继承的 OWNER 关系的例子相对容易理解。然而,我们建议避免依赖来源于多种不同类型直接关系的间接关系的策略。在未定义权限边界的情况下,间接关系可能会过度授权。在我们的示例中,继承关系的边界在目录的根级别petVideosDirectory定义。遵循最小权限原则,限制继承关系在明确的权限边界内。使用 MEMBEROF 来表示您的图中的父关系,以与 Cedar 策略术语保持一致。然而,请记住,Verified Permissions 无法自动发现 Neptune 图,因此您的查询仍需设计为正确遍历它。向 Verified Permissions 发起授权请求
以下示例展示了向 Verified Permissions 发起的授权请求的结构。在此示例中,使用 Amazon Cognito 作为 Verified Permissions 策略存储的身份源。Cognito 用户 ID 声明映射到用户实体 PetVideosAppUser。由 Cognito 发出的令牌在 Verified Permissions 中映射为格式为 ltuser pool IDgtltsubgt 的主体 ID。
以下请求是针对视频资源实体,UUID 为 878c101aca0e4733904daf3f252abf50即 aliceCatVideomp4 的视频 ID,使用 Alice 的 ID 令牌发出的,用户 ID 为 Alice 和 Charlie 的返回值是在 Neptune 中遍历关系图以获取具有 OWNER 关系的用户并将这些用户包含在实体字段中的拥有