【OpenStack源码分析之六】从虚拟机启动流程看安全认证

时间:2022-12-23 20:58:47

前言

从7.8号开始分析OpenStack已经有两周了,原本计划一个月分析完Neutron和Nova的,但是捋了下Nova的虚拟机启动流程,尤其是看到popsuper1982仁兄写得虚拟机启动的100个知识点,大概流程是清楚了,但是我没办法再去逐一深究,所以想把这里面再提取几个我关注的知识点研究一下。先借用一下网上的两张图:
虚拟机启动的100个知识点

【OpenStack源码分析之六】从虚拟机启动流程看安全认证

虚拟机启动的整体流程
【OpenStack源码分析之六】从虚拟机启动流程看安全认证

这里面我比较关注的几个问题:
- 安全认证机制,如何确保客户端的访问时可信的。(我并不做安全,只是纯属兴趣,毕竟互联网金融时代我也想了解下我的财富是否安全^_^)
- 虚拟机调度算法(类似于进程调度,这个任务是操作系统的核心)
- 虚拟机在整个流程中的状态迁移
- HA机制涉及的技术,包括事务,分布式技术等
- Hypervisor层的接口与调用
- 虚拟机热迁移如何实现
- OAM:OpenStack后台运行的周期性任务

一口气列了七个问题,我想到下周能彻底写完就算比错,因为Neutron的部分我有些底子。再用一周应该可以分析完成。

安全认证

我不是搞安全的,在我看来,安全认证的范围在于如何证明你妈是你妈,也就是当一个Restcall到来的时候,如何保障消息来源的可靠性以及消息的完整性,消息来源的可靠性的意思是Restcall的来源是经过认证的注册用户,而不是第三方黑客;消息的完整性是指消息在传递的过程中没有被修改。注意,这里面没有涉及消息的加密技术,这是另一个范畴,加密是保障消息在传递过程中第三方无读取权限(比如网上交易里涉及的密码等等)。
【OpenStack源码分析之六】从虚拟机启动流程看安全认证

Token是什么
一般来说,Token是通过提供有效的用户名/密码组合提供给用户的一段数据。另外,与Token密切相关的是它的有效期(通常是几小时甚至几分钟)。Client可以缓存Token并将其注入到OpenStack API请求中。OpenStack API端点将令牌从用户请求中取出,并通过KeyStone后端进行验证,从而确认调用的合法性。
我们现在把注意力放在两种Token生成方式:通用唯一标识符(UUID)和公共密钥基础设施(PKI)的标识

UUID

【OpenStack源码分析之六】从虚拟机启动流程看安全认证

基于提供的用户名/密码对:
- KeyStone将做以下工作:
- 生成一个UUID令牌。
- 将UUID令牌存储在后端。
- 发送一份拷贝的UUID令牌返回给客户端。
- 客户机将缓存令牌。
- 然后客户端会把UUID附在每个API调用上。
- 在每一个用户的请求,API端点会送这个UUID回到Keystone验证。
- Keystone将UUID和它的认证后端匹配(检查UUID字符串、日期)。
- KeyStone将返回“成功”或“失败”消息到API端点。
从上面的图表中可以看到,对于每个用户调用,API端点都需要使用KeyStone服务进行联机验证。想象成千上万的Client执行VM List、网络创建等等操作。这种设计导致了大量流量被导向了KeyStone造成单点故障。事实上,在生产中,Keystone被证明是负载最重的OpenStack服务之一,但Grizzly版本之后就采取了PKI方式来解决这个问题。

背景知识:非对称加密

采用非对称加密算法,公钥获取的可靠性就非常重要,获取到正确的公钥,后续的工作就成功了一半。另一半是保障数据的完整性,这个是通过数据签名实现的,怎么样才能保障获取到正确的公钥呢?
我们第一反应可能会想到以下的两个方法:
- a)把公钥放到互联网的某个地方的一个下载地址,事先给“客户”去下载。
- b)每次和“客户”开始通信时,“服务器”把公钥发给“客户”。
但是这个两个方法都有一定的问题,
对于a)方法,“客户”无法确定这个下载地址是不是“服务器”发布的,你凭什么就相信这个地址下载的东西就是“服务器”发布的而不是别人伪造的呢,万一下载到一个假的怎么办?另外要所有的“客户”都在通信前事先去下载公钥也很不现实。
对于b)方法,也有问题,因为任何人都可以自己生成一对公钥和私钥,他只要向“客户”发送他自己的私钥就可以冒充“服务器”了。示意如下:

“客户”->“黑客”:你好 //黑客截获“客户”发给“服务器”的消息
“黑客”->“客户”:你好,我是服务器,这个是我的公钥 //黑客自己生成一对公钥和私钥,把公钥发给“客户”,自己保留私钥
“客户”->“黑客”:向我证明你就是服务器
“黑客”->“客户”:你好,我是服务器 {你好,我是服务器}[黑客自己的私钥|RSA] //客户收到“黑客”用私钥加密的信息后,是可以用“黑客”发给自己的公钥解密的,从而会误认为“黑客”是“服务器”

因此“黑客”只需要自己生成一对公钥和私钥,然后把公钥发送给“客户”,自己保留私钥,这样由于“客户”可以用黑客的公钥解密黑客的私钥加密的内容,“客户”就会相信“黑客”是“服务器”,从而导致了安全问题。这里问题的根源就在于,大家都可以生成公钥、私钥对,无法确认公钥对到底是谁的。 如果能够确定公钥到底是谁的,就不会有这个问题了。例如,如果收到“黑客”冒充“服务器”发过来的公钥,经过某种检查,如果能够发现这个公钥不是“服务器”的就好了。

解决这个问题其实就不是技术问题了,需要一个权威机构来授权数字证书,它可以解决我们上面的问题。先大概看下什么是数字证书,一个证书包含下面的具体内容(证书相当于协议的控制面,会定义后续交互的算法和公钥等):

◆CA (证书的发布机构)

指出是什么机构发布的这个证书,也就是指明这个证书是哪个公司创建的(只是创建证书,不是指证书的使用者)。对于上面的这个证书来说,就是指”SecureTrust CA”这个机构。

◆Valid from , Valid to (证书的有效期)

也就是证书的有效时间,或者说证书的使用期限。 过了有效期限,证书就会作废,不能使用了。

◆Public key (公钥)

这个我们在前面介绍公钥密码*时介绍过,公钥是用来对消息进行加密和解密的。

◆Subject (主题)

这个证书是发布给谁的,或者说证书的所有者,一般是某个人或者某个公司名称、机构的名称、公司网站的网址等。 对于这里的证书来说,证书的所有者是Trustwave这个公司。

◆Signature algorithm (签名所使用的算法)

就是指的这个数字证书的数字签名所使用的加密算法,这样就可以使用证书发布机构的证书里面的公钥,根据这个算法对指纹进行解密。指纹的加密结果就是数字签名。

◆Thumbprint, Thumbprint algorithm (指纹以及指纹算法)

这个是用来保证证书的完整性的,也就是说确保证书没有被修改过,其原理就是在发布证书时,发布者根据指纹算法(一个hash算法)计算整个证书的hash值(指纹)并和证书放在一起,使用者在打开证书时,自己也根据指纹算法计算一下证书的hash值(指纹),如果和刚开始的值对得上,就说明证书没有被修改过,因为证书的内容被修改后,根据证书的内容计算的出的hash值(指纹)是会变化的。 注意,这个指纹是数据的指纹,并不是代表客户端或服务器端的指纹。

注意,为了保证安全,在证书的发布机构发布证书时,证书的指纹和指纹算法,都会加密后再和证书放到一起发布,以防有人修改指纹后伪造相应的数字证书。这里问题又来了,证书的指纹和指纹算法用什么加密呢?他们是用证书发布机构的私钥进行加密的。可以用证书发布机构的公钥对指纹和指纹算法解密,也就是说证书发布机构除了给别人发布证书外,他自己本身也有自己的证书。证书发布机构的证书是哪里来的呢???这个证书发布机构的数字证书(一般由他自己生成)在我们的操作系统刚安装好时(例如windows xp等操作系统),这些证书发布机构的数字证书就已经被微软(或者其它操作系统的开发机构)安装在操作系统中了,微软等公司会根据一些权威安全机构的评估选取一些信誉很好并且通过一定的安全认证的证书发布机构,把这些证书发布机构的证书默认就安装在操作系统里面了,并且设置为操作系统信任的数字证书。这些证书发布机构自己持有与他自己的数字证书对应的私钥,他会用这个私钥加密所有他发布的证书的指纹作为数字签名。

说白了,要想具备CA资质,又需要到更权威的机构去认证,而这些更权威的机构是已经默认在操作系统中安装了其公钥证书。所以在初始阶段,Client会拿着Server端的证书去权威机构鉴定是否是对方,而Server端会拿着Client的证书去自己的CA机构Keystone验证可靠性。
【OpenStack源码分析之六】从虚拟机启动流程看安全认证

证书的发布机构

前面已经初步介绍了一下证书发布机构,这里再深入讨论一下。

其实所有的公司都可以发布证书,我们自己也可以去注册一家公司来专门给别人发布证书。但是很明显,我们自己的专门发布证书的公司是不会被那些国际上的权威机构认可的,人家怎么知道你是不是个狗屁皮包公司?因此微软在它的操作系统中,并不会信任我们这个证书发布机构,当应用程序在检查证书的合法信的时候,一看证书的发布机构并不是操作系统所信任的发布机构,就会抛出错误信息。也就是说windows操作系统中不会预先安装好我们这个证书发布机构的证书,不信任我们这个发布机构。

不受信任的证书发布机构的危害

为什么一个证书发布机构受不受信任这么重要?我们举个例子。假设我们开了一个狗屁公司来为别人发布证书,并且我和微软有一腿,微软在他们的操作系统中把我设置为了受信任的证书发布机构。现在如果有个小公司叫Wicrosoft 花了10块钱让我为他们公司申请了一个证书,并且公司慢慢壮大,证书的应用范围也越来越广。然后有个奸商的公司JS Company想冒充Wicrosoft,于是给了我¥10000,让我为他们颁布一个证书,但是证书的名字(Subject)要写Wicrosoft,假如我为了这¥10000,真的把证书给了他们,那么他们以后就可以使用这个证书来冒充Wicrosoft了。

如果是一个优秀的证书发布机构,比如你要向他申请一个名字叫Wicrosoft的证书,它会让你提供很多资料证明你确实可以代表Wicrosoft这个公司,也就是说他回去核实你的身份。证书发布机构是要为他发布出的证书负法律责任的。

到这里,你可能会想,TMD,那我们自己就不能发布证书吗?就一定要花钱去申请?当然不是,我们自己也可以成立证书发布机构,但是需要通过一些安全认证等等,只是有点麻烦。另外,如果数字证书只是要在公司内部使用,公司可以自己给自己生成一个证书,在公司的所有机器上把这个证书设置为操作系统信任的证书发布机构的证书(这句话仔细看清楚,有点绕口),这样以后公司发布的证书在公司内部的所有机器上就可以通过验证了(在发布证书时,把这些证书的Issuer(发布机构)设置为我们自己的证书发布机构的证书的Subject(主题)就可以了)。但是这只限于内部应用,因为只有我们公司自己的机器上设置了信任我们自己这个所谓的证书发布机构,而其它机器上并没有事先信任我们这个证书发布机构,所以在其它机器上,我们发布的证书就无法通过安全验证。

PKI方式

【OpenStack源码分析之六】从虚拟机启动流程看安全认证
在PKI方式下,KeyStone已经成为一个CA(认证授权)机构,PKI 的本质就是基于数字签名,Keystone 用私钥对 token 进行数字签名,各个 API server 用公钥在本地验证该 token。也就是说通过这种方式来实现单点登录(用户只需要登录一次就可以访问所有相互信任的应用系统)。当然这里如何确保安全(比如黑客截获这个Token冒充客户端发送请求,当然这里会有一个Token过期时间),我也不太清楚,只是当前已经在使用这种方式,是否安全具体做安全的人可以告知一下。这里的Token是通过Service catalog,User roles,Metadata等消息来生成的

总结一下:
如何确保消息源的可靠性? 通过第三方权威机构认证的CA机构才有授予证书的权利,而这些第三方权威机构在操作系统默认已经安装,在初始阶段,Client会拿着Server端的证书去权威机构鉴定是否是对方,而Server端会拿着Client的证书去自己的CA机构Keystone验证可靠性。

如何确保数据的完整性? 通过数据签名算法,首先对数据进行Hash算法生成指纹,然后用公钥或者私钥加密生成数字签名,接收方拿到数据后使用私钥解密数字签名,同时使用相同的Hash算法对数据生成指纹进行比对。

如何确保数据是保密的,第三方无查看权限? 交互双方在互相认定证书之后会使用公私钥加密约定消息体的对称加密算法和公钥,这个过程是客户端来发起的,服务器端不允许这个操作。

总而言之,证书类似一个协议控制面,用来做消息源可靠性的认定以及数据完整性的算法约定,后续的交互就会用上证书约定的公钥和指纹算法。消息体的保密性是无法确保的。需要靠另外的数据加密算法。

参考文献:
http://www.cnblogs.com/popsuper1982/p/3800235.html
http://blog.sina.com.cn/s/blog_44ee37cd01016r1h.html