ChinqIT VerifyChinqIT Verify

Authentification interne HMAC entre dashboard et gateway

Le dashboard et la gateway communiquent via un canal HMAC authentifié séparé du canal public. Ce document décrit le mécanisme de identité de l'appelant (per-caller identity) et la procédure de déploiement associée. Il est destiné aux opérateurs et aux revues d'incident.

Aperçu

Chaque appel interne (/internal/*, /api/v2/internal/webhooks/*, /api/v2/bulk/status-by-user/*) porte quatre en-têtes HMAC :

En-têteDescription
x-internal-signatureSignature HMAC-SHA256 du canonique
x-internal-timestampUnix timestamp, fenêtre ±60 s
x-internal-nonceUUID unique par requête (anti-rejeu)
x-internal-caller (phase B)Identité de l'appelant (dashboard, ops, ...)

Le canonique signé est METHOD:PATH:BODY:TS:NONCE[:CALLER]. Le segment :CALLER est ajouté en phase B (migrate) — voir §Procédure de déploiement.

Procédure de déploiement (expand → migrate → contract)

Le changement de format HMAC suit le pattern expand → migrate → contract sur trois PR distincts, pour rendre l'ordre de déploiement indifférent.

Phase A — Expand (cette PR)

  • Le gateway accepte deux formats : 5-field (legacy, sans :CALLER) et 6-field (avec :CALLER).
  • Le flag GATEWAY_INTERNAL_ALLOW_LEGACY_CANONICAL vaut true par défaut — les requêtes legacy sont acceptées.
  • Le dashboard continue d'émettre le format 5-field sans x-internal-caller. Aucun appel interne ne tombe.
  • Le middleware requireCaller('dashboard') est monté sur chaque route interne.

Phase B — Migrate (PR de suivi)

  • Le dashboard émet x-internal-caller: dashboard et signe le canonique 6-field.
  • Le gateway accepte déjà les deux formats. Aucun appel interne ne tombe.
  • Surveiller la ligne de log internal.legacy_canonical_used côté gateway. Quand elle disparaît pendant 24 h, le dashboard est entièrement migré.

Phase C — Contract (PR de suivi)

  • Mettre GATEWAY_INTERNAL_ALLOW_LEGACY_CANONICAL=0 dans l'env gateway. Aucun déploiement de code requis. Le branche 5-field est fermée par env.
  • Vérifier pendant 24 h : zéro ligne internal.legacy_canonical_used. Si OK, ouvrir un PR qui supprime la branche 5-field et la ligne de log.

Variables d'environnement

VariableDéfautEffet
GATEWAY_INTERNAL_SECRET(requis)Secret HMAC partagé. Plusieurs valeurs séparées par , acceptées (sharding).
GATEWAY_INTERNAL_ALLOWED_CALLERSdashboardAllowlist des appelants. Valeurs séparées par ,.
GATEWAY_INTERNAL_ALLOW_LEGACY_CANONICALtrue (unset ou 1)Quand true, accepte les requêtes 5-field sans x-internal-caller. Quand 0, exige le header.
INTERNAL_INTERNAL_SECRETS(unset)Legacy : sharded-secret list. Conservé pour rétro-compatibilité.
INTERNAL_HMAC_WINDOW_SEC60Fenêtre de timestamp symétrique (±60 s).

Logs

ÉvénementNiveauQuand
internal.caller_list_loadedinfoUne fois par démarrage du process.
internal.authenticatedinfoUne fois par requête authentifiée.
internal.legacy_canonical_usedwarnUne fois par process — au premier appel 5-field legacy. C'est la télémétrie de rollout : quand elle disparaît, le dashboard est migré.

Procédure d'incident

Tous les appels internes 401 après un déploiement ?

  1. Vérifier que GATEWAY_INTERNAL_SECRET est défini des deux côtés.
  2. Vérifier que le canonique calculé par le dashboard correspond à celui attendu par le gateway. Le canonique est METHOD:PATH:BODY:TS:NONCE (phase A) ou METHOD:PATH:BODY:TS:NONCE:CALLER (phase B+).
  3. Si GATEWAY_INTERNAL_ALLOW_LEGACY_CANONICAL=0 et le dashboard n'émet pas x-internal-caller, le remettre à 1 en attendant la migration du dashboard. Le flag est l'interrupteur d'urgence — il n'y a pas de bypass par code.

Un déploiement d'urgence pour fermer la branche legacy ?

Mettre GATEWAY_INTERNAL_ALLOW_LEGACY_CANONICAL=0. Aucun déploiement de code requis.

On this page