【问题标题】:Resource-based RBAC implementation ideas基于资源的RBAC实现思路
【发布时间】:2021-08-01 23:35:55
【问题描述】:

我需要在我的应用程序中实现一个非常复杂的 RBAC 模型。 它非常类似于 Azure RBAC:https://docs.microsoft.com/en-us/azure/role-based-access-control/overview

让我用一个例子来解释一下:

假设我有一个资源类型:server_group

然后我有角色:

  1. admin(可以在 server_group 上执行 CRUD + 其他权限)
  2. editor(可以在 server_group 上执行 RU + 其他权限)
  3. viewer(只能Rserver_group+其他权限)

这些角色是租户范围的角色:这里的操作范围是当前用户注册所在的组织。

这是为资源类型分配角色权限的传统模型。

但是,如果您需要向具有viewer 角色但在资源类型的特定实例范围内的特定用户授予更多权限怎么办?

Mark 是管理员,他创建了一个server_group sg1,他想将server_group_editor 的角色分配给拥有viewer 租户范围角色的Alice。

server_group_editor 角色有一个适用范围:server_group

server_group_editor 添加了更新server_group 资源类型的功能。

由于 Alice 在 sg1 实例中具有 server_group_editor 的角色,因此她现在可以编辑此资源。

以前她不能这样做,因为她的租户范围的权限只允许她列出所有服务器组。

我希望这是有道理的。

话虽如此,我很想知道是否有产品支持这种灵活的 RBAC 模型,无论是 SaaS 还是可以作为独立服务部署的应用程序?

我正在查看 Auth0、Okta、KeyCloak,但我看不到它们支持这个模型。

提前致谢!

【问题讨论】:

  • 这不是 Azure-rbac 问题,而是 Auth0、Okta、KeyCloak rbac 问题。我删除了 Azure rbac 标签。

标签: keycloak auth0 okta rbac


【解决方案1】:

我们在我工作的公司遇到了类似的问题。

我们使用 Auth0,但内置的角色/权限功能并不能完全满足我们复杂的细粒度 authZ 要求 - 基本上,我们需要能够处理可能属于一个或多个组的用户,但每个组的不同权限。我们可以通过在app_metadata 中存储一个复杂的权限结构,然后将其附加到用户访问令牌(通过 Auth0 规则)来解决这个问题,但我们预计这会变得笨拙......

我们通过构建内部“权利”微服务并在我们这边持久化一些访问控制数据(即用户、组、角色和权限)来解决这个问题。

这是一个高级图表:

当用户注册时(使用与“IdpFacade”微服务对话的 Auth0 自定义通用登录页面),我们将事件发布到消息代理(Azure 服务总线)。此事件触发在“访问控制”数据存储中创建用户(以及初始组、角色、权限关联)。 注意:我们也可以通过 API 更新这个数据存储(例如,如果我们想动态地为用户分配额外的角色/权限)

当用户向启用授权的微服务发出请求时,我们会将细粒度的 authZ 决策推迟到授权服务。授权服务首先从数据存储中查询用户角色/权限(基于 JWT 主题,本质上是来自 Auth0/IDP 的用户标识符)。然后,我们使用 Overload input 模式将此信息与 HTTP 方法、URI / 资源路径和(可选)附加元数据(以键值对的形式)一起传递到 Open Policy Agent(又名 OPA)。 OPA 在名为 Rego 的 DSL 中定义所有 authZ 策略并进行决策。

'entitlement' 服务的响应基本上是一个单独的字段,用于指示是否应允许或拒绝访问。如果 allow 为 false,启用授权的微服务将返回 HTTP 403。供参考。我们在 .NET Core 中构建了一些样板来简化对权利的调用。这是一个例子:

[HttpPost]
[CheckEntitlement()]
public async Task<IActionResult> PostAsync(

注意:在属性中我们可以指定策略名称,以及(可选)元数据。

这种方法的优点:

  • 简化的 IDP 实施
  • 微服务中的简化 authZ 逻辑,例如他们不需要了解复杂的 authZ 层次结构/要求,只需调用权利即可。
  • 解耦架构 - 无需接触微服务即可更新 authZ 策略。
  • 实时 authZ 即可以更新角色/权限,并且更改将是即时的,而 JWT 中的权限在 JWT 到期之前一直有效。

我可能应该写一篇关于这种方法的详细博客,因为我认为这是一种非常好的方法(尽管最初需要做一些工作)。

【讨论】:

  • 如何对授予用户确实有权访问列表中某些对象的数据进行分页?您需要从更细粒度的分配中传递他已被授予/拒绝访问的资源的 ID。只有这样,底层的微服务才能正确过滤掉数据。
  • 我想我理解你的问题。授权服务不知道特定资源的所有者,因此我们必须从启用授权的微服务(作为元数据)传递它。 CheckEntitlement 属性可以选择定义一个 IMetadataProvider impl,例如ResourceOwnerMetadataProvider 可能会根据 URL 路径中定义的资源解析实际的资源所有者,例如/api/v1/transaction/{transaction-id} 并将其添加到请求中。我们需要处理一些复杂的用户层次结构,因此需要处理诸如推断权限之类的事情......
  • 注意:OPA 没有数据库,因此我们需要将所有内容都传递给它,以便它可以做出策略决策。
  • 您使用 OPA 的事实是次要的……我的问题是关于分页的。例如,假设您的系统中有一个名为“students”的实体。如果没有任何授权规则,GET /api/students?page=1 将返回包含 20 个项目的第一页和包含总数为 X 的元数据。现在我的 API 的客户端可以正确地对数据进行分页。但是,如果您有细粒度的 RBAC,当默认情况下某些用户可能被拒绝访问所有项目并以排除的形式授予子集时,您将如何正确地为主题的数据分页?
  • OPA 与否 OPA,我需要传递到我的微服务中,即从真实数据存储源中检索数据,有关用户被授予/拒绝访问权限的项目的信息,然后应用来自 URL 请求参数的其他一些过滤器。如果您正在决定主题是否可以访问单个项目,那么整个 ALLOW/DENY 决策工作正常,但是当您检索列表并且需要正确显示总计数时,逐页正确获取,这就是我看到复杂性。顺便说一句,感谢您的参与,我很感激。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2019-04-15
  • 2021-10-24
  • 2020-06-18
  • 2015-03-04
  • 2023-03-25
  • 2011-06-22
  • 1970-01-01
相关资源
最近更新 更多