结论

数字化系统的授权机制,一共有好几十种。对于企业内部系统来说,我极力推荐 ABAC

别再使用 RBAC 了! ABAC,应用尽用。

认证

尽管认证和授权是两回事,但总是成对出现。而对企业的数字化系统来说,认证又分为对外认证和对内认证,或者说是对最终用户认证和对内部员工认证。我本以为对公司来说,外部用户是最重要的,所以对外认证要比对内认证更加复杂,因为对内认证往往怎么简单怎么来,事实上,很多企业还真的是这样做的。然而出乎我的意料,对内认证其实更加复杂,原因是对外认证往往是单一场景,而对内认证却是多场景。

image.png

一般来说,对外认证就是一个登录场景,没有太多的访问控制,即要么是非登录态,只能访问少量公开资源;要么是登录态,可以访问所有资源。但是对内认证的场景多样,其访问控制机制也相应地纷繁复杂。以下详解几个常见的访问控制机制。

授权/访问控制模型

授权,也叫访问控制,都是做允许或者禁止某个用户做某件事情的决定。一个最高层次的抽象模型图示意如下:

image.png

  • 主体,是请求的发起者。可以是用户、也可以是进程、应用、设备等。
  • 客体,是请求的接收方。可以是一个 API、一个文件、一个数据库等资源。
  • 请求,是主体对客体进行的操作,比如读、写、执行等。

常见的访问控制机制

业界上的访问控制机制特别多,这里列举几个常见的,并在后面对比一下它们的优缺点。

  • **ACL **(Access Control Lists),访问控制列表。需要管理员为每个资源(客体)显式分配权限。
  • **RBAC **(Role-Based Access Control),基于角色的访问控制。于 2000 年开始流行,它定义了一系列的角色与权限之间的关系。
  • GBAC (Group-Based Access Control),可以维护具有层级关系的群组权限。
  • DAC (Discretionary Access Control),自主访问控制。让资源(客体)所有者来定义访问控制规则。
  • MAC (Mandatory Access Control),强制访问控制。基于安全级别标签的访问控制策略,其安全性最高。
  • Claims as Permissions,基于声明的访问控制。很多企业或组织都在某种形式上使用了这种机制。
  • ABAC (Attribute-Based Access Control policy),基于属性的访问控制策略,它不将访问权限直接赋予给用户,而且通过评估一些布尔规则来为资源(客体)授予访问权限。

ACL

这是一种比较古老的权限控制机制,它是面向资源的访问控制模型。管理员为每个资源(客体)分配权限列表,这个列表里记录了用户/角色对于资源的操作权限,当需要访问这些资源时,会首先检查访问控制列表中是否存在当前用户/角色的访问权限,如果存在,允许相应的操作,否则就拒绝相应的操作。
image.png
ACL 的核心思路是将某个对象的某种权限授予某个用户或者某个角色,它们之间的关系是多对多。

好处

  • 实施起来最简单

坏处

  • 一旦要修改安全策略或者需要审计,就意味着需要遍历大量的资源;
  • 应用开发者必须保证所有的资源在创建出来开始就有合适的保护措施。

RBAC

基于角色的访问控制,应用特别广泛。它是防止权限泛滥,实现最小特权原则的经典解决方案。RBAC 将用户按角色分类,通过用户的角色来确定用户对某项资源是否具备操作权限,它简化了用户与权限的管理,将用户与角色关联,角色与权限关联,然后权限与资源关联。
image.png

image.png

好处

  • 比 ACL 更具扩展性
  • 在粗粒度的访问控制中工作得特别好
    比如这样的场景:拥有经理角色的用户可以批准采购单。

坏处

  • 随着组织的演进,往往出现角色爆炸的现象;
    比如在一开始,一个销售的角色可以访问客户记录,这很合理。随着组织的扩张,开始组建按地域划分的销售团队,于是对客户记录的访问也需要按照地域来进行限制,这就导致系统中分别增加了美洲区的销售角色和亚太区的销售角色。
  • 当管理员更新用户的权限时,需要大量的手工操作;
  • 做不到细粒度的访问控制;
    比如这样的场景就做不到:经理只能批准其部门产生的采购单。
    为了解决这种场景下的问题,应用开发者需要在应用里写额外的代码来做相应的检查,这导致了一个访问控制被分别定义在了两个不同的地方。从而导致了
    • 安全管理成本变高
    • 合规和审计变得困难
    • 安全策略缺少单一视图
  • 资源与角色紧藕合,改一个角色会影响多个资源

GBAC

基于群组的访问控制机制。看上去和 RBAC 很像,但是 GBAC 可以用来对一个或多个具有层级关系的群组来定义访问资源的权限。它允许将某个群组的访问权限继承到其下级群组中,当然,也可以选择不去继承。
image.png

好处

  • 很适合用于公司的组织架构权限

坏处

同 RBAC。

  • 另外,如果公司的组织结构关系维护在别的系统中(比如 Azure AD 、SAP 或者企业微信中),那么容易造成群组关系维护困难(一个改变需要同步好几个系统)

DAC

自主访问控制,让客体(资源)的所有者来定义访问控制规则。它是 Trusted Computer System Evaluation Criteria (TCSEC)定义的和一种访问控制机制,在 DAC 中,系统会根据被操作对象的权限控制列表中的信息,来决定当前用户能够对其进行哪些操作,用户可以将其具备权限直接或者间接授予其他用户。

比如百度网盘的资源上传者,需要将文件分享给他人时,就可以定义是对所有人公开,还是只对百度网盘用户公开,还是只对知道密码的人公开等等,并且可以定义对哪些人只读,对哪些人可以修改等等权限。
image.png

好处

  • 灵活
  • 维护成本低
  • 降低了管理员的工作难度

坏处

  • 增强了整体访问控制监管的难度
  • 安全性没有保证,完全取决于所有者的个人安全意识

MAC

强制访问控制,通过定义安全级别标签来进行访问控制,也叫非自主访问控制,它可以限制主体对资源(客体)执行某种操作。它的安全策略由安全策略管理员集中控制,用户无权覆盖策略。比如为了保证机密性,MAC 不允许低级别的主体读取高级别的客体、不允许高级别的主体写入低级别的客体;为了保证完整性,MAC 不允许高级别的主体读取低级别的客体,不允许低级别的主体写入高级别的客体。一般普通公司不会采取 MAC,除非有相应的合规要求。

好处

  • 非常安全

坏处

  • 对实施要求很高
  • 需要对所有数据进行标记

Claims as Permissions

基于声明式的权限管理。这常常和 RBAC 结合使用,以弥补 RBAC 在细粒度的访问控制中的不足。如果我们想给 HR 部门的 Sally 一个临时的权限,来帮助用户 Bob 来申报采购单,可以声明式地为 Sally 直接添加特殊的权限,如: json { sub: 1234567890, name: Sally, role: manager, department: personal, canRaiseAPurchaseOrder: true, maxValueForPurchaseOrder: 1000, }

好处

  • 非常灵活

坏处

  • 难以审计
  • 难以验证正常的人拥有正确的权限
  • 需要重新变动人员组织和责任时,需要手动流程
  • 管理员倾向于添加越来越多的权限,但很少移除它们
  • 决策数据定义在安全系统中,又被复制到其他的系统中,容易导致不一致发生
  • 对于采用了 OAuth 或者 OpenID 单点登录的方案,在用户的令牌中携带全量用户权限,容易出现体积非常大的访问令牌
  • 在用户身份声明中携带权限信息,导致认证和授权含混在一起

声明与应用逻辑混合方案

以上几种访问控制机制都有如下特征:

  • 静态规则
  • 手动管理权限
  • 审计成本高
  • 适应组织的变化成本高

对基于声明式的权限管理进行改进,就得到了声明与应用逻辑混合起来的方案,如:

javascript { sub: 1234567890, name: John Doe, role: manager, department: sales }

var maxPo = FindMaxPoValue(department) If ( role ==‘manager’ && poTotal < maxPo )

这样就规避了从原始系统复制决策数据到用户令牌中的问题,而是从原始系统去获取数据。如果 John 从一个部门转移到了另一个部门,其采购单的金额上限会从新的部门中获取。

好处

  • IT 管理员只需要管理身份
  • 访问控制决策从信息源头获取,而不是在访问控制系统中的拷贝。

坏处

  • 不容易审计:审计员需要读应用代码
  • 更新访问控制逻辑需要重新部署应用
  • 认证和授权仍然混在一起,没能做到关注点分离

ABAC

看了以上种种机制,各有优缺点。那么有没有一个完美的授权机制呢?我们开始呼唤这样的访问控制解决方案:

  • 能够地从组织内部自然获取到的信息来做访问控制决策
  • 没有额外的管理成本
  • 可以在不需要部署应用的情况下更改这个决策
  • 所有的利益相关者都能阅读
  • 易于审计

这样的访问控制解决方案真的存在吗?其实 ABAC 就是这样的一种解决方案。它是基于属性的访问控制,有时也被称为 PBAC (Policy-Based Access Control)。它不给用户直接赋予访问权限,而是通过执行一系列的布尔规则来为资源授权(动态计算一个或者一组属性是否满足某一条件来进行授权)。ABAC 中一般来说包含用户属性、环境属性、操作属性以及资源属性。比如,以下是一个表达门禁访问权限的伪代码:

如果当前时间在 8 点到 18 点之间,并且用户拥有员工角色

驱动这些规则的数据被称为属性,可以从任何地方获得,而不局限于身份声明。比如当前时间(环境属性)、资源拥有者(资源属性)等等。
image.png
image.pngimage.png
ABAC 和所有之前介绍过的机制都不同,当安全需求变化时,ABAC 不需要手动调整具体权限。它只需要设定好策略逻辑,就能使得所有资源的访问控制都立即生效。因此,ABAC 是一种抽象程度更高的机制。它不从单一安全系统中获取决策属性,而是可以从组织中的任何地方获取。

其实 ABAC 也存在很多年了,NIST 组织对 ABAC 做了正式的定义,这个正式的定义包含如下组件:

  • 策略实施点(PEP),在资源服务器处提供不同的环境来实施授权决策。
    image.png
  • 策略决策点(PDP),提供分布式策略决策点。授权请求被发送到此处,策略在这里根据请求的权限来评估。
  • 策略访问点(PAP),通常是一组 UI 管理界面,用来管理资源服务器、资源、范围、权限和策略。
    image.png
  • 策略信息点(PIP),当评估授权策略时从运行环境中的身份声明里获取属性。

当需要决定允许还是拒绝一个请求时,应用代码与 PEP 交互。PEP 构建了请求的上下文,并询问 PDP 的决定结果。而 PDP 从 PAP 处拉取策略,并使用上下文中的属性以及从 PIP 获取额外的属性,来对请求进行评估。从而,PAP 可以在策略存储中响应变化,而不需要重新部署应用。
image.png
很多 ABAC 解决方案基于 OASIS XACML 架构,安全专家通过 XML 来定义访问控制策略。但是除此之外,还有另外的领域特定语言(DSL)可以用来定义访问控制策略,比如 ALFA,大致长这样: java namespace AcmeCorp.DoorPolicy { import Oasis.Attributes

policy buildingAccess { target clause ResourceType == door apply denyUnlessPermit

 // Employees can open the door during office hours only
 rule openMainDoor
 {
   target clause Resource == mainDoor and
                 Action == open
   permit
   condition Subject.Role == employee and
             CurrentTime >= 08:00:00:time and
             CurrentTime < 18:00:00:time
  }
}

}

ALFA 的目标是希望几乎所有人都能阅读和验证策略的意图。使用领域特定语言(DSL)编写安全策略,所有审计员以及业务利益相关方都可以根据组织的职责贡献和验证安全策略并演进。如果觉得学习一门新的 DSL 也是成本,那么有些解决方案(比如知名开源身份与访问管理系统 Keycloak)还直接采用了广泛使用的 JavaScript 来做为策略 DSL。 javascript const context = $evaluation.getContext(); const contextAttributes = context.getAttributes();

if (contextAttributes.containsValue(kc.client.network.ip_address, 127.0.0.1)) { $evaluation.grant(); }

好处

拥有我们所呼唤的所有特性,即

  • 能够地从组织内部自然获取到的信息来做访问控制决策
  • 没有额外的管理成本
  • 可以在不需要部署应用的情况下更改这个决策
  • 所有的利益相关者都能阅读
  • 易于审计

坏处

  • 比较复杂
  • 实施难度较大
  • DSL 的学习曲线

总结

应用主要就是为用户交付功能而设计的,但是一般不是所有用户都能在应用中干所有事情。比如应用中有的特性是保密的,有些需要用户有更高级的订阅(付费)等等。交付这些限制性的功能,同样是应用设计中的关键部分。本文探索了控制访问功能的常见机制,对比了其优缺点,并且极力推荐在企业的内部系统中,采用 ABAC 方案。

参考资料