External Secrets Operator (ESO)

Syncs secrets from external providers (OpenBao/Vault, AWS, GCP, Azure) into Kubernetes Secrets. Includes ClusterSecretStore, ExternalSecret CRs, automatic rotation, and OpenBao auto-seed Job.

Architecture

ESO Controller - Watches ExternalSecret CRs, syncs from provider
ClusterSecretStore - Cluster-wide backend config (Vault/AWS/GCP/Azure)
ExternalSecret - Per-component CR that pulls secrets from the store
Seed Job - One-time Job that populates OpenBao with all component secrets (conditional)
Webhook - Validates CRs on admission

Attributes

Attribute Example Where It Impacts
namespace REQ external-secrets All manifests, namespace.yaml
secret_store_provider REQ vault ClusterSecretStore provider type (vault, aws, gcp, azure)
replicas 1 helm-values.yaml controller replicas
mem_request / mem_limit 128Mi / 256Mi helm-values.yaml resources.requests/limits.memory
cpu_request / cpu_limit 100m / 200m helm-values.yaml resources.requests/limits.cpu
eso_helm_version 2.1.0 helm/generate-yaml.sh chart version

Vault Provider Attributes

secret_store_host REQ https://openbao.sre.example.io ClusterSecretStore server URL, seed Job BAO_ADDR
secret_store_path secret ClusterSecretStore KV engine path
secret_store_version v2 ClusterSecretStore KV version
secret_store_auth_token REQ ****** eso.env token, used by ClusterSecretStore + seed Job

AWS Provider Attributes

aws_region us-east-1 ClusterSecretStore AWS region
aws_access_key / aws_secret_key ****** eso.env AWS credentials

GCP Provider Attributes

gcp_project_id my-project ClusterSecretStore GCP project
gcp_credentials ****** eso.env GCP service account JSON

Azure Provider Attributes

azure_vault_url https://myvault.vault.azure.net ClusterSecretStore Azure Key Vault URL
azure_tenant_id abc-123 ClusterSecretStore Azure tenant
azure_client_id / azure_client_secret ****** eso.env Azure service principal credentials

ESO Integration (Component Templates)

When ESO exists in a stack, these component templates automatically switch from local K8s Secrets to ExternalSecret CRs that pull from the ClusterSecretStore:

Component Secrets Managed OpenBao Path
rabbitmq erlang cookie, password secret/{name}
cnpg admin creds + per-database creds secret/{name}, secret/{name}/{db}
mongodb cluster secrets (10 keys) + per-database secret/{name}, secret/{name}/{db}
grafana admin user/password secret/{name}
prometheus SMTP + Slack alerting creds secret/{name}
keycloak_operator DB creds, admin creds, client secret secret/{name}/db, /admin, /client
OpenBao Seed Job (seed-openbao-job.yaml):
Condition: Only generated when external_secrets-openbao link exists
1. Connects to OpenBao via secret_store_host URL (cross-cluster)
2. Authenticates with the same token as ClusterSecretStore
3. Uses seed_if_missing logic — skips secrets that already exist (idempotent)
4. Seeds all 6 component types from cookiecutter.components
5. Auto-deletes after 5 minutes (ttlSecondsAfterFinished: 300)
Image: quay.io/openbao/openbao:latest | backoffLimit: 3
Detection Mechanism:
Components detect ESO via cookiecutter.components — checks for type == "external_secrets"
When ESO is absent, output is identical to the non-ESO flow (local K8s Secrets)

Links

Link Direction Generated Output
Prometheus → ESO Inbound Enables service-monitor.yaml for metrics scraping
Istio → ESO Inbound Enables istio-injection label on namespace.yaml
ESOOpenBao Outbound Generates seed-openbao-job.yaml to auto-populate OpenBao with all component secrets

Generated Files

File Condition Content
k8s/deploy/base/namespace.yaml Always Namespace definition with optional istio-injection label
k8s/deploy/base/cluster-secret-store.yaml Always ClusterSecretStore CR for the selected provider (vault/aws/gcp/azure)
k8s/deploy/base/service-monitor.yaml prometheus-external_secrets link ServiceMonitor for Prometheus metrics scraping
k8s/deploy/base/seed-openbao-job.yaml external_secrets-openbao link Seed Job: populates OpenBao with all component secrets (SOPS encrypted)
k8s/deploy/base/kustomization.yaml Always Kustomize resources + secretGenerator for eso.env
k8s/deploy/base/secret/eso.env Always Provider credentials (SOPS encrypted)
k8s/deploy/base/secret/registry.json Always Container registry credentials (SOPS encrypted)
helm/helm-values.yaml Always Helm values: replicas, resources, webhook config
helm/generate-yaml.sh Always Helm template rendering script
day2/seed-vault.sh Always Manual seed script for any Vault backend (same seed_if_missing logic)

Helm Chart

Repo: https://charts.external-secrets.io
Chart: external-secrets/external-secrets
Version: 2.1.0