本文属于机器翻译版本。若本译文内容与英语原文存在差异,则一律以英文原文为准。
示例 2:使用 OPA 和 Rego 进行多租户访问控制和用户定义的 RBAC
此示例使用 OPA 和 Rego 来演示如何通过租户用户定义的自定义角色在多租户应用程序的 API 上实现访问控制。它还演示了如何根据租户限制访问权限。此模型显示 OPA 如何根据高级角色中提供的信息做出精细的权限决策。
租户的角色存储在用于为 OPA 做出访问决策的外部数据(RBAC 数据)中:
{ "roles": { "tenant_a": { "all_access_role": ["viewData", "updateData"] }, "tenant_b": { "update_data_role": ["updateData"], "view_data_role": ["viewData"] } } }
这些角色由租户用户定义时,应存储在外部数据源或身份提供者 (IdP) 中,在将租户定义的角色映射到权限和租户本身时,身份提供者可以充当真实来源。
此示例使用 OPA 中的两个策略来做出授权决策,并研究这些策略如何强制执行租户隔离。这些策略使用前面定义的 RBAC 数据。
default allowViewData = false allowViewData = true { input.method == "GET" input.path = ["viewData", tenant_id] input.tenant_id == tenant_id role_permissions := data.roles[input.tenant_id][input.role][_] contains(role_permissions, "viewData") }
要显示此规则将如何运作,请考虑具有以下输入的 OPA 查询:
{ "tenant_id": "tenant_a", "role": "all_access_role", "path": ["viewData", "tenant_a"], "method": "GET" }
通过组合 RBAC 数据、OPA 策略和 OPA 查询输入,可以按如下方式做出此 API 调用的授权决定:
-
来自的用户向
Tenant A
发出 API 调用/viewData/tenant_a
。 -
数据微服务接收调用并查询
allowViewData
规则,传递 OPA 查询输入示例中显示的输入。 -
OPA 使用 OPA 策略中的查询规则来评估所提供的输入。OPA 还使用 RBAC 数据中的数据来评估输入。OPA 会执行以下操作:
-
验证用于进行 API 调用的方法是否为
GET
。 -
验证请求的路径是否为。
viewData
-
检查路径
tenant_id
中的是否等于与用户input.tenant_id
关联的路径。这样可以确保保持租户隔离。另一个租户,即使角色相同,也无法获得进行此 API 调用的授权。 -
从角色的外部数据中提取角色权限列表并将其分配给变量。
role_permissions
此列表是通过使用与用户关联的租户定义角色来检索的input.role.
-
role_permissions
检查它是否包含权限viewData.
-
-
OPA 将以下决定返回给数据微服务:
{ "allowViewData": true }
此过程显示了 RBAC 和租户意识如何有助于通过 OPA 做出授权决定。为了进一步说明这一点,可以考虑使用以下查询输入/viewData/tenant_b
进行 API 调用:
{ "tenant_id": "tenant_b", "role": "view_data_role", "path": ["viewData", "tenant_b"], "method": "GET" }
此规则将返回与 OPA 查询输入相同的输出,尽管它是针对具有不同角色的不同租户的。这是因为此调用是针对的,/tenant_b
而 RBAC view_data_role
中的数据仍具有与之关联的viewData
权限。要对强制执行相同类型的访问控制/updateData
,可以使用类似的 OPA 规则:
default allowUpdateData = false allowUpdateData = true { input.method == "POST" input.path = ["updateData", tenant_id] input.tenant_id == tenant_id role_permissions := data.roles[input.tenant_id][input.role][_] contains(role_permissions, "updateData") }
该规则在功能上与allowViewData
规则相同,但它验证的是不同的路径和输入法。该规则仍可确保租户隔离,并检查租户定义的角色是否向 API 调用者授予权限。要了解如何强制执行此操作,请检查以下 API 调用的查询输入/updateData/tenant_b
:
{ "tenant_id": "tenant_b", "role": "view_data_role", "path": ["updateData", "tenant_b"], "method": "POST" }
使用allowUpdateData
规则评估此查询输入时,会返回以下授权决定:
{ "allowUpdateData": false }
此呼叫将不会获得授权。尽管 API 调用者关联了正确的,tenant_id
并且正在使用经批准的方法调用 API,但还是租户view_data_role
定义input.role
的。view_data_role
没有updateData
权限;因此,对的调用/updateData
是未经授权的。对于拥有. 的tenant_b
用户来说,此调用本来是成功的update_data_role
。