Armazenamento seguro de segredos: variáveis de ambiente vs vault
1. O cenário de risco: por que segredos vazam?
1.1. Exemplos reais de vazamentos por má gestão
Em 2019, um engenheiro da Uber commitou acidentalmente credenciais AWS em um repositório público, expondo dados de 57 milhões de usuários. Casos como esse são recorrentes: segredos vazam em logs de depuração, arquivos de configuração versionados, pipelines de CI/CD mal configurados e até mesmo em capturas de tela compartilhadas em fóruns.
# Exemplo de vazamento clássico em código-fonte
DB_PASSWORD=supersecret123
API_KEY=sk-abc123def456
1.2. O problema do "secret sprawl" em aplicações modernas
Com a adoção de microsserviços, containers e múltiplos ambientes (dev, staging, produção), o número de segredos cresce exponencialmente. Uma aplicação típica pode ter dezenas de chaves de API, senhas de banco, tokens JWT e certificados TLS. Esse espalhamento dificulta o rastreamento, a rotação e a revogação.
1.3. Diferença entre configuração não sensível e segredo crítico
Configurações como PORT=3000 ou LOG_LEVEL=debug não são sensíveis. Já DB_PASSWORD, JWT_SECRET e AWS_ACCESS_KEY são segredos críticos. A confusão entre esses dois tipos leva a práticas inseguras, como versionar arquivos .env ou hardcodear credenciais.
2. Variáveis de ambiente: o padrão-ouro (com ressalvas)
2.1. Como usar variáveis de ambiente corretamente
Variáveis de ambiente são a forma mais básica e amplamente adotada para configurar aplicações. O uso correto envolve:
# .env (NUNCA versionar!)
DATABASE_URL=postgres://user:pass@localhost:5432/mydb
REDIS_PASSWORD=redis123
Para Docker:
# docker-compose.yml
services:
app:
environment:
- DATABASE_URL=${DATABASE_URL}
- REDIS_PASSWORD=${REDIS_PASSWORD}
2.2. Limitações: persistência em logs, processos filhos e debugging
Variáveis de ambiente vazam facilmente:
- São capturadas em logs de erro (console.log(process.env.DATABASE_URL))
- Herdadas por processos filhos, expondo segredos a subprocessos
- Visíveis em comandos como ps aux e arquivos /proc/[pid]/environ
- Persistem em dumps de memória e core files
2.3. Boas práticas: rotação manual, criptografia em repouso e .gitignore
# .gitignore (obrigatório!)
.env
.env.*
*.env.local
# Rotação manual: alterar senhas periodicamente e reiniciar serviços
# Criptografia em repouso: usar ferramentas como sops ou git-crypt
3. Vaults de segredos: a evolução necessária
3.1. O que é um vault
Um vault é um sistema centralizado para armazenar, acessar e gerenciar segredos. Os principais exemplos são:
- HashiCorp Vault: open-source, multiplataforma, suporta múltiplos backends
- AWS Secrets Manager: integrado ao ecossistema AWS, rotação automática
- Azure Key Vault: para aplicações no Azure, com HSM opcional
- Google Secret Manager: nativo do GCP
3.2. Ciclo de vida do segredo
Um vault gerencia o ciclo completo:
1. Criação: segredo é armazenado criptografado
2. Acesso: autenticação via token, JWT ou certificado
3. Rotação: substituição automática em intervalos definidos
4. Expiração: TTL (Time-To-Live) para leases temporários
5. Revogação: remoção imediata do acesso
3.3. Vantagens: auditoria, acesso dinâmico e isolamento por ambiente
- Auditoria: todo acesso é logado (quem, quando, qual segredo)
- Acesso dinâmico: segredos são gerados sob demanda com permissões mínimas
- Isolamento: ambientes diferentes usam paths diferentes (
secret/dev/db,secret/prod/db)
4. Comparação prática: variáveis de ambiente vs vault
4.1. Cenário 1: Aplicação monolítica em servidor único
Para um app simples rodando em um VPS, variáveis de ambiente com .env criptografado são suficientes. A complexidade de um vault não se justifica.
4.2. Cenário 2: Microsserviços com orquestração (Kubernetes)
Em Kubernetes, variáveis de ambiente via Secrets ainda são comuns, mas vaults oferecem vantagens:
# Kubernetes Secret (limitado)
apiVersion: v1
kind: Secret
metadata:
name: db-credentials
type: Opaque
data:
password: c3VwZXJzZWNyZXQxMjM= # base64 (NÃO é segurança!)
# Vault injector (recomendado)
# Sidecar que injeta segredos diretamente no pod
4.3. Matriz de decisão: custo, complexidade e segurança
| Critério | Variáveis de ambiente | Vault |
|---|---|---|
| Custo | Gratuito | Custo de infraestrutura |
| Complexidade | Baixa | Média a alta |
| Segurança | Média | Alta |
| Rotação automática | Manual | Automática |
| Auditoria | Inexistente | Completa |
| Ideal para | Protótipos, apps pequenos | Produção, compliance |
5. Implementando vault na prática (exemplo com HashiCorp Vault)
5.1. Setup mínimo: iniciar servidor Vault em dev mode
# Terminal 1: Iniciar Vault em modo desenvolvimento (NUNCA em produção!)
$ vault server -dev
# Terminal 2: Configurar ambiente
$ export VAULT_ADDR='http://127.0.0.1:8200'
$ export VAULT_TOKEN='root-token'
# Criar um segredo
$ vault kv put secret/dev/db password=supersecret123
5.2. Injetando segredos via API: exemplo em Python
# app.py
import requests
import os
VAULT_ADDR = os.getenv('VAULT_ADDR', 'http://127.0.0.1:8200')
VAULT_TOKEN = os.getenv('VAULT_TOKEN')
def get_secret(path):
headers = {'X-Vault-Token': VAULT_TOKEN}
response = requests.get(f'{VAULT_ADDR}/v1/{path}', headers=headers)
response.raise_for_status()
return response.json()['data']['data']
# Uso
secrets = get_secret('secret/dev/db')
db_password = secrets['password']
print(f'Conectando ao banco com senha: {db_password}')
5.3. Integração com CI/CD: evitando segredos hardcoded em pipelines
# .github/workflows/deploy.yml
jobs:
deploy:
steps:
- name: Autenticar no Vault
run: |
vault login -method=token token=${{ secrets.VAULT_TOKEN }}
- name: Obter segredos
run: |
vault kv get -field=password secret/prod/db > /tmp/db_pass
echo "DB_PASSWORD=$(cat /tmp/db_pass)" >> $GITHUB_ENV
6. Armadilhas comuns e como evitá-las
6.1. Cache indevido de segredos na memória da aplicação
Nunca armazene segredos em variáveis globais ou caches de longa duração. Sempre busque sob demanda ou use TTL curto.
# ERRADO
secrets_cache = {}
def get_secret(name):
if name in secrets_cache:
return secrets_cache[name] # Nunca expire!
...
# CORRETO
def get_secret(name):
# Buscar do vault a cada requisição ou usar cache com TTL
return vault_client.read_secret(name, ttl=60) # Expira em 60s
6.2. Vault como ponto único de falha (HA e disaster recovery)
Configure Vault em cluster com alta disponibilidade e backups regulares. Sempre tenha um plano de disaster recovery.
# Configuração mínima de HA no Vault
storage "raft" {
path = "/vault/data"
node_id = "node1"
}
cluster_addr = "https://vault-1.example.com:8201"
api_addr = "https://vault-1.example.com:8200"
6.3. Combinação perigosa: vault + variáveis de ambiente sem criptografia
Nunca exporte segredos do vault para variáveis de ambiente sem antes criptografar o arquivo de configuração.
# PERIGOSO
export $(vault kv get -format=json secret/prod/db | jq -r '.data.data | to_entries[] | .key + "=" + .value')
# SEGURO
# Usar injector que injeta diretamente no processo, sem expor via env
7. Conclusão e recomendações finais
7.1. Quando ficar com variáveis de ambiente
- Projetos pessoais ou protótipos
- Aplicações monolíticas com até 3-5 segredos
- Times pequenos sem requisitos de compliance
- Ambientes de desenvolvimento local
7.2. Quando migrar para um vault
- Mais de 10 segredos gerenciados manualmente
- Múltiplos ambientes e times
- Requisitos de auditoria (SOC2, PCI-DSS, HIPAA)
- Microsserviços com rotação frequente de credenciais
- Integração com Kubernetes ou Docker Swarm
7.3. Checklist de segurança: o mínimo que todo dev deve implementar hoje
[ ] NUNCA versionar segredos (use .gitignore)
[ ] Usar variáveis de ambiente com criptografia em repouso
[ ] Implementar rotação periódica de senhas e chaves
[ ] Auditoria básica: quem acessou o quê e quando
[ ] Isolar segredos por ambiente (dev/staging/prod)
[ ] Evitar cache de longa duração de segredos
[ ] Documentar o processo de revogação de emergência
A segurança de segredos não é opcional — é uma responsabilidade fundamental de todo desenvolvedor. Comece pequeno, mas comece hoje.
Referências
- HashiCorp Vault Documentation — Documentação oficial completa do HashiCorp Vault, incluindo instalação, configuração e melhores práticas.
- AWS Secrets Manager User Guide — Guia oficial da AWS para gerenciamento de segredos com rotação automática.
- OWASP Secrets Management Cheat Sheet — Guia de referência da OWASP sobre práticas seguras de gerenciamento de segredos.
- 12 Factor App: Config — Princípio clássico sobre armazenamento de configuração em variáveis de ambiente.
- Kubernetes Secrets vs Vault: When to Use Which — Documentação oficial sobre integração do Vault com Kubernetes e diferenças em relação aos Secrets nativos.
- GitHub Secret Scanning Documentation — Como o GitHub detecta e alerta sobre vazamentos de segredos em repositórios.
- Mozilla's Secrets Management Guidelines — Diretrizes práticas de gerenciamento de segredos usadas internamente pela Mozilla.