Paillasse/docs/adr/0004-https-csp-et-exposition.md
Adam Belkacemi 618cd7efbe passe le portail en HTTPS sur syllabuslab.fr, avec en-têtes de sécurité et CSP
Certificat Let's Encrypt obtenu et renouvelé par certbot (authentificateur
nginx), expiration surveillée par Prometheus. TLS selon Mozilla v6.0
intermediate, HSTS, CSP stricte avec nonce sur l'application et adaptée
sur la vitrine, xterm.js servi par le portail. Page de statut prévue sur
status.syllabuslab.fr, administration de Grafana et Kuma par tunnel seul.

Corrige aussi une faille XSS dans la page de classe, la page /cours en
erreur depuis l'étape 8, et NodeSource relancé à chaque déploiement.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-09 10:39:50 +02:00

61 lines
3.1 KiB
Markdown

# ADR 0004 — HTTPS, CSP en deux niveaux, et ce qui est exposé sur Internet
- **Date** : 2026-10-09
- **Statut** : accepté
## Contexte
Étape 12 : le portail passe sur `syllabuslab.fr` en HTTPS. Il faut un
certificat qui se renouvelle seul, des en-têtes de sécurité, une CSP
« adaptée à xterm.js », Grafana et Uptime Kuma derrière authentification,
et une page de statut publique.
## Décisions
1. **certbot du dépôt Debian, `certonly` avec l'authentificateur nginx.**
Il obtient et renouvelle le certificat sans jamais modifier nos fichiers :
Ansible reste seul maître du vhost. Pas d'e-mail ACME (Let's Encrypt
n'envoie plus d'avis d'expiration) : c'est Prometheus qui alerte
(`CertificatExpireBientot`, moins de 14 jours).
2. **TLS : Mozilla v6.0 « intermediate »** (TLS 1.2 et 1.3, suites ECDHE),
pour les vieux postes des établissements. Sans X25519MLKEM768 (OpenSSL
3.0 sur Debian 12) ni OCSP stapling (abandonné par Let's Encrypt).
HSTS 2 ans avec `includeSubDomains`, sans `preload` (réversible).
3. **CSP en deux niveaux, posée par Laravel** (elle dépend de la page) :
- *application* (connexion, inscription, toute page authentifiée) :
`script-src 'self' 'nonce-…'`. Les scripts en ligne portent le nonce
de la requête ; xterm.js est servi par le portail (Vite) et non plus
par jsDelivr ; les gestionnaires `onclick`/`onsubmit` sont remplacés
par des écouteurs. Une injection de script serait bloquée ;
- *vitrine* (pages reprises du design) : scripts en ligne et CDN
autorisés. Ces pages contiennent 52 scripts en ligne et le CDN
d'exécution de Tailwind ; elles n'affichent aucune donnée d'utilisateur.
Les violations sont remontées à `/csp-rapport` (journal Laravel).
4. **Administration de Grafana et d'Uptime Kuma : tunnel SSH seulement**
(choix d'Adam). Il faut la clé SSH, puis le mot de passe de l'outil.
Rien de plus n'est exposé sur Internet.
5. **Page de statut sur `status.syllabuslab.fr`** : Nginx ne laisse passer
que la page de statut, son API en lecture (GET/HEAD) et ses fichiers
statiques. Tableau de bord, `/socket.io` (connexion admin) et `/metrics`
renvoient 404. Le rôle n'active ce site que si le nom résout vers le
serveur, et ajoute alors le nom au certificat (`--expand`).
## Alternatives écartées
- **CSP stricte partout** : demanderait de réécrire les ~50 pages du design
(scripts en ligne, Tailwind par CDN). Reporté (voir `docs/dette.md`).
- **Grafana et Kuma publics derrière mot de passe** : pratique, mais exposés
à la force brute pour aucun besoin actuel.
- **certbot en snap** (recommandation du projet certbot) : une deuxième
chaîne de mises à jour à surveiller ; le paquet Debian suit
unattended-upgrades comme le reste.
## Conséquences
- Toute nouvelle page de l'application qui ajoute un script doit lui donner
`nonce="{{ Vite::cspNonce() }}"`, sinon le navigateur le bloque (et le
signale dans le journal).
- `Permissions-Policy` interdit caméra et micro : à ouvrir pour la visio
(étape 15).
- Les tests et scripts doivent passer par `https://syllabuslab.fr` : le
cookie de session est `secure`.