release(secrets-mcp): 0.6.0 - local gateway onboarding and target_exec
All checks were successful
Secrets MCP — Build & Release / 检查 / 构建 / 发版 (push) Successful in 4m1s
Secrets MCP — Build & Release / 部署 secrets-mcp (push) Has been skipped

This commit is contained in:
voson
2026-04-12 15:48:22 +08:00
parent 34093b0e23
commit cb5865b958
19 changed files with 3515 additions and 453 deletions

View File

@@ -11,7 +11,7 @@ cargo build --release -p secrets-mcp
```bash
cargo build --release -p secrets-mcp-local
# 产物: target/release/secrets-mcp-local本机代理远程 /mcp,见下节)
# 产物: target/release/secrets-mcp-local本机 MCP gateway,见下节)
```
发版产物见 Gitea Releasetag`secrets-mcp-<version>`Linux musl 预编译);其它平台本地 `cargo build`
@@ -57,22 +57,54 @@ SECRETS_ENV=production
### 本地 MCP gateway`secrets-mcp-local`
用于在本机启动一个 **仅监听 localhost** 的 MCP 入口:先在浏览器打开远程 **Dashboard** 登录并复制 API Key再向本机 `POST /local/unlock` 提交一次 **64 位 hex** 加密密钥;之后 Cursor 等客户端可将 MCP URL 配为 `http://127.0.0.1:9316/mcp`**无需**在配置里长期保存 `X-Encryption-Key`。解锁状态在进程内按 TTL 缓存,过期需重新解锁。
`secrets-mcp-local` 现在是**独立的本地 MCP 入口**,不再依赖把远程 `/mcp` 原样透传到本机。它始终能完成 MCP `initialize` / `tools/list`,但会按状态暴露不同工具面:
- `bootstrap`:尚未绑定或尚未解锁,只暴露 `local_status``local_bind_start``local_bind_exchange``local_unlock_status``local_onboarding_info`
- `pendingUnlock`:远端授权已完成,但本地仍未完成 passphrase 解锁;仍只暴露 bootstrap 工具
- `ready`:绑定 + 解锁均完成,额外暴露 `secrets_find``secrets_search``secrets_history``secrets_overview``secrets_delete(dry_run)``target_exec`
上线流程:
1. 启动 `secrets-mcp-local`
2. 在浏览器打开本地首页 `http://127.0.0.1:9316/`
3. 点击“开始绑定”,打开页面给出的 `approve_url`
4. 在远端网页确认授权后,返回本地首页等待自动进入解锁阶段
5. 在本地页面或 `/unlock` 完成浏览器内 PBKDF2 派生、`key_check` 校验与本地解锁
6. 之后将 Cursor 等客户端的 MCP URL 配为 `http://127.0.0.1:9316/mcp`
这套流程下Cursor 会先稳定连上 local MCP未就绪时 AI 只能看到 bootstrap 工具,因此会明确告诉用户去打开本地 onboarding 页面或 `approve_url`,不会再因为 `401` 被误判成“连接失败”。
运行时说明:
- local gateway 的业务数据面已切到远端 JSON HTTP API`find/search/history/overview/delete-preview/decrypt` 直接走 `/api/local-mcp/...`
- `target_exec` 首次执行某个目标时,建议同时传入 `secrets_find/search` 返回的目标摘要local gateway 会按 `entry_id` 缓存解析后的执行上下文,后续同一目标可复用而不必重新读取密钥
- 远端 `key_version` 变化时,本地会自动从 `ready` 回退到 `pendingUnlock`
- 远端 API key 已失效或绑定用户不存在时,本地会自动清除 bound 状态并重新回到 `bootstrap`
`target_exec` 运行时会注入一组标准环境变量,例如:
- `TARGET_ENTRY_ID``TARGET_NAME``TARGET_FOLDER``TARGET_TYPE`
- `TARGET_HOST``TARGET_PORT``TARGET_USER``TARGET_BASE_URL`
- `TARGET_API_KEY``TARGET_TOKEN``TARGET_SSH_KEY`
- `TARGET_META_<KEY>``TARGET_SECRET_<KEY>`(对 metadata / secret 字段名做大写与下划线归一化)
典型用法:
-`secrets_find` 找到目标服务器,再用 `target_exec` 执行 `ssh -i <(printf '%s' \"$TARGET_SSH_KEY\") \"$TARGET_USER@$TARGET_HOST\" 'df -h'`
-`secrets_search` 找到 API 服务条目,再用 `target_exec` 执行 `curl -H \"Authorization: Bearer $TARGET_API_KEY\" \"$TARGET_BASE_URL/health\"`
本地状态行为:
- `POST /local/lock`:仅清除本地解锁缓存,保留绑定
- `POST /local/unbind`:同时清除本地绑定与解锁状态
- `GET /local/status`:返回 `bootstrap` / `pendingUnlock` / `ready`、待确认绑定会话、缓存目标数、`onboarding_url` / `unlock_url`
| 变量 | 说明 |
|------|------|
| `SECRETS_REMOTE_MCP_URL` | **必填**。远程 MCP 完整 URL,例如 `https://secrets.example.com/mcp`。 |
| `SECRETS_REMOTE_BASE_URL` | **必填**。远程 Web 基址,例如 `https://secrets.example.com`。 |
| `SECRETS_MCP_LOCAL_BIND` | 可选。监听地址,默认 `127.0.0.1:9316`。 |
| `SECRETS_LOCAL_API_KEY` | 可选。若设置,则 `/local/unlock``encryption_key`。 |
| `SECRETS_LOCAL_UNLOCK_TTL_SECS` | 可选。默认解锁缓存秒数(单次 `unlock` 可用 `ttl_secs` 覆盖)。 |
| `SECRETS_LOCAL_ALLOW_PLAINTEXT_TOOLS` | 可选。设为 `1`/`true` 时允许代理 `secrets_get` / `secrets_export` / `secrets_env_map`;默认 **不允许**(网关直接返回错误,避免明文进入 agent 上下文)。 |
| `SECRETS_REMOTE_DASHBOARD_URL` | 可选。首页引导链接;未设置时由 `SECRETS_REMOTE_MCP_URL` 推导为同 origin 的 `/dashboard`。 |
| `SECRETS_LOCAL_UNLOCK_TTL_SECS` | 可选。默认解锁缓存秒数(`/local/unlock/complete` 可传 `ttl_secs` 覆盖)。 |
| `SECRETS_LOCAL_EXEC_CONTEXT_TTL_SECS` | 可选。`entry_id` 复用已解析执行上下文的缓存秒数;到期、`lock``unbind` 或远端 `key_version` 变化后会失效。 |
```bash
SECRETS_REMOTE_MCP_URL=https://secrets.example.com/mcp cargo run -p secrets-mcp-local
# 浏览器打开首页提示的 Dashboard解锁示例
# curl -X POST http://127.0.0.1:9316/local/unlock -H 'Content-Type: application/json' \
# -d '{"encryption_key":"<64 hex>","api_key":"<Bearer token>"}'
SECRETS_REMOTE_BASE_URL=https://secrets.example.com cargo run -p secrets-mcp-local
# 启动后直接打开 http://127.0.0.1:9316/
# 页面会引导你完成 bind -> approve -> unlock -> ready 全流程
```
## PostgreSQL TLS 加固
@@ -205,7 +237,7 @@ flowchart LR
## 数据模型
主表 **`entries`**`folder``type``name``notes``tags``metadata`,多租户时带 `user_id`+ 子表 **`secrets`**(每行一个加密字段:`name``type``encrypted`,通过 `entry_secrets` 中间表与 entry 建立 N:N 关联)。**唯一性**`UNIQUE(user_id, folder, name)``user_id` 为空时为遗留行唯一 `(folder, name)`)。另有 `entries_history``secrets_history``audit_log`,以及 **`users`**(含 `key_salt``key_check``key_params``api_key`)、**`oauth_accounts`**。首次连库自动迁移建表(`secrets-core``migrate`);已有库在进程启动时亦由同一 `migrate()` 增量补齐表、索引与 N:N 结构。若需从更早版本对照一次性 SQL可在 git 历史中检索已移除的 `scripts/migrate-v0.3.0.sql`。**Web 登录会话**tower-sessions使用同一 `SECRETS_DATABASE_URL`,进程启动时对会话存储执行迁移(见 `secrets-mcp``PostgresStore::migrate`),无需额外环境变量。
主表 **`entries`**`folder``type``name``notes``tags``metadata`,多租户时带 `user_id`+ 子表 **`secrets`**(每行一个加密字段:`name``type``encrypted`,通过 `entry_secrets` 中间表与 entry 建立 N:N 关联)。**唯一性**`UNIQUE(user_id, folder, name)``user_id` 为空时为遗留行唯一 `(folder, name)`)。另有 `entries_history``secrets_history``audit_log`,以及 **`users`**(含 `key_salt``key_check``key_params``api_key`)、**`oauth_accounts`**、**`local_mcp_bind_sessions`**(短时本地绑定确认会话)。首次连库自动迁移建表(`secrets-core``migrate`);已有库在进程启动时亦由同一 `migrate()` 增量补齐表、索引与 N:N 结构。若需从更早版本对照一次性 SQL可在 git 历史中检索已移除的 `scripts/migrate-v0.3.0.sql`。**Web 登录会话**tower-sessions使用同一 `SECRETS_DATABASE_URL`,进程启动时对会话存储执行迁移(见 `secrets-mcp``PostgresStore::migrate`),无需额外环境变量。
| 位置 | 字段 | 说明 |
|------|------|------|
@@ -253,7 +285,7 @@ crates/secrets-core/ # db / crypto / models / audit / service
taxonomy.rs # SECRET_TYPE_OPTIONSsecret 字段类型下拉选项)
service/ # 业务逻辑add, search, update, delete, export, env_map 等)
crates/secrets-mcp/ # MCP HTTP、Web、OAuth、API KeyCHANGELOG.md 嵌入 /changelog
crates/secrets-mcp-local/ # 可选:本机 MCP gateway代理远程 /mcp
crates/secrets-mcp-local/ # 可选:本机 MCP gatewaybootstrap + ready 双工具面
scripts/
release-check.sh # 发版前 fmt / clippy / test
setup-gitea-actions.sh