ARTICLE · INTELLIGENCE

战地情报 · 详情页

来自尧图项目组的一线实战观察与深度解析

External Secrets Operator 集成 Passbolt:SecretStore 配置、ExternalSecret 同步与自定义字段全指南

External Secrets Operator 集成 Passbolt:SecretStore 配置、ExternalSecret 同步与自定义字段全指南 External Secrets Operator 集成 PassboltSecretStore 配置、ExternalSecret 同步与自定义字段全指南【免费下载链接】external-secretsExternal Secrets Operator reads information from a third-party service like AWS Secrets Manager and automatically injects the values as Kubernetes Secrets.项目地址: https://gitcode.com/GitHub_Trending/ex/external-secrets本指南围绕 External Secrets OperatorESO官方提供的 Passbolt Provider讲解如何将 Passbolt 密码库中的凭据通过SecretStore与ExternalSecret两个 CRD 同步为 Kubernetes Secret。读完本文你将掌握 Passbolt SecretStore 的认证与自定义 CA 配置、按 ID 拉取与按名称查找dataFrom.find两种取值方式、property精确选取与custom_fields.name自定义字段语法并能结合源码理解每条配置背后的实际行为。一、Passbolt Provider 概述与集成原理Passbolt 是一个开源的团队密码管理器数据采用端到端加密存储。ESO 通过官方 go-passbolt 的包注释中写明该 Provider 通过 Passbolt REST API 获取存储在其中的秘密secrets。从源码看整个集成有以下关键行为providers/v1/passbolt/passbolt.go只读能力Capabilities()返回SecretStoreReadOnly第 70–72 行PushSecret、DeleteSecret、GetSecretMap、SecretExists均返回 not implemented因此本 Provider 不支持PushSecret等写入场景只用于单向同步立即登录与会话复用NewClient在创建客户端后立即调用client.Login(ctx)第 111–113 行后续每次取值前通过assureLoggedIn检查会话失效时自动重新登录第 335–340 行V5 元数据预取缓存登录后调用PreFetchCaches预取会话密钥与元数据密钥以加速 V5 资源的解密Close时还会调用SavePendingSessionKeys保存会话密钥第 115–119、216–221 行注册方式Provider 通过NewProvider()、ProviderSpec()与MaintenanceStatus()注册第 387–401 行当前维护状态为MaintenanceStatusMaintained已维护。二、创建 Passbolt SecretStore认证与 Host 配置ESO 通过KindSecretStore定义与 Passbolt 的连接。官方要求passboltProvider 出现在spec.provider下并且必须配置auth与host。Passbolt API 的认证需要两样东西用户密码password与私钥private key二者都存放在一个 Kubernetes Secret 中通过passwordSecretRef与privateKeySecretRef引用。完整配置见 docs/snippets/passbolt-secret-store.yamlapiVersion: external-secrets.io/v1 kind: SecretStore metadata: name: passbolt spec: provider: passbolt: host: https://passbolt.passbolt.svc.cluster.local auth: passwordSecretRef: key: password name: passbolt-credentials privateKeySecretRef: key: privateKey name: passbolt-credentials字段说明spec.provider.passbolt.hostPassbolt 服务地址必须是 HTTPS 协议。ValidateStore会解析该 URL 并强制校验host.Scheme https否则报错host Url has to be https schemeproviders/v1/passbolt/passbolt.gospec.provider.passbolt.auth.passwordSecretRef引用存放 Passbolt 用户密码的 Secret需指定name与keyspec.provider.passbolt.auth.privateKeySecretRef引用存放用户私钥的 Secret即 Passbolt 中该用户用于解密数据的私钥。字段类型定义位于 apis/externalsecrets/v1/secretsstore_passbolt_types.goPassboltAuth由PasswordSecretRef与PrivateKeySecretRef两个SecretKeySelector组成PassboltProvider由Auth、Host、可选CABundle与可选CAProvider组成。2.1 SecretStore 校验规则ValidateStoreValidateStoreproviders/v1/passbolt/passbolt.go按顺序校验以下内容任一不满足都会拒绝该 SecretStore校验项错误信息spec.provider.passbolt存在missing: spec.provider.passboltauth存在missing: spec.provider.passbolt.authauth.passwordSecretRef的 name/key 非空missing: spec.provider.passbolt.auth.passwordSecretRefauth.privateKeySecretRef的 name/key 非空missing: spec.provider.passbolt.auth.privateKeySecretRefhost非空missing: spec.provider.passbolt.hosthost可被解析且 scheme 为httpshost Url has to be https scheme2.2 凭据解析逻辑NewClient中通过resolvers.SecretKeyRef在 SecretStore 所在命名空间内解析password与privateKey两个引用providers/v1/passbolt/passbolt.go随后构造 go-passbolt 客户端。实际认证时client.Login(ctx)会先向 Passbolt 发起登录请求之后所有 API 调用均依赖该会话。三、自定义 CA 证书配置如果 Passbolt 实例使用了私有 CA 或自定义 CA 签发的证书需要让 ESO 信任该 CA。两种方式任选其一见 docs/snippets/passbolt-secret-store-ca.yamlapiVersion: external-secrets.io/v1 kind: SecretStore metadata: name: passbolt-with-custom-ca spec: provider: passbolt: host: https://passbolt.example.com # Reference a ConfigMap or Secret containing the CA bundle that signed # the Passbolt server certificate. caProvider: type: ConfigMap name: passbolt-ca-bundle key: ca.crt auth: passwordSecretRef: key: password name: passbolt-credentials privateKeySecretRef: key: privateKey name: passbolt-credentialscaBundle内联 PEM直接把 PEM 编码的 CA 证书内容写在spec.provider.passbolt.caBundle中caProvider引用外部来源通过typeConfigMap或Secret、name、key引用一个 ConfigMap 或 Secret 中存放的 CA bundle。如果两者都未设置ESO 使用系统根证书校验 TLS 连接。底层实现在buildHTTPClientproviders/v1/passbolt/passbolt.go当caBundle与caProvider均为空时返回nil让 go-passbolt SDK 使用默认 HTTP 客户端与系统根 CA否则通过esutils.FetchCACertFromSource拉取 CA 内容追加到x509.NewCertPool()若 PEM 解析失败返回failed to parse CA certificate for Passbolt provider克隆默认http.Transport并仅覆盖TLSClientConfig.RootCAs同时强制MinVersion TLS 1.2保留原有的代理、拨号器、HTTP/2 与空闲连接设置。四、创建 ExternalSecret 同步 Passbolt 秘密要把 Passbolt 秘密同步为 Kubernetes Secret需要创建KindExternalSecret并引用上一步的 SecretStore。默认情况下同步出的秘密包含name、username、uri、password、description五个标准属性如需只取其中某一个属性可以在remoteRef.property中指定。示例见 docs/snippets/passbolt-external-secret-example.yamlapiVersion: external-secrets.io/v1 kind: ExternalSecret metadata: name: passbolt-example-simple spec: refreshInterval: 1h0m0s secretStoreRef: name: passbolt kind: SecretStore target: name: passbolt-example data: - secretKey: full_secret remoteRef: key: e22487a8-feb8-4591-95aa-14b193930cb4 # Replace with ID of exising Passbolt secret - secretKey: password_only remoteRef: key: e22487a8-feb8-4591-95aa-14b193930cb4 # Replace with ID of exising Passbolt secret property: password # You can limit the secret to only display one property要点说明remoteRef.key是Passbolt 资源的 UUID而非名称需替换为实际存在的 Passbolt 秘密 IDremoteRef.property可选取值范围为name、username、uri、password、description或custom_fields.name详见第六节。源码GetProp中若传入其他值会返回property must be one of name, username, uri, password, description, or custom_fields.nameproviders/v1/passbolt/passbolt.go不指定property时GetSecret走esutils.JSONMarshal(secret)分支返回整个秘密的 JSON 对象providers/v1/passbolt/passbolt.go。4.1 同步结果示例上述 ExternalSecret 将生成如下形态的 Kubernetes Secret见 docs/snippets/passbolt-secret-example.yamlapiVersion: v1 kind: Secret metadata: name: passbolt-example data: full_secret: {name:passbolt-secret,username:some-username,password:supersecretpassword,uri:passbolt.com,description:some description} password_only: supersecretpassword type: Opaque可以看到full_secret键保存的是完整 JSON 对象password_only键则只保存password属性的原始字符串值。4.2 取值流程GetSecret 调用链GetSecretproviders/v1/passbolt/passbolt.go的调用链为assureLoggedIn确保会话有效getPassboltSecret(ctx, ref.Key)调用client.GetResource(id)拉取资源secretFromResource获取资源类型GetResourceType与秘密数据GetSecret再通过helper.GetResourceFieldMaps解出元数据字段与机密字段组装成Secret结构体providers/v1/passbolt/passbolt.go若property为空返回 JSON 序列化结果否则调用GetProp取单个属性。Secret结构体的 JSON 字段名为name、username、password、uri、description与可选的custom_fieldsproviders/v1/passbolt/passbolt.go这也正是上面同步结果 JSON 键名的来源。五、按名称查找秘密dataFrom.find除了按 ID 精确拉取还可以用dataFrom配合find按名称正则搜索 Passbolt 中的秘密。示例见 docs/snippets/passbolt-external-secret-findbyname.yamlapiVersion: external-secrets.io/v1 kind: ExternalSecret metadata: name: passbolt-example spec: refreshInterval: 1h0m0s secretStoreRef: name: passbolt kind: SecretStore target: name: passbolt-example dataFrom: - find: name: regexp: .*底层由GetAllSecrets实现providers/v1/passbolt/passbolt.go其行为要点必须提供find.name.regexp若ref.Name为空或RegExp为空直接返回missing: find.name.regexp错误先取全部资源再本地过滤调用client.GetResources拉取所有资源再用编译后的正则nameRegexp.MatchString(secret.Name)按解密后的名称过滤结果以资源ID - JSON的 map 形式返回V5 加密元数据的性能提示源码注释明确指出由于 V5 资源的元数据含名称是加密的每个资源都必须先解密才能过滤即使不匹配也会被解密在秘密数量较大时可能影响性能正则会作用于解密后的名称因此regexp: .*匹配所有秘密每个匹配项会以 Passbolt 资源 ID 为键写入目标 Secret。六、自定义字段Custom FieldsPassbolt 资源除了标准属性外还可以携带任意自定义字段。ESO 通过custom_fields.name属性语法暴露这些字段其中name是字段在 Passbolt 中配置的显示名称。示例见 docs/snippets/passbolt-external-secret-custom-fields.yamlapiVersion: external-secrets.io/v1 kind: ExternalSecret metadata: name: passbolt-custom-fields-example spec: refreshInterval: 1h0m0s secretStoreRef: name: passbolt kind: SecretStore target: name: passbolt-custom-fields data: # Fetch a single custom field by its display name (metadata_key). # The property value is the literal prefix custom_fields. followed by # the name of the field as configured in Passbolt. - secretKey: api_token remoteRef: key: e22487a8-feb8-4591-95aa-14b193930cb4 # Replace with the ID of an existing Passbolt secret property: custom_fields.api-token - secretKey: deploy_key remoteRef: key: e22487a8-feb8-4591-95aa-14b193930cb4 property: custom_fields.deploy-key # Omitting property returns the full secret as JSON, with custom_fields # included as a nested object keyed by the field display name. - secretKey: full_secret remoteRef: key: e22487a8-feb8-4591-95aa-14b193930cb4其产生的 Kubernetes Secret 形态如下见 docs/snippets/passbolt-secret-custom-fields-example.yamlapiVersion: v1 kind: Secret metadata: name: passbolt-custom-fields data: api_token: my-api-token-value deploy_key: ssh-ed25519-AAAA... full_secret: {name:my-service,username:deploy,password:supersecretpassword,uri:https://example.com,description:,custom_fields:{api-token:my-api-token-value,deploy-key:ssh-ed25519-AAAA...}} type: Opaque关于自定义字段的官方说明与源码印证不指定property时返回完整 JSONcustom_fields键只要资源至少包含一个命名自定义字段就会出现在该 JSON 对象中键名为字段显示名称名称与值均可加密存储Passbolt 会按字段配置把名称或值存放在明文元数据侧或加密机密侧ESO 在读取前对两侧都进行解密因此无论哪种存储方式字段都可以用显示名称寻址。这在Secret结构体注释中有明确说明providers/v1/passbolt/passbolt.go属性解析逻辑GetProp中通过strings.CutPrefix(key, custom_fields.)识别自定义字段前缀若前缀匹配但字段不存在则返回custom field not found: name否则返回字段值providers/v1/passbolt/passbolt.go字段组装自定义字段最终由helper.ParseCustomFields(metaFields, secretFields).Map()填充到Secret.CustomFields中providers/v1/passbolt/passbolt.go。七、实战小结与注意事项场景使用的 CRD 字段说明建立连接SecretStore.spec.provider.passbolt.host/authhost 必须 HTTPS凭据存于 K8s Secret信任私有 CAcaBundle或caProvider不配置则使用系统根证书按 ID 同步ExternalSecret.spec.data[].remoteRef.keykey 为 Passbolt 资源 UUID只取单属性remoteRef.property支持五个标准属性与custom_fields.name按名称查找ExternalSecret.spec.dataFrom[].find.name.regexp正则匹配解密后的资源名称读取自定义字段property: custom_fields.namename 为 Passbolt 中的字段显示名称需要记住的限制Passbolt Provider 是只读的PushSecret、DeleteSecret等写入操作未实现相关用法请参考仓库中其他支持读写的 Provider如 docs/provider/aws-secrets-manager.mdfind.name.regexp为必填项缺失会直接报错按名称查找会对所有资源解密后再过滤V5 资源较多时需评估性能开销更完整的 SecretStore / ExternalSecret 通用字段说明可参阅 docs/api/secretstore.md 与 docs/api/externalsecret.md。本文所有配置示例均可在仓库 docs/snippets 目录中找到对应 YAMLProvider 实现与测试代码位于 providers/v1/passbolt类型定义位于 apis/externalsecrets/v1/secretsstore_passbolt_types.go便于读者进一步深入验证。【免费下载链接】external-secretsExternal Secrets Operator reads information from a third-party service like AWS Secrets Manager and automatically injects the values as Kubernetes Secrets.项目地址: https://gitcode.com/GitHub_Trending/ex/external-secrets创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
RELATED READING

延伸阅读

更多一线实战笔记与深度复盘,助您持续精进