Перейти до вмісту

Блог ·

Наліпка, що переживе зміну імені хоста

Наліпка на сервері є публічним документом. Що ми на неї наносимо, чому QR-код не містить URL і як таблицю штрихкоду перевіряють, а не приймають на віру.

Автор: Provibr

Наліпка на сервері є публічним документом. Вона їде у фургоні курʼєра, її читають працівники віддалених рук, які працюють на компанію, з якою ви ніколи не укладали договору, і врешті машину списують, а наліпка їде на звалище разом із корпусом. Усе, що на ній надруковано, за час життя машини є опублікованим.

Це єдине спостереження вирішує майже все про те, що має містити наліпка в центрі обробки даних, і воно виключає більшість того, що на них зазвичай пишуть.

Що на ній є, а чого немає

Три речі: непрозорий локатор, номер ревізії цього друку і той самий локатор ще раз у придатному для читання людиною вигляді, згрупований по чотири, щоб хтось міг набрати його, коли код не сканується.

Немає на ній: імені клієнта, організації, серійного номера, інвентарної позначки, стійки, у якій вона зараз живе, імені хоста, логотипа чи будь-якого токена. Наліпка є ідентичністю, а не записом.

Стійка є тим, про що сперечаються, бо писати її на наліпці зручно рівно до першого переміщення машини. Тоді наліпка впевнено вказує хибне місце, а хибне місце, що має вигляд авторитетного, гірше за жодне. На рівень нижче, це також причина, чому позиція у стійці не отримує наліпки: позиція U є не річчю, а координатою, і вона перестає означати те, що означала, тієї миті, коли виправлять початковий юніт стійки.

Чому QR-код не містить URL

Типовим для будь-чого з QR-кодом є закодувати посилання. Ми кодуємо голий локатор, і на це є три причини в порядку ваги.

Наліпка переживає імʼя хоста. Обліковий запис, який згодом переїде на власний домен, інакше мав би тисячу надрукованих наліпок, що вказують на адресу, яка його більше не обслуговує, а тисячу наліпок ніхто не передруковує.

URL каже більше, ніж локатор. Він називає платформу, а на власному домені клієнта він називає клієнта. Це рівно та категорія відомостей, від якої наліпка має бути вільною: URL є не скороченням, а додатковим полем, і саме в цього поля найбільше сторонніх очей.

І є рівно один шлях введення. Камера телефона, USB-сканер, який набирає в поле, і людина, що переписує рукою, дають той самий рядок у тому самому полі. URL створив би четверту форму, яку дає лише камера, а четверта форма є четвертою нагодою помилитися.

Локатор не є токеном на предʼявника

Це та частина, що робить решту безпечною. Володіння локатором не дає вам нічого.

Сканування є звичайною автентифікованою дією. Спрацьовує вхід організації, перевіряється дозвіл на читання, запит обмежується обліковим записом, і лише тоді сервер каже, чи існує тут цей локатор. Локатор з іншого облікового запису дає рівно ту саму відповідь, що й вигаданий кимось: невідомий. Відкликаний отримує власну відмову, бо це інший факт, і людина з наліпкою в руках заслуговує знати, який саме.

Немає також префікса постачальника. Схема попереду дозволила б програмі відрізнити нашу наліпку від штрихкоду, який виробник уже приклеїв, і сказала б кожному, хто знайде наліпку, якій платформі вона належить. Форма робить цю роботу мовчки: локатор є шістнадцятьма символами з відомого алфавіту, а все, що не має цієї форми, шукають як інвентарну позначку або серійний номер, чого потік сканування все одно потребує для штрихкоду виробника і для того, хто зчитує номер із корпусу.

Шістнадцять символів, і чому шістнадцять

Алфавітом є Crockford base32: цифри й літери без I, L, O та U. I та L сплутуються з цифрою один, O з нулем; U відкинуто стандартом, щоб уникнути випадкової лайки. Ми йдемо за ним, бо два інші коди в цьому продукті вже так роблять, а два алфавіти були б вадою, яка чекає своєї миті.

Шістнадцять символів алфавіту з тридцяти двох це вісімдесят бітів. Довжину обрано не заради стійкості до вгадування, бо вгадування нічого не купує: пошук авторизований у будь-якому разі. Її обрано заради колізій. Вісімдесят бітів роблять дублікат серед мільйонів наліпок незначущим, тож унікальний індекс під низом ніколи не змушує до повтору, який користувач помітив би. Шістнадцять це також приблизно найдовший рядок, який людина переписує чотирма групами по чотири без помилки.

Нормалізація працює на всьому, що надходить: обрізати, привести до верхнього регістру, прибрати пробіли й дефіси, тоді відобразити I та L в одиницю, а O в нуль. Той, хто набирає з наліпки, не має знати, що цих літер немає. Для U відображення свідомо немає: жодна цифра на неї не схожа, тож U є справжньою помилкою набору й належить у відмову, а не в тиху заміну.

Code 128, написаний вручну і перевірений, а не прийнятий на віру

QR-код використовує бібліотеку, яка вже була у файлі блокування заради двофакторної автентифікації: жодних залежностей часу виконання й відтворювач, що дає SVG, не торкаючись ні canvas, ні DOM. Повторне використання цього краще за написання другого кодувальника QR.

Для Code 128 такого пакета тут не було. Кандидати, які виконують цю роботу, тягнуть шар малювання, націлений на canvas або браузер, а це рівно те, чого відтворений на сервері SVG мати не може, і вони на два порядки більші за саму річ. Code 128 малий: таблиця візерунків, стартовий символ, контрольна сума за модулем сто три і стоповий символ. Це пара сотень рядків і жодного ланцюга постачання заради таблиці, яка не змінювалася з 1981 року.

Проблема з набором стандартної таблиці зі специфікації в тому, що помилка в ній падає тихо. SVG має бездоганний вигляд, тести проходять, а через місяці сканер у центрі обробки даних читає інший символ. Тож таблицю перевіряють чотирма незалежними інваріантами й декодером, і все це у файлі тесту:

  1. Сто шість візерунків, крім стопового символу, кожен рівно з шести елементів, що дають у сумі одинадцять модулів.
  2. Парність у штрихах. Кожен символ Code 128 має парну суму по своїх трьох штрихах; це та властивість, за якою сканер зʼясовує, у який бік він читає, і вона тримається для всіх ста шести. Одна помилково набрана цифра ламає або це, або суму вище.
  3. Ширини елементів від одного до чотирьох, і всі сто шість візерунків різні.
  4. Стоповий символ, єдиний візерунок із семи елементів і тринадцяти модулів.
  5. Декодер у тесті, який читає згенеровані ширини штрихів назад і мусить відновити вхідний рядок, разом із контрольним символом.

Таблиця, що переживає чотири незалежні інваріанти й повний оберт, не є «мабуть, правильною», і саме ця різниця є всією причиною їх написати.

Ми лишилися в subset B, а не перемикалися автоматично. Наліпка несе великі літери й цифри, які subset B покриває за один прохід. Subset C удвічі скоротив би числові пари, але локатор не є числовим рядом, тож автоматичне перемикання було б гілкою, яка ніколи не спрацьовує.

Розкладка аркуша є наслідком штрихкоду

Двадцять чотири наліпки на аркуш A4, три впоперек і вісім униз. Це число не є вподобанням дизайну, це арифметика, яка йде у зворотному напрямку.

Code 128 із шістнадцяти символів має ширину двісті одинадцять модулів: одинадцять на старт, одинадцять на символ, одинадцять на контрольний символ і тринадцять на стоп. Додайте дві тихі зони по десять модулів, і впоперек потрібно двісті тридцять один модуль. Практичною нижньою межею для звичайного сканера є модуль у чверть міліметра, нижче якої читання переходить із надійного в подеколи. Це пʼятдесят вісім міліметрів штрихкоду.

Чотири колонки на A4 дають наліпку близько пʼятдесяти двох міліметрів завширшки й модуль близько двох десятих міліметра: аркуш, що має охайніший вигляд і не читається в холодному коридорі. Три на вісім дають наліпку сімдесят на тридцять сім міліметрів, придатну ширину шістдесят чотири й модуль 0,277 міліметра. Кількість випливає з коду, а не навпаки. Сторінку свідомо заповнено повністю, а поле розміщено всередині кожної наліпки, а не навколо сітки, тож драйверові принтера ніколи не доводиться нічого масштабувати, а масштабування є єдиним, чого штрихкод не терпить.

Ця межа є константою у вихідному коді, а не коментарем, тож тест міряє ширину модуля відтвореного SVG проти неї. Зміна розкладки, що стискає штрихкод занадто тонко, є червоним тестом, а не скаргою з коридору.

Одна активна наліпка на обʼєкт

Передруки є звичайним випадком, тож інваріант несе база даних, а не код. Два часткові унікальні індекси, один для машин і один для стійок, бо це єдині дві речі, що несуть наліпку, дозволяють щонайбільше одну наліпку, яку не відкликано. Без них передрук, що впав на півдорозі, лишає дві чинні наліпки на одній машині, і ніхто не скаже, яка справжня. Друга пара тримає ревізію унікальною на обʼєкт, тож передрук рахує вгору й ніколи не повторюється. Стелею є три цифри: число має лишатися читабельним, а тисяча передруків однієї машини не є проблемою маркування.

Що ми б записали

  1. Ставтеся до наліпки як до опублікованої і вирішуйте, що на ній буде, питаючи, хто читатиме її через пʼять років.
  2. Кодуйте ідентифікатор, а не посилання. Він переживає зміну домену, ребрендинг і поглинання; URL не переживає жодного з них.
  3. Зробіть ідентифікатор нічого не вартим сам по собі, щоб загублена наліпка була проблемою логістики, а не безпеки.
  4. Перевіряйте стандартну таблицю інваріантами й повним обертом, бо цей клас помилок ніколи не падає гучно.
  5. Виводьте розкладку друку з найменшого читабельного модуля й закріпіть цю межу як константу, яку тест може виміряти.

Заради чесності щодо нашої власної позиції: робота над центрами обробки даних лежить за прапорцем розгортання, який типово вимкнено, а поверх нього ще й налаштування на кожну організацію, тож це є описом задуму, а не оголошенням. Дві речі явно недоведені. Матрицю QR не декодовано незалежною реалізацією, бо в цьому репозиторії немає декодера. І нічого не надруковано на папері й не проскановано в коридорі, а це єдине випробування, яке для штрихкоду справді має вагу. Те саме міркування про те, що компонентові дозволено знати, зʼявляється тут і в іншому: облікові дані лишаються на хості, а агент зʼєднується лише назовні.

Із роботи над центрами обробки даних у Provibr. Те, що зупиняє двох людей, які заявляють один юніт стійки, є в єдиній справжній межі зайнятості стійки.

Читати далі

Почніть з одного хоста й одного агента

Створіть обліковий запис, встановіть агента однією командою та підключіть свій перший хост Proxmox. Пробний період триває 14 днів і не потребує платіжних даних.