Blog ·
Une étiquette qui survit au renommage d’hôte
Une étiquette sur un serveur est un document public. Ce que nous y mettons, pourquoi le QR ne contient aucune URL, et comment une table de codes se vérifie.
Par Provibr
Une étiquette collée sur un serveur est un document public. Elle voyage dans une camionnette de messagerie, elle est lue par des techniciens d’intervention sur site qui travaillent pour une entreprise avec laquelle vous n’avez jamais contracté, et un jour la machine est mise au rebut et l’étiquette part à la benne avec le châssis. Tout ce qui est imprimé dessus est, sur la durée de vie de la machine, publié.
Cette seule observation décide de presque tout ce qu’une étiquette de datacenter doit contenir, et elle exclut l’essentiel de ce que les gens y mettent.
Ce qui y figure, et ce qui n’y figure pas
Trois choses : un localisateur opaque, le numéro de révision de cette impression, et le même localisateur à nouveau sous forme lisible par un humain, groupé par quatre pour que quelqu’un puisse le taper quand le code refuse de se lire.
Pas dessus : le nom du client, l’organisation, le numéro de série, le code d’inventaire, le rack où elle vit actuellement, le nom d’hôte, un logo, ou un jeton quel qu’il soit. Une étiquette est une identité, pas une fiche.
Le rack est celui dont on discute, parce que l’écrire sur l’étiquette est commode jusqu’à la première fois où une machine déménage. L’étiquette affirme alors avec assurance une localisation fausse, et une localisation fausse qui a l’air de faire autorité est pire que pas de localisation du tout. Un cran plus bas, c’est aussi pourquoi une position dans un rack ne reçoit pas d’étiquette : une position en U n’est pas une chose mais une coordonnée, et elle cesse de vouloir dire ce qu’elle voulait dire dès l’instant où l’unité de départ du rack est corrigée.
Pourquoi le QR code ne contient pas d’URL
Le réflexe, avec un QR code, est d’encoder un lien. Nous encodons le localisateur nu, pour trois raisons, par ordre de poids.
Une étiquette survit à un nom d’hôte. Un compte qui migrerait plus tard vers son propre domaine aurait sinon un millier d’étiquettes imprimées pointant vers une adresse qui ne le sert plus, et personne ne réimprime un millier d’étiquettes.
Une URL en dit plus qu’un localisateur. Elle nomme la plateforme, et sur le domaine propre d’un client elle nomme le client. C’est précisément la catégorie d’information dont l’étiquette est censée être exempte : une URL n’est pas un raccourci, c’est un champ supplémentaire, et c’est le champ qui a le plus de témoins.
Et il n’y a qu’un seul chemin d’entrée. Un appareil photo de téléphone, un lecteur USB qui tape dans un champ et un humain qui recopie à la main produisent tous la même chaîne dans la même case. Une URL créerait une quatrième forme que seul l’appareil photo produit, et une quatrième forme est une quatrième chose à rater.
Le localisateur n’est pas un jeton au porteur
C’est la partie qui rend le reste sûr. Détenir le localisateur ne vous donne rien.
Un scan est une action authentifiée ordinaire. La porte de l’organisation s’applique, la permission de lecture est vérifiée, la requête est cantonnée au compte, et alors seulement le serveur dit si ce localisateur existe ici. Un localisateur d’un autre compte produit exactement la même réponse qu’un localisateur inventé : inconnu. Un localisateur révoqué a son propre refus, parce que c’est un fait différent et que la personne qui tient l’étiquette mérite de savoir lequel des deux c’est.
Il n’y a pas non plus de préfixe fournisseur. Un schéma en tête permettrait au logiciel de distinguer notre étiquette du code-barres que le fabricant a déjà collé, et il dirait à quiconque trouve l’étiquette à quelle plateforme elle appartient. La forme fait ce travail silencieusement : un localisateur, ce sont seize caractères d’un alphabet connu, et tout ce qui n’a pas cette forme est recherché comme code d’inventaire ou comme numéro de série, ce dont le flux de scan a de toute façon besoin pour le code-barres du fabricant et pour quelqu’un qui relève un numéro sur le châssis.
Seize caractères, et pourquoi seize
L’alphabet est le Crockford base32 : les chiffres et les lettres sans I, L, O et U. I et L se confondent avec le chiffre un, O avec zéro ; le U est écarté par la norme pour éviter les grossièretés accidentelles. Nous la suivons parce que deux autres codes de ce produit le font déjà, et que deux alphabets seraient un bogue qui attend son heure.
Seize caractères d’un alphabet de trente-deux caractères, cela fait quatre-vingts bits. La longueur n’a pas été choisie pour la difficulté à deviner, parce que deviner n’apporte rien : la recherche est autorisée de toute façon. Elle a été choisie pour les collisions. Quatre-vingts bits rendent négligeable un doublon sur des millions d’étiquettes, si bien que l’index unique en dessous ne force jamais une nouvelle tentative qu’un utilisateur remarquerait. Seize, c’est aussi à peu près la plus longue chaîne que quelqu’un recopie en quatre groupes de quatre sans se tromper.
La normalisation s’applique à tout ce qui entre : suppression des espaces de bord, passage en majuscules, retrait des espaces et des traits d’union, puis I et L deviennent un et O devient zéro. Personne qui tape depuis une étiquette ne devrait avoir à savoir que ces lettres sont absentes. Le U n’a délibérément aucune correspondance : aucun chiffre ne lui ressemble, donc un U est une vraie faute de frappe et a sa place dans un refus plutôt que dans une substitution silencieuse.
Code 128, écrit à la main, et vérifié plutôt que cru
Le QR code utilise une bibliothèque qui était déjà dans le fichier de verrouillage pour l’authentification à deux facteurs : aucune dépendance d’exécution, et un moteur de rendu qui produit du SVG sans toucher à un canvas ni à un DOM. Réutiliser cela vaut mieux qu’écrire un second encodeur QR.
Pour le Code 128, aucun paquet de ce genre n’existait ici. Les candidats qui font le travail traînent une couche de dessin visant un canvas ou un navigateur, ce qui est la seule chose qu’un SVG rendu côté serveur ne doit pas avoir, et ils sont deux ordres de grandeur plus gros que la chose elle-même. Le Code 128 est petit : une table de motifs, un caractère de départ, une somme de contrôle modulo cent trois, et un caractère d’arrêt. Cela fait deux cents lignes environ et aucune chaîne d’approvisionnement pour une table qui n’a pas changé depuis 1981.
Le problème, quand on recopie une table normalisée depuis une spécification, c’est qu’une erreur y échoue silencieusement. Le SVG a l’air parfait, les tests passent, et des mois plus tard un lecteur dans un datacenter lit un autre caractère. La table est donc vérifiée par quatre invariants indépendants et un décodeur, le tout dans le fichier de test :
- Cent six motifs en plus du caractère d’arrêt, chacun d’exactement six éléments dont la somme fait onze modules.
- Une parité paire dans les barres. Tout caractère du Code 128 a une somme paire sur ses trois barres ; c’est la propriété qu’un lecteur utilise pour déterminer dans quel sens il lit, et elle vaut pour les cent six. Un seul chiffre mal recopié casse soit celle-ci, soit la somme ci-dessus.
- Des largeurs d’élément comprises entre un et quatre, et les cent six motifs tous distincts.
- Le caractère d’arrêt, le seul motif à sept éléments et treize modules.
- Un décodeur dans le test qui relit les largeurs de barres générées et doit retrouver la chaîne d’entrée, caractère de contrôle compris.
Une table qui survit à quatre invariants indépendants et à un aller-retour n’est pas « probablement juste », et cette distinction est toute la raison de les écrire.
Nous sommes restés dans le sous-ensemble B plutôt que de basculer automatiquement. L’étiquette porte des lettres majuscules et des chiffres, que le sous-ensemble B couvre en une passe. Le sous-ensemble C réduirait de moitié les paires numériques, mais un localisateur n’est pas une suite numérique, donc un basculement automatique serait une branche qui ne se déclenche jamais.
La disposition de la planche découle du code-barres
Vingt-quatre étiquettes par page A4, trois en largeur et huit en hauteur. Ce nombre n’est pas une préférence de conception, c’est une arithmétique qui se déroule dans l’autre sens.
Un Code 128 de seize caractères fait deux cent onze modules de large : onze pour le départ, onze par caractère, onze pour le caractère de contrôle et treize pour l’arrêt. Ajoutez deux zones de silence de dix modules et il vous faut deux cent trente et un modules en largeur. Le plancher pratique pour un lecteur ordinaire est un module d’un quart de millimètre, en dessous duquel la lecture passe de fiable à occasionnelle. Cela fait cinquante-huit millimètres de code-barres.
Quatre colonnes sur une A4 donnent une étiquette d’environ cinquante-deux millimètres de large et un module proche de deux dixièmes de millimètre : une planche qui a l’air plus nette et qui ne se lit pas dans une allée froide. Trois par huit donnent une étiquette de soixante-dix sur trente-sept millimètres, une largeur utilisable de soixante-quatre, et un module de 0,277 millimètre. Le nombre découle du code et non l’inverse. La page est délibérément pleine, avec la marge à l’intérieur de chaque étiquette plutôt qu’autour de la grille, si bien qu’un pilote d’imprimante n’a jamais à mettre quoi que ce soit à l’échelle, et la mise à l’échelle est la seule chose qu’un code-barres ne tolère pas.
Ce plancher est une constante dans la source plutôt qu’un commentaire, si bien qu’un test mesure la largeur de module du SVG rendu par rapport à elle. Un changement de disposition qui comprime trop le code-barres est un test rouge au lieu d’une plainte venue de l’allée.
Une seule étiquette active par objet
Les réimpressions sont le cas ordinaire, donc c’est la base de données qui porte l’invariant plutôt que le code. Deux index uniques partiels, un pour les machines et un pour les racks, qui sont les deux seules choses à porter une étiquette, n’autorisent au plus qu’une étiquette qui n’a pas été révoquée. Sans eux, une réimpression qui échoue à mi-chemin laisse deux étiquettes valides sur une machine, et personne ne peut dire laquelle est la vraie. Une seconde paire garde la révision unique par objet, si bien qu’une réimpression compte vers le haut et ne se répète jamais. Trois chiffres est le plafond : le nombre doit rester lisible, et un millier de réimpressions d’une même machine n’est pas un problème d’étiquetage.
Ce que nous écririons
- Traitez l’étiquette comme publiée, et décidez de ce qui y figure en demandant qui la lira dans cinq ans.
- Encodez l’identifiant, pas un lien. Il survit à un changement de domaine, à un changement de marque et à un rachat ; une URL ne survit à aucun des trois.
- Rendez l’identifiant sans valeur à lui seul, pour qu’une étiquette perdue soit un problème de logistique et non un problème de sécurité.
- Vérifiez une table normalisée par des invariants et un aller-retour, parce que cette classe d’erreur n’échoue jamais bruyamment.
- Dérivez la disposition d’impression du plus petit module lisible, et fixez ce plancher comme une constante qu’un test peut mesurer.
Par honnêteté sur notre propre position : le travail sur les datacenters est derrière un indicateur de déploiement désactivé par défaut, avec un réglage par organisation par-dessus, si bien que ceci est la description d’une conception et non une annonce. Deux choses sont explicitement non prouvées. La matrice QR n’a pas été décodée par une implémentation indépendante, parce qu’il n’y a pas de décodeur dans ce dépôt. Et rien n’a été imprimé sur papier ni scanné dans une allée, ce qui est le seul test qui compte vraiment pour un code-barres. Le même raisonnement sur ce qu’un composant a le droit de savoir apparaît ailleurs ici : les identifiants restent sur l’hôte, et l’agent ne se connecte que vers l’extérieur.
Issu du travail sur les datacenters chez Provibr. Ce qui empêche deux personnes d’affecter la même unité de rack est dans la seule vraie limite à l’occupation d’un rack.