Chapitre 7
Sécurité
Les mesures de sécurité en place dans la plateforme et sur le serveur, et ce qui reste de la responsabilité de l'exploitant.
Concerne :Équipe techniqueHébergeur
Transport et en-têtes#
- HTTPS obligatoire : Caddy redirige HTTP vers HTTPS et renouvelle seul le certificat (Let's Encrypt). HTTP/2 et HTTP/3 sont servis.
- En-têtes ajoutés par Caddy :
Strict-Transport-Security(un an, sous-domaines compris),X-Content-Type-Options: nosniff,X-Frame-Options: DENY,Referrer-Policy: strict-origin-when-cross-origin,Permissions-Policy(caméra, micro et géolocalisation refusés) ; l'en-têteServerest retiré. Politique de sécurité du contenu (CSP), envoyée par l'application : scripts du site seulement, aucun script en ligne, aucune ressource ni connexion vers un autre site.
default-src 'self'; script-src 'self'; style-src 'self' 'unsafe-inline'; img-src 'self' data: blob:; font-src 'self' data:; connect-src 'self'; object-src 'none'; base-uri 'self'; frame-ancestors 'self'; form-action 'self'Le module hors ligne (
/terrain/) a sa propre politique, qui ajoute'wasm-unsafe-eval'(exigé par WebAssembly).- État de santé :
/health(qui interroge la base) est réservé au contrôle interne de Docker ; Caddy répond 404 à l'extérieur.
Comptes et sessions#
- Mots de passe hachés (ASP.NET Identity), de 8 à 128 caractères dont un chiffre.
- Verrouillage : après 5 échecs, le compte est bloqué 15 minutes.
- Limitation par adresse IP : 10 tentatives de connexion par minute, 5 demandes d'inscription et 5 demandes « mot de passe oublié » par heure, 300 appels à l'API par minute (réglables, voir Configuration). Au-delà : réponse 429.
- Session : cookie
read.sessionHttpOnly,Secureen HTTPS,SameSite=Lax, fermée après 30 minutes d'inactivité. Un compte désactivé ou dont le rôle change perd son accès dans la minute. - Lien « mot de passe oublié » : valable une heure, utilisable une fois ; le message affiché est le même que le compte existe ou non.
- Mot de passe temporaire (compte créé par l'administrateur, premier administrateur) : à changer avant toute autre action.
- API : jetons seulement (jamais le cookie du site), compte revérifié à chaque appel (chapitre API et module hors ligne).
Autorisations et données#
- Les autorisations (rôle et périmètre géographique) sont appliquées dans les services de l'application, jamais dans les seules pages : un écran caché n'est jamais la seule protection. Une donnée hors du périmètre du compte répond 404, une action non autorisée 403. Une matrice d'accès automatisée vérifie chaque route pour chaque rôle.
- Base : l'application se connecte avec un rôle restreint (
POSTGRES_APP_USER) qui n'est pas propriétaire des tables et ne peut ni modifier ni effacer le journal d'audit. Le compte propriétaire ne sert qu'aux migrations et aux scripts de sauvegarde. Le port de la base n'est pas publié. - Journal d'audit : chaque écriture, connexion, échec de connexion, export et téléchargement de fichier restreint y est inscrit, avec l'adresse IP réelle du client.
- Protection des personnes : aucune donnée nominative de bénéficiaire (effectifs agrégés) ; photos d'enfants sous consentement, sans métadonnées de localisation, jamais publiques ; listes de présence réservées à l'équipe projet et supprimées à échéance ; petits effectifs masqués sur le portail public.
Serveur#
Mesures prises à l'installation :
- SSH par clé seulement, connexion
rootinterdite ; - pare-feu
ufw: 22, 80 et 443 seulement ; - mises à jour de sécurité automatiques du système ;
- secrets dans
/opt/read/.env(droits 600), jamais dans le dépôt de code ni dans l'image ; - conteneur de l'application exécuté sous un utilisateur non
root; - journaux Docker bornés (5 fichiers de 10 Mo par conteneur).
Responsabilités de l'exploitant#
| Fréquence | Action |
|---|---|
| Chaque jour | Vérifier le compte rendu de la sauvegarde (copie hors serveur comprise) |
| Chaque mois | Mettre à jour les images (Mise à jour mensuelle) ; restauration d'essai |
| Chaque mois | Vérifier les comptes SSH autorisés (~/.ssh/authorized_keys) et les comptes d'administrateur de la plateforme |
| À chaque départ | Retirer la clé SSH de la personne ; faire désactiver ses comptes par l'administrateur ; changer les secrets qu'elle connaissait |
| En cas d'incident | Conserver les journaux (Supervision) avant toute remise en état ; consulter le journal d'audit |
Attention
Les clés de protection des données (volume app-keys) sont enregistrées en clair dans le volume, ce qui est acceptable sur un serveur dédié ; elles sont chiffrées dans la copie hors serveur. Ne copiez jamais ce volume ailleurs sans chiffrement.
Signaler ou traiter une compromission#
Si vous soupçonnez un accès illégitime :
- Gardez une copie des journaux (
docker compose logs, volumeapp-logs) et faites une sauvegarde. - Faites désactiver par l'administrateur les comptes concernés ; changez les mots de passe exposés.
- Pour couper tous les accès d'un coup (sessions et appareils du module hors ligne), changez les secrets de la base, puis remplacez les clés de protection des données : arrêtez
app, videz le volumeapp-keys, redémarrez. Tous les utilisateurs devront se reconnecter. - Examinez le journal d'audit (écran Journal d'audit de l'administrateur) pour mesurer l'étendue des actions.