一、引言:
上一期“谈AK管理之基础篇”,我们讲了如何规范的进行访问密钥生命周期管理。通过分出不同权限的阿里云RAM子账号,将不同的权限分给不同的用户,这样一旦子账号泄露也不会造成全局的信息泄露。但是,由于子账号在一般情况下是长期有效的,因此,子用户的访问密钥也是不能泄露的。
二、泄露挑战
AK通常的泄露途径会有哪些呢?我们先从用户的使用方式来分析和发现:
1. 硬编码在代码里
很多用户对访问密钥的安全意识不够或者没有意识到风险,为了使用方便,会直接把访问密钥的二元组写在代码里,供程序使用;在现在反编译和内存分析的技术已经很成熟的当下,硬编码的方式无异于明文存储密钥,有巨大的泄露风险。
2. 第三方密钥存储
还有很多客户了解访问密钥的重要性,会使用第三方的密钥存储系统或者配置文件,将原始的密钥加密起来。这种方式的做法加延了密钥泄露的链路,但本质上只是原始密钥泄露的风险转移到另外一把密钥上,比如第三方密钥存储系统的访问key,或者是加密的密钥,归根结底还是会存在“最后一把密钥”的安全泄露风险。比如避免密钥硬编码到代码中提到的:系统属性,环境凭证,配置文件等。
三、无密钥访问方案-基础
针对访问密钥的泄露高风险,我们有没有一些方案既能克服“最后一把密钥”的风险,又能很方便的进行可控的身份认证呢?很自然,我们会想出来的第一个方案:既然长期的访问密钥权限大,我们能不能换一种短期且权限可控的访问密钥呢,这就要介绍阿里云的另外一种身份类型和与之相对应的访问密钥。
阿里云虚拟身份
RAM角色(RAM role)与RAM用户一样,都是RAM身份类型的一种,只不过RAM角色是一种虚拟用户,没有确定的身份认证密钥,需要被一个受信的实体用户扮演才能正常使用。简单说,可信实体扮演RAM角色,并使用角色令牌去访问RAM角色里规定的资源以及资源上的OpenAPI。
RAM角色
RAM角色有确定的身份,可以被赋予一组权限策略,但没有确定的登录密码或访问密钥。RAM角色需要被一个受信的实体用户扮演,扮演成功后实体用户将获得RAM角色的安全令牌,使用这个安全令牌就能以角色身份访问被授权的资源。
可信实体(Trusted entity)
角色的可信实体是指可以扮演角色的实体用户身份。创建角色时必须指定可信实体,角色只能被受信的实体扮演。可信实体可以是受信的阿里云账号、受信的阿里云服务或身份提供商。
角色令牌(Role token)
角色令牌是角色身份的一种临时访问密钥。角色身份没有确定的访问密钥,当一个实体用户要使用角色时,必须通过扮演角色来获取对应的角色令牌,然后使用角色令牌来调用阿里云服务API。
对于虚拟身份类型(角色身份),对应的OpenAPI访问凭证就是上面说的角色令牌,是一种时效和权限可控的临时访问密钥。相对于阿里云实体身份的访问密钥的长效控制机制,STS提供的是一种临时访问授权。通过STS可以返回临时的访问密钥和令牌,这些信息可以直接发给临时用户用来访问阿里云服务。一般来说,从STS获取的权限会受到更加严格的限制,并且拥有时间限制,因此这些信息泄露之后对于系统的影响也很小。
阿里云用户在RAM中,定义一个角色,并授权了可以扮演此角色的可信实体,比如某主账户下的子用户账号A,然后授权账户可以访问RAM的接口获取临时访问密钥。账户A的访问流程就如下描述了。所以结合了STS访问密钥的方案一如下描述。
网关
- 客户的应用使用阿里云颁发给账户A的访问密钥签名访问RAMOpenAPI的请求,发给网关;
- 阿里云网关在验证身份和API的权限校验通过后,将请求发送到RAM的OpenAPI,请求颁发STS临时访问密钥;
- 阿里云RAM的OpenAPI颁发STS临时访问密钥;
- 阿里云网关将申请的STS临时访问密钥返回给调用方-云客户应用;
- 云客户应用再将获取的STS临时访问密钥分发给其自己的终端或者别的应用系统;
6- 9步和我们在前言里介绍的一样,应用使用访问密钥正常访问阿里云服务的OpenAPI,只不过这里使用的是STS临时访问密钥了。
四、无密钥访问方案-进阶
无密钥访问方案-基础方案里,我们把权限较大的长期访问密钥,替换成了STS临时访问密钥,由于STS在时间等属性上有限制,这样可以把原来泄露长期访问密钥带来的风险降低到短时间维度,做到了一定程度的安全风险减小,但细心的同学还会发现,要获取一个STS临时访问密钥,还是需要云账户或者其RAM子用户的长期访问密钥,也还是没有解决“最后一把密钥”的问题。
既然阿里云RAM提供了角色功能,并能把这个角色授权给实体,这个是实体是账户或者服务,那可不可以把这个角色和某些特定实体关联呢,比如某个IP,某个区域后者环境等。这种环境可以映射到什么实体呢?我们看现阶段客户的应用绝大部分会运行在机器,docker容器或者某个运行环境(Serverless)里,在这个特定的范围里,比如某个机上,是否可以实现免输入长期访问密钥而调用RAM的OpenAPI获取STS临时访问密钥呢。我们接下来引入阿里云ECS的一个特殊角色来举例。
实例RAM角色
ECS实例RAM(Resource Access Management)角色让ECS实例扮演具有某些权限的角色,从而赋予实例一定的访问权限。实例RAM角色允许用户将一个角色关联到ECS实例,在实例内部基于STS临时凭证(临时凭证将周期性更新)访问其他云产品的API。一方面可以保证AccessKey安全,另一方面也可以借助RAM实现权限的精细化控制和管理。
云产品OpenAP
首先,我们定一个特殊的角色,这个角色就是ECS实例角色,然后把这个角色授予这个特定的ECS实例,在这个实例里的应用可以通过如下流程进行完整的阿里云OpenAPI访问。
- 在已经授予了实例RAM角色的机器上的应用,可以向ECS的元数据服务请求STS临时访问密钥;
curl http://100.100.100.200/latest/meta-data/ram/security-credentials/{RAM角色名称}
- ECS元数据服务返回已经获取的STS临时访问密钥给客户的应用
{ "AccessKeyId" : "STS.XXXXXXX", "AccessKeySecret" : "XXXXXXX", "Expiration" : "2019-09-24T09:05:00Z", "SecurityToken" : "XXXXXXX", "LastUpdated" : "2019-09-24T03:05:00Z", "Code" : "Success" }
- 客户的应用可以把获取的STS临时访问密钥分发给自己的其他应用;
- 客户的其他应用从而使用获得的STS临时访问密钥正常访问阿里云服务的OpenAPI。
除了ECS,阿里云的一些其他运行环境(ECI,ContainerService,FuntionCompute)都有类似的安全实现,在使用了此类安全实现后,用户不在需要直接把访问密钥AccessKey固化在实例中,如写在配置文件中,硬编码在代码中等不安全的存储访问密钥。
五、总结
AK泄露问题导致企业安全事故或生产事故已有大量的案例,实施无密钥访问方案将会有效解决AK安全问题,也正在成为企业访问密钥管理的最佳实践。