XFORCE-GAMES/auto-certs-client

GitHub: XFORCE-GAMES/auto-certs-client

一个自动轮换游戏服务器TLS证书的POSIX sh客户端,通过签名验证提升安全性和运维效率。

Stars: 0 | Forks: 0

# auto-certs shell 客户端 `auto_certs.sh` 是一个符合 POSIX `sh` 标准的客户端,游戏内容提供商安装在他们的主机上,用于保持其 TLS 证书为最新状态。它会轮询 auto-certs 服务器,下载新的证书包,进行原子化安装,运行内容提供商的重新加载钩子,并将结果回报给服务器。 代码刻意保持小巧、简洁,并以纯 shell 编写,供系统管理员在冷读时可在 30 分钟内完成审计。这种立场至关重要:拥有生产主机的内容提供商 MIS 团队必须能够在以 root 权限运行之前,确信其中没有后门。 ## 验证机制 每个已发布的版本都附带四个用于建立来源证明的文件: | 文件 | 它证明了什么 | |---|---| | `.tar.gz.release.sig` | **RSA-4096 分离签名**,覆盖压缩包。用于验证的公钥**固定在 `install.sh` 自身中** — 因此,想要分发恶意压缩包的攻击者要么必须伪造 RSA-4096 签名(在没有 AWS Secrets Manager 私钥的情况下这是不可行的),要么完全替换 `install.sh`。内容提供商审计一次 `install.sh`;此后,信任即转移到每个后续版本。 | | `.tar.gz.sigstore.json` | **无需密钥的 Sigstore 包**,用于透明日志审计。任何人(内容提供商 MIS、内部红队、第三方研究人员)都可以通过 `cosign verify-blob --bundle ...sigstore.json --certificate-identity-regexp ...` 来验证压缩包确实来自此 GitHub 仓库的 CI 流水线,而非旁路通道。 | | `.tar.gz.sbom.spdx.json` | **SPDX 软件物料清单**,列出压缩包中的每个文件。可在版本间进行可审计的差异比较。 | | `SHA256SUMS` | 每个文件的 SHA-256 哈希值。纯文本格式,易于与 GitHub 发布页面进行差异比较。 | `install.sh` 会先使用其固定的公钥验证 RSA-4096 签名,**然后**才解压压缩包。没有有效 `.release.sig` 的版本将被拒绝 — 不存在“跳过验证”的选项。 ## 快速开始(适用于安装前阅读此文档的内容提供商 MIS) 两步安装。默认流程将密钥以 0600 权限保存在文件中(`/etc/auto-certs/conf.d/.conf`),而不是在安装命令行中输入它们 — `argv` 值可能会记录在 `~/.bash_history`、`ps aux` 输出和通过 tee 录制的会话记录中。这是每个有凭证意识的 CLI(如 kubectl、gh、 doctl 等)采用的相同模式。向你发送安装说明的操作员可能会包含针对你环境定制的替代一步法变体;本文档记录的是对审计友好的默认方法。 **步骤 1 — 安装**(不在 argv 中传递密钥): ``` curl -sSL https://github.com/XFORCE-GAMES/auto-certs-client/releases/latest/download/install.sh \ | sudo sh -s -- --app ``` **步骤 2 — 将密钥粘贴到占位符配置中**(你的 `$EDITOR` 会防止它们进入 shell 历史记录): ``` sudo $EDITOR /etc/auto-certs/conf.d/.conf # 为以下每一行标题提供简体中文翻译。下方恰好有 7 行;请严格按照顺序输出 7 行翻译,每行一条。只输出翻译内容,无需其他任何说明。 # 重要提示:保留所有专业术语、专有名词、工具/库/框架名称以及技术行话的英文原样。例如:'Running Naabu' -> '运行 Naabu', 'Kubernetes Setup' -> 'Kubernetes 设置', 'API Reference' -> 'API 参考'。 ``` **步骤 3 — 编辑重新加载钩子**: ``` sudo $EDITOR /opt/auto-certs/reload.sh # 根据安装说明邮件中提供给您的值,填写空白的 API_TOKEN= 和 BUNDLE_PASSWORD= 行。 # 将 `exit 1` 默认值替换为您的重载命令,例如 service nginx reload # 或您的技术栈所需的任何命令。 ``` **步骤 4 — 验证**: ``` sudo /opt/auto-certs/launcher.sh --once --app ``` 安装程序会: 1. 将启动器放置到 `/opt/auto-certs/launcher.sh`。 2. 将有效负载(实际的获取/验证/安装逻辑)放置到 `/opt/auto-certs/payload-/`,并将 `/opt/auto-certs/current` 指向它。 3. 在 `/etc/auto-certs/conf.d/.conf`(权限 0600)放置一个每应用的占位符配置,其中 `API_TOKEN=` 和 `BUNDLE_PASSWORD=` 为空 — **你需要用安装说明邮件中的值编辑此文件**。 4. 如果不存在,则在 `/etc/auto-certs/machine_id` 生成每台机器的 UUID(请将此文件排除在任何黄金镜像密封之外,以便通过快照供应的子机器各自生成自己的 UUID)。 5. 在 `/opt/auto-certs/reload.sh` 放置一个占位符重新加载钩子 — **你需要编辑此文件**以执行你技术栈所需的操作。 6. 添加一个每日运行 `/opt/auto-certs/launcher.sh` 的 cron 条目。 如果你忘记填写 `API_TOKEN=` 或 `BUNDLE_PASSWORD=`,启动器将拒绝调用 API,并打印一个可操作的错误信息,引导你回到配置文件。运行 `sudo /opt/auto-certs/launcher.sh --validate-config` 可以一次性检查所有配置。 **在同一主机上支持多应用**:使用不同的 `--app` 值重新运行安装程序。现有的配置和重新加载钩子将被保留;只有二进制目录树会被升级。 ## CentOS 6 引导 如果你在 CentOS 6 主机上安装,并且步骤 1 中的标准 `curl | sh` 单行命令失败,出现以下错误: ``` curl: (60) SSL certificate problem: unable to get local issuer certificate ``` ...这是因为 CentOS 6 的 `ca-certificates` 包版本早于用于签名 `objects.githubusercontent.com`(GitHub 用于提供发布资源下载)的 Let's Encrypt 根证书。这是信任存储年龄与 TLS 验证之间的鸡生蛋问题。 **推荐的引导变通方法** — 仅对初始获取使用 `--insecure`: ``` curl --insecure -sSL \ https://github.com/XFORCE-GAMES/auto-certs-client/releases/latest/download/install.sh \ | sudo sh -s -- --app ``` 这对于**仅此次获取**是可接受的,因为: 1. **下载的 `install.sh` 携带了固定的 RSA-4096 公钥**,并使用它来验证发布压缩包的 `.release.sig`,**然后才解压**。`--insecure` curl 绕过**不会**绕过该验证 — 即使是能够完美替换压缩包的中间人攻击者,也必须伪造 RSA-4096 签名。 2. **安装后,客户端携带其自身捆绑的 Mozilla CA 证书包**,位于 `/opt/auto-certs/current/lib/cacert.pem`。后续所有获取都通过 `curl --cacert ...` 明确使用该证书包。你的系统 `ca-certificates` 包不再位于任何 auto-certs 操作的信任路径中。 **替代方案 — 先在现代主机上安装,然后 `scp` 文件**: 如果 `--insecure` 违反你的安全策略,可以在任何现代主机(RHEL 7+、Ubuntu 16+、macOS 等)上运行 curl,然后将生成的 `install.sh` `scp` 到 CentOS 6 主机并在本地运行: ``` # 在现代主机上: curl -sSL \ https://github.com/XFORCE-GAMES/auto-certs-client/releases/latest/download/install.sh \ -o install.sh scp install.sh user@centos6-host:/tmp/ # 在 CentOS 6 主机上: sudo sh /tmp/install.sh --app ``` `install.sh` 脚本本身在 CentOS 6 上运行良好;只有引导获取需要一个现代的 TLS 协议栈。 **为什么我们不推荐 `yum update ca-certificates`**:CentOS 6 上的 yum 也使用(同等陈旧的)系统信任存储来验证 `mirrorlist.centos.org`。更新路径本身在相同的信任链上是损坏的。它在某些配置下可以工作(通过 HTTP 的 vault.centos.org,或替换过的仓库 URL),但这些变通方法超出了我们的范围。上面的 `--insecure`-一次-然后-捆绑方法更可靠且操作范围更窄。 ## 故障排查 启动器支持几种不会影响生产状态的诊断模式: | 命令 | 它的功能 | |---|---| | `sudo /opt/auto-certs/launcher.sh --validate-config` | 解析 `/etc/auto-certs/conf.d/` 下的所有配置文件,报告哪些缺少 `API_TOKEN` 或 `BUNDLE_PASSWORD`。可随时安全运行。 | | `sudo /opt/auto-certs/launcher.sh --once --app ` | 针对单个应用的一次性运行:轮询服务器,如有新版本则安装,运行钩子,报告结果。绕过每日 cron 定时。 | | `sudo /opt/auto-certs/launcher.sh --once --app --diagnose` | 与 `--once` 相同,但会向标准输出写入详细的逐步跟踪信息。适用于首次安装验证。 | | `sudo /opt/auto-certs/launcher.sh --self-check` | 验证配置解析、所需工具、证书目录可写性、重新加载钩子存在性、磁盘上证书包的完整性。**不执行重新加载钩子** — 可在生产环境中安全运行。 | 如果问题仍然存在,`/var/log/auto-certs/.log` 下的日志包含结构化的逐步事件。失败的报告也会排队存放在 `/var/lib/auto-certs/queue//`,并在下一个 cron 周期重试;该目录通常应为空。 ## 仓库布局 ``` . ├── install.sh ← one-line installer + pinned release-signing pubkey ├── launcher.sh ← ≤60-line POSIX sh; locates payload, integrity-checks, execs ├── updater.sh ← sidecar that polls the server for newer payloads ├── payload/ │ ├── VERSION ← single-line semver (matched by git tag with `v` prefix) │ ├── auto_certs.sh ← main entry point — polling, install, hook, report │ └── lib/ │ ├── common.sh ← logging, redaction, timeout wrapper │ ├── http.sh ← curl+wget abstraction │ ├── crypto.sh ← openssl wrappers (sig verify, decrypt, x509) │ ├── atomic.sh ← atomic mv helpers │ ├── report.sh ← report-back assembly + redaction │ ├── server-pubkey.pem ← legacy in-payload trust anchor (pre-v0.4.0-rc15 fallback) │ └── cacert.pem ← Mozilla NSS CA bundle (refreshed via updater.sh) ├── reload.sh.placeholder ← explanatory comments + `exit 1` body ├── conf.d/ │ └── example.conf.template ← annotated config template ├── CHANGELOG.md ← curated release notes per tag ├── README.md ← this file ├── LICENSE └── SECURITY.md ← vulnerability disclosure ``` ## 操作约束 - 生产代码中**仅使用 POSIX `sh`** — 不使用 bash 特性(`[[ ]]`、`${var,,}`、`<<<`、数组、`function`、`local`)。 - **标准小型工具集**:`openssl`、`curl` *或* `wget`、`tar`、`mv`、`mktemp`、`sha256sum`(并有 `shasum -a 256` 作为备选)、`awk`、`grep`、`sed`、`cut`、`tr`。不依赖 `jq`、`systemctl` 或 GNU 特定的标志。 - **CentOS 6 的 `openssl` 版本是 1.0.1e** — 没有 `enc -pbkdf2` 标志,没有 `kdf` 子命令。信封格式使用单遍 HMAC-SHA256 密钥派生函数,通过 `openssl dgst -sha256 -hmac` 实现(自 openssl 1.0.0,2010年3月起可用);客户端使用服务器使用的相同 `(password, salt)` 计算相同的密钥,并运行 `openssl enc -aes-256-cbc -d -K -iv `。已在真实的 CentOS 6.8 / 7.9 / Ubuntu 16.04 低端主机上进行端到端实证验证。 - **标准的 `unzip` 不能解密 AES ZIP 文件** — 我们不提供 ZIP 格式。证书包是 `tar` + `openssl enc -aes-256-cbc`。 - **分离签名验证是解密的硬性前提条件**。固定的 RSA-4096 公钥 — 由 `install.sh` 在安装时根据其自身嵌入的 heredoc 写入到 `${INSTALL_ROOT}/server-pubkey.pem`(即 `/opt/auto-certs/server-pubkey.pem`) — 用于在尝试解密之前验证服务器在每个加密信封上的签名。相同的密钥文件(与 `install.sh` heredoc 字节完全一致)也是 `updater.sh` 的持久信任根;它位于自动更新的有效负载区域之外,因此未来恶意的有效负载无法轮换其自身的公钥来伪造发布签名。(v0.4.0-rc15 之前的安装会从 `payload/lib/server-pubkey.pem` 读取,该文件仍作为向后兼容的回退方案提供。) - **重新加载钩子失败时没有自动回滚**。新证书包保留在磁盘上;旧的内存中证书继续提供服务,直到有东西触发重新加载。失败会被回报;操作员通过每应用聊天组通知内容提供商。 - **源代码必须能在 <30 分钟内由非专业系统管理员完成审计**。没有花哨的技巧。没有代码压缩。纯 shell 脚本。 ## 了解更多 - **[CHANGELOG.md](CHANGELOG.md)** — 每个版本的变更内容。 - **[SECURITY.md](SECURITY.md)** — 如何报告漏洞。 - **[Releases 页面](https://github.com/XFORCE-GAMES/auto-certs-client/releases)** — 每个签名的压缩包,附带软件物料清单 + cosign 证书包 + RSA `.release.sig` + SHA256SUMS。 - **你的提供商提供的操作员手册** — 你的 auto-certs 服务操作员维护内部操作手册(令牌轮换、证书包密码轮换、JKS 密码更改、重新加载钩子参考模式),并根据请求与内容提供商 MIS 分享。请通过每应用聊天组询问。
标签:CentOS, POSIX shell, RSA-4096, SBOM, SHA-256, Shell脚本, Sigstore, TLS/SSL, 原子安装, 安全测试工具, 游戏控制面板, 游戏服务器, 硬件无关, 签名验证, 网络安全, 自动化证书续期, 自动化运维, 证书管理, 运维工具, 通配符证书, 隐私保护, 零依赖