自 2010 年末首次发布,OpenStack 已经成为了使用最为广泛的 Infrastructure as a Service (IaaS)云平台之一。OpenStack 是一个不断成长的开源解决方案套件,由核心项目和孵化项目组成。各个项目之间是松耦合的关系,通过 Message Queue 和 REST API 进行通讯。考虑到性能等问题,OpenStack 官方默认的配置都是非加密的。在一些企业级的应用中,用户对通讯的加密非常看重。本文简单介绍如何通过配置,使 OpenStack 的 REST API 通讯以 SSL 加密方式进行。
开始之前
环境准备
- 一个 RHEL 6.5 的 Linux 操作系统
- 运行在 RHEL6.5 之上的 OpenStack Icehouse 版本
文中术语说明
- REST:含状态传输(英文:Representational State Transfer,简称REST),是目前主流的 web 服务实现方案之一。它是一种设计风格,以 URI 表示资源,并且支持资源的获取、创建、修改和删除。
- SSL:安全套接层(Secure Sockets Layer,SSL)是一种安全协议,目的是为互联网通信,提供安全及数据完整性保障。
OpenStack 通讯机制概述
本文假设读者已经对 OpenStack 有了一定的了解,因此对 OpenStack 的发展及使用场景不再赘述。仅对与本文相关的通讯机制部分作一定的说明。
OpenStack 由多个相对独立的项目组成,每个项目有独立的代码,并且能独立运行。项目与项目之间协同工作,完成了一个基础架构云平台。由于各个项目独立运行,因此,相互之间的通讯显得格外重要。OpenStack 的各个项目之间,有两种通讯方式,一种是基于 AMQP(Advanced Message Queuing Protocol )的消息队列机制;一种是 REST 风格的 HTTP 请求。在空闲时间,各个项目之间相安无事。一旦某个项目发生了变化,首先会通过消息队列将变化传递到相关的项目,之后被通知的项目再通过 HTTP 请求来获得变化的具体内容。对于 OpenStack 中的某些较大项目,在项目内部又细分成几个模块,这几个模块之间的通讯可能就是消息队列和 HTTP 请求并存。
OpenStack 各个项目本身都支持 SSL 加密认证。但是,如果对通讯都进行 SSL 加密,耗时必然会加大。因此,出于性能考虑,OpenStack 的默认配置都没有使能 SSL。本文将简要介绍如何将一个默认的 OpenStack 云环境,配置成 REST API 是 SSL 加密的云环境。本文之后部分所描述的 SSL 加密都是针对 OpenStack 各个项目的 REST API,本文之后部分的通讯都是指各个项目之间的 HTTP 请求通讯。
#p#
以 SSL 方式配置 Keystone 的 REST API
Keystone(OpenStack Identity Service)在 OpenStack 框架中,负责身份验证和服务令牌等功能,它实现了 OpenStack 的 Identity API。Keystone 类似一个服务总线,或者说是整个 OpenStack 框架的注册表, 其他服务通过 Keystone 来注册其服务的 Endpoint(服务访问的 URL),任何服务之间相互的调用,首先需要经过 Keystone 的身份验证,来获得目标服务的 endpoint 来找到目标服务。有关 Keystone 的更多信息,可以查看 Keystone 的 wiki。
因为 Keystone 会与所有其他的 OpenStack 项目通讯,先配置好 Keystone,可以在配置其他项目时把该项目与 Keystone 的通讯也配置成 SSL 加密方式。反之,如果先配置别的项目,在 Keystone 完成 SSL 配置之后,还需要再在各个项目中将 Keystone 部分的配置修改成 SSL 加密的方式。因此,本文首先对 Keystone 进行配置。
生成自签名证书
SSL 通讯的核心是基于证书的,Keystone 比较方便的是,能生成一个用于测试的自签名证书。执行以下命令:
- # keystone-manage ssl_setup --keystone-user keystone --keystone-group keystone
清单 1. 用 Keystone 命令生成用于测试的自签名证书
执行完清单 1 的命令后,在/etc/keystone/ssl 路径下会新增几个证书文件。为了确保 Keystone 能正常读取文件,修改文件的用户组。
清单 2. 修改 Keystone 生成的证书文件所在的用户组
- # chown -R keystone:keystone /etc/keystone/ssl
修改 Keystone 的 endpoint
Endpoint 的概念在后面还会多次出现,这里简单说一下。endpoint,翻译为“端点”,我们可以理解它是一个 OpenStack 项目暴露出来的访问点,如果需要访问一个项目,可以先获取它的 endpoint,再从 endpoint 进行访问。OpenStack 中,endpoint 是由 Keystone 进行管理的。这么做是合理的,因为 Keystone 与所有项目都进行通讯。在 Keystone 中包含一个 endpoint 模板,这个模板提供了所有存在的项目 endpoint 信息。一个 endpoint template 包含一个 URLs 列表,列表中的每个 URL 都对应一个项目实例的访问地址,并且具有 public、internal 和 admin 这三种权限。public url 可以被全局访问,internal url 只能被局域网访问,admin url 被从常规的访问中分离。
由于本文想将 Keystone 配置成 SSL 加密,因此需要让所有的访问者知道 Keystone 服务的入口已经改变了,可以通过修改 Keystone 的 endpoint 来实现这一目的。
清单 3. 获取当前的 Keystone endpoint 列表
- #keystone endpoint-list
通过读取 Keystone 的配置文件可以知道它的 public 端口是 5000,internal 和 admin 端口是 35357。通过端口号能从 endpoint list 中找到 Keystone 的 endpoint。由于 Keystone 在 V2 版本不提供修改 endpoint 的接口,在这里可以先创建一个新的 https 的 endpoint,再删除之前的 endpoint。
清单 4. 创建 Keystone 的 SSL endpoint
- # keystone endpoint-create
- --service keystone --region RegionOne --publicurl
- https://{keystoneHost}:5000/v2.0 --internalurl
- https://{keystoneHost}:35357/v2.0 --adminurl
- https://{keystoneHost}:35357/v2.0
清单 4 中的{keystoneHost}是指 Keystone 所在的 host。这里要注意,一定要先添加 HTTPS 的 endpoint,再删除旧的 HTTP 的 endpoint。否则会由于找不到 Keystone 服务的入口导致后继的操作将无法进行。
添加完成之后,Keystone 相当于有两个 endpoint 暴露出来了,在实际中究竟使用哪一个呢?答案是不确定。这就导致在添加完 HTTPS 的 endpoint 之后,Keystone 提供给自己的服务入口可能是 HTTPS 的,也可能是旧的 HTTP 的。在这里可以做个测试,执行清单 3 的命令,如果命令不能返回 endpoint 列表,则说明 Keystone 对外暴露的是 HTTPS 的 endpoint。反之,则说明 Keystone 对外暴露的仍然是旧的 HTTP 的 endpoint,此时,可以删除该 endpoint,以确保 Keystone 对外暴露的是 HTTPS 的 endpoint。
清单 5. 删除 Keystone 的 http endpoint
- # keystone
- endpoint-delete {old endpoint id}
清单 5 中,{old endpoint id}是通过清单 3 中的指令获取的旧的 Keystone 的 endpoint 的 id。
此时,由于对外暴露的 Keystone 服务端口已经是 SSL 的,但是其本身还是以非 SSL 方式运行,所以 Keystone 服务已经无法使用了。我们需要将 Keystone 本身也修改成以 SSL 加密认证方式工作。
修改 Keystone 的 SSL 相关配置
由于已经通过清单 1 的命令生成了用于测试的自签名证书,在本小节需要将其写入 Keystone 的配置。打开 Keystone 的配置文件,修改如下配置项:
清单 6. 修改 Keystone 的 SSL 相关配置
- # vi
- /etc/keystone/keystone.conf [ssl] enable = True certfile =
- /etc/keystone/ssl/certs/keystone.pem keyfile =
- /etc/keystone/ssl/private/keystonekey.pem ca_certs =
- /etc/keystone/ssl/certs/ca.pem
为了使修改的配置生效,重启 Keystone 服务。
清单 7. 重启 Keystone 服务
- # service openstack-keystone restart
至此,Keystone 的 SSL 配置已经完成了,Keystone 对外的接口已经是 SSL 加密认证的,所有访问的 url 都是 HTTPS 开头的。为了使之后的命令能执行,需要更新 OpenStack cli 的认证 url。
清单 8. 更新 OpenStack cli 的认证 url
- # export
- OS_AUTH_URL=https://{keystoneHost}:5000/v2.0
如果之前没有做,现在可以删除之前的旧的 http 的 endpoint。
清单 9. 删除 Keystone 的非 SSL endpoint
- # keystone –-insecure
- endpoint-delete {old endpoint id}
清单 9 中,{old endpoint id}是通过清单 3 中的指令获取的旧的 Keystone 的 endpoint 的 id。
这里说明一下清单 9 中的参数 --insecure。 OpenStack 的 CLI 命令,实际上都是通过执行 curl 命令调用相应项目的 REST API 来实现。我们之前是用一个自签名的证书来配置 Keystone 的 SSL 加密认证,这个证书是不被 curl 所认可的。加上 --insecure 参数可以让 curl 忽略这个证书。另一方面,也可以将这个自签名证书导入 curl,具体操作见参考资源,这样就可以省去该参数。如果是通过别的工具,例如 Firefox 来访问 OpenStack 的 REST API,仅需要在第一次访问时接受证书,之后就可以正常访问了。
#p#
以 SSL 方式配置 Nova 的 REST API
Nova(OpenStack Compute Service)在 OpenStack 框架中,负责虚机的管理,是整个 Infrastructure as a Service 系统中的最重要部分。有关 Nova 的更多信息,可以查看 Nova 的 wiki。但是在 SSL 配置中,Nova 的地位与其他项目一样。因此,本文将不会逐个介绍如何对各个项目进行 SSL 配置,仅以 Nova 为例说明。
配置 Nova 以 SSL 加密方式连接 Keystone
前面已经将 Keystone 配置成 SSL 加密认证了。由于 OpenStack 所有的其他项目都需要通过 Keystone 进行用户认证,而默认的配置,都是以非 SSL 方式连接 Keystone。所以,理论上此时除了 Keystone,OpenStack 的其他项目都已经无法使用了。所以,配置 Nova 的第一步,应将 Nova 中有关 Keystone 的部分修改成 SSL 加密的。
清单 10. 修改 Nova 配置以 SSL 方式连接 Keystone
- # vi
- /etc/nova/API-paste.ini auth_uri = https://10.1.0.92:5000/v2.0
- auth_protocol = https insecure = True
这里的 insecure = True 与之前说明的 --insecure 参数是一个道理。 修改完之后,重启 nova-API,以使配置生效。
清单 11. 重启 nova-API
- # service openstack-nova-API restart
此时,Nova 已经可以使用了。可以使用以下命令检验之。
清单 12. 查看 nova 下所有 hypervisor
- # nova --insecure hypervisor-list
在检验时需要注意,由于 Nova 可能与其他项目也存在交互,例如调用 Nova 的某些命令,可能需要去 Neutron 取数据,而 Neutron 同样也需要经过 Keystone 认证。但是,在目前的步骤,Neutron 还没有被配置,所以,Neutron 中有关 Keystone 的配置仍然是非 SSL 的。这个时候 Neutron 的是无法通过 Keystone 认证的,数据也无法获取,最终会导致 Nova 的相应命令执行失败。因此,在目前的步骤下,检验 Nova 需要用一些只使用 Nova 内部数据的命令,例如清单 12。
生成自签名证书
Nova 不像 Keystone,提供命令生成用于测试的自签名证书。我们在这里使用前面 Keystone 的证书。首先将证书拷贝至 Nova 目录下,然后修改证书所在的用户组以供 Nova 使用。
清单 13. 将 Keystone 的证书拷贝至 Nova 目录下
- # mkdir /etc/nova/ssl # cp
- /etc/keystone/ssl/certs/keystone.pem /etc/nova/ssl/ # cp
- /etc/keystone/ssl/private/keystonekey.pem /etc/nova/ssl/ # chown -R
- nova:nova /etc/nova/ssl/
修改 Nova 的 endpoint
endpoint 的概念之前已经介绍过了,这里直接调用清单 3 中的命令,获取 endpoint 列表。从 Nova 的配置文件中可以知道它的 public,internal 和 admin 端口是 8774。
清单 14. 创建 Nova 的 SSL endpoint
- # keystone --insecure
- endpoint-create --service nova --region RegionOne --publicurl
- "https://{novaHost}:8774/v2/%(tenant_id)s" --internalurl
- "https://{novaHost}:8774/v2/%(tenant_id)s" --adminurl
- "https://{novaHost}:8774/v2/%(tenant_id)s"
创建完成之后,删除之前的非 SSL endpoint 以避免混淆。相应的命令参见清单 9。此时,由于对外暴露的 Nova 服务端口已经是 SSL 的,但是其本身还是非 SSL 方式运行,所以 Nova 服务又无法使用了。我们需要将 Nova 本身也修改成以 SSL 加密认证方式工作。
修改 Nova 的 SSL 相关配置
直接修改 Nova 的配置文件,
清单 15. 修改 Nova 的 SSL 相关配置
- # vi /etc/nova/nova.conf [DEFAULT]
- enabled_ssl_APIs=osAPI_compute
- ssl_cert_file=/etc/nova/ssl/keystone.pem
- ssl_key_file=/etc/nova/ssl/keystonekey.pem
修改完配置之后,调用清单 11 的命令重启 nova-API 以使配置生效。之后用清单 12 中的命令测试结果即可。如果想看具体的调用,可以加上 --debug 参数。可以发现,现在所有的 curl 命令都调用 https 的 url。
总结
OpenStack 在 Icehouse 版本共有 9 个核心项目,若干个孵化项目。随着 OpenStack 的成长,项目数还会增加。出于性能考虑,OpenStack 所有的项目默认都是以非 SSL 方式工作,需要用户手动修改配置以使能 SSL。在修改配置上,Keystone 由于其在整个架构中所处的特殊地位,而略有不同。其他的项目,如 Glance、Cinder、Neutron 等,虽然在配置文件中某些属性可能不同,但是配置过程与 Nova 大致相同。读者可以尝试按照 Nova 的配置过程去配置其他的项目。