Aller au contenu

Anonymisation et pseudonymisation d’une base ScoDoc

Informations techniques

  • Cette page est destinée aux personnes qui souhaitent approfondir leur compréhension des traitements de pseudonymisation effectué par ScoDoc. Pour un usage normal, la documentation sur le RGPD est suffisante.

Le RGPD impose de limiter la conservation des données personnelles à la durée nécessaire aux finalités du traitement. Le script tools/anonymize_db.py permet de supprimer ou de remplacer certaines données personnelles anciennes tout en conservant une partie de l’historique scolaire nécessaire aux statistiques et au suivi des cohortes.

Ce traitement constitue principalement une pseudonymisation, et non une anonymisation irréversible au sens strict du RGPD. L'ensemble des données personnelle est supprimé ou remplacé par des valeurs fictives, mais, par des croisements et recoupements avec d'éventuelles sources de données externes, il peut être théoriquement possible de remonter à des données personnelles. C'est un scénario très peu réaliste en situation réelle, mais la base pseudonymisée doit restée protégée, et surtout ne pas passer en accès public.

Précautions d’utilisation

Le script modifie directement une base PostgreSQL ScoDoc. Avant de l’utiliser en production :

  1. avertir les utilisateurs et arrêter le serveur ScoDoc et les traitements susceptibles de modifier la base ;
  2. effectuer et vérifier une sauvegarde (bases sql et fichiers annexes ScoDoc) ;
  3. tester d’abord le traitement avec --dry-run ;
  4. vérifier la date limite et la liste des étudiants et semestres affichée ;
  5. exécuter le traitement réel ;
  6. supprimer séparément les fichiers signalés par le script ;
  7. contrôler la base avant de remettre le service en production.

Il est préférable de tester initialement le traitement sur une copie récente de la base.

Le script s’exécute avec l’utilisateur système scodoc, PostgreSQL étant démarré :

cd /opt/scodoc
tools/anonymize_db.py [options] NOM_BASE

Toutes les opérations sont exécutées dans une transaction unique. En cas d’erreur, la transaction n’est pas validée. Les tables temporaires utilisées sont supprimées au COMMIT ou au ROLLBACK.

Le traitement prend typiquement de l'ordre de 10 secondes à quelques minutes, suivant la taille de votre base et votre serveur. Une transaction importante peut produire du WAL (Write-Ahead Log), conserver des verrous et retarder le nettoyage par PostgreSQL. Il est donc préférable d’exécuter le traitement hors période d’activité.

Rappel: en production, la base de données postgresql est nommée SCODOC.

Sélection des étudiants

Par défaut, tous les étudiants sont traités.

Avec une date limite :

tools/anonymize_db.py --before 2020-01-01 NOM_BASE

un étudiant est sélectionné si la date de fin la plus récente de tous les formsemestres auxquels il a été inscrit est strictement antérieure à celle fournie (1er janvier 2020 dans l'exemple ci-dessus).

MAX(notes_formsemestre.date_fin) < '2020-01-01'

Les étudiants sans aucune inscription sont exclus lorsque --before est utilisé. Sans --before, tous les étudiants de identite sont sélectionnés.

Note technique: la sélection est enregistrée dans la table temporaire indexée students_to_anonymize.

Utilisation du script

Le script modifie directement une base PostgreSQL ScoDoc. Avant son exécution en production :

  1. arrêter le serveur ScoDoc et les traitements susceptibles d’écrire dans la base ;
  2. effectuer et vérifier une sauvegarde PostgreSQL ;
  3. tester le traitement avec --dry-run ;
  4. vérifier le nombre d’étudiants, les semestres et les fichiers affichés ;
  5. exécuter le traitement réel avec --archives-file ;
  6. utiliser ensuite un script distinct pour supprimer les fichiers listés ;
  7. contrôler la base avant de redémarrer ScoDoc.

Il est recommandé de tester préalablement le traitement sur une copie récente de la base.

Syntaxe

Le script doit être lancé avec l’utilisateur système scodoc, PostgreSQL étant démarré :

cd /opt/scodoc

tools/anonymize_db.py \
  [--users | --all-users | --only-users] \
  [--no-students | --only-students] \
  [--before YYYY-MM-DD] \
  [--archives-file CHEMIN] \
  [--dry-run] \
  NOM_BASE

Options

Option Effet
--before YYYY-MM-DD Définit la date limite. Pour les étudiants, leur dernier formsemestre doit se terminer strictement avant cette date. Avec --users, le compte doit être inactif et sa dernière activité antérieure à cette date.
--users Traite aussi les utilisateurs vérifiant active = FALSE et last_seen < before. Nécessite --before.
--all-users Traite aussi tous les utilisateurs, sans filtre sur active ou last_seen.
--only-users Traite tous les utilisateurs sans traiter les étudiants ni la configuration générale.
--no-students Ne traite pas les étudiants. Peut être combiné avec --users --before pour traiter uniquement les anciens comptes inactifs.
--only-students Ne traite que les étudiants, sans utilisateurs ni configuration générale.
--archives-file CHEMIN Après un COMMIT réussi, écrit les archives et photos à supprimer dans le fichier indiqué, à raison d’un chemin relatif par ligne. Nécessite le traitement des étudiants.
--dry-run Exécute toutes les requêtes puis effectue un ROLLBACK. La base reste inchangée et aucun manifeste de fichiers n’est écrit.
-h, --help Affiche l’aide.

Exemples

Simuler le traitement des anciens étudiants :

tools/anonymize_db.py \
  --dry-run \
  --before 2020-01-01 \
  NOM_BASE

Traiter les anciens étudiants et produire le manifeste des fichiers à supprimer :

tools/anonymize_db.py \
  --before 2020-01-01 \
  --archives-file /tmp/archives-a-supprimer.txt \
  NOM_BASE

Traiter les anciens étudiants et les anciens comptes utilisateurs inactifs :

tools/anonymize_db.py \
  --users \
  --before 2020-01-01 \
  --archives-file /tmp/archives-a-supprimer.txt \
  NOM_BASE

Ne traiter que les anciens comptes utilisateurs inactifs :

tools/anonymize_db.py \
  --no-students \
  --users \
  --before 2020-01-01 \
  NOM_BASE

Traiter tous les étudiants et tous les utilisateurs :

tools/anonymize_db.py \
  --all-users \
  --archives-file /tmp/archives-a-supprimer.txt \
  NOM_BASE

Ne traiter que les étudiants :

tools/anonymize_db.py \
  --only-students \
  --before 2020-01-01 \
  --archives-file /tmp/archives-a-supprimer.txt \
  NOM_BASE

Manifeste des fichiers à supprimer

Le manifeste contient des chemins relatifs à :

/opt/scodoc-data

Exemple :

archives/docetuds/8/21219
archives/justificatifs/8/21219/2026-03-16-13-56-47
photos/F44/RT_21219.jpg
photos/F44/RT_21219.h90.jpg

Il est trié et ne contient pas de doublons. Les archives et photos ne sont pas supprimées par anonymize_db.py (mais par un autre script à lancer séparément).

Transaction

Les opérations SQL sont exécutées dans une transaction unique. Les tables temporaires sont supprimées lors du COMMIT ou du ROLLBACK.

Le manifeste est préparé avant la validation, mais n’est publié au chemin demandé qu’après un COMMIT réussi. En cas d’échec du commit, le manifeste temporaire est supprimé.

Données étudiantes traitées

Identité

Dans identite :

Champ Traitement
nom, prenom Remplacés par des noms et prénoms fictifs.
nom_usuel Mis à NULL.
civilite_etat_civil, prenom_etat_civil Mis à NULL.
date_naissance Ramenée au 1er janvier de l’année de naissance.
lieu_naissance, dept_naissance, nationalite Remplacés par ?.
statut Mis à NULL.
boursier Mis à FALSE.
photo_filename Mis à NULL.
code_nip, code_ine, code_pegase_apprenant, scodoc7_id Mis à NULL.

Exemple :

2001-03-15 → 2001-01-01

L’année de naissance est conservée pour permettre des statistiques par âge ou cohorte.

Les fichiers physiques des photos correspondant à photo_filename sont ajoutés au manifeste pour suppression séparée.

Adresses et coordonnées

Dans adresse :

  • email devient ano@nyme.fr ;
  • emailperso, description, adresse postale, ville, pays, téléphones et fax sont mis à NULL.

Admission

Dans admissions :

  • le nom du lycée est remplacé ;
  • le rapporteur, la localisation et le code du lycée sont supprimés ;
  • le type d’admission et les informations de bourse antérieure sont supprimés ;
  • les groupes et classements APB sont supprimés.

Les informations scolaires générales non explicitement listées, comme le type de baccalauréat, peuvent rester disponibles pour les statistiques.

Suivi et annotations

Dans itemsuivi, situation est mis à NULL.

Les associations entre les éléments de suivi et leurs tags sont supprimées dans itemsuivi_tags_assoc. Les définitions des tags dans itemsuivi_tags ne sont pas supprimées.

Dans etud_annotations, les commentaires sont mis à NULL.

Assiduités et absences

Les champs suivants sont supprimés :

Table Champs
billet_absence description
assiduites description, external_data
justificatifs raison, external_data, fichier

Le champ fichier contient le nom d’une archive de justificatifs. Avant de le mettre à NULL, le script mémorise et affiche les répertoires physiques à supprimer séparément :

archives/justificatifs/8/21219/2026-03-16-13-56-47

Ces chemins sont relatifs à :

/opt/scodoc-data

Le script SQL ne supprime pas lui-même les fichiers présents sur le système de fichiers: il faut ensuite lancer un second script charger d'effacer tous les fichiers annexes identifiés: tools/delete_anonymized_archives.sh (c'est indiqué en clair à l'issue du script de anonymize_db.py).

Notes et appréciations

Les textes libres suivants sont mis à NULL :

Table Champ
notes_appreciations comment
notes_notes comment
notes_notes_log comment

Les valeurs des notes et leur historique sont conservés.

Photos

Les photos des étudiants anciens sont déréférencées et lister comme à effacer pour le script suivant.

Journaux

Les lignes de scolog associées aux étudiants sélectionnés sont supprimées intégralement.

Demandes d’inscription

Lorsque --before est fourni, les lignes de form_semestre_demande_inscription dont :

date_demande < DATE_LIMITE

sont supprimées intégralement.

Cette suppression concerne notamment les noms, coordonnées, NIP, INE, motivations et pièces jointes enregistrés dans ces demandes.

Sans --before, aucune demande d’inscription n’est supprimée.

Configuration générale

Sauf avec --only-students ou --only-users, les valeurs suivantes de scodoc_site_config sont mises à NULL :

  • rgpd_coordonnees_dpo ;
  • pegase_password.

Utilisateurs

Les utilisateurs ne sont traités qu’avec --users ou --only-users.

Pour tous les comptes :

  • les mots de passe et anciens mots de passe sont invalidés ;
  • les jetons sont supprimés ;
  • les dates de création et d’expiration sont remplacées ;
  • les adresses électroniques sont remplacées.

Pour tous les comptes sauf admin :

  • nom et prénom sont remplacés ;
  • le nom d’utilisateur est remplacé par un identifiant fictif unique ;
  • les références textuelles au nom d’utilisateur sont mises à jour dans plusieurs tables de journaux et d’historique.

Bilan affiché

À la fin du traitement, le script affiche :

  • le nombre d’étudiants traités ;
  • la liste des formsemestres auxquels ces étudiants ont été inscrits ;
  • le nombre d’étudiants concernés pour chaque formsemestre ;
  • la liste des archives et photos à supprimer.

En mode --dry-run, ces informations décrivent ce qui aurait été modifié.

Limites et pseudonymisation

Le traitement conserve volontairement un historique scolaire détaillé afin de permettre notamment :

  • le suivi longitudinal des cohortes ;
  • le calcul des taux de réussite ;
  • l’analyse des parcours et réorientations ;
  • les statistiques sur les notes, validations et décisions de jury ;
  • les statistiques d’assiduité ;
  • les analyses par année de naissance ou formation.

Pour permettre ces usages, le script conserve notamment :

  • l’etudid interne ;
  • les inscriptions aux formsemestres ;
  • les notes et leurs historiques ;
  • les validations et décisions de jury ;
  • les dates et événements scolaires ;
  • les groupes, parcours et formations ;
  • certaines données d’admission ;
  • les stages, apprentissages et badges éventuels.

Ces informations peuvent permettre d’individualiser un parcours. Le croisement d’une formation rare, de dates, d’un établissement d’origine, d’un stage ou d’une trajectoire particulière peut parfois conduire à une réidentification.

La base résultante doit donc être considérée comme pseudonymisée, sauf analyse complémentaire démontrant que toute réidentification est raisonnablement impossible.

Elle doit continuer à bénéficier de mesures de protection adaptées :

  • accès limité aux personnes autorisées ;
  • finalité statistique définie ;
  • journalisation des accès ;
  • absence de diffusion publique de données individuelles ;
  • agrégation des résultats avant publication ;
  • vigilance pour les cohortes ou sous-groupes de faible effectif ;
  • durée de conservation documentée ;
  • réévaluation périodique du risque de réidentification.

Le script ne remplace pas une politique RGPD complète : registre des traitements, définition des durées de conservation, base légale, information des personnes, gestion des droits et analyse des risques restent nécessaires.