Skip to content

Deploy Standardized ESO ClusterSecretStore for Hashicorp Vault

This section demonstrates what is needed for deployment. Users can evaluate and adjust for their own environment. Vault provides multiple authentication methods, the two most relevant for External Secrets are:

  • Token Authentication: Static token to authenticate into Vault.
  • Kubernetes Authentication: ESO authenticates to Vault using a Kubernetes service account JWT.

There are multiple types of authentication methods: token, approle, kubernetes, etc. Here we use the token method. See the External Secrets Vault provider docs for full details.

Prerequisites

Network and Istio Requirements

When deploying in a Big Bang environment with hardened Istio and NetworkPolicies, ESO needs network-level and service mesh-level access to Vault.

Handled automatically by the ESO chart:

  • Egress NetworkPolicy: The ESO chart creates allow-egress-vault when networkPolicies.enabled: true, allowing ESO pods to reach the vault namespace on port 8200.
  • Ingress NetworkPolicy (vault-side): The ESO chart defaults the pod label vault-ingress: "true" on ESO pods. The BB Vault chart includes a NetworkPolicy (allow-ingress-to-vault-port-8200-from-custom-app-ingress) that allows ingress on port 8200 from any pod with this label.

Required in your Vault configuration:

The BB Vault chart deploys a deny-all Istio AuthorizationPolicy by default. You must add an ALLOW policy for the external-secrets namespace. Add the following to your Vault Big Bang override values:

addons:
  vault:
    values:
      istio:
        hardened:
          customAuthorizationPolicies:
            - name: allow-external-secrets
              enabled: true
              spec:
                action: ALLOW
                rules:
                  - from:
                      - source:
                          namespaces:
                            - external-secrets
                    to:
                      - operation:
                          ports:
                            - "8200"

Authentication Method: Token

Create a Secret containing your Vault Token

This is needed for the token auth. Example below.

kubectl create secret generic vault-token -n external-secrets --from-literal=token='<VAULT_TOKEN>'

Big Bang Override Values

addons:
  externalSecrets:
    enabled: true
    values:
      networkPolicies:
        enabled: true
      clusterSecretStoreConfiguration:
        enabled: true
        clusterSecretStoreList:
          - name: vault-secrets
            source:
              provider: vault
              server: "https://vault.example.com:8200"
              path: kv
              version: v2
              auth:
                type: token
                secretName: vault-token
                namespace: external-secrets
                key: token

Authentication Method: Kubernetes

Vault’s Kubernetes authentication allows ESO to log in using a Kubernetes ServiceAccount. Vault verifies the SA’s JWT with the Kubernetes API and issues a Vault token mapped to a Vault role.

Prerequisites: - A Vault server accessible from the cluster - Kubernetes auth path enabled and configured in Vault - A Vault role bound to the ESO ServiceAccount

Configure Vault

Enable Kubernetes Auth in Vault:

vault auth enable kubernetes

Use the /config endpoint to configure Vault to talk to Kubernetes. Use kubectl cluster-info to validate the Kubernetes host address and TCP port.

vault write auth/kubernetes/config \
    token_reviewer_jwt="<your reviewer service account JWT>" \
    kubernetes_host=https://192.168.99.100:<your TCP port or blank for 443> \
    kubernetes_ca_cert=@ca.crt

Create a named role:

vault write auth/kubernetes/role/eso-role \
    bound_service_account_names=external-secrets \
    bound_service_account_namespaces=external-secrets \
    policies=default \
    ttl=1h

Big Bang Override Values

addons:
  externalSecrets:
    enabled: true
    values:
      networkPolicies:
        enabled: true
      clusterSecretStoreConfiguration:
        enabled: true
        clusterSecretStoreList:
          - name: vault-secrets
            source:
              provider: vault
              server: "https://vault.example.com:8200"
              path: kv
              version: v2
              auth:
                type: kubernetes
                mountPath: "kubernetes"
                role: "eso-role"
                serviceAccountRef:
                  name: "external-secrets"
                  namespace: "external-secrets"

Fetching Secrets with ExternalSecret

Once the ClusterSecretStore is configured, create ExternalSecret resources to fetch data from Vault. The name field must match the ClusterSecretStore name defined above.

Using individual keys (data)

addons:
  externalSecrets:
    enabled: true
    values:
      externalSecretsConfiguration:
        enabled: true
        secretList:
          - name: vault-secrets
            namespace: external-secrets
            secrets:
              targetName: my-app-secret
              targetPolicy: "Owner"
              data:
                - secretKey: username
                  remoteRef:
                    key: my-app/config
                    property: username
                - secretKey: password
                  remoteRef:
                    key: my-app/config
                    property: password

Using all keys from a path (dataFrom)

addons:
  externalSecrets:
    enabled: true
    values:
      externalSecretsConfiguration:
        enabled: true
        secretList:
          - name: vault-secrets
            namespace: external-secrets
            secrets:
              targetName: my-app-secret
              targetPolicy: "Owner"
              dataFrom:
                - extract:
                    key: my-app/config

Troubleshooting

ClusterSecretStore shows InvalidProviderConfig with 503

Symptom: upstream connect error or disconnect/reset before headers. retried and the latest reset reason: remote connection failure, transport failure reason: delayed connect error: Connection refused

Causes and fixes:

  1. Missing Istio AuthorizationPolicy on Vault: The Vault namespace has a deny-all AuthorizationPolicy. Add the customAuthorizationPolicies shown in the Prerequisites section to your Vault override values.

  2. Missing vault-ingress pod label: Verify ESO pods have the vault-ingress: "true" label. This is defaulted by the chart but can be overridden:

    kubectl get pods -n external-secrets -l app.kubernetes.io/name=external-secrets -o jsonpath='{.items[0].metadata.labels.vault-ingress}'
    
    If missing, ensure your values include:
    upstream:
      podLabels:
        vault-ingress: "true"
    

  3. NetworkPolicies not enabled: Ensure networkPolicies.enabled: true is set in your ESO values so the egress policy to Vault is created.

Invalid vault credentials with non-printable characters

If you encounter invalid vault credentials: configured Vault token contains non-printable characters and cannot be used, trim the token before creating the secret:

TOKEN_CLEAN="$(tr -d '\r\n' < /path/to/token)"
kubectl create secret generic vault-token -n external-secrets --from-literal=token="$TOKEN_CLEAN"