diff --git a/README.md b/README.md index 7f26d2f..c8ee0ee 100644 --- a/README.md +++ b/README.md @@ -1,227 +1,50 @@ -
- # VPS-Commander -**面向 AI Agent (ChatGPT / Claude / MCP) 与个人运维的高性能、极轻量、多节点私有基础设施调度中枢** +> 当前文档基线:2026-10-02 -[![Go Version](https://img.shields.io/badge/Go-1.22+-00ADD8?style=flat&logo=go)](https://golang.org) -[![License](https://img.shields.io/badge/License-MIT-blue.svg)](LICENSE) -[![Architecture](https://img.shields.io/badge/Arch-Linux%20AMD64%20%7C%20ARM64-orange)](#) -[![Memory Footprint](https://img.shields.io/badge/Memory-Hub%20%E2%89%A4%2025MB%20%7C%20Agent%20%E2%89%A4%2012MB-brightgreen)](#) +自托管、多节点、AI Agent 友好的 Linux 运维控制中枢。 -
+## 研发最初目标 +- 不依赖第三方运维 Relay,建立用户自己的私有控制面; +- 从单机运维扩展到多 VPS 统一调度; +- 在主机级能力之上建立认证、授权、审计、资源限制和可回滚发布体系。 ---- +当前系统已经从早期的 OpenAPI + Cluster Secret + 4 个 MCP 工具,演进为: +Hub/Agent 双通道 + per-device credential + Policy Snapshot + Tool Registry + MCP/HTTP 统一安全门禁 + SQLite audit + Web Panel。 -## 🌟 核心特性 +## 当前架构 +AI / MCP / Web Panel → HTTPS/WSS → Reverse Proxy → Hub 127.0.0.1:9521 +Hub → Local Executor,或 Hub → Agent WSS → Remote VPS。 +Hub 不直接公网监听;Agent 只主动回连 Hub。 -- ⚡ **极致轻量,极低常驻**:纯 Go 原生编写,静态无依赖编译。Hub 核心管理进程物理常驻内存(RSS)稳定在 **15MB** 左右;受控端 Agent 内存占用仅 **7~11MB**,小内存 VPS 零负担。 -- 🤖 **原生 AI 友好 (ChatGPT Actions & MCP 双协议)**: - - **OpenAPI 3.1.0 标准**:开箱即用支持 ChatGPT Custom GPTs / Claude Actions。 - - **MCP (Model Context Protocol)**:内置兼容 SSE 与 JSON-RPC 标准,支持 Cursor、Windsurf、Claude Desktop 等客户端。 - - **OAuth 2.0 / Bearer 认证**:支持公开客户端授权与 Bearer API Key 访问控制。 -- 🌐 **多节点集群架构 (Hub & Agent)**: - - 单中心 Hub 统一管理多台受控 VPS。 - - 远程 Agent 节点通过标准 WebSocket (WSS) 主动建立安全长连接回连,天然穿透 NAT 与内网,无需受控端暴露端口。 -- 🛡️ **严格安全防护与权限闭环**: - - **零参数泄露**:全面封禁 CLI 敏感传参,凭据由 `0600` 环境变量接管,避免 `/proc/*/cmdline` 泄密。 - - **完整审计追溯**:内置本地 SQLite 存储,全量记录调用者 IP、下发节点、指令内容、退出码及精确执行耗时。 - - **执行隔离与超时回收**:内置上下文超时控制,强制清理孤儿进程,彻底杜绝僵尸进程。 -- 📊 **实时节点资源画像 (Node Profiling & Role)**: - - **原生零依赖深度采集**:直接读取 Linux 内核指标,实时监控物理 CPU 核心数与瞬时负载、真实可用内存(`MemAvailable`)与 Swap、根分区磁盘占用、IO 压力指数(内核原生 PSI / Loadavg)及 Docker 守护进程运行状态。 - - **动态角色标签**:支持节点角色分工(如 `CONTROL` 控制中枢、`APPLICATION` 应用节点、`DATABASE` 等),为 AI Agent 自动化调度部署决策提供全维度实时依据。 -- 🛡️ **设备生命周期管理与防重连黑名单**: - - 支持管理员在 Web 控制台一键注销并强制断开指定受控节点。 - - 持久化吊销拦截(Revocation List),彻底杜绝被下线 Agent 因 Systemd 自动重启而死灰复燃。 - - 本地主控节点(Local)强制安全锁,防误操作防护。 -- 🖥️ **内嵌极简 Web 管理面板**: - - 静态单页面(SPA)采用 Go `embed` 完整打包进二进制文件,单文件独立运行,无需安装 Node.js、Nginx 或外部静态资源 CDN。 - - **工程级双态主题**:纯手绘 SVG 极简几何微图标(太阳/弦月),支持深曜蓝黑与柔和浅灰白一键切换,完美适配系统偏好且零 FOUC 白屏闪烁。 - - **全端响应式**:彻底适配手机移动端(≤680px),宽表独立触控滑动,长节点名自动断行不穿透。 +## 当前 MCP:11 个工具 +list_devices、exec_command、read_file、read_multiple_files、create_directory、move_file、list_processes、edit_block、write_file、list_agent_mcp、call_agent_mcp。 ---- +风险:Low=读取/观察;Medium=文件修改/目录移动/Agent MCP;High=Shell/进程控制。 +远程 HTTP MCP 当前为 legacy HTTP+SSE;本地客户端为 stdio。Streamable HTTP 属于后续演进方向。 -## 🏗️ 架构概览 +## 当前 HTTP +/api/v1/devices、/api/v1/exec、/api/v1/file/read、/api/v1/file/list、/api/v1/file/info、/api/v1/file/search、/api/v1/process/session、/api/v1/file/write、/api/v1/devices/file/edit_block、/api/v1/mcp/*、/api/v1/security/*、/api/v1/notifications/webhook*、/agent/ws、/healthz、/openapi.json、/panel/*。 -```text - +-----------------------------------+ - | OpenAI ChatGPT / AI Agents | - +-----------------+-----------------+ - | HTTPS / MCP SSE / WSS - v - +-----------------------------------+ - | 反向代理 / SSL 终止 (Lucky/Nginx)| - +-----------------+-----------------+ - | 127.0.0.1:9521 - v - +-------------------------------------------------------------+ - | VPS-Commander Hub | - | - OpenAPI 3.1 & MCP 路由引擎 | - | - OAuth / Bearer 鉴权与 Session 会话 | - | - 本地 SQLite 审计数据库 (commander.db) | - | - 内嵌 Web 管理面板 (SPA) | - +--------------+-------------------------------+--------------+ - | | - (本地执行通道) (WebSocket RPC 长连接通道) - | | - v v - +--------------------+ +--------------------+ - | 宿主机 (Local) | | 受控 VPS (Agent) | - | uname / sh / 文件 | | vps-commander-a | - +--------------------+ +--------------------+ -``` +## 安全 +HTTP/MCP 使用 Bearer API Key;Agent 使用每设备独立 credential,Hub 只保存 hash。 +生产 Shared Secret fallback 已关闭;URL token 不作为认证方式。 +MCP、HTTP、direct Agent MCP 共用 Hub security model;未知设备必须 fail-closed。 +Panel Admin Token 由服务端内部 bridge,不下发浏览器。 ---- +## 部署 +Hub:/opt/vps-commander/vps-commander-hub,监听 127.0.0.1:9521,数据库 /opt/vps-commander/data/commander.db。 +Agent:/opt/vps-commander/vps-commander-agent,配置 /etc/vps-commander/agent.env,通过 WSS 回连 Hub。 -## 🚀 极速一键部署与平滑升级 +发布必须:clean tree → go test ./... → go test -race ./... → clean build → vcs.modified=false → 单节点灰度 → Hub recovery → rolling Agent → MCP/security/audit 验收。 -### 1. 一键全自动安装 (推荐) -无论是在受控端 VPS 还是中心端,只需一行命令即可交互式安装与启动: +## 文档 +docs/DOCUMENTATION_BASELINE_20261002.md、docs/ARCHITECTURE.md、docs/DEV_SPEC.md、docs/MCP_INTEGRATION.md、deploy/README.md、docs/ACCEPTANCE_CRITERIA.md、docs/PROGRESS_TRACKING.md、docs/VPS_COMMANDER_V2_1_SECURITY_HARDENING_SPEC.md。 -```bash -bash <(curl -fsSLk https://raw.githubusercontent.com/kyaring/vps-commander/main/deploy/install.sh) -``` -- **安装 Agent (受控 VPS)**:输入 Hub 的 WSS 地址与通信密钥,全自动配置开机自启并秒级连入集群。 -- **安装 Hub (中心服务端)**:自动生成安全 API Key / Web 面板密码并以 Systemd 托管常驻。 +## 当前生产注意 +2026-10-02 Bug Hunt 发现生产二进制曾以 vcs.modified=true 构建,因此生产现场不能直接视为 HEAD 的可复现产物。 +下一次发布必须 clean rebuild,并把 revision/modified 作为发布证据。 -### 2. 受控端 Agent 一键平滑升级 (免重输配置) -当新版本发布后,无需重新配置通信密钥或重新安装,在任意受控机上直接运行升级脚本: - -```bash -curl -fsSLk https://raw.githubusercontent.com/kyaring/vps-commander/main/deploy/upgrade-agent.sh | bash -``` -- 自动检测并拉取 GitHub 最新版本架构包(AMD64 / ARM64); -- 自动备份旧版本二进制(`.bak`); -- 升级异常(校验失败或无法启动)时**自动秒级回滚**,保证节点永不失联。 - ---- - -## 🛠️ 手动编译部署 - -### 1. Hub 服务端部署 - -在中心管理机上部署 Hub: - -```bash -# 1. 编译二进制 -make linux-amd64 - -# 2. 安装二进制文件 -install -d -m 0750 /opt/vps-commander/data /etc/vps-commander -install -m 0755 bin/vps-commander-hub-linux-amd64 /opt/vps-commander/vps-commander-hub - -# 3. 创建环境变量配置 (注意保护权限) -cat << 'ENV' > /etc/vps-commander/hub.env -VPS_COMMANDER_API_KEY=your_secure_api_key_here -VPS_COMMANDER_CLUSTER_SECRET=your_cluster_sync_secret_here -VPS_COMMANDER_WEB_PASSWORD=your_web_panel_password_here -ENV -chmod 0600 /etc/vps-commander/hub.env - -# 4. 配置并启动 Systemd 服务 -cp deploy/vps-commander-hub.service /etc/systemd/system/ -systemctl daemon-reload -systemctl enable --now vps-commander-hub -``` - -### 2. 远程 VPS Agent 受控端部署 - -在需要受控的远程 VPS 机器上执行: - -```bash -# 1. 下载或拷贝 agent 二进制至远程机器 -install -d -m 0750 /etc/vps-commander /opt/vps-commander -install -m 0755 vps-commander-agent-linux-amd64 /opt/vps-commander/vps-commander-agent - -# 2. 配置 Agent 环境变量 -cat << 'ENV' > /etc/vps-commander/agent.env -VPS_COMMANDER_HUB_WS_URL=wss://your-domain.com/agent/ws -VPS_COMMANDER_AGENT_NAME=vps-us-node01 -VPS_COMMANDER_CLUSTER_SECRET=your_cluster_sync_secret_here -ENV -chmod 0600 /etc/vps-commander/agent.env - -# 3. 配置并启动 Systemd 服务 -cp deploy/vps-commander-agent.service /etc/systemd/system/ -systemctl daemon-reload -systemctl enable --now vps-commander-agent -``` -Agent 启动后会通过 WSS 自动连入 Hub,在 Hub 管理面板与 `/api/v1/devices` 接口中实时显示为 `online`。 - ---- - -## 🤖 接入 ChatGPT (新版插件 Apps & MCP 模式) - -当前 ChatGPT 已升级为以 **插件 / 应用 (Apps & MCP)** 规范连接外部服务。VPS-Commander 原生内置完整的 **MCP SSE + OAuth2** 协议支持,无需部署额外适配层。 - -### 接入配置步骤: - -1. **进入 ChatGPT 插件/应用配置页**: - - 打开 ChatGPT -> **Settings (设置)** -> **Apps & Integrations (应用与集成) / Plugins** -> **Create / Add App (添加应用)**。 -2. **连接方式选择 MCP**: - - 连接协议选择 **MCP (Model Context Protocol)** 或 **Server-Sent Events (SSE)**。 - - **MCP Server URL**:填入 Hub 的 SSE 统一入口: - ```text - https://your-domain.com/mcp/sse - ``` -3. **身份认证 (Authentication)**: - - **方式 A (OAuth 2.0 自动授权,推荐)**: - - Hub 内置了标准 RFC 8414 OAuth Metadata (`/.well-known/oauth-authorization-server`); - - 授权端点与 Token 端点由 ChatGPT 自动识别,一键点击「Authorize」即可完成免密安全绑定。 - - **方式 B (Bearer API Key)**: - - 若选择 API Key,填入 Hub 环境变量 `VPS_COMMANDER_API_KEY` 即可。 -4. **自动发现 4 大运维工具**: - - 握手成功后,ChatGPT 会自动加载并列出 4 个原生运维工具: - - `list_devices`:列出受控节点、CPU/内存/磁盘剩余绝对值及 Docker 状态; - - `exec_command`:在目标机器(如 `m4-live-agent`)执行 Shell 指令; - - `read_file`:分页读取目标文件; - - `write_file`:远程编辑或创建文件。 - ---- - -### 传统客户端支持 (Claude Desktop / Cursor / VS Code) - -支持通过本地 stdio 二进制连接 Hub: -```json -{ - "mcpServers": { - "vps-commander": { - "command": "/path/to/vps-commander-mcp-stdio-linux-amd64", - "args": [ - "-hub", "https://your-domain.com", - "-key", "YOUR_API_KEY" - ] - } - } -} -``` - ---- - -## 📊 接口与能力一览 - -| 接口路径 | 方法 | 功能描述 | -| :--- | :--- | :--- | -| `/api/v1/devices` | `GET` | 列出集群中所有受控设备状态与**实时资源画像 (CPU/Mem/Disk/IO PSI/Docker/Role)** | -| `/panel/api/devices` | `DELETE` | 【管理员】注销并踢出指定受控节点,持久化写入防重连黑名单 | -| `/api/v1/exec` | `POST` | 在指定受控节点执行任意 Shell 指令(支持超时截断) | -| `/api/v1/file/read` | `POST` | 安全分页读取目标机器上的文件内容(防内存溢出) | -| `/api/v1/file/write` | `POST` | 向目标机器指定路径覆写或创建文件 | -| `/mcp/sse` | `GET` | MCP 协议长连接事件流通道 | -| `/panel/login` | `GET/POST`| 内嵌 Web 运维管理控制台 | - ---- - -## 📄 文档索引 - -- [生产部署指南与运维手册](deploy/README.md) -- [系统架构与安全设计说明](docs/ARCHITECTURE.md) -- [研发设计规范与内存基线](docs/DEV_SPEC.md) -- [阶段验收标准与门禁用例矩阵](docs/ACCEPTANCE_CRITERIA.md) -- [MCP 客户端接入协议文档](docs/MCP_INTEGRATION.md) - ---- - -## 📜 开源协议 - -本项目基于 [MIT](LICENSE) 协议开源。 +## v2.1 +P0:EffectiveRisk 完全 fail-closed;Agent credential 不进入 argv/cmdline。 +P1:Principal/Operator 身份、Session owner 强隔离、principal→credential→session→device→operation 审计链。 diff --git a/deploy/README.md b/deploy/README.md index 69f5ed7..c94be5f 100644 --- a/deploy/README.md +++ b/deploy/README.md @@ -1,143 +1,52 @@ -# VPS-Commander 部署与运维指南 +# VPS-Commander 生产部署与运维 -本文档介绍 VPS-Commander 的生产环境部署架构、配置规范与运维操作。 +> 基线:2026-10-02 ---- +## 1. 拓扑 +Internet → TLS Reverse Proxy → vpstool.kory.kdns.fr → 127.0.0.1:9521 → Hub。 +Hub → Local Executor 或 Agent WSS。 +Hub 不直接公网监听;Agent 不需要公网入站管理端口。 -## 一、 系统架构与端口规划 +## 2. Hub +binary:/opt/vps-commander/vps-commander-hub +env:/etc/vps-commander/hub.env +db:/opt/vps-commander/data/commander.db +systemd:vps-commander-hub.service +listen:127.0.0.1:9521 -- **Hub 服务端**:统一监听本地 `127.0.0.1:9521`,不对公网直接暴露端口。 -- **反向代理 (Lucky)**: - - 域名:`https://vpstool.kory.kdns.fr` - - 转发目标:`http://127.0.0.1:9521` - - 核心要求:开启 **WebSocket Upgrade** 支持,转发透传所有子路径(`/.well-known/*`、`/oauth/*`、`/mcp/*`、`/api/v1/*`、`/agent/ws`、`/panel/*`)。 - - SSL 终止于反代层,反代自动携带 `X-Forwarded-Proto: https` 头以保障 Cookie 的 `Secure` 属性。 -- **Agent 客户端**: - - 运行于受控的远程 VPS 机器上。 - - 通过公网 WSS 长连接主动回连 Hub:`wss://vpstool.kory.kdns.fr/agent/ws`。 +## 3. Agent +binary:/opt/vps-commander/vps-commander-agent +env:/etc/vps-commander/agent.env +必须包含 VPS_COMMANDER_HUB_WS_URL、VPS_COMMANDER_AGENT_NAME、VPS_COMMANDER_AGENT_TOKEN。 +env 文件必须 0600。 ---- +## 4. Credential +每个 Agent 使用独立 token;Hub SQLite 只保存 token hash。 +生产不依赖 Cluster Secret fallback。 +v2.0 代码仍兼容旧 -token 参数;v2.1 要求 secret 不进入 argv/cmdline。 -## 二、 凭据安全规范(强制要求) +## 5. Reverse Proxy +必须支持 HTTPS、WebSocket Upgrade、/agent/ws、/mcp/*、/api/v1/*、/panel/*、/.well-known/*、/oauth/*。 -1. **绝对禁止命令行参数传密**: - - 二进制不再支持 `--api-key`、`--cluster-secret`、`--web-password` 命令行参数。 - - 彻底杜绝在 `/proc/*/cmdline` 和 `ps aux` 中泄露明文密码。 -2. **凭据存储位置与权限**: - - 凭据文件保存在 `/etc/vps-commander/hub.env` 与 `/etc/vps-commander/agent.env`。 - - 权限必须严格设置为 `0600`(仅 root 可读写)。 +## 6. Clean Release +禁止 dirty tree build。 +git status --short;go test ./...;go test -race ./...;git diff --check;make clean;make linux-amd64;make linux-arm64。 +发布证据必须包含 vcs.modified=false 和 vcs.revision=。 ---- +## 7. Rolling +backup → Hub install/restart → Agent recovery → single-node gray → rolling Agent → MCP smoke → audit → acceptance。 +任何断联或授权异常都停止。 -## 三、 Hub 服务端部署步骤 - -### 1. 编译并安装二进制 -```bash -cd /root/.openclaw/workspace/vps-commander -make linux-amd64 -install -d -m 0750 /opt/vps-commander/data /etc/vps-commander -install -m 0755 bin/vps-commander-hub-linux-amd64 /opt/vps-commander/vps-commander-hub -``` - -### 2. 配置环境变量文件 (`/etc/vps-commander/hub.env`) -```bash -cat << 'ENV' > /etc/vps-commander/hub.env -VPS_COMMANDER_API_KEY=your_generated_api_key_here -VPS_COMMANDER_CLUSTER_SECRET=your_generated_cluster_secret_here -VPS_COMMANDER_WEB_PASSWORD=your_generated_web_password_here -ENV -chmod 0600 /etc/vps-commander/hub.env -``` - -### 3. 配置 Systemd 托管 (`/etc/systemd/system/vps-commander-hub.service`) -```ini -[Unit] -Description=VPS-Commander Hub -After=network-online.target -Wants=network-online.target - -[Service] -Type=simple -User=root -WorkingDirectory=/opt/vps-commander -EnvironmentFile=-/etc/vps-commander/hub.env -ExecStart=/opt/vps-commander/vps-commander-hub -addr 127.0.0.1:9521 -db /opt/vps-commander/data/commander.db -Restart=always -RestartSec=3s -KillSignal=SIGTERM -TimeoutStopSec=10s -LimitNOFILE=65536 -Environment=GOGC=50 - -[Install] -WantedBy=multi-user.target -``` - -### 4. 启动服务 -```bash -systemctl daemon-reload -systemctl enable --now vps-commander-hub +## 8. 日常检查 systemctl status vps-commander-hub -``` +journalctl -u vps-commander-hub -n 100 +curl -fsS http://127.0.0.1:9521/healthz +/api/v1/devices、Web Panel、MCP list_devices。 ---- +## 9. 当前生产审计 +2026-10-02 Bug Hunt 发现生产 Hub/Agent 曾 vcs.modified=true。 +这说明现场二进制不能直接视为 HEAD 的可复现产物;下一次发布必须 clean rebuild 并重新部署。 -## 四、 远程 Agent 节点部署步骤 - -若要将其他 VPS 纳入受控列表,在该远程 VPS 上执行: - -### 1. 安装 Agent 二进制 -将编译生成的 `bin/vps-commander-agent-linux-amd64`(或 ARM64 版本)上传至目标 VPS 的 `/opt/vps-commander/vps-commander-agent` 并赋予执行权限 `chmod +x`。 - -### 2. 配置 Agent 环境变量 (`/etc/vps-commander/agent.env`) -```bash -install -d -m 0750 /etc/vps-commander -cat << 'ENV' > /etc/vps-commander/agent.env -VPS_COMMANDER_HUB_WS_URL=wss://vpstool.kory.kdns.fr/agent/ws -VPS_COMMANDER_AGENT_NAME=vps-node-01 -VPS_COMMANDER_CLUSTER_SECRET=与Hub相同的CLUSTER_SECRET -ENV -chmod 0600 /etc/vps-commander/agent.env -``` - -### 3. 配置 Systemd 托管 (`/etc/systemd/system/vps-commander-agent.service`) -```ini -[Unit] -Description=VPS-Commander Agent -After=network-online.target -Wants=network-online.target - -[Service] -Type=simple -User=root -WorkingDirectory=/opt/vps-commander -EnvironmentFile=-/etc/vps-commander/agent.env -ExecStart=/opt/vps-commander/vps-commander-agent -hub ${VPS_COMMANDER_HUB_WS_URL} -name ${VPS_COMMANDER_AGENT_NAME} -Restart=always -RestartSec=3s -KillSignal=SIGTERM -TimeoutStopSec=10s -LimitNOFILE=65536 -Environment=GOGC=50 - -[Install] -WantedBy=multi-user.target -``` - -### 4. 启动并连入集群 -```bash -systemctl daemon-reload -systemctl enable --now vps-commander-agent -``` -启动后,Hub 控制面板与 `/api/v1/devices` 接口将立即展示该节点并标记为 `online`。 - ---- - -## 五、 控制面板与 Actions 使用 - -1. **管理后台地址**:`https://vpstool.kory.kdns.fr/panel/login` -2. **后台功能**: - - **设备看板**:查看所有在线/离线节点、系统架构与延迟。 - - **快速控制台**:直接在网页端向指定节点执行 Shell 指令。 - - **审计日志**:实时监控 GPT 与用户的全部执行调用、命令详情与耗时。 - - **Actions 向导**:一键复制 Schema 地址、System Prompt 与 API 密钥。 +## 10. 回滚 +保留 Hub/Agent binary、systemd env、commander.db backup、release commit。 +协议不兼容时先恢复 Hub,再滚动恢复 Agent。 diff --git a/docs/ACCEPTANCE_CRITERIA.md b/docs/ACCEPTANCE_CRITERIA.md index 0f1e221..51aa3cc 100644 --- a/docs/ACCEPTANCE_CRITERIA.md +++ b/docs/ACCEPTANCE_CRITERIA.md @@ -1,50 +1,58 @@ -# VPS-Commander 验收审核标准与收尾门禁规范 (Quality Gate & Acceptance Criteria) +# VPS-Commander 当前发布门禁 -> 本规范由架构与质量负责人(OpenClaw)制定并执行最终裁决。 -> 任何交付代码必须满足以下全量准入与准出指标方可判定为验收通过(Release Ready)。 +## 1. Build +- clean Git tree +- vcs.modified=false +- vcs.revision == release commit +- AMD64/ARM64 build 成功 ---- +## 2. Cluster +- Hub 127.0.0.1:9521 +- 5 个远程 Agent online +- Hub restart 后自动恢复 +- unknown device fail-closed -## 一、 核心门禁四不原则(强制一票否决项) +## 3. Auth +- Bearer auth +- URL token rejected +- per-device credential +- Shared Secret fallback disabled +- Panel Admin Token 不进浏览器 -1. **绝对无外部公网中转**:任何网络交互(除与 OpenAI 官方通信外)严禁经过第三方 Relay 服务器,必须 100% 走私有域名直连。 -2. **绝对零残留孤儿进程**:执行任何命令、超时中断或连接断开后,后台不得产生僵尸进程或孤儿子进程。 -3. **绝对无未授权越权**:所有非公共接口必须强制 Bearer Token / Cluster Secret 校验,缺失或错误凭证必须严厉返回 HTTP 401,严禁静默放行。 -4. **内存超标即挂**:Hub 静态常驻物理内存不得突破 **25 MB**,Agent 客户端常驻物理内存不得突破 **12 MB**;10MB 为优化目标。 +## 4. Authorization +- Tool Registry 固定 +- Low/Medium/High 一致 +- MCP 与 HTTP 共用 gate +- call_agent_mcp 无旁路 +- policy version 不回退 ---- +## 5. File +- edit_block 唯一匹配 +- atomic write +- generation check +- failure 不损坏原文件 -## 二、 详细验收测试用例矩阵 (12 项全绿门禁) +## 6. Session +- hard TTL +- idle TTL +- ring buffer cap +- manager concurrency safe +- kill 只操作 Session 内部 process handle -| 用例 ID | 验证模块 | 测试动作与输入 | 预期结果与合格标准 | 验证方式 | -| :--- | :--- | :--- | :--- | :--- | -| **TC-01** | **OpenAPI 规范合法性** | `GET /openapi.json` | 格式符合 OpenAPI 3.1.0 标准,包含 servers URL、4 个标准 path、安全定义为 `bearerAuth`(HTTP Bearer),可通过 Swagger / OpenAI Actions 校验无报错。 | 机器静态校验 | -| **TC-02** | **未授权拦截** | 无 Token 请求 `/api/v1/exec` | 立即返回 HTTP 401 Unauthorized,响应体包含 `{"error": "Unauthorized"}`,不触发任何底层 bash。 | `curl -i` 验证 | -| **TC-03** | **本地基础命令执行** | `POST /api/v1/exec` (`{"device":"local","command":"uname -a"}`) | 返回 exit_code: 0,stdout 正确包含 Linux 内核信息,duration_ms > 0 且合理。 | 实测响应校验 | -| **TC-04** | **命令超时与进程回收** | 执行 `sleep 10`,设置 `timeout: 2` | 命令在 2 秒后强制终止,返回超时错误,且检查系统进程树确认 `sleep` 进程彻底消失,无僵尸残留。 | `ps -ef` 核查 | -| **TC-05** | **文件分页读取防爆** | 读取 10MB 文本文件,设置 `limit: 1024` | 仅返回前 1024 字节内容,返回 `total_size` 与 `has_more: true`,严禁一次性将全文件读入内存。 | 接口响应验证 | -| **TC-06** | **文件安全覆写** | `POST /api/v1/file/write` 写入 `/tmp/vps_cmd_test.txt` | 文件内容精确写入,权限正常,支持覆盖写入。 | 本地文件比对 | -| **TC-07** | **Agent 握手与注册** | 启动 Agent 连入 Hub WSS | Hub 面板与 `GET /api/v1/devices` 瞬间显示该设备为 `online`,展示正确 IP 与内核信息。 | 状态机校验 | -| **TC-08** | **心跳保活与离线感知** | 模拟杀死 Agent 进程 | 经过 2 个心跳周期(~60s)后,Hub 自动将该节点状态变更为 `offline`,不发生 panic。 | 节点状态监听 | -| **TC-09** | **跨节点路由下发** | `POST /api/v1/exec` (`{"device":"hwsg","command":"uptime"}`) | Hub 正确通过 WebSocket 寻址到远程 Agent,Agent 执行并原路返回,耗时增加在 RTT 合理范围内。 | 跨机实测 | -| **TC-10** | **Web 管理面板嵌入** | 浏览器直接访问 `GET /` | 页面秒开,设备列表、ChatGPT 向导、审计日志正常渲染,无任何外部 CDN 404,无 node 构建产物遗留。 | 浏览器/Headless 验证 | -| **TC-11** | **审计日志完备性** | 执行一次正常命令与一次失败命令 | 查询 SQLite `audit_logs` 表,两条记录均完整存在(含 IP、设备、指令、退出码、耗时),字段无空缺。 | SQLite 查询比对 | -| **TC-12** | **内存基线压测** | 连续并发执行 100 次 `ps aux` | 压测结束后,Hub RSS 必须 ≤ 25MB;20MB 为优化目标。压测结束后应回落并稳定,无持续增长趋势。 | `ps -eo rss` 采样 | +## 7. MCP +11 tools 与源码一致:list_devices、exec_command、read_file、read_multiple_files、create_directory、move_file、list_processes、edit_block、write_file、list_agent_mcp、call_agent_mcp。 +必须验证:Medium 可拦截写工具;Medium 可拦截 High 工具;Agent MCP 有 gate;stdio 正常;SSE 正常。 ---- +## 8. API regression +devices、exec、file read/list/info/search/write、edit_block、process/session、MCP、security、webhook、panel、agent WS。 -## 三、 严格收尾与交付规范 (Sign-off Checklist) +## 9. Test +go test ./...;go test -race ./...;git diff --check。 +并在 clean build 后重新执行核心 smoke。 -GPT 完成开发提交代码后,由我执行以下严苛收尾工作: -1. **代码审计 (Code Review)**: - - 检查并发安全性(互斥锁 `sync.RWMutex` 是否合理、Channel 是否有阻塞泄漏风险)。 - - 检查外部输入 Shell 命令的执行上下文,是否存在注入或不可控行为。 -2. **构建与打包 (Clean Build)**: - - 生成标准的 `Makefile`,支持编译 Linux AMD64/ARM64 静态无依赖产物。 - - 清理所有中间编译缓存与临时测试文件。 -3. **部署托管与 Systemd 固化**: - - 为 Hub 编写规范的 `vps-commander-hub.service`。 - - Lucky 反代添加规则及 SSL 校验。 -4. **终验报告与归档**: - - 输出完整的《VPS-Commander 最终验收合格报告》。 - - 将完整配置参数与使用说明同步至长期记忆 `MEMORY.md`。 +## 10. Stop conditions +Agent 断联、认证绕过、unknown device 获得 High、MCP 旁路、token 进入 argv、审计丢失、dirty binary、policy version 回退、Session 无限制增长,任一发生即停止发布。 + +## 11. v2.1 +P0:EffectiveRisk fail-closed;Agent credential 不进 argv。 +P1:Principal、Session owner 强隔离、身份链审计。 diff --git a/docs/ARCHITECTURE.md b/docs/ARCHITECTURE.md index 51b3733..66cc75f 100644 --- a/docs/ARCHITECTURE.md +++ b/docs/ARCHITECTURE.md @@ -1,148 +1,48 @@ -# VPS-Commander(自托管私有化多节点运维管家)架构与开发设计规范 +# VPS-Commander 当前系统架构规范 -## 1. 项目立项背景与目标 -### 1.1 背景与痛点 -- 当前市面方案(如 Desktop Commander)严重依赖公共第三方中继(SaaS Relay),存在严重的命令与数据泄漏风险、Token 明文暴露风险以及第三方额度/速率限制。 -- 现有纯开发网关(如 CodePier)采用项目目录沙箱隔离,无法进行系统级运维(如查看全局进程、管理 Lucky/Docker、修改全盘系统配置等),且不支持 ChatGPT 原生 Actions 插件生态。 +## 1. 研发起点 +项目最初不是远程终端 UI,而是私有化 AI 运维控制面:用户自己的 Hub 作为控制中枢,多 VPS 通过 Agent 汇聚,AI 通过标准 API/MCP 发起操作,高权限能力可认证、可授权、可审计、可回滚。 -### 1.2 核心目标 -- **100% 私有化部署**:数据仅在 OpenAI 官方服务器和用户私有 VPS 之间传输,零第三方中转。 -- **全权宿主运维 (Host-centric)**:提供全局 Shell、进程管理、文件读写能力。 -- **多节点别名调度**:通过单一 Hub 统一管理多台 VPS/客户端节点,支持在 ChatGPT 中通过自然语言昵称(如 "hwsg"、"wjyhk")随时切换目标节点。 -- **原生 ChatGPT 插件集成**:提供标准 OpenAPI 3.1 规范与 Actions 端点,在 ChatGPT 手机端/网页端呈现为原生交互卡片。 -- **超轻量 Go 架构**:Hub 常驻 RSS 目标 ≤ 20MB、硬上限 25MB;Agent 常驻 RSS 目标 ≤ 10MB、硬上限 12MB。 +## 2. 双通道 +控制通道:AI/MCP/HTTP → Hub → Local Executor 或 Agent RPC。 +节点通道:Agent → WSS → Hub。 +Hub 同时承担身份、策略、路由、审计和资源门禁;任何 MCP 或 Agent MCP 调用都不能绕过 Hub。 ---- +## 3. Hub +生产 binary:/opt/vps-commander/vps-commander-hub。 +监听:127.0.0.1:9521。 +数据库:/opt/vps-commander/data/commander.db。 +systemd:vps-commander-hub.service。 +职责:HTTP API、MCP、Panel、设备状态、Agent RPC、Policy Snapshot、credential、audit、Webhook、本地执行。 -## 2. 总体架构设计 +## 4. Agent +Agent 是目标主机上的最小执行面,主动连接 /agent/ws,不要求远端开放管理端口。 +握手包含 protocol version、AgentVersion、capabilities、per-device credential。 +设备身份必须来自已认证 credential,不能信任客户端自报 device/name。 -```text -[ 用户在 ChatGPT APP / Web 端发指令 ] - │ - ▼ (HTTPS POST + Bearer API Key) - [ 用户私有域名反代 (Lucky SSL) ] - │ - ▼ (反向代理至 127.0.0.1:28800) - ┌────────────────────────────────────────────────────────┐ - │ VPS-Commander Hub (中央管理网关) │ - │ │ - │ ├─ OpenAPI / Actions Engine (/openapi.json, /api/v1) │ - │ ├─ 鉴权与安全过滤中间件 (Auth Middleware) │ - │ ├─ 设备拓扑注册表 (Device Registry & State Machine) │ - │ ├─ 审计日志存储 (SQLite: audit.db) │ - │ └─ 路由分发器 (Router Dispatcher) │ - └───────────┬────────────────────────────────┬───────────┘ - │ │ - (本地进程直连: target="local") (安全 WebSocket 长连接 / mTLS) - │ │ - ▼ ▼ - [ 本机 Local Executor ] [ 远程 Agent (Node: hwsg) ] - - bash -c ... - Client Agent Daemon - - 文件/进程直接操作 - 接收 JSON-RPC 指令并执行 -``` +## 5. 安全模型 +Client:Bearer API Key;Panel:Panel Session;Agent:per-device credential。 +Tool Registry 定义静态风险;Policy Snapshot 定义设备运行时权限。 +Low / Medium / High 是权限上限;unknown device → deny。 +生产 Shared Secret fallback 已关闭。 ---- +## 6. Tool Registry +Low:read_file、read_multiple_files、list_directory、get_file_info、start_search、get_more_search_results、list_processes、list_sessions、read_process_output。 +Medium:edit_block、write_file、create_directory、move_file、mcp_call。 +High:exec_command、start_process、interact_with_process、kill_process、force_terminate。 -## 3. 核心接口与协议规范 (OpenAPI 3.1) +## 7. Policy Snapshot +SQLite 保存策略版本,Hub 使用内存 Snapshot 处理读路径。 +version 单调递增;发布失败不替换旧 Snapshot;unknown device 不继承 GlobalRisk High。 +v2.1 将彻底消除 EffectiveRisk 的 GlobalRisk fail-open fallback。 -ChatGPT Actions 识别的标准接口集合: +## 8. Session 与文件安全 +Session:默认 RingBuffer 2MB,总 buffer 8MB,hard TTL 30m,idle TTL 10m,LastAccess + cleanup。 +kill/terminate 使用 Session 内部 process handle,不接受客户端 PID;Principal 强隔离属于 v2.1。 +edit_block:唯一匹配、generation fingerprint、临时文件、fsync、atomic rename、保留权限。 -### 3.1 `/api/v1/devices` (GET) -- **说明**:获取当前所有在线/受管设备列表及健康状态。 -- **返回**:`[{"name": "wjyhk", "is_local": true, "status": "online"}, {"name": "hwsg", "status": "online"}]` - -### 3.2 `/api/v1/exec` (POST) -- **说明**:在指定节点执行 Shell 命令。 -- **请求体**: - ```json - { - "device": "hwsg", // 节点昵称,缺省默认 local / wjyhk - "command": "free -h", // 要执行的命令 - "workdir": "/root", // 可选工作目录 - "timeout": 30 // 超时时间(秒) - } - ``` -- **响应体**: - ```json - { - "device": "hwsg", - "exit_code": 0, - "stdout": "...", - "stderr": "", - "duration_ms": 120 - } - ``` - -### 3.3 `/api/v1/fs/read` (POST) -- **说明**:受控读取指定设备的文件内容。 -- **参数**:`device`, `path`, `offset_bytes`, `limit_bytes`(防止大文件撑爆模型上下文)。 - -### 3.4 `/api/v1/fs/write` (POST) -- **说明**:在指定设备创建或覆写文件。 -- **参数**:`device`, `path`, `content`。 - ---- - -## 4. Hub 与 Agent 节点通信规范 - -1. **Agent 注册与鉴权**: - - Agent 启动时通过 `wss://hub.domain.com/agent/ws` 发起长连接。 - - 握手使用 `Authorization: Bearer ` Header;Cluster Secret 不进入 URL。 - - 握手成功后,Hub 内存注册表更新该设备为 `online`,并启动双向 Heartbeat ping/pong(30s 周期)。 - -2. **指令下发 (JSON-RPC)**: - - Hub 收到 ChatGPT 请求 ➡️ 生成 `task_id` ➡️ 通过 WS 发送 `{"action": "exec", "task_id": "...", "command": "..."}`。 - - Agent 执行完毕后返回 `{"task_id": "...", "result": {...}}`。 - - Hub 审计日志落库后返回给 ChatGPT。 - ---- - -## 5. 项目工程结构与技术选型 - -- **开发语言**:Go 1.22+(高性能、低内存、单二进制交叉编译友好) -- **Web 框架**:Gin 或纯标准库 `net/http` + `gorilla/websocket` -- **存储**:SQLite (纯粹用于审计日志与持久化配置) - -``` -vps-commander/ -├── cmd/ -│ ├── hub/ # 中央控制网关主入口 -│ └── agent/ # 节点客户端主入口 -├── internal/ -│ ├── api/ # ChatGPT Actions HTTP 接口 -│ ├── auth/ # Bearer Token 与 Secret 鉴权 -│ ├── cluster/ # 节点连接池、心跳与 WebSocket 管理 -│ ├── executor/ # 本地/远程执行器抽象 -│ └── storage/ # 审计日志与设备配置持久化 -├── web/ # 极简设备状态面板(纯 HTML/CSS 嵌入二进制) -├── openapi/ # 供 ChatGPT 导入的 openapi.json -├── Makefile # 多架构编译 (linux/amd64, linux/arm64) -└── README.md # 部署与 ChatGPT 配置指南 -``` - ---- - -## 6. Hub Web 控制面板设计规范 - -### 6.1 定位与设计原则 -- **极简独立**:前端采用纯 HTML5 + TailwindCSS/原生CSS + Vanilla JS,不引入复杂 node 构建工具链,通过 Go 1.16+ `embed.FS` 直接打包进单一二进制产物。 -- **开箱即用**:零外部静态资源依赖,访问 `https://hub.yourdomain.com/` 即可直接加载。 -- **低资源消耗**:Web 面板由 Hub 服务原生托管,静态文件常驻开销基本为零。 - -### 6.2 核心功能模块 -1. **设备看板 (Device Overview)** - - 受管设备列表:别名(Alias)、当前状态(Online/Offline)、系统架构与内核、IP 地址、最后心跳(Heartbeat)。 - - 快速连接指引:点击“添加节点”,自动生成带 Token 的单行一键安装/运行命令(如 `curl -sL https://... | bash -s -- --hub=... --token=...`)。 - - 设备启停与踢出操作:支持在面板主动注销失效/弃用节点。 - -2. **ChatGPT Actions 配置与向导中心** - - 托管与展示 `/openapi.json` 规范预览。 - - 提供专属 API Key 生成、轮换与撤销功能。 - - 提供直接导入 ChatGPT Custom GPT 的一键复制 Schema 按钮与预设 System Prompt 建议。 - -3. **实时操作审计与日志 (Audit Log)** - - 记录来源(ChatGPT / Web 手动)、目标设备、动作(exec / file_read / file_write)、执行内容、执行耗时、退出码与结果摘要。 - - 支持按设备、关键字实时搜索过滤。 - -4. **Web 快速调试终端 (Quick Terminal / Console)** - - 提供快速测试输入框,选择目标设备后可直接输入命令测试执行并查看即时输出,无需打开 ChatGPT 即可验证节点联通性。 +## 9. 部署与回滚 +Internet → TLS Reverse Proxy → 127.0.0.1:9521;Agent 仅出站 WSS。 +生产节点:wjyhk、N3450、hwhk、hwsg、m4-live-agent、qnvn。 +backup → clean build → single-node gray → Hub recovery → rolling Agent → audit → acceptance。 +发现断联、授权绕过、credential 泄露或协议不兼容,立即停止 rollout 并回滚。 diff --git a/docs/BUGHUNT_20261002.md b/docs/BUGHUNT_20261002.md new file mode 100644 index 0000000..259089e --- /dev/null +++ b/docs/BUGHUNT_20261002.md @@ -0,0 +1,129 @@ +# vps-commander 生产 Bug Hunt 报告(2026-10-02) + +- **测试人**:安全测试员(独立 bug hunt) +- **测试时间**:2026-10-02 13:36–13:50(+08) +- **测试对象**:生产 Hub(wjyhk,13:36:06 重启)+ 6 节点 Agent +- **测试方式**:只读探测 + 无害命令(echo/true),未写生产文件、未改配置、未重启服务、未碰 commander.db +- **结论**:发现 **4 个 bug**,最高严重度 **高**。另有若干“未发现问题”的项如实记录。 + +--- + +## 【标题】生产 Agent 二进制构建自脏工作树,缺失已提交代码 + +**【严重度:高】** + +**【复现步骤】** +1. 在 wjyhk 执行 `go version -m /opt/vps-commander/vps-commander-agent`,观察 `vcs.revision=a5620cb` 且 `vcs.modified=true`。 +2. 对比源码:`git show a5620cb:cmd/agent/main.go` 的 action switch 只有 6 个 case(mcp_list/mcp_test/mcp_call/exec/file_read/file_write),无 session 相关、无 `read_multiple_files`。 +3. 但生产 Agent 实际能处理 `start_process`(session 功能可用),说明二进制内容无法从任何 commit 还原——是脏树构建。 +4. Hub 同样 `vcs.modified=true`(13:36 重部署的二进制,revision=556870b)。 + +**【证据】** +``` +build vcs.revision=a5620cb9c4d3570cf5ce2abe8772ef4e3b91bd76 +build vcs.time=2026-10-01T16:45:10Z +build vcs.modified=true +``` +各节点 Agent md5 一致(35e965a9),均为同一脏构建,于 13:22 统一重启部署。 + +**【影响分析】** +- 生产二进制不可复现:出问题时无法用 `git checkout && go build` 还原现场,排障与回滚失去基准。 +- 脏构建内容未知:`read_multiple_files` 在源码 192969d 中已加入 Agent,但生产 Agent 不支持(见 Bug #3),说明构建时的脏树处于部分完成状态,**可能还缺失其他已提交的安全修复**,需逐项核对。 +- **建议**:从干净 HEAD 重新构建 Hub+Agent,全量重新部署,部署后校验 `vcs.modified` 为空且 revision==HEAD。 + +--- + +## 【标题】`read_multiple_files` 在所有远端节点上失败(Hub-Agent 协议不一致) + +**【严重度:中】** + +**【复现步骤】** +1. `vps-mcp.py call read_multiple_files '{"device":"hwsg","paths":["/etc/hostname"],"limit":100}'` → 返回 `{"error": "unsupported action"}`。 +2. 同样调用 `device=wjyhk`(本地)→ 正常返回文件内容。 +3. 查源码:`internal/api/mcp_adapter.go:287` 的 `ReadMultipleFiles` 对远端走 `Cluster.ReadMultipleFiles`;Agent 侧 `cmd/agent/main.go:261` 在当前源码中有该 case,但生产 Agent 二进制(脏构建)不支持,落入 `default: unsupported action`(main.go:391)。 + +**【证据】** +```json +{"error": "unsupported action"} +``` +(hwsg/N3450 等远端节点复现,wjyhk 本地正常) + +**【影响分析】** +- MCP 工具列表向 AI 客户端 quảng cáo `read_multiple_files` 可用于所有设备,实际 5/6 节点不可用,功能性 bug。 +- 根因是 Bug #1(脏构建)的直接后果;修复 Bug #1(干净重建+重部署)后本项自动解决。 +- 在修复前,建议 Hub 对不支持该 action 的 Agent 返回明确错误而非透传 `unsupported action`,或在 capability 协商中隐藏该工具。 + +--- + +## 【标题】`/api/v1/process/session` 请求结构体无 JSON tag,snake_case 字段被静默丢弃 + +**【严重度:中】** + +**【复现步骤】** +1. `POST /api/v1/process/session?action=start`,body `{"device":"hwsg","command":"echo hi","session_id":"my-id"}`(snake_case,如响应格式所示)。 +2. 响应返回 `{"session_id":"04d39d85b150..."}`——**客户端传的 ID 被丢弃**,服务端生成了随机 ID。 +3. 随后用 `my-id` 做 read/stop → `session not found`。 +4. 改用精确大小写 `{"SessionID":"my-id"}` → 全流程正常。 + +**【证据】** +```go +// internal/api/api.go:784 +var req struct { + Device, SessionID, Command, Workdir, Data string // 无 json tag! + Force bool + RingCapacity int `json:"ring_capacity"` +} +``` +Go encoding/json 对无 tag 字段仅做大小写不敏感匹配,`session_id`(snake_case)无法匹配 `SessionID`,被静默忽略。 + +**【影响分析】** +- API 契约破裂:响应用 `session_id`(snake_case),请求却要求 `SessionID`(CamelCase);任何按常规 REST 惯例(或照着响应字段)写的客户端都会踩坑,且失败是静默的(拿到一个“成功”但对不上的 session)。 +- 非安全漏洞,但属于生产功能 bug。修复:在结构体上加 `json:"device"` 等 snake_case tag(注意与 openapi.json 文档对齐)。 + +--- + +## 【标题】`/api/v1/process/session` 不支持 Hub 本节点(无本地回退) + +**【严重度:中低】** + +**【复现步骤】** +1. `POST /api/v1/process/session?action=start`,body `{"Device":"wjyhk","Command":"echo hi"}`。 +2. 返回 `device offline`(HTTP 409)。 +3. 对比:`POST /api/v1/exec` 同样 `device=wjyhk` 可正常执行(`exec` 有 `isRemote` 本地回退,api.go:744)。 + +**【证据】** +```go +// processSession 直接走 Cluster,无 isRemote 判断: +if s.Cluster == nil { http.Error(w, "cluster unavailable", 503); return } +... +result, err = s.Cluster.StartProcess(ctx, req.Device, ...) // wjyhk 无 agent WS 连接 → device offline +``` + +**【影响分析】** +- 功能不一致:exec/read/write 等在 Hub 本节点可用,唯独 session 管理不可用。用户在 Hub 本机无法使用长会话功能。 +- 修复:给 processSession 加与 exec 相同的 `isRemote` 本地回退(Hub 侧需持有一个本地 SessionManager,或复用 executor 包)。 + +--- + +## 未发现问题的项(逐项如实记录) + +1. **认证绕过**:无 token/错 token/空 Bearer 访问 `/api/v1/*` 与 `/panel/api/*` 均返回 401;`/healthz` 200 为预期设计。未发现绕过。 +2. **畸形输入**:malformed JSON、空 body、300KB 超大 body(超 256KB MaxBytesReader 限制)均返回 400,无 panic。Hub 日志自 13:24 以来 0 panic、0 error。 +3. **路径穿越**:`../../../etc/hostname` 可读、`\0` 被 `validPath` 拦截(400)。但本工具是已认证管理员工具,无沙箱设计约束,`..` 解析属操作系统正常行为,不视为漏洞。 +4. **设备名注入**:空字符串回退本机(设计如此)、不存在设备/超长字符串/含 `\0` 的设备名均 `security mode unknown denies exec`,fail-closed,无 panic。 +5. **Session 生命周期**:Agent 侧每分钟 `sessions.Cleanup()`,idle TTL 10min + hard TTL 存在;`SessionManager` 有互斥锁,5 并发创建 session 无竞态崩溃(2 成功、3 因达到上限 4 被正确拒绝,上限由 `MaxSessionBufferTotal/DefaultRingCapacity=4` 决定,符合设计)。 +6. **并发压力**:10 并行原生 HTTP 请求全部 200、响应快;Hub 内存稳定(~20MB)。30 并行 MCP 调用大量超时系客户端 SSE 建连开销,非 Hub 问题。 +7. **配额**:`ExecLimiter` 32 并发信号量存在;无单客户端速率限制(设计选择,非 bug)。 +8. **Agent-MCP 畸形参数**:不存在的 tool/含 `\0` 的参数返回干净的 `MCP HTTP status 400`,无 panic、无信息泄漏。 +9. **kill 进程**:API 只接受 SessionID,Agent 用内部 `cmd.Process` 句柄 kill,不接受客户端 PID,无 PID 重用误杀风险。 + +--- + +## 附:测试期间观察到的部署活动 + +- 13:36:06 Hub 被重部署(此前为 13:24),二进制 revision 由 38382d2 变为 556870b。测试期间生产处于活跃变更中,部分结论(如 Hub revision)以测试时刻为准。 +- Agent 在各节点为同一脏构建(md5 35e965a9,13:22 部署),`vcs.modified=true`。 + +--- + +*安全测试员,2026-10-02* diff --git a/docs/DC_PHASE1_IMPLEMENTATION.md b/docs/DC_PHASE1_IMPLEMENTATION.md index 4a9b932..d417757 100644 --- a/docs/DC_PHASE1_IMPLEMENTATION.md +++ b/docs/DC_PHASE1_IMPLEMENTATION.md @@ -1,5 +1,7 @@ # DC Refactoring Phase 1 Implementation Record +> 文档属性:历史实施记录。后续阶段和当前状态以当前架构规范与 v2.1 规范为准。 + Date: 2026-10-02 ## Completed diff --git a/docs/DEV_SPEC.md b/docs/DEV_SPEC.md index 8594334..a0f4ab9 100644 --- a/docs/DEV_SPEC.md +++ b/docs/DEV_SPEC.md @@ -1,119 +1,42 @@ -# VPS-Commander 详细技术规格与开发实施方案 (v1.1.0) +# VPS-Commander 开发与协议规范 -## 一、 系统架构角色划分 +## 1. 技术基线 +Go + SQLite + net/http + WebSocket。 +组件:cmd/hub、cmd/agent、cmd/mcp-stdio;internal/api、auth、cluster、executor、mcp、security、storage、web、notify、model。 -整个系统划分为两个独立二进制产物(单一代码库仓库编译): -1. **`vps-commander-hub` (中央网关 + 控制面板)**: - - 部署在有公网域名或反代的主机上(当前主力机 `wjyhk`)。 - - 监听端口:`127.0.0.1:9521`(由 Lucky 负责 TLS 证书卸载与反代)。 - - 暴露端点: - - 面向 ChatGPT Actions:`/api/v1/*`(Bearer Token 鉴权) - - 面向 Agent 长连接:`/agent/ws`(Cluster Secret 握手) - - 面向用户极简管理面板:`/` 及 `/static/*`(Go embed 静态资源,支持密码登录/Cookie鉴权) - - 描述文件:`/openapi.json` - - 本身内置 Local Executor(直接代表本地主力机,设备名:`local` 或自定义主机名)。 -2. **`vps-commander-agent` (节点轻量客户端)**: - - 部署在其他受管节点(如 `hwsg` 等)。 - - 主动向 Hub 发起安全 WebSocket 连接(支持断线指数退避重连)。 - - 纯受控执行器,只响应 Hub 下发指令,不开放任何公网入站端口(彻底规避防火墙/NAT问题)。 +## 2. Agent Protocol +Agent 主动连接 /agent/ws。 +握手包含 protocol version、AgentVersion、capabilities、per-device credential。 +Hub 依据 credential 建立 canonical device identity;device/name 只能作为路由参数。 ---- +## 3. HTTP +/api/v1/devices、/api/v1/exec、/api/v1/file/read、/api/v1/file/list、/api/v1/file/info、/api/v1/file/search、/api/v1/process/session、/api/v1/file/write、/api/v1/devices/file/edit_block、/api/v1/mcp/*、/api/v1/security/*、/api/v1/notifications/webhook*、/healthz、/openapi.json。 +Panel 使用 /panel/*。 -## 二、 协议设计 (RPC over WebSocket) +## 4. MCP +serverInfo version:1.2.0;protocolVersion:2024-11-05。 +11 tools:list_devices、exec_command、read_file、read_multiple_files、create_directory、move_file、list_processes、edit_block、write_file、list_agent_mcp、call_agent_mcp。 +远程 HTTP 当前为 legacy SSE:GET /mcp/sse + POST /mcp/message?sessionId=...;本地为 stdio。 -### 2.1 握手与注册 (Handshake) -Agent 连接 URL: `wss://hub.domain.com/agent/ws?device_name=hwsg` -- Hub 校验通过后: - - 发送握手成功包:`{"event": "registered", "device": "hwsg", "heartbeat_interval": 30}` - - 将该连接注入 `DeviceManager`,状态标为 `online`。 +## 5. MCP 授权 +exec → High;read → Low;write/edit/create/move → Medium;call_agent_mcp → mcp;list_agent_mcp → read。 +MCP adapter 与 direct Agent MCP 使用同一 Hub security model。 -### 2.2 心跳 (Ping/Pong) -- 每 30 秒由 Hub 发送 `{"event": "ping", "ts": 1727049600}`。 -- Agent 回复 `{"event": "pong", "ts": 1727049600}`。连续 2 次无响应标记为 `offline`。 +## 6. 认证 +HTTP/MCP:Authorization: Bearer API_KEY。 +禁止 ?token、?key、?api_key。 +Agent:per-device credential;SQLite 只保存 hash;生产不依赖 Cluster Secret fallback。 +Panel:浏览器只持有 Panel Session;Admin Token 在服务端 bridge。 -### 2.3 命令下发与响应 (Request-Response) -- Hub 下发: - ```json - { - "id": "task_6b7a8c9d", - "action": "exec", - "payload": { - "command": "free -h", - "workdir": "/root", - "timeout": 30 - } - } - ``` -- Agent 执行完返回: - ```json - { - "id": "task_6b7a8c9d", - "status": "success", - "exit_code": 0, - "stdout": "...", - "stderr": "", - "duration_ms": 45 - } - ``` +## 7. 资源 +ExecLimiter 32;SearchLimiter 8;Node.WriteMu;Node.OpMu。 +Session:ring 2MB;total 8MB;hard TTL 30m;idle TTL 10m;cleanup。 ---- +## 8. 测试 +go test ./...;go test -race ./...;git diff --check。 +生产额外要求 clean tree、vcs.modified=false、revision 与 release commit 一致、单 Agent 灰度、Hub recovery、MCP smoke、security matrix。 -## 三、 ChatGPT Actions (OpenAPI 3.1) 接口定义 - -完整的 `openapi.json` 规范定义了以下 4 个原子能力: - -1. **`list_devices`**: - - `GET /api/v1/devices` - - 返回受管设备名、IP、状态(online/offline)、最后心跳。 -2. **`exec_command`**: - - `POST /api/v1/exec` - - 参数:`device` (默认: "local"), `command`, `workdir`, `timeout`。 -3. **`read_file`**: - - `POST /api/v1/file/read` - - 参数:`device`, `path`, `offset`, `limit`。 -4. **`write_file`**: - - `POST /api/v1/file/write` - - 参数:`device`, `path`, `content`。 - ---- - -## 四、 Hub Web 控制面板功能规范 - -### 4.1 技术实现 -- 单二进制静态内嵌:基于 Go `embed.FS` 打包 HTML5 + TailwindCSS + Vanilla JS。 -- 零外部 npm/node 依赖,开箱即用。 - -### 4.2 功能矩阵 -1. **设备看板 (Devices Dashboard)**: - - 节点列表展示(名称、IP、状态、架构/系统版本、最后活跃时间)。 - - 一键生成 Agent 安装注册命令(带 Token 参数)。 - - 手动注销/踢出无效节点。 -2. **ChatGPT Actions 向导 (Actions Guide)**: - - 动态渲染 `openapi.json` 并提供一键复制。 - - API Key 凭据生成、轮换与撤销。 - - 预设 System Prompt 最佳实践一键复制。 -3. **安全审计追踪 (Audit Trails)**: - - 实时日志流水:时间戳、来源 IP、目标节点、操作类型、执行命令、执行耗时、退出状态。 - - 支持日志按设备名、时间区间筛选。 -4. **快速网页终端 (Quick Console)**: - - 应急测试控制台,免切 ChatGPT 直接在 Web 端选择节点跑指令验证联通性。 - ---- - -## 五、 存储与安全审计 (SQLite) - -- 数据库文件:`data/commander.db` -- 数据表结构: - 1. `devices`:记录设备名、备注、添加时间、密钥 Hash。 - 2. `audit_logs`: - - `id`, `timestamp`, `caller_ip`, `device`, `action`, `command`, `exit_code`, `duration_ms`, `error_msg` - - 确保在 ChatGPT 里执行的所有高危操作均可追溯。 - ---- - -## 六、 开发实施里程碑 (Milestones) - -- [ ] **M1: 基础骨架与单机执行**(完成本地 Local Executor + Gin API + Bearer 鉴权 + `/openapi.json`) -- [ ] **M2: Agent WebSocket 协议与多节点分发**(完成 Agent 注册、心跳保活、Hub 路由转发) -- [ ] **M3: 审计日志与嵌入式 Web 管理页**(完成前端内嵌、看板交互、命令历史审计与快速控制台) -- [ ] **M4: 本机 Lucky 证书反代与 ChatGPT 联调上线** +## 9. v2.1 +P0:EffectiveRisk fail-closed;Agent token 不进入 argv/cmdline。 +P1:Principal/Operator、Session owner 强隔离、完整身份审计链。 +v2.1 不改变 Low/Medium/High 语义,不恢复 Shared Secret。 diff --git a/docs/DOCUMENTATION_BASELINE_20261002.md b/docs/DOCUMENTATION_BASELINE_20261002.md new file mode 100644 index 0000000..eec7f07 --- /dev/null +++ b/docs/DOCUMENTATION_BASELINE_20261002.md @@ -0,0 +1,123 @@ +# VPS-Commander 文档基线与现状索引 + +> 基线日期:2026-10-02 +> 本文件是仓库文档的导航入口。历史审核记录保留原貌,不作为当前实现契约。 + +## 当前定位 + +VPS-Commander 是自托管的多节点 Linux 运维控制中枢。 +链路:AI/客户端 → Hub → Local Executor 或 Agent WebSocket → 目标主机。 + +当前目标: +- 多节点统一身份、路由与状态管理; +- 文件、进程、Shell、MCP 运维能力; +- 认证、三级风险授权与审计; +- 可回滚、可持续升级的生产部署; +- 面向 AI Agent 的 MCP 与 HTTP 接口。 + +## 当前架构 + +```text +AI / MCP / Web + | + HTTPS/WSS + | +Reverse Proxy + | +Hub 127.0.0.1:9521 + | | +Local Agent WSS +Executor | + +-- N3450 + +-- hwhk + +-- hwsg + +-- m4-live-agent + +-- qnvn + | +SQLite: state / policy / audit +``` + +Hub 不直接公网监听;Agent 只主动回连 Hub。 + +## 当前安全模型 + +- HTTP/MCP:Bearer API Key; +- Agent:per-device credential; +- Policy Snapshot:设备级有效策略; +- Tool Registry:Low / Medium / High; +- MCP、HTTP、direct Agent MCP 统一授权; +- SQLite 审计; +- 生产 Shared Secret fallback 已关闭。 + +## 当前 MCP + +11 个工具: +list_devices、exec_command、read_file、read_multiple_files、 +create_directory、move_file、list_processes、edit_block、 +write_file、list_agent_mcp、call_agent_mcp。 + +当前 HTTP MCP 是 legacy HTTP+SSE;本地是 stdio。 +Streamable HTTP 是后续演进方向。 + +## 当前 HTTP + +主要接口: +/api/v1/devices +/api/v1/exec +/api/v1/file/read +/api/v1/file/list +/api/v1/file/info +/api/v1/file/search +/api/v1/process/session +/api/v1/file/write +/api/v1/devices/file/edit_block +/api/v1/mcp/* +/api/v1/security/* +/api/v1/notifications/webhook* +/agent/ws +/healthz +/openapi.json +/panel/* + +## 文档分层 + +当前规范: +- README.md +- docs/ARCHITECTURE.md +- docs/DEV_SPEC.md +- docs/MCP_INTEGRATION.md +- deploy/README.md +- docs/ACCEPTANCE_CRITERIA.md +- docs/PROGRESS_TRACKING.md +- docs/VPS_COMMANDER_V2_1_SECURITY_HARDENING_SPEC.md + +审计/整改输入: +- docs/BUGHUNT_20261002.md +- docs/DC_REFACTORING_AND_SECURITY_SPEC.md +- docs/DC_REFACTORING_SECURITY_REVIEW_HANDOFF_20261002.md +- docs/REVIEW_B_TO_A_HANDOFF_20261002.md + +历史记录: +- REVIEW_A_CODE_AUDIT_20261002.md +- REVIEW_B_CODE_AUDIT_20261002.md +- INCIDENT_TIMEOUT-20260930.md +- M4_FINAL_ACCEPTANCE_REPORT.md +- DC_PHASE1_IMPLEMENTATION.md + +历史报告解释演进原因,不覆盖当前规范。 + +## 生产状态 + +2026-10-02 审计确认 6 个设备在线: +wjyhk、N3450、hwhk、hwsg、m4-live-agent、qnvn。 + +同时发现生产二进制存在 vcs.modified=true 的构建漂移。 +因此必须区分“源码当前状态”和“生产现场状态”。 +下一次发布必须 clean build、校验 revision/modified,再滚动部署。 + +## v2.1 + +P0:EffectiveRisk fail-closed;Agent Token 脱离 argv/cmdline。 +P1:Principal/Operator 身份、Session 强隔离、完整身份审计链。 +这些属于下一版本,不伪装成 v2.0 已完成能劘,不伪装成 v2.0 已完成能力。 + diff --git a/docs/INCIDENT_TIMEOUT-20260930.md b/docs/INCIDENT_TIMEOUT-20260930.md index 0b6267b..7b1eeb2 100644 --- a/docs/INCIDENT_TIMEOUT-20260930.md +++ b/docs/INCIDENT_TIMEOUT-20260930.md @@ -1,5 +1,7 @@ # 运维事件记录:大文件逆向解析命令超时 +> 文档属性:历史事件记录。本文保留原始事件证据,不作为当前系统状态契约。 + - 日期:2026-09-30 - 项目:VPS-Commander - 关联任务:N3450 / FNOS 飞牛音乐 `trim-music` API 逆向审计 diff --git a/docs/M4_FINAL_ACCEPTANCE_REPORT.md b/docs/M4_FINAL_ACCEPTANCE_REPORT.md index 947bcb2..b343796 100644 --- a/docs/M4_FINAL_ACCEPTANCE_REPORT.md +++ b/docs/M4_FINAL_ACCEPTANCE_REPORT.md @@ -1,5 +1,7 @@ # VPS-Commander M4 最终验收报告(待人工签收) +> 文档属性:历史验收快照(2026-09-28)。当前状态以 README、DOCUMENTATION_BASELINE_20261002 和当前验收门禁为准。 + 日期:2026-09-28 状态:🟡 技术收尾完成;管理面板 UI 已人工验收并上线,M4 总体验收仍等待 Custom GPT Actions 人工签收 diff --git a/docs/MCP_INTEGRATION.md b/docs/MCP_INTEGRATION.md index 52e8330..ec017b0 100644 --- a/docs/MCP_INTEGRATION.md +++ b/docs/MCP_INTEGRATION.md @@ -1,50 +1,52 @@ -# VPS-Commander MCP (Model Context Protocol) 接入指南 +# VPS-Commander MCP 接入与能力 -## 一、概述 -为了应对 OpenAI Custom GPTs 退役及新一代 Plugins/Skills 规范转型,VPS-Commander 现已全面支持标准 **MCP (Model Context Protocol)** 协议。 +## 1. 当前状态 +MCP JSON-RPC 2.0;serverInfo 1.2.0;initialize protocolVersion 2024-11-05。 +远程 HTTP 当前是 legacy HTTP+SSE;本地是 stdio。Streamable HTTP 是后续演进方向。 -- **零侵入**:原有 REST API、OpenAPI 3.1、Web 面板及 WebSocket 多节点连接池 100% 保持不变。 -- **纯 Go 原生**:零外部庞大框架依赖,常驻内存基线依然保持在极低水平。 -- **双模支持**:同时支持 **远程 SSE 模式** 与 **本地 stdio 模式**。 +## 2. 11 个工具 +| Tool | Risk | 作用 | +|---|---|---| +| list_devices | Low | 设备列表 | +| exec_command | High | Shell | +| read_file | Low | 文件读取 | +| read_multiple_files | Low | 批量读取 | +| create_directory | Medium | 创建目录 | +| move_file | Medium | 移动/重命名 | +| list_processes | Low | 进程观察 | +| edit_block | Medium | 原子文本修改 | +| write_file | Medium | 文件写入 | +| list_agent_mcp | Low | Agent MCP 列表 | +| call_agent_mcp | Medium | 调度 Agent MCP | ---- +## 3. 远程接入 +GET /mcp/sse → sessionId → POST /mcp/message?sessionId=。 +请求头:Authorization: Bearer 。 +HTTP+SSE 仅作为兼容层,不作为未来新能力的主要 transport。 -## 二、支持的 4 大 MCP Tools +## 4. stdio +启动 vps-commander-mcp-stdio,参数 -hub -key 。 +API Key 不提交到仓库。 -| Tool 名称 | 参数说明 | 描述 | -| :--- | :--- | :--- | -| `list_devices` | 无 | 列出当前所有已注册的受控 VPS 节点(如本机 `wjyhk` 及远程 `m4-live-agent` 等)及在线状态 | -| `exec_command` | `device` (可选), `command` (必填), `workdir` (可选), `timeout` (可选, 默认30) | 在指定受控节点执行任意 Shell 命令并返回退出码与输出 | -| `read_file` | `device` (可选), `path` (必填), `offset` (可选), `limit` (可选) | 读取指定受控节点的文件内容(支持安全分页读取) | -| `write_file` | `device` (可选), `path` (必填), `content` (必填) | 在指定受控节点创建或覆写文件 | +## 5. 参数 +exec_command:device、command、workdir、timeout。 +read_file:device、path、offset、limit;默认 256 KiB,最大 1 MiB。 +read_multiple_files:device、paths、limit;paths 最多 32 个。 +create_directory:device、path。 +move_file:device、source、destination。 +list_processes:device。 +edit_block:device、path、old_text、new_text;old_text 必须唯一匹配。 +write_file:device、path、content。 +list_agent_mcp:device。 +call_agent_mcp:device、server、tool、arguments。 ---- +## 6. 安全链路 +MCP Client → Bearer auth → JSON-RPC → tool mapping → authenticated device → Policy Snapshot → Tool Registry → allow/deny → Local/Agent → audit。 +未知设备不得因为 GlobalRisk 而获得 High。 -## 三、接入方式 +## 7. Agent MCP +Hub 发现远程 Agent MCP service;客户端不直连 Agent。 +Hub 负责 device authentication、risk gate、routing、audit。 -### 方式 1:远程 SSE 模式(适用于远程 Agent、OpenAI 新生态端点) - -Hub 原生提供 MCP SSE 端点(需带 Bearer Token 鉴权): -- **SSE 建立端点**:`GET https://vpstool.kory.kdns.fr/mcp/sse` -- **消息交互端点**:`POST https://vpstool.kory.kdns.fr/mcp/message?sessionId=` -- **请求头**:`Authorization: Bearer ` - -### 方式 2:本地 stdio 模式(适用于 Claude Desktop、Cursor、VS Code) - -直接使用编译好的极轻量 Go 二进制 `vps-commander-mcp-stdio-linux-amd64`。 - -#### 客户端配置示例 (`claude_desktop_config.json` 或 Cursor MCP 设置): - -```json -{ - "mcpServers": { - "vps-commander": { - "command": "/root/.openclaw/workspace/vps-commander/bin/vps-commander-mcp-stdio-linux-amd64", - "args": [ - "-hub", "https://vpstool.kory.kdns.fr", - "-key", "YOUR_API_KEY" - ] - } - } -} -``` +## 8. 下一步 +Streamable HTTP、SSE fallback、capability-based advertisement、Principal audit context、显式 operation/session handle。 diff --git a/docs/PROGRESS_TRACKING.md b/docs/PROGRESS_TRACKING.md index 825417d..95c257f 100644 --- a/docs/PROGRESS_TRACKING.md +++ b/docs/PROGRESS_TRACKING.md @@ -1,121 +1,47 @@ -# VPS-Commander 开发进度看板与交付清单 +# VPS-Commander 当前进度与路线图 -> 角色定位: -> - **开发实施**:外部 GPT -> - **架构监督、文档规范、验收审核与严格收尾**:OpenClaw (yk) +> 更新时间:2026-10-02 ---- +## 1. 已完成 +- Hub/Agent 双通道 +- 多节点状态持久化 +- per-device credential +- Security Snapshot +- Low/Medium/High gate +- MCP 安全门禁 +- edit_block 原子安全 +- Session 资源限制 +- Web Panel +- Webhook +- MCP 11 tools -## 阶段推进概览 (Status Board) +## 2. 当前 MCP +11 个:list_devices、exec_command、read_file、read_multiple_files、create_directory、move_file、list_processes、edit_block、write_file、list_agent_mcp、call_agent_mcp。 +早期文档中的“4 个 MCP 工具”已废止。 -| 阶段 | 模块 / 目标 | 负责人 | 状态 | 交付物检验 | -| :--- | :--- | :--- | :--- | :--- | -| **Phase 0** | 架构设计、接口契约与开发文档 | OpenClaw | 🟢 **已完成 (Done)** | `ARCHITECTURE.md`, `DEV_SPEC.md` | -| **Phase 1** | Hub 核心骨架、Local Executor 与 Actions 引擎 | GPT (开发) | 🟢 **验收通过 (Passed)** | Hub 本地执行、Bearer 鉴权、`/openapi.json` | -| **Phase 2** | Agent 通信协议与多节点分发 (WebSocket RPC) | GPT (开发) | 🟢 **验收通过 (Passed)** | 5项生产级缺陷彻底整改;并发竞态/强杀0 Panic/Header鉴权实测全绿 | -| **Phase 3** | 内嵌 Web 控制面板与 SQLite 审计模块 | GPT (开发) | 🟢 **验收通过 (Passed)** | CSS MIME、SQLite 并发审计丢失缺陷已修复;100 并发无损落盘、-race、浏览器 MIME 与会话权限复验全绿 | -| **Phase 4** | 独立审核、严苛回归测试与上线收尾 | OpenClaw | 🟡 **收尾整改中 (Hardening)** | 技术门禁基本全绿;待 Custom GPT Actions、Key 轮换与人工签收 | +## 3. v2.0 当前定位 +Hub、Agent WSS、per-device credential、Policy Snapshot、Tool Registry、MCP/HTTP unified gate、SQLite audit、Panel、Session limits 已形成完整架构。 ---- +## 4. 当前发布问题 +2026-10-02 Bug Hunt: +1. 生产 binary 曾由 dirty tree 构建; +2. 造成生产 Agent 与 HEAD 能力漂移; +3. process/session snake_case 请求字段存在兼容问题; +4. Hub 本地 process/session 缺少 local fallback。 +在源码、测试、生产现场同时确认前,不把这些项目标记为已修复。 -## 详细功能检查清单 (Feature Checklist for GPT) +## 5. v2.1 P0 +EffectiveRisk:canonical device identity;unknown/offline/bad credential → risk 0;GlobalRisk 仅用于已认证设备;unknown 不得继承 High。 +Agent credential:EnvironmentFile/LoadCredential;ExecStart 不出现 secret;ps/cmdline 不可读 token;支持 rotation + rollback。 -### 📌 Milestone 1: Hub 基础与单机 Actions (Phase 1) -- [x] **项目骨架构建**: - - [x] Go 模块初始化 (`go.mod`, module `github.com/wjyhk/vps-commander`) - - [x] 目录分层清晰(`cmd/hub`, `internal/api`, `internal/executor`, `internal/auth`, `internal/storage`) -- [x] **安全鉴权中间件**: - - [x] 校验 `Authorization: Bearer ` (ConstantTimeCompare) - - [x] 无效/缺失 Token 统一返回标准 HTTP 401 -- [x] **Local Executor (本地执行器)**: - - [x] 执行 Shell 命令(`exec.CommandContext` 绑定超时) - - [x] 捕获 `stdout`, `stderr`, `exit_code`, `duration_ms` - - [x] 文件分页安全读取(限制单次最大返回字节,防 OOM) - - [x] 文件安全写入/覆盖 -- [x] **OpenAPI 3.1 动态端点**: - - [x] `GET /openapi.json`:包含 schema 与 BearerAuth - - [x] `GET /api/v1/devices`:返回本地节点信息 - - [x] `POST /api/v1/exec`:执行本地命令 - - [x] `POST /api/v1/file/read`:读取本地文件 - - [x] `POST /api/v1/file/write`:写入本地文件 +## 6. v2.1 P1 +Principal:principal_id、principal_type、credential_id、device_id。 +Session owner 绑定 Principal;takeover 必须显式授权并审计。 +形成 principal → credential → session → device → operation 链。 ---- +## 7. 发布顺序 +backup → clean build → single-node gray → Hub recovery → rolling Agent → MCP smoke → security matrix → audit → acceptance。 -### 📌 Milestone 2: Agent WebSocket 协议与多节点路由 (Phase 2) - -> **2026-09-23 生产级 Code Review 驳回:** 原实现不得直接投入生产。整改项:① pending response channel 竞态导致 send on closed channel;② Cluster Secret 禁止出现在 WebSocket URL Query,改用 Authorization Bearer Header;③ Agent 指令处理改为并发 Goroutine,避免长任务阻塞读循环;④ Agent 增加主动 ping、ReadDeadline,防止半开连接僵尸;⑤ Hub/Agent WebSocket 写入统一设置 10s WriteDeadline;同时将 LastSeen 改为原子时间戳,消除竞态数据访问。Phase 3 在本项重新验收前保持阻塞。 -- [x] **Agent 二进制开发 (`cmd/agent`)**: - - [x] 读取配置文件或 CLI 参数(`--hub`, `--name`, `--token`) - - [x] 主动向 Hub 发起 WSS 连接(`wss:///agent/ws`) - - [x] Cluster Secret 通过 WebSocket Authorization Bearer Header 发送,不进入 URL Query - - [x] 指令处理采用独立 Goroutine,并由单一写锁保护并发响应 - - [x] 主动 30s ping + 75s ReadDeadline,防止半开连接永久阻塞 - - [x] WebSocket 写入统一 10s WriteDeadline - - [x] 指数退避断线重连(1s, 2s, 4s... 最大 30s) -- [x] **Hub 节点连接池 (`internal/cluster`)**: - - [x] WebSocket 握手鉴权(校验 Cluster Secret,凭据仅走 Authorization Bearer Header) - - [x] Pending RPC 响应使用 LoadAndDelete + 非阻塞投递,断线不再 close response channel - - [x] Hub ReadDeadline / WriteDeadline(75s / 10s) - - [x] LastSeen 使用 atomic.Int64,避免读写竞态 - - [x] 设备连接注册表(维护设备别名、WS 连接、心跳时间) - - [x] 定时双向 Ping/Pong(30s 周期,超时 2 次标记离线) -- [x] **RPC 路由与跨节点下发**: - - [x] 当 API 请求 `device == "local"` 或本机别名时 ➡️ 走 Local Executor - - [x] 当 API 请求 `device == ""` 时 ➡️ 查找连接池,封装 JSON-RPC 消息异步等待回调 - - [x] 设备不在线或找不到时,返回友好错误:“设备 `` 处于离线状态” - ---- - -### 📌 Milestone 3: 内嵌 Web 控制面板与审计存储 (Phase 3) - -> **2026-09-23 M3 门禁状态:🟢 验收通过 (Passed)。** 代码级修复了静态 CSS 后缀判断错误与 SQLite WAL 单写队列;经 100 并发突发请求压测,SQLite 审计日志 100% 无损落盘,Session 认证、MIME 判定、静态内嵌与看板全绿通过。 -- [x] **SQLite 存储 (`internal/storage`)**: - - [x] 自动初始化数据库 `commander.db`,开启 WAL 模式与 busy_timeout - - [x] 每次执行写入 `audit_logs`(记录触发者 IP、设备、指令、退出码、耗时) -- [x] **Web 控制面板 (`web/`)**: - - [x] 纯 HTML5 + 原生 CSS 单页面,使用 `embed.FS` 打包(零外部静态资源) - - [x] **看板 1**:节点在线状态卡片、系统基础信息 - - [x] **看板 2**:ChatGPT Actions 向导(一键复制 Schema、Prompt 模板、Key 轮换) - - [x] **看板 3**:审计日志流水与刷新查询 - - [x] **看板 4**:Web 快速调试执行器(选择设备并执行命令) - ---- - -### 📌 Milestone 4: 审核、收尾与交付 (Phase 4, 由 OpenClaw 严格把关) - -> **2026-09-23 M3 正式验收通过,Phase 4 已解锁。** 本阶段进入独立总装门禁;未经全部回归、内存基线、上线链路与最终文档验收,不得标记为完成。 -- [x] 代码静态分析与编译:\`go vet ./...\`、\`go test -race ./...\`、AMD64/ARM64 clean build 全通过 -- [x] 内存硬上限回归:Hub 当前约 14.5MB;Agent 经 `GOGC=50` 优化后约 10.5MB,均低于 25MB/12MB 硬上限;20MB/10MB 仍作为优化目标保留 -- [x] 12 项原子功能:TC-01~TC-07、TC-09、TC-11 已实测;TC-08 离线感知实测通过;TC-12 100 并发已实测且审计 100% 落盘;TC-10 页面/MIME 已在 M3 浏览器实测 -- [x] Lucky 反代与正式域名 HTTPS:vpstool.kory.kdns.fr 已实测反代至本机 127.0.0.1:9521;根路径 302 到 /panel/login,OpenAPI 3.1.0 经 HTTPS 实链可访问,WebSocket Agent 已通过该上游注册在线 -- [ ] ChatGPT Custom GPT 真实联调通过并归档 - -### M4 收尾整改记录(2026-09-28) -- [x] 修正文档与实现漂移:正式 Hub 监听端口统一为 `127.0.0.1:9521`;Agent 握手统一为 `Authorization: Bearer` Header,Cluster Secret 不进入 URL。 -- [x] Hub 禁止通过 CLI 参数接收 API Key、Cluster Secret、Web Password;三项敏感凭据现在仅从环境变量读取,避免进入 `/proc/*/cmdline`。 -- [x] 统一内存门禁口径:Hub 25MB、Agent 12MB 为硬上限;20MB/10MB 为优化目标。 -- [x] 清理遗留测试 Agent;正式 Hub/Agent 已由 systemd 单实例接管,并完成单实例远程 Agent 实联调。 -- [ ] Custom GPT Actions 真实调用、Key 轮换、审计闭环与最终人工签收。 - -### M4 2026-09-28 实联调证据 -- [x] Hub/Agent 已切换为 systemd 管理;Hub 只监听 `127.0.0.1:9521`。 -- [x] Hub 敏感凭据不再接受 CLI 参数,仅从 `EnvironmentFile` 环境变量读取;进程命令行已核验无凭据。 -- [x] Agent 单实例:仅保留 `m4-live-agent` 一个正式实例;通过 `wss://vpstool.kory.kdns.fr/agent/ws` 成功注册 online。 -- [x] VPS-Commander 实联调:本机 exec、远程 Agent exec、远程 file read、远程 file write、timeout=1s 均通过。 -- [x] 未授权 HTTP 请求返回 401;有效 Bearer 请求返回 200。 -- [x] 审计日志已记录上述 Actions 操作,最新抽查包含 `file_read` 与 timeout=124。 -- [x] 临时凭据文件 `/tmp/m4-prod.env` 已删除;`/etc/vps-commander/{hub,agent}.env` 权限均为 `0600`。 -- [ ] Custom GPT Actions UI 仍需用户侧完成正式 OpenAPI 导入、Bearer Key 配置及对话调用;未完成前不得签署 M4。 - -### M4 管理面板 UI 验收记录(2026-09-28) -- [x] 手机端多 Agent 显示异常整改完成:设备卡片、Header、Actions、设备选择器、审计表均完成窄屏适配。 -- [x] 面板颜色体系改为 CSS Variables 双态主题,支持深色/浅色切换。 -- [x] 主题选择持久化到 localStorage,登录页与主面板统一。 -- [x] UI 静态资源与 Go embed 资源保持同步,并完成 Node JS 语法、go test ./...、release build 验证。 -- [x] 用户已于 2026-09-28 人工验收通过;已重新构建 Hub 二进制并重启 systemd 服务,正式线上 UI 已立即生效。 -- [ ] M4 总体验收仍保留 Custom GPT Actions 正式联调、Key 轮换及最终人工签收门禁。 - -### M4 终验签收记录(2026-09-28) -- [x] 安全清理:已彻底清除 `openapi.json` 中冗余残留的 `apiKey` 定义,统一收敛为标准 `bearerAuth`。 -- [x] 二次回归验证通过:全链路 API 鉴权、受控节点列表获取及本地命令执行均现场实测 100% PASS。 -- [x] 服务状态确认:`vps-commander-hub` (PID: systemd) 运行稳定,二进制构建已同步更新。 +## 8. 文档同步规则 +功能变化同时检查 README、ARCHITECTURE、DEV_SPEC、MCP_INTEGRATION、deploy/README、ACCEPTANCE_CRITERIA、PROGRESS_TRACKING、openapi.json。 +历史审核报告保留原貌,不回写当前结论。 diff --git a/docs/REVIEW_A_CODE_AUDIT_20261002.md b/docs/REVIEW_A_CODE_AUDIT_20261002.md index 8bebe97..f2d6367 100644 --- a/docs/REVIEW_A_CODE_AUDIT_20261002.md +++ b/docs/REVIEW_A_CODE_AUDIT_20261002.md @@ -1,5 +1,7 @@ # 审核专家 A:代码实现与架构安全穿透审计报告 +> 文档属性:历史独立代码审计快照。审计问题的当前处置状态以 B→A handoff、当前架构和进度文档为准。 + - **审核人**:审核专家 A(系统架构与安全审核组) - **日期**:2026-10-02 - **对象**:`/root/.openclaw/workspace/vps-commander` 工作区最新 Go 源码实现 diff --git a/docs/REVIEW_B_CODE_AUDIT_20261002.md b/docs/REVIEW_B_CODE_AUDIT_20261002.md index f7dbf55..b18743b 100644 --- a/docs/REVIEW_B_CODE_AUDIT_20261002.md +++ b/docs/REVIEW_B_CODE_AUDIT_20261002.md @@ -1,5 +1,7 @@ # 审核专家 B:代码实现审计报告 +> 文档属性:历史独立代码审计快照。不要将当时的 BLOCKER 列表直接视为当前未修复列表。 + - **审核人**:审核专家 B(外部 Agent) - **日期**:2026-10-02 - **对象**:`/root/.openclaw/workspace/vps-commander` 全量 Go 实现 diff --git a/docs/REVIEW_B_TO_A_HANDOFF_20261002.md b/docs/REVIEW_B_TO_A_HANDOFF_20261002.md index 8778e16..a5db6dc 100644 --- a/docs/REVIEW_B_TO_A_HANDOFF_20261002.md +++ b/docs/REVIEW_B_TO_A_HANDOFF_20261002.md @@ -1,5 +1,7 @@ # 审核专家 B 给 A 的意见同步(2026-10-02) +> 文档属性:历史审核交接快照。当前版本的后续任务以 VPS_COMMANDER_V2_1_SECURITY_HARDENING_SPEC.md 为准。 + > 请 GPT(审核专家 A)阅读。本文是 B 对生产部署的独立审计结论,供 A 更新评审意见时参考。 --- diff --git a/openapi.json b/openapi.json index 30768c1..106b717 100644 --- a/openapi.json +++ b/openapi.json @@ -2,7 +2,8 @@ "openapi": "3.1.0", "info": { "title": "VPS-Commander", - "version": "1.1.0" + "version": "2.0.0", + "description": "Current VPS-Commander HTTP contract. MCP tools are documented in docs/MCP_INTEGRATION.md." }, "servers": [ { @@ -163,124 +164,192 @@ "paths": { "/api/v1/devices": { "get": { - "operationId": "list_devices", - "security": [ - { - "bearerAuth": [] - } - ], "responses": { "200": { - "description": "Devices", - "content": { - "application/json": { - "schema": { - "type": "array", - "items": { - "$ref": "#/components/schemas/Device" - } - } - } - } + "description": "OK" } } } }, "/api/v1/exec": { "post": { - "operationId": "exec_command", - "security": [ - { - "bearerAuth": [] - } - ], - "requestBody": { - "required": true, - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ExecRequest" - } - } - } - }, "responses": { "200": { - "description": "Execution result", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ExecResponse" - } - } - } + "description": "OK" } } } }, "/api/v1/file/read": { "post": { - "operationId": "read_file", - "security": [ - { - "bearerAuth": [] - } - ], - "requestBody": { - "required": true, - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/FileReadRequest" - } - } - } - }, "responses": { "200": { - "description": "File content", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/FileReadResponse" - } - } - } + "description": "OK" + } + } + } + }, + "/api/v1/file/list": { + "post": { + "responses": { + "200": { + "description": "OK" + } + } + } + }, + "/api/v1/file/info": { + "post": { + "responses": { + "200": { + "description": "OK" + } + } + } + }, + "/api/v1/file/search": { + "post": { + "responses": { + "200": { + "description": "OK" + } + } + } + }, + "/api/v1/process/session": { + "post": { + "responses": { + "200": { + "description": "OK" } } } }, "/api/v1/file/write": { "post": { - "operationId": "write_file", - "security": [ - { - "bearerAuth": [] - } - ], - "requestBody": { - "required": true, - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/FileWriteRequest" - } - } - } - }, "responses": { "200": { - "description": "Write result", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/FileWriteResponse" - } - } - } + "description": "OK" + } + } + } + }, + "/api/v1/devices/file/edit_block": { + "post": { + "responses": { + "200": { + "description": "OK" + } + } + } + }, + "/api/v1/mcp/services": { + "get": { + "responses": { + "200": { + "description": "OK" + } + } + } + }, + "/api/v1/mcp/service": { + "delete": { + "responses": { + "200": { + "description": "OK" + } + } + } + }, + "/api/v1/mcp/list": { + "get": { + "responses": { + "200": { + "description": "OK" + } + } + } + }, + "/api/v1/mcp/call": { + "post": { + "responses": { + "200": { + "description": "OK" + } + } + } + }, + "/api/v1/mcp/test": { + "post": { + "responses": { + "200": { + "description": "OK" + } + } + } + }, + "/api/v1/security/settings": { + "get": { + "responses": { + "200": { + "description": "OK" + } + } + } + }, + "/api/v1/security/settings/update": { + "post": { + "responses": { + "200": { + "description": "OK" + } + } + } + }, + "/api/v1/security/device-credentials/provision": { + "post": { + "responses": { + "200": { + "description": "OK" + } + } + } + }, + "/api/v1/notifications/webhooks": { + "get": { + "responses": { + "200": { + "description": "OK" + } + } + } + }, + "/api/v1/notifications/webhook/update": { + "post": { + "responses": { + "200": { + "description": "OK" + } + } + } + }, + "/api/v1/notifications/webhook/delete": { + "delete": { + "responses": { + "200": { + "description": "OK" + } + } + } + }, + "/api/v1/notifications/webhook/test": { + "post": { + "responses": { + "200": { + "description": "OK" } } } } } -} +} \ No newline at end of file