Skip to main content

Documentation Index

Fetch the complete documentation index at: https://snakysec.mintlify.app/llms.txt

Use this file to discover all available pages before exploring further.

ADR-002 — HashiCorp Vault for runtime secret injection

Date: 2025-01-20 Status: Accepted Deciders: Nicolas (founder)

Context

The platform handles sensitive credentials per client (Entra ID client secrets/certificates, tenant IDs) and platform-level secrets (ENCRYPTION_KEY, GitLab token, database URL). These must not be stored in .env files committed to the repo or baked into Docker images.

Decision

HashiCorp Vault KV v2 is used for all runtime secrets, injected via instrumentation.ts at Next.js server startup.

Rationale

  • Zero secrets in Git: .env only contains infrastructure URLs (DATABASE_URL, REDIS_URL, VAULT_ADDR)
  • AES-256-GCM client secrets: Per-client credentials encrypted at rest in PostgreSQL (ClientSecret model), decrypted on demand via ENCRYPTION_KEY fetched from Vault
  • X.509 cert auth for Entra ID: Certificate private key stored in Vault, never touches disk outside the container
  • Audit worker AppRole: Worker uses Vault AppRole (separate role, limited TTL) — principle of least privilege
  • Key rotation: Rotate ENCRYPTION_KEY via vault kv patch without redeployment

Architecture

Next.js startup (instrumentation.ts)
  └── vault.ts → KV v2 read mssp/platform
        └── sets process.env.ENTRA_CERT_PRIVATE_KEY, ENTRA_CERT_PEM,
            ENCRYPTION_KEY, GITLAB_TOKEN, ...

Audit worker startup
  └── AppRole auth → Vault token (short TTL)
        └── reads per-client secrets on demand

Consequences

  • VAULT_ADDR must be set in .env; all other secrets come from Vault
  • next build uses SKIP_ENV_VALIDATION=true — Vault unavailable at build time
  • Dev mode: Vault dev server in docker-compose, pre-seeded via docker/vault/init.sh
  • Production: Vault in HA mode with Raft storage (documented in docker/vault/vault-prod.hcl)

Alternatives rejected

  • AWS Secrets Manager: Vendor lock-in; added cost; overkill for single-region PME MSSP
  • Kubernetes Secrets: No Kubernetes in the stack; Docker Swarm / Compose deployment target
  • Doppler / Infisical: Third-party SaaS dependency for secrets management violates data residency requirements (EU clients)