Vault

O Vault é o coração do CriptEnv — ele gerencia o armazenamento e a sincronização de segredos criptografados. Todos os dados trafegam já criptografados; o servidor nunca tem acesso aos valores em texto claro (arquitetura zero-knowledge).

Fluxo Zero-Knowledge

Antes de usar os endpoints do Vault, é importante entender o fluxo de criptografia. Toda a criptografia e descriptografia acontece no cliente:

Push (enviar segredos):

1. Cliente obtém senha mestra do usuário

2. Deriva chave mestra via PBKDF2 (100k iterações)

3. Deriva chave do ambiente via HKDF (salt = env_id)

4. Criptografa cada segredo com AES-256-GCM

5. Envia ciphertext + nonce + tag ao servidor

Pull (receber segredos):

1. Cliente recebe ciphertext + nonce + tag do servidor

2. Deriva chaves (mesmo processo do push)

3. Descriptografa localmente com AES-256-GCM

Info

O servidor armazena apenas dados opacos (ciphertext). Sem a senha mestra do usuário, é impossível recuperar os valores originais — nem o CriptEnv, nem qualquer pessoa com acesso ao banco de dados, consegue ler os segredos.
text
https://api.criptenv.dev/v1/vault

POST Push Segredos

Envia segredos criptografados para um ambiente. Suporta detecção de conflitos via versionamento otimista — se os segredos foram alterados por outro usuário desde a última sincronização, a API retorna um conflito.

text
POST /v1/vault/push
ParâmetroTipoDescrição
environment_idobrigatóriostringID do ambiente destino
key_idobrigatóriostringID da chave de criptografia usada
secretsobrigatórioobject[]Array de segredos criptografados
secrets[].nameobrigatóriostringNome do segredo (ex: DATABASE_URL)
secrets[].ciphertextobrigatóriostringValor criptografado em base64
secrets[].nonceobrigatóriostringNonce do AES-GCM em base64
secrets[].tagobrigatóriostringAuth tag do AES-GCM em base64
base_versionintegerVersão base para detecção de conflitos (omitir para forçar overwrite)
strategystringEstratégia de merge: merge (padrão) ou replace (substitui todos)Padrão: merge
Exemplo — Push de segredos
curl -X POST "https://api.criptenv.dev/v1/vault/push" \
  -H "Authorization: Bearer cek_a1b2c3d4e5f6" \
  -H "Content-Type: application/json" \
  -d '{
    "environment_id": "env_a1b2c3",
    "key_id": "key_m2n4p6q8",
    "base_version": 5,
    "strategy": "merge",
    "secrets": [
      {
        "name": "DATABASE_URL",
        "ciphertext": "YWJjZGVmZ2hpamtsbW5vcA==",
        "nonce": "MTIzNDU2Nzg5MDEy",
        "tag": "QUJDREVGR0hJSktMTU5P"
      },
      {
        "name": "REDIS_URL",
        "ciphertext": "cXJzdHV2d3h5ejAxMjM0",
        "nonce": "OTg3NjU0MzIxMDk4",
        "tag": "UEhJR0pLTE1OT1FSU1RV"
      }
    ]
  }'
200OK
json
{
  "data": {
    "environment_id": "env_a1b2c3",
    "version": 6,
    "secrets_pushed": 2,
    "secrets_total": 14,
    "pushed_at": "2025-01-20T14:30:00Z"
  }
}

Detecção de Conflitos

Se outro membro modificou os segredos desde a última sincronização, a API retorna um conflito com os detalhes:

409Conflict
json
{
  "error": {
    "code": "version_conflict",
    "message": "Os segredos foram modificados por outro usuário desde sua última sincronização.",
    "details": {
      "your_base_version": 5,
      "current_version": 7,
      "conflicting_keys": ["DATABASE_URL"],
      "modified_by": "usr_x9y8z7w6",
      "modified_at": "2025-01-20T14:25:00Z"
    }
  }
}

Info

Em caso de conflito, faça um pull para obter a versão mais recente, resolva o conflito manualmente e tente novamente o push.

GET Pull Segredos

Retorna todos os segredos criptografados de um ambiente. Os dados retornados devem ser descriptografados no cliente usando a chave derivada da senha mestra.

text
GET /v1/vault/pull
ParâmetroTipoDescrição
environment_idobrigatóriostringID do ambiente para puxar segredos
formatstringFormato de saída: json ou envPadrão: json
names_onlybooleanSe true, retorna apenas os nomes dos segredos (sem ciphertext)Padrão: false
Exemplo — Pull de segredos
curl -X GET "https://api.criptenv.dev/v1/vault/pull?environment_id=env_a1b2c3" \
  -H "Authorization: Bearer cek_a1b2c3d4e5f6"
200OK
json
{
  "data": {
    "environment_id": "env_a1b2c3",
    "version": 6,
    "key_id": "key_m2n4p6q8",
    "secrets": [
      {
        "name": "DATABASE_URL",
        "ciphertext": "YWJjZGVmZ2hpamtsbW5vcA==",
        "nonce": "MTIzNDU2Nzg5MDEy",
        "tag": "QUJDREVGR0hJSktMTU5P"
      },
      {
        "name": "REDIS_URL",
        "ciphertext": "cXJzdHV2d3h5ejAxMjM0",
        "nonce": "OTg3NjU0MzIxMDk4",
        "tag": "UEhJR0pLTE1OT1FSU1RV"
      }
    ],
    "pulled_at": "2025-01-20T14:35:00Z"
  }
}
Pull com names_only (para diff)
curl -X GET "https://api.criptenv.dev/v1/vault/pull?environment_id=env_a1b2c3&names_only=true" \
  -H "Authorization: Bearer cek_a1b2c3d4e5f6"
200OK
json
{
  "data": {
    "environment_id": "env_a1b2c3",
    "version": 6,
    "secret_names": [
      "DATABASE_URL",
      "REDIS_URL",
      "JWT_SECRET",
      "STRIPE_API_KEY"
    ],
    "total": 14
  }
}

GET Versão do Vault

Retorna a versão atual do vault de um ambiente, útil para verificar se houve alterações desde a última sincronização sem precisar baixar todos os segredos.

text
GET /v1/vault/version
ParâmetroTipoDescrição
environment_idobrigatóriostringID do ambiente
Exemplo — Verificar versão
curl -X GET "https://api.criptenv.dev/v1/vault/version?environment_id=env_a1b2c3" \
  -H "Authorization: Bearer cek_a1b2c3d4e5f6"
200OK
json
{
  "data": {
    "environment_id": "env_a1b2c3",
    "version": 6,
    "last_modified_at": "2025-01-20T14:30:00Z",
    "last_modified_by": "usr_a1b2c3d4",
    "secret_count": 14
  }
}

Exemplo Completo — Fluxo de Deploy

Veja como usar os endpoints do Vault em um fluxo típico de CI/CD:

Fluxo completo: verificar → pull → decrypt → deploy
# 1. Verificar versão atual (evita pull desnecessário)
VERSION=$(curl -s "https://api.criptenv.dev/v1/vault/version?environment_id=env_a1b2c3" \
  -H "Authorization: Bearer $CI_TOKEN" | jq -r '.data.version')

# 2. Pull dos segredos criptografados
curl -s "https://api.criptenv.dev/v1/vault/pull?environment_id=env_a1b2c3" \
  -H "Authorization: Bearer $CI_TOKEN" \
  -o encrypted-secrets.json

# 3. Descriptografar localmente (usando CLI do CriptEnv)
criptenv decrypt --input encrypted-secrets.json --output .env --password "$MASTER_PASSWORD"

# 4. Deploy com segredos descriptografados
docker compose up -d