Como projetar sistemas de configuração centralizada com Vault
1. Fundamentos da Configuração Centralizada com Vault
A configuração centralizada com HashiCorp Vault vai muito além do simples armazenamento de senhas. Em um ecossistema de 1200 temas de infraestrutura moderna, o Vault se destaca por tratar configurações como secrets dinâmicos — credenciais que são geradas sob demanda, têm tempo de vida limitado e podem ser revogadas instantaneamente.
Conceitos fundamentais:
- Secrets estáticos: valores fixos como senhas de banco, chaves de API — armazenados no KV Secrets Engine
- Secrets dinâmicos: credenciais geradas pelo Vault no momento da requisição (ex: usuário de banco com validade de 1 hora)
- Configurações dinâmicas: parâmetros de aplicação que podem ser alterados sem reinicialização
Diferentemente de soluções como etcd ou Consul (focadas em descoberta de serviço e armazenamento de chave-valor simples), o Vault implementa zero trust architecture: nenhum sistema confia em outro por padrão. Toda requisição deve ser autenticada e autorizada, com criptografia tanto em trânsito (TLS) quanto em repouso (AES-256-GCM).
# Exemplo: Configuração mínima de um servidor Vault
storage "raft" {
path = "/opt/vault/data"
node_id = "node1"
}
listener "tcp" {
address = "0.0.0.0:8200"
tls_disable = false
tls_cert_file = "/etc/vault/certs/vault.crt"
tls_key_file = "/etc/vault/certs/vault.key"
}
seal "awskms" {
region = "us-east-1"
kms_key_id = "alias/vault-unseal"
}
api_addr = "https://vault.example.com:8200"
cluster_addr = "https://vault.example.com:8201"
2. Arquitetura de Alto Nível para Configuração Centralizada
A arquitetura do Vault para configuração centralizada é composta por três camadas essenciais:
Servidor Vault: responsável por autenticação, autorização e armazenamento. Pode operar em modo standalone ou cluster (Raft ou Consul como backend de armazenamento).
Storage Backend: onde os dados criptografados residem. Opções incluem Raft (integrado), Consul, DynamoDB, MySQL. O backend de armazenamento nunca vê dados decifrados — toda criptografia ocorre no servidor Vault.
Selo de Segurança (Seal): mecanismo que protege a chave mestra. Pode ser via Shamir (divisão de chaves entre operadores) ou cloud KMS (AWS KMS, Azure Key Vault, GCP Cloud KMS).
# Padrão de deployment multi-cluster com replicação
# Primário (us-east-1)
storage "raft" {
path = "/vault/data"
node_id = "primary-1"
}
replication {
mode = "primary"
token = "hvs.replication-token"
}
# Secundário (us-west-2) - apenas leitura
storage "raft" {
path = "/vault/data"
node_id = "secondary-1"
}
replication {
mode = "secondary"
token = "hvs.replication-token"
primary_api_addr = "https://vault-primary.example.com:8200"
}
Para ambientes Kubernetes, o Vault se integra nativamente via Vault Agent Injector — um mutating webhook que injeta sidecars nos pods para fornecer configurações.
3. Estrutura de Paths e Namespaces para Organização de Configurações
A organização hierárquica é crucial para gerenciar 1200 temas de configuração. O Vault utiliza paths como unidades de acesso e namespaces como isolamento lógico entre equipes ou ambientes.
Hierarquia recomendada:
# Estrutura de paths para configuração centralizada
secret/
├── datacenter/
│ ├── us-east/
│ │ ├── database/
│ │ │ └── primary
│ │ └── redis/
│ │ └── config
│ └── eu-west/
│ ├── database/
│ │ └── replica
│ └── cache/
├── application/
│ ├── payment-service/
│ │ ├── production
│ │ └── staging
│ └── notification-service/
│ ├── config
│ └── webhook-keys
└── infrastructure/
├── kubernetes/
│ ├── cluster-1/
│ │ └── service-accounts
│ └── cluster-2/
└── terraform/
└── state-backend
Namespaces multi-tenant permitem isolar completamente ambientes:
# Política de acesso baseada em namespace e path
path "namespace-dev/secret/application/*" {
capabilities = ["create", "read", "update", "delete", "list"]
}
path "namespace-prod/secret/application/*" {
capabilities = ["read", "list"]
required_parameters = ["version"]
}
path "namespace-prod/secret/infrastructure/*" {
capabilities = ["deny"]
}
4. Estratégias de Versionamento e Rollback de Configurações
O KV Secrets Engine v2 oferece versionamento automático — cada alteração cria uma nova versão, mantendo as anteriores disponíveis para rollback.
Operações de versionamento:
# Escrever configuração (cria versão 1)
vault kv put secret/application/payment-service/production \
db_host="prod-db.example.com" \
db_port="5432" \
max_connections="100"
# Atualizar (cria versão 2)
vault kv put secret/application/payment-service/production \
db_host="prod-db.example.com" \
db_port="5432" \
max_connections="200"
# Listar versões
vault kv metadata get secret/application/payment-service/production
# Rollback para versão 1
vault kv rollback -version=1 secret/application/payment-service/production
# Deletar versão específica (soft delete)
vault kv metadata delete -versions=2 secret/application/payment-service/production
# Destruir permanentemente
vault kv destroy -versions=2 secret/application/payment-service/production
Auditoria imutável: configure audit devices para registrar toda operação:
# Habilitar audit log para arquivo
vault audit enable file file_path=/vault/logs/audit.log
# Audit para syslog
vault audit enable syslog facility="AUTH" tag="vault-audit"
# Audit para socket (Graylog, ELK)
vault audit enable socket address="10.0.1.10:514" socket_type="tcp"
Cada entrada de audit contém timestamp, identidade do requisitante, path acessado e operação — impossível de modificar retroativamente.
5. Autenticação e Autorização para Acesso a Configurações
O Vault suporta múltiplos métodos de autenticação, cada um adequado a diferentes cenários:
AppRole: ideal para máquinas e serviços automatizados
Kubernetes Auth: para pods que precisam de configurações
LDAP: para integração com Active Directory corporativo
Tokens: método base, com políticas associadas
# Configuração de AppRole para CI/CD
vault auth enable approle
# Criar role com política restrita
vault write auth/approle/role/jenkins-role \
token_policies="ci-cd-policy" \
token_ttl=1h \
token_max_ttl=4h \
secret_id_ttl=10m \
secret_id_num_uses=40
# Política HCL para acesso controlado
path "secret/application/*" {
capabilities = ["read", "list"]
allowed_parameters = {
"version" = []
}
denied_parameters = {
"delete" = []
}
}
path "secret/infrastructure/terraform/*" {
capabilities = ["read", "list"]
# Apenas entre 9h e 18h
condition {
time {
weekday = ["mon", "tue", "wed", "thu", "fri"]
timezone = "America/Sao_Paulo"
start_time = "09:00"
end_time = "18:00"
}
}
}
Para secrets dinâmicos, configure leases com renovação automática:
# Configurar lease para banco PostgreSQL
vault write database/config/postgres-lab \
plugin_name="postgresql-database-plugin" \
allowed_roles="*" \
connection_url="postgresql://{{username}}:{{password}}@postgres.example.com:5432/lab" \
username="vault_admin" \
password="P@ssw0rd"
# Role que gera credenciais com TTL controlado
vault write database/roles/db-readonly \
db_name="postgres-lab" \
creation_statements="CREATE USER \"{{name}}\" WITH PASSWORD '{{password}}' VALID UNTIL '{{expiration}}'; GRANT SELECT ON ALL TABLES IN SCHEMA public TO \"{{name}}\";" \
default_ttl="30m" \
max_ttl="2h"
6. Integração com Aplicações e Pipelines de CI/CD
A injeção de configurações em aplicações segue dois padrões principais:
Vault Agent Sidecar: ideal para Kubernetes, o agente executa como sidecar e mantém arquivos de configuração sincronizados.
# Configuração do Vault Agent para sidecar
pid_file = "/tmp/agent-pid"
vault {
address = "https://vault-internal:8200"
retry {
num_retries = 5
}
}
auto_auth {
method "kubernetes" {
mount_path = "auth/kubernetes"
config {
role = "app-role"
jwt_path = "/var/run/secrets/kubernetes.io/serviceaccount/token"
}
}
}
template {
source = "/etc/config.tpl"
destination = "/etc/config/app.conf"
perms = 0644
# Recarregar aplicação quando config mudar
exec {
command = ["/bin/systemctl", "reload", "myapp"]
}
}
Template de configuração (Consul Template syntax):
{{- with secret "secret/application/payment-service/production" }}
# Configuração gerada pelo Vault Agent em {{ currentTime }}
db_host = "{{ .Data.data.db_host }}"
db_port = {{ .Data.data.db_port }}
max_connections = {{ .Data.data.max_connections }}
db_password = "{{ .Data.data.db_password }}"
{{- end }}
{{- with secret "database/creds/db-readonly" }}
# Credenciais dinâmicas - válidas até {{ .Data.lease_duration }}s
db_user = "{{ .Data.username }}"
db_pass = "{{ .Data.password }}"
{{- end }}
Pipeline seguro: injete secrets em runtime, nunca em build:
# Pipeline Jenkins - injeção segura em tempo de execução
stage('Deploy') {
steps {
script {
# Obter token AppRole
sh '''
VAULT_TOKEN=$(vault write -field=token auth/approle/login \
role_id=${ROLE_ID} \
secret_id=${SECRET_ID})
# Exportar configurações como variáveis de ambiente
vault kv get -field=db_host secret/application/payment-service/production > .env
vault kv get -field=db_password secret/application/payment-service/production >> .env
# Deploy com configurações injetadas
docker run --env-file .env myapp:${BUILD_TAG}
'''
}
}
}
7. Monitoramento, Performance e Boas Práticas Operacionais
Métricas essenciais para operação do Vault:
# Métricas Prometheus do Vault
# vault_raft_leader_latency_ms - latência de replicação Raft
# vault_token_count - número de tokens ativos
# vault_secret_lease_count - leases ativos
# vault_audit_log_request_failure - falhas de auditoria
# vault_core_unsealed - status do selo (1=aberto, 0=fechado)
# Configuração de métricas no Vault
telemetry {
prometheus_retention_time = "24h"
disable_hostname = true
}
Estratégias de cache com Vault Agent:
# Vault Agent com cache local
cache {
use_auto_auth_token = true
}
listener "tcp" {
address = "127.0.0.1:8200"
tls_disable = true
}
# Aplicação consulta agente local, que faz cache
# Reduz latência de 50ms para <1ms em leituras repetidas
Disaster Recovery:
# Backup do storage backend Raft
vault operator raft snapshot save /backup/vault-snapshot-$(date +%Y%m%d).snap
# Restore em novo cluster
vault operator raft snapshot restore /backup/vault-snapshot-20240101.snap
# Failover automático com replicação
# No primário:
vault write -f sys/replication/primary/enable primary_cluster_addr="https://vault-primary:8201"
# No secundário:
vault write sys/replication/secondary/enable token="hvs.replication-token"
Rate limiting para evitar abuso:
# Rate limit por caminho
path "secret/application/*" {
capabilities = ["read"]
rate_limit = {
rate = 100
burst = 200
}
}
Referências
- HashiCorp Vault Documentation - Official — Documentação completa do Vault, incluindo configuração, autenticação e melhores práticas de deployment
- Vault Agent Templates Guide — Tutorial oficial sobre templates para injeção de configurações em aplicações
- Vault Production Hardening Guide — Guia de segurança para ambientes de produção com Vault
- Kubernetes Vault Integration Tutorial — Como integrar Vault com Kubernetes usando Vault Agent Injector
- Vault Secrets Engine - KV v2 — Documentação do KV Secrets Engine v2 com versionamento e rollback
- Vault Replication Guide — Guia completo sobre replicação e disaster recovery no Vault