前言

在前面的章节中我们记录了 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 的语义是:

  1. 生成 Amphora 私钥
  2. 生成 Amphora 证书签名请求(CSR)
  3. 向 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 通信的步骤

  1. 创建 Amphora 的过程中 Octavia Worker 会首先生成 Amphora 的私钥,并且向 CA 中心申请签发 Amphora 证书(内含 Amphora 公钥),此时 Amphora 的私钥、证书都会准备好
  2. Octavia Worker 通过 Config Driver 将 Amphora 的私钥、Amphora 的证书作为 user data 注入到 Amphora 虚拟机。
  3. Amphora 虚拟机上运行的 amphora-agent Web Server 启动时 Flask app 就会加载 Amphora 的私钥和证书,并启用 HTTPS 通讯协议。
  4. Octavia Worker 的 AmphoraAPIClient 首次想 amphora-agent 发送请求时,首先会下载 Amphora 证书,然后与自己手上的 CA 根证书解密出 Amphora 的公钥,然后再与 Amphora 的私钥进行匹配。
  5. 若匹配成功,则建立 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 的安全通信实现的更多相关文章

  1. Octavia 的实现与分析(OpenStack Rocky)

    目录 文章目录 目录 Octavia 基本对象概念 基本使用流程 软件架构 服务进程清单 代码结构 loadbalancer 创建流程分析 network_tasks.AllocateVIP netw ...

  2. octavia的实现与分析(二)·原理,基本架构与基本流程

    [了解] 其实说白了,Octavia就是将用户的API请求经过逻辑处理,转换成Haproxy或者Nginx的配置参数,下发到amphora虚机中. Octavia的内部实现中,逻辑流程的处理主要使用T ...

  3. openstack octavia的实现与分析(二)原理,架构与基本流程

    [了解] 其实说白了,Octavia就是将用户的API请求经过逻辑处理,转换成Haproxy或者Nginx的配置参数,下发到amphora虚机中. Octavia的内部实现中,逻辑流程的处理主要使用T ...

  4. Octavia 创建 Listener、Pool、Member、L7policy、L7 rule 与 Health Manager 的实现与分析

    目录 文章目录 目录 创建 Listener 创建 Pool 创建 Member CalculateDelta HandleNetworkDeltas AmphoraePostNetworkPlug ...

  5. Octavia 的 HTTPS 与自建、签发 CA 证书

    目录 文章目录 目录 Octavia 为什么需要自建 CA 证书? GenerateServerPEMTask CertComputeCreate Amphora Agent AmphoraAPICl ...

  6. Octavia 创建 loadbalancer 的实现与分析

    目录 文章目录 目录 从 Octavia API 看起 Octavia Controller Worker database_tasks.MapLoadbalancerToAmphora comput ...

  7. Octavia 项目加速 OpenStack LBaaS 落地大规模应用场景

    目录 文章目录 目录 OpenStack LBaaS Octavia 软件架构 网络架构 操作对象基本概念 功能实现基本概念 Ocatvia Daemon 列表 部署 Ocatvia 手动方式集成 O ...

  8. octavia的实现与分析(一)·openstack负载均衡的现状与发展以及lvs,Nginx,Haproxy三种负载均衡机制的基本架构和对比

    [负载均衡] 大量用户发起请求的情况下,服务器负载过高,导致部分请求无法被响应或者及时响应. 负载均衡根据一定的算法将请求分发到不同的后端,保证所有的请求都可以被正常的下发并返回. [主流实现-LVS ...

  9. Octavia Rocky UDP 负载均衡功能试验

    目录 文章目录 目录 前言 UDP 简述 功能验证 网络拓扑 资源对象清单 验证 TS Amphorae UDP 包被非法篡改 存疑 前言 以往,Octavia 通过 HAProxy + Keepal ...

随机推荐

  1. deep_learning_Function_tensorflow_random_normal_initializer

    函数原型:tf.random_normal_initializer(mean=0.0, stddev=1.0, seed=None, dtype=tf.float32) 返回一个生成具有正态分布的张量 ...

  2. htpasswd 使用&&在线生成器

    1.简单介绍 htpasswd-管理用于基本身份验证的用户文件. 这个文件可以用来控制nginx或Apache的目录访问控制权限,例如,nginx的在配置nginx_status的态的时候(如下图所示 ...

  3. 浙大数据结构课后习题 练习一 7-1 Maximum Subsequence Sum (25 分)

    Given a sequence of K integers { N​1​​, N​2​​, ..., N​K​​ }. A continuous subsequence is defined to ...

  4. oracle 清空当前用户所有对象

    BEGIN FOR REC IN (SELECT OBJECT_NAME,OBJECT_TYPE FROM USER_OBJECTS WHERE OBJECT_TYPE='PROCEDURE' OR ...

  5. 第四章 生命周期函数--35 vue-resource发起get、post、jsonp请求

    vue-resource 官网 https://github.com/pagekit/vue-resource <!DOCTYPE html> <html lang="en ...

  6. 网站实现https访问

    https协议 是一种通过计算机网络进行安全通信的传输协议.HTTPS经由HTTP进行通信,但利用SSL/TLS来加密数据包.HTTPS开发的主要目的,是提供对网站服务器的身份认证,保护交换数据的隐私 ...

  7. 前端要懂的nginx配置

    多服务接口nginx反向代理 ```js server { listen 80; server_name xx.xx.xx.com; // 前端部署的域名 root /med; index index ...

  8. LightOJ-1104-birthday Paradox(概率)

    链接: https://vjudge.net/problem/LightOJ-1104 题意: Sometimes some mathematical results are hard to beli ...

  9. mysql数据库之 存储引擎、事务、视图、触发器、存储过程、函数、流程控制、数据库备份

    目录 一.存储引擎 1.什么是存储引擎? 2.mysql支持的存储引擎 3. 使用存储引擎 二.事务 三.视图 1.什么是视图 2.为什么要用视图 3.如何用视图 四.触发器 为何要用触发器 创建触发 ...

  10. Nowcoder Typing practice ( Trie 图 )

    题目链接 题意 : 给出 n 个串.然后给出一个问询串.问你对于问询串的每一个前缀.需要至少补充多少单词才能使得其后缀包含 n 个串中的其中一个.注意 '-' 字符代表退格 分析 : 多串的匹配问询自 ...