62 lines
3.1 KiB
Markdown
62 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`.
|