对云环境下访问控制系统的思考

背景

现在,云计算市场已是一片红海,不论是国内还是国外的云计算市场竞争都相当激烈。主流的云计算厂商在争夺企业客户方面都不留余地,因为企业用户对云计算的发展有着极为重要的意义,尤其是大企业客户。可以毫不夸张的说,没有企业用户,云计算的发展绝不会发展的如此迅速。

企业上云首当其冲的问题就是安全性,安全性已经成为企业上云最大的障碍。这里的安全性不光是基础设施的安全和稳定,比如虚拟机的高可用、RDS的高可靠等等,也包括应用层面的安全性,如WAF、证书服务、加密服务等等,还包括因为企业本身的IT架构/研发架构的复杂性带来的资源管控方面的安全性需求。毫不夸张地说,谁解决好了企业的安全性诉求,那么他就能在这片红海中立于不败之地。

安全是一个很大的话题,我不敢妄谈。最近我在做访问控制方面的工作,故此分享一下我对这个领域的一点思考。访问控制是安全中一块,也是十分重要的一块。有些云计算提供商甚至都没有将其划归到安全的范围,可能是没有意识到访问控制的重要性。AWS中访问控制的产品是IAM,可以说是云计算厂商中做的最早也最为完善的一个。IAM在其的产品分类中有一个词我觉得形容该产品最为合适——“合规性“。其实访问控制就是满足企业用户对于合规性的需求,说白了就是规范企业用户对云计算资源的访问。

既然这是一篇关于访问控制的文章,那么我们先来看看关于访问控制的定义。

维基百科关于访问控制的定义是:访问控制是指允许或者禁止某人使用某项资源的能力。这个定义中有几个关键点需要留意:

  1. 某项资源
  2. 允许/禁止
  3. 能力

虽说维基百科关于访问控制的定义略显简陋,但是这个定义我觉得已经勾勒出了访问控制系统的大致形态。首先是人,访问控制的主体是人,所以其最为重要的使用群体是用户,那就是说这个系统是一个面向用户的系统。其次是某项资源,资源是访问控制的客体,某项的限定词则表明资源的具体形式是未知的。再次是允许/禁止,这是访问控制对外提供服务的最为直观的表现形式,用一个更为专业的名称来形容的话就是“鉴权”。最后是能力,为什么我把能力专门拿出来作为一个关键点来说,因为这是理论和实践的一个关键区分点之一。访问控制的理论为我们设计对应的系统和产品指明了方向,但是在生产环境中使用的还是遇到各种各样的现实问题。有一点需要特别注意的是,访问控制系统作为一个通用的公共服务,它需要提供的是一种能力,而不是针对特定环境和产品,否则只为沦为某个特定的专家系统。

维基百科关于【访问控制】的定义在理论层面已经颇为全面,然而从系统的设计到角度来看还缺少一个关键点,那就是——动作。这里的动作(可以也称之为操作)可以理解为具体系统所开放的能力,或者用户可以对系统执行的操作。例如,RDS产品需要开放createDataBase\listDataBase\deleteDatabase等等动作,又如NOS(网易对象存储)需要开放listBucket\createBucket\listObject\putObject等等动作。就算脱离云计算的环境,动作也是访问控制中不可缺少的要素之一,因为任何给人使用的产品都会伴随与人的交互,而这些交互的细粒度表现就是这些动作。

既然现在我们已经了解了访问控制的基本理论,那是否可以开始设计系统开始编码了呢?千万不要这么做,想清楚再做远比边做边想要节约时间。这听上去有点和现在的“敏捷开发“不太符合,实际上恰恰相反,”敏捷开发”虽然强调持续集成、快速迭代,但是这却是建立在前期良好的架构设计的基础之上的。言归正传,这是一篇关于访问控制实践探究的文章,在我们设计系统之前,先看看以前的访问控制系统一般是怎么做的。

传统的访问控制模型

在访问控制系统的设计中,有两种设计模式是十分重要,也是得到广泛应用的,那就是访问控制列表(ACL)和基于角色的访问控制(RBAC)。

1.访问控制列表(ACL)

访问控制列表是早期的一种访问控制技术,其原理十分简单,就是记录哪些用户对这个资源能进行哪些操作,有类似如下的二维表维护在文件中:

User Create Update Query Delete
张三 ×
李四
王五 × × ×

这种访问控制的方式好处显而易见,就是简单直观,易维护。这种设计在操作系统、路由器、交换机和工业控制系统中都得到了广泛的使用。不过,ACL的缺点也是显而易见的,那就是当用户、资源和操作组建增长时,维护这张表的代价会异常庞大,另外,这种设计模式将用户对资源的控制权限直接绑定,十分死板,灵活性不够,无法满足云环境下动态资源授权的需求。

2.基于角色的访问控制(RBAC)

基于角色的访问控制将用户按其属性进行分类构建出一个个具体的角色,而将权限授权角色,用户通过扮演角色来间接地获取对应的权限。RBAC非常适合现实环境,尤其是企业,因为使用资源的使用者一般并不是资源的拥有者,资源的所有者属于企业。在云环境中更是如此,可能使用RDS的人是公司的开发或者PE,而RDS的归属者是对应的企业。RBAC从访问控制的主体的角度出发,很好使适应了企业的组织结构,同时也将用户和权限分离开了,用户只需要通过扮演不通的角色就能获得对应的权限,这种方式解决了云环境下动态授权的权限需求。

那是否RBAC能解决我们所有的问题了?显然不是。现实的问题往往是复杂的,不会像非黑即白这样简单。RBAC将人和权限分离的方法确实解决了一部分灵活性的问题,但是也增加了使用成本,同时它对细粒度的权限控制没有很好的应对之法。

云环境下面临的挑战

现在我们也知道了主流的访问控制模型一般是怎么做的了,那么如何应用在云环境中呢?我觉得在云环境下的访问控制系统主要面临以下几个挑战:

1.资源标识的灵活性

访问控制的系统的立项一般都晚于云计算中的其他产品,因为它本身属于支撑产品。但随着其他产品形态组建完善,如何很好地描述各个产品的资源就成了一件非常令人头疼地问题。在一些IaaS的产品形态中,很大一部分是以实例(instance)的方式来提供服务的;而在某些PaaS的产品形态中,有些是实例的方式来提供服务,而又有一些有着很强的特殊性,比如上文提到的NOS,它们的资源描述是需要以树形方式来表达的。SaaS产品用统一的访问控制系统来管理一般不太可能,因为每个Software的产品形态和使用方式千差万别,你很难去做到统一。在对访问控制系统的设计过程中我发现了一个很有趣的现象,当你考虑的产品越接近应用层面(上层服务),访问控制系统就越接近专家系统。这样很好理解,越上层的服务它的特殊性越强,所以通用性越差,只能做成专家系统。

2.细粒度的权限控制

访问控制系统的有一个比较困难的点,那就是细粒度的权限控制。这一点在访问控制模型中你找不到答案,它们只是在比较宏观的层面讨论了人和权限的关系。细粒度的权限控制是现实中存在的一个需求,比如一个企业有若干台虚拟机,有一些虚拟机用作webserver,而有一些虚拟机用作数据库,还有一些作为中间件服务器,比如Zookeeper等等。而使用这些虚拟机的人各不相同,他们能看到并操作的虚拟机也应该得到严格地监管,否则可能会引起安全事故。细粒度地权限控制关键点在于“多细”,越细致地控制会导致你的系统复杂度成倍增加,不利于的系统地可维护性。我的建议是只做到实例级别,但有一个例外,那就是对象存储。能做到多细的程度很大一部分取决于第一点中你地资源标识地方式,如果你的资源描述方式得当,那么更加细粒度地访问控制并不会增加你系统地复杂度。这个我会在下文中提到。

3.身份的多样性

如果一个云计算厂商想吃下一个大客户,满足其业务架构只是其一,还有一个十分重要的条件就是满足其组织架构。大企业绝对有实力也有能力解决其本身的业务架构,其实上不上云更多地是战略性的考虑,他们更加看重云服务的稳定性、安全性和可维护性。同时,其本身的组织架构也十分复杂,要想让其没有阻力地上云,解决其员工的身份问题首当其冲。所以现在主流的云厂商都会提供多种身份的表示方式,例如:子账号、组和角色。

4.权限的描述方式

权限的描述方式也是十分重要的一个点,可以说这个点设计得好坏决定了你后期能否悠然地应对业务方的接入还是每天火急火燎地和各个业务方定协议定接口。我们知道所有需要访问控制的云产品必然有其支持的动作(Action),每个产品资源(Resource)的描述方式也各不相同,同时允许(Allow)还是禁止(Deny)针对某个资源的操作也是需要明确给出来的。这三个点构成了权限描述的三个要素。如果在前期的设计中没有充分思考这个问题,那么恭喜你,你很有可能给自己埋了一个深坑。你很有可能设计几张大表,来表示各个业务方支持的动作,资源以及用户和他们的关系。出现这样的设计是因为没有真正理解访问控制系统的业务领域。当你在设计这几张表的时候其实意味着访问控制系统在“理解”各个产品的功能,这对一个通用的访问控制系统是致命的。访问控制系统作为一个底层/共享的通用系统,对外输出地只能是能力,而不是去理解各个产品它们自己地业务领域。说到这里,我还是推荐所有的技术人员都有必要学习一下DDD的理论,就算不用自己写代码,系统性地学习其战略模式也会让你收益颇多。

5.动态的授权体系

这一点相比以上4点来说要简单,这是因为如果你的访问控制系统已经很好地解决上面的挑战,那么你也就自然而然得获得了动态的授权体系。之说以是动态的,是因为云环境下用户和权限的关系往往不是一成不变的。用户在某个时刻希望获得A授权,而在另外一个时刻又希望获得B授权,而且有时授权还带有时效性,当过了截至时间授权也就自动失效了。这种动态性的需求是真实存在的,但我认为满足这个需求依赖于针对前4点的设计,如果把前面的设计做好了,那么系统也就自然而然地满足了动态性的需求,这是一个水到渠成的过程。

业界是如何处理这个问题

说实话,当我去设计蜂巢的访问控制系统的时候并没有像现在考虑的这么全面。我意识到了一些问题的棘手性,也调研了现在业界做访问控制的方法,可以说做的最好的还是IAM
IAM将用户身份划归为子用户、组和角色,基本上这三种身份标识可以满足身份多样性的要求了。我觉得IAM关于权限描述的方式令我耳目一新,它使用了领域专用(DSL)语言来描述权限,具体的形式如下:

1
2
3
4
5
6
7
8
{
"Version": "2012-10-17",
"Statement": {
"Effect": "Allow",
"Action": "s3:ListBucket",
"Resource": "arn:aws:s3:::example_bucket"
}
}

这是我第一次接触DSL的概念,当时对这种设计模式是完全懵逼的,也不太理解其设计思想。随着考虑的问题越来越多,我发现了DSL的强大之处。因为云环境下的访问控制系统最令人头疼的问题就是资源和权限的描述方式,这种极致的灵活性很难通过设计表格来获得。因为任何的以表为中心的设计方式都会映射到某个具体的领域模型上,又因为各个业务的权限控制各不相同,难道说我要根据各个业务来建立模型?前面也说过了,这是万万不可取的,这样设计只会让你深陷无尽的加班和调试之中。用DSL来将访问控制和具体的权限理解分隔开了是最为合适的方式。

通过一套约定的DSL语法来描述权限,访问控制系统可以获得极大的灵活性,同时也不需要理解具体的权限。对权限的理解还是由各个业务方自己控制,这样系统就获得了最大程度的解耦。访问控制系统只用维护这套DSL语法就可以无限的扩展性,多么完美的方案啊!有时间我会专门写一篇关于DSL的文章来对其应用场景进行分析。

实际上,用DSL语法来描述权限也不是IAM首创,早在2001年就出现了响应的规范——XACML(可扩展的访问控制高标识语言),该规范现在已经发展到3.0了。其大致的鉴权流程如下图所示,如果对其原理由兴趣的同学可以查看对应的资料。

以上就是我对云环境下访问控制系统的一点理解,如有不严谨的地方,还望指正。总而言之,云环境下的访问控制系统面临的挑战很多,充分理解访问控制的原理有助于理解代码背后的意义,让我们的系统设计不至于走偏。基于DSL的访问控制模型已经成为业界的主流,但各个云计算厂商自身的业务场景和面向目标人群又各有不通,如何制定适应自身环境的DSL成为了一个关键。后续有机会我会分享网易蜂巢在访问控制系统方面的实践。

参考资料:

访问控制
访问控制模型ACL和RBAC
DSL

坚持原创技术分享,您的支持将鼓励我继续创作!