LaPorta USB

Справочник: файл политики

Политика – один файл JSON. Путь к нему задаётся при установке параметром POLICYPATH и хранится в реестре; его читают и служба, и окно администратора. Имена полей – в нижнем регистре через подчёркивание (enforcement_mode, strict_mode).

Разбор снисходителен к трём вещам: незнакомые поля пропускаются (по ним новая версия программы не ломает старую политику), комментарии // разрешены, запятая после последнего элемента списка ошибкой не считается. Окно администратора, сохраняя политику, незнакомые поля верхнего уровня оставляет на месте, а комментарии – нет: файл записывается заново.

Целый пример

{
  "version": 7,
  "updated_utc": "2026-08-18T09:14:00Z",
  "updated_by": "DOMAIN\\petrov",
  "enforcement_mode": "audit",
  "strict_mode": false,
  "notify_user": true,
  "check_updates": true,
  "defaults": { "flash": "block", "external_hdd": "block", "other": "allow" },
  "rules": [
    { "id": "R-001", "match": { "serial": "001cc0ec34d5" }, "action": "allow",
      "note": "Флешка бухгалтерии №1", "owner": "Иванова А.П." },
    { "id": "R-014", "match": { "vid": "0951", "pid": "1666" }, "action": "readonly" }
  ],
  "log": { "retention_days": 90, "share_path": "\\\\server\\laportausb$\\logs" }
}

Поля верхнего уровня

ПолеОбязательноЗначение
versionдаЦелое больше нуля. По нему окно администратора замечает, что файл правил кто-то ещё
updated_utcнетВремя последней правки
updated_byнетКто правил
enforcement_modeнетaudit либо enforce. Без поля – audit
strict_modeнетПревентивный слой. Без поля – выключен
notify_userнетУведомления в трее. Без поля – включены
check_updatesнетПроверять ли обновления на сайте программы. Без поля – проверять
install_updatesнетЧасы, в которые служба сама поставит обновление: 02:00-05:00. Без поля – не ставит
defaultsдаДействие по классу носителя
rulesнетПравила по отдельным устройствам
logнетСрок хранения журнала и путь выгрузки

Поле strict_mode включает превентивный слой – запрет установки неизвестных USB-накопителей через ветку ограничений установки устройств, а не только отключение уже подключённых. Действует лишь вместе с enforcement_mode: enforce: в паре с audit strict_mode ничего не включает, режим наблюдения ничего не ограничивает. Устройство слоя, порядок регистрации носителя в белом списке и срок жизни этого списка – в overview.md.

Поле check_updates выключает автоматическую проверку обновлений – ту, которую служба делает раз в сутки: берёт с laportausb.ru подписанный манифест выпуска, сверяет версию и при более новой пишет в журнал событие update_available. Пакет при этом не скачивается и не ставится: обновление ставит человек кнопкой в окне администратора («Справка» – «Обновления…»). Без поля проверка включена.

Поле install_updates разрешает службе ставить обновление самой и задаёт часы, в которые это позволено: "install_updates": "02:00-05:00". Время местное. Окно через полночь писать можно – 23:00-05:00. Начало входит в окно, конец – нет.

Без поля служба не ставит ничего: установка останавливает службу, и машина на эти минуты остаётся без запретов – выбирать их должен администратор, а не случай. Поэтому окно задают ночным, а не рабочим.

Поле работает только вместе с check_updates: служба, которая не проверяет, не узнает и о том, что ставить. Запрет проверки параметром установки UPDATECHECK=0 отменяет и установку – он сильнее политики. Выключенные обновления запрещают и установку выпуска, найденного до того, как их выключили.

Установка попадает в журнал: update_installing пишется между скачиванием и запуском установщика, а неудача – update_install_failed. Пакет скачивается в %ProgramData%\LaPorta USB\updates и сверяется с подписанным манифестом по размеру и sha256 – как и при установке кнопкой.

Неудача не повторяется тут же: следующая попытка – не раньше чем через час. Окно установки открыто часами, а служба возвращается к своим делам каждые полминуты, и без паузы отказ пакета обернулся бы сотней скачиваний и сотней записей в журнале за одну ночь.

Поле check_updates выключает только автоматическую проверку. Кнопка в окне продолжает работать: за ней стоит администратор, который сам её нажал. Если машине нельзя обращаться наружу вовсе, запрет задаётся при установке параметром UPDATECHECK=0 – он машинный, живёт в реестре и политикой не перебивается. Оба выключателя описаны в install.md.

Незнакомое значение enforcement_mode – ошибка разбора, а не молчаливое возвращение к audit. Иначе опечатка в слове enforce оставила бы машину в режиме наблюдения, а администратор считал бы, что запреты включены.

Умолчания по классам устройств

"defaults": { "flash": "block", "external_hdd": "block", "other": "allow" }
КлючОбязателенПримечание
flashдаФлешка
external_hddдаВнешний диск
otherнетПрочие USB-устройства, включая телефоны в режиме MTP. Без ключа – allow
tokenзапрещёнВалидатор отвечает: «Класс token не настраивается политикой: токены никогда не блокируются»
unknownнет такого ключаКласс не определён – решение по устройству не пересчитывается

Класс unknown означает, что узел устройства отключён и не запущен: система сообщает идентификатор, VID/PID и имя, но не сменность носителя, а без неё флешку от внешнего диска не отличить. Догадка стоила бы неверного решения, поэтому класс остаётся неопределённым.

Телефон в режиме MTP относится к other, и other: block его запрещает: узел устройства отключается, и телефон пропадает из проводника. А вот other: readonly к нему неприменим – тома и буквы диска у MTP нет, ставить метку не на что. Отказ не молчаливый: в журнал идёт apply_failed, в событии подключения – enforcement_failed.

Правила

Правило – отбор устройства (match) и действие над ним (action).

ПолеОбязательноЗначение
idдаНеповторяющийся в пределах файла
matchдаУсловие отбора, см. ниже
actionдаallow, readonly либо block
noteнетДля человека: что это за носитель
ownerнетДля человека: чей он
added_utcнетКогда правило заведено

Внутри match:

ПолеЗначение
serialСерийный номер устройства
vidИдентификатор изготовителя, ровно четыре шестнадцатеричные цифры
pidИдентификатор изделия, ровно четыре шестнадцатеричные цифры
interfacesСостав интерфейсов, записи вида класс:подкласс:протокол
interfaces_matchequals либо none_of. Без поля – equals

Задаётся либо serial, либо пара vid+pid целиком. Одно с другим одновременно – ошибка; половина пары – тоже ошибка. serial, vid и pid приводятся к верхнему регистру, так что регистр в файле значения не имеет.

Записи в interfaces – шестнадцатеричные пары, звёздочка допускается вместо целой доли: 03:*:* – любая клавиатура или мышь, 08:06:50 – обычный накопитель. equals требует совпадения состава, none_of – отсутствия перечисленного. Устройство, состав интерфейсов которого прочитать не удалось, не удовлетворяет никакому условию: разрешать по неподтверждённому значит открывать ровно ту дверь, ради закрытия которой условие и заводилось.

Пример правила с условием – разрешить этот накопитель, пока он остаётся только накопителем:

{
  "version": 12,
  "enforcement_mode": "enforce",
  "defaults": { "flash": "block", "external_hdd": "block" },
  "rules": [
    { "id": "R-021",
      "match": { "serial": "001CC0EC34D5", "interfaces": ["03:*:*"], "interfaces_match": "none_of" },
      "action": "allow", "note": "Отзывается, если внутри окажется клавиатура" }
  ]
}

Порядок применения правил

Решение принимается первым подошедшим пунктом сверху вниз. В журнал попадает причина – она в скобках.

  1. Токен (token_never_enforced). Всегда allow. Ни одно правило к токену не применяется: заблокированный токен – это потерянный вход в систему.

    Токеном считается устройство, которое система опознала как смарткарт-ридер, либо устройство с известным VID производителя токенов, объявившее интерфейс чип-карты. Одного VID недостаточно: его сообщает о себе само устройство, и перепрошитая флешка назвалась бы токеном. Узел, объявивший интерфейс накопителя, токеном не считается ни при каком VID – поэтому flash-раздел настоящего токена подчиняется правилам как обычная флешка. Вход в систему и ЭЦП этим не задеваются: они живут на соседнем узле, которого запрет раздела не касается.

  2. Точное правило по serial (exact_rule_serial). Только если серийный номер заслуживает доверия: часть дешёвых носителей сообщает один номер на всю партию.

  3. Групповое правило по vid+pid (group_rule_vid_pid). Правило с заданным serial на этом шаге не рассматривается.

  4. Умолчание по классу (default_flash, default_external_hdd, default_other).

Из нескольких правил, подошедших на одном шаге, выигрывает block; если запрета среди них нет – первое по порядку в файле.

Условие interfaces уточняет правило, а не образует своё. Не совпало – правило не применяется вовсе, и устройство уходит дальше по списку, к умолчанию. Так не возникает вопроса о старшинстве между правилом по серийнику и правилом по составу.

Если класса нет в умолчаниях, решение – block: молча разрешить неизвестный класс опаснее, чем запретить. При действительной политике эта ветка недостижима, потому что flash и external_hdd обязательны.

Журнал

"log": { "retention_days": 90, "share_path": "\\\\server\\laportausb$\\logs" }

retention_days – файлы журнала старше этого срока удаляются. Значение должно быть больше нуля. Без раздела log действует 90 дней.

share_path – каталог, куда выгружается копия журнала. Пусто или поля нет – выгрузка не выполняется.

Ошибки разбора

Политика, которая не разобралась, не применяется. Служба продолжает работать по последней удачно прочитанной политике из кэша, а если и кэша нет – уходит в запасной режим и разрешает всё. Молчаливого частичного применения не бывает: либо файл разобран целиком, либо не принят целиком.

В запасном режиме служба не обращается на сайт за обновлениями. Разрешено всё относится к носителям: выход наружу – не носитель, и делать его по умолчанию, не видя выбора администратора, нельзя. Кэш при этом выбор сохраняет: пропавшая шара сама по себе проверку не включает и не выключает.

Отказы выглядят так:

Поле version обязательно и должно быть больше нуля
Класс token не настраивается политикой: токены никогда не блокируются
Правило R-007: serial и vid/pid нельзя задавать одновременно
Неизвестное действие 'deny'. Допустимы: allow, readonly, block

Проверить файл до раскатки можно в окне администратора, на вкладке политики: оно разбирает файл тем же кодом, что и служба, и показывает те же строки.