ARTICLE DETAIL

资讯详情

深耕网站视觉设计与运营推广的一线实战洞察。

External Secrets Operator 接入 CyberArk Conjur/Secrets Manager:三种认证方式的 SecretStore 配置实战

External Secrets Operator 接入 CyberArk Conjur/Secrets Manager:三种认证方式的 SecretStore 配置实战 External Secrets Operator 接入 CyberArk Conjur/Secrets Manager三种认证方式的 SecretStore 配置实战【免费下载链接】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仓库中的官方 Conjur Provider 文档docs/provider/conjur.md为主体系统讲解如何将 CyberArk Conjur / Secrets Manager 作为外部密钥源接入 Kubernetes从前提条件、TLS 信任配置到apikey、jwt、cert三种认证方式的 SecretStore 完整定义与部署步骤再到 ExternalSecret 的单密钥拉取与按名称/标签批量拉取。读完本文你将能够独立完成 Conjur 后端到 K8s Secret 的端到端同步并理解其底层实现原理。前提条件Prerequisites在安装 Secrets Manager Provider 之前你需要准备一个可用的 Conjur / Secrets Manager 实例如 Conjur OSS 或 CyberArk Secrets Manager并且有可访问的 Secrets Manager 端点例如https://myapi.example.com已配置好认证信息如hostid、apikey或 JWT/Cert 认证器的 service ID认证方式受支持apikey默认开箱即用jwt与cert需要在 Secrets Manager 侧额外配置认证器可选Secrets Manager 服务端证书用于自签名证书场景见下文「Secrets Manager 服务端证书」一节。一个已安装 ESO 的 Kubernetes 集群。从源码注册表看Conjur Provider 属于被维护状态providers/v1/conjur/provider.go 中的MaintenanceStatus()返回MaintenanceStatusMaintained并在 pkg/register/conjur.go 中被注册到控制器因此安装 ESO 后该 Provider 即可直接使用。Secrets Manager 服务端证书如果你的 Secrets Manager 服务端使用自签名证书官方建议在 SecretStore 定义中通过caBundle字段填充该自签名证书以便 ESO 校验服务端 TLS 身份。证书 CA 必须通过caBundle或caProvider二者之一在 SecretStore 中引用完整示例见 docs/snippets/conjur-ca-bundle.yaml.... spec: provider: conjur: # Service URL url: https://myapi.conjur.org # [OPTIONAL] base64 encoded string of certificate caBundle: base64 encoded cabundle # [OPTIONAL] caProvider: # Instead of caBundle you can also specify a caProvider, # which retrieves the cert from a Secret or ConfigMap caProvider: type: Secret # Can be Secret or ConfigMap name: name of secret or configmap key: key inside secret or configmap # namespace is required for ClusterSecretStore # but not relevant for SecretStore namespace: my-cert-secret-namespace ....两点说明caBundle接受的是base64 编码后的证书字符串直接内联在 YAML 中caProvider则是从同集群的 Secret 或 ConfigMap 中动态读取 PEM 证书适合证书轮换场景其中的namespace字段仅在ClusterSecretStore下必填普通SecretStore会使用自身所在命名空间。对应到 API 类型定义apis/externalsecrets/v1/secretstore_conjur_types.goConjurProvider同时支持CABundle与CAProvider两个可选字段验证逻辑位于 providers/v1/conjur/util/provider.go。External secret store外部密钥存储要把 Secrets Manager 中的密钥同步到 Kubernetes必须配置一个外部 SecretStore并通过以下三种认证方式之一向 Secrets Manager API 认证认证方式说明复杂度apikey使用 Secrets Manager 的hostid和apikey认证最简单Secrets Manager 侧无需额外配置jwt使用 JWT 令牌认证需要配置 authn-jwt 认证器cert使用客户端证书与私钥认证需要配置 authn-cert 认证器三种认证方式在SecretStore.spec.provider.conjur.auth下互斥这一点同时由 OpenAPI 校验注解kubebuilder:validation:MaxProperties1/MinProperties1apis/externalsecrets/v1/secretstore_conjur_types.go和 webhook 校验函数validateAuthCountproviders/v1/conjur/validate.go双重保证——源码中明确要求「must specify exactly one Auth.* method」。Option 1使用 apiKey 认证的 SecretStore该方法使用 Secrets Manager 的hostid与apikey进行认证是三种方式中最易于搭建和使用的因为你的 Secrets Manager 实例无需任何额外配置。Step 1定义外部 SecretStore建议将文件保存为conjur-secret-store.yaml完整示例见 docs/snippets/conjur-secret-store-apikey.yamlapiVersion: external-secrets.io/v1 kind: SecretStore metadata: name: conjur spec: provider: conjur: # Service URL url: https://myapi.conjur.org # [OPTIONAL] base64 encoded string of certificate caBundle: OPTIONALxFIELDxxxBase64xCertxString auth: apikey: # conjur account account: conjur userRef: # Get this from K8S secret name: conjur-creds key: hostid apiKeyRef: # Get this from K8S secret name: conjur-creds key: apikey字段说明urlConjur 实例的 API 端点必填auth.apikey.accountConjur 组织账户名必填auth.apikey.userRef指向一个 Kubernetes Secret其中key对应的值即 Conjurhostidauth.apikey.apiKeyRef指向同一个或另一个 Kubernetes Secret其中key对应的值即 Conjurapikey。Step 2为 Secrets Manager 凭据创建 Kubernetes SecretESO 的 Conjur Provider 需要从 K8s Secret 中读取apikey凭据才能连接 Secrets Manager 服务端。下面是用kubectl创建 K8s Secret 的示例# 整条命令为一行 kubectl -n external-secrets create secret generic conjur-creds --from-literalhostidMYCONJURHOSTID --from-literalapikeyMYAPIKEY # 示例 # kubectl -n external-secrets create secret generic conjur-creds --from-literalhostidhost/data/app1/host001 --from-literalapikey321blahblahconjur-creds正是conjur-secret-store.yaml中userRef与apiKeyRef字段定义的name请保持一致。Step 3创建 SecretStore重要除非使用 ClusterSecretStore否则凭据 Secret 必须与 SecretStore 位于同一命名空间。# 警告将在 external-secrets 命名空间中创建 store请按需修改 # kubectl apply -n external-secrets -f conjur-secret-store.yaml # 警告执行删除命令将删除 secret store 配置 # # 如需删除该 external secretstore # kubectl delete secretstore -n external-secrets conjurOption 2使用 JWT 认证的 SecretStore该方法使用 JWT 令牌向 Secrets Manager 认证JWT 令牌可以通过以下两种方式之一获取从被引用的 KubernetesServiceAccount获取 JWT 令牌推荐从 KubernetesSecret中读取已存在的 JWT 令牌。Step 1定义外部 SecretStore使用 JWT 认证时SecretStore中必须指定account— Secrets Manager 账户名serviceID— Secrets Manager 中配置的 JWT AuthenticatorWebService的 ID用于校验 JWT 令牌。方式 A从 ServiceAccount 获取 JWT 令牌apiVersion: external-secrets.io/v1 kind: SecretStore metadata: name: conjur spec: provider: conjur: # Service URL url: https://myapi.conjur.org # [OPTIONAL] base64 encoded string of certificate caBundle: OPTIONALxFIELDxxxBase64xCertxString auth: jwt: # conjur account account: conjur # The authn-jwt service ID serviceID: my-jwt-auth-service # Service account to retrieve JWT token for serviceAccountRef: name: my-service-account # [OPTIONAL] audiences to include in JWT token audiences: - https://conjur.company.com重要该方法仅支持 Kubernetes 1.22 及以上版本因为它依赖 TokenRequest API 从被引用的 ServiceAccount 获取 JWT 令牌。audiences可以在 Secrets Manager JWT authenticator 中定义。从源码看providers/v1/conjur/auth_jwt.goProvider 会构造authenticationv1.TokenRequest调用ServiceAccounts(...).CreateToken获取令牌并将令牌有效期固定为JwtLifespan 600秒10 分钟若使用的是ClusterSecretStore且serviceAccountRef显式指定了namespaceTokenRequest 会在该命名空间下发起。方式 B从 Kubernetes Secret 中引用 JWT 令牌apiVersion: external-secrets.io/v1 kind: SecretStore metadata: name: conjur spec: provider: conjur: # Service URL url: https://myapi.conjur.org # [OPTIONAL] base64 encoded string of certificate caBundle: OPTIONALxFIELDxxxBase64xCertxString auth: jwt: # conjur account account: conjur # The authn-jwt service ID serviceID: my-jwt-auth-service # Secret containing a valid JWT token secretRef: name: my-jwt-secret key: tokenJWT 令牌必须标识你的 Secrets Manager host、与已配置的 Secrets Manager JWT authenticator 兼容并满足 Secrets Manager 的 JWT 使用规范。你可以使用外部 JWT 签发者或 Kubernetes API Server 来签发令牌例如用下面的命令创建 ServiceAccount 令牌kubectl create token my-service-account --audiencehttps://conjur.company.com --duration3600s源码细节当使用secretRef时若key未填写Provider 会默认回退到token键见 providers/v1/conjur/auth_jwt.go 的getJWTToken逻辑。将 SecretStore 文件保存为conjur-secret-store.yaml。Step 2创建 SecretStore# 警告将在 external-secrets 命名空间中创建 store请按需修改 # kubectl apply -n external-secrets -f conjur-secret-store.yaml # 警告执行删除命令将删除 secret store 配置 # # 如需删除该 external secretstore # kubectl delete secretstore -n external-secrets conjurOption 3使用 cert 认证的 SecretStore该方法使用客户端 X.509 证书与私钥通过authn-cert认证器向 Secrets Manager 认证。证书必须由 Secrets Managerauthn-cert服务信任的 CA 签发。Conjur 会使用认证器策略中配置的约束如cn、san-uri、san-dns、san-ip变量校验提交的证书并可通过 per-host 注解将约束限定到单个工作负载。Step 1定义外部 SecretStore使用 cert 认证时SecretStore中必须指定account— Secrets Manager 账户名serviceID— Secrets Manager 中配置的authn-certWebService的 IDclientCertRef— 指向包含PEM 编码客户端证书的 Kubernetes SecretclientKeyRef— 指向包含PEM 编码客户端私钥的 Kubernetes SecrethostId可选— 用于认证的 Secrets Manager host 身份。默认request模式下必填使用spiffe模式时留空host 身份将从证书的 SPIFFE SAN URIspiffe://trust-domain/workload-id中推导。完整示例见 docs/snippets/conjur-secret-store-cert.yamlapiVersion: external-secrets.io/v1 kind: SecretStore metadata: name: conjur spec: provider: conjur: # Service URL url: https://myapi.conjur.org # [OPTIONAL] base64 encoded string of certificate caBundle: OPTIONALxFIELDxxxBase64xCertxString auth: cert: # conjur account account: conjur # The authn-cert service ID serviceID: my-cert-auth-service # [OPTIONAL] HostID for cert authentication (leave empty for spiffe mode). # hostId: vm-01 # Reference to a Kubernetes secret containing the PEM-encoded client certificate clientCertRef: name: conjur-client-cert key: tls.crt # Reference to a Kubernetes secret containing the PEM-encoded client key clientKeyRef: name: conjur-client-cert key: tls.keyStep 2为客户端证书与私钥创建 Kubernetes Secret使用证书认证连接 Secrets Manager 服务端时ESO 的 Conjur Provider 需要从 K8s Secret 中读取客户端证书与私钥。可以使用 TLS 类型或 generic 类型的 Secret下面示例使用 generic 类型# 整条命令为一行 kubectl -n external-secrets create secret generic conjur-client-cert \ --from-filetls.crt/path/to/client.crt \ --from-filetls.key/path/to/client.keyconjur-client-cert是conjur-secret-store.yaml中clientCertRef与clientKeyRef字段定义的name。证书与私钥都必须为 PEM 编码私钥为 RSA 格式见 apis/externalsecrets/v1/secretstore_conjur_types.go 中ConjurCert.ClientKeyRef的注释说明。Step 3创建 SecretStore重要除非使用 ClusterSecretStore否则凭据 Secret 必须与 SecretStore 位于同一命名空间。# 警告将在 external-secrets 命名空间中创建 store请按需修改 # kubectl apply -n external-secrets -f conjur-secret-store.yaml # 警告执行删除命令将删除 secret store 配置 # # 如需删除该 external secretstore # kubectl delete secretstore -n external-secrets conjur定义 ExternalSecret 并拉取密钥配置好 Secrets Manager Provider 的 SecretStore 之后就可以从 Secrets Manager 拉取密钥了。下面是拉取单个密钥的示例完整文件见 docs/snippets/conjur-external-secret.yamlapiVersion: external-secrets.io/v1 kind: ExternalSecret metadata: name: conjur spec: refreshInterval: 1h0m0s secretStoreRef: # 必须与 SecretStore 中的 metadata.name 一致 name: conjur kind: SecretStore data: - secretKey: secret00 remoteRef: key: data/app1/secret00将文件保存为conjur-external-secret.yaml。其中data[].remoteRef.key是 Conjur 中的变量路径如data/app1/secret00data[].secretKey是同步到 K8s Secret 中的键名。Find by Name / Find by Tag按名称或标签查找Conjur Provider 同样支持 ESO 的Find by Name与Find by Tag特性即通过正则表达式或标签动态批量拉取多个 Secrets Manager 密钥。两种过滤器在单个find上互斥如果同时设置了name和tags则只使用nametags会被忽略。按名称查找完整示例见 docs/snippets/conjur-external-secret-find.yamlapiVersion: external-secrets.io/v1 kind: ExternalSecret metadata: name: conjur-find-by-name spec: refreshInterval: 1h0m0s secretStoreRef: # 必须与 SecretStore 中的 metadata.name 一致 name: conjur kind: SecretStore target: name: k8s-secret-to-be-created dataFrom: - find: name: # 匹配 app1 命名空间下的所有密钥例如 app1/secret00、app1/secret01 等 regexp: ^app1\/.$按标签查找将name替换为tags即可dataFrom: - find: tags: environment: prod application: app1安全建议使用这些批量查找特性时强烈建议将 Secrets Manager host 的权限限制为仅能访问其所需的密钥。这样既更安全也能降低 Secrets Manager 服务端和 ESO 双方的负载。创建 ExternalSecret 并校验同步结果创建 ExternalSecret# 警告将在 external-secrets 命名空间中创建 external-secret请按需修改 # kubectl apply -n external-secrets -f conjur-external-secret.yaml # 警告执行删除命令将删除 external-secrets 配置 # # 如需删除该 external secret # kubectl delete externalsecret -n external-secrets conjur验证 K8s Secret登录 Secrets Manager 服务端确认目标密钥已存在检查 Kubernetes Secret 的值确认与 Secrets Manager 服务端中的值一致# 警告该命令将以明文显示存储的密钥 # # 假设密钥名为 secret00该命令会显示其值 kubectl get secret -n external-secrets conjur -o jsonpath{.data.secret00} | base64 --decode echo源码视角Provider 的工作原理与约束为了让上文的配置更具可验证性这里补充几个关键实现事实均来自 providers/v1/conjur 目录能力声明为读写Capabilities()返回SecretStoreReadWriteproviders/v1/conjur/provider.go意味着 Conjur Provider 同时支持GetSecret拉取与PushSecret推送能力推送实现见 providers/v1/conjur/client_push.go。校验规则即上文三种认证方式webhook 的ValidateStoreproviders/v1/conjur/validate.go依次校验url不能为空auth下必须且只能配置apikey/jwt/cert之一apikey模式必须提供account、userRef、apiKeyRefjwt模式必须提供account、serviceID且secretRef与serviceAccountRef至少其一cert模式必须提供account、serviceID、clientCertRef与clientKeyRef。配置错误会在创建/更新 SecretStore 时被 webhook 直接拒绝。TokenRequest 的底层实现JWT 的 ServiceAccount 模式依赖 KubernetesTokenRequest子资源 APIkube客户端不支持该子资源因此 Provider 在NewClient中自行构造了kubernetes.Clientset见 providers/v1/conjur/provider.go这是上文「仅支持 Kubernetes 1.22」这一限制的源码根因。JWT 令牌生命周期从 ServiceAccount 签发的 JWT 令牌有效期为 600 秒10 分钟由常量JwtLifespan定义providers/v1/conjur/auth_jwt.go每次同步会自动重新签发无需手动管理令牌轮换。延伸阅读ClusterSecretStore API 文档跨命名空间共享凭据与存储时使用Conjur Provider 完整源码providers/v1/conjur其中 provider_test.go 与 validate_test.go 覆盖了各类校验分支的测试用例Conjur 相关 API 类型定义apis/externalsecrets/v1/secretstore_conjur_types.go以及 CRD 定义 config/crds/bases/external-secrets.io_secretstores.yaml仓库内配套的完整 YAML 示例片段均位于 docs/snippets 目录文件名以conjur-开头。【免费下载链接】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),仅供参考
返回列表