# 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 un enregistrement A : champ « Sous-domaine » = `status` (seulement : OVH ajoute `.syllabuslab.fr` ; saisir le nom complet crée `status.syllabuslab.fr.syllabuslab.fr`), cible `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), menu « Pages de statut » (pas « Ajouter une sonde ») : créer une page dont l'identifiant (slug) est `syllabus`, y ajouter les sondes à publier, enregistrer. Vérifier : `curl -m 5 http://127.0.0.1:3001/api/status-page/syllabus` sur le serveur doit répondre (Kuma 1.23 ne répond jamais pour une page inexistante). 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 : ``` ``` 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`.