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.

Runbook — Vault Transit migration for ClientSecret rows

Owner: Plateforme · Audience: MSSP_ADMIN avec accès Vault root + Postgres Statut: V1 (avril 2026) · Niveau de risque: moyen (déchiffrement de tous les ClientSecret puis ré-écriture)

Contexte

Avant le 2026-04, chaque ClientSecret était chiffré en AES-256-GCM avec une clé ENCRYPTION_KEY injectée dans process.env du conteneur applicatif. La clé n’était pas dans .env, mais elle était lisible via /proc/<node-pid>/environ par tout root du conteneur ou tout opérateur capable d’un docker exec. Vault Transit (cryptography-as-a-service) déplace la clé maître dans Vault. L’app appelle transit/encrypt/mssp-clients et transit/decrypt/mssp-clients en HTTP, ne détient jamais la clé, et obtient en plus la rotation, le rewrap et l’audit centralisés. Le code applicatif (src/lib/crypto.ts) supporte les deux formats simultanément :
  • legacy AESClientSecret.iv + authTag non NULL → déchiffrement local.
  • TransitencryptedValue préfixé vault:v1:…, iv et authTag à NULL → appel HTTP Vault.
Toute nouvelle écriture utilise Transit. Ce runbook décrit comment rewrap les lignes héritées.

Pré-requis

  1. Vault déployé, descellé, secrets engine transit/ activé avec les clés mssp-platform et mssp-clients. Vérification :
    docker exec mssp-vault vault list transit/keys
    # Doit retourner: mssp-clients, mssp-platform
    
  2. La policy mssp-app accorde update sur transit/encrypt/mssp-clients et transit/decrypt/mssp-clients (déjà appliqué par platform/docker/vault/init.sh).
  3. Postgres up, schéma à jour (ClientSecret.iv et ClientSecret.authTag nullable). Vérification :
    docker exec mssp-postgres psql -U mssp -d mssp_platform -c "\d \"ClientSecret\""
    # iv et auth_tag doivent apparaître nullable
    
  4. Variables d’environnement disponibles à l’opérateur : DATABASE_URL, VAULT_ADDR, VAULT_TOKEN (token avec capability update sur transit/encrypt/mssp-clients), ENCRYPTION_KEY (l’ancienne clé AES, lue depuis Vault mssp/data/platform).

Procédure

1 — Inventaire pré-migration

docker exec mssp-postgres psql -U mssp -d mssp_platform -c \
  "SELECT COUNT(*) FROM \"ClientSecret\" WHERE iv IS NOT NULL AND encrypted_value NOT LIKE 'vault:%';"
Notez le compte. Ce sera la cible.

2 — Dry-run (aucune écriture, valide la chaîne complète decrypt→re-encrypt)

docker exec mssp-app sh -c '
  cd /app && \
  DATABASE_URL=$(cat /proc/1/environ | tr "\0" "\n" | grep "^DATABASE_URL=" | cut -d= -f2-) \
  VAULT_ADDR=$VAULT_ADDR \
  VAULT_TOKEN=$VAULT_TOKEN \
  ENCRYPTION_KEY=$ENCRYPTION_KEY \
  node scripts/rewrap-legacy-secrets.mjs --dry-run
'
Sortie attendue : une ligne JSON "would rewrap" par row, puis "done" avec ok = N, failed = 0, dryRun = true. Si failed > 0 : interrompre. Soit la clé AES n’est pas la bonne (mauvais ENCRYPTION_KEY), soit une row a été corrompue. Ne pas continuer avant d’avoir résolu.

3 — Application

docker exec mssp-app sh -c '
  cd /app && \
  DATABASE_URL=$(cat /proc/1/environ | tr "\0" "\n" | grep "^DATABASE_URL=" | cut -d= -f2-) \
  VAULT_ADDR=$VAULT_ADDR \
  VAULT_TOKEN=$VAULT_TOKEN \
  ENCRYPTION_KEY=$ENCRYPTION_KEY \
  node scripts/rewrap-legacy-secrets.mjs
'
Le script traite chaque row dans sa propre transaction. Si une écriture échoue, les rows déjà rewrappées restent en Transit — le rerun est idempotent (filtre iv IS NOT NULL).

4 — Vérification post-migration

# Compte de lignes héritées restantes (doit être 0)
docker exec mssp-postgres psql -U mssp -d mssp_platform -c \
  "SELECT COUNT(*) FROM \"ClientSecret\" WHERE iv IS NOT NULL AND encrypted_value NOT LIKE 'vault:%';"

# Compte de lignes Transit (doit égaler le total initial)
docker exec mssp-postgres psql -U mssp -d mssp_platform -c \
  "SELECT COUNT(*) FROM \"ClientSecret\" WHERE iv IS NULL AND encrypted_value LIKE 'vault:%';"

5 — Smoke-test applicatif

Côté UI, ouvrir un client ayant des secrets, déclencher une action qui nécessite decrypt (ex : test de connexion onboarding). Si la lecture passe sans erreur, la migration est validée.

6 — Audit log

docker exec mssp-postgres psql -U mssp -d mssp_platform -c \
  "INSERT INTO \"PlatformAuditLog\" (action, resource, details, \"userId\")
   VALUES ('vault.transit_migration', 'ClientSecret',
           jsonb_build_object('migrated', N, 'date', now()),
           '<MSSP_ADMIN_USER_ID>');"
Remplacer N par le compte effectif et <MSSP_ADMIN_USER_ID> par l’opérateur. Le log audit est scellé Ed25519 par les anchors.

Garde-fous

  • Le script refuse de tourner contre un DATABASE_URL non-localhost sans --confirm-prod. Ce flag est volontairement explicite : ne pas l’ajouter par réflexe.
  • Le script utilise des transactions par row — pas de blast radius transactionnel. En cas d’échec partiel, les rows OK sont déjà migrées et le rerun reprend là où l’arrêt a eu lieu.
  • ENCRYPTION_KEY reste nécessaire tant que toutes les rows n’ont pas été rewrappées. Elle peut être retirée de mssp/data/platform UNIQUEMENT après confirmation que COUNT(*) WHERE iv IS NOT NULL = 0.

Rollback

Aucun rollback automatique. Si la migration produit des rows inutilisables :
  1. Vault Transit ne fait JAMAIS de purge — toutes les opérations sont sur des clés versionnées. Donc même si la clé mssp-clients est rotée, les ciphertexts vault:v1:… restent déchiffrables.
  2. Si malgré tout un rollback est nécessaire : restaurer la table ClientSecret depuis le dernier backup Postgres (cf. docs/dr/).

Post-migration

Une fois la totalité des clients migrés et validés :
  1. Retirer ENCRYPTION_KEY de mssp/data/platform dans Vault.
  2. Retirer la lecture de ENCRYPTION_KEY dans instrumentation.ts (mapping encryption_keyENCRYPTION_KEY) et dans le mapping requis prod du même fichier.
  3. Supprimer le code decryptLegacyAes() de src/lib/crypto.ts (laisser une note dans le commit avec un lien vers ce runbook pour traçabilité).
Ces 3 étapes ne sont pas urgentes — le code legacy est dormant tant qu’il n’y a pas de row iv NOT NULL. Calendrier suggéré : Q3 2026 (après 2 mois de stabilité Transit).