Amphorae 与 Octavia Worker 的安全通信实现
前言
在前面的章节中我们记录了 LoadBalancer、Listener、Pool、Member 等等 Octavia 核心资源对象的创建流程,本篇我们在此之上继续讨论处于 LB Management Network 上的 Amphorae 虚拟机是如何与处于 OpenStack Management Network 上的 Octavia Worker 进行安全通信的。
为什么 Octavia 需要自建 CA 证书?
首先我们提出一个问题:为什么 Octavia 需要自建 CA 而不使用 OpenStack 的通用认证体系?
答案是:For production use the ca issuing the client certificate and the ca issuing the server certificate need to be different so a hacker can’t just use the server certificate from a compromised amphora to control all the others.
简而言之,Octavia 自建 CA 证书主要有两个必要:
- amphora-agent 没有加入 OpenStack 鉴权体系,需要证书来保证通讯安全
- 防止恶意用户利用 amphora 作为 “肉鸡” 攻击 OpenStack 的内部网络
基于自建 CA 实现的 SSL 通信
Octavia 提供了自动化脚本通过 OpenSSL 指令来创建 CA 中心并自签发 CA 根证书。执行下述指令即可完成:
$ source /opt/rocky/octavia/bin/create_certificates.sh /etc/octavia/certs/ /opt/rocky/octavia/etc/certificates/openssl.cnf
NOTE:自签发即自己担保自己,用自己的私钥对自己的 CSR 进行签发。只有顶级认证角色才会自签发,所以也称为根证书,本质是签发服务器证书的公钥。
所谓 CA,在操作系统上的载体只是一个文件目录(Directory),包含了各类型秘钥的证书。CA 在信任系统中充当第三方信托机构的角色,提供证书签发和管理服务,可以有效解决非对称加密系统中常见的中间人攻击问题。更多关于 CA 中心为内容可以参考《使用 OpenSSL 自建 CA 并签发证书》,这里不再赘述。
Octavia 自建的 CA 中心:
$ ll /etc/octavia/certs/
total 44
-rw-r--r-- 1 stack stack 1294 Oct 26 12:51 ca_01.pem
-rw-r--r-- 1 stack stack 989 Oct 26 12:51 client.csr
-rw-r--r-- 1 stack stack 1708 Oct 26 12:51 client.key
-rw-r--r-- 1 stack stack 4405 Oct 26 12:51 client-.pem
-rw-r--r-- 1 stack stack 6113 Oct 26 12:51 client.pem
-rw-r--r-- 1 stack stack 71 Oct 26 12:51 index.txt
-rw-r--r-- 1 stack stack 21 Oct 26 12:51 index.txt.attr
-rw-r--r-- 1 stack stack 0 Oct 26 12:51 index.txt.old
drwxr-xr-x 2 stack stack 20 Oct 26 12:51 newcerts
drwx------ 2 stack stack 23 Oct 26 12:51 private
-rw-r--r-- 1 stack stack 3 Oct 26 12:51 serial
-rw-r--r-- 1 stack stack 3 Oct 26 12:51 serial.old
- newcerts dir:存放 CA 签署(颁发)过的数字证书
- private dir:存放 CA 的私钥
- serial file:存放证书序列号(e.g. 01),每新建一张证书,序列号会自动加 1
- index.txt file:存放证书信息
- ca_01.pem PEM file:CA 证书文件
- client.csr file:Server CSR 证书签名请求文件
- client.key file:Server 私钥文件
- client-.pem:PEM 编码的 Server 证书文件
- client.pem:结合了 client-.pem 和 client.key 的文件
列举 Octavia 与 CA 认证相关的配置项:
- 应用于 Create Amphora Flow 中的 TASK:GenerateServerPEMTask,生成 Amphora 私钥并签发 Amphora 证书。
[certificates]
ca_private_key_passphrase = foobar
ca_private_key = /etc/octavia/certs/private/cakey.pem
ca_certificate = /etc/octavia/certs/ca_01.pem
- 应用于 Octavia Worker 的 AmphoraAPIClient,拿着 CA 根证书(是 Amphora 证书的公钥,可以解开 Amphora 证书得到 Amphora 的公钥)和 Amphora 证书向 amphora-agent 发起 SSL 通信。
[haproxy_amphora]
server_ca = /etc/octavia/certs/ca_01.pem
client_cert = /etc/octavia/certs/client.pem
- 应用于 Task:CertComputeCreate,指定 CA 根证书的路径
[controller_worker]
client_ca = /etc/octavia/certs/ca_01.pem
Amphora Agent 启动加载证书
首先看为 Amphorae 生成证书的代码实现:
# /opt/rocky/octavia/octavia/controller/worker/tasks/cert_task.py
class GenerateServerPEMTask(BaseCertTask):
"""Create the server certs for the agent comm
Use the amphora_id for the CN
"""
def execute(self, amphora_id):
cert = self.cert_generator.generate_cert_key_pair(
cn=amphora_id,
validity=CERT_VALIDITY)
return cert.certificate + cert.private_key
Octavia Certificates 功能模块提供了 local_cert_generator(default)
和 anchor_cert_generator
两种证书生成器,通过配置项 [certificates] cert_generator
选用。
# /opt/rocky/octavia/octavia/certificates/generator/local.py
@classmethod
def generate_cert_key_pair(cls, cn, validity, bit_length=2048,
passphrase=None, **kwargs):
pk = cls._generate_private_key(bit_length, passphrase)
csr = cls._generate_csr(cn, pk, passphrase)
cert = cls.sign_cert(csr, validity, **kwargs)
cert_object = local_common.LocalCert(
certificate=cert,
private_key=pk,
private_key_passphrase=passphrase
)
return cert_object
上述 LocalCertGenerator.generate_cert_key_pair
Method 的语义是:
- 生成 Amphora 私钥
- 生成 Amphora 证书签名请求(CSR)
- 向 CA 中心申请签署 Amphora证书
属于常规的证书创建流程,与 create_certificates.sh 脚本的区别在于,Octavia Certificates 应用了 cryptography python 库而非 OpenSSL 来实现。
TASK:GenerateServerPEMTask 最终 return 了 Amphora 私钥和证书,然后实现 TASK:CertComputeCreate 将这些文件注入到 Amphora 虚拟机。登录 Amphora 即可查看这些文件,路径记录在配置文件中:
# /etc/octavia/amphora-agent.conf
[amphora_agent]
# Octavia Worker 的证书
agent_server_ca = /etc/octavia/certs/client_ca.pem
# Amphora 的私钥和证书
agent_server_cert = /etc/octavia/certs/server.pem
Gunicorn HTTP Server 启动时就会将证书文件加载, 加载证书的 options 如下:
options = {
'bind': bind_ip_port,
'workers': 1,
'timeout': CONF.amphora_agent.agent_request_read_timeout,
'certfile': CONF.amphora_agent.agent_server_cert,
'ca_certs': CONF.amphora_agent.agent_server_ca,
'cert_reqs': True,
'preload_app': True,
'accesslog': '/var/log/amphora-agent.log',
'errorlog': '/var/log/amphora-agent.log',
'loglevel': 'debug',
}
AmphoraAPIClient 发送证书请求
class AmphoraAPIClient(object):
def __init__(self):
super(AmphoraAPIClient, self).__init__()
...
self.session = requests.Session()
self.session.cert = CONF.haproxy_amphora.client_cert
self.ssl_adapter = CustomHostNameCheckingAdapter()
self.session.mount('https://', self.ssl_adapter)
...
def request(self, method, amp, path='/', timeout_dict=None, **kwargs):
...
LOG.debug("request url %s", path)
_request = getattr(self.session, method.lower())
_url = self._base_url(amp.lb_network_ip) + path
LOG.debug("request url %s", _url)
reqargs = {
'verify': CONF.haproxy_amphora.server_ca,
'url': _url,
'timeout': (req_conn_timeout, req_read_timeout), }
reqargs.update(kwargs)
headers = reqargs.setdefault('headers', {})
...
上述代码是 requests 库启用 HTTPS 请求的常规实现:
self.session.cert
:上传 Octavia Worker 私钥和证书,用于 Amphora 发起的 SSL 通信reqargs = {'verify': CONF.haproxy_amphora.server_ca, ...}
:携带 Amphora 证书,向 Amphora 发起 SSL 通信
小结
梳理 Octavia 建立 SSL 通信的步骤:
- 创建 Amphora 的过程中 Octavia Worker 会首先生成 Amphora 的私钥,并且向 CA 中心申请签发 Amphora 证书(内含 Amphora 公钥),此时 Amphora 的私钥、证书都会准备好
- Octavia Worker 通过 Config Driver 将 Amphora 的私钥、Amphora 的证书作为 user data 注入到 Amphora 虚拟机。
- Amphora 虚拟机上运行的 amphora-agent Web Server 启动时 Flask app 就会加载 Amphora 的私钥和证书,并启用 HTTPS 通讯协议。
- Octavia Worker 的 AmphoraAPIClient 首次想 amphora-agent 发送请求时,首先会下载 Amphora 证书,然后与自己手上的 CA 根证书解密出 Amphora 的公钥,然后再与 Amphora 的私钥进行匹配。
- 若匹配成功,则建立 SSL 安全通信。
NOTE: 同样的 Amphora 如果希望向 Octavia Worker 自动发起建立 SSL 通信,那么 Amphora 就需要拿着 Octavia Worker 的证书进行访问。所以 Octavia 的证书也同样会被注入到 Amphora。
最后
本篇是《OpenStack Rocky Octavia 实现与分析》系列的第四篇,主要讨论 Amphora 是如何与 Octavia Worker 建立双向的 SSL 安全通信的问题。实话说,Octavia 在解决这个问题的时候并不那么清晰明了,从命名到代码的实现都弥漫着混乱的氛围,需要细细梳理才得以清晰。并且 Octavia 和 Amphora 能够健康通信又是 LBaaS 功能正常运作的基础,所以还是非常有必要掌握这一问题的。
Amphorae 与 Octavia Worker 的安全通信实现的更多相关文章
- Octavia 的实现与分析(OpenStack Rocky)
目录 文章目录 目录 Octavia 基本对象概念 基本使用流程 软件架构 服务进程清单 代码结构 loadbalancer 创建流程分析 network_tasks.AllocateVIP netw ...
- octavia的实现与分析(二)·原理,基本架构与基本流程
[了解] 其实说白了,Octavia就是将用户的API请求经过逻辑处理,转换成Haproxy或者Nginx的配置参数,下发到amphora虚机中. Octavia的内部实现中,逻辑流程的处理主要使用T ...
- openstack octavia的实现与分析(二)原理,架构与基本流程
[了解] 其实说白了,Octavia就是将用户的API请求经过逻辑处理,转换成Haproxy或者Nginx的配置参数,下发到amphora虚机中. Octavia的内部实现中,逻辑流程的处理主要使用T ...
- Octavia 创建 Listener、Pool、Member、L7policy、L7 rule 与 Health Manager 的实现与分析
目录 文章目录 目录 创建 Listener 创建 Pool 创建 Member CalculateDelta HandleNetworkDeltas AmphoraePostNetworkPlug ...
- Octavia 的 HTTPS 与自建、签发 CA 证书
目录 文章目录 目录 Octavia 为什么需要自建 CA 证书? GenerateServerPEMTask CertComputeCreate Amphora Agent AmphoraAPICl ...
- Octavia 创建 loadbalancer 的实现与分析
目录 文章目录 目录 从 Octavia API 看起 Octavia Controller Worker database_tasks.MapLoadbalancerToAmphora comput ...
- Octavia 项目加速 OpenStack LBaaS 落地大规模应用场景
目录 文章目录 目录 OpenStack LBaaS Octavia 软件架构 网络架构 操作对象基本概念 功能实现基本概念 Ocatvia Daemon 列表 部署 Ocatvia 手动方式集成 O ...
- octavia的实现与分析(一)·openstack负载均衡的现状与发展以及lvs,Nginx,Haproxy三种负载均衡机制的基本架构和对比
[负载均衡] 大量用户发起请求的情况下,服务器负载过高,导致部分请求无法被响应或者及时响应. 负载均衡根据一定的算法将请求分发到不同的后端,保证所有的请求都可以被正常的下发并返回. [主流实现-LVS ...
- Octavia Rocky UDP 负载均衡功能试验
目录 文章目录 目录 前言 UDP 简述 功能验证 网络拓扑 资源对象清单 验证 TS Amphorae UDP 包被非法篡改 存疑 前言 以往,Octavia 通过 HAProxy + Keepal ...
随机推荐
- Flight HDU - 3499 (分层最短路)
Recently, Shua Shua had a big quarrel with his GF. He is so upset that he decides to take a trip to ...
- 【基础操作】博弈论 / SG 函数详解
博弈死我了……(话说哪个小学生会玩博弈论提到的这类弱智游戏,还取石子) 先推荐两个文章链接:浅谈算法——博弈论(从零开始的博弈论) 博弈论相关知识及其应用 This article was updat ...
- js获取前几个月的具体日期
// 往前数monthNum月份,不能往后数monthNum getPreMonthDay("2018-12-28",20) // 往前数monthNum月份,不能往后数month ...
- spark 三种数据集的关系(一)
Catalyst Optimizer: Dataset 数据集仅可用Scala或Java.但是,我们提供了以下上下文来更好地理解Spark 2.0的方向数据集是在2015年作为Apache Spark ...
- CGI环境变量
所有的CGI程序都接收以下的环境变量,这些变量在CGI程序中发挥了重要的作用: 变量名 描述 CONTENT_TYPE 这个环境变量的值指示所传递来的信息的MIME类型.目前,环境变量CONTENT_ ...
- cordova打包遇到Connection timedout:
在cordova项目打包时,有时候处在公司内网环境,导致有些文件无法下载报下面的错误: A problem occurred configuring root project 'android'. & ...
- 计算机网络(六),UDP报文段详解
目录 1.UDP作用 2.UDP报文段详解 六.UDP报文段详解 1.UDP作用 (1)面向非连接 (2)不维护连接状态,支持同时向多个客户端传送相同的消息 (3)报文段报头只有8个字节,格外开销较小 ...
- HGOI20190813 省常中互测6
Problem A 蛋糕 将$n \times m $大小的蛋糕切成每块为$1 \times 1$大小的$n\times m$块. 交换任意两块蛋糕的切割顺序的方案算作一种. 对于$100 \%$的数 ...
- 理解ext文件系统
理解ext文件系统 @(0001学习博客) 注意:本文参考骏马金龙的博客,详情请移步浏览 一.一些常见的文件系统 Linux的文件系统: ext2(无日志功能), ext3, ext4, xfs, r ...
- ubuntu E: Could not get lock /var/lib/apt/lists/lock 异常信息
转载:https://www.cnblogs.com/qq952693358/p/6537846.html 在更换软件源时遇到了如下问题: sudo apt-get update E: Could n ...