- 网络安全
- CLI
- 后端
【免费下载链接】certbot
Certbot is EFF's tool to obtain certs from Let's Encrypt and (optionally) auto-enable HTTPS on your server. It can also act as a client for any other CA that uses the ACME protocol.
导读
letstest 是 Certbot 项目自带的一套轻量级 AWS 测试农场(test farm)脚本,用于在真实 EC2 云主机上对 Certbot 客户端进行跨发行版集成测试。通过本指南,你将掌握如何用一条命令在 Ubuntu、Debian、CentOS 等多台 EC2 实例上并行克隆 Certbot 仓库、安装依赖、运行测试脚本并回收结果日志,也理解其底层基于 boto3 与 Fabric 的自动化原理,从而在自己的 CI 流程或发布验证中复用它。
什么是 letstest
letstest 是 Certbot 仓库letstest/目录下的一个独立 Python 包,其pyproject.toml中的描述为 "Test Certbot on different AWS images"。它解决的问题非常具体:Certbot 需要兼容多个 Linux 发行版与多种 HTTP 服务器(Apache、Nginx 等),单机单元测试无法覆盖真实的系统差异(包管理器、默认配置文件路径、SELinux 策略等),因此需要一个能在多种真实操作系统镜像上自动跑集成测试的设施。
从 multitester.py 的模块 docstring 可以看出它的四个核心工作步骤:
- 拉起实例:根据给定的 AMI 列表,为不同发行版启动 EC2 实例;
- 分发仓库:将 Certbot 仓库复制并部署到各实例;
- 并行执行:在所有实例上运行 Certbot 测试(bash 脚本);
- 收集结果:记录执行过程与成功/失败状态,供排错使用。
整个流程由letstest/letstest/multitester.py(约 520 行)单一入口实现,通过pyproject.toml中[project.scripts]声明的letstest = "letstest.multitester:main"暴露为命令行工具。
工作原理与整体流程
四个阶段的工作流
从 multitester.py 的main()函数可以还原出完整流程:
第一阶段:准备本地仓库(git 对象选择)
- 默认克隆
https://github.com/certbot/certbot.git的当前分支; - 支持通过
--branch指定分支、通过--pull_request指定 PR 进行测试; - 克隆完成后打包为
le.tar.gz,等待上传到远端实例; - 所有动作在一个
tempfile.mkdtemp()创建的临时目录中进行,该目录同时也是日志目录。
第二阶段:准备 EC2 资源
- 读取 YAML 配置文件中的
targets列表; - 通过 boto3 会话(使用
aws_profile指定的 IAM 配置)连接 EC2; - 选择一个合适的子网(默认子网或名为
certbot-subnet的子网,要求开启自动分配公网 IP); - 创建或复用名为
certbot-security-group的安全组,放行 TCP 22(SSH)与 UDP 60000-61000(供 mosh 使用),见 make_security_group。
第三阶段:并行执行测试
- 为每个 target 启动一个独立的多进程 worker(
multiprocessing.Process); - 每个 worker 通过 Fabric 的
Connection建立 SSH 连接; - 依次执行:上传
le.tar.gz并解压 → 设置环境变量(公网 IP、私网 IP、主机名、PIP 源、OS 类型)→ 上传并运行指定的测试 bash 脚本,见 install_and_launch_certbot; - 测试通过
Manager.Queue传递任务与结果,避免multiprocessing.Queue的潜在死锁问题。
第四阶段:回收与清理
- 拉取每台实例上的 Certbot 运行日志(
/var/log/letsencrypt/letsencrypt.log或./certbot.log),追加到每台机器对应的输出日志; - 汇总结果为
results文件,格式为序号 目标名 pass/fail; - 默认情况下终止所有 EC2 实例;
--saveinstances可保留实例以便人工登录排错,见 cleanup。
实例自毁保护机制
为防止测试任务卡死导致 AWS 资源泄漏,make_instance在默认(非--saveinstances)模式下会注入两重保险:
InstanceInitiatedShutdownBehavior = 'terminate':实例关机即销毁;UserData写入#!/bin/bash\nshutdown -P +60:实例启动 60 分钟后自动关机。
同时_get_block_device_mappings会把所有 EBS 卷的DeleteOnTermination显式设为True,确保实例终止时磁盘一并回收,见 make_instance。
安装与配置
1. 准备开发环境
letstest 随 Certbot 的开发环境一起安装。在按 Certbot 官方贡献文档创建本地开发环境后,此包即可使用。该包依赖如下(见 pyproject.toml):
boto3/botocore:AWS SDK,负责 EC2 资源操作;fabric>=2:SSH 执行与文件传输(使用 2.x API);pyyaml:解析 targets 配置文件。
Python 版本要求>=3.10。
2. 配置 AWS 凭据
测试使用 AWS SDK for Python(boto3)操作 EC2,需要先配置凭据。README 指向 boto3 快速入门指南,核心步骤是使用 AWS CLI 配置 IAM 角色的密钥。multitester.py的 docstring 给出了完整示例(multitester.py):
aws configure --profile HappyHacker # 交互式输入 IAM 角色的 Access Key / Secret Key / region aws ec2 create-key-pair --profile HappyHacker --key-name MyKeyPair \ --query 'KeyMaterial' --output text > MyKeyPair.pem注意:
- 区域:建议在
~/.aws/config中为 profile 设置region = us-east-1,因为 targets.yaml 中列出的 AMI 均位于us-east-1; - 密钥命名约定:代码假定密钥文件名为
<keyname>.pem,并据此推断KEYNAME(见 multitester.py),因此MyKeyPair.pem对应密钥名MyKeyPair; - 若使用环境变量方式提供凭据,可将 aws_profile 参数传为
SET_BY_ENV,此时代码会把 PROFILE 置为None,交由 boto3 默认凭据链解析。
3. 准备 SSH 密钥文件
还需要一个包含受信 SSH 私钥的文件(即上一步create-key-pair生成的.pem文件),用于 Fabric 连接实例。multitester.py通过 FabricConfig的connect_kwargs.key_filename传入该密钥,见 main()。
使用方法
激活上述开发环境的虚拟环境后,在letstest/目录下执行:
letstest targets/targets.yaml /path/to/your/key.pem <profile name> scripts/<test to run>对应官方 README 中的用法。执行后会在本地生成一个临时目录(其路径会打印到终端),包含每台实例的日志文件(命名形如0_ubuntu24.04.log)以及汇总结果文件results。由于要等待实例启动、安装依赖并运行完整测试,整个过程耗时较长。
完整命令行参数
从 multitester.py 的 argparse 定义可以提取出全部参数:
| 参数 | 必填 | 默认值 | 说明 |
|---|---|---|---|
config_file | 是 | — | AWS 服务器集群的 YAML 配置文件 |
key_file | 是 | — | AWS 密钥文件(<keyname>.pem) |
aws_profile | 是 | — | AWS profile 名称(对应~/.aws/中的配置) |
test_script | 是 | test_apache2.sh | 要部署并运行的 bash 测试脚本路径 |
--repo | 否 | https://github.com/certbot/certbot.git | 要测试的 Certbot git 仓库 |
--branch | 否 | ~ | 要试跑的 git 分支 |
--pull_request | 否 | ~ | 要试跑的 certbot/certbot PR 编号 |
--merge_main | 否 | 关闭 | 若设置,将 PR 合并进 certbot/certbot 的 main 分支后再测 |
--saveinstances | 否 | 关闭 | 运行结束后不销毁 EC2 实例,便于排错 |
--alt_pip | 否 | 空 | 从中拉取候选发布包的 pip 源服务器 |
测试 PR / 分支 / 主干
main()中的 git 对象选择逻辑(multitester.py)展示了三种测试场景:
- 测 PR:
letstest targets.yaml key.pem profile scripts/test_apache2.sh --pull_request 1234,会执行git fetch origin pull/1234/head:lePRtest并 checkout;配合--merge_main会先git merge origin/main再测试,这正是 PR 合入前的冒烟验证; - 测分支:
--branch my-feature,使用git clone --branch <branch> --single-branch; - 测主干:默认行为,直接克隆仓库当前分支。
自定义测试脚本
test_script参数指向的脚本只是一段普通的 bash 脚本,运行时通过环境变量接收参数。README 指出scripts/test_apache2.sh是最好的参考范例。脚本头部注释明确了注入的环境变量(test_apache2.sh):
$OS_TYPE:操作系统类型(如ubuntu、centos),来自 targets YAML 中的type字段;$PUBLIC_IP、$PRIVATE_IP、$PUBLIC_HOSTNAME:实例的公网/私网 IP 与公网主机名;$PIP_EXTRA_INDEX_URL:--alt_pip指定的候选发布包源。
这些变量由 install_and_launch_certbot 通过 Fabric 的prefix()以export形式注入。源码注释特别说明了两点踩坑经验:Fabric 的run的env参数不可用(见 fabric issue #1744),且prefix()会在命令间插入&&,因此脚本内必须用 export 而非内联变量赋值。
test_apache2.sh本身演示了一个完整的 Apache 集成测试脚本:
- 按 OS 类型初始化 Apache:Ubuntu/Debian 系使用 apt 安装
apache2并调整000-default.conf的 ServerName;CentOS 系禁用 SELinux、安装httpd mod_ssl、创建站点目录与 VirtualHost 配置; - 引导依赖:调用
sudo letstest/scripts/bootstrap_os_packages.sh安装编译与运行依赖; - 安装 Python:通过 pyenv 安装 Python 3.10;
- 构建环境:
tools/venv.py -e acme -e certbot -e certbot-apache -e certbot-ci tox构建开发虚拟环境; - 启动 Pebble:用
venv/bin/run_acme_server --http-01-port 80在本地启动 Pebble ACME 测试服务器,并轮询等待其就绪(最多 150 秒); - 运行 Certbot:以 Pebble 为 ACME 服务器,对
$PUBLIC_HOSTNAME执行完整签发流程(--register-unsafely-without-email、--redirect、--no-verify-ssl等); - 断言与回归:检查生成的
options-ssl-apache.conf是否包含SSLSessionTickets(验证现代 TLS 配置生效),Ubuntu 上还会额外运行venv/bin/tox -e apacheconftest做 Apache 配置回归。
此外,脚本通过trap DumpPebbleLogsOnFailure EXIT在失败时自动倾倒 Pebble 日志,方便在 CI 日志中直接定位 ACME 交互层面的问题。
targets 配置文件格式
targets/targets.yaml 是默认的集群定义,核心结构为targets:下的列表,每个 target 包含四个字段:
| 字段 | 含义 | 示例 |
|---|---|---|
ami | 位于 us-east-1 的 AMI ID | ami-045a47a3b15302634 |
name | 目标名(用于日志命名与展示) | ubuntu24.04 |
type | 操作系统类型(传给测试脚本的$OS_TYPE) | ubuntu/centos |
virt | 虚拟化类型(hvm或 32 位系统的paravirtual,决定默认机型) | hvm |
user | SSH 登录用户名 | ubuntu/admin/ec2-user |
默认文件覆盖了 4 个目标:Ubuntu 24.04、Ubuntu 22.04、Debian 12、CentOS Stream 9,注释中明确说明所有机器必须使用 x86_64 架构,因为 Pebble 目前不发布其他架构的镜像。
机型选择逻辑在 create_client_instance:target 中可指定machine_type覆盖;否则hvm虚拟化默认使用t2.medium,32 位系统默认使用c1.medium。
关键实现细节与排错指引
子网与安全组的自动化
should_use_subnet(multitester.py)要求子网满足:map_public_ip_on_launch为真,且要么是可用区默认子网,要么名为certbot-subnet。若找不到可用子网,程序会打印提示并退出——这也是自建 VPC 时最容易踩的坑:需要创建开启"自动分配公网 IPv4"且命名为certbot-subnet的子网。
安全组certbot-security-group若不存在则自动创建(TCP 22 与 UDP 60000-61000),存在则复用。注意源码注释提示同名安全组无法重复创建,重复运行是安全的。
多进程并行与日志
main()使用multiprocessing.Manager().Queue分发任务(官方建议避免使用原生multiprocessing.Queue,因其实现缺陷在某些情况下会死锁)。每个 worker 进程把 stdout 重定向到自己的日志文件(test_client_process),主进程通过join(5 * 60)循环等待并定期输出.以保持 CI 心跳。全部完成后输出排序后的结果,任一失败则sys.exit(1),便于上层 CI 捕获失败信号。
已知限制(README Notes)
- Marketplace 镜像需人工接受条款:部分 AWS 官方镜像(如官方 CentOS、FreeBSD 镜像)需要在 AWS Marketplace 网页上接受用户条款,此步骤无法自动化;
- EC2 实例数配额:AWS EC2 默认 t2/t1 实例上限为 20 台,若 targets 超过该数量需通过在线表单申请提升配额。
与 Certbot 生态的协作位置
letstest 与仓库内其他测试设施分工明确:certbot-ci(certbot-integration-tests)在容器/本地环境中做 ACME 端到端测试;而 letstest 面向真实云主机的多发行版矩阵,是 Certbot 发布前跨 OS 兼容性验证的重要一环。其测试脚本复用仓库根部的tools/venv.py构建开发环境,并与 Pebble 测试 ACME 服务器配合,可在不触碰生产 Let's Encrypt 服务的前提下完成完整的证书签发流程验证。letstest/scripts/version.py还提供了一个读取certbot/src/certbot/__init__.py中版本号的小工具,供发布流程获取当前版本。
快速上手清单
aws configure --profile <profile>配置 IAM 凭据,区域设为us-east-1;aws ec2 create-key-pair ... > MyKeyPair.pem创建密钥并妥善保管;- 在 Certbot 开发环境中安装
letstest包; - 执行
letstest targets/targets.yaml MyKeyPair.pem <profile> scripts/test_apache2.sh; - 观察终端打印的临时日志目录,等待完成;失败时查看
results文件与各实例日志,配合--saveinstances保留实例进行人工排查。
- 网络安全
- CLI
- 后端
【免费下载链接】certbot
Certbot is EFF's tool to obtain certs from Let's Encrypt and (optionally) auto-enable HTTPS on your server. It can also act as a client for any other CA that uses the ACME protocol.
相关推荐
Certbot与自动化测试:使用pytest进行插件开发与集成测试
Certbot与自动化测试:使用pytest进行插件开发与集成测试 为什么自动化测试对Certbot插件至关重要 你是否还在手动测试Certbot插件?每次更新
网络安全CLI后端如何用foobox-cn打造你的专属音乐播放中心:新手完全指南
如何用foobox cn打造你的专属音乐播放中心:新手完全指南 你是否厌倦了千篇一律的音乐播放器界面?是否希望有一个既能管理本地音乐库又能收听网络电台的全能播放
桌面应用音视频KeyDB高性能Redis分支:5分钟快速上手与实战指南
KeyDB高性能Redis分支:5分钟快速上手与实战指南 KeyDB 是一个高性能的Redis分支,专注于多线程、内存效率和高吞吐量。作为Redis的现代化替代
数据库KV存储缓存数据存储
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考