Справочник: файл политики
Политика – один файл 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_match | equals либо 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": "Отзывается, если внутри окажется клавиатура" }
]
}
Порядок применения правил
Решение принимается первым подошедшим пунктом сверху вниз. В журнал попадает причина – она в скобках.
-
Токен (
token_never_enforced). Всегдаallow. Ни одно правило к токену не применяется: заблокированный токен – это потерянный вход в систему.Токеном считается устройство, которое система опознала как смарткарт-ридер, либо устройство с известным VID производителя токенов, объявившее интерфейс чип-карты. Одного VID недостаточно: его сообщает о себе само устройство, и перепрошитая флешка назвалась бы токеном. Узел, объявивший интерфейс накопителя, токеном не считается ни при каком VID – поэтому flash-раздел настоящего токена подчиняется правилам как обычная флешка. Вход в систему и ЭЦП этим не задеваются: они живут на соседнем узле, которого запрет раздела не касается.
-
Точное правило по
serial(exact_rule_serial). Только если серийный номер заслуживает доверия: часть дешёвых носителей сообщает один номер на всю партию. -
Групповое правило по
vid+pid(group_rule_vid_pid). Правило с заданнымserialна этом шаге не рассматривается. -
Умолчание по классу (
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
Проверить файл до раскатки можно в окне администратора, на вкладке политики: оно разбирает файл тем же кодом, что и служба, и показывает те же строки.