Pular para o conteúdo principal

External Secrets Operator (ESO) compat layer

A partir da v4.5, o CipherVault expõe endpoints compatíveis com o External Secrets Operator (ESO) usando o Webhook provider. Isso permite quem já usa ESO em produção adotar CipherVault sem trocar de operator.

Se você está começando do zero em K8s, prefira o Kubernetes Operator nativo ou o Guardian — funcionalidades mais ricas. O ESO compat é para migração suave.

Endpoints

GET /eso/secrets/by-id?id=<secret_id> Por UUID
GET /eso/secrets/by-name?vault=<v>&name=<n> Por nome
GET /eso/vault/<vault_name> Listagem de secrets do vault

Auth via mTLS + DPoP (AppConnection padrão).

Setup — ESO SecretStore (Webhook)

apiVersion: external-secrets.io/v1beta1
kind: SecretStore
metadata:
name: ciphervault
namespace: billing
spec:
provider:
webhook:
url: "https://cv.acme.com.br/eso/secrets/by-name?vault=producao&name={{ .remoteRef.key }}"
headers:
X-Client-Id: "{{ .clientCreds.client_id }}"
secrets:
- name: clientCreds
secretRef:
name: cv-app-credentials
result:
jsonPath: "$.value"
caBundle: <PEM da CA do CV>

ExternalSecret

apiVersion: external-secrets.io/v1beta1
kind: ExternalSecret
metadata:
name: stripe-key
namespace: billing
spec:
refreshInterval: 5m
secretStoreRef:
name: ciphervault
kind: SecretStore
target:
name: stripe-credentials
type: Opaque
data:
- secretKey: STRIPE_KEY
remoteRef:
key: api/stripe/secret_key

Result: ESO cria K8s Secret stripe-credentials no namespace billing, populado do CV, atualizado a cada 5min.

Response format

Endpoint retorna JSON simples:

{
"id": "sec_01HXY...",
"name": "secret_key",
"vault": "producao",
"path": "api/stripe/secret_key",
"type": "api_key",
"value": "sk_live_...",
"version": 7,
"updated_at": "2026-05-12T13:00:00Z"
}

ESO extrai $.value via jsonPath configurado no SecretStore.

Auth via AppConnection

ESO conecta com X-Client-Id + X-Client-Secret no header. Para mTLS (recomendado), configure ESO com caBundle + cert do client:

spec:
provider:
webhook:
url: "https://cv.acme.com.br/eso/secrets/by-name?..."
tlsConfig:
caCert: ...
clientCert: ...
clientKey: ...

Diferenças vs. Operator nativo

CapabilityESO compatK8s OperatorGuardian
Materializar K8s Secret
Refresh automático
Dynamic Secrets lease✅ (CipherVaultLease)
Drift detection
Validating webhook
Auto-create namespace✅ (Federation)
Multi-cluster federation✅ (Federation)✅ (Phase 4)
Workload identity (SPIFFE)parcial

Migração ESO → Operator nativo

Quando você quiser sair do ESO:

# 1. Manifests novos com CipherVaultSecret CRDs (Operator nativo)
kubectl apply -f new-crds.yaml

# 2. Esperar Operator materializar (mesma resource name)
kubectl wait --for=condition=Ready CipherVaultSecret/stripe-key -n billing --timeout=5m

# 3. Remover ExternalSecret
kubectl delete externalsecret stripe-key -n billing

# 4. ESO SecretStore pode ser removido quando todos ExternalSecrets foram migrados
helm uninstall external-secrets-operator -n external-secrets-system

Limitações

  • Sem Push mode — ESO permite pushar K8s Secrets para o backend; compat layer não suporta
  • Sem multi-secret single-call — ESO dataFrom que busca múltiplos secrets de uma vez não é otimizado; use path aggregator do CV diretamente para isso
  • Audit log registra cada chamada — alto volume com refreshInterval curto pode encher SIEM. Use refreshInterval >= 5m

Boas práticas

  • AppConnection dedicada para ESO — escopo eso:read apenas
  • refreshInterval entre 5min e 1h — abaixo disso desperdiça API quota
  • Migração planejada — se você é greenfield, comece direto com Operator nativo; se brownfield com ESO, use compat layer como ponte