Pular para o conteúdo principal

Dynamic Secrets — JIT credentials

A partir da v1.7, o CipherVault emite credenciais just-in-time com TTL ≤ 24h em 6 engines. A app recebe um lease com username/password/ token efêmeros, usa, e o CipherVault revoga automaticamente na expiração ou release.

License gate: enterprise.

Engines suportadas (17 total)

EngineParadigmaRevokeVersão
postgresCREATE ROLE + GRANT + DROP ROLEImediato1.7.0
mysqlCREATE USER + GRANT + DROP USERImediato1.7.1
mongodbcreateUser / dropUser admin DBImediato1.7.2
aws_stsAssumeRole / GetFederationTokenNo-op (token expira sozinho)1.7.1
gcp_iam (access_token)IAMCredentials.GenerateAccessTokenNo-op (cap 1h GCP)1.7.2
gcp_iam (sa_key)Cria SA key com TTL ≤ 24h (CV cap)No-op (key expira sozinho)3.0
azure_spGraph addPassword com endDateTimeremovePassword1.7.2
cassandraCREATE ROLE WITH LOGIN AND PASSWORDDROP ROLE3.0
mssqlCREATE LOGIN + CREATE USER FOR LOGINDROP USER + DROP LOGIN3.0
redis (ACL)ACL SETUSER ... ON >password (Redis 6+)ACL DELUSER3.0
active_directoryldap_modify user/passwordDisable + remove4.5
ldapOpenLDAP / 389DS / FreeIPADisable + remove4.5
consulacl_token_createacl_token_destroy4.5
nomadacl_token_createacl_token_destroy4.5
rabbitmqPUT /api/users + permissionsDELETE /api/users4.5
alicloud_stsAssumeRole AliyunNo-op4.5
mongodb_atlasProgrammatic API keyRevoke key4.5
hcp_terraformWorkspace variablesDelete vars4.5

Plugins customizados via Plugin SDK podem adicionar engines proprietários sem fork do backend.

gcp_iam modes

A v3 adicionou template.mode em roles GCP IAM:

{
"engine": "gcp_iam",
"template": {
"mode": "sa_key", // ou "access_token" (default)
"service_account": "etl@project.iam.gserviceaccount.com"
}
}
  • access_token — token com cap 1h imposto pelo GCP. Adequado para chamadas API
  • sa_key — SA key JSON com TTL configurável (cap 24h pelo CV). Adequado para ferramentas que esperam credentials.json

mTLS nas engines (v3.0+)

postgres e mysql engines aceitam mTLS na conexão admin:

{
"engine": "postgres",
"connection": {
"host": "db-billing.internal.acme.com.br",
"port": 5432,
"ssl_ca": "<PEM CA>",
"ssl_cert": "<PEM client cert>",
"ssl_key_secret": "internal/db/postgres/cv-admin-key"
}
}

Conceitos

  • Backend — conexão com o sistema externo (Postgres, AWS, etc.) que vai emitir creds
  • Role — template de permissão e TTL no backend
  • Lease — credencial efêmera emitida (cv_* username + senha gerada)
admin: cria backend → cria role
app: solicita lease (role_id, ttl) → recebe { username, password, expires_at }
usa por TTL
(expira sozinho OU app chama release)
backend executa DROP USER / removePassword

Configuração — admin

1. Criar backend (Postgres)

curl -X POST https://cv.acme.com.br/dynamic-secrets/backends \
-H "Authorization: Bearer $CV_TOKEN" \
-d '{
"name": "billing-postgres-prd",
"engine": "postgres",
"connection": {
"host": "db-billing.internal.acme.com.br",
"port": 5432,
"database": "billing",
"admin_username": "cv_admin",
"admin_password_secret": "internal/db/postgres/cv-admin"
}
}'

A admin_password_secret aponta para um secret armazenado no próprio CV (meta-protege a credencial admin que cria/destroi roles).

2. Criar role

curl -X POST https://cv.acme.com.br/dynamic-secrets/roles \
-H "Authorization: Bearer $CV_TOKEN" \
-d '{
"backend_id": 12,
"name": "billing-readonly",
"ttl_seconds": 600,
"max_ttl_seconds": 3600,
"creation_statements": [
"CREATE ROLE \"{{name}}\" WITH LOGIN PASSWORD '\''{{password}}'\'' VALID UNTIL '\''{{expiration}}'\''",
"GRANT pg_read_all_data TO \"{{name}}\""
],
"revocation_statements": [
"REVOKE ALL ON DATABASE billing FROM \"{{name}}\"",
"DROP ROLE IF EXISTS \"{{name}}\""
]
}'

Templating seguro com whitelist anti-SQL injection: somente {{name}}, {{password}}, {{expiration}}.

3. Modes

  • direct (default) — CipherVault conecta diretamente ao DB e roda statements
  • sensor (Phase 4 — v1.7.2+) — task vai para dynamic_secret_tasks, sensor remoto puxa via poll 30s e executa em DB interno (sem expor DB para o CV)

Uso pela aplicação

Via SDK (Python)

from ciphervault.admin import AdminClient

cv = AdminClient(url="https://cv.acme.com.br", token=os.environ["CV_TOKEN"])

# Solicita lease
lease = cv.dynamic.request_lease(role_id=42, ttl_seconds=600, reason="ETL daily")

import psycopg2
conn = psycopg2.connect(
host="db-billing.internal.acme.com.br",
user=lease["username"], # cv_etl_<jti>
password=lease["password"],
dbname="billing",
)
# ... use ...
conn.close()

# Release (opcional — TTL expira sozinho)
cv.dynamic.release_lease(lease["id"])

Via CLI Go cv

LEASE=$(cv lease request 42 --ttl 600 --output json)
USER=$(echo "$LEASE" | jq -r .username)
PASS=$(echo "$LEASE" | jq -r .password)

PGPASSWORD="$PASS" psql -h db-billing.internal.acme.com.br -U "$USER" -d billing

Via Secretless Proxy (Postgres apenas, MVP)

secretless-proxy \
--listen :5432 \
--upstream db-billing.internal.acme.com.br:5432 \
--cv-url https://cv.acme.com.br \
--conn-id app_01HXY... \
--role-id 42

# App conecta em localhost:5432 com user/pass arbitrários — proxy injeta cred
psql -h localhost -U dummy -d billing

Operacional

  • Cap absoluto 24h — independente de max_ttl_seconds da role
  • Job de expiração 60s com leader-lock multi-replica
  • Reconcile diário — detecta orphans no backend (usuários cv_* sem lease ativo no CV) — alerta dynamic_lease_orphan_in_backend severity critical
    • auto_fix_orphans (v3.0+, opt-in via dynamic_backends.auto_fix_orphans=true) — drop automático de orphans com idade > 24h
  • Lease pool / reuso (v3.0+) — role.lease_reuse_max_uses permite mesma (role, app_connection) reaproveitar lease ativa via SKIP LOCKED. Reduz RTT inicial do Secretless Proxy de 100ms → 5ms
  • Rate limiting — token-bucket in-memory, capacity 30, refill 0.5/s
  • Prometheus metrics — 7 métricas custom + default process metrics. /metrics gated por CV_METRICS_ENABLED=true

Tabelas

dynamic_backends -- conexões cadastradas
dynamic_roles -- templates por backend
dynamic_leases -- leases ativas + revogadas
dynamic_secret_tasks -- queue para sensor mode

Tutorial passo a passo

Veja Tutoriais → Rotação automática (alinhar sua rotação com leases dinâmicos para zero-downtime).

Boas práticas

  • TTL curto — 5–15 min para ETL/jobs; 1h para sessões interativas. Cap final 24h.
  • Modo sensor em DBs internos — não exponha o DB de produção para o CipherVault SaaS.
  • Reconcile + alertas — orphan no backend significa drift; investigue imediatamente.
  • Statements idempotentesIF EXISTS no DROP, OR REPLACE quando aplicável.
  • Não use admin do banco como admin_username — crie role cv_admin com permissões mínimas para criar/dropar roles.