审计 — 2026-06-07 BL-06 Agent per-server key 强制
范围
移除 Agent 认证 global API_KEY legacy 回退;涉及 3 个后端文件 + 1 个新测试文件。
| 文件 |
行数 |
Read 范围 |
server/api/agent.py |
379 |
L40-93(认证函数) |
server/api/servers.py |
2056 |
L619-636, L1625-1640(安装链路) |
server/application/services/script_service.py |
735 |
L44-50(回调 key) |
tests/test_agent_per_server_key.py |
88 |
全文 |
tests/load_test.py |
202 |
顶部 docstring |
tests/quick_load.py |
87 |
顶部 docstring |
Step 3 规则扫描
| H |
规则 |
结论 |
| H1 |
Agent 认证 fail-closed |
FIXED 移除 global 回退;无 per-server key → False |
| H2 |
安装链路静默降级 |
FIXED 无 key 明确 400/批量错误项 |
| H3 |
长任务回调 key 泄露面 |
FIXED 仅用 per-server key,无 global 回退 |
| H4 |
compare_digest 时序安全 |
SAFE 保留 secrets.compare_digest |
| H5 |
DB 查服异常 |
SAFE 保持 fail-closed return False |
Closure
| H |
判定 |
依据 |
| H1 |
FIXED |
agent.py:60-82 仅 agent_api_key 匹配 |
| H2 |
FIXED |
servers.py:627-633, servers.py:1635-1637 |
| H3 |
FIXED |
script_service.py:44-50 ValueError |
| H4 |
SAFE |
agent.py:82 compare_digest |
| H5 |
SAFE |
agent.py:68-76 except → False |
入口表(agent.py 受影响路由)
| 方法 |
路径 |
鉴权 |
| POST |
/api/agent/heartbeat |
X-API-Key + per-server agent_api_key |
| POST |
/api/agent/script-callback |
同上 + job secret |
巡检补修(同日)
| 项 |
原问题 |
修复 |
| H6 |
receive_heartbeat 认证后再次 get_server(重复查库) |
_verify_server_api_key 返回 Optional[Server],handler 复用 |
| H7 |
验 key 通过后 unknown_server discarded 分支为死代码 |
删除;不存在/无 key/错 key 统一 401 |
| H8 |
script-callback docstring 仍写「per-server or global」 |
改为仅 per-server |
| H9 |
无回归测试约束 get_server 调用次数 |
test_verify_server_key_single_get_server_per_auth_check + assert_called_once_with |
生产只读探测(2026-06-07)
| 探测 |
结果 |
GET /health |
200 |
POST /api/agent/heartbeat 假 key |
401 |
security_probe_external.sh heartbeat/WS |
PASS |
注:BL-06 完整语义(global key 不可冒充)需部署本地改动后生产才生效;当前生产假 key 已 401。
DoD