learn-tech/专栏/周志明的架构课/25_授权(下):系统如何确保授权的结果可控?.md
2024-10-16 06:37:41 +08:00

12 KiB
Raw Blame History

                        因收到Google相关通知网站将会择期关闭。相关通知内容
                        
                        
                        25 _ 授权(下):系统如何确保授权的结果可控?
                        你好,我是周志明。今天,我们接着上一讲的话题,继续来探究关于授权的第二个核心问题:系统如何确保授权的结果可控?

在上节课的开篇我提到了授权的结果是用于对程序功能或者资源的访问控制Access Control并且也给你介绍了一种最为常用的权限控制模型RBAC基于角色的访问控制Role-Based Access Control

那么这节课我就来和你聊聊这种访问控制模型的概念、原理和一些要注意的问题。希望你能在理解了RBAC是如何运作的之后将其灵活运用在自己实际工作中关于功能、数据权限的管理上而且这也是为后面学习Kubernetes的权限控制、服务安全等内容提前做的铺垫工作。

接下来我们就从RBAC的几个基础概念开始学起吧。

RBAC的基础概念

首先我们要明确所有的访问控制模型实质上都是在解决同一个问题User拥有什么权限Authority去操作Operation哪些资源Resource

这个问题初看起来并不太难一种直观的解决方案就是在用户对象上设定一些权限当用户使用资源时检查是否有对应的操作权限即可。很多著名的安全框架比如Spring Security的访问控制本质上就是支持这么做的。

不过,这种把权限直接关联在用户身上的简单设计,在复杂系统上确实会导致一些比较繁琐的问题。

你可以试想一下,如果某个系统涉及到成百上千的资源,又有成千上万的用户,一旦两者搅合到一起,要为每个用户访问每个资源都分配合适的权限,就必定会导致巨大的操作量和极高的出错概率。

而这也正是RBAC所关注的核心问题。

RBAC模型在业界有很多种说法其中最具系统性且得到了普遍认可的说法是美国乔治梅森George Mason大学信息安全技术实验室提出的RBAC96模型。

为了避免对每一个用户设定权限RBAC将权限从用户身上剥离改为绑定到“角色”Role“权限控制”这项工作就可以具体化成针对“角色拥有操作哪些资源的许可”这个逻辑表达式的值是否为真的求解过程。

这个逻辑表达式中涉及的关键概念有用户、角色、资源等我画了张图你可以参考图中展示的RBAC主要元素之间的关系

其中你可能发现了除了前面提到的用户、角色和资源以外图上还出现了一个新的名词“许可”Permission

许可其实是抽象权限的具象化体现。权限在RBAC系统中的含义是“允许何种操作作用于哪些资源之上”这句话的具体实例即为“许可”。

提出许可这个概念的目的,其实跟提出角色的目的是完全一致的,只是许可会更抽象。角色为的是解耦用户与权限之间的多对多关系,而许可为的是解耦操作与资源之间的多对多关系。比如说,不同的数据都能够有增、删、改等操作,而如果把操作与数据搅和在一起,也会面临前面我提到的权限配置膨胀的问题。

不过现在,你可能快被这些概念、逻辑给绕晕了。没事儿,我再给你举个更具体的例子,帮你理清这一堆名词之间的关系。

想像一下某个论文管理系统的UserStory中与访问控制相关的Backlog可能会是这样描述的

Backlog周同学User是某SCI杂志的审稿人Role职责之一是在系统中审核论文Authority。在审稿过程Session当他认为某篇论文Resource达到了可以公开发表的标准时就会在后台点击“通过”按钮Operation来完成审核。

所以在这个Backlog中“给论文点击通过按钮”就是一种许可它是“审核论文”这项权限的具象化体现。现在你是不是就清楚一些了

另外我还想强调的是采用RBAC的角色、资源等概念不仅是为了简化配置操作通过设定这些概念之间的关系与约束还是很多关键的安全原则和设计原则的实现基础。下面我们就从计算机安全中的“最小特权原则”Least Privilege开始来了解一下吧。

RBAC的概念间关系

在RBAC模型中角色拥有许可的数量是根据完成该角色工作职责所需的最小权限所赋予的。

最典型的例子是操作系统权限管理中的用户组。即根据对不同角色的职责分工如管理员Administrator、系统用户System、验证用户Authenticated Users、普通用户Users、来宾用户Guests分配其各自的权限。这样就既保证了用户能够正常工作也避免了用户出现越权操作的风险。

而当用户的职责发生变化时,在系统中就体现为它所隶属的角色被改变,比如将“普通用户角色”改变为“管理员角色”,就可以迅速让该用户具备管理员的多个细分权限,降低权限分配错误的风险。

另外RBAC还允许定义不同角色之间的关联与约束关系以此进一步强化它的抽象描述能力。

比如说不同的角色之间可以有继承性典型的就是RBAC-1模型的角色权限继承关系。

我举个例子。如果要描述开发经理应该和开发人员一样具有代码提交的权限,描述开发人员应该和任何公司的员工一样具有食堂就餐的权限,那么我们就可以直接把食堂就餐的权限赋予到公司员工的角色上,把代码提交的权限赋予到开发人员的角色上,再让开发人员的角色从公司员工派生,开发经理的角色从开发人员中派生即可。

另外不同的角色之间也可以具有互斥性典型的就是RBAC-2模型的角色职责分离关系。互斥性要求当权限被赋予角色时、或角色被赋予用户时应该遵循的强制性职责分离规定。

我举个例子。角色的互斥约束可以限制同一用户,只能分配到一组互斥角色集合中至多一个角色,比如不能让同一名员工既当会计,也当出纳,否则资金安全无法保证。而角色的基数约束可以限制某一个用户拥有的最大角色数目,比如不能让同一名员工全部包揽产品、设计、开发、测试等工作,否则产品质量无法保证。

OK现在我们就了解了通过RBAC建立的用户、角色等概念并且也定义了它们之间的关联与约束关系其实这些都属于RBAC中“Role Based”范畴的内容而RB只是手段是为了AC这个目的服务的。

所以接下来我们就一起来看看“Access Control”范畴的内容也就是RBAC的访问控制。

RBAC的访问控制

建立访问控制模型的基本目的就是为了管理垂直权限和水平权限。垂直权限即功能权限,比如前面提到的审稿编辑有通过审核的权限、开发经理有代码提交的权限、出纳有从账户提取资金的权限,这一类某个角色完成某项操作的许可,都可以直接翻译为功能权限。

由于实际应用与权限模型具有高度对应的关系因此把权限从具体的应用中抽离出来放到通用的模型中是相对容易的Spring Security、Apache Shiro等权限框架就是这样的抽象产物大多数系统都能采用这些权限框架来管理功能权限。

那么与此相对要管理水平权限也就是数据权限的话则要困难得多。比如用户A、B都属于同一个角色但它们各自在系统中产生的数据完全有可能是私有的A访问或删除了B的数据也照样属于越权。

一般来说,数据权限是很难抽象与通用的,仅在角色层面进行控制并不能满足全部业务的需要。很多时候,数据权限必须具体到用户,甚至具体管理到发生数据的某一行、某一列之上,因此数据权限基本上只能由信息系统自主来完成,并不存在能放之四海皆准的通用数据权限框架。

Spring Security的RBAC实现

在课程后面要介绍的“不可变基础设施”的模块里其中要讲解的一个“重要角色”Kubernetes也是完全遵循RBAC模型来进行服务访问控制的。Fenixs Bookstore所使用的Spring Security也参考了但并没有完全遵循RBAC来设计它的访问控制功能所以这里我就以Spring Security为例给你简要介绍一下RBAC的实现。

在Spring Security的设计里用户和角色都可以拥有权限比如在它的HttpSecurity接口就同时有着hasRole()和hasAuthority()方法如果你是刚接触Spring Security的设计的话可能会混淆它们之间的关系。那么下面我们就直接来看看Spring Security的访问控制模型是长什么样子的你也可以去对比一下前面的RBAC的关系图

从实现角度来看Spring Security中Role和Authority的差异很小它们完全共享同一套存储结构唯一的差别就只是Role会在存储时自动带上“ROLE_”前缀罢了。

但从使用角度来看Role和Authority的差异可以很大用户可以自行决定系统中到底Permission只能对应到角色身上还是可以让用户也拥有某些角色中没有的权限。

你应该会觉得这一点好像不符合RBAC的思想但我个人认为这是一种创新而非破坏在Spring Security的文档上也说的很清楚这取决于你自己如何使用。

The core difference between these two指Role和Authority is the semantics we attach to how we use the feature. For the framework, the difference is minimal and it basically deals with these in exactly the same way.

这样我们通过RBAC就很容易控制最终用户在广义和精细级别上能够做什么我们可以指定用户是管理员、专家用户或者只是普通用户并使角色和访问权限与组织中员工的身份职位保持一致仅根据需要为员工完成工作的最低限度来分配权限。

这些都是人们通过设计大量的软件系统、长时间积累下来的实践经验,将这些经验运用在软件产品上,绝大多数情况下都要比自己发明创造一个新的轮子更加安全。

小结

针对如何确保授权的结果可控的问题这节课我们学习了一种最常用的解决方案基于角色的访问控制RBAC

其中在Role-Based部分我通过一些例子给你介绍了以角色为中心的一系列概念以及这些概念之间的关系与约束在Access Control部分我还介绍了垂直和水平权限的控制的差异也以Spring Security为例带你了解了它的大致运作过程。你需要记住以下几个核心要点

所有的访问控制模型实质上都是在解决同一个问题User拥有什么权限Authority去操作Operation哪些资源Resource。 为避免对每一个用户设定权限RBAC提出了角色和许可等概念角色为的是解耦用户与权限之间的多对多关系而许可为的是解耦操作与资源之间的多对多关系。 建立访问控制模型的基本目的就是为了管理垂直权限和水平权限。垂直权限即功能权限,水平权限则是数据权限,它很难抽象与通用。

一课一思

你是否使用过RBAC或者是其他权限控制模型你是自己实现的还是基于现成框架实现的

欢迎在留言区分享你的答案。如果觉得有收获,也欢迎你把今天的内容分享给其他的朋友。感谢你的阅读,我们下一讲再见。