Files
Nexus/docs/project/risk-acceptance-single-operator.md
T
Nexus Deploy b866e944ab fix: Code Review P0/P1 batches 1-3 and single-operator risk acceptance
Apply sync/install/auth/schedule/retry/agent/settings fixes from full
code review; document accepted WS and Agent legacy risks for solo ops.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-04 15:57:49 +08:00

127 lines
4.7 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.
# 风险接受记录 — 单人运维场景(2026-06-04
## 背景
Nexus 全量 Code Review(批次 1~3)完成后,有两项被标记为「刻意未纳入」,需更大协议变更或 Agent 全站迁移:
1. WebSocket JWT 仍通过 query 传递(ADR-011
2. Agent 认证保留 global `API_KEY` 对未分配 `agent_api_key` 服务器的 legacy 回退
**运营事实(2026-06-04 确认)**:后台仅 **一名** 操作员自用,无多人共享账号、无外包运维、无多租户。操作员即系统 owner,管理员身份视为完全可信。
本文档记录在该威胁模型下的**正式风险接受**与重评条件,避免后续审计或接续开发误将两项抬为 P0。
---
## 威胁模型(单人运维)
| 维度 | 假设 |
|------|------|
| 后台用户 | 仅 1 人,可信 |
| 内鬼 / 权限滥用 | 不适用 |
| 主要防护目标 | 外网未授权访问、安装/认证漏洞、多 worker 竞态、子机 Agent M2M 密钥管理 |
| 日志访问 | Nginx/宝塔等 access log 仅 operator 可阅,不外发第三方 |
---
## 接受项 1WebSocket JWT queryADR-011
### 现状
- `/ws/alerts``/ws/sync``/ws/terminal/{id}` 均在握手 URL 使用 `?token=...`
- 设计依据:ADR-011;浏览器 WebSocket 无法自定义 Authorization Header
- 批次 3 已统一:缺失 token → **4001**;无效/过期 JWT → **4401**
### 接受理由
- Token 仅在 operator 登录后由其浏览器持有,无「不可信管理员」场景
- 改首帧鉴权 / WS ticket / 子协议需前后端同发、三条通道联测,**单人自用 ROI 极低**
- 残余风险(access log 留存 JWT、DevTools 可见)在「仅 operator 可读日志」前提下可接受
### 残余风险
- 本机恶意软件可窃取 session(与 token 在 query 或 Header 无本质差别)
- 若未来日志外发 SIEM/第三方,URL 中的 JWT 成为额外泄露面
### 重评触发条件
- 新增第二管理员或外包运维
- 等保/客户安全审计要求「凭证不得出现在 URL」
- access log 外发或多人可读
- 后台改为多租户或 SaaS 形态
### 决定
**维持 ADR-011,不排 WS 协议改造。**
---
## 接受项 2Agent global API_KEY legacy 回退
### 现状
- 子机 Agent 通过 `X-API-Key` 调用 `/api/agent/heartbeat`(无 JWT、无后台登录)
- 认证逻辑(`server/api/agent.py`):
1. 服务器必须存在
2. 若已分配 `agent_api_key` → 必须匹配 per-server key
3. **Legacy**:未分配 per-server key → 仍接受 global `API_KEY`(写 warning 日志)
- 批次 3 已收紧:未知 `server_id` 拒绝;DB 查服异常 fail-closed
### 接受理由
- 与「后台几人用」无关,但单人运维下 global key 分发面可控(`.env`、安装脚本、子机 `config.json`
- 硬禁用 global 回退可能导致大量 legacy Agent 心跳 401**可用性风险大于当前威胁**
- 已有 per-server key 的服务器已与 global 隔离
### 残余风险
- global `API_KEY` 若从备份、误提交、子机配置泄露,攻击者可对 **尚未分配 `agent_api_key`** 的服务器伪造心跳(污染在线状态/监控数据,非 RCE)
- 攻击者需同时能访问中心 API 地址并持有 key
### 缓解(已实施)
- 未知 server_id 不再接受 global 冒充
- 新装/生成 key 流程优先 per-server`POST /servers/{id}/agent-key`
- legacy 使用 global 时服务器日志告警,便于逐步迁移
### 重评触发条件
- global key 疑似或确认泄露
- 计划轮换 `API_KEY`
- 新装 Agent 100% per-server 且存量迁移完成
- 监控/告警数据完整性成为合规要求
### 决定
**保留 legacy global 回退;不排硬禁用。** 有空时可做摸底(`agent_api_key IS NULL` 数量)与渐进迁移,非阻塞项。
---
## 仍须保持的修复(与单人场景无关)
以下项已在 Code Review 批次 1~3 修复,属于**稳定性/外网暴露**问题,不因单人运维而降级:
- Sync/脚本并行任务 AsyncSession 竞态
- 安装向导 create-admin 鉴权窗口
- schedule/retry 多 worker 重复执行
- 登录开放重定向、推送 WS 断线与 logout 码
- Settings 敏感项脱敏、Agent unknown server 拒绝等
---
## 变更记录
| 日期 | 说明 |
|------|------|
| 2026-06-04 | 初始记录;operator 确认单人自用后台 |
---
## 引用
- ADR-011`docs/project/roadmap.md`WebSocket JWT query
- Code Review 批次 3`docs/changelog/2026-06-04-code-review-p1-p2-batch3.md`
- 本记录 changelog`docs/changelog/2026-06-04-risk-acceptance-single-operator.md`
- AI 接续:`docs/project/AI-HANDOFF-2026-05-23.md` §7b · `docs/project/AI-HANDOFF-2026-06-03.md` §Code Review 收尾
- Agent 认证实现:`server/api/agent.py``_verify_server_api_key`