密钥、出站身份与安全边界
tool-bridge 同时处理两类身份:调用者使用 SK 访问网关,网关使用上游凭证访问 MCP、HTTP、Plugin 或远端网关。两者必须隔离,不能把本地调用者 SK 直接转发给上游。
本页适合挂载需要 token/OAuth 的 Provider、配置远端联邦或设计生产 Secret 管理的操作者。开始前应已理解权限、SK 与可见性。
| 类型 | 用途 | 应存放在哪里 |
|---|---|---|
TB_BOOTSTRAP_ADMIN_SK |
首次引导最高权限身份 | 部署平台 Secret;明文另存密码管理器 |
TB_SECRET_ENCRYPTION_KEY |
加密 SecretStore 与相关签名材料 | 部署平台 Secret;不得进入普通 vars |
| 调用者 SK | Agent、用户、设备访问当前网关 | CLI/浏览器 profile 或受保护的 CI Secret |
| 上游凭证 | MCP/HTTP/Plugin token、OAuth client、远端 SK | 网关 SecretStore,由节点 authRef / skRef 引用 |
部署 trust roots 与运行时上游凭证不是一回事。Admin SK 不是 SecretStore 主密钥;SecretStore 主密钥也不能用于调用 API。
节点只保存引用
Section titled “节点只保存引用”挂载上游时,节点记录保存 authRef:
tools/docs node providerConfig: { region: "...", baseUrl: "..." } # 可回显的非敏感配置 authRef: "docs-token" # SecretStore 引用名
SecretStore docs-token: <真实 token> # 写入但不可回读远端 federation 使用 skRef 指向远端专用 SK,语义相同。
providerConfig 会被有节点读取权限的管理身份看到,因此不能存 access key、client secret、Authorization header 或含 token 的 URL。把字段叫作 password 并不会让它自动变安全。
1. 通过 stdin 写入单值凭证
Section titled “1. 通过 stdin 写入单值凭证”tb secret set --name docs-token < docs.tokentb secret ls省略 --value 时,CLI 从 stdin 读取,避免 token 出现在普通 argv 和 shell history。tb secret ls 只返回名称与更新时间,不会回读值。
挂载 MCP:
tb tool mount tools/docs \ --kind mcp \ --url https://mcp.example.com/mcp \ --auth-ref docs-token具体 header 名、scheme 和 Provider 参数以当前版本 tb tool mount --help 以及目标节点 ~help 为准。
2. 写入多字段凭证
Section titled “2. 写入多字段凭证”S3 一类 Provider 往往需要多个字段。可以把 JSON 文件从 stdin 写入一个 Secret 槽,或使用当前 CLI 支持的重复 --field key=value。例如:
tb secret set --name docs-s3 < s3-credential.jsons3-credential.json 的字段形状由目标 integration export 的运行时契约决定。先查询 system/catalog 的对应 export,不要从另一 provider 或旧版文档猜字段。
文件本身也包含明文,应限制权限并在安全写入后按组织策略处理。
3. 验证引用而不是回读 secret
Section titled “3. 验证引用而不是回读 secret”SecretStore 是 write-only 管理面。正确验证方式是:
tb secret ls确认引用名存在;- 挂载节点时使用
--auth-ref <name>; - 读取挂载路径
tb help <path>; - 完成一次不会产生破坏性副作用的真实调用;
- 检查错误、日志、Dashboard 和调用历史都没有明文凭证。
无法回读 Secret 值是设计边界,不是缺少一个 secret get 命令。凭证轮换应再次 secret set 覆盖槽位,再用节点调用验证。
OAuth 凭证需要分槽管理
Section titled “OAuth 凭证需要分槽管理”OAuth client credential、access token 与 refresh token 具有不同生命周期,不能互相 fallback。挂载声明 OAuth 的 MCP 或 integration 后,应使用该 Provider 的授权流程完成交互;数据面调用只能静默刷新,不能在 Agent 调用过程中偷偷启动浏览器授权。
自定义域名下,canonical origin 与 OAuth redirect 必须一致。切换 Workers 预览 URL、正式域名或反向代理 origin 后,要重新核对回调配置。
精确 OAuth 命令和 provider scopes 以当前 tb <command> --help、catalog export 与运行时 ~help 为准。
调用者 SK 不透传给上游
Section titled “调用者 SK 不透传给上游”请求链应当是:
Agent scoped SK │ 只用于本地认证与授权 ▼tool-bridge │ 从节点 authRef/skRef 解析目标凭证 ▼MCP / HTTP / Plugin / remote gateway这一边界保证:
- 上游不会看到不属于它的本地 SK;
- 不同本地 Agent 可以共享同一个受控上游身份,而不互相获得凭证明文;
- 远端 federation 使用远端专用 SK,不会意外获得本地调用者权限。
出站与重定向边界
Section titled “出站与重定向边界”- 上游默认要求 HTTPS;
TB_ALLOW_INSECURE_HTTP=true只适用于本地 stub; - remote、HTTP、MCP 与 Plugin 都要经过 URL/host/超时边界;
- Authorization、自定义敏感 header 或 secret body 遇跨源 redirect 时不得转发;
- Remote federation 的 host allowlist 为空时拒绝所有远端;
- 内置 Plugin 与网关同进程同权,宿主必须收窄 env 并通过受控 fetch 出站。
这些限制不应靠 provider 作者自觉绕开。出现 redirect 或 host 拒绝时,应修正目标和 allowlist,而不是把密钥拼进 query string。
卸载节点与删除 Secret 是两个独立动作。这样可以避免卸载一个节点时误删仍被其他节点引用的凭证。
安全轮换顺序:
- 在上游创建新凭证;
- 用
tb secret set --name <existing-ref>更新槽位,或创建新 ref; - 如更换 ref,更新挂载节点;
- 用受限身份完成真实调用;
- 在上游吊销旧凭证;
- 只有确认没有其他引用时才运行
tb secret rm <name>。
SecretStore 当前不会把依赖关系当作可回读的密钥图。删除前由管理员确认引用范围。
挂载成功,但第一次调用返回 unavailable
Section titled “挂载成功,但第一次调用返回 unavailable”检查 SecretStore 加密密钥是否在宿主启动时提供、引用名是否拼写一致,以及 provider 是否要求多字段凭证。SDK 未提供自定义 secrets 且没有 encryption key 时,默认 Secret 能力会禁用并 fail closed。
管理面能看到 token
Section titled “管理面能看到 token”如果值出现在 providerConfig、节点描述、URL、toast 或日志中,说明配置边界被破坏。先轮换泄漏凭证,再把值迁入 SecretStore;仅删除日志并不能撤销泄漏。
OAuth 在预览域名正常、正式域名失败
Section titled “OAuth 在预览域名正常、正式域名失败”核对 TB_CANONICAL_ORIGIN、上游 redirect URI 和实际唯一访问 origin。不要同时让多个 origin 竞争同一回调身份。
Federation 远端收到本地 SK
Section titled “Federation 远端收到本地 SK”这是不应发生的安全问题。正常出站只解析 remote 节点的 skRef。停止使用该路径,保存脱敏证据并检查部署版本;不要把本地 SK 手工放进 remote header 配置。
- 按使用内置集成、MCP或Context安全接入上游;
- 阅读联邦另一棵 tool-bridge配置 host allowlist 与远端专用 SK;
- 在生产上线检查清单中验证密钥、日志与轮换路径。