Secrets management externo: Vault, Sealed Secrets ou External Secrets

1. Por que Secrets Management Externo no Kubernetes?

1.1. Limitações do Secrets nativo do Kubernetes

O recurso Secret nativo do Kubernetes é frequentemente mal compreendido como uma solução segura. Na realidade, ele apenas codifica dados em base64 — não criptografa. Qualquer pessoa com acesso ao etcd ou permissão get no namespace consegue ler os valores. Além disso, não há rotação automática de segredos, nem auditoria de acesso granular. Em clusters multi-tenant, a exposição acidental de segredos em logs ou manifests versionados no Git é um risco constante.

1.2. Requisitos de segurança e compliance

Normas como GDPR, HIPAA e PCI-DSS exigem criptografia em repouso, rotação periódica e logs de acesso a dados sensíveis. O Secrets nativo falha em todos esses pontos. Ferramentas externas preenchem essas lacunas com criptografia forte, políticas de acesso e integração com sistemas de auditoria.

1.3. Visão geral da arquitetura

Três arquiteturas dominam o cenário:
- Sidecar: um container auxiliar injeta segredos no pod (ex: Vault Agent Injector)
- Operador: um controller Kubernetes reconcilia CRDs para sincronizar segredos (ex: External Secrets Operator)
- Controller nativo: um operador que decripta segredos selados no cluster (ex: Sealed Secrets)

2. HashiCorp Vault: O Padrão Ouro para Segredos

2.1. Conceitos fundamentais

Vault opera com caminhos lógicos (secret/data/myapp), políticas HCL que definem permissões de leitura/escrita, e tokens de curta duração. A autenticação Kubernetes usa o ServiceAccount do pod para gerar tokens temporários, eliminando a necessidade de credenciais estáticas.

2.2. Integração com Kubernetes

O Vault Agent Injector (sidecar) intercepta a criação de pods e injeta um container Vault Agent que renderiza templates de configuração com segredos. Alternativamente, o CSI Provider monta segredos como volumes efêmeros, ideais para workloads que não suportam injeção via variáveis de ambiente.

2.3. Prós e Contras

Prós: rotação dinâmica de segredos (bancos de dados, certificados TLS), audit logging completo, suporte multi-cloud e on-premises. Contras: complexidade operacional elevada (manutenção do cluster Vault, unseal keys, HA), curva de aprendizado íngreme, custo de infraestrutura adicional.

3. Sealed Secrets: Criptografia Git-Nativa com Bitnami

3.1. Funcionamento

Um controller no cluster possui um par de chaves RSA. O cliente kubeseal usa a chave pública para criptografar um Secret em um SealedSecret — um recurso Kubernetes que pode ser versionado no Git com segurança. Apenas o controller, com a chave privada, consegue decriptá-lo.

3.2. Fluxo de trabalho

# 1. Criar um Secret comum
kubectl create secret generic mysecret --from-literal=password=supersecret -n myapp --dry-run=client -o yaml > secret.yaml

# 2. Selar com a chave pública do cluster
kubeseal --format yaml < secret.yaml > sealed-secret.yaml

# 3. Commit do SealedSecret no Git
git add sealed-secret.yaml && git commit -m "Add sealed secret"

# 4. O controller no cluster decripta automaticamente e cria o Secret
kubectl apply -f sealed-secret.yaml

3.3. Casos de uso

Ideal para ambientes GitOps puros (ArgoCD, Flux) onde todo o estado deve estar no repositório. Funciona offline, sem dependência de provedores externos. Excelente para dev/test e clusters pequenos/médios.

4. External Secrets Operator: Ponte para Provedores de Nuvem

4.1. Arquitetura

O operador introduz dois CRDs principais:
- SecretStore: configura a conexão com o provedor externo (AWS Secrets Manager, Azure Key Vault, GCP Secret Manager, Vault)
- ExternalSecret: mapeia segredos do provedor para Secrets Kubernetes

O operador reconcilia continuamente, sincronizando alterações no provedor externo para o cluster.

4.2. Exemplo de configuração

apiVersion: external-secrets.io/v1beta1
kind: SecretStore
metadata:
  name: aws-secrets-store
spec:
  provider:
    aws:
      service: SecretsManager
      region: us-east-1
      auth:
        secretRef:
          accessKeyIDSecretRef:
            name: aws-creds
            key: access-key
          secretAccessKeySecretRef:
            name: aws-creds
            key: secret-key
---
apiVersion: external-secrets.io/v1beta1
kind: ExternalSecret
metadata:
  name: myapp-secret
spec:
  refreshInterval: 1h
  secretStoreRef:
    name: aws-secrets-store
    kind: SecretStore
  target:
    name: myapp-secret
  data:
    - secretKey: db_password
      remoteRef:
        key: /prod/myapp/database
        property: password

4.3. Vantagens

Sincronização automática com polling configurável, rotação centralizada no provedor, integração nativa com GitOps (o ExternalSecret é versionado, não o valor). Suporta múltiplos provedores simultaneamente.

5. Comparação Técnica e Critérios de Escolha

5.1. Matriz de decisão

Critério Vault Sealed Secrets External Secrets
Criptografia Forte Forte Forte (provedor)
Rotação automática Sim Não Sim (polling)
GitOps nativo Parcial Sim Sim
Latência de injeção Baixa Zero Média (polling)
Complexidade operacional Alta Baixa Média
Custo de infraestrutura Alto Baixo Médio

5.2. Cenários típicos

  • Startup / Projeto pessoal: Sealed Secrets — simples, sem dependências externas
  • Enterprise / Regulamentado: Vault — compliance, auditoria, rotação dinâmica
  • Multi-cloud / Híbrido: External Secrets — unifica provedores de nuvem

6. Implementação Prática com Exemplos

6.1. Exemplo 1: Sealed Secrets com ArgoCD

# Instalar controller
helm repo add sealed-secrets https://bitnami-labs.github.io/sealed-secrets
helm install sealed-secrets sealed-secrets/sealed-secrets -n kube-system

# Selar segredo para produção
kubeseal --controller-namespace kube-system \
  --controller-name sealed-secrets \
  --format yaml < secret-prod.yaml > sealed-prod.yaml

# Aplicar via ArgoCD (o Application aponta para o repositório Git)
kubectl apply -f sealed-prod.yaml

6.2. Exemplo 2: External Secrets com AWS Secrets Manager

# Instalar operador
helm repo add external-secrets https://charts.external-secrets.io
helm install external-secrets external-secrets/external-secrets -n external-secrets

# Configurar SecretStore (assumindo credenciais AWS em secret)
cat <<EOF | kubectl apply -f -
apiVersion: external-secrets.io/v1beta1
kind: SecretStore
metadata:
  name: aws-store
spec:
  provider:
    aws:
      service: SecretsManager
      region: us-east-1
      auth:
        secretRef:
          accessKeyIDSecretRef:
            name: aws-creds
            key: access-key
          secretAccessKeySecretRef:
            name: aws-creds
            key: secret-key
EOF

# Criar ExternalSecret
cat <<EOF | kubectl apply -f -
apiVersion: external-secrets.io/v1beta1
kind: ExternalSecret
metadata:
  name: db-credentials
spec:
  refreshInterval: 30m
  secretStoreRef:
    name: aws-store
    kind: SecretStore
  target:
    name: db-credentials
  data:
    - secretKey: password
      remoteRef:
        key: /prod/database/password
EOF

6.3. Exemplo 3: Vault Injector com sidecar

# Anotação no Deployment para ativar o injector
apiVersion: apps/v1
kind: Deployment
metadata:
  name: myapp
  annotations:
    vault.hashicorp.com/agent-inject: "true"
    vault.hashicorp.com/role: "myapp-role"
    vault.hashicorp.com/agent-inject-secret-db-creds: "secret/data/myapp/db"
    vault.hashicorp.com/agent-inject-template-db-creds: |
      {{- with secret "secret/data/myapp/db" -}}
      export DB_PASSWORD="{{ .Data.data.password }}"
      {{- end }}
spec:
  template:
    metadata:
      annotations:
        vault.hashicorp.com/agent-inject: "true"
    spec:
      serviceAccountName: myapp-sa
      containers:
      - name: myapp
        image: node:18
        command: ["sh", "-c", "source /vault/secrets/db-creds && node app.js"]

7. Boas Práticas e Segurança Avançada

7.1. Gerenciamento de chaves

  • Vault: use KMS (AWS KMS, Azure Key Vault) para auto-unseal, evite unseal keys manuais
  • Sealed Secrets: faça backup da chave mestra (kubeseal --fetch-cert > master.crt) e armazene em cofre seguro
  • External Secrets: as credenciais do SecretStore devem ser rotacionadas periodicamente

7.2. Network Policies

Isole o tráfego do operador de secrets para o provedor externo usando NetworkPolicies:

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: external-secrets-egress
spec:
  podSelector:
    matchLabels:
      app.kubernetes.io/name: external-secrets
  policyTypes:
  - Egress
  egress:
  - to:
    - ipBlock:
        cidr: 10.0.0.0/8  # Intervalo IP do provedor
    ports:
    - protocol: TCP
      port: 443

7.3. Monitoramento e alertas

Configure métricas de falha de decriptação, tempo de sincronização e acesso a segredos. Prometheus + Grafana com dashboards específicos para cada operador.

8. Tendências e Futuro do Secrets Management

8.1. Convergência com Service Mesh

SPIFFE/SPIRE e Istio estão integrando identidade de workload para autorização de acesso a segredos, eliminando a necessidade de tokens estáticos.

8.2. Secrets nativos com KMS Encryption Provider

O Kubernetes 1.24+ permite criptografar Secrets em repouso no etcd usando KMS externo (AWS KMS, Azure Key Vault, GCP Cloud KMS), uma alternativa mais simples que operadores externos.

8.3. Serverless e edge

Ambientes efêmeros como Knative e K3s exigem soluções leves. External Secrets Operator com polling rápido e Sealed Secrets (sem dependência de rede) são as escolhas naturais.

Referências