首先,我很抱歉回复晚了。以下是我的评论。
ACL、RBAC、ABAC
我正在学习各种访问控制模型,发现ABAC和RBAC比较流行。
历史上,访问控制通过访问控制列表(ACL)来处理,然后是基于角色的访问控制(RBAC),最近是基于属性的访问控制(ABAC)。 ACL变得笨重且难以管理,这就是为什么NIST在1992年提出了RBAC的原因(是的,它那么老)。 RBAC是众所周知、成熟的,并内置于大多数IAM产品和应用程序中。例如,用户目录(LDAP、AD…)维护用户和角色分配,并向应用程序提供这些角色,应用程序可以使用这些角色来确定是否应该授予访问权限。使用RBAC时,无法进行更细粒度的访问(例如,基于关系的访问,即用户只能看到自己的数据),因此将要么(a)应用程序开发人员编写自定义代码以实现正确的访问,要么(b)使用ABAC。
为什么使用ABAC?
ABAC给您提供了根据任何属性(不仅限于角色和用户属性)定义细粒度访问权限的能力,通过使用策略来描述可以发生或不能发生的情况。ABAC有时被称为PBAC(基于策略的访问控制)。您可以参考XACML,这是实现ABAC策略的语言。您还可以了解
alfa(
Wikipedia),这是一种更简单的语言,可直接映射到XACML。
ABAC还定义了一种架构,即策略决策点(PDP)的概念,它根据其配置的策略处理您的授权请求。 PDP(在您的情况下,是WSO2 IS的WSO2 Balana部分)是由一个策略执行点(PEP)调用的,例如您的应用程序或坐落在您的应用程序前面的某个东西(例如API网关或拦截器,在您的情况下是WSO2 API Manager)。
![The ABAC Architecture](https://istack.dev59.com/4hw4j.webp)
你的使用场景
我有一个项目的基本情况,我不确定是应该选择RBAC还是ABAC。显然,RBAC是ABAC的子集,所以我应该选择ABAC,但是编写XACML策略需要一些经验。我们正在使用WSO IS和APIM。
我不会说RBAC是ABAC的子集。从功能角度来看确实是这样。但这不是二选一的问题。ABAC将通过引入更多属性、策略和前述架构来扩展RBAC。
我的身份验证服务器(IS)中有管理员、所有者和成员角色。
- 管理员可以查看、删除和更新用户。
- 所有者可以查看和更新。
- 成员只能查看。
这很好。你正在定义你的授权要求。这些将直接映射到你的ALFA / XACML策略中。
目前,我正在使用HTTP动词来实现所需的结果,即所有者无法访问DELETE请求,成员无法访问PUT和DELETE。
在 ABAC 中,我们也使用操作。这些可以是普通的人类操作(查看、编辑、删除、批准...),然后可以映射到 HTTP 动词。
您的挑战
在下面的文本中,我以粗体标记了我认为是您额外授权要求的内容。
我有一个仪表板,在其中显示不同的部分,如顶级用户、计费、服务、顶级消费者等。
我需要根据用户角色和服务器属性填充导航栏,例如
成员不应该访问导航栏中的其他用户(添加、列表)。导航栏项目取决于用户角色,因此我们可以通过 RBAC 管理它们?
这将通过 ABAC 策略处理。请参见下文
我们计划添加运营、市场营销、支持等角色。这是否意味着我们需要创建单独的数据库模式来维护每个角色的访问权限?
不!您不应该在自定义构建系统中创建新的 DB 模式,更不用说维护访问权限。使用策略即可做到这一点。
在仪表盘中,我需要隐藏/显示用户、服务等的视图、更新和删除按钮。现在成员可以看到用户,但没有权限更新或删除他们。他们无法查看统计数据、账单和其他私人信息。所有者可以看到与其部门/组织相关的所有用户,但管理员可以看到所有部门/组织的所有用户。在这里,我们需要为所有消费者使用相同的API,但API应对不同的角色有不同的响应。角色可以是10个或100个,因此我们不能为每个角色创建不同的API。
问题:我们可以通过RBAC实现所有这些场景,但是为了管理导航栏和视图相关的实现,我们需要在服务器端添加业务逻辑,而不是使用WSO2-IS和WSO2-APIM。是否有一种方法来管理视图权限,例如隐藏/显示按钮和部分,甚至使用相同的API,但它应该为不同的API消费者返回不同的结果。
答案:是的,当然。这就是使用ABAC和策略的目的。鉴于您正在使用WSO2 IS,请查看该产品内部的PDP Balana。还有其他解决方案,例如AuthZForce(开源)或Axiomatics(我所在的公司)。
这是一个用ALFA编写的示例策略,以下是XACML翻译。
namespace haris {
policyset users {
target clause axiomatics.objectType == "user record"
apply firstApplicable
policy viewUser {
target clause axiomatics.actionId == "view"
apply firstApplicable
rule administrator{
target clause axiomatics.user.role == "administrator"
permit
}
rule owners{
target clause axiomatics.user.role == "owner"
permit
condition axiomatics.user.department == axiomatics.record.department
}
rule member{
permit
condition axiomatics.user.username == axiomatics.record.owner
}
}
policy updateUser {
target clause axiomatics.actionId == "update"
apply firstApplicable
rule administrator{
target clause axiomatics.user.role == "administrator"
permit
}
rule owner{
target clause axiomatics.user.role == "owner"
permit
}
}
policy deleteUser {
target clause axiomatics.actionId == "delete"
apply firstApplicable
rule administrator{
target clause axiomatics.user.role == "administrator"
permit
}
}
}
}
而且还有XML版本
<?xml version="1.0" encoding="UTF-8"?>
<xacml3:PolicySet
PolicyCombiningAlgId="urn:oasis:names:tc:xacml:1.0:policy-combining-algorithm:first-applicable"
PolicySetId="http://axiomatics.com/alfa/identifier/haris.users"
Version="1.0"
xmlns:xacml3="urn:oasis:names:tc:xacml:3.0:core:schema:wd-17">
<xacml3:Description>User Records</xacml3:Description>
<xacml3:PolicySetDefaults>
<xacml3:XPathVersion>http://www.w3.org/TR/1999/REC-xpath-19991116
</xacml3:XPathVersion>
</xacml3:PolicySetDefaults>
<xacml3:Target>
<xacml3:AnyOf>
<xacml3:AllOf>
<xacml3:Match
MatchId="urn:oasis:names:tc:xacml:1.0:function:string-equal">
<xacml3:AttributeValue
DataType="http://www.w3.org/2001/XMLSchema#string">user record</xacml3:AttributeValue>
<xacml3:AttributeDesignator
AttributeId="axiomatics.objectType"
Category="urn:oasis:names:tc:xacml:3.0:attribute-category:resource"
DataType="http://www.w3.org/2001/XMLSchema#string"
MustBePresent="false" />
</xacml3:Match>
</xacml3:AllOf>
</xacml3:AnyOf>
</xacml3:Target>
<xacml3:Policy
PolicyId="http://axiomatics.com/alfa/identifier/haris.users.viewUser"
RuleCombiningAlgId="urn:oasis:names:tc:xacml:1.0:rule-combining-algorithm:first-applicable"
Version="1.0">
<xacml3:Description>View user record</xacml3:Description>
<xacml3:PolicyDefaults>
<xacml3:XPathVersion>http://www.w3.org/TR/1999/REC-xpath-19991116
</xacml3:XPathVersion>
</xacml3:PolicyDefaults>
<xacml3:Target>
<xacml3:AnyOf>
<xacml3:AllOf>
<xacml3:Match
MatchId="urn:oasis:names:tc:xacml:1.0:function:string-equal">
<xacml3:AttributeValue
DataType="http://www.w3.org/2001/XMLSchema#string">view</xacml3:AttributeValue>
<xacml3:AttributeDesignator
AttributeId="axiomatics.actionId"
Category="urn:oasis:names:tc:xacml:3.0:attribute-category:action"
DataType="http://www.w3.org/2001/XMLSchema#string"
MustBePresent="false" />
</xacml3:Match>
</xacml3:AllOf>
</xacml3:AnyOf>
</xacml3:Target>
<xacml3:Rule Effect="Permit"
RuleId="haris.users.viewUser.administrator">
<xacml3:Description>Administrators can view all users
</xacml3:Description>
<xacml3:Target>
<xacml3:AnyOf>
<xacml3:AllOf>
<xacml3:Match
MatchId="urn:oasis:names:tc:xacml:1.0:function:string-equal">
<xacml3:AttributeValue
DataType="http://www.w3.org/2001/XMLSchema#string">administrator</xacml3:AttributeValue>
<xacml3:AttributeDesignator
AttributeId="axiomatics.user.role"
Category="urn:oasis:names:tc:xacml:1.0:subject-category:access-subject"
DataType="http://www.w3.org/2001/XMLSchema#string"
MustBePresent="false" />
</xacml3:Match>
</xacml3:AllOf>
</xacml3:AnyOf>
</xacml3:Target>
</xacml3:Rule>
<xacml3:Rule Effect="Permit"
RuleId="haris.users.viewUser.owners">
<xacml3:Description>Owners can view users in their department
</xacml3:Description>
<xacml3:Target>
<xacml3:AnyOf>
<xacml3:AllOf>
<xacml3:Match
MatchId="urn:oasis:names:tc:xacml:1.0:function:string-equal">
<xacml3:AttributeValue
DataType="http://www.w3.org/2001/XMLSchema#string">owner</xacml3:AttributeValue>
<xacml3:AttributeDesignator
AttributeId="axiomatics.user.role"
Category="urn:oasis:names:tc:xacml:1.0:subject-category:access-subject"
DataType="http://www.w3.org/2001/XMLSchema#string"
MustBePresent="false" />
</xacml3:Match>
</xacml3:AllOf>
</xacml3:AnyOf>
</xacml3:Target>
<xacml3:Condition>
<xacml3:Apply
FunctionId="urn:oasis:names:tc:xacml:3.0:function:any-of-any">
<xacml3:Function
FunctionId="urn:oasis:names:tc:xacml:1.0:function:string-equal" />
<xacml3:AttributeDesignator
AttributeId="axiomatics.user.department"
Category="urn:oasis:names:tc:xacml:1.0:subject-category:access-subject"
DataType="http://www.w3.org/2001/XMLSchema#string"
MustBePresent="false" />
<xacml3:AttributeDesignator
AttributeId="axiomatics.record.department"
Category="urn:oasis:names:tc:xacml:3.0:attribute-category:resource"
DataType="http://www.w3.org/2001/XMLSchema#string"
MustBePresent="false" />
</xacml3:Apply>
</xacml3:Condition>
</xacml3:Rule>
<xacml3:Rule Effect="Permit"
RuleId="haris.users.viewUser.member">
<xacml3:Description>Members can view their own user record only
</xacml3:Description>
<xacml3:Target />
<xacml3:Condition>
<xacml3:Apply
FunctionId="urn:oasis:names:tc:xacml:3.0:function:any-of-any">
<xacml3:Function
FunctionId="urn:oasis:names:tc:xacml:1.0:function:string-equal" />
<xacml3:AttributeDesignator
AttributeId="axiomatics.user.username"
Category="urn:oasis:names:tc:xacml:1.0:subject-category:access-subject"
DataType="http://www.w3.org/2001/XMLSchema#string"
MustBePresent="false" />
<xacml3:AttributeDesignator
AttributeId="axiomatics.record.owner"
Category="urn:oasis:names:tc:xacml:3.0:attribute-category:resource"
DataType="http://www.w3.org/2001/XMLSchema#string"
MustBePresent="false" />
</xacml3:Apply>
</xacml3:Condition>
</xacml3:Rule>
</xacml3:Policy>
<xacml3:Policy
PolicyId="http://axiomatics.com/alfa/identifier/haris.users.updateUser"
RuleCombiningAlgId="urn:oasis:names:tc:xacml:1.0:rule-combining-algorithm:first-applicable"
Version="1.0">
<xacml3:Description>Update user</xacml3:Description>
<xacml3:PolicyDefaults>
<xacml3:XPathVersion>http://www.w3.org/TR/1999/REC-xpath-19991116
</xacml3:XPathVersion>
</xacml3:PolicyDefaults>
<xacml3:Target>
<xacml3:AnyOf>
<xacml3:AllOf>
<xacml3:Match
MatchId="urn:oasis:names:tc:xacml:1.0:function:string-equal">
<xacml3:AttributeValue
DataType="http://www.w3.org/2001/XMLSchema#string">update</xacml3:AttributeValue>
<xacml3:AttributeDesignator
AttributeId="axiomatics.actionId"
Category="urn:oasis:names:tc:xacml:3.0:attribute-category:action"
DataType="http://www.w3.org/2001/XMLSchema#string"
MustBePresent="false" />
</xacml3:Match>
</xacml3:AllOf>
</xacml3:AnyOf>
</xacml3:Target>
<xacml3:Rule Effect="Permit"
RuleId="haris.users.updateUser.administrator">
<xacml3:Description>Administrator can update any user
</xacml3:Description>
<xacml3:Target>
<xacml3:AnyOf>
<xacml3:AllOf>
<xacml3:Match
MatchId="urn:oasis:names:tc:xacml:1.0:function:string-equal">
<xacml3:AttributeValue
DataType="http://www.w3.org/2001/XMLSchema#string">administrator</xacml3:AttributeValue>
<xacml3:AttributeDesignator
AttributeId="axiomatics.user.role"
Category="urn:oasis:names:tc:xacml:1.0:subject-category:access-subject"
DataType="http://www.w3.org/2001/XMLSchema#string"
MustBePresent="false" />
</xacml3:Match>
</xacml3:AllOf>
</xacml3:AnyOf>
</xacml3:Target>
</xacml3:Rule>
<xacml3:Rule Effect="Permit"
RuleId="haris.users.updateUser.owner">
<xacml3:Description>Owner can update any user</xacml3:Description>
<xacml3:Target>
<xacml3:AnyOf>
<xacml3:AllOf>
<xacml3:Match
MatchId="urn:oasis:names:tc:xacml:1.0:function:string-equal">
<xacml3:AttributeValue
DataType="http://www.w3.org/2001/XMLSchema#string">owner</xacml3:AttributeValue>
<xacml3:AttributeDesignator
AttributeId="axiomatics.user.role"
Category="urn:oasis:names:tc:xacml:1.0:subject-category:access-subject"
DataType="http://www.w3.org/2001/XMLSchema#string"
MustBePresent="false" />
</xacml3:Match>
</xacml3:AllOf>
</xacml3:AnyOf>
</xacml3:Target>
</xacml3:Rule>
</xacml3:Policy>
<xacml3:Policy
PolicyId="http://axiomatics.com/alfa/identifier/haris.users.deleteUser"
RuleCombiningAlgId="urn:oasis:names:tc:xacml:1.0:rule-combining-algorithm:first-applicable"
Version="1.0">
<xacml3:Description>Delete user</xacml3:Description>
<xacml3:PolicyDefaults>
<xacml3:XPathVersion>http://www.w3.org/TR/1999/REC-xpath-19991116
</xacml3:XPathVersion>
</xacml3:PolicyDefaults>
<xacml3:Target>
<xacml3:AnyOf>
<xacml3:AllOf>
<xacml3:Match
MatchId="urn:oasis:names:tc:xacml:1.0:function:string-equal">
<xacml3:AttributeValue
DataType="http://www.w3.org/2001/XMLSchema#string">delete</xacml3:AttributeValue>
<xacml3:AttributeDesignator
AttributeId="axiomatics.actionId"
Category="urn:oasis:names:tc:xacml:3.0:attribute-category:action"
DataType="http://www.w3.org/2001/XMLSchema#string"
MustBePresent="false" />
</xacml3:Match>
</xacml3:AllOf>
</xacml3:AnyOf>
</xacml3:Target>
<xacml3:Rule Effect="Permit"
RuleId="haris.users.deleteUser.administrator">
<xacml3:Description>Administrator can delete any user
</xacml3:Description>
<xacml3:Target>
<xacml3:AnyOf>
<xacml3:AllOf>
<xacml3:Match
MatchId="urn:oasis:names:tc:xacml:1.0:function:string-equal">
<xacml3:AttributeValue
DataType="http://www.w3.org/2001/XMLSchema#string">administrator</xacml3:AttributeValue>
<xacml3:AttributeDesignator
AttributeId="axiomatics.user.role"
Category="urn:oasis:names:tc:xacml:1.0:subject-category:access-subject"
DataType="http://www.w3.org/2001/XMLSchema#string"
MustBePresent="false" />
</xacml3:Match>
</xacml3:AllOf>
</xacml3:AnyOf>
</xacml3:Target>
</xacml3:Rule>
</xacml3:Policy>
</xacml3:PolicySet>
执行策略
对于不同的角色/用户,我如何为单个API返回不同的数据?
假设您有一个API,例如 /api/profiles/{profileID}
。您可以使用以下两种方式来使用API:
- GET /api/profiles 将返回用户有权查看的所有配置文件
- GET /api/profiles/123 如果用户有权查看,则返回配置文件123,否则返回HTTP 403(或404 - 您可以认为您甚至不想透露该配置文件确实存在)。
要做到这一点,您需要实现一个策略实施点(PEP)。这可以是WSO2的API Manager。PEP负责:
- 解析传入的API调用(GET /api/profile/123)
- 将其转换为授权请求,例如:Alice是否可以查看配置文件123?
- 将请求发送给PDP
- 处理从PDP收到的响应 - 特别是提取决策(例如允许)。
如果决策是允许,则呼叫将转发到您的后端API。如果不是,则可以按照之前讨论的返回HTTP 403/404。
如果是403,则呼叫确实会传递到后端,最终从您的后端返回响应并通过PEP进行处理,在那里它可以再次调用PDP,例如以删除数据为例。
“我是否需要在服务器中涉及业务逻辑,例如获取导航栏项目、获取API使用情况统计信息、管理员的完全数据访问权限以及所有者和成员的组织/部门受限数据?如何执行这些基本操作?”
不需要。在构建菜单或导航项时,您还可以调用PDP并询问给定用户是否可以访问给定的功能集,例如“Alice是否可以查看导航栏项目#123?”您需要最少的业务逻辑来调用PDP。