From 119b8ae5d66d00e830c68d584cf484a3c344dee8 Mon Sep 17 00:00:00 2001 From: xuans Date: Sun, 20 Sep 2026 03:24:36 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BF=AE=E6=AD=A3=E7=94=9F=E4=BA=A7=E6=8E=A2?= =?UTF-8?q?=E6=B5=8B=E4=B8=8E=E5=A4=87=E4=BB=BD=E8=AF=B4=E6=98=8E=E5=B9=B6?= =?UTF-8?q?=E8=AE=B0=E5=BD=95=E9=83=A8=E7=BD=B2=E9=98=BB=E5=A1=9E=E8=AF=81?= =?UTF-8?q?=E6=8D=AE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- deploy/README.md | 60 ++++++++++++++++++++-------- doc/Linux生产流程测试记录.md | 60 ++++++++++++++++++++++++++++ 2 files changed, 104 insertions(+), 16 deletions(-) diff --git a/deploy/README.md b/deploy/README.md index 33c581e..369ac5f 100644 --- a/deploy/README.md +++ b/deploy/README.md @@ -102,13 +102,35 @@ Scert 提供两个用途不同的无认证检查接口: - `GET /healthz`:只表示进程和 HTTP 服务仍可响应,不能证明 DNS 凭据、TLS 文件和数据库可用。 - `GET /readyz`:生产就绪检查,只有初始化完成、已配置的敏感凭据可解密、TLS 证书与私钥为普通文件且数据库可访问时才返回 HTTP `200`。 -安装、升级、恢复和配置变更后必须同时检查: +安装、升级、恢复和配置变更后必须同时检查两个接口,并验证证书名称和可信链。以下示例在部署服务器上执行;域名、上游端口和 CA 文件必须与实际配置一致,不能直接使用示例域名: ```bash -curl -k --fail --silent --show-error https://127.0.0.1:9004/healthz -curl -k --fail --silent --show-error https://127.0.0.1:9004/readyz +management_domain=scert.example.com +upstream_port=9004 +ca_bundle=/etc/ssl/certs/ca-certificates.crt +curl --noproxy '*' --fail --silent --show-error --max-time 15 \ + --cacert "$ca_bundle" --resolve "${management_domain}:${upstream_port}:127.0.0.1" \ + "https://${management_domain}:${upstream_port}/healthz" +curl --noproxy '*' --fail --silent --show-error --max-time 15 \ + --cacert "$ca_bundle" --resolve "${management_domain}:${upstream_port}:127.0.0.1" \ + "https://${management_domain}:${upstream_port}/readyz" ``` +`--resolve` 仅将连接定向到回环地址,仍按 URL 中的配置域名发送 SNI 并验证 TLS。私有 CA 场景应将 `ca_bundle` 改为已通过可信渠道核验、仅管理员可修改的 CA 文件,不得使用 `-k` 或 `--insecure`。这里检查的是上游,不代表 Nginx 或公网 DNS 已通过验收。 + +反向代理模式还需在独立客户端按正常 DNS 检查公开入口,不使用指定解析或隧道。以下公开端口必须与 `server.proxy_https_port` 一致;直接模式使用实际对外 HTTPS 端口: + +```bash +management_domain=scert.example.com +public_port=443 +curl --noproxy '*' --fail --silent --show-error --max-time 15 \ + "https://${management_domain}:${public_port}/healthz" +curl --noproxy '*' --fail --silent --show-error --max-time 15 \ + "https://${management_domain}:${public_port}/readyz" +``` + +公开入口默认使用客户端系统信任库;私有 CA 环境须显式指定经过核验的 CA 文件。HTTP `200` 之外还应核对 `/readyz` JSON 的 `status` 为 `ready`;TLS 失败、错误响应或域名解析不符都不能算通过。 + `/readyz` 失败时返回 HTTP `503` 和不包含敏感引用的原因码: - `setup_incomplete`:初始化尚未完成。 @@ -170,7 +192,7 @@ location / { 管理域名由部署配置决定,不固定为示例域名。使用非标准 HTTPS 端口时,必须设置 `server.proxy_https_port`,初始化向导和管理设置均提供对应字段。省略该字段或设为 `0` 时,代理公开端口仍为 `443`;直接模式忽略该字段并使用 `server.port`。 -例如本次授权测试入口为 `web.apmmk.cn`,HTTP `8003` 跳转至 HTTPS `8004`,核心服务仅监听 `127.0.0.1:9004`: +例如自定义端口方案可以使用 `web.apmmk.cn`,HTTP `8003` 跳转至 HTTPS `8004`,核心服务仅监听 `127.0.0.1:9004`。以下仅为配置示例,不代表当前测试环境或生产环境的实际域名、端口: ```json { @@ -218,12 +240,12 @@ server { `Host` 必须保留外部端口,否则同源安全检查可能拒绝请求。跳转目标使用明确配置的域名,不直接信任来访 `Host`。证书路径须替换为实际签发路径;证书更新后需要执行配置检查并平滑重载 Nginx。安全组仅开放所需公开端口,不开放内部 `9004`,不改动其他应用占用的 `80/443`。先验证真实证书、DNS、登录、会话和重置链接,再判定部署通过。 -### 默认端口示例 +### 标准公开端口示例 -开发阶段可以使用测试域名 `web.xuans.com` 验证 Web 页面和反向代理链路。推荐让 Scert 只监听本机端口 `9004`,由 Nginx 监听 `9003` 接收测试访问并转发: +使用标准公开端口时,让 Scert 只监听本机端口 `9004`,由 Nginx 在共享 `443` 上按域名接收访问并转发。下面的 `scert.example.com` 必须替换为实际配置域名: ```text -测试访问 HTTPS 9003 +公开访问 HTTPS 443 ↓ Nginx ↓ https://127.0.0.1:9004 @@ -237,7 +259,11 @@ Scert "server": { "host": "127.0.0.1", "port": 9004, - "https_mode": "proxy" + "https_mode": "proxy", + "proxy_https_port": 443 + }, + "web": { + "hostname": "scert.example.com" } } ``` @@ -247,15 +273,15 @@ Nginx 示例: ```nginx server { listen 443 ssl http2; - server_name web.xuans.com; + server_name scert.example.com; - ssl_certificate /etc/letsencrypt/live/web.xuans.com/fullchain.pem; - ssl_certificate_key /etc/letsencrypt/live/web.xuans.com/privkey.pem; + ssl_certificate /实际证书目录/fullchain.pem; + ssl_certificate_key /实际证书目录/privkey.pem; location / { proxy_pass https://127.0.0.1:9004; proxy_ssl_server_name on; - proxy_ssl_name web.xuans.com; + proxy_ssl_name scert.example.com; proxy_ssl_verify on; proxy_ssl_trusted_certificate /etc/ssl/certs/ca-certificates.crt; proxy_ssl_verify_depth 3; @@ -268,17 +294,19 @@ server { } ``` -如果需要 HTTP 自动跳转,再配置并开放 `80`;正式公网访问通常使用 `443`,开发测试访问使用 Nginx 的 `9003`。Scert 内部端口 `9004` 和 Nginx 测试端口 `9003` 都不应加入公网防火墙规则。端口可以在配置文件的 `server.port` 修改,修改后需要重启 Scert;如果改为直接对外监听,则还需要同步调整防火墙和安全组规则。 +如果需要 HTTP 自动跳转,再为实际管理域名配置 `80` 到 `443` 的跳转。共享 Nginx 时仅增加该域名的命名虚拟主机,不修改其他站点或增加冲突的默认站点。Scert 内部端口 `9004` 不应加入公网防火墙规则;修改 `server.port` 后需要同步调整 Nginx 上游并重启 Scert。 -`web.xuans.com` 仅用于开发阶段测试,不能作为生产环境证书、DNS、ACME 或最终 HTTPS 验收依据。 +示例域名与配置不能作为生产环境证书、DNS、ACME 或最终 HTTPS 验收依据。 开发环境使用自签名证书时,应优先将测试 CA 加入独立信任文件。只有在隔离的临时开发环境中,才允许短时使用 `proxy_ssl_verify off`;该设置禁止复制到生产配置。 ## 备份与恢复 -完整备份包含配置、主密钥、加密敏感配置、SQLite 一致性快照或 MySQL 导出、证书目录以及带 SHA-256 的 `manifest.json`。备份目录必须由 `Scert` 用户控制并保持 `0700`,不得放入 Web 根目录或公开共享目录。 +完整备份包含配置、主密钥、加密敏感配置、SQLite 一致性快照、MySQL 导出或 PostgreSQL 自定义格式归档、证书目录以及带 SHA-256 的 `manifest.json`。备份目录必须由 `Scert` 用户控制并保持 `0700`,不得放入 Web 根目录或公开共享目录。 -PostgreSQL 的内置完整备份恢复尚未实现,`backup`、`restore` 会明确拒绝,不会遗漏数据库却报告成功。三库初始化可用不等于三库运维能力已完整验收;选择 PostgreSQL 时仍须补齐原生数据库备份、配置/凭据/证书保护及恢复演练,当前不能声明这一能力已具备生产准入。 +PostgreSQL 的 `backup`、`restore` 已接入官方 `pg_dump`、`pg_restore`。两个工具必须具有相同主版本且至少为 16,`pg_dump` 主版本不得低于数据库服务端主版本;连接必须保持 `sslmode=verify-full`。工具缺失、版本不兼容或 TLS 校验失败都会中止,不会发布遗漏数据库的备份。 + +PostgreSQL 自动恢复仅支持原目标数据库、对象清单及所有者一致的场景,不支持空库灾难恢复、跨数据库或跨结构迁移。集群角色、角色密码、表空间定义、服务端配置及外置数据库 CA/客户端证书须另行保护;本机维护锁也不能阻止其他主机写入,恢复前必须停止所有相关实例和外部结构变更任务。归档可能包含可执行 SQL,只能恢复可信来源的备份。已有隔离测试不替代当前部署环境的恢复演练,不能据此声明生产验收通过。 备份和恢复都会获取跨进程维护锁;如果主服务仍在运行会直接拒绝。运维时仍必须显式停服,避免外部工具或尚未纳入锁协议的操作修改证书目录: diff --git a/doc/Linux生产流程测试记录.md b/doc/Linux生产流程测试记录.md index 8270aad..6473d0c 100644 --- a/doc/Linux生产流程测试记录.md +++ b/doc/Linux生产流程测试记录.md @@ -1,5 +1,65 @@ # Linux 生产流程测试记录 +## 当前进展:发布说明修正与入口、依赖审计 + +2026-09-20 03:12 起接续,03:22 完成本节所列检查。本节为最新状态,下文按各自时间保留历史证据。实际仓库仍为 `D:\Desktop\Scert`,目标为 `45.136.13.241`,本次管理域名为 `odacm.cn`;这些测试参数不硬编码进产品,也不构成验收依据。本轮未登录服务器、上传产物、修改 DNS/Nginx、修改系统信任库或清空共享数据库,完整生产部署验收尚未通过。 + +### 需求与任务状态 + +- [✓] 接回 Windows 与 Linux 目标的两项 `govulncheck`,均已正常退出;没有重复启动未结束任务。 +- [✓] 修改前检查点 `71fe48c` 已推送,暂存区事先为空;旧补丁、二进制、脚本及历史构建目录全部保留。 +- [✓] 修正 `deploy/README.md`:生产探测不再跳过 TLS,分别说明回环上游和正常 DNS 公开入口验证;统一标准 `443` 示例,旧 `8003/8004` 仅保留为自定义端口示例。 +- [✓] 按当前实现修正 PostgreSQL 备份恢复说明,注明官方工具、版本、严格 TLS、同目标同对象清单限制及独立保护的集群资源,不扩大为灾难恢复已验收。 +- [✓] 复核 Go/Wails 的 `-trimpath` 和前端禁用源码映射,发布检查及 CLI 定向回归通过,已有 Linux 产物路径扫描再次通过。 +- [!] SSH 新指纹尚未通过可信控制台核对;没有发送密码、更新 `known_hosts` 或接受新主机身份。 +- [!] 两家 HTTPS DNS 查询仍指向旧地址,当前入口 TLS 检查失败;不可用固定解析探测替代域名生产验收。 +- [!] 本机 PowerShell 有效策略仍为 `Restricted`,没有修改或绕过;最新正式发布脚本、Linux 双层集成与部署流程仍未完成。 + +### 入口与主机身份 + +本机 `Resolve-DnsName odacm.cn -Type A -DnsOnly` 返回 `198.18.1.249`。严格 HTTPS DoH 查询 Cloudflare 与 Google 均返回 `odacm.cn A 47.108.78.12`、TTL 600,不是本次目标 `45.136.13.241`。这是两个递归解析器的当前观察,不宣称已直接验证权威 DNS;本机普通 DNS 的结果不能替代公共解析结论,也没有据此更改网络或 DNS 设置。 + +以下三项均已实际执行,无跳过证书验证: + +```text +curl.exe --noproxy "*" --fail --silent --show-error --max-time 15 https://odacm.cn/readyz +curl.exe --noproxy "*" --fail --silent --show-error --max-time 15 --resolve odacm.cn:443:45.136.13.241 https://odacm.cn/readyz +curl.exe --noproxy "*" --silent --show-error --max-time 15 --resolve odacm.cn:80:45.136.13.241 -I http://odacm.cn/ +``` + +前两项返回 curl 错误 35:`schannel: failed to receive handshake, SSL/TLS connection failed`;第三项返回错误 52:`Empty reply from server`。只能说明本机所经网络路径上的请求失败,不能证明目标 Nginx 配置、服务状态或证书根因;透明代理等网络因素仍未排除。 + +03:21 左右,Paramiko 无认证握手读取到 Ed25519 指纹 `SHA256:cVoSXsYmhALjAdN2Gso3JvbnvYQCQBFuRv3IZjFvzsE`,`authenticated=False`。它与历史可信值 `SHA256:XN9mJ75b4CJsFPZ7fbkAmU1yFxKZ4Tw01z8TN2EJMlk` 不同;网络上反复读到同一新公钥不构成可信确认。须在服务商可信控制台执行 `ssh-keygen -lf /etc/ssh/ssh_host_ed25519_key.pub` 后核对,再决定是否认证。 + +### 依赖与回归证据 + +```text +go mod verify +govulncheck ./... +GOOS=linux GOARCH=amd64 CGO_ENABLED=0 govulncheck ./... +govulncheck -show verbose ./... +npm.cmd audit --omit=dev --json +go test -trimpath -count=1 -p=2 ./internal/releasearchive ./internal/cli +git diff --check +``` + +Go 命令在 `backend` 执行,npm 命令在 `frontend` 执行;Linux 环境变量一行是目标配置的简写,实际通过 PowerShell 子进程环境设置。`go mod verify` 返回 `all modules verified`。两平台漏洞扫描均报告调用路径零项、导入包零项、依赖模块一项;Windows 详细报告将其定位为 `GO-2026-5932`,涉及 `golang.org/x/crypto@v0.56.0` 中不再维护的 `openpgp` 包,无修复版本,当前代码未导入受影响包或调用其符号。没有为消除模块提示而移除仍需要的加密依赖,也不能将本结果描述成所有依赖完全没有已知风险。 + +前端生产依赖审计报告零漏洞,不包含开发依赖,也不代表未来漏洞保证。发布检查包与 CLI 回归均通过;真实 PostgreSQL 集成入口未提供官方工具和隔离环境参数,本轮不算新增真实数据库演练。部署说明的两个 JSON 配置块通过解析检查,差异检查无错误;没有在 Linux 上执行新文档中的 Nginx 配置或健康探测示例。 + +### 本地路径要求与产物边界 + +重新调用 `scert-release --verify-only`,对 `.runtime/clean-path-artifacts-20260920-0243/` 的三个 Linux 程序与整个资源目录,以及 `.runtime/app-integration-20260920-0307/app.test` 执行构建标记和路径扫描,均通过。扫描参数包含当前与旧工作区、用户目录、实际 Go 工具链及缓存、Go/Node 安装目录与临时目录;这些参数不写入产物。已有 Web 产物未找到 `.map` 文件。 + +这两处是前序已生成的核验产物,本轮没有重新编译完整发布包,也没有把新部署说明复制到旧产物中;此前记录的摘要及源码版本边界继续适用。正式候选必须从最终提交重新运行完整发布脚本,生成清单和校验文件并通过同样检查后再部署。模块导入路径、相对文件名和运行时部署路径不等于本机构建绝对路径,裁剪要求不删除这些运行所需信息。 + +### 待解除的验收阻塞 + +- [ ] 通过可信控制台确认当前 SSH 主机身份;确认后先只读检查现场,不能沿用旧服务器 PID、端口或配置结论。 +- [ ] 核对 `odacm.cn` 的实际 DNS 配置与迁移范围,使其指向授权目标;分别验证权威/公共解析、本机解析及正常 DNS 的严格 HTTPS 入口。 +- [ ] 在获准的构建环境运行完整发布脚本,并在隔离 Linux 单元执行五个应用与 Nginx 双层场景,确认没有跳过。 +- [ ] 完成 root 辅助服务/systemd、中断恢复、最新候选部署、管理证书续期、目标推送、通知送达、升级回退与容量验收;未完成前不能宣告生产部署通过。 + ## 当前进展:真实应用与 Nginx 双层切换集成用例 2026-09-20 02:54 起接续。本节为最新状态,后续章节保留为历史证据。本轮没有登录服务器、部署程序、修改系统信任库、修改正式 Nginx 或清空共享数据库。完整生产部署验收尚未通过。