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>
This commit is contained in:
parent
aa004c0736
commit
618cd7efbe
30 changed files with 987 additions and 24 deletions
60
docs/runbooks/https.md
Normal file
60
docs/runbooks/https.md
Normal file
|
|
@ -0,0 +1,60 @@
|
|||
# Runbook — HTTPS, en-têtes de sécurité, page de statut (étape 12)
|
||||
|
||||
## Où sont les choses
|
||||
|
||||
| Élément | Emplacement |
|
||||
|---|---|
|
||||
| Certificat | `/etc/letsencrypt/live/syllabuslab.fr/` (un seul certificat : `syllabuslab.fr`, `www`, et `status` quand son DNS existe) |
|
||||
| Renouvellement | `certbot.timer` (deux fois par jour), authentificateur nginx, puis `systemctl reload nginx` |
|
||||
| Alerte d'expiration | métrique `syllabus_certificat_expiration_timestamp` (script `/usr/local/sbin/syllabus-expiration-certificat`, cron quotidien), règles `CertificatExpireBientot` et `CertificatNonMesure` (`kolla/config/prometheus/alertes.rules`) |
|
||||
| Vhost | `ansible/roles/portail/templates/nginx-portail.conf.j2` → `/etc/nginx/sites-available/portail.conf` |
|
||||
| TLS et en-têtes | `/etc/nginx/snippets/syllabus-tls.conf`, `syllabus-entetes.conf` (rôle `portail`) |
|
||||
| CSP | `portail/app/Http/Middleware/PolitiqueSecuriteContenu.php` ; violations dans `storage/logs/laravel.log` (« Violation CSP ») |
|
||||
| Décisions | [ADR 0004](../adr/0004-https-csp-et-exposition.md) |
|
||||
|
||||
Tout est posé par `ansible-playbook portail.yml`.
|
||||
|
||||
## Vérifier
|
||||
|
||||
```
|
||||
curl -sSI https://syllabuslab.fr/connexion | grep -iE "strict-transport|content-security|x-frame"
|
||||
echo | openssl s_client -connect syllabuslab.fr:443 -servername syllabuslab.fr 2>/dev/null | openssl x509 -noout -dates -ext subjectAltName
|
||||
ssh paillasse "sudo certbot renew --dry-run" # renouvellement simulé (environnement de test Let's Encrypt)
|
||||
ssh paillasse "sudo grep -c 'Violation CSP' /var/www/portail/storage/logs/laravel.log"
|
||||
```
|
||||
|
||||
## Activer la page de statut
|
||||
|
||||
1. Ajouter chez OVH : `status.syllabuslab.fr` A `163.172.4.195`.
|
||||
2. Vérifier qu'il est publié : `dig +short A status.syllabuslab.fr @ns111.ovh.net`.
|
||||
3. Dans Uptime Kuma (par tunnel), créer une page de statut avec l'identifiant (slug) `syllabus` et y mettre les sondes à publier.
|
||||
4. `cd ansible && script -q /dev/null ansible-playbook portail.yml -i inventory.ini` : le rôle détecte le nom, l'ajoute au certificat et active le site.
|
||||
5. Vérifier : `https://status.syllabuslab.fr` affiche la page ; `https://status.syllabuslab.fr/dashboard` et `/metrics` répondent 404.
|
||||
|
||||
## Si le certificat va expirer (alerte)
|
||||
|
||||
```
|
||||
ssh paillasse "systemctl status certbot.timer; sudo journalctl -u certbot --since -3d | tail -30"
|
||||
ssh paillasse "sudo certbot renew"
|
||||
```
|
||||
|
||||
Causes probables : port 80 inaccessible depuis Internet, DNS modifié,
|
||||
configuration Nginx invalide (`sudo nginx -t`). Limite Let's Encrypt :
|
||||
5 échecs de validation par heure et par nom — corriger avant de réessayer.
|
||||
|
||||
## Ajouter un script à une page de l'application
|
||||
|
||||
La CSP stricte bloque tout script sans le nonce de la requête :
|
||||
|
||||
```
|
||||
<script nonce="{{ Vite::cspNonce() }}">…</script>
|
||||
```
|
||||
|
||||
Pas de `onclick="…"` : utiliser `addEventListener` dans un script avec nonce.
|
||||
Pas de CDN : passer par Vite (`resources/js/`).
|
||||
|
||||
## Pièges (évités ou rencontrés)
|
||||
|
||||
- Évité par conception : une redirection `return 301` au niveau `server` s'exécute avant toute `location`, elle risquerait de court-circuiter le défi ACME que certbot insère au renouvellement. Les redirections sont dans `location /` ; `certbot renew --dry-run` réussit.
|
||||
- `X25519MLKEM768` (recommandé par Mozilla v6.0) demande OpenSSL 3.5 ; Debian 12 a OpenSSL 3.0 : retiré par précaution (non essayé). À réintroduire au passage à Debian 13.
|
||||
- Depuis Internet, un scan peut montrer 21, 554 et 1723 ouverts : c'est la box du réseau qui scanne (même résultat vers `192.0.2.1`, adresse inexistante). Côté serveur : `sudo ss -tlnp` et `sudo nft list chain inet filter input`.
|
||||
Loading…
Add table
Add a link
Reference in a new issue