Chapitre 9.3 — Contrôle d’accès & habilitations
⏱️ TL;DR — La question centrale de la confidentialité, c’est « qui peut voir quoi ? ». La réponse tient en un principe : le moindre privilège — chacun n’accède qu’aux données strictement nécessaires à son rôle, et rien de plus. On l’outille avec des rôles (RBAC), une authentification forte (MFA) sur les accès sensibles, une revue régulière des accès, un cloisonnement (un formateur ne voit que ses stagiaires) et une journalisation des accès aux données sensibles. Une matrice d’habilitations met tout ça noir sur blanc — et la rend démontrable.
🎯 Objectifs
- Appliquer le principe du moindre privilège à un système réel.
- Concevoir des rôles (RBAC) au lieu de droits attribués à la main, un par un.
- Savoir où imposer une authentification forte (MFA) et pourquoi.
- Mettre en place une revue des accès et un cloisonnement par périmètre.
- Journaliser les accès aux données sensibles et rédiger une matrice d’habilitations.
Le moindre privilège : le réflexe de base
Le principe du moindre privilège : chaque personne (et chaque service, et chaque clé d’API) ne reçoit que les droits strictement nécessaires à sa tâche, pour la durée nécessaire. C’est la traduction, côté accès, du principe de minimisation : on ne donne pas « tout » par confort, on donne « juste ce qu’il faut ».
Le mauvais réflexe, très répandu : tout le monde est admin, « ce sera plus simple ». C’est l’inverse de la sécurité. Chaque droit accordé en trop est une surface d’attaque supplémentaire : un compte compromis, une erreur humaine, un départ mal géré, et c’est toute la base qui est exposée au lieu d’un périmètre restreint.
⚠️ Piège — Le compte admin partagé : un seul login
admin/ mot de passe que toute l’équipe utilise. Résultat : impossible de savoir qui a fait quoi (pas de traçabilité), impossible de révoquer l’accès d’une personne qui part (il faudrait changer le mot de passe de tous), et un seul secret qui traîne partout. Chacun doit avoir son compte nominatif, avec ses droits.
💡 Réflexe — Par défaut, zéro accès, puis on ajoute ce qui est nécessaire — jamais l’inverse (« tout ouvert, on restreindra plus tard » ne restreint jamais). À chaque nouveau besoin, la question est « quel est le minimum pour cette tâche ? », pas « qu’est-ce qui serait pratique d’avoir ? ».
Des rôles, pas des droits à la main : le RBAC
Attribuer les droits personne par personne ne passe pas l’échelle et finit en désordre. La bonne approche est le RBAC (Role-Based Access Control) : on définit des rôles (formateur, gestionnaire, support, admin), on attache des permissions à chaque rôle, et on assigne un rôle aux personnes. Ajouter un formateur, c’est lui donner le rôle « formateur » — pas recocher quinze cases à la main.
// Rôles et permissions déclarés une fois, réutilisés partout
type Role = "formateur" | "gestionnaire" | "support" | "admin"
const permissions: Record<Role, string[]> = {
formateur: ["stagiaire:lire:sesGroupes", "resultat:lire:sesGroupes"],
gestionnaire:["stagiaire:lire", "stagiaire:ecrire", "facturation:lire"],
support: ["ticket:lire", "ticket:ecrire"], // PAS d'accès aux données santé
admin: ["*"], // à réserver à très peu de personnes, avec MFA obligatoire
}
function peut(role: Role, action: string): boolean {
const p = permissions[role]
return p.includes("*") || p.includes(action)
}L’intérêt : les droits deviennent lisibles (on voit d’un coup d’œil ce que chaque rôle peut faire), auditables et cohérents. Le rôle admin avec "*" doit rester exceptionnel — le moins de personnes possible, et toujours protégé par MFA.
Authentification forte (MFA) sur les accès sensibles
Un mot de passe seul, même haché côté serveur, ne suffit pas pour les accès à fort pouvoir : il peut être deviné, hameçonné ou réutilisé depuis une fuite ailleurs. L’authentification à plusieurs facteurs (MFA / 2FA) ajoute un second facteur (application d’authentification, clé physique) : voler le mot de passe ne suffit plus pour entrer.
Où l’imposer en priorité :
- Tous les comptes à privilèges : admin, accès à la prod, accès aux données sensibles.
- Les outils d’infrastructure (hébergeur, base, dépôt de code, gestionnaire de secrets).
- Idéalement, la proposer à tous les utilisateurs pour protéger leurs comptes.
💡 Réflexe — La MFA est la mesure au meilleur rapport effort/protection contre la compromission de comptes. Si tu ne dois en imposer qu’à un seul endroit, commence par les accès administrateur et les outils d’infrastructure : ce sont les clés du royaume.
Revue des accès : les droits périment
Les habilitations ne sont pas « à vie ». Les gens changent de poste, un besoin temporaire devient permanent par oubli, un prestataire termine sa mission. Sans entretien, les droits s’accumulent (le fameux privilege creep) : au bout de deux ans, plus personne ne sait qui a accès à quoi ni pourquoi.
D’où la revue périodique des accès : à intervalle régulier (par exemple chaque trimestre ou semestre), on relit la liste des personnes et de leurs droits, et on retire tout ce qui n’est plus justifié. C’est simple, peu coûteux, et c’est une preuve d’accountability (on documente la revue et ses décisions).
Cloisonnement : chacun dans son périmètre
Le RBAC dit quel type d’action un rôle peut faire ; le cloisonnement dit sur quelles données. Les deux se combinent. Un formateur a le droit de « lire les stagiaires » — mais uniquement les siens, pas ceux des autres formateurs ni ceux d’un autre organisme. C’est le cloisonnement par périmètre (souvent appelé multi-tenant ou par groupe).
// Le rôle autorise l'action ; le cloisonnement restreint AUX données du périmètre.
async function lireStagiaires(user: Utilisateur) {
if (!peut(user.role, "stagiaire:lire:sesGroupes") && !peut(user.role, "stagiaire:lire")) {
throw new Error("Accès refusé")
}
// Un formateur ne voit QUE les stagiaires de ses groupes.
if (user.role === "formateur") {
return db.stagiaires.findMany({ where: { groupeId: { in: user.groupeIds } } })
}
// Un gestionnaire voit son organisme, pas les autres.
return db.stagiaires.findMany({ where: { organisationId: user.organisationId } })
}Sans cloisonnement, une requête « liste des stagiaires » renvoie tout le monde : c’est une fuite de données massive à un WHERE près. Le cloisonnement se code dans la couche d’accès aux données, pas seulement dans l’interface (masquer un bouton n’empêche pas d’appeler l’API directement).
⚠️ Piège — La référence directe non contrôlée : l’URL
/stagiaires/4187charge le stagiaire4187sans vérifier qu’il appartient au périmètre de l’utilisateur connecté. Un formateur curieux change le numéro et lit le dossier d’un stagiaire qui n’est pas le sien. Toujours vérifier, côté serveur, que la ressource demandée est dans le périmètre autorisé de l’appelant.
Journaliser les accès aux données sensibles
Pour les données sensibles (santé, mineurs, éléments intimes), le contrôle d’accès préventif ne suffit pas : il faut aussi une trace a posteriori de qui a consulté quoi, et quand. Cette journalisation des accès (à ne pas confondre avec les logs applicatifs du chapitre 9.5) sert à détecter les consultations anormales, à enquêter après un incident, et à dissuader les accès curieux (« je sais que c’est tracé »).
Ce qu’on journalise pour un accès sensible : qui (identité de l’agent), quoi (quelle ressource, pas son contenu en clair), quand, éventuellement pourquoi (motif). Et ces journaux d’accès sont eux-mêmes protégés et à accès restreint — sinon ils deviennent une seconde fuite.
📚 Le texte — Le contrôle d’accès et la journalisation relèvent de la confidentialité et de l’intégrité exigées par l’article 32, prolongement du 6e principe (art. 5.1.f). La CNIL en fait un attendu constant de ses contrôles (gestion des habilitations, traçabilité des accès aux données sensibles) ; ses guides sécurité détaillent les bonnes pratiques.
Une matrice d’habilitations (exemple)
La matrice d’habilitations met par écrit « qui a le droit de faire quoi sur quelles données ». C’est l’outil qui rend le contrôle d’accès lisible et démontrable. Exemple pour FormaCampus :
| Rôle | Comptes stagiaires | Résultats / notes | Aménagements (santé) | Facturation | Journaux d’accès | Admin technique |
|---|---|---|---|---|---|---|
| Formateur | Lecture — ses groupes | Lecture/écriture — ses groupes | ❌ Aucun | ❌ | ❌ | ❌ |
| Gestionnaire OF | Lecture/écriture — son organisme | Lecture — son organisme | ❌ (sauf strict besoin justifié) | Lecture | ❌ | ❌ |
| Référent handicap | Lecture — périmètre défini | ❌ | Lecture/écriture — accès journalisé | ❌ | ❌ | ❌ |
| Support | Lecture limitée | ❌ | ❌ | ❌ | ❌ | ❌ |
| Admin technique | Selon besoin, MFA | Selon besoin, MFA | ❌ par défaut (accès exceptionnel tracé) | ❌ | Lecture | ✅ MFA |
Deux enseignements de cette matrice : les aménagements de handicap (santé) sont visibles par très peu de rôles et l’accès est journalisé ; l’admin technique a du pouvoir sur l’infrastructure mais pas un accès banalisé aux données santé. Le pouvoir technique et l’accès aux données sensibles sont deux choses différentes.
🧭 Sur FormaCampus — On applique : comptes nominatifs (zéro compte partagé), rôles RBAC (formateur, gestionnaire, référent handicap, support, admin), MFA obligatoire sur admin et accès prod, cloisonnement strict (un formateur ne voit que ses groupes, un organisme ne voit que ses stagiaires), journalisation des accès aux aménagements de handicap, et revue des accès chaque trimestre avec retrait des droits obsolètes. La matrice ci-dessus est versionnée dans la doc de conformité.
🔒 Côté personne concernée — Un stagiaire s’attend à ce que son formateur voie ses résultats — pas à ce que n’importe quel formateur de la plateforme, ou le support, puisse ouvrir son dossier de santé « par curiosité ». Le cloisonnement et la journalisation, c’est exactement cette attente traduite en technique : le bon interlocuteur voit ce qu’il doit voir, et chaque accès à une donnée intime laisse une trace.
✏️ Exercices
Exercice 1 — Trop de droits ? Dans une équipe de 8 personnes, 6 ont le rôle admin « parce que c’est pratique ». Cite trois risques concrets et propose la correction.
✅ Solution
Risques : (1) surface d’attaque énorme — 6 comptes qui, compromis, ouvrent toute la base ; (2) aucune traçabilité utile (tout le monde peut tout, difficile d’imputer une action) ; (3) erreurs humaines à fort impact (un admin peut supprimer ou exfiltrer par mégarde). Correction : appliquer le moindre privilège — définir des rôles précis (support, gestionnaire, formateur), réserver admin à 1-2 personnes avec MFA, retirer les droits superflus, et journaliser les actions d’administration. Documenter la nouvelle matrice.
Exercice 2 — Le formateur curieux. Ton API expose GET /api/stagiaires/:id. Un formateur remplace l’id de son stagiaire par un autre et obtient le dossier d’un stagiaire d’un autre organisme. Quelle est la faille et comment la corriger ?
✅ Solution
C’est une référence directe non contrôlée (absence de cloisonnement côté serveur). L’endpoint vérifie sans doute que l’utilisateur est authentifié et a le rôle formateur, mais pas que le stagiaire demandé est dans son périmètre. Correction : côté serveur, après avoir chargé le stagiaire, vérifier qu’il appartient bien à un groupe/organisme de l’appelant (WHERE groupeId IN user.groupeIds), sinon renvoyer un refus. Ne jamais se reposer sur l’interface (masquer un lien n’empêche pas d’appeler l’API). Le cloisonnement se code dans la couche données.
Exercice 3 — Où mettre la MFA d’abord ? Budget limité, tu ne peux imposer la MFA que sur un périmètre pour commencer. Lequel, et pourquoi ?
✅ Solution
Sur les comptes à privilèges et les outils d’infrastructure : admin de la plateforme, accès à la prod, hébergeur, base de données, dépôt de code, gestionnaire de secrets. Raison : ce sont les clés du royaume — leur compromission expose l’ensemble des données, alors qu’un compte utilisateur standard n’expose que lui-même. La MFA sur ces accès offre le meilleur rapport effort/protection. On étend ensuite aux utilisateurs (au moins en option).
🧠 Quiz de révision
1. Qu’est-ce que le principe du moindre privilège ?
Chaque personne, service ou clé ne reçoit que les droits strictement nécessaires à sa tâche, pour la durée nécessaire — et rien de plus. C’est la minimisation appliquée aux accès. Par défaut zéro accès, on ajoute ce qui est justifié, jamais l’inverse.
2. Pourquoi préférer le RBAC à des droits attribués à la main ?
Parce que les rôles (permissions attachées à un rôle, rôle attribué aux personnes) rendent les droits lisibles, cohérents et auditables, et passent à l’échelle. Ajouter quelqu’un = lui donner un rôle, pas recocher des dizaines de cases. Le rôle admin tout-puissant doit rester exceptionnel et protégé par MFA.
3. Où faut-il imposer la MFA en priorité ?
Sur les comptes à privilèges (admin, prod, données sensibles) et les outils d’infrastructure (hébergeur, base, dépôt de code, secrets). Ce sont les accès dont la compromission expose tout le système. La MFA fait que voler le mot de passe ne suffit plus pour entrer.
4. Qu’est-ce que le cloisonnement, et en quoi diffère-t-il du RBAC ?
Le RBAC dit quel type d’action un rôle peut faire ; le cloisonnement dit sur quelles données (le périmètre). Un formateur a le droit de « lire des stagiaires » mais seulement les siens. Le cloisonnement se code côté serveur, dans la couche données — masquer un bouton dans l’interface ne suffit pas.
5. Pourquoi journaliser les accès aux données sensibles ?
Pour garder une trace a posteriori de qui a consulté quoi et quand : détecter les consultations anormales, enquêter après incident, et dissuader les accès curieux. Ces journaux d’accès sont eux-mêmes protégés et à accès restreint. C’est complémentaire du contrôle d’accès préventif, pas un substitut.
Chapitre suivant : Sécurité organisationnelle — parce que la sécurité n’est pas que technique : sensibilisation, gestion des départs, procédures, et le facteur humain, 1re cause d’incident.