This document covers Vault as the
ClusterSecretStore or SecretStore backend that the External Secrets Operator (ESO) uses to replicate Airflow secrets between data planes during failover. It’s a different integration from using Vault as an Airflow secrets backend for Airflow variables and connections within a single Deployment. You can use either integration independently, or both together.Prerequisites
- A Vault server reachable from every data plane cluster that will use it.
- Permission to create policies, auth mounts, and roles in Vault.
- The Vault CLI, or equivalent API access, authenticated with an admin or operator token.
kubectlaccess to each data plane cluster. Depending on your ESO mode, you need permission to create either a cluster-scopedClusterSecretStoreor a namespacedSecretStore. See Which secret store to create.
The manifests and commands here assume the platform is installed in the
astronomer namespace. If you installed it into a different namespace, replace astronomer throughout, including bound_service_account_namespaces and the serviceAccountRef.namespace.Which secret store to create
Vault works behind either anexternal-secrets.io ClusterSecretStore or a namespaced SecretStore. Which kind you create — a single shared store, a platform-synced store, or one per pool namespace — is determined by your External Secrets Operator mode, not by Vault. See External Secrets Operator security to choose a mode, and the manifests reference for the store manifests. This page covers only the Vault-specific configuration you add to that store.
Grant Vault access for data plane failover
APC currently offers ESO integration with Vault only for data plane failover, not as a standalone mechanism for syncing other secrets. The policy in this document grants read and write access unconditionally:- ESO creates
ExternalSecretresources on every failover-enabled cluster, which read the replicated secrets from Vault. - The deployment orchestrator on the source cluster also creates
PushSecretresources, which write the fernet key, environment variables, and database credentials to Vault so the destination cluster can pull them.
Enabling data plane failover (
global.dataPlaneFailover.enabled: true) doesn’t enable ESO by itself. ESO installs from its own Helm subchart, gated separately by external-secrets.enabled. See Enable data plane failover.Step 1: Create a Vault policy
Create a Vault policy that grants read and write access:secret/data/* and secret/metadata/* paths. PushSecret uses the metadata path to manage secret versions, so a policy that grants access only to secret/data/* still causes PushSecret writes to fail.
Write the policy to Vault:
Step 2: Enable a Kubernetes auth mount for each data plane cluster
Vault’sauth.kubernetes method validates a service account token against one specific Kubernetes API server per auth mount. If more than one data plane cluster authenticates to the same Vault instance, each cluster needs its own auth mount — a single mount can’t validate tokens from more than one cluster.
-
Enable a dedicated mount for the cluster:
-
Configure the mount with that cluster’s API server details:
Retrieve
kubernetes_hostfrom the cluster’s API server endpoint, and retrievekubernetes_ca_certandtoken_reviewer_jwtfrom a service account token that Vault uses to validate other tokens. See Vault’s Kubernetes auth method documentation for how to generate the reviewer JWT for your Kubernetes version.
-path value each time.
Step 3: Create a Vault role
Create a role that binds the policy from Step 1 to the auth mount from Step 2, scoped to the service account ESO runs as:<eso-service-account> is the Kubernetes service account that the ESO Pod runs as on this data plane cluster. If you installed ESO through the APC Helm chart’s bundled subchart (external-secrets.enabled: true), this is the release’s ESO service account in the astronomer namespace.
If the cluster uses External Secrets Operator security Mode 3 (customer-managed isolated identity), map the per-namespace service account here instead of the shared ESO service account, so each Deployment authenticates to Vault as its own identity.
Step 4: Add the Vault provider to your secret store
Reference the auth mount and role you created from thespec.provider.vault block of your ESO secret store. The example below is a ClusterSecretStore (the shared-identity form). For a namespaced SecretStore — the platform-synced store in Mode 2 or a per-pool-namespace store in Mode 3 — use the identical spec.provider.vault block in the SecretStore shape shown in the manifests reference.
metadata.name on every data plane cluster that shares this Vault instance — this is the value you provide for global.dataPlaneFailover.externalSecretManagerName in your Helm values. Use the same path on every cluster as well, since it identifies the Vault secrets engine that holds the replicated secrets, and the destination cluster reads from the same location the source cluster writes to. The auth.kubernetes.mountPath and auth.kubernetes.role values differ per cluster.
Network requirements
If your data plane clusters run in separate networks, Vault must be reachable from each of them over the network, not just from its own cluster’s in-cluster DNS.- Expose Vault through a network load balancer reachable from every data plane cluster that needs it.
- Open firewall or security group rules that allow traffic from each data plane cluster’s CIDR range to the Vault endpoint.
- Confirm connectivity from each cluster before you rely on the configuration — see the verification steps in the following section.
Verify the configuration
Before applying Helm values that depend on thisClusterSecretStore or SecretStore, confirm the setup works end to end.
-
Write a test secret to Vault:
-
Create a test
ExternalSecretin the data plane cluster’sastronomernamespace that references the store and reads the test secret. This example uses aClusterSecretStore; on a namespace-pools cluster, setsecretStoreRef.kindtoSecretStoreinstead. -
Confirm it syncs:
The
STATUScolumn should showSecretSynced. If it doesn’t, check the ESO Pod logs for authentication or permission errors before continuing.
dataPlaneFailover.enabled: true), also complete the PushSecret and connection-secret checks in Verify secret replication before a failover. Those checks confirm write access, which the preceding ExternalSecret test doesn’t cover.
Troubleshooting
PushSecretreports a failure, or Airflow secrets don’t appear on the destination cluster after a failover: The Vault policy likely grants read-only access on a cluster wheredataPlaneFailover.enabledistrue. Update the policy to includecreateandupdateon bothsecret/data/*andsecret/metadata/*, then retry.ExternalSecretorPushSecretfails to authenticate from one data plane cluster but succeeds from another: Confirm the failing cluster has its own Kubernetes auth mount and that the mount’skubernetes_hostand reviewer JWT match that cluster, not another cluster’s.- A cluster in a different network can’t reach Vault: Confirm Vault is exposed beyond in-cluster DNS for that network, and that firewall or security group rules allow traffic from the cluster’s CIDR range. See Network requirements.