fix(securite): supprime le secret JWT de repli présent dans le dépôt

JWT_SECRET retombait sur "data-sentinel-secret-change-in-prod", une valeur
lisible par quiconque a accès au code : un oubli de configuration suffisait
à permettre de forger un jeton d'administrateur.

Sans JWT_SECRET, une clé aléatoire est désormais tirée au démarrage, avec un
avertissement explicite. Le démarrage n'est volontairement pas bloqué : un
oubli de variable d'environnement ne doit pas transformer une configuration
incomplète en indisponibilité totale du service. Contrepartie assumée et
documentée : les sessions ne survivent pas à un redémarrage tant que la
variable n'est pas définie.

Vérifié : la production signe déjà avec un secret propre, ce correctif ne
change donc rien à son fonctionnement.

Ajoute par ailleurs APP_BUILD, injecté par la CI depuis le SHA du commit et
exposé par GET /health (et /version.json côté front). Jusqu'ici, rien ne
permettait de savoir quelle version tournait réellement : un déploiement
non appliqué était indiscernable d'un déploiement réussi.
This commit is contained in:
2026-08-15 14:46:49 +02:00
parent cb84e20e9a
commit 4bc4770e2d
6 changed files with 74 additions and 6 deletions
+20 -1
View File
@@ -34,7 +34,8 @@ sur `localhost`. Pour une instance nommée, définir `DB_SERVER` (ex.
| `DB_TRUSTED_CONNECTION` | force l'authentification Windows même si `DB_USER` est défini | — |
| `DB_DRIVER` | pilote ODBC | `ODBC Driver 18 for SQL Server` |
| `CORS_ORIGINS` | origines autorisées (séparées par `,`) | `localhost:5173,localhost:3000` |
| `JWT_SECRET` | clé de signature JWT | placeholder (à définir en prod) |
| `JWT_SECRET` | clé de signature JWT **obligatoire en déploiement** | clé aléatoire régénérée à chaque démarrage |
| `APP_BUILD` | SHA du commit construit, injecté par la CI et exposé par `/health` | `local` |
| `JWT_ALGORITHM` / `JWT_EXPIRE_MINUTES` | algo / durée du token | `HS256` / `60` |
## Authentification & rôles
@@ -96,8 +97,26 @@ routeurs). Chaque domaine fonctionnel vit dans `routers/` :
Spécification complète : `GET /openapi.json` (export dans `docs/openapi.json`).
## Vérifier qu'un déploiement a pris
`GET /health` expose le SHA du commit dont l'image a été construite :
```bash
curl -s https://datasentinel-api.nfteam.ovh/health
# {"api":"ok","database":"ok","version":"1.0.0","build":"cb84e20e1f2a",...}
```
Comparer `build` au dernier commit poussé sur `main`. S'ils diffèrent, le
conteneur tourne encore une ancienne image : `docker compose pull` puis
`docker compose up -d` (un `up -d` seul ne retélécharge rien). Le front expose
la même information sur `/version.json`.
## Sécurité
- `JWT_SECRET` doit être défini en déploiement. À défaut, l'API démarre quand
même mais tire une clé aléatoire à chaque lancement (sessions perdues au
redémarrage) : aucun secret de repli n'est écrit dans le dépôt, un secret
public permettrait de forger un jeton d'administrateur.
- En-têtes : `X-Content-Type-Options`, `X-Frame-Options`, `Referrer-Policy`, `Strict-Transport-Security`.
- CORS restreint aux origines `CORS_ORIGINS`, tous verbes + credentials.
- Requêtes SQL **paramétrées** (noms de tables/colonnes whitelistés) ; le compte applicatif