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.
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
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)
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
| Aspecto | K8s Secrets | Sealed Secrets | External Secrets | Vault Direct |
|---|---|---|---|---|
| GitOps | ❌ | ✅ | ✅ | ⚠️ |
| Rotação | Manual | Manual | Automática | Automática |
| Auditoria | Básica | Básica | Via provider | ✅ Completa |
| Dynamic | ❌ | ❌ | ✅ | ✅ |
| Complexidade | Baixa | Média | Média | Alta |
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.
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.