理解IAM,云时代的软件开发系列之一
by Xu Wenhao
1. 痛苦的古代科技
最近一段时间,在不断地和同事们改进BotHub.AI现有的基础架构,发现过去自己,包括现在身边的很多同学,还在拿上一个时代,自行维护或者托管数据中心的方式在运营,维护,以及部署完全依托于云服务器的应用,各种笨办法不一而足。所以准备写一系列文章,讲一讲在所有的服务器都在各大公有云的时代,或者用两个字来说“现代”,应该如何进行软件开发,眼下这篇是第一篇文章。
尽管我深度相信Serverless是大势所趋,不过大部人应该一开始用的都是云服务提供的VM,比如Google Compute Engine或者AWS EC2。有了VM,稍有一些安全概念的开发者或者运维人员,通常都会按照老习惯设置创建一系列用户,权限,SSH Keys等,于是,问题就来了。
大家常常犯的错误是,不通过云服务自带的机制,而是自行根据经验去维护一套运维和安全的体系。而自行维护一套权限系统的成本是很高的,特别是对于早期创业团队来说,于是,各种简化山寨的办法就出现了。
- 只有一个人(通常这个人被称呼为CTO),拥有登陆生产服务器的权限
- 因为为每个人维护一个SSH Key以及进行权限分组太麻烦了,所以所有人公用一组SSH Key
- 因为设置VPC太麻烦了,所以生产环境和测试环境都在云服务的整个内网中,所有服务器对于内网都开放
- 当然,上述的3过于奔放了,所以通过IP白名单来设置一些服务器之间的互相访问的权限
然而,上述的这些设置其实都会有一些问题,比如
- 对于上面的1,显然你的CTO不能生病,请假,坐飞机了
- 对于上面的2,显然你的工程师千万不能离职,不然每当有一个人离职你必须在全公司换一次SSH Key
- 对于上面的3,尽管你已经禁止了各种外网访问的端口,保不齐通常的这个Zone/Region中,有人看到了有什么新的漏洞想要试一把
- 对于上面的4,如果你想要做服务器的Auto-Scale怎么办
事实上,现代的云服务其实都已经提供了一种机制来解决这个问题了,就是云服务内的IAM,全称试 Identity and Access Management(身份和访问权限服务)。
2. 理解现代云服务 —— IAM 概览

Google Cloud IAM Overview
所有的现代云服务都提供了IAM服务,IAM服务的大部分概念,对于做过一些web后台开发,开发过权限系统的人来说,并不难理解。除了少数的概念之外,其实就是一个标准的权限系统。
- Users and Groups,IAM中的I指的是Identity,简单来说,就是某一个“用户”,如果我们把一组用户放在一个Group里,那么一个Group就是代表了这些所有用户的一个特殊的Identity
- Permissions and Roles,IAM中的A指的是Access,你也可以理解为就是Permission,很多个Permission打包在一起,就是一个Role
- Policy,I和A的组合,或者说 Member Identity 和 Roles 的组合,就是一个Policy,意味着我们一组的Permission,授予了某一个Member(通常是一个Group)
可以看到这里的I+A的组合,其实就是一个普通的,支持Group和Role的权限系统。而其中所有的基础的User,最简单的方式,就是和公司内部的邮箱绑定,而Groups,可以和公司内部的邮件组绑定(事实上,如果你使用的是G Suite+Google Cloud的话,Google Groups和G Suite User就是Google Cloud的IAM中支持的用户和Groups)。而这个基本的I+A的组合,加上Cloud中管理Resource(资源)的层级结构,以及Service Accounts这个特殊的概念,就构成了基本的IAM服务。
3. 云服务上资源的层级结构

Google Cloud Policy Hierachy
在上面描述I+A的体系的时候,我们引入了一个概念叫做Permission,那么这个Permission针对的是什么呢?在云服务中,Permission是针对Resource(资源而言)的,一个VM在云中是一个Resource,一个Cloud Storage在云中的一个Bucket是一个Resource,而Permission,就是是否有权限针对这些Resource进行一个特定的操作,比如,是否可以读取Bucket中的内容,或者是否可以重启某个VM。
而云服务,又可以把Resource通过Organization+Project两级组织起来。Organization,通常就是指你的公司,一般来说,你的Cloud中应该只有一个Organization。而Project,则可以按照你的要求把一系列Resource组织起来,比如上图中,我们把Resource按照生产,测试和开发环境,组织成了example-prod, example-test以及example-dev。你不仅仅可以按照部署环境来组织Resource,你也可以按照不同的Service来组织服务,特别是在比较大采用SOA架构的公司中,不同团队负责不同的服务,那么可以将不同的Service变成一个个独立的Project。
将Resource组合成Project的用途有两个,其一是,上面讲到的I+A组合而成的Policy,不仅仅可以应用在Resource上,还可以直接应用在Organization以及Project上。并且,下层的Resource会继承来自上层Organization和Project的Policy。这样,你就不用再一一在每个Resource上单独应用Policy了。其二是,同一个Project内,有一个默认的信任边界(trust boundary),比如,Compute Engine可以直接访问对应的Cloud Storage的Bucket。这样,很大程度上也就解决了之前所说的权限管理问题。
对于人数不多的开发团队,上图中简单将环境区分成Prod, Test以及Dev可能就足够了。
4. Service Account,让程序和程序对话
最后说说Service Account,前面我们说到了IAM中的I,主要指的都是“人”,可能是一个工程师,也可能是一个有多个工程师的邮件组。但是,实际对于任何线上的服务和资源,如果是长期运行的话,我们的Policy不应该设置在“人”这个层面。不然的话,一旦有人离职,意味着这个Identity在系统中消失,也就意味着对应的所有Policy相当于失效了,严重的话,所有的线上服务也就不能正常提供了。
所以,在Google Cloud中,引入了一类特殊的Identity,叫做Service Account。Service Account的特殊性在于,他既是Identity,又是Resource,这个带来的作用就是,对于Resource,我们可以授权给Service Account,对于希望有Service Account对应权限的“人”,我们可以把对应的Service Account视作是一个Resource,设定好特定的Policy,使得普通的Identity可以“扮演”(Act As)这个Service Account。
这样,我们无需分享Service Account帐号给到工程师,而是只要给他们对应的Policy,工程师即可以在线上Act As这个Service Account,来运行程序。对应访问的Resource,验证的也是Service Account的权限。
而既是工程师离职,或者换了团队,我们只需要修改对应的Policy,既不会影响线上的服务(因为服务使用的Service Account的权限没有变化),也不必收回帐号或者重新创建帐号(因为用户并没有拿到Service Account,只是有一个Policy允许他Act As Service Account,把这个权限取消即可)。
好了,了解了IAM,Cloud内的Resource层级结构,以及Service Account,对于云内的IAM体系也就有了一个基本的了解。下回,我们来讲讲另一个现代软件开发和权限相关的问题,OAUTH 2.0。
本文主要参考了 Google Cloud IAM 的官方文档。我始终建议任何进行严肃的软件开发的同学,要去读自己使用的云服务的手册。
tags: