Skip to content

SecretsManagement ​

Scope: namespaced · Required by every workload

Selects the credential backend for a namespace. Workloads in the same namespace can bind it via secretsRef and reference the materialized Secret names; a workload without secretsRef uses Secrets you create yourself instead. One backend per resource. For the full secrets model, providers, and the Key Vault matrix, see Secrets Management.

Spec ​

FieldTypeDescription
backendenum eso | sealedSecrets (required)The credential backend
esoobjectESO configuration (when backend: eso)
sealedSecretsobjectSealed Secrets configuration (when backend: sealedSecrets)

eso ​

FieldTypeDescription
providerenum azureKeyVault (default) | hashicorpVault | rawThe ESO SecretStore provider
vaultURLstringAzure Key Vault URL (azureKeyVault provider)
authTypeenum WorkloadIdentity (default) | ServicePrincipalAzure auth method
serviceAccountNamestringSA ESO authenticates as (Workload Identity). The operator creates this ServiceAccount if it's missing (owned by the CR, annotated from clientID/tenantID); a pre-existing SA is adopted untouched
clientIDstringAzure user-assigned managed-identity client ID. Stamped onto the created SA as azure.workload.identity/client-id, which ESO reads to exchange the SA token. Required for Workload Identity unless you pre-create the SA with that annotation
tenantID / authSecretRefstring / refsService Principal credentials. tenantID is also stamped onto the Workload-Identity SA as azure.workload.identity/tenant-id
hashicorpVaultobjectHashiCorp Vault connection — see hashicorpVault
providerConfigobjectRaw ESO spec.provider block (provider raw)
refreshIntervaldurationDefault 1h
externalSecretslistThe Secrets to materialize

hashicorpVault ​

FieldTypeDescription
serverstring (required)Vault address, e.g. https://vault.example.internal:8200
pathstringKV mount, default secret
versionenum v2 (default) | v1KV engine version
namespacestringVault Enterprise namespace (e.g. team-a); empty for open-source Vault
caSecretRef{ name, key }Secret holding the PEM certificate of the CA that signed Vault's TLS certificate (key default ca.crt) — needed when Vault uses a private CA, the norm on-prem
authobject (required)Exactly one of the three below
auth.kubernetes{ role, mountPath, serviceAccountName }Vault Kubernetes auth (recommended in-cluster). The Vault role is bound to serviceAccountName; the operator creates that ServiceAccount if it is missing (an existing one is used untouched). Empty ⇒ ESO's own ServiceAccount. mountPath default kubernetes
auth.appRole{ path, roleId, secretIdSecretRef }Vault AppRole auth (common on-prem): the role ID plus a Secret holding the secret ID (key default secret-id). path default approle
auth.tokenSecretRef{ name, key }A Secret holding a Vault token (key default token). Tokens expire — prefer the methods above

With Vault, each keys entry maps a key of the Kubernetes Secret to a secret path under the mount; the Kubernetes key is also the field read from that Vault secret (OPENAI_API_KEY: navique/models reads field OPENAI_API_KEY of secret/navique/models).

The Vault side — a read-only policy on the mount and the role for your auth method — is set up once by your Vault administrator; the management console writes the exact commands for your settings.

externalSecrets[] ​

FieldDescription
nameTarget Kubernetes Secret name
keys{ k8sKey: remoteSecretName } shortcut mapping
dataFull ESO remoteRef form (secretKey, remoteKey, property, version) for providers where property/version matter
findRegexpBulk dataFrom.find by regexp

sealedSecrets ​

FieldDescription
controllerNamespaceWhere the Sealed Secrets controller lives; defaults to this namespace

Examples ​

ESO — Azure Key Vault via Workload Identity (production default) ​

yaml
apiVersion: core.navique.com/v1alpha1
kind: SecretsManagement
metadata:
  name: forge-secrets
  namespace: forge-gateway
spec:
  backend: eso
  eso:
    vaultURL: https://kvforgepltprod.vault.azure.net/
    serviceAccountName: forge-sa   # created by the operator if absent (adopted if it exists)
    clientID: 11111111-2222-3333-4444-555555555555  # managed-identity client ID (SA annotation)
    refreshInterval: 1h
    externalSecrets:
      - name: model-credentials
        keys:
          OPENAI_API_KEY: gateway-foundry-api-key
          ANTHROPIC_API_KEY: gateway-foundry-api-key

ESO — Service Principal (non-AKS / Kind) ​

yaml
spec:
  backend: eso
  eso:
    vaultURL: https://kv.vault.azure.net/
    authType: ServicePrincipal
    tenantID: <tenant-guid>
    authSecretRef:
      clientID:     { name: azure-sp, key: client-id }
      clientSecret: { name: azure-sp, key: client-secret }

ESO — HashiCorp Vault on-prem (Kubernetes auth, private CA) ​

yaml
spec:
  backend: eso
  eso:
    provider: hashicorpVault
    hashicorpVault:
      server: https://vault.example.internal:8200
      namespace: team-a            # Vault Enterprise only
      caSecretRef: { name: vault-ca }
      auth:
        kubernetes: { role: navique, serviceAccountName: navique-vault }
    externalSecrets:
      - name: model-credentials
        keys: { OPENAI_API_KEY: navique/models }

ESO — HashiCorp Vault with AppRole ​

yaml
spec:
  backend: eso
  eso:
    provider: hashicorpVault
    hashicorpVault:
      server: https://vault.example.internal:8200
      caSecretRef: { name: vault-ca }
      auth:
        appRole:
          roleId: 0f3c…                                 # not a secret
          secretIdSecretRef: { name: vault-approle }    # key secret-id
    externalSecrets:
      - name: model-credentials
        keys: { OPENAI_API_KEY: navique/models }

ESO — HashiCorp Vault with a token (dev / hermetic) ​

yaml
spec:
  backend: eso
  eso:
    provider: hashicorpVault
    hashicorpVault:
      server: http://vault.vault.svc:8200
      auth:
        tokenSecretRef: { name: vault-token, key: token }
    externalSecrets:
      - name: model-credentials
        keys: { OPENAI_API_KEY: model-credentials }

ESO — any provider (raw passthrough) ​

provider: raw injects the ESO spec.provider block verbatim, so every ESO provider works (AWS, GCP, IBM, Akeyless, 1Password, …) with no operator changes:

yaml
spec:
  backend: eso
  eso:
    provider: raw
    providerConfig:
      aws:
        service: SecretsManager
        region: eu-central-1
        auth: { jwt: { serviceAccountRef: { name: forge-sa } } }
    externalSecrets:
      - name: model-credentials
        data:
          - { secretKey: OPENAI_API_KEY, remoteKey: prod/model, property: openai, version: AWSCURRENT }

Sealed Secrets ​

yaml
spec:
  backend: sealedSecrets
  sealedSecrets:
    controllerNamespace: sealed-secrets

Behavior ​

  • ESO ⇒ the operator ensures the External Secrets Operator (provenance-aware), waits for its CRDs to be Established, then applies a namespacedSecretStore and the configured ExternalSecrets. A namespaced store (not a ClusterSecretStore) keeps each namespace's credentials isolated.
  • Sealed Secrets ⇒ the operator ensures the Sealed Secrets controller and reconciles the referenced SealedSecrets.

Workloads that set secretsRef reconcile only once that SecretsManagement is ready.

Status ​

{ phase, backend, storeReady, materializedSecrets[], conditions, observedGeneration }.

For every ESO backend, conditions carries SecretStoreReady: whether ESO can reach and sign in to the secret store. When ESO reports that it cannot, the condition — and Ready, since nothing can sync — is False with ESO's own cause, e.g. x509: certificate signed by unknown authority (set caSecretRef), permission denied (check the Vault role and policy) or a wrong Vault namespace.

For an Azure Key Vault + WorkloadIdentity backend, conditions also carries FederatedCredentialReady — the passive signal for whether the Azure federated identity credential exists for the ESO ServiceAccount subject. See Secrets operations → the federated credential.

Open core under AGPL-3.0. Enterprise components are proprietary and license-gated.