密钥管理

密钥管理

OpenClaw 支持 additive SecretRef,因此支持的凭证不需要以纯文本形式存储在配置中。

纯文本仍然有效。SecretRef 是每个凭证选择加入的。

目标和运行时模型

密钥被解析到内存运行时快照中。

  • 解析在激活期间是急切的,而非在请求路径上懒惰的。
  • 当有效的活动 SecretRef 无法解析时,启动快速失败。
  • 重新加载使用原子交换:完全成功,或保留最后已知良好的快照。
  • 运行时请求仅从活动的内存快照读取。

这使密钥提供程序中断远离热请求路径。

活动表面过滤

SecretRef 仅在有效的活动表面上验证。

  • 启用的表面:未解析的引用阻止启动/重新加载。
  • 非活动表面:未解析的引用不阻止启动/重新加载。
  • 非活动引用发出非致命诊断,代码为 SECRETS_REF_IGNORED_INACTIVE_SURFACE

非活动表面示例:

  • 禁用的频道/账户条目。
  • 没有启用账户继承的顶级频道凭证。
  • 禁用的工具/功能表面。
  • 未被 tools.web.search.provider 选择的 Web 搜索提供程序特定密钥。 在自动模式(提供程序未设置)中,提供程序特定密钥对于提供程序自动检测也是活动的。
  • gateway.remote.token / gateway.remote.password SecretRef 是活动的(当 gateway.remote.enabled 不是 false 时),如果以下之一为真:
    • gateway.mode=remote
    • gateway.remote.url 已配置
    • gateway.tailscale.modeservefunnel 在没有这些远程表面的本地模式中:
    • 当令牌认证可以获胜且未配置 env/认证令牌时,gateway.remote.token 是活动的。
    • 仅当密码认证可以获胜且未配置 env/认证密码时,gateway.remote.password 才是活动的。

Gateway 认证表面诊断

当 SecretRef 配置在 gateway.auth.passwordgateway.remote.tokengateway.remote.password 上时,Gateway 启动/重新加载显式记录表面状态:

  • active:SecretRef 是有效认证表面的一部分,必须解析。
  • inactive:SecretRef 被此运行时忽略,因为另一个认证表面获胜,或 因为远程认证被禁用/未激活。

这些条目使用 SECRETS_GATEWAY_AUTH_SURFACE 记录,并包括活动表面策略使用的原因, 因此你可以看到为什么凭证被视为活动或非活动。

入职参考预检

当入职在交互模式下运行且你选择 SecretRef 存储时,OpenClaw 在保存之前运行预检验证:

  • Env 引用:验证 env 变量名称并确认在入职期间可见非空值。
  • 提供程序引用(fileexec):验证提供程序选择,解析 id,并检查解析的值类型。

如果验证失败,入职显示错误并让你重试。

SecretRef 契约

在任何地方使用一个对象形状:

{ source: "env" | "file" | "exec", provider: "...", id: "..." }

source: "env"

{ source: "env", provider: "default", id: "OPENAI_API_KEY" }

验证:

  • provider 必须匹配 ^[a-z][a-z0-9_-]{0,63}$
  • id 必须匹配 ^[A-Z][A-Z0-9_]{0,127}$

source: "file"

{ source: "file", provider: "filemain", id: "/providers/openai/apiKey" }

验证:

  • provider 必须匹配 ^[a-z][a-z0-9_-]{0,63}$
  • id 必须是绝对 JSON 指针(/...
  • 段中的 RFC6901 转义:~ => ~0/ => ~1

source: "exec"

{ source: "exec", provider: "vault", id: "providers/openai/apiKey" }

验证:

  • provider 必须匹配 ^[a-z][a-z0-9_-]{0,63}$
  • id 必须匹配 ^[A-Za-z0-9][A-Za-z0-9._:/-]{0,255}$

提供程序配置

secrets.providers 下定义提供程序:

{
  secrets: {
    providers: {
      default: { source: "env" },
      filemain: {
        source: "file",
        path: "~/.openclaw/secrets.json",
        mode: "json", // 或 "singleValue"
      },
      vault: {
        source: "exec",
        command: "/usr/local/bin/openclaw-vault-resolver",
        args: ["--profile", "prod"],
        passEnv: ["PATH", "VAULT_ADDR"],
        jsonOnly: true,
      },
    },
    defaults: {
      env: "default",
      file: "filemain",
      exec: "vault",
    },
    resolution: {
      maxProviderConcurrency: 4,
      maxRefsPerProvider: 512,
      maxBatchBytes: 262144,
    },
  },
}

Env 提供程序

  • 通过 allowlist 可选允许列表。
  • 缺少/空的 env 值失败解析。

File 提供程序

  • path 读取本地文件。
  • mode: "json" 期望 JSON 对象负载并将 id 解析为指针。
  • mode: "singleValue" 期望引用 id "value" 并返回文件内容。
  • 路径必须通过所有权/权限检查。
  • Windows 故障关闭说明:如果路径的 ACL 验证不可用,解析失败。仅对于受信任的路径,在该提供程序上设置 allowInsecurePath: true 以绕过路径安全检查。

Exec 提供程序

  • 运行配置的绝对二进制路径,无 shell。
  • 默认情况下,command 必须指向常规文件(不是符号链接)。
  • 设置 allowSymlinkCommand: true 以允许符号链接命令路径(例如 Homebrew shim)。OpenClaw 验证解析的目标路径。
  • allowSymlinkCommandtrustedDirs 配对用于包管理器路径(例如 ["/opt/homebrew"])。
  • 支持超时、无输出超时、输出字节限制、env 允许列表和受信任目录。
  • Windows 故障关闭说明:如果命令路径的 ACL 验证不可用,解析失败。仅对于受信任的路径,在该提供程序上设置 allowInsecurePath: true 以绕过路径安全检查。

请求负载(stdin):

{ "protocolVersion": 1, "provider": "vault", "ids": ["providers/openai/apiKey"] }

响应负载(stdout):

{ "protocolVersion": 1, "values": { "providers/openai/apiKey": "sk-..." } }

可选的每 id 错误:

{
  "protocolVersion": 1,
  "values": {},
  "errors": { "providers/openai/apiKey": { "message": "not found" } }
}

Exec 集成示例

1Password CLI

{
  secrets: {
    providers: {
      onepassword_openai: {
        source: "exec",
        command: "/opt/homebrew/bin/op",
        allowSymlinkCommand: true, // Homebrew 符号链接二进制文件需要
        trustedDirs: ["/opt/homebrew"],
        args: ["read", "op://Personal/OpenClaw QA API Key/password"],
        passEnv: ["HOME"],
        jsonOnly: false,
      },
    },
  },
  models: {
    providers: {
      openai: {
        baseUrl: "https://api.openai.com/v1",
        models: [{ id: "gpt-5", name: "gpt-5" }],
        apiKey: { source: "exec", provider: "onepassword_openai", id: "value" },
      },
    },
  },
}

HashiCorp Vault CLI

{
  secrets: {
    providers: {
      vault_openai: {
        source: "exec",
        command: "/opt/homebrew/bin/vault",
        allowSymlinkCommand: true, // Homebrew 符号链接二进制文件需要
        trustedDirs: ["/opt/homebrew"],
        args: ["kv", "get", "-field=OPENAI_API_KEY", "secret/openclaw"],
        passEnv: ["VAULT_ADDR", "VAULT_TOKEN"],
        jsonOnly: false,
      },
    },
  },
  models: {
    providers: {
      openai: {
        baseUrl: "https://api.openai.com/v1",
        models: [{ id: "gpt-5", name: "gpt-5" }],
        apiKey: { source: "exec", provider: "vault_openai", id: "value" },
      },
    },
  },
}

sops

{
  secrets: {
    providers: {
      sops_openai: {
        source: "exec",
        command: "/opt/homebrew/bin/sops",
        allowSymlinkCommand: true, // Homebrew 符号链接二进制文件需要
        trustedDirs: ["/opt/homebrew"],
        args: ["-d", "--extract", '["providers"]["openai"]["apiKey"]', "/path/to/secrets.enc.json"],
        passEnv: ["SOPS_AGE_KEY_FILE"],
        jsonOnly: false,
      },
    },
  },
  models: {
    providers: {
      openai: {
        baseUrl: "https://api.openai.com/v1",
        models: [{ id: "gpt-5", name: "gpt-5" }],
        apiKey: { source: "exec", provider: "sops_openai", id: "value" },
      },
    },
  },
}

支持的凭证表面

规范的支持和不支持的凭证列在:

运行时铸造或旋转凭证和 OAuth 刷新材料故意排除在只读 SecretRef 解析之外。

必需行为和优先级

  • 没有引用的字段:不变。
  • 有引用的字段:激活期间在活动表面上必需。
  • 如果纯文本和引用都存在,引用在支持的优先级路径上优先。

警告和审计信号:

  • SECRETS_REF_OVERRIDES_PLAINTEXT(运行时警告)
  • REF_SHADOWED(当 auth-profiles.json 凭证优先于 openclaw.json 引用时的审计发现)

Google Chat 兼容行为:

  • serviceAccountRef 优先于纯文本 serviceAccount
  • 当设置兄弟引用时,纯文本值被忽略。

激活触发器

密钥激活运行于:

  • 启动(预检加最终激活)
  • 配置重新加载热应用路径
  • 配置重新加载重启检查路径
  • 通过 secrets.reload 手动重新加载

激活契约:

  • 成功原子交换快照。
  • 启动失败中止 Gateway 启动。
  • 运行时重新加载失败保留最后已知良好的快照。

降级和恢复信号

当重新加载时激活在健康状态后失败,OpenClaw 进入降级的密钥状态。

一次性系统事件和日志代码:

  • SECRETS_RELOADER_DEGRADED
  • SECRETS_RELOADER_RECOVERED

行为:

  • 降级:运行时保留最后已知良好的快照。
  • 恢复:在下次成功激活后发出一次。
  • 已经降级时重复失败记录警告但不 spam 事件。
  • 启动快速失败不发出降级事件,因为运行时从未激活。

命令路径解析

选择加入的凭证敏感命令路径(例如 openclaw memory 远程内存路径和 openclaw qr --remote)可以通过 Gateway 快照 RPC 解析支持的 SecretRef。

  • 当 Gateway 运行时,这些命令路径从活动快照读取。
  • 如果配置的 SecretRef 是必需的且 Gateway 不可用,命令解析快速失败,具有可操作的诊断。
  • 后端密钥轮换后的快照刷新由 openclaw secrets reload 处理。
  • 这些命令路径使用的 Gateway RPC 方法:secrets.resolve

审计和配置工作流

默认操作员工作流:

openclaw secrets audit --check
openclaw secrets configure
openclaw secrets audit --check

secrets audit

发现包括:

  • 静止的纯文本值(openclaw.jsonauth-profiles.json.env
  • 未解析的引用
  • 优先级遮蔽(auth-profiles.json 优先于 openclaw.json 引用)
  • 传统残留(auth.json、OAuth 提醒)

secrets configure

交互式助手:

  • 首先配置 secrets.providersenv/file/exec,添加/编辑/删除)
  • 让你选择 openclaw.json 中的支持密钥承载字段加上一个代理范围的 auth-profiles.json
  • 可以直接在目标选择器中创建新的 auth-profiles.json 映射
  • 捕获 SecretRef 详情(sourceproviderid
  • 运行预检解析
  • 可以立即应用

有用的模式:

  • openclaw secrets configure --providers-only
  • openclaw secrets configure --skip-provider-setup
  • openclaw secrets configure --agent <id>

configure 应用默认值:

  • auth-profiles.json 清理目标提供程序的匹配静态凭证
  • auth.json 清理传统静态 api_key 条目
  • <config-dir>/.env 清理匹配的已知密钥行

secrets apply

应用保存的计划:

openclaw secrets apply --from /tmp/openclaw-secrets-plan.json
openclaw secrets apply --from /tmp/openclaw-secrets-plan.json --dry-run

对于严格目标/路径契约详情和确切的拒绝规则,参见:

单向安全策略

OpenClaw 故意不写入包含历史纯文本密钥值的回滚备份。

安全模型:

  • 预检必须在写入模式之前成功
  • 运行时激活在提交之前验证
  • 应用使用原子文件替换更新文件,并在失败时尽最大努力恢复

传统认证兼容性说明

对于静态凭证,运行时不再依赖纯文本传统认证存储。

  • 运行时凭证源是解析的内存快照。
  • 发现时清理传统静态 api_key 条目。
  • OAuth 相关的兼容行为保持分开。

Web UI 说明

一些 SecretInput 联合在原始编辑器模式下比在表单模式下更容易配置。

相关文档