# spark-mcp-go 架构说明 ## 包依赖图 ``` main ├─ config ├─ logging ├─ storage (SQLite) ├─ admin │ └─ storage / cluster / audit ├─ mcp │ ├─ tools │ │ ├─ rm │ │ ├─ httpclient │ │ ├─ analyzer │ │ └─ storage / cluster │ └─ server (mark3labs/mcp-go) └─ middleware ``` - `admin` 只依赖 `storage`、`cluster`、`audit`、`middleware`。 - `tools` 依赖 `rm`(ResourceManager 客户端)、`httpclient`(通用 HTTP 原语)、`analyzer`(日志分析)。 - `mcp` 聚合所有 Tools,注册到 `mark3labs/mcp-go` 的 Streamable HTTP server。 - `main` 负责加载配置、打开数据库、挂载路由、启动 HTTP 服务。 ## 数据流 1. 管理员调用 `/admin/clusters` POST,写入 cluster JSON。 2. `storage` 把 cluster 持久化到 SQLite(后续会对敏感字段加密)。 3. LLM Agent 调用 `/mcp` Tool(如 `list_clusters`)。 4. Tool 从 storage 读取 cluster,携带 auth 信息,通过 `httpclient` 或本地 `spark-submit` 调用 YARN/Spark。 5. 结果返回给 LLM;每次 Tool 调用同时写入独立审计日志。 ## 11 Tools 分类 | 分类 | Tools | |---|---| | discovery | `list_clusters` | | exec | `spark_submit` | | RM | `list_applications`, `get_application_status`, `get_application_logs`, `kill_application`, `fetch_cluster_env` | | SHS | `fetch_spark_metrics` | | analyzer | `analyze_spark_log` | | 原语 | `fetch_url`, `upload_file` | ## 关键设计决策 - **slice-form `spark_submit`**:参数以字符串数组传入,避免 shell 拼接和注入。 - **cluster `url_allowlist`**:所有外发 HTTP(`fetch_url`、RM、SHS)必须匹配 allowlist,防止 SSRF。 - **日志降级链**:`get_application_logs` 依次尝试 `amContainerLogs`、aggregated-logs、通用 logs 端点。 - **多 token admin**:`ADMIN_TOKENS` 支持逗号分隔多管理员 token,便于轮换。 - **per-tool 独立审计日志**:每个 Tool 每次调用写入 `${LOG_DIR}/tools/.log`,文件权限 `0600`。 - **`auth_password` 不可通过 JSON 创建**:字段带 `json:"-"` tag,避免接口泄露密码;生产通过专用端点或数据库初始化写入。 ## 安全模型(三道防线) 1. **Token 鉴权**:`ADMIN_TOKENS` 保护管理面,`AGENT_TOKEN` 保护 MCP 面。 2. **SSRF 防护**:`fetch_url` 与所有集群请求都走 cluster allowlist,且内置 DNS rebinding 检查。 3. **路径/参数白名单**:`spark_submit` 仅允许 jar、class、--conf 等安全参数;禁止 shell 元字符与重定向。 ## 运行与部署 详见 [docs/runbook.md](docs/runbook.md)。