Pular para o conteúdo
DevSecOps 13 min read

Secrets Management: HashiCorp Vault e External Secrets no Kubernetes

Aprenda a gerenciar secrets de forma segura em Kubernetes usando HashiCorp Vault, External Secrets Operator, e boas práticas de segurança.

Por Equipe Integr8 04/01/2025

O Problema dos Secrets

Secrets mal gerenciados são uma das principais causas de breaches de segurança. Senhas em código, tokens em variáveis de ambiente, chaves em ConfigMaps - são práticas que colocam toda a organização em risco.

⚠️Estatística

Em 2024, 15% dos breaches envolveram credenciais expostas ou mal gerenciadas. O tempo médio para detectar um leak de secret é de 327 dias.

Evolução do Secrets Management

    HashiCorp Vault

    Vault é a solução mais completa para secrets management, oferecendo secrets estáticos, dinâmicos, PKI, e muito mais.

    Arquitetura do Vault

    Vault: Secret Engines, Auth Methods e Storage Backend
    100%
    Arquitetura HashiCorp Vault

    Vault: Secret Engines, Auth Methods e Storage Backend

    Instalando Vault no Kubernetes

    # Adicionar repo Helm
    helm repo add hashicorp https://helm.releases.hashicorp.com
    
    # Instalar Vault em modo HA
    helm install vault hashicorp/vault \
      --namespace vault \
      --create-namespace \
      --set server.ha.enabled=true \
      --set server.ha.raft.enabled=true \
      --set server.ha.replicas=3 \
      --set ui.enabled=true
    
    # Inicializar Vault (apenas uma vez!)
    kubectl exec -n vault vault-0 -- vault operator init \
      -key-shares=5 \
      -key-threshold=3 \
      -format=json > vault-init.json
    
    # Unseal (repetir para cada réplica)
    kubectl exec -n vault vault-0 -- vault operator unseal $KEY1
    kubectl exec -n vault vault-0 -- vault operator unseal $KEY2
    kubectl exec -n vault vault-0 -- vault operator unseal $KEY3

    Configurando Kubernetes Auth

    # Habilitar auth method Kubernetes
    vault auth enable kubernetes
    
    # Configurar com service account do Vault
    vault write auth/kubernetes/config \
      kubernetes_host="https://$KUBERNETES_PORT_443_TCP_ADDR:443" \
      token_reviewer_jwt="$(cat /var/run/secrets/kubernetes.io/serviceaccount/token)" \
      kubernetes_ca_cert=@/var/run/secrets/kubernetes.io/serviceaccount/ca.crt
    
    # Criar policy para aplicação
    vault policy write myapp-policy - <<EOF
    path "secret/data/myapp/*" {
      capabilities = ["read"]
    }
    path "database/creds/myapp-role" {
      capabilities = ["read"]
    }
    EOF
    
    # Criar role para Kubernetes
    vault write auth/kubernetes/role/myapp \
      bound_service_account_names=myapp \
      bound_service_account_namespaces=production \
      policies=myapp-policy \
      ttl=1h

    Secrets Dinâmicos para Database

    # Habilitar database secrets engine
    vault secrets enable database
    
    # Configurar conexão PostgreSQL
    vault write database/config/postgres \
      plugin_name=postgresql-database-plugin \
      allowed_roles="myapp-role" \
      connection_url="postgresql://{{username}}:{{password}}@postgres:5432/mydb?sslmode=disable" \
      username="vault_admin" \
      password="admin_password"
    
    # Criar role para gerar credenciais dinâmicas
    vault write database/roles/myapp-role \
      db_name=postgres \
      creation_statements="CREATE ROLE \"{{name}}\" WITH LOGIN PASSWORD '{{password}}' VALID UNTIL '{{expiration}}'; GRANT SELECT, INSERT, UPDATE ON ALL TABLES IN SCHEMA public TO \"{{name}}\";" \
      default_ttl="1h" \
      max_ttl="24h"
    
    # Obter credenciais dinâmicas
    vault read database/creds/myapp-role
    # Retorna: username=v-kubernetes-myapp-xxxx, password=yyyy (válido por 1h)
    Benefício de Dynamic Secrets

    Se um secret dinâmico for comprometido, ele expira automaticamente. Não há necessidade de rotação manual - cada request gera credenciais únicas.

    External Secrets Operator

    ESO sincroniza secrets de providers externos (Vault, AWS Secrets Manager, etc.) para Kubernetes Secrets.

    Instalação

    helm repo add external-secrets https://charts.external-secrets.io
    
    helm install external-secrets external-secrets/external-secrets \
      --namespace external-secrets \
      --create-namespace

    Configurando SecretStore para Vault

    # ClusterSecretStore - disponível em todos os namespaces
    apiVersion: external-secrets.io/v1beta1
    kind: ClusterSecretStore
    metadata:
      name: vault-backend
    spec:
      provider:
        vault:
          server: "https://vault.vault.svc:8200"
          path: "secret"
          version: "v2"
          auth:
            kubernetes:
              mountPath: "kubernetes"
              role: "external-secrets"
              serviceAccountRef:
                name: "external-secrets"
                namespace: "external-secrets"

    Sincronizando Secrets

    # ExternalSecret - sincroniza secret específico
    apiVersion: external-secrets.io/v1beta1
    kind: ExternalSecret
    metadata:
      name: myapp-secrets
      namespace: production
    spec:
      refreshInterval: "15m"
      secretStoreRef:
        kind: ClusterSecretStore
        name: vault-backend
    
      target:
        name: myapp-secrets
        creationPolicy: Owner
    
      data:
        # Secret estático do KV
        - secretKey: database-password
          remoteRef:
            key: secret/data/myapp/production
            property: database_password
    
        # Pode mapear múltiplos campos
        - secretKey: api-key
          remoteRef:
            key: secret/data/myapp/production
            property: api_key
    
    ---
    # Usando no Deployment
    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: myapp
    spec:
      template:
        spec:
          containers:
            - name: myapp
              envFrom:
                - secretRef:
                    name: myapp-secrets

    Dynamic Secrets com ESO

    # ExternalSecret para database credentials dinâmicas
    apiVersion: external-secrets.io/v1beta1
    kind: ExternalSecret
    metadata:
      name: db-credentials
      namespace: production
    spec:
      refreshInterval: "30m"  # Refresh antes do TTL expirar
      secretStoreRef:
        kind: ClusterSecretStore
        name: vault-backend
    
      target:
        name: db-credentials
        creationPolicy: Owner
        template:
          type: Opaque
          data:
            DATABASE_URL: "postgresql://{{ .username }}:{{ .password }}@postgres:5432/mydb"
    
      dataFrom:
        - extract:
            key: database/creds/myapp-role

    Sealed Secrets para GitOps

    Para cenários onde você quer commitar secrets no Git:

    # Instalar kubeseal
    brew install kubeseal
    
    # Instalar Sealed Secrets controller
    kubectl apply -f https://github.com/bitnami-labs/sealed-secrets/releases/download/v0.24.0/controller.yaml
    
    # Criar sealed secret
    kubectl create secret generic myapp-secret \
      --dry-run=client \
      --from-literal=password=supersecret \
      -o yaml | kubeseal --format yaml > sealed-secret.yaml
    
    # Aplicar (controller descriptografa e cria o Secret real)
    kubectl apply -f sealed-secret.yaml
    # sealed-secret.yaml (pode ir para Git!)
    apiVersion: bitnami.com/v1alpha1
    kind: SealedSecret
    metadata:
      name: myapp-secret
      namespace: production
    spec:
      encryptedData:
        password: AgBy8hCi...encrypted...data==

    Comparativo de Soluções

    AspectoK8s SecretsSealed SecretsExternal SecretsVault Direct
    GitOps⚠️
    RotaçãoManualManualAutomáticaAutomática
    AuditoriaBásicaBásicaVia provider✅ Completa
    Dynamic
    ComplexidadeBaixaMédiaMédiaAlta

    Boas Práticas

    🔄

    Rotação Automática

    Configure TTL curto e refresh automático. Nunca rotação manual.

    📊

    Auditoria

    Habilite audit logs no Vault. Saiba quem acessou o quê.

    🔐

    Least Privilege

    Cada aplicação acessa apenas seus próprios secrets.

    🚫

    Nunca em Logs

    Configure aplicações para nunca logar secrets.

    💡Recomendação

    Para a maioria dos casos, External Secrets Operator + Vault é a combinação ideal: simplicidade do ESO com poder do Vault.


    Quer implementar secrets management seguro na sua organização? Fale com nossos especialistas em DevSecOps.