letsencrypt/pebble
GitHub: letsencrypt/pebble
一个用于测试 ACME 客户端实现的轻量级 RFC 8555 模拟 CA 服务器。
Stars: 756 | Forks: 171
# Pebble
[](https://github.com/letsencrypt/pebble/actions/workflows/checks.yml)
[](https://github.com/letsencrypt/pebble/actions/workflows/tests.yml)
[](https://coveralls.io/github/letsencrypt/pebble)
[](https://goreportcard.com/report/github.com/letsencrypt/pebble)
Pebble 是 [Boulder](https://github.com/letsencrypt/boulder) 的一个迷你版本,
是一个小型的 [ACME](https://github.com/ietf-wg-acme/acme) 测试服务器,
不适合用作生产环境 CA。
## !!! 警告 !!!

Pebble **不适用于生产环境**。Pebble 仅用于**测试**。
根据设计,Pebble 会在每次调用之间丢弃所有状态,并会
随机化用于签发的密钥/证书。
## 目标
Pebble 有几个顶层目标:
1. 提供简化的 ACME 测试前端
2. 为新的和破坏兼容性的 ACME 功能提供测试平台
3. 鼓励 ACME 客户端最佳实践
4. 积极构建防止非测试用途的防护措施
Pebble 旨在满足 ACME 客户端在开发 ACME v2 支持时,
需要一个更易于使用、独立的 Boulder 版本来测试其客户端的需求。
Boulder 是多进程的,需要繁重的依赖项(MariaDB、
gRPC 等),并且与其他项目的操作集成非常复杂。
在可能的情况下,Pebble 旨在成为新 ACME 协议功能的测试平台,
以便为后续的 Boulder 支持提供信息。Pebble 为 Boulder
开发人员提供了一种方法,可以比 Boulder 更激进地测试破坏兼容性的更改。
在 ACME 规范允许自定义/CA 选择的地方,Pebble
旨在做出与 Boulder 不同的选择。例如,Pebble 更改了
其资源和目录端点的路径结构,使其不同于
Boulder。目标是强调客户端规范兼容性,并
避免对 Boulder 和 Let's Encrypt 生产服务进行“过度拟合”。
最后,Pebble 将通过积极构建
使其在生产环境中使用不可能或非常不便的防护措施,来强制执行其仅用于测试的用途。Pebble 将不支持非易失性存储或执行之间的持久化。Pebble 还将随机化用于签发的密钥/证书。在可能的情况下,Pebble 将做出迫使客户端正确实现 ACME 的决定(例如,随机化 `/directory` 端点 URL 以确保客户端不对 URL 进行硬编码。)
## 限制
Pebble 缺少一些 ACME 功能(欢迎提交 PR!)。它目前不支持
预授权或通过证明对证书所有域名的授权来撤销由不同 ACME 账户签发的证书。
Pebble 不执行与 Boulder 相同的所有输入验证。某些将被 Boulder/Let's Encrypt 拒绝的域名可能与 Pebble 一起使用。
Pebble 不强制执行任何速率限制。它目前不是
用于测试您的客户端是否正确处理 Boulder/Let's Encrypt 速率限制的合适工具。
## 安装
1. [设置 Go](https://golang.org/doc/install)
2. 将 `~/go/bin` 添加到您的 $PATH 中,或者将 `GOBIN` 设置为一个已经在您的
$PATH 中的目录,以便 `pebble` 在您的 $PATH 中,方便执行。
- 一种方法是将 `export PATH=$PATH:$HOME/go/bin` 添加到您的 `~/.profile`
3. git clone https://github.com/letsencrypt/pebble/
4. cd pebble
5. go install ./cmd/pebble
## 用法
### Binary
假设 pebble 可以在您的 $PATH 中轻松访问:
```
pebble -config ./test/config/pebble-config.json
```
(否则将 `pebble` 替换为 `~/go/bin/pebble` 或 `$GOBIN/pebble`)
之后,您可以在 `https://localhost:14000/dir` 访问 Pebble 服务器的 ACME 目录。
### Docker
Pebble 包含一个 [docker-compose](https://docs.docker.com/compose/) 文件,该文件
将创建一个 `pebble` 实例,该实例使用 `pebble-challtestsrv` 实例进行
DNS 解析,并将正确的端口映射到主机系统。
要下载并启动容器,请运行:
```
docker-compose up
```
之后,您可以从主机访问 ACME API,
地址为 `https://localhost:14000/dir`,`pebble` 的管理界面
地址为 `https://localhost:15000`,`pebble-challtestsrv` 的管理
界面地址为 `http://localhost:8055`。
首先,您可能需要使用新的默认 IPv4 地址更新 `pebble-challtestsrv` DNS 数据,
以用于响应来自 `pebble` 的 `A` 查询:
```
curl --request POST --data '{"ip":"172.20.0.1"}' http://localhost:8055/set-default-ipv4
```
有关更多信息,请参阅 [pebble-challtestsrv
README](https://github.com/letsencrypt/pebble/blob/master/cmd/pebble-challtestsrv/README.md)。
如果您正在为 `pebble` 或 `pebble-challtestsrv` 运行一次性容器,
则需要手动映射端口。
```
docker run -p 14000:14000 -p 15000:15000 ghcr.io/letsencrypt/pebble:latest
docker run -p 5001:5001 -p 5002:5002 -p 5003:5003 -p 8053:8053 -p 8055:8055 -p 8443:8443 ghcr.io/letsencrypt/pebble-challtestsrv:latest
```
#### 预构建 Docker 镜像
Pebble 版本作为 Docker 镜像发布到
[Github Container Registry](https://github.com/orgs/letsencrypt/packages?repo_name=pebble)
使用 docker-compose 文件:
```
services:
pebble:
image: ghcr.io/letsencrypt/pebble:latest
command: -config /test/my-pebble-config.json
ports:
- 14000:14000 # ACME port
- 15000:15000 # Management port
environment:
- PEBBLE_VA_NOSLEEP=1
volumes:
- ./my-pebble-config.json:/test/my-pebble-config.json
```
使用 Docker 命令:
```
docker run -p 14000:14000 -p 15000:15000 -e "PEBBLE_VA_NOSLEEP=1" ghcr.io/letsencrypt/pebble
# 或
docker run -p 14000:14000 -p 15000:15000 -e "PEBBLE_VA_NOSLEEP=1" --mount src=$(pwd)/my-pebble-config.json,target=/test/my-pebble-config.json,type=bind ghcr.io/letsencrypt/pebble -config /test/my-pebble-config.json
```
### 默认验证端口
为了更容易测试 ACME 客户端并运行挑战响应服务器,
而无需 root 权限,Pebble 默认使用非特权高端口验证 ACME 挑战:
* **默认 HTTP-01 端口**: 5002
* **默认 TLS-ALPN-01 端口**: 5001
可以通过编辑提供给 `pebble` 的 Pebble `-config` 文件中的 `"httpPort"` 和 `"tlsPort"` 值来更改这些端口。
### 严格模式
Pebble 积极支持新协议功能和破坏向后
兼容性更改的目标与其为客户端在集成测试中
提供简单、轻量级 ACME 测试服务器的目标略有冲突。
一方面,我们希望快速引入破坏性更改,并将 Pebble 用作
此类的测试平台。另一方面,我们要确保不会过于频繁地破坏使用 Pebble 的客户端集成测试。
作为满足这两个需求的平衡,Pebble 支持 `-strict` 标志。通过
运行 Pebble 时使用 `-strict false`,将禁用已知会破坏客户端兼容性的更改。
目前,我们默认将 `-strict` 设置为 false,但这**将在未来更改**。
如果您将 Pebble 用于集成测试,并且比起尽快了解破坏性更改
更看重可靠性,请显式运行带有 `-strict false` 的 Pebble。
### DNS Server
默认情况下,Pebble 使用系统 DNS 解析器,这可能意味着缓存会导致
DNS-01 验证出现问题。这也可能意味着不执行 DNSSEC 验证。
您应该根据您的
需求配置系统的递归 DNS 解析器,或者使用 `-dnsserver` 标志定义 DNS 服务器的地址。
```
pebble -dnsserver 10.10.10.10:5053
pebble -dnsserver 8.8.8.8:53
pebble -dnsserver :5053
```
您可能会发现将 `pebble` 的 `-dnsserver` 设置为您在启动 `pebble-challtestsrv` 实例时用作 `-dnsserver` 参数的地址很有用。这将
让您轻松地为 Pebble 提供 DNS 数据。请参阅包含的
`docker-compose.yml` 和 [pebble-challtestsrv
README](https://github.com/letsencrypt/pebble/blob/master/cmd/pebble-challtestsrv/README.md)
以获取更多信息。
### 全速测试
默认情况下,Pebble 会在
各个挑战验证尝试之间休眠随机秒数(从 0 到 15)。这确保客户端不会
通过观察对挑战响应的单个请求来假设挑战何时从 CA 端解决。相反,客户端必须轮询
挑战以观察状态,因为 CA 可能会发送许多验证请求。
要在没有人工休眠的情况下“全速”测试签发,请将环境
变量 `PEBBLE_VA_NOSLEEP` 设置为 `1`。例如:
`PEBBLE_VA_NOSLEEP=1 pebble -config ./test/config/pebble-config.json`
休眠的最大秒数可以通过定义 `PEBBLE_VA_SLEEPTIME` 来配置。它必须设置为正整数。
### 跳过验证
如果您想避免为真实的 HTTP-01、DNS-01 或 TLS-ALPN-01 验证请求搭建挑战响应服务器的麻烦,Pebble
支持一种将挑战验证请求始终视为成功的模式。
默认情况下,此模式处于禁用状态,并且会执行挑战验证。
要使所有挑战 POST 请求成功而不执行任何验证,请运行:
`PEBBLE_VA_ALWAYS_VALID=1 pebble`
### 无效 Anti-Replay Nonce 错误
`urn:ietf:params:acme:error:badNonce` 错误类型旨在可重试。
当收到此错误时,客户端应向 `/new-nonce` 端点发出后续请求(或使用错误响应中的 nonce)以重试失败的请求,而不是直接退出。
Boulder 的经验表明,许多 ACME 客户端不会优雅地重试
无效的 nonce 错误。为了帮助确保未来的 ACME 客户端能够
默认优雅地处理这些错误,**Pebble 会将 5% 的所有有效 nonce 拒绝为无效**。
可以使用环境变量 `PEBBLE_WFE_NONCEREJECT` 配置被拒绝的有效 nonce 的百分比。例如,要将 90% 的良好 nonce 拒绝为无效而不是 15%,请运行:
`PEBBLE_WFE_NONCEREJECT=90 pebble`
要**从不**拒绝有效 nonce 为无效,请运行:
`PEBBLE_WFE_NONCEREJECT=0 pebble`
### 对象重用
RFC 允许重用多个对象。
**客户端应该准备好 ACME 服务器可能会重用任何给定的对象类型,无论 Pebble 是否为该对象实现重用策略。**
Pebble 和 Boulder 在任何给定时间__可能__或__可能不__实现相同的对象重用策略。存在一份关于 Boulder 的 [ACME 实现细节](https://github.com/letsencrypt/boulder/blob/main/docs/acme-implementation_details.md) 文档,其中包含有关 Boulder 如何处理此问题的一些信息。
#### 订单重用
RFC 允许 ACME 服务器重用订单。Pebble 目前不会重用订单;然而 Boulder 确实至少在一种情况下重用订单:
* 如果一个账户请求的新订单与该账户现有的“pending”或“ready”订单完全相同,该订单将被重用。
#### 授权重用
ACME 服务器可以选择在新订单中重用先前订单的授权。ACME 客户端 [应该始终检查](https://tools.ietf.org/html/rfc8555#section-7.1.3) 新订单及其授权的状态,以确认它们是否需要响应任何挑战。
#### 有效授权重用
**Pebble 将在新订单中重用有效授权(如果存在),概率为 50%**。
可以使用环境变量 `PEBBLE_AUTHZREUSE` 控制百分比,例如,要始终重用授权:
`PEBBLE_AUTHZREUSE=100 pebble`
#### 待处理授权重用
Pebble 目前不会跨订单重用待处理授权,但是其他 ACME 服务器 - 特别是 Boulder - 将重用待处理授权。
### 避免客户端 HTTPS 错误
Pebble 仅可通过 HTTPS 访问,并使用由 [测试
CA](test/certs/pebble.minica.pem) 生成的 [测试
证书](test/certs/localhost/cert.pem)(有关更多信息,请参阅 [`test/certs/`
目录](test/certs/README.md))。
由于 Pebble 测试 CA 不属于任何默认 CA 信任存储,您必须将
[`test/certs/pebble.minica.pem`](test/certs/pebble.minica.pem) 证书
添加到客户端的受信任根配置中以避免 HTTPS 错误。您的客户端
应该提供一个运行时选项来指定受信任根 CA 列表。
**重要提示:不要将 `pebble.minica.pem` CA 添加到系统范围的信任
存储或任何生产系统/代码库中。此 CA 的私钥是
故意在此 [仓库中公开的](test/certs/pebble.minica.key.pem).**
### 管理界面
为了简化 Pebble 与测试系统的交互,特定的 HTTP
管理界面在与 ACME 协议不同的端口上公开,
并提供几个有用的测试端点。
这些端点是 Pebble 及其内部行为特有的,不属于
定义 ACME 协议的 RFC 8555。
管理界面由 `pebble-config.json` 中的 `managementListenAddress` 字段配置,该字段定义了管理
界面将监听的地址和端口。将 `managementListenAddress` 设置为空字符串或 `null`
以禁用它。
`test/config/pebble-config.json` 中定义的此管理界面的默认配置是在端口 15000 上监听任何地址:
```
"managementListenAddress": "0.0.0.0:15000",
```
#### CA 根证书和中间证书
请注意,CA 的根证书和中间证书在每次
启动时都会重新生成。可以通过向 `https://localhost:15000/roots/0`
和 `https://localhost:15000/intermediates/0` 发送 `GET` 请求分别检索它们。
您可能需要根证书来验证生成的证书的完整信任链,
例如在端到端测试中。
这些证书的私钥也可以通过向 `https://localhost:15000/root-keys/0` 和https://localhost:15000/intermediate-keys/0` 发送 `GET` 请求分别检索。
**重要提示:不要将 Pebble 的根证书或中间证书添加到您用于
普通浏览或用于非测试目的的信任存储中,因为 Pebble 及其生成的密钥未经过审计或未达到与 Let's Encrypt 生产 CA 及其密钥相同的标准。此外这些密钥由 Pebble 公开,并将在进程终止后立即丢失:因此它们不安全,仅用于测试。**
如果通过将 `PEBBLE_ALTERNATE_ROOTS` 设置为
正整数来启用备用根链,则可以通过向 `https://localhost:15000/roots/0`、`https://localhost:15000/root-keys/1`
`https://localhost:15000/intermediates/2`、`https://localhost:15000/intermediate-keys/3`
等发送 `GET` 请求来检索这些根证书。这些端点还会为所有备用根和中间证书及密钥发送 `Link` HTTP 标头。
可以使用 `PEBBLE_CHAIN_LENGTH` 控制证书链的长度,其
默认值和最小值为 `1`(叶 + 1 个中间证书)。对于更高的值,Pebble 将
在叶和根之间包含额外的中间证书。额外的中间证书 *不* 通过管理界面公开。
#### 证书状态
可以通过向 `https://localhost:15000/cert-status-by-serial/` 发送 `GET` 请求来查询证书(PEM 格式)及其吊销状态,其中 `` 是证书序列号的十六进制表示(无 `0x` 前缀)。
可以通过以下方式获取:
```
openssl x509 -in cert.pem -noout -serial | cut -d= -f2
```
端点将信息作为 JSON 对象返回:
```
$ curl -ki https://127.0.0.1:15000/cert-status-by-serial/66317d2e02f5d3d6
HTTP/2 200
cache-control: public, max-age=0, no-cache
content-type: application/json; charset=utf-8
link: ;rel="index"
content-length: 1740
date: Fri, 12 Jul 2019 22:14:21 GMT
{
"Certificate": "-----BEGIN CERTIFICATE-----\nMIIEVz...tcw=\n-----END CERTIFICATE-----\n",
"Reason": 4,
"RevokedAt": "2019-07-13T00:13:20.418489956+02:00",
"Serial": "66317d2e02f5d3d6",
"Status": "Revoked"
}
```
### OCSP Responder URL
Pebble 不支持作为响应者的 OCSP 协议,因此不会在
签发的证书中设置 OCSP Responder URL。但是,如果您设置了与 Pebble 并排运行的正确
OCSP Responder,您可能需要设置此 URL。
这可以通过将 Pebble 使用的 `pebble-config.json` 的 `ocspResponderURL` 字段
设置为非空字符串来实现:在这种情况下,此字符串将用于
所有签发证书的相应字段。
例如,要让 Pebble 签发指示客户端检查 URL `http://127.0.0.1:4002`
以检索证书的 OCSP 状态的证书,请运行 Pebble 并使用包含以下内容的 `pebble-config.json`:
```
"ocspResponderURL": "http://127.0.0.1:4002",
```
### 列出订单
Pebble 支持根据
[RFC 8555, Section 7.1.2](https://tools.ietf.org/html/rfc8555#section-7.1.2.1) 枚举 ACME 账户对象的所有订单。默认情况下,每页返回三个
订单,以便于测试分页。可以通过
将 `PEBBLE_WFE_ORDERS_PER_PAGE` 环境变量设置为正整数来修改此数字。例如,
要每页有 15 个订单,请运行
`PEBBLE_WFE_ORDERS_PER_PAGE=15 pebble`
标签:ACME, Boulder, EVTX分析, EVTX分析, Go, LangChain, Let's Encrypt, LNA, Python工具, RFC 8555, Ruby工具, SOC Prime, SSL/TLS, 安全测试, 安全监控, 开发工具, 攻击性安全, 日志审计, 模拟环境, 测试服务器, 自动化证书管理, 证书颁发机构, 请求拦截, 轻量级