Pular para o conteúdo principal

Rotação automática de credenciais (PostgreSQL)

Tutorial completo para habilitar rotação a cada 30 dias da senha master de um banco PostgreSQL de produção, com rollback automático em caso de falha.

Cenário

  • Banco billing-prod (PostgreSQL 14) com usuário app_user.
  • Aplicação billing-api consome via SDK Python ou cv-agent sidecar.
  • Objetivo: rotacionar a senha de app_user a cada 30 dias, sem downtime.

1. Criar usuário admin no PostgreSQL

O CipherVault precisa de um usuário PG com permissão ALTER USER em app_user. Não use o postgres superuser — princípio do menor privilégio.

CREATE ROLE ciphervault_admin LOGIN PASSWORD 'temp_strong_password_change_me';

-- Permissão mínima para alterar senha de app_user
GRANT app_user TO ciphervault_admin;
ALTER ROLE ciphervault_admin CREATEROLE;

2. Armazenar credencial admin no CipherVault

curl -X POST https://api.ciphervault.com.br/v1/vaults/producao/secrets \
-H "Authorization: Bearer $CIPHERVAULT_TOKEN" \
-d '{
"path": "db/postgres/admin-billing",
"type": "password",
"value": "temp_strong_password_change_me",
"metadata": {
"description": "Credencial admin que o CipherVault usa para rotacionar app_user",
"owner": "sre@acme.com.br"
}
}'

3. Criar o secret rotacionável

curl -X POST https://api.ciphervault.com.br/v1/vaults/producao/secrets \
-H "Authorization: Bearer $CIPHERVAULT_TOKEN" \
-d '{
"path": "db/postgres/billing-app",
"type": "database",
"engine": "postgresql",
"connection": {
"host": "db-billing.internal.acme.com.br",
"port": 5432,
"database": "billing",
"ssl_mode": "verify-full",
"ca_bundle_secret": "infra/db/ca",
"target_username": "app_user",
"admin_username": "ciphervault_admin",
"admin_password_secret": "db/postgres/admin-billing"
},
"rotation": {
"enabled": true,
"interval_days": 30,
"grace_window_minutes": 10,
"rollback_on_failure": true,
"notify_on_failure": ["sre-oncall@acme.com.br", "#sre-alerts"],
"test_after_rotate": {
"type": "tcp_connect_with_password",
"timeout_seconds": 5
}
}
}'

test_after_rotate valida a nova senha conectando ao Postgres com ela antes de finalizar a rotação. Se falhar, rollback imediato.

4. Forçar primeira rotação manual

Recomendado: dispare uma rotação inicial para validar a configuração.

curl -X POST \
https://api.ciphervault.com.br/v1/vaults/producao/secrets/db/postgres/billing-app/rotate \
-H "Authorization: Bearer $CIPHERVAULT_TOKEN" \
-d '{ "reason": "Setup inicial — validar pipeline de rotação" }'

Acompanhe:

curl https://api.ciphervault.com.br/v1/vaults/producao/secrets/db/postgres/billing-app/rotation-status \
-H "Authorization: Bearer $CIPHERVAULT_TOKEN"

Estados: pending → rotating → testing → grace_window → completed (ou rolled_back em falha).

5. Configurar a aplicação

Opção A: SDK com refresh automático

from ciphervault import Client

client = Client(
endpoint="https://api.ciphervault.com.br",
cache_ttl_seconds=60, # detecta nova versão em até 60s
)

def get_db_connection():
secret = client.secrets.get(
vault="producao",
path="db/postgres/billing-app",
)
return psycopg2.connect(
host=secret.connection["host"],
user=secret.connection["target_username"],
password=secret.value,
dbname=secret.connection["database"],
sslmode="verify-full",
)

Use connection pooling com max_lifetime < grace_window para garantir que conexões antigas reciclem antes da senha velha ser revogada.

Opção B: cv-agent sidecar (Kubernetes)

Veja Operator + sidecar. O sidecar atualiza o socket Unix; conexões PG recriam transparentemente.

6. Monitoramento

Métricas Prometheus expostas pelo CipherVault server:

  • cv_rotation_success_total{vault, path} — contador
  • cv_rotation_failure_total{vault, path, reason} — contador
  • cv_rotation_duration_seconds{vault, path} — histogram
  • cv_secret_age_days{vault, path} — gauge (idade desde última rotação)

Alertas Prometheus recomendados:

groups:
- name: ciphervault-rotation
rules:
- alert: CipherVaultRotationFailed
expr: increase(cv_rotation_failure_total[1h]) > 0
labels:
severity: critical
annotations:
summary: "Rotação falhou em {{ $labels.vault }}/{{ $labels.path }}"

- alert: CipherVaultSecretAgeHigh
expr: cv_secret_age_days > 35
for: 1h
labels:
severity: warning
annotations:
summary: "Secret {{ $labels.path }} não rotaciona há {{ $value }} dias"

7. Plano de rollback manual

Caso descubra um problema em produção pós-rotação:

curl -X POST \
https://api.ciphervault.com.br/v1/vaults/producao/secrets/db/postgres/billing-app/rollback \
-H "Authorization: Bearer $CIPHERVAULT_TOKEN" \
-d '{ "to_version": 5, "reason": "Rotação v6 quebrou conexões long-lived" }'

A versão antiga é restaurada no cofre e no PostgreSQL.

Boas práticas

  • Comece em staging. Rode rotação semanal em staging por 1 mês antes de produção.
  • Grace window generosa. Apps com pool de conexão longo precisam de 15–30min.
  • Rotação da credencial admin. A db/postgres/admin-billing deve ter rotação semestral com aprovação manual.
  • Não dependa só de e-mail. Configure também alerta em SIEM/PagerDuty para falhas.