Scert/backend/internal/nginxactivation/README.md

56 lines
6.4 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# Nginx 本地激活组件
本组件包含受限的 Nginx 管理证书事务及应用侧双层协调器。应用已接入协调与周期恢复,但正式部署、真实 Nginx 协调及完整自动续期仍须单独验收,不能仅凭组件测试或交叉编译通过就正式切流。
## 权限边界
- `scert-nginx` 独立命令只在 Linux 上运行,以 root 身份加载 root 所有且不可由其他用户写入的独立策略文件。
- 仅接受 systemd 提供的单个 Unix 流监听器,验证进程编号、描述符数量和固定 socket 路径;不自行监听 TCP、不删除 socket。
- 服务端通过 `SO_PEERCRED` 核对固定非 root UID;客户端同时验证 socket 路径及父目录和服务端内核 UID。
- 请求不能提供命令、配置路径、证书磁盘路径、上游地址或域名;这些值只能来自独立策略。策略引用的 Nginx 配置及其 include 依赖仍须由部署者维护为可信配置。
- `Directory` 及其版本目录为激活器所有的 0700 目录,私钥、证书、事务文件使用 0600。应用主进程不获得 Nginx 重载权限。
## 协议与事务
协议为四字节大端长度前缀和 JSON,版本为 1,帧上限为 2 MiB,拒绝未知字段和尾随内容。并发连接上限为四个;事务冲突直接返回失败,由协调者查询状态,不自动重放变更操作。
| 动作 | 行为 |
| --- | --- |
| `ready` | 检查不存在未决事务、双层 TLS 和专用证书材料一致、Nginx 配置合法 |
| `state` | 返回事务编号、状态和两张叶证书的 SHA-256,不返回私钥或磁盘路径 |
| `stage` | 验证候选,持久化事务并仅切换 Nginx,成功后返回随机事务编号 |
| `stage_request` | 接受应用预先保存的随机请求编号,先持久化占位再暂存;同一编号不允许重放 |
| `resolve_request` | 与暂存使用同一把锁,返回关联事务,或先持久化取消栅栏再返回未执行终态 |
| `commit` | 确认双层已使用候选证书,再记录提交 |
| `reconcile` | 依据实际上游证书回退或提交;无关证书、上游不可用或外部变更时保留未决事务 |
`stage` 的应答丢失不等于没有执行。调用方必须用 `state` 查询,并结合持久化的候选摘要核对事务,不能直接重新申请证书或重试暂存。重复 `commit` 不返回幂等成功,调用方须确认查询到的是同一事务的提交终态。`reconcile` 对已完成的同一事务返回原终态,不代表重新验证了当下入口状态。
应用协调器只使用 `stage_request`,并在签发前要求 `ready.request_fencing=true`。请求编号为 128 位随机数的规范十六进制文本,不接受任意路径。激活器保留每个请求的占位或取消记录,后续事务覆盖主事务日志也不会解除旧编号的重放保护。尚未进入事务的请求可由 `resolve_request` 取消;并发暂存持锁时恢复请求失败并等待下轮,不抢先报告取消。取消应答丢失后可查询同一编号,不重放变更操作。
协调记录仍兼容旧版本没有请求编号的记录,但不能为旧请求追溯建立可靠栅栏。旧记录无法确认对应事务时继续保持未决,需要维护人员核对,禁止直接清除。新应用与激活器必须配套升级,旧客户端可能拒绝新增的就绪字段。请求记录目前不自动清理,容量规划须包含这些小文件。
激活等待要求三次间隔 100 毫秒的新连接探测连续通过,每次严格核验证书链、域名、叶证书及 Scert 就绪响应。该检查降低平滑重载过程中偶然命中新工作进程导致的误判,不构成对未来所有连接的保证。
停止服务会取消活动请求并等待有界回退;监听器异常关闭报告错误。请求持有的私钥切片及帧缓冲在返回路径清理,但不声明能够擦除 Go 运行时或 JSON 解码器产生的所有内部副本。
## 接入前要求
发布包现提供独立 socket/service、拒绝直接使用的策略模板和 `--initialize` 命令。初始化从 root 受保护副本导入当前证书,核对双层 TLS 与就绪状态,仅创建专用材料,不修改或重载站点;已有状态或失败残留拒绝覆盖。部署步骤见 `deploy/nginx/Nginx辅助服务部署说明.md`,新增初始化用例尚待 Linux 执行,模板尚未完成 systemd 实机验收。
1. 安装独立 socket/service,固定调用 UID,初始化专用版本目录并让目标站点引用 `active.conf`。
2. 应用须持久化旧状态、候选摘要、激活阶段和关联事务;完整生命周期必须串行化,不能在恢复检查上游之后并发切换上游。
3. 覆盖代理暂存、上游配置持久化与内存切换、代理提交之间的中断及应答丢失,并在启动时先恢复再允许申请下一张证书。
4. 不可将本组件的 `Recover` 视作双层恢复。它只回退代理;`Reconcile` 也必须由了解应用持久化状态的协调者调用。
5. 应用等待自身 HTTPS 进入接收循环后开始周期恢复,每次最多 100 秒,结束后等待一分钟;关闭应用会取消并等待恢复。只有 `Handler()` 的桌面或嵌入式运行时不能充当管理 HTTPS 上游,签发前检查明确拒绝。
6. 协调记录归应用用户所有,允许中文或空格目录,同时保留 0700、所有者、父路径及链接检查;实际写入 Nginx 指令的激活目录仍限制字符。
7. 本协议不提供租约超时后强制覆盖、自动清理旧版本或通用 Nginx 管理接口。损坏记录、保存失败、无关证书或配置变动保留保护,不宣称已经完成无人值守续期验收。
## 验证范围
Windows 测试只能覆盖通用协议和 TLS 探测。Linux 测试覆盖目录、文件、Unix 身份、策略、事务及继承监听器;真实 Nginx 用例需显式指定 `SCERT_TEST_NGINX_BINARY`。不同 UID 测试需在隔离 root 单元中设置 `SCERT_TEST_ROOT_IPC=1`,只在临时目录中复制测试程序并降权子进程,不修改真实用户或正式 socket。
`TestCoordinatorWithRealNginxAndIPC` 使用独立 Nginx 进程和真实 Unix IPC,覆盖正常提交以及暂存、提交应答丢失。上游仍为测试 HTTPS 夹具,不等同于真实应用配置持久化、ACME 签发或正式 systemd 安装验收。2026-09-20 新增用例已交叉编译,当前目标主机身份尚待确认,未执行本轮 Linux 用例。
实机执行命令、程序摘要和失败修复记录见仓库 `doc/Linux生产流程测试记录.md`。