108 行
10 KiB
Markdown
108 行
10 KiB
Markdown
# ARM 公网健康监控受控部署
|
||
|
||
## Goal
|
||
|
||
把提交 `a0f0483` 中已通过本地合同的公网健康诊断与防抖增强,安全升级到现有 ARM 异机监控;保留已有脱敏状态和备份 dead-man 能力,先安装为 disabled 并完成只读核验,再受控启用 5 分钟 timer。部署后只以真实公网 `/ready` 的自然结果运行,不制造故障、不发送专门测试消息。
|
||
|
||
## Background and Confirmed Facts
|
||
|
||
- `08-23-wecom-public-health-alert-diagnostics-and-debounce` 已完成本地实现:DNS/TCP 分类分离、连续 2 次健康恢复、60 分钟同类复发抖动提醒、连续健康 30 分钟静默退出,以及“OA 公网健康”专用标题。
|
||
- 本地应用健康合同 36 项、自动备份共享合同 74 项均通过;候选工作提交为 `a0f0483`,归档提交为 `42bbbda`。
|
||
- 腾讯云服务器是 OA 真实生产主机,运行 OA 应用、数据库及公网入口;ARM 是独立异机备份与外部健康探测节点,不运行 OA 服务。应用健康探测器部署在 ARM,并从外部访问腾讯云 OA 的公网 `/ready`。
|
||
- 2026-07-27 已在 ARM 安装并启用旧版监控,现有应用健康探测器、两个 systemd units、独立状态目录及共用企微 helper 均可能存在;本次是原位升级,不适用首次安装时的“必须不存在”前提。
|
||
- 现有安装器 `install` 会先停用应用健康 timer,再覆盖固定的探测器、helper 和 units,并保留状态目录;`enable` 会重新安装后启用 timer。
|
||
- 用户已同意为本次 ARM 监控节点 rollout 建立 Trellis task,并允许按“默认禁用安装 → 只读检查 → 受控启用”规划;该授权不包含腾讯云 OA 应用部署或配置变更。
|
||
|
||
## Requirements
|
||
|
||
### R1 — 本地与来源门禁
|
||
|
||
- 部署源必须来自已提交的 `a0f0483`,且探测器、helper、安装器相对该提交无漂移。
|
||
- 远端写入前复跑应用健康合同和自动备份共享合同;任一失败即停止。
|
||
- 不使用工作区中未提交的报销任务文件,不把当前 Trellis 文档作为远端部署源。
|
||
|
||
### R2 — ARM 只读预检
|
||
|
||
- 写入前通过既有受控 SSH 入口核对身份、`sudo -n`、Python、systemd、当前应用健康 timer/service、备份 dead-man 基线和公网 `/ready`。
|
||
- 只在 ARM 内解析并验证现有 root-owned `0600` webhook 文件路径;不得读取、传输或回显正文。
|
||
- 记录现有探测器/helper/unit 的哈希匹配结果、允许的状态 schema/phase、timer enabled/active 和 dead-man 基线;证据只包含布尔值、稳定 token、短提交号和哈希是否匹配。
|
||
- `sudo -n` 需要密码、现有对象为符号链接/权限异常、状态无法解析、真实 `/ready` 不健康或备份 dead-man 基线异常时,停止在写入前并报告。
|
||
|
||
### R3 — Disabled 原位升级
|
||
|
||
- 只上传已提交的探测器、共用 helper 和安装器到本次唯一临时目录,并核对源/上传件 SHA-256。
|
||
- 运行安装器 `install`,只覆盖固定的应用健康探测器、共用 helper 和两个应用健康 units;保留现有应用健康状态、alert state、webhook、备份 receiver/dead-man、归档和其他 systemd 对象。
|
||
- 安装后 timer 必须为 disabled/inactive;探测器/helper 为 root:root `0755`,units 为 `0644`,状态目录为 root:root `0700`,已有状态文件为 `0600`。
|
||
- 已安装探测器/helper 必须与 `a0f0483` 的候选哈希一致,unit 仍固定正式 HTTPS `/ready`、失败阈值 2、5 分钟周期和安全目标路径。
|
||
|
||
### R4 — Disabled 状态核验
|
||
|
||
- 在 timer disabled 时只运行正式 systemd oneshot 对真实公网 `/ready` 做一次健康检查,不改 URL、DNS,也不人工编辑状态内容。
|
||
- oneshot 必须成功,状态 schema 必须为 v2 且只包含允许字段;健康基线不得产生故障或恢复消息。
|
||
- 如旧状态迁移后自然形成一个通知候选,立即停止启用并报告,不以删除或伪造状态来压制消息。
|
||
|
||
### R5 — 受控启用与观察
|
||
|
||
- R1–R4 全部通过后,才运行安装器 `enable`;不执行不可达端口、停服务、改 DNS 等故障注入。
|
||
- timer 最终必须 enabled/active,调度周期仍为 5 分钟,最近一次 service 成功,下一次计划时间符合 timer 合同。
|
||
- 启用后至少观察两个连续调度窗口,并核对状态 schema/phase、service 结果和消息去重状态;允许真实健康异常自然触发生产运维消息,但不发送专门测试消息。
|
||
- 备份 dead-man 的 unit/timer 状态和共用标题合同必须保持不变。
|
||
|
||
### R6 — 停止与回滚
|
||
|
||
- 任一步出现身份、权限、哈希、unit、状态、真实健康或备份基线不一致时,停止扩大变更并保留脱敏证据。
|
||
- disabled 安装后、enable 前失败:恢复升级前探测器/helper/units 的同机备份,保留状态目录,再核对 timer 回到升级前状态;不得删除共用 webhook、备份组件或归档。
|
||
- enable 后失败:先 disable/stop 应用健康 timer,恢复升级前文件和 units,执行 daemon-reload,并按升级前 enabled/active 基线恢复 timer;只有确认真实 `/ready` 健康和旧版可读取状态后才重新启用。
|
||
- 若新版已写入旧版不能读取的 schema v2,回滚时先保留精确状态文件副本,再将精确状态文件移出活动目录,让旧版建立新健康基线;不得伪造恢复状态。
|
||
- 若正式健康告警已经自然发出但无法闭环恢复,保持 timer 停用并明确报告“告警未闭环”,不发送人工伪造的恢复消息。
|
||
|
||
### R7 — 隐私、清理与报告
|
||
|
||
- 不在聊天、Trellis、日志摘要或提交中保存主机地址、用户名、完整远端路径、webhook、Secret、原始响应、journal 或企微 payload。
|
||
- 删除本次精确临时上传目录和临时权限入口;若使用临时 sudoers,必须在同一受控 root 流程中校验后删除,并证明原非交互权限已恢复到基线。
|
||
- 未完成远端检查前不得报告“已部署”;未观察两个调度窗口前不得报告“运行稳定”。
|
||
|
||
## Acceptance Criteria
|
||
|
||
- [x] **AC1 / R1**:候选来源固定为 `a0f0483`,本地 36 项应用健康合同和 74 项自动备份合同再次通过,部署源无漂移。
|
||
- [x] **AC2 / R2**:ARM 写入前预检通过,且证据不含凭证、地址、完整路径、原始响应或 payload。
|
||
- [x] **AC3 / R2**:记录升级前应用健康与备份 dead-man 的脱敏基线;现有状态可严格解析,回滚材料已在 ARM 同机受控保存。
|
||
- [x] **AC4 / R3**:disabled 安装后 timer 明确 disabled/inactive,受管文件、units、权限、固定目标和 SHA-256 全部符合合同。
|
||
- [x] **AC5 / R4**:timer disabled 时正式 oneshot 对公网 `/ready` 成功,状态安全迁移至 schema v2,未产生测试或恢复噪声。
|
||
- [x] **AC6 / R5**:受控启用后 timer enabled/active,连续两个调度窗口成功且状态/消息去重无异常。
|
||
- [x] **AC7 / R5**:备份 receiver/dead-man、归档和共享非应用健康标题均未改变。
|
||
- [x] **AC8 / R6**:每个阶段都有可执行停止/回滚点;本轮未触发回滚,最终 timer 状态、真实健康和备份基线均完成复核。
|
||
- [x] **AC9 / R7**:临时上传与临时权限已精确清理,最终证据仅包含允许的脱敏字段。
|
||
|
||
## Scope
|
||
|
||
- 从提交 `a0f0483` 取得并复核探测器、企微 helper 与既有安装器。
|
||
- 对现有 ARM 应用健康监控执行只读预检、同机回滚准备、disabled 原位升级和正式 `/ready` oneshot。
|
||
- 前置门禁全部通过后启用 5 分钟 timer,并观察两个连续调度窗口。
|
||
- 核对应用健康独立状态、共享 helper 兼容和备份 dead-man 基线,完成临时材料清理及脱敏记录。
|
||
|
||
## Out of Scope
|
||
|
||
- 修改 DNS、resolver、Caddy、TLS 证书、OA 应用、数据库、Compose 或业务数据。
|
||
- 故意制造失败、停止真实服务、使用不可达端口或发送企微测试消息。
|
||
- 修改机器人配置、webhook 内容、备份 receiver/dead-man 配置、归档或保留策略。
|
||
- 清理历史状态、历史告警、旧候选文件或其他并行任务改动。
|
||
- 宣称 ARM 监控具备第三方 dead-man 能力。
|
||
|
||
## Test Plan
|
||
|
||
- 本地:应用健康合同、自动备份合同、安装器 Shell 语法、process baseline、Trellis governance、task validate、敏感扫描和 `git diff --check`。
|
||
- ARM 写前:连接/权限、当前版本/哈希、应用健康和 dead-man timer/service、状态 schema、webhook 文件属性、公网 `/ready` 的脱敏布尔检查。
|
||
- ARM 写后 disabled:哈希、owner/mode、unit 固定合同、timer disabled/inactive、正式 oneshot 和 schema v2。
|
||
- ARM enable 后:enabled/active、两个连续调度窗口、最近 service 成功、状态/去重 token、dead-man 基线不变、临时材料清理。
|
||
|
||
## Execution Evidence
|
||
|
||
- 2026-08-23:候选提交门禁、安装器 Shell 语法、应用健康合同 36 项、自动备份共享合同 74 项和 process baseline 均通过;测试 capture 未访问真实企微。
|
||
- 2026-08-23:既有 ARM SSH alias 可非交互连接,但首个写前门禁 `sudo -n true` 返回需要密码;流程在任何 root 检查、上传或远端写入前停止。
|
||
- 2026-08-23:用户在 ARM 侧建立临时非交互 sudo 运维入口后,完整只读预检通过:旧应用健康 timer 和备份 dead-man 均 enabled/active,probe state 为有效 v1,webhook 文件合同与腾讯云 OA 公网 `/ready` 均通过。
|
||
- 2026-08-23:候选上传哈希、同机回滚副本、disabled 原位安装、受管文件权限和固定 unit 合同均通过;正式 oneshot 成功把 probe state 从 v1 保守迁移为 v2/healthy,alert state 未变化,未产生恢复噪声。
|
||
- 2026-08-23:timer 受控启用后连续两个自然调度窗口成功,probe 保持 v2/healthy,未出现非预期企微消息,备份 dead-man 基线未变化。腾讯云 OA 应用、数据库、DNS 和业务数据均未修改。
|
||
- 2026-08-23:三个临时上传文件和空目录已精确删除;临时 sudoers 已删除、sudoers 全量语法通过,`sudo -n` 恢复为不可用。ARM 同机回滚副本按计划保留,后续清理需另行授权。
|
||
- 2026-08-23:收尾 task validate、Trellis governance、process baseline、敏感扫描和 `git diff --check` 均通过;文档审计 errors=0,仅保留既有未登记文件 warning。
|