跳转到内容

密钥、出站身份与安全边界

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。

挂载上游时,节点记录保存 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 并不会让它自动变安全。

Terminal window
tb secret set --name docs-token < docs.token
tb secret ls

省略 --value 时,CLI 从 stdin 读取,避免 token 出现在普通 argv 和 shell history。tb secret ls 只返回名称与更新时间,不会回读值。

挂载 MCP:

Terminal window
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 为准。

S3 一类 Provider 往往需要多个字段。可以把 JSON 文件从 stdin 写入一个 Secret 槽,或使用当前 CLI 支持的重复 --field key=value。例如:

Terminal window
tb secret set --name docs-s3 < s3-credential.json

s3-credential.json 的字段形状由目标 integration export 的运行时契约决定。先查询 system/catalog 的对应 export,不要从另一 provider 或旧版文档猜字段。

文件本身也包含明文,应限制权限并在安全写入后按组织策略处理。

SecretStore 是 write-only 管理面。正确验证方式是:

  1. tb secret ls 确认引用名存在;
  2. 挂载节点时使用 --auth-ref <name>
  3. 读取挂载路径 tb help <path>
  4. 完成一次不会产生破坏性副作用的真实调用;
  5. 检查错误、日志、Dashboard 和调用历史都没有明文凭证。

无法回读 Secret 值是设计边界,不是缺少一个 secret get 命令。凭证轮换应再次 secret set 覆盖槽位,再用节点调用验证。

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 为准。

请求链应当是:

Agent scoped SK
│ 只用于本地认证与授权
tool-bridge
│ 从节点 authRef/skRef 解析目标凭证
MCP / HTTP / Plugin / remote gateway

这一边界保证:

  • 上游不会看到不属于它的本地 SK;
  • 不同本地 Agent 可以共享同一个受控上游身份,而不互相获得凭证明文;
  • 远端 federation 使用远端专用 SK,不会意外获得本地调用者权限。
  • 上游默认要求 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 是两个独立动作。这样可以避免卸载一个节点时误删仍被其他节点引用的凭证。

安全轮换顺序:

  1. 在上游创建新凭证;
  2. tb secret set --name <existing-ref> 更新槽位,或创建新 ref;
  3. 如更换 ref,更新挂载节点;
  4. 用受限身份完成真实调用;
  5. 在上游吊销旧凭证;
  6. 只有确认没有其他引用时才运行 tb secret rm <name>

SecretStore 当前不会把依赖关系当作可回读的密钥图。删除前由管理员确认引用范围。

挂载成功,但第一次调用返回 unavailable

Section titled “挂载成功,但第一次调用返回 unavailable”

检查 SecretStore 加密密钥是否在宿主启动时提供、引用名是否拼写一致,以及 provider 是否要求多字段凭证。SDK 未提供自定义 secrets 且没有 encryption key 时,默认 Secret 能力会禁用并 fail closed。

如果值出现在 providerConfig、节点描述、URL、toast 或日志中,说明配置边界被破坏。先轮换泄漏凭证,再把值迁入 SecretStore;仅删除日志并不能撤销泄漏。

OAuth 在预览域名正常、正式域名失败

Section titled “OAuth 在预览域名正常、正式域名失败”

核对 TB_CANONICAL_ORIGIN、上游 redirect URI 和实际唯一访问 origin。不要同时让多个 origin 竞争同一回调身份。

这是不应发生的安全问题。正常出站只解析 remote 节点的 skRef。停止使用该路径,保存脱敏证据并检查部署版本;不要把本地 SK 手工放进 remote header 配置。