Gestione dei secret
La regola: nessun secret fornito da una persona compare mai inline in una custom resource, in un valore di chart o in un template. Le credenziali raggiungono la piattaforma attraverso uno di tre percorsi, selezionato e configurato dalla risorsa SecretsManagement.
Le tre fonti dei secret
- External Secrets (ESO) — recupera i secret da uno store esterno (Azure Key Vault per impostazione predefinita, ma qualsiasi provider ESO) e li riporta in Secret Kubernetes namespaced.
- Sealed Secrets — manifest cifrati a riposo, decifrati all'interno del cluster.
- Generati dall'operatore — credenziali create dall'operatore stesso (virtual key di LiteLLM, chiavi di callback di Langfuse, password dei datastore). Memorizzate come Secret Kubernetes posseduti, con owner reference per la garbage collection; puoi convertirli manualmente in ESO/Sealed.
SecretsManagement è obbligatoria e seleziona il backend (1) o (2). I workload si collegano a una SecretsManagement dello stesso namespace tramite secretsRef e fanno riferimento ai nomi dei Secret materializzati.
Provider ESO
L'operatore effettua il provisioning di un SecretStore namespaced (non di un ClusterSecretStore), mantenendo isolate le credenziali di ciascun namespace.
Azure Key Vault (il predefinito in produzione)
- Workload Identity (
authType: WorkloadIdentity) — produzione su AKS. Il ServiceAccount di ogni workload consumatore necessita della labelazure.workload.identity/use: "true"e di una federated identity credential in Azure. L'operatore imposta le label di pod/SA tramite i valori di chart che genera. - Service Principal (
authType: ServicePrincipal) — funziona ovunque, anche su cluster non AKS e su Kind (che non dispone della federazione OIDC per Workload Identity). ForniscitenantID+authSecretRef.{clientID, clientSecret}.
apiVersion: external-secrets.io/v1
kind: SecretStore
metadata: { name: azure-keyvault, namespace: forge-gateway }
spec:
provider:
azurekv:
authType: WorkloadIdentity
vaultUrl: https://kvforgepltprod.vault.azure.net/
serviceAccountRef: { name: forge-sa }La federated credential è un passaggio manuale obbligatorio
L'operatore configura il lato Kubernetes (il ServiceAccount con le label, il SecretStore, gli ExternalSecret). Non chiama Azure, quindi non può creare la federated identity credential che consente a quel ServiceAccount di scambiare il proprio token con la managed identity della piattaforma. Devi crearne una per ogni (namespace, serviceAccount) — l'issuer OIDC di AKS richiede un subject esattamente corrispondente e non supporta wildcard:
az identity federated-credential create \
--name "eso-<namespace>-<serviceAccount>" \
--identity-name "<managed-identity>" \
--resource-group "<resource-group>" \
--issuer "$(az aks show -g <resource-group> -n <cluster> --query oidcIssuerProfile.issuerUrl -o tsv)" \
--subject "system:serviceaccount:<namespace>:<serviceAccount>" \
--audiences "api://AzureADTokenExchange"Finché non esiste, lo scambio di token di ESO fallisce con l'errore Entra AADSTS70021: No matching federated identity record found …. L'operatore osserva lo status del SecretStore di ESO e lo riporta nella condition FederatedCredentialReady della SecretsManagement:
Waiting— ESO non ha ancora validato lo store.False/MissingFederatedCredential— è stato rilevato l'erroreAADSTS70021; il messaggio indica il subject esatto per cui creare una credential.True— ESO si è autenticato; la credential è presente.
Ready indica comunque che il backend è stato collegato; FederatedCredentialReady è il segnale specifico per la relazione di fiducia lato Azure. (Con authType: ServicePrincipal non serve alcuna federated credential e questa condition non viene impostata.)
HashiCorp Vault
Consente di eseguire l'intero percorso dei secret all'interno del cluster (nessun Key Vault cloud, Service Principal o federated identity). Per KV-v2, ogni valore di keys è il percorso del secret e il nome della chiave Kubernetes è la proprietà al suo interno.
Qualsiasi provider (passthrough grezzo)
provider: raw inserisce il blocco ESO spec.provider così com'è, quindi è supportato ogni provider ESO — AWS, GCP, IBM, Akeyless, 1Password, Kubernetes e qualsiasi provider che ESO aggiungerà in futuro — senza modifiche all'operatore. La forma externalSecrets[].data espone il remoteRef ESO completo (remoteKey / property / version).
Vedi il riferimento SecretsManagement per la struttura esatta dei campi ed esempi per ciascun provider.
Matrice delle chiavi Azure Key Vault
Quando usi Azure Key Vault, questi sono i nomi dei secret che l'operatore si aspetta (ripresi dai precedenti valori di chart della piattaforma). SecretsManagement.eso.externalSecrets[].keys mappa le chiavi dei Secret Kubernetes → i nomi dei secret in Key Vault.
Gateway (forge-gateway)
| Secret Kubernetes / chiave | Secret Key Vault | Usato per |
|---|---|---|
model-credentials / OPENAI_API_KEY | gateway-foundry-api-key | Autenticazione verso il modello upstream |
model-credentials / ANTHROPIC_API_KEY | gateway-foundry-api-key | Autenticazione verso il modello upstream |
litellm-db-credentials / DATABASE_URL | (composto a partire dal PostgresCluster) | DB di LiteLLM |
entra-sso-credentials / client-id,client-secret | gateway-entra-sso-client-id / -secret | SSO della UI (con enableEntraSSO) |
litellm-license / license-key | gateway-litellm-license-key | LiteLLM enterprise |
ChatUI (forge-ui)
| Secret Kubernetes / chiave | Secret Key Vault |
|---|---|
librechat-credentials-env / CREDS_KEY | chatui-creds-key |
librechat-credentials-env / CREDS_IV | chatui-creds-iv |
librechat-credentials-env / JWT_SECRET | chatui-jwt-secret |
librechat-credentials-env / JWT_REFRESH_SECRET | chatui-jwt-refresh-secret |
librechat-credentials-env / LITELLM_API_KEY | chatui-litellm-api-key (oppure una virtual key generata automaticamente, se in licenza) |
forge-ui-basic-auth / htpasswd | chatui-basic-auth-htpasswd |
Per ChatUI, le credenziali di MongoDB e Meilisearch non provengono da Key Vault. Sono possedute dalle risorse datastore: la master key di Meilisearch dalla MeilisearchInstance, e la password SCRAM di Mongo + il MONGO_URI per database dal MongoCluster.
Langfuse (forge-langfuse)
nextauth-secret + salt vengono generati e ruotati automaticamente dal langfuse-operator in un Secret <instance>-generated-secrets — non ricavarli da Key Vault se non per sovrascriverli. Le credenziali dei datastore provengono dai Secret materializzati delle risorse datastore referenziate (più Key Vault per i datastore esterni).
Secret generati dall'operatore
- Virtual key di LiteLLM (auto-wiring di ChatUI) e chiavi master/salt (
autoGenerate: true). - Password dei ruoli CloudNativePG (esposte come Secret di credenziali per database).
- La password SCRAM del
MongoClustere i SecretMONGO_URIper database. - Il Secret della master key della
MeilisearchInstance.
Tutti i Secret posseduti dall'operatore ricevono owner reference per la garbage collection e una label managed-by=navique-ai-core-operator.
Rotazione
Con la funzionalità credential-rotation e un blocco rotation per risorsa (intervallo predefinito di 90 giorni), l'operatore ruota le credenziali che possiede — le virtual key di LiteLLM e le password generate di ClickHouse / Redis / Mongo / Meilisearch — aggiornando l'annotation core.navique.com/rotated-at.
Fuori ambito (ruotati dai rispettivi sistemi): i secret di Key Vault (ruotali in KV; ESO li risincronizza) e le password dei ruoli gestite da CNPG (ruotale tramite CNPG). L'operatore non ruota mai credenziali che non possiede. Senza la funzionalità, il blocco rotation viene ignorato.
Abbandonare i secret in chiaro
Ruota i secret precedentemente committati
I precedenti chart Helm della piattaforma committavano secret reali in git (chiavi API dei modelli, client secret dell'SSO Entra, licenza LiteLLM, URL dei database, secret di Langfuse). Questi sono compromessi per definizione e devono essere ruotati nell'ambito della migrazione — non copiarne nessuno nell'operatore. Ruotali tutti in Key Vault, ricavali tramite ESO ed elimina la cronologia git se possibile.
Cosa non fare
- Nessun valore di secret negli esempi — usa segnaposto e una nota per popolare il vault.
- Nessun logging dei secret. Oscura le stringhe di connessione negli eventi e nelle condition.
- Nessun secret incorporato nell'immagine dell'operatore (la chiave pubblica della licenza va bene; mai la chiave privata).