Suite de l'acte 1 — « Cartographier un SI : mon cheminement d'architecte SI » et de l'acte 2 — « Quand la cartographie devient une source de vérité vivante ».
L'acte 2 se terminait sur l'idée d'une carto qu'on apprend « à faire répondre aux bonnes questions » — et sur une case « à étudier » du schéma d'architecture : Mercator, maintenu, utilisé par le biomédical. Ce troisième épisode raconte comment cette case a disparu — et ce qu'on a appris en route sur les dispositifs médicaux connectés.
Là où on s'était arrêté
Petit rappel du terrain : un groupement d'établissements publics de santé, un SI mutualisé. Depuis l'acte 2, NetBox est notre source de vérité — IPAM, DCIM, VM synchronisées depuis vCenter, découverte réseau SNMP en cron, et la carto applicative netbox-it-landscape branchée directement dessus.
Mais un pan entier du SI vivait encore à part : le biomédical. Échographes, moniteurs multiparamétriques, automates de biologie, IRM, pompes à perfusion… Tout cela était documenté dans Mercator (le méta-modèle de cartographie de l'ANSSI), consciencieusement tenu par les équipes biomédicales — et c'était d'ailleurs un des succès de l'acte 1 : le biomédical avait adhéré à Mercator précisément parce qu'il n'a pas accès aux sources de vérité de l'IT (vCenter, firewalls, IPAM).
Le problème : cette cartographie était invisible depuis NetBox. Un DM connecté, c'est pourtant un objet qui a une IP, un VLAN, des flux, une surface d'attaque. Exactement le genre de choses qu'une source de vérité est censée connaître.
La question de la slide « prochaines étapes » de mon REX — « Intégrer Mercator à NetBox ? » — méritait une vraie réponse.
1. Avant de modéliser, lire ce que les données ont à dire
Le point de départ, ce sont trois exports Excel de Mercator : Applications, Blocs applicatifs, Flux applicatifs. Rien d'exotique en apparence. Sauf qu'en ouvrant le champ Description des applications, surprise :
IP 10.x.x.x AET HOST NAME Masque 255.255.255.224 Passerelle 10.x.x.x
DNS ... Port ... SSID WIFI ... adresse mac ... Login ... Mot de passe ...
VLAN ... Numéro Equipement ... Anti Virus ... Type/Commentaire ...
Un formulaire complet aplati dans une seule cellule, labels collés aux valeurs, espaces insécables en prime. Les équipes biomédicales avaient inventé leur propre modèle de données — 18 champs ! — faute d'un outil qui le leur offre. Même chose côté flux : une seconde fiche aplatie avec Protocole, IP port source, IP port EAI, IP port cible, Sonde PRTG, Procédure reprise, Contact éditeur.
C'est la première leçon de cet acte 3, et elle est contre-intuitive : le modèle de données existait déjà. Il n'était pas à inventer, il était à écouter. Un parsing positionnel plus tard (repérer chaque label, découper entre deux labels), on avait des statistiques de remplissage précises : 96 % des équipements ont une IP, 52 % un AE Title DICOM, 42 % un VLAN… et quelques découvertes moins réjouissantes, on y revient.
Deuxième enseignement de l'analyse, plus structurant encore : sur les ~290 objets du périmètre « biomédical », plus d'un tiers ne sont pas des dispositifs médicaux. Des serveurs de middleware, des consoles de post-traitement, des imprimantes DICOM, des passerelles PACS, des switches, des VPN de télémaintenance. Et le graphe de flux est parfaitement fermé : sur 525 flux, zéro extrémité inconnue du référentiel.
2. La décision de modélisation qui découle des données
Ce graphe fermé a dicté le modèle. Plutôt qu'un modèle MedicalDevice pur (et des GenericForeignKey partout pour raccorder les flux aux serveurs), le plugin repose sur un seul modèle Equipment avec un champ role :
class EquipmentRoleChoices(ChoiceSet):
MEDICAL_DEVICE = 'medical_device' # échographe, moniteur, automate…
SERVER = 'server' # middleware, PACS, serveur de résultats
WORKSTATION = 'workstation' # console de revue, poste d'acquisition
GATEWAY = 'gateway' # passerelle DICOM, box constructeur
SOFTWARE_INTERFACE = 'software_interface'
NETWORK = 'network'
REMOTE_ACCESS = 'remote_access' # VPN de télémaintenance
# …
Un seul référentiel, un seul modèle de flux (EquipmentFlow, avec ses trois extrémités source / EAI / cible héritées de la fiche Mercator), et les champs réglementaires du DM (classe RDM/RDIV, n° GMAO) simplement laissés vides pour les rôles non médicaux.
Deux autres choix de modélisation méritent d'être partagés :
-
Ne rien stocker de ce que l'IPAM sait déjà. Masque, passerelle, DNS remplissaient 80 % des fiches Mercator… et sont des propriétés du préfixe, pas de l'équipement. On les a supprimés du modèle : l'IP est une FK vers
ipam.IPAddress, le reste se déduit. Trois champs de moins, zéro divergence possible. -
Les frontières sont explicites. La GMAO biomédicale reste la source de vérité du parc et de la maintenance (on garde un
gmao_id, extrait automatiquement du nom des équipements). NetBox porte ce que personne d'autre ne porte : le lien DM ↔ réseau ↔ flux ↔ posture cyber.
3. Le pipeline d'import — et le rapport qualité qui vaut de l'or
Fidèle à la recette de l'acte 2 (le dry-run + l'importeur idempotent qui avaient sauvé la découverte réseau), l'import se fait en deux temps :
Exports Mercator (xlsx) → convertisseur local → JSON normalisé
(parsing des formulaires ↓
aplatis + rapport qualité) manage.py import_biomed
(idempotent, --dry-run)
↓
NetBox
Le convertisseur tourne sur le poste (là où le parsing sale a le droit d'être sale), l'import côté serveur est une management command Django propre, rejouable à l'infini : clé de rapprochement = identifiant Mercator, résolution des IP contre l'IPAM existant (le masque est hérité du préfixe englobant), rejeu = zéro création.
Mais le livrable le plus utile de cette étape n'est pas le plugin. C'est le rapport qualité que le convertisseur produit en sortie : taux de remplissage par champ, VLAN non normalisables, AE Titles pollués, équipements sans plateau, IP publiques inattendues… et surtout : des identifiants et mots de passe en clair dans le champ description. Ceux-là ne sont jamais importés — le modèle prévoit un champ vault_ref qui référence le coffre-fort de mots de passe, jamais le secret lui-même — et le constat est remonté pour purge à la source.
Si vous ne deviez retenir qu'une chose de cet article : avant d'importer une cartographie historique, écrivez le rapport qualité d'abord. Il vous dira ce que votre modèle doit prévoir, et il vous évitera d'industrialiser des secrets en clair.
4. Requalifier 417 flux « Data » sans y passer un mois
Dans Mercator, la nature des flux mélangeait deux axes (protocole et type de message), et 200 flux étaient étiquetés… « Data ». Le fourre-tout classique.
Plutôt qu'une reprise manuelle, on a écrit un moteur de règles (source, cible) → (protocole, type de message) : une liste ordonnée d'expressions régulières, la première qui matche gagne, avec un repli par protocole. La connaissance métier fait le reste — une centrale de monitorage qui parle à des moniteurs, c'est des constantes ; un middleware de biologie vers ses automates, c'est du pilotage d'automates ; une modalité vers un serveur de dose, c'est de la dosimétrie ; un serveur d'appel malade vers ses terminaux, c'est de l'appel malade.
Résultat : 417 flux requalifiés, reliquat zéro, en une après-midi — règles rejouables et versionnées à part (les règles nominatives du parc restent locales, le dépôt public ne contient qu'un fichier d'exemple).
Ces types alimentent ensuite des familles de flux (Images/DICOM, Worklist, Résultats & automates, Constantes & signaux, CR/documents, Télémaintenance, Exploitation…), chacune avec sa couleur — c'est la clé de lecture de toute la partie visualisation.
5. Dériver plutôt que déclarer : l'exposition réseau
Champ « exposition réseau » : isolé, segmenté, à plat, exposé. Première tentation : le faire saisir. Mauvaise idée — un champ déclaratif diverge dès le premier changement de VLAN.
À la place, l'exposition est dérivée de l'IPAM : un script regroupe les équipements par sous-réseau, mesure la densité biomédicale de chaque /24 dans l'IPAM, crée les préfixes manquants avec un rôle « Réseau biomédical », et en déduit l'exposition — préfixe dédié = segmenté, sous-réseau partagé avec les serveurs = à plat, plan d'adressage legacy constructeur = isolé, IP publique = exposé. L'IPAM devient la source, le champ n'est qu'un cache.
Bonus inattendu du rapprochement par adresse MAC : le OUI (les 3 premiers octets) révèle les cartes réellement embarquées dans les DM — des cartes industrielles Adlink dans un arceau de bloc, Advantech dans un module EEG. Le « dispositif médical » est souvent un PC industriel déguisé, et ça, aucune GMAO ne le documente.
6. La carto que les utilisateurs voulaient vraiment
La première version de la vue cartographie était un diagramme de flux source → cible, avec un code couleur rouge/vert sur le chiffrement. Fierté de l'architecte : on voyait d'un coup d'œil que la quasi-totalité des flux biomédicaux circulent en clair (DICOM et HL7 v2 sans TLS — aucun RSSI hospitalier ne tombera de sa chaise).
Et puis les retours utilisateurs sont arrivés, et ils avaient raison sur toute la ligne :
- « Le chiffrement, on s'en fiche dans la carto » — c'est un indicateur de tableau de bord cyber, pas une clé de lecture topologique. Les arêtes sont depuis colorées par famille de flux.
- « Une modélisation différente par rôle » — chaque rôle a désormais sa forme et son icône : pilule à croix médicale pour les DM, rectangle à lignes de rack pour les serveurs, hexagone pour le réseau, écusson-cadenas pour les VPN, double bordure pour les passerelles.
- « Et une vue sans traits, juste des pastilles » — la vue par défaut est finalement une vue plateaux : des cards compactes par plateau technique (imagerie, biologie délocalisée, réanimation…), équipements triés par rôle, chacun portant des pastilles colorées indiquant ses familles d'interfaces. Le diagramme de flux reste à un clic.
Tout est rendu en SVG généré côté serveur — zéro librairie JavaScript, le même pattern que les vues d'it-landscape. Et le tableau de bord cyber, lui, garde ses compteurs cliquables : flux en clair, équipements exposés, OS hors support, flux non supervisés, télémaintenances constructeur.
Ce qu'on en retient
- Le modèle de données de vos utilisateurs existe déjà — dans leurs Excel, leurs champs libres, leurs conventions de nommage. Le travail de modélisation consiste d'abord à l'extraire, pas à l'inventer.
-
Un référentiel fermé vaut mieux qu'un modèle pur. Le champ
rolea évité trois modèles et des clés génériques, et le graphe de flux est resté navigable de bout en bout. - Le rapport qualité est un livrable de premier rang. C'est lui qui a révélé les secrets en clair, les IP publiques oubliées et les 200 flux à requalifier.
- Dériver plutôt que déclarer : l'exposition réseau calculée depuis l'IPAM ne divergera jamais de la réalité, contrairement à un champ saisi.
- Les itérations UI dictées par les utilisateurs ont produit une meilleure carto que la version « démonstration technique » de départ. La vue préférée du terrain est celle sans aucun trait.
Essayez-le
netbox-biomed est sur GitHub — modèles Plateau / Équipement (à rôle) / Flux, import Mercator idempotent avec rapport qualité, tableau de bord cyber, cartographie SVG à deux modes, i18n FR/EN, et les outils d'exploitation (requalification par règles, dérivation d'exposition, rapprochement DCIM par MAC/OUI).
👉 github.com/lquastana/netbox-biomed — installez-le sur une instance de test, adaptez le convertisseur à votre export (Mercator ou autre), ouvrez une issue. Et si le sujet DM connectés × NetBox vous parle, une ⭐ aide le projet à trouver sa communauté — les outils open source de cartographie biomédicale ne courent pas les rues.
La boucle de l'acte 2 est bouclée : la case « Mercator, à étudier » du schéma d'architecture a disparu. Le biomédical est entré dans la source de vérité — avec ses spécificités, pas malgré elles. Et la carto continue d'apprendre à répondre aux bonnes questions : la prochaine sera sans doute « que se passe-t-il si ce plateau tombe ? » — le simulateur d'impact de l'acte 2 n'attend que les flux biomédicaux.
Laurent Quastana — Architecte SI hospitalier.
Top comments (0)