1. Uma nova série: segurança e governança em infraestrutura
Provisionar infraestrutura com código, versionar tudo em Git e automatizar o deploy resolve boa parte dos problemas operacionais de um time — mas também cria uma nova superfície de risco. Um terraform apply errado pode expor um bucket ao mundo; um segredo comitado por engano fica para sempre no histórico do repositório; uma role com permissão de mais é só uma credencial roubada de distância de um incidente grave. Nesta nova série, vamos tratar de três pilares de segurança e governança que toda automação de infraestrutura precisa levar em conta: gestão de segredos, policy as code e least privilege em IAM.
Começamos pelo problema mais básico e, ainda assim, um dos mais comuns em auditorias de segurança: como guardar e distribuir segredos sem deixá-los em texto puro em lugar nenhum.
2. O problema de guardar segredos em texto puro
É extremamente comum encontrar, em projetos reais, segredos vazando por canais aparentemente inofensivos:
- Um
terraform.tfvarscomdb_password = "supersecreta123"comitado "só para testar localmente" — e que nunca foi removido do histórico do Git. - Variáveis de ambiente com credenciais de nuvem definidas direto no arquivo de configuração do CI (visíveis em texto puro para qualquer pessoa com acesso de leitura ao pipeline).
- O próprio state file do Terraform, que guarda em texto puro todos os atributos dos recursos que gerencia — incluindo senhas de banco de dados criadas via
random_passwordou strings de conexão completas.
O problema não é só o vazamento inicial. Um segredo comitado no Git continua acessível no histórico mesmo depois de removido do arquivo atual — é preciso reescrever o histórico (git filter-repo, BFG) e ainda assim tratar o segredo como comprometido, porque qualquer clone anterior já o tem. A prática correta é nunca deixar o segredo chegar ao repositório: ele deve viver em um sistema dedicado, com controle de acesso, auditoria e rotação.
3. Introdução ao Vault
O HashiCorp Vault é o sistema de gestão de segredos mais usado no ecossistema de IaC. Os conceitos centrais são:
- Secrets engines: módulos plugáveis que definem como os segredos são gerados e armazenados. O mais simples é o KV (key-value), que guarda pares chave-valor estáticos, criptografados em repouso. Outros, como o engine da AWS, geram segredos dinâmicos: credenciais IAM criadas sob demanda, com tempo de vida limitado.
- Leases: todo segredo dinâmico tem um lease (contrato de validade). Quando o lease expira, o Vault revoga a credencial automaticamente — sem depender de ninguém lembrar de fazer rotação manual.
- Políticas de acesso: definem quem pode ler/escrever em quais paths do Vault, integradas com métodos de autenticação (tokens, AppRole, Kubernetes service accounts, OIDC, etc.).
A alternativa mais comum fora do universo HashiCorp é o AWS Secrets Manager (ou seu equivalente no Azure/GCP), que resolve o mesmo problema de forma mais simples quando o time já está 100% dentro de uma única nuvem, trocando flexibilidade multi-cloud por integração nativa e menos operação própria. Os exemplos abaixo usam Vault, mas o raciocínio de "nunca commitar segredo, sempre buscar em runtime" é o mesmo nos dois.
4. Subindo um Vault local para experimentar
Para fins de estudo, o Vault tem um modo de desenvolvimento que roda tudo em memória, sem persistência real:
vault server -dev -dev-root-token-id="root-token-local"
Em outro terminal, apontando o cliente para o servidor local:
export VAULT_ADDR="http://127.0.0.1:8200"
export VAULT_TOKEN="root-token-local"
vault status
5. Guardando e lendo segredos no KV
# Habilita o secrets engine KV versão 2 no path "secret/"
vault secrets enable -path=secret kv-v2
# Guarda um segredo
vault kv put secret/app/database \
username="app_user" \
password="uma-senha-bem-forte"
# Lê o segredo de volta
vault kv get secret/app/database
O KV v2 guarda versões de cada segredo, o que permite auditar quando um valor mudou e fazer rollback se necessário — algo que uma variável de ambiente jogada num .env nunca oferece.
6. Integrando Vault com Terraform
O provider oficial do Vault para Terraform permite ler segredos em tempo de plan/apply, sem que eles apareçam em nenhum arquivo .tf versionado:
provider "vault" {
address = "http://127.0.0.1:8200"
}
data "vault_kv_secret_v2" "database" {
mount = "secret"
name = "app/database"
}
resource "aws_db_instance" "app" {
identifier = "app-db"
engine = "postgres"
instance_class = "db.t3.micro"
username = data.vault_kv_secret_v2.database.data["username"]
password = data.vault_kv_secret_v2.database.data["password"]
}
Um cuidado importante: o valor lido ainda vai parar no state file, em texto puro, porque é assim que o Terraform rastreia atributos de recursos. Isso não elimina a necessidade de um backend de state criptografado (S3 com SSE, ou o encryption nativo do OpenTofu visto na série anterior) — o Vault resolve o problema de "de onde o segredo vem", não o de "onde o resultado final fica guardado depois".
7. Segredos dinâmicos: indo além do KV estático
O ganho real de segurança do Vault aparece nos secrets engines dinâmicos. Em vez de guardar uma credencial fixa da AWS, o Vault pode gerar uma nova a cada solicitação, com expiração automática:
# Habilita o secrets engine da AWS
vault secrets enable aws
vault write aws/config/root \
access_key="AKIA..." \
secret_key="..." \
region="us-east-1"
# Define uma role que gera credenciais com uma policy IAM específica
vault write aws/roles/deploy-readonly \
credential_type="iam_user" \
policy_document=-<<EOF
{
"Version": "2012-10-17",
"Statement": [
{ "Effect": "Allow", "Action": "s3:GetObject", "Resource": "*" }
]
}
EOF
# Gera uma credencial temporária, válida por um tempo limitado
vault read aws/creds/deploy-readonly
Cada vault read acima gera um par de chaves novo, com lease próprio. Se uma pipeline de CI usa esse fluxo, uma credencial vazada em um log específico expira sozinha em minutos ou horas, em vez de ficar válida indefinidamente como uma chave de usuário IAM tradicional.
8. Conclusão
Segredos em texto puro no repositório — ou em variáveis de ambiente de CI sem controle — são um dos vetores de incidente mais comuns e mais fáceis de evitar em automação de infraestrutura. Um secrets manager dedicado (Vault, AWS Secrets Manager ou equivalente) resolve isso com armazenamento criptografado, controle de acesso granular e, no melhor caso, credenciais dinâmicas de curta duração. No próximo artigo desta série, vamos olhar para outro tipo de risco: recursos inseguros que passam pelo apply porque nenhuma regra automatizada os bloqueou antes — e como o Policy as Code resolve isso com OPA.
Imagem de capa: Logo oficial da HashiCorp, mantenedora do Vault — Wikimedia Commons
Referências:
Top comments (0)