使用外部秘密操作者和保险库进行组合利用

“External Secret Operator是指外部秘密运营商。”

外部秘密运营商(ESO)是一种用于在Kubernetes上管理外部秘密的软件。以下文章列举了一些特点,但我认为最重要的是在实施GitOps时变得更容易管理秘密。您可以实现GitOps而无需将秘密信息提交到GitHub。

我们将使用Hashicorp Vault作为外部的秘密管理器。

前提条件

    • Vaultを知っている

 

    Kubernetesを知っている

环境

    • Windows11 (wsl2)

 

    • Kubernetes version 1.25.3 (kind構築)

 

    Vault version 1.12

验证

这次要做的事情

    • ESOインストール

 

    • Vault のKubernetes authを利用する認証設定

 

    動作確認

安装ESO

ESO的安装非常简单,只需执行以下helm命令即可。

helm repo add external-secrets https://charts.external-secrets.io

helm install external-secrets \
   external-secrets/external-secrets \
    -n external-secrets \
    --create-namespace \
    --set installCRDs=true

准备秘密数据

我会将测试数据注册到Vault中。
这次只需确认ESO的功能,所以我注册了”my-value=mysecret”。

/ $ vault secrets enable -path=eso -version=2 -description="This secret engine is used the ESO to get secrets" kv
Success! Enabled the kv secrets engine at: eso/
/ $ vault kv put eso/foo my-value=mysecret
== Secret Path ==
eso/data/foo

======= Metadata =======
Key                Value
---                -----
created_time       2023-02-04T10:19:04.717624389Z
custom_metadata    <nil>
deletion_time      n/a
destroyed          false
version            1

Kubernetes验证准备完成。

ESO可以使用的认证方式有5种。

    • token-based

 

    • appRole

 

    • kubernetes-native

 

    • ldap

 

    jwt/oidc

 

这次我们将验证最容易使用的Kubernetes auth。原因将在最后稍作说明。
在验证过程中,我们参考了以下页面。
https://cloud.redhat.com/blog/vault-integration-using-kubernetes-authentication-method#:~:text=Kubernetes%20Auth%20Method%20The%20Kubernetes%20authentication%20method%20can,%2Fvar%2Frun%2Fsecrets%2Fkubernetes.io%2Fserviceaccount%2Ftoken%20and%20is%20sent%20to%20Vault%20for%20authentication.

「system:auth-delegator」是Kubernetes的默认角色。

kubectl create sa vault-auth -n vault
kubectl create clusterrolebinding k8s-auth-client-for-vault --clusterrole=system:auth-delegator --serviceaccount=vault:vault-auth

在进行Kubernetes身份验证时,Vault所需的有以下三个方面。

    1. Service Account的令牌

 

    1. kubernetes API服务器的端点

 

    Kubernetes集群的CA证书

首先,我们需要创建以下资源以获取Service Account的密钥。

kubectl apply -f vault-auth.yaml -n vault
apiVersion: v1
kind: Secret
metadata:
  name: vault-auth
  annotations:
    kubernetes.io/service-account.name: "vault-auth"
type: kubernetes.io/service-account-token

2号和3号可以分别从Kubernetes配置文件中获取,所以现在已经准备好了。
在进行格式化的同时,获取以下数值。
请注意,Service Account的令牌和CA证书是通过base64编码的,所以需要注意。如果搞错了,身份验证将无法成功。

token_reviewer_jwt=$(kubectl get secret -n vault -o jsonpath='{.data.token}' vault-auth | base64 -d)
kubernetes_host=https://kubernetes.default.svc.cluster.local  # vault がKubernetes API Serverにアクセスするために必要
kubernetes_ca_cert=$(kubectl config view -o jsonpath='{.clusters[].cluster.certificate-authority-data}' --minify=true --raw | base64 -d)

Kubernetes授權配置

使用下列命令在Kubernetes中启用身份验证。
将角色名称设置为”eso-vault”,策略是先前创建的角色。

vault auth enable -description="k8s secret engine for vault" kubernetes 
vault write auth/kubernetes/config \
    token_reviewer_jwt=$token_reviewer_jwt \
    kubernetes_host=$kubernetes_host \
    kubernetes_ca_cert=$kubernetes_ca_cert

vault write auth/kubernetes/role/eso-vault \
    bound_service_account_names=vault-auth \
    bound_service_account_namespaces=vault \
    policies=default,eso-vault-client \
    ttl=15m

ESO准备就绪。

我会设置 ESO 请求的角色。

vault policy write eso-vault-client eso-vault-client.hcl
path "eso/data/*" {
  capabilities = ["read"]
}

确认动作。 如果返回以下结果,就可以了。

/ $ vault write auth/kubernetes/login role=eso-vault jwt=$token_reviewer_jwt
Key                                       Value
---                                       -----
token                                     hvs.CAESIKQznRS1XNprF8eQjF_zZFlL8Da9jCHRmhCvTE3F5aP9Gh4KHGh2cy5IMGo1SHd0eU9ldzhIc00wZEJ2WG1MZGs
token_accessor                            dmRuQwUOUugmuXzqPEIwzVxl
token_duration                            1m
token_renewable                           true
token_policies                            ["default" "eso-vault-client"]
identity_policies                         []
policies                                  ["default" "eso-vault-client"]
token_meta_role                           eso-vault
token_meta_service_account_name           vault-auth
token_meta_service_account_namespace      vault
token_meta_service_account_secret_name    vault-auth
token_meta_service_account_uid            d35d56fd-24f3-45b8-a1e9-20b15a08f172
image.png

从ESO网站引用,https://external-secrets.io/v0.7.2/provider/hashicorp-vault/。

首先,我们将每个设置都以yaml格式编写。

apiVersion: external-secrets.io/v1beta1
kind: ClusterSecretStore
metadata:
  name: vault-backend-k8s-auth
  labels:
    service: secret-manager
    version: 1.0.0
    env: prd
spec:
  provider:
    vault:
      server: http://vault.vault.svc.cluster.local:8200  # 接続先のVault Cluster
      path: eso
      version: v2
      auth:
        kubernetes:
          # Path where the Kubernetes authentication backend is mounted in Vault
          mountPath: kubernetes  # 有効にしたkubernetes auth。今回はデフォルトなのでkubernetes
          # A required field containing the Vault Role to assume.
          role: eso-vault  # 作成したvaultのrole名
          # Optional service account field containing the name
          # of a kubernetes ServiceAccount
          serviceAccountRef:
            name: vault-auth
            namespace: vault
apiVersion: external-secrets.io/v1beta1
kind: ExternalSecret
metadata:
  name: vault-eso-example
spec:
  refreshInterval: 15s
  secretStoreRef:
    name: vault-backend-k8s-auth  # 利用するSecretStoreの名前
    kind: ClusterSecretStore
  target:
    name: output-secret  # 作成するsecretの名前
  data:
  - secretKey: foobar  # 作成するSecretのKeyの名前
    remoteRef:
      # vault kv put eso/foo my-value=mysecretで作成したシークレットを取得する設定
      key: eso/foo
      property: my-value

如果使用没有报错,就可以了。获取Secret的动机需要大约10秒钟。

kubectl apply -f ./secret-store-k8s-es.yaml
kubectl apply -f ./secret-store-k8s-ss.yaml

root@mypc02:/mnt/e/work/eso# kc get clustersecretstores.external-secrets.io,externalsecrets.external-secrets.io
NAME                                                            AGE   STATUS   CAPABILITIES   READY
clustersecretstore.external-secrets.io/vault-backend-k8s-auth   26m   Valid    ReadWrite      True

NAME                                                   STORE                    REFRESH INTERVAL   STATUS         READY
externalsecret.external-secrets.io/vault-eso-example   vault-backend-k8s-auth   15s                SecretSynced   True

确认行动

最后,获取Secret并确认其值。

root@mypc02:/mnt/e/work/eso# kc get secret
NAME            TYPE     DATA   AGE
output-secret   Opaque   1      76s
root@mypc02:/mnt/e/work/eso# kc get secret output-secret -o yaml | grep data: -A1
data:
  foobar: bXlzZWNyZXQ=
root@mypc02:/mnt/e/work/eso# echo bXlzZWNyZXQ= | base64 -d
mysecret

最后

为了成功避免在本次中将Kubernetes的Secret信息提交到GitHub上,我们进行了ESO的验证。虽然在实际应用中可能有一些需要考虑的地方,但我觉得它非常易用。由于一开始没有考虑选择kubernetes auth的原因,所以我会稍后提及。但由于未经验证,所以无法确定是否正确,请仅作为参考。

首先,我们排除了ldap和jwt/oidc,因为它们不适用于M2M身份验证。
对于基于令牌的认证,我对其为静态认证方式以及ttl和max-ttl的更新有些担忧。根据ttl和max-ttl的设定,可能需要定期手动更新,这让我感到有些不便。
虽然approle是一种动态认证方式,但我仍然认为它需要更新ttl和max-ttl,需要另外实现更新的机制。

谢谢您阅读完以上内容,到此为止。

广告
将在 10 秒后关闭
bannerAds