跳转到主要内容
secret-manager 存储加密的应用程序密钥,并将其暴露给经过身份验证的用户和显式授权的插件。 它是一个 WASM 插件,因此它使用与其他 WASM 插件相同的插件契约和主机回调。

插件标识

插件名称用于插件配置、插件消息的目标以及各个密钥的访问策略。

配置

标准插件设置在 [Plugins.secret-manager] 下配置:
Params 通过插件的 RegisterRequest 传递给插件。插件使用以下参数名称: 插件会将更改保存到其自身的显式 Params 部分。它不会将这些值写入共享的 KV 存储。宿主程序会将参数补丁应用到当前配置,并刷新插件管理器的配置快照;插件也会更新其内存中的副本。 请将 secretmgr.identity 和所有 secretmgr.secret.* 值视为敏感信息。 identity 是一个私钥,而 secret 参数包含加密的秘密信息,这些信息不应在日志或常规配置诊断中暴露。

通过环境变量提供 identity

identity 参数支持内核的环境变量引用语法。为了避免将私钥写入配置文件,请将私钥的值存储在环境变量中,并在 Params 中引用它:
内核会在将 Params 传递给插件之前解析 env://SECRET_KEY。 引用时必须不带尾随的 ?,这样如果未设置 SECRET_KEY, 参数解析将失败,并且 secret-manager 无法启动。这比在加密数据已存在时静默生成新 identity 要好。 首次安装且未设置 secretmgr.identity 参数时,插件会生成一个 X25519 identity,并通过 PatchParams 将其持久化。 然后,您可以将生成的身份验证信息移动到受保护的环境变量中,设置 secretmgr.identity = env://SECRET_KEY,并使用 SECRET_KEY 启动应用程序。 请务必使用相同的 identity:使用新生成的密钥无法解密经过 identity 加密的密钥。 如果 identity 必须直接存储在配置中,则仍然可以使用 scrypt 加密和密码短语保护各个密钥值,这样配置中包含的将是密文而不是明文密钥值。 当前插件不接受使用密码短语包装的 secretmgr.identity 值;该参数必须解析为原始 identity。解密经过密码短语加密的密钥仍然需要 identity。

密钥元数据

每个 secretmgr.meta.<name> 值都具有以下格式:
encryption 可以是 identityscryptallowed_pluginsupdated_at 字段也保留在 HTTP API 返回的元数据中。 策略中的插件名称将与内核中经过身份验证的源名称进行比较。

密钥名称

密钥名称在截断后必须为 1-128 个字符。它们可以包含 ASCII 字符: 字母、数字、/_-.,但不能包含 ..。 空名称以及包含任何其他字符的名称将被拒绝。

加密

插件存储使用标准 Base64 编码的密文。 密码永远不会被持久化。忘记密码会导致 scrypt 密钥无法恢复。Scrypt 使用故意耗时且内存密集型的计算从密码派生加密密钥。 这使得每次离线密码猜测的成本更高,因此基于密码短语的加密方式比使用存储的 X25519 身份信息要慢。当额外的延迟可以接受时,请选择这种方式。 经过身份验证的 HTTP API 和插件间的 IPC 接口都可以在调用者提供密码短语时检索 scrypt 加密的密钥。 如果没有正确的 secretmgr.identity,则无法解密使用 identity 加密的密钥。 密文不足以恢复密钥。 解密过程中接受的最大明文大小为 1 MiB。

HTTP API

所有已注册的 HTTP 路由都需要经过身份验证的用户。该插件返回的 JSON 数据包含: Content-Type: application/json; charset=utf-8Cache-Control: no-store

列出密钥

响应:
此列表仅包含元数据,不包含任何密钥值。条目按密钥名称排序。

添加密钥

请求体:
passphrase 为可选。空值表示选择 identity 加密。 非空值表示选择 scrypt 加密。allowed_plugins 可以为空, 这意味着任何插件都无法通过进程间通信 (IPC) 获取密钥。 成功返回 HTTP 201 Created
如果 JSON 格式错误、名称无效或插件策略无效,则端点返回 400 Bad Request;如果密钥已存在,则返回 409 Conflict;如果加密或持久化失败,则返回 500 Internal Server Error

更新密钥

此请求使用与 /keys/add 相同的字段。name 用于标识现有的密钥,且无法更改。 要在更改元数据或访问策略的同时保留现有密文,请将 value 设置为单个字符*,并将 passphrase 留空。 如果提供带有此标记的密码短语,则请求将被拒绝。 成功返回 HTTP 200 OK,格式与 { "success": true, "name": "..." } 相同。 未知密钥返回 404 Not Found;格式错误的输入或无效的策略返回 400 Bad Request

揭示密钥

请求体:
当密钥使用 scrypt 加密时,必须填写密码短语;对于 identity 密钥,密码短语必须为空。成功返回明文:
如果输入格式错误或缺少/无效的 scrypt 密码,则端点返回 400 Bad Request 如果缺少密钥或其他解密失败,则返回 404 Not Found

删除密钥

请求体:
成功返回 HTTP 200 OK
删除操作会移除密文、策略和元数据参数。删除不存在的名称不会造成任何损害。无效名称会返回 400 Bad Request 错误。

插件消息 API

插件间消息检索使用内核的同步插件消息传输。目标插件名称为 secret-manager,支持的主题为:
有效负载为 UTF-8 JSON:
发送插件必须列在所请求密钥的 allowed_plugins 列表中。对于 identity 密钥,密码短语可以为空;对于 scrypt 密钥,密码短语是必需的。 内核会将消息的 source 设置为发送者的注册名称;调用者无法伪造此字段。 成功后,回复会将明文内容放入 message 中:
失败时,回复会在 error 中放置描述,并且不会返回密钥值:
消息接口会拒绝不支持的主题、无效的 JSON、无效的密钥名称、未经授权的来源、缺失的密钥、不支持的加密元数据、 缺失的 scrypt 密码短语以及无效的密码短语。 有关通用消息信封和主机认证来源的行为,请参阅 插件消息

KV 和其他插件接口

secret-manager 不使用共享的 KV 存储来存储密钥数据。 使用者不得在 KV 命名空间中查找密钥;请使用 HTTP。 API 或插件上述消息主题。 该插件未声明 Socket.IO 命名空间或事件。其与宿主的交互仅限于:
  • 在注册期间接收 Params
  • 使用宿主的 PatchParams 回调来持久化身份和密钥的更改;
  • 处理已认证的 HTTP 请求;
  • 接收已认证的插件消息。
其静态页面加载共享的前端资源和标准主题的 Web SDK,但这些浏览器资源是 UI 依赖项,而非密钥存储接口。

安全注意事项

  • 仅将 HTTP 端点用于已认证的管理访问。
  • 优先使用插件消息进行服务间访问,并将每个密钥仅授予需要它的插件名称。
  • 将插件消息回复视为明文密钥材料。
  • 为每次 scrypt 检索提供密码短语,并且绝不将其记录或持久化到调用插件中。
  • 不要在日志中附加请求正文、密码短语、解密值、身份或密文参数。