fix(security): BL-06 强制 Agent per-server key 并合并心跳单次查库
移除 Agent 认证与安装链路的 global API_KEY 回退,收口 risk-acceptance 接受项 2;巡检补修心跳重复 get_server 并加 assert_called_once 回归测试。 Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -5,7 +5,7 @@
|
||||
Nexus 全量 Code Review(批次 1~3)完成后,有两项被标记为「刻意未纳入」,需更大协议变更或 Agent 全站迁移:
|
||||
|
||||
1. WebSocket JWT 仍通过 query 传递(ADR-011)
|
||||
2. Agent 认证保留 global `API_KEY` 对未分配 `agent_api_key` 服务器的 legacy 回退
|
||||
2. ~~Agent 认证保留 global `API_KEY` 对未分配 `agent_api_key` 服务器的 legacy 回退~~ **已收口(2026-06-07 BL-06)**
|
||||
|
||||
**运营事实(2026-06-04 确认)**:后台仅 **一名** 操作员自用,无多人共享账号、无外包运维、无多租户。操作员即系统 owner,管理员身份视为完全可信。
|
||||
|
||||
@@ -56,44 +56,28 @@ Nexus 全量 Code Review(批次 1~3)完成后,有两项被标记为「
|
||||
|
||||
---
|
||||
|
||||
## 接受项 2:Agent global API_KEY legacy 回退
|
||||
## 接受项 2:Agent global API_KEY legacy 回退 — **已收口(2026-06-07)**
|
||||
|
||||
### 现状
|
||||
### 原状(2026-06-04 接受)
|
||||
|
||||
- 子机 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
|
||||
- 认证逻辑曾允许:未分配 `agent_api_key` 时回退接受 global `API_KEY`(写 warning 日志)
|
||||
|
||||
### 接受理由
|
||||
### 收口决定(BL-06)
|
||||
|
||||
- 与「后台几人用」无关,但单人运维下 global key 分发面可控(`.env`、安装脚本、子机 `config.json`)
|
||||
- 硬禁用 global 回退可能导致大量 legacy Agent 心跳 401,**可用性风险大于当前威胁**
|
||||
- 已有 per-server key 的服务器已与 global 隔离
|
||||
- **2026-06-07**:生产 0 台子机窗口,移除 global 回退,强制 per-server `agent_api_key`
|
||||
- 改动点:`server/api/agent.py`、`server/api/servers.py`(安装链路)、`server/application/services/script_service.py`(长任务回调)
|
||||
- global `API_KEY` 仍保留为必需环境变量(启动校验、加密等非 Agent 用途),**不再作为 Agent 认证通行证**
|
||||
|
||||
### 运维语义
|
||||
|
||||
- 新建服务器自动生成 `nxs-...` per-server key
|
||||
- `uninstall-agent` 会将 `agent_api_key` 置 `None`;重装前须 `POST /api/servers/{id}/agent-key` 重新生成
|
||||
|
||||
### 残余风险
|
||||
|
||||
- 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` 数量)与渐进迁移,非阻塞项。
|
||||
- **已消除**:global key 伪造未迁移服务器心跳的面已关闭
|
||||
- 接受项 2 自 2026-06-07 起**作废**,不再作为开放风险项
|
||||
|
||||
---
|
||||
|
||||
@@ -114,6 +98,7 @@ Nexus 全量 Code Review(批次 1~3)完成后,有两项被标记为「
|
||||
| 日期 | 说明 |
|
||||
|------|------|
|
||||
| 2026-06-04 | 初始记录;operator 确认单人自用后台 |
|
||||
| 2026-06-07 | 接受项 2 收口:BL-06 强制 per-server agent_api_key,移除 global 回退 |
|
||||
|
||||
---
|
||||
|
||||
|
||||
Reference in New Issue
Block a user