Configure External Secrets Operator to fetch secrets from Vault

Kubernetes Vault ExternalSecret

3 min read | by Jordi Prats

The External Secrets Operator can be configured to retrieve secrets from Vault, to demonstrate this we are going to use a test vault running on Kubernetes.

First, we'll need to setup vault, we are going to need a token the allow the External Secrets Operator to retrieve secrets, for this demo we are going to use a helm chart for a test vault where the token is test.

Install test vault

Installing this test vault doesn't take much:

helm repo add testvault https://pet2cattle.github.io/helm-testvault/
helm install testvault testvault/testvault -n testvault --create-namespace

We can use the vaultcli Pod to create the secret we want to store on vault, in this case is going to be s3cr3t:

kubectl exec -it testvault-vaultcli -n testvault -- sh -c \
  "echo test | vault login -; vault kv put secret/demo secret=s3cr3t; vault kv get secret/demo"

Install External Secrets Operator

To install the External Secrets Operator doesn't take much either since we don't need to configure much at the chart level:

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

Configure ESO to use Vault

To configure the External Secrets Operator to connect to Vault we'll need to create a Secret with the vault's token and a SecretStore object pointing to Vault:

kubectl apply -f - <<"EOF"
apiVersion: v1
kind: Secret
metadata:
  name: vault-token
data:
  token: dGVzdA==
---
apiVersion: external-secrets.io/v1beta1
kind: SecretStore
metadata:
  name: vault-backend
spec:
  provider:
    vault:
      server: "http://testvault.testvault:80"
      path: "secret"
      version: "v2"
      auth:
        tokenSecretRef:
          name: "vault-token"
          key: "token"
EOF

As soon as this SecretStore is available, we can now create an ExternalSecret referencing the SecretStore to retrieve the actual secret:

kubectl apply -f - <<"EOF"
apiVersion: external-secrets.io/v1beta1
kind: ExternalSecret
metadata:
  name: vault-example
spec:
  refreshInterval: "15s"
  secretStoreRef:
    name: vault-backend
    kind: SecretStore
  data:
  - secretKey: demo
    remoteRef:
      key: secret/demo
      property: secret
EOF

This ExternalSecret is going to create a Kubernetes Secret containing the data it retrieves from Vault:

$ kubectl get externalsecrets
NAME                                               STORE           REFRESH INTERVAL   STATUS         READY
externalsecret.external-secrets.io/vault-example   vault-backend   15s                SecretSynced   True

NAME                                            AGE   STATUS   READY
secretstore.external-secrets.io/vault-backend   13s   Valid    True
$ kubectl get secret vault-example -o yaml
apiVersion: v1
data:
  demo: czNjcjN0
immutable: false
kind: Secret
metadata:
(...)
type: Opaque
$ echo "czNjcjN0" | base64 -d
s3cr3t

Posted on 18/10/2022