Secrets management — nunca no código, cofres (Vault, Secrets Manager)
Segredos são qualquer dado que concede acesso a um recurso: senhas, API keys, tokens, certificados, chaves privadas. Quando um segredo vaza, o atacante tem acesso direto ao recurso protegido — banco de dados, serviço de pagamento, conta cloud. O vazamento mais comum ainda é o mais evitável: hardcode no código-fonte commitado em repositório.
Por Que Nunca Hardcodar Segredos
# Ruim — segredo hardcoded
DATABASE_URL = "postgresql://admin:S3cr3t@db.example.com/prod"
API_KEY = "sk-live-abc123xyz"
# Commit + push = segredo exposto para sempre no histórico git
Git guarda o histórico completo. Mesmo que você delete o segredo num commit posterior, ele permanece acessível via git log ou GitHub history. Ferramentas como truffleHog e gitleaks vasculham repositórios públicos e privados em busca exatamente disso.
Alternativas Corretas
1. Variáveis de Ambiente
A solução mais simples para desenvolvimento local e pequenos projetos:
# .env (nunca commite — adicione ao .gitignore)
DATABASE_URL=postgresql://admin:S3cr3t@db.example.com/prod
API_KEY=sk-live-abc123xyz
import os
db_url = os.environ["DATABASE_URL"] # erro explícito se ausente
api_key = os.getenv("API_KEY", "") # default vazio — cuidado
Problema: .env local não escala para múltiplos serviços ou rotação de secrets.
2. HashiCorp Vault
Vault é um cofre de secrets open-source com controle de acesso granular, auditoria e rotação automática.
# Escrever um secret no Vault
vault kv put secret/myapp/db \
url="postgresql://admin:S3cr3t@db.example.com/prod" \
password="S3cr3t"
# Ler no deploy / runtime
vault kv get -field=url secret/myapp/db
import hvac
client = hvac.Client(url="https://vault.example.com", token=os.environ["VAULT_TOKEN"])
secret = client.secrets.kv.read_secret_version(path="myapp/db")
db_url = secret["data"]["data"]["url"]
A aplicação nunca carrega o segredo de arquivo — busca do Vault em runtime com token de curta duração.
3. AWS Secrets Manager
Para workloads na AWS, o Secrets Manager integra com IAM para controle de acesso e suporta rotação automática:
import boto3, json
def get_secret(secret_name: str) -> dict:
client = boto3.client("secretsmanager", region_name="us-east-1")
response = client.get_secret_value(SecretId=secret_name)
return json.loads(response["SecretString"])
db_creds = get_secret("prod/myapp/db")
conn = psycopg2.connect(
host=db_creds["host"],
user=db_creds["username"],
password=db_creds["password"],
)
A instância EC2/ECS usa role IAM com permissão mínima — sem credenciais no código ou no container.
Outros Cofres
| Plataforma | Serviço |
|---|---|
| GCP | Secret Manager |
| Azure | Key Vault |
| GitHub | Actions Secrets |
| Kubernetes | Secrets (+ external-secrets operator) |
Detecção de Vazamentos
Ative no repositório:
# gitleaks — varre histórico git
gitleaks detect --source . --verbose
# truffleHog — detecta entropia alta (possível chave)
trufflehog git file://. --only-verified
No GitHub, ative Secret Scanning nas configurações do repositório — o GitHub bloqueia push de padrões conhecidos de API keys.
Rotação de Secrets
Um segredo que nunca muda é um risco permanente. Defina:
- Rotação periódica (ex: 90 dias para API keys, 30 para passwords de banco).
- Rotação imediata ao suspeitar de comprometimento.
- Zero downtime rotation: escreva novo secret, atualize app, revogue antigo.
Checklist
-
.enve arquivos de config com secrets no.gitignore -
git logauditado — nenhum secret no histórico - Secrets acessados via variável de ambiente ou cofre
- Rotação configurada e testada
- Secret scanning ativo no repositório
- Sem secrets em logs de aplicação