Перейти к содержимому

Справочник конфигурации Tessera

Этот документ — справочник по основному конфигурационному файлу tessera:

  • /etc/tessera/config.toml — основная конфигурация модуля и демона tessera.

Авторизация «какой пользователь на каком хосте» живёт в самом сертификате — в X.509-расширениях pam_cert_host_binding и pam_cert_user_binding. Когда расширение pam_cert_user_binding присутствует на leaf-сертификате, оно полностью определяет, под каким PAM-пользователем разрешено залогиниться, а массив [[user_mapping]] из этого файла игнорируется. [[user_mapping]] оставлен в схеме как legacy-fallback — он применяется только для тех сертификатов, которые выпущены без расширения pam_cert_user_binding. См. docs/cert-issuance.md.

Каждое поле описано в формате «тип → значение по умолчанию → допустимые значения → влияние на поведение → security implication». Все поля валидируются при загрузке через tessera_core::config::ValidatedConfig::try_from (см. crates/tessera_core/src/config/validated.rs и crates/tessera_core/src/config/raw.rs). Несуществующие поля или неверные типы — ошибка загрузки → fail-closed.

Все примеры используют тестовые данные ([email protected], BANKOMAT-001, ca-test.example). Никаких реальных CA, паролей или клиентских хостов в этом документе нет.

Полный поставочный пример лежит в dist/config/config.toml.example. Этот пример проверяется регрессионным тестом crates/tessera_core/tests/dist_examples_parse.rs — он гарантирует, что пример действительно валидируется через ValidatedConfig::try_from.

ПолеТипDefaultДопустимые значенияВлияниеSecurity implication
crypto_backendстрока"openssl", "pkcs11_native"Какой бэкенд считает подписи и хеши."openssl" обязателен для ГОСТ через gost-engine.
modeстрока"pkcs12", "pkcs11"Где живёт ключ пользователя."pkcs11" — non-extractable ключ; "pkcs12" — программная защита.
pkcs11_moduleпутьабсолютный путь к .soКакой PKCS#11-модуль используется.Обязателен в mode = "pkcs11".
pkcs11_token_labelстрокаNone≤ 64 байт без NULФильтр по CKA_LABEL токена.Защищает от случайного выбора чужого токена на машине.
pkcs11_object_labelстрокаNone≤ 64 байт без NULФильтр по CKA_LABEL объекта (cert/privkey).Аналогично, защита от выбора неправильного объекта.
pkcs11_max_pin_attemptsцелое31..=5Сколько раз модуль предложит ввести PIN.Слишком много → анти-paranoia; слишком мало → плохой UX.
pkcs11_locking_modeстрока"os""os", "mutex"Стратегия блокировок PKCS#11.Зависит от поставляемого PKCS#11-модуля (см. документацию вендора).
pkcs11_pin_promptстрока"Введите PIN токена: "UTF-8, непустая, ≤ 128 байтТекст приглашения PIN на PKCS#11-пути.Локализация UX, не безопасности.
pkcs11_slot_wait_secondsцелое100..=60Сколько секунд ждать вставки токена.0 — не ждать; UX vs. удобство.
pkcs11_allow_extractable_keysбулевоfalsetrue, falseПринимать ли ключи с CKA_EXTRACTABLE = TRUE.false (default) — отказ (fail-closed): extractable-ключ ломает инвариант режима B. true — только WARN pkcs11_extractable_key; включать осознанно.
pkcs12_path_patternстрока"certs/user.p12"относительный путь от mountpoint USB, опц. ${user}Где искать .p12 на USB-носителе (поддерживает ${user}).Только относительный путь; ../. сегменты и абсолютные пути отклоняются валидатором.
pkcs12_pin_promptстрока"Smart-card PIN: "UTF-8, непустая, ≤ 128 байтТекст приглашения для пароля .p12.Локализация UX.
gost_engine_pathпутьNoneабсолютный путь к .soЯвный путь к gost-engine. По умолчанию — поиск по id.None — engine ищется через OPENSSL_ENGINES.
usb_wait_secondsцелое100..=300Сколько секунд ждать USB-носителя.UX. На 0 — fail-fast.
usb_allowed_devicesмассив строк[]строки "vid:pid", по 4 hex-цифры (формат lsusb), напр. ["0951:1666"]Allow-list USB-устройств, рассматриваемых как носитель .p12; пустой/отсутствующий = любое USB block-устройство.Гигиена против случайных/посторонних флешек, НЕ граница доверия: VID/PID подделываются, доверие даёт только расшифровка .p12 + валидация цепочки.
max_usb_partitionsцелое81..=64Максимум партиций, перебираемых при поиске .p12.Защита от DoS: физический атакующий не сможет навязать огромное число mount/umount.
on_usb_removedстрока"lock""lock", "logout", "hook", "shutdown"Действие при подтверждённом извлечении USB."shutdown" уместен для банкоматов; "lock" — для рабочих станций.
usb_removed_grace_secondsцелое00..=300Окно отмены: реинсерт того же серийника отменяет действие.Защищает от ложных срабатываний; на банкоматах ставить 0.
suspend_grace_secondsцелое00..=600Окно после resume, в котором USB-removal игнорируется.Хабы во время suspend часто шумят; 30 секунд — типовое значение.
monitor_fail_modeстрока"strict""strict", "permissive"Пробрасывать ли нефатальные ошибки IPC с monitord вызывающему коду (strict) или глотать с WARN (permissive).DeviceGone/Unauthorized фатальны всегда; транспортные сбои monitord не отменяют успех auth (см. architecture.md §13).

Авторизация (host + user) описана в самом сертификате через X.509 v3 расширения pam_cert_host_binding и pam_cert_user_binding. Этот файл содержит только trust + identity + monitor + hooks; см. cert-issuance.md для выпуска сертификатов с нужными расширениями.

ЗначениеДействие при подтверждённом извлечении USBТиповой сценарий
"lock"LockSession через D-Bus к logind для этой сессии. Хост продолжает работать.Рабочая станция оператора.
"logout"TerminateSession для этой сессии. Хост продолжает работать, остальные сессии целы.Киоски, банкоматы (если хост не выключаем).
"hook"Запускается внешний исполняемый файл, заданный в monitor.on_usb_removed_hook_path.Сложные сценарии (audit + custom action).
"shutdown"PowerOff через D-Bus к logind — выключение хоста.Банкоматы / выделенные АРМ.

При "hook" секция [monitor] должна содержать on_usb_removed_hook_path = "/абсолютный/путь". Валидатор отказывает в загрузке конфига при on_usb_removed = "hook" без hook_path.

ПолеТипDefaultДопустимые значенияВлияниеSecurity implication
on_usb_removed_hook_pathпутьNoneабсолютный путьИсполняемый файл для on_usb_removed = "hook". Валиден только при этом значении on_usb_removed.Исполняется от root; путь проверяется на небезопасные права.
idle_timeout_secondsцелое301..=3600Idle-таймаут IPC-соединения с monitord.Анти-DoS: висящие соединения закрываются.
max_concurrent_connectionsцелое641..=4096Максимум одновременных IPC-соединений к monitord.Анти-DoS: ограничивает расход ресурсов демона.
ПолеТипDefaultДопустимые значенияВлияниеSecurity implication
anchorsсписок путей≥ 1 PEM-файлКорневые CA доверия.Корень доверия. Должны быть 0640 root:root.
intermediatesсписок путей[]PEM-файлыПромежуточные CA (опционально).Снимает нагрузку с поиска цепи.
max_chain_depthцелое51..=16Максимальная глубина X.509-цепи.Анти-DoS.
clock_skew_secondsцелое00..=600Допустимое отклонение часов при проверке notBefore/notAfter.Слишком много — атакующий с устаревшим сертификатом.
allowed_signature_algorithmsсписок строк[]OID или именаWhitelist подписей. Пустой/опущенный — подменяется безопасным дефолтом: sha256/384/512WithRSAEncryption, ecdsa-with-SHA256/384/512 (без SHA-1 и без ГОСТ).Запрет SHA-1/MD5/слабых RSA действует и без явной настройки; ГОСТ требует явного opt-in.

Записи сравниваются точно (без подстрок) с OpenSSL display-формой алгоритма сертификата (см. pre_validate_end_entity в crates/tessera_core/src/x509/pre_validate.rs):

  • RSA: "sha256WithRSAEncryption", "sha384WithRSAEncryption", "sha512WithRSAEncryption"
  • ECDSA: "ecdsa-with-SHA256", "ecdsa-with-SHA384", "ecdsa-with-SHA512"
  • ГОСТ Р 34.10-2012-256: "id-tc26-signwithdigest-gost3410-12-256"
  • ГОСТ Р 34.10-2012-512: "id-tc26-signwithdigest-gost3410-12-512"
ПолеТипDefaultДопустимые значенияВлияниеSecurity implication
modeстрока"none""none", "crl"Какие источники отзыва используются."none" — отзыв не проверяется (НЕ для production).
crl_pathsсписок путей[]PEM/DER-файлыЛокальные CRL.Обязательны при mode = "crl".
crl_max_age_hoursцелоеNone1..=8760 (часы)Максимальный возраст CRL от thisUpdate до отказа.Не задан — свежесть CRL не проверяется; не рекомендуется.

Важно: OCSP не реализован. Значения mode = "ocsp" / mode = "crl_then_ocsp", как и любые ocsp_*-ключи в секции, — ошибка валидации конфига (fail-closed на загрузке; см. openspec/changes/ocsp-support — proposal на будущую поддержку). Офлайн-контур — mode = "crl" с регулярно обновляемым локальным CRL.

ПолеТипDefaultДопустимые значенияВлияниеSecurity implication
enabledboolfalsetrue, falseВключает pinning по SPKI корневых CA.Защита от компрометации УЦ.
allowed_root_spki_sha256список строк[]64-символьные lower-case hexСписок разрешённых SPKI-хешей корней.Любой корень не из списка отвергается.
ПолеТипDefaultДопустимые значенияВлияниеSecurity implication
sourcesсписок строк"machine_id", "dmi_board_serial", "dmi_system_uuid", "dmi_system_serial", "hostname", "custom_command", "override"Цепочка источников host_id. Первый непустой выигрывает.Чем стабильнее источник, тем сильнее host-binding.
fallbackстрока"deny""deny", "warn", "allow"Что делать, если все источники пустые.На production — только "deny".
overrideстрокаNoneUTF-8, без перевода строкЖёстко заданное значение host_id (для тестов).НЕ использовать на production.
custom_commandпутьNoneабсолютный путь к скриптуСкрипт, печатающий host_id в stdout.Скрипт исполняется от root. Должен быть 0750 root:root.
custom_command_timeout_secondsцелое51..=30Таймаут на исполнение custom_command.Анти-DoS.

Реализация цепочки — в crates/tessera_core/src/host_identity/chain.rs. Поведение fallback = "deny" гарантирует fail-closed: если ни один источник не дал значения, аутентификация не проходит.

Только для сертификатов без расширения pam_cert_user_binding. Если на leaf-сертификате расширение pam_cert_user_binding присутствует, массив [[user_mapping]] полностью игнорируется — авторизацию определяет сам сертификат. На новые выпуски расширение должно проставляться всегда (mandatory-extension policy, см. docs/threat-model.md §3.8).

Массив таблиц. Каждая запись — пара «PAM-пользователь → критерий сертификата».

ПолеТипDefaultДопустимые значенияВлияниеSecurity implication
pam_userстрокаUNIX-имя пользователяКакой UNIX-пользователь предъявляется PAM-стеку.Должен быть локальный аккаунт.
cert_subject_cnстрокаNoneзначение CN из subject-DNСопоставление по CN.Один из трёх критериев должен быть установлен.
cert_san_emailстрокаNoneRFC822-имя из SANСопоставление по subjectAltName.Точная строка, без regex.
cert_san_upnстрокаNoneUPN-имя из SAN OtherNameСопоставление по UPN (Microsoft AD).Применимо для смешанных AD-сред.

Ровно одно из cert_subject_cn/cert_san_email/cert_san_upn должно быть установлено в каждой записи. Невыполнение — ошибка валидации.

ПолеТипDefaultДопустимые значенияВлияниеSecurity implication
levelстрока"error", "warn", "info", "debug", "trace"Уровень детализации журнала демона. Переменная окружения TESSERA_LOG имеет приоритет над этим полем."trace" — отладка; не оставлять на production.
syslog_facilityстрокаопционален"auth", "authpriv", "user", "daemon"Deprecated, игнорируется. PAM-модуль пишет в syslog facility auth фиксированно. Поле валидируется (local0..7 не поддержаны — ошибка загрузки), но на runtime не влияет; при наличии ключа в журнал выдаётся WARN «deprecated and ignored».Не влияет на поведение.
journald_priorityboolопционаленtrue, falseDeprecated, игнорируется. При наличии ключа — WARN «deprecated and ignored».Не влияет на поведение.

PIN-коды и пароли никогда не логируются. Полные DN сертификатов логируются на уровне debug и выше; на info и ниже — только CN.

Массив таблиц. Каждый хук — внешняя команда, исполняемая в стадии жизненного цикла. Полная реализация — в crates/tessera_core/src/hooks/.

ПолеТипDefaultДопустимые значенияВлияниеSecurity implication
stageстрока"pre_auth", "post_auth_success", "session_open", "session_close", "usb_removed"На какой стадии жизненного цикла вызывается хук.Хуки исполняются с sandbox-ограничениями (см. docs/threat-model.md).
commandсписок строк[ "/usr/local/sbin/foo", "arg" ], первый элемент — абсолютный путьArgv хука. Передаётся буквально, placeholder’ы в argv НЕ подставляются.Динамика передаётся только через env — argv injection невозможен.
timeout_secondsцелое101..=120Таймаут исполнения.Хук убивается через SIGKILL по истечении.
on_failureстрокаNone"warn", "ignore"; любое иное значение → abortЧто делать при ненулевом коде возврата хука.Default: abort (deny) для pre_auth (там "warn" тоже принудительно abort); "warn" для остальных стадий.
run_asстрокаNoneUNIX-имяUID, под которым запускается хук.По умолчанию — root. Снижение привилегий — лучшая практика.
envтаблица{}строки { KEY = "literal ${placeholder}" }Переменные окружения, передаваемые хуку.База: whitelist PATH/HOME/USER/LOGNAME/LANG + все TESSERA_*-переменные; кастомные ключи могут их переопределить.

Подстановка ${...} работает только в значениях envcommand исполняется буквально (см. crates/tessera_core/src/hooks/fork_exec.rs). Кроме того, хук всегда получает готовый набор переменных TESSERA_STAGE, TESSERA_USER, TESSERA_SERVICE, TESSERA_HOST_ID, TESSERA_HOST_ID_HASH, TESSERA_HOST_ID_SOURCE, TESSERA_CERT_CN, TESSERA_CERT_SERIAL, TESSERA_USB_SERIAL, TESSERA_USB_VID_PID, TESSERA_SESSION_ID (пустая строка, если значение недоступно).

Допустимые placeholder’ы для значений env (см. crates/tessera_core/src/hooks/placeholder.rs):

  • ${pam_user} — UNIX-пользователь.
  • ${pam_service} — PAM-сервис.
  • ${host_id} / ${host_id_hash} / ${host_id_source} — вычисленный host_id, его SHA-256 и имя источника.
  • ${cert_cn} — Common-Name сертификата.
  • ${cert_serial} — серийник сертификата (hex).
  • ${usb_serial} / ${usb_vid_pid} — данные USB-носителя.
  • ${session_id} — UUID PAM-сессии.

Пример: динамические данные — через env, не через argv:

[[hooks]]
stage = "post_auth_success"
command = ["/usr/local/sbin/audit-login"]
timeout_seconds = 5
on_failure = "warn"
env = { AUDIT_USER = "${pam_user}", AUDIT_SERIAL = "${cert_serial}" }

Опциональная. Контролирует wallpaper writer для fly-dm — впечатывает host_id в JPG-фон, на который указывает [background].path в /etc/X11/fly-dm/fly-modern/settings.ini. Workaround для МКЦ-3 fly-modern theme, где PAM_TEXT_INFO не пробрасывается в UI.

ПолеТипDefaultОписание
update_wallpaperboolfalseВключить wallpaper writer.
wallpaper_targetpath/usr/share/wallpapers/fly-default-light.jpgJPG, который daemon перерисовывает.
wallpaper_backuppath/var/lib/tessera/wallpaper.orig.jpgКуда сохраняется one-time оригинал источника.
wallpaper_fontpath/usr/share/fonts/truetype/dejavu/DejaVuSans-Bold.ttfTrueType шрифт для рендера.
wallpaper_font_sizeint64Размер шрифта в пунктах.
wallpaper_text_colorstring"#000000"Цвет в hex (#RRGGBB).
wallpaper_gravityenum"south"north / south / east / west / center — якорь позиционирования.
wallpaper_offset_xint0Горизонтальное смещение в пикселях от gravity-якоря.
wallpaper_offset_yint120Вертикальное смещение в пикселях от gravity-якоря (для south — вверх).
template_rustring"Банкомат %n host_id={host_id_short} ({source})"Шаблон для ru locale.
template_enstring"ATM %n host_id={host_id_short} ({source})"Шаблон для en locale.

Подстановки в template’е: {host_id_short} (первые 8 hex sha256), {source} (имя источника — MachineId, DmiBoardSerial …), %n (hostname). Поведение, baseline для settings.ini, troubleshooting — см. fly-dm-greeter.md.

Legacy-поле update_greet_string (0.3.16–0.3.18) — переписывало /etc/X11/fly-dm/override/GreetString.desktop. На production МКЦ-3 fly-modern игнорируется (no-op). Сохранено для обратной совместимости, но НЕ работает на банкоматах. Использовать update_wallpaper вместо.

Массив таблиц. Каждая запись — переопределение [trust] для ограниченного набора host_id.

ПолеТипDefaultДопустимые значенияВлияниеSecurity implication
when_host_id_inсписок строксписок host_idНа каких машинах применять override.Должен быть непустым.
anchorsсписок путей[]PEM-файлыКакие корни доверия использовать вместо основных.Сужает доверие на конкретных машинах.
intermediatesсписок путей[]PEM-файлыКакие промежуточные использовать.Аналогично.

Worked example: минимальная валидная конфигурация

Заголовок раздела «Worked example: минимальная валидная конфигурация»
crypto_backend = "openssl"
mode = "pkcs12"
pkcs12_path_pattern = "certs/${user}.p12" # относительно mountpoint USB
usb_wait_seconds = 10
on_usb_removed = "lock"
usb_removed_grace_seconds = 5
suspend_grace_seconds = 30
monitor_fail_mode = "strict"
[trust]
anchors = ["/etc/tessera/ca/bundle.pem"]
[trust.revocation]
mode = "none"
[host_identity]
sources = ["machine_id", "hostname"]
fallback = "deny"
[[user_mapping]]
pam_user = "alice"
cert_subject_cn = "Alice"
[logging]
level = "info"

Привязка сертификата к хостам и пользователям полностью описывается двумя X.509 v3 расширениями leaf-сертификата:

  • pam_cert_host_binding (OID 2.25.183976554325829274683049824615098) — SEQUENCE OF UTF8String, каждая запись — либо *, либо sha256:<HEX>, либо «сырое» значение machine_id (тогда сравнение идёт через SHA-256 от строки).
  • pam_cert_user_binding (OID 2.25.215438916728501023845629178354627) — SEQUENCE OF UTF8String, каждая запись — либо *, либо точное имя PAM-пользователя.

Для авторизации сертификата на конкретном host_id / pam_user требуется хотя бы одна совпавшая запись в каждом из расширений. Отсутствие любого из расширений, повреждённое DER-кодирование или полное отсутствие совпадений — отказ (PAM_AUTH_ERR).

Подробности и готовые рецепты openssl.cnf — в cert-issuance.md.

3.1 Банкомат — оффлайн, CRL с TTL, USB обязателен

Заголовок раздела «3.1 Банкомат — оффлайн, CRL с TTL, USB обязателен»

Свойства: машина в железной коробке, нет Интернета, ключ — на токене, извлечение USB → немедленное завершение сессии (без grace).

crypto_backend = "openssl"
mode = "pkcs11"
pkcs11_module = "/usr/lib/librtpkcs11ecp.so"
pkcs11_max_pin_attempts = 3
pkcs11_slot_wait_seconds = 5
usb_wait_seconds = 5
on_usb_removed = "shutdown" # банкомат — выключаемся
usb_removed_grace_seconds = 0 # без отмены
suspend_grace_seconds = 0
monitor_fail_mode = "strict"
[trust]
anchors = ["/etc/tessera/ca/bankomat-ca.pem"]
allowed_signature_algorithms = [
"1.2.643.7.1.1.3.2", # ГОСТ-2012-256
]
[trust.revocation]
mode = "crl"
crl_paths = ["/etc/tessera/crl/bankomat.crl"]
crl_max_age_hours = 72
[trust.pinning]
enabled = true
allowed_root_spki_sha256 = [
"ee0bd4f3a3c8e21d4a2b1c0d9e8f7a6b5c4d3e2f1a0b9c8d7e6f5a4b3c2d1e0f"
]
[host_identity]
sources = ["dmi_board_serial", "machine_id"]
fallback = "deny"
[[user_mapping]]
pam_user = "operator"
cert_san_upn = "[email protected]"
[logging]
level = "warn"

Обоснование выбора:

  • mode = "pkcs11" + librtpkcs11ecp.so: ключ non-extractable.
  • on_usb_removed = "shutdown": банкомат не должен оставаться включённым с разлоченной сессией.
  • usb_removed_grace_seconds = 0: на банкомате не может быть «вынул и передумал».
  • mode = "crl" с crl_max_age_hours = 72: трое суток — компромисс между UX (CRL обновляется ежедневно) и безопасностью.
  • host_identity.sources = ["dmi_board_serial", ...]: материнская плата привязана к корпусу, замена → новый host_id → требуется перевыпустить сертификат с новым значением в pam_cert_host_binding.
  • pinning.enabled = true: компрометация УЦ не открывает все банкоматы автоматически.

3.2 Рабочая станция в защищённом контуре — CRL, ГОСТ-токен

Заголовок раздела «3.2 Рабочая станция в защищённом контуре — CRL, ГОСТ-токен»
crypto_backend = "openssl"
mode = "pkcs11"
pkcs11_module = "/usr/lib/librtpkcs11ecp.so"
pkcs11_token_label = "STAFF"
pkcs11_max_pin_attempts = 3
pkcs11_slot_wait_seconds = 10
usb_wait_seconds = 10
on_usb_removed = "lock"
usb_removed_grace_seconds = 30
suspend_grace_seconds = 60
monitor_fail_mode = "strict"
[trust]
anchors = ["/etc/tessera/ca/staff-ca.pem"]
intermediates = ["/etc/tessera/ca/staff-int.pem"]
allowed_signature_algorithms = [
"1.2.643.7.1.1.3.2", # ГОСТ-2012-256
"1.2.643.7.1.1.3.3", # ГОСТ-2012-512
]
[trust.revocation]
mode = "crl"
crl_paths = ["/etc/tessera/crl/staff.crl"]
crl_max_age_hours = 24
[host_identity]
sources = ["machine_id", "hostname"]
fallback = "deny"
[[user_mapping]]
pam_user = "staff"
cert_subject_cn = "Staff Operator"
[logging]
level = "info"
[[hooks]]
stage = "post_auth_success"
command = ["/usr/local/sbin/audit-login"]
timeout_seconds = 5
on_failure = "warn"
run_as = "audit"
env = { AUDIT_USER = "${pam_user}", AUDIT_SERIAL = "${cert_serial}" }

Обоснование:

  • usb_removed_grace_seconds = 30: пользователь может вытащить токен, чтобы что-то перевставить, и продолжить работу.
  • mode = "crl" + crl_max_age_hours = 24: единственный поддерживаемый источник отзыва; свежесть CRL контролируется TTL.
  • [[hooks]] для аудита: сторонняя система аудита получает событие «вход» (данные — через env, argv передаётся буквально).

3.3 Тестовое окружение — mode = "pkcs12", без revocation

Заголовок раздела «3.3 Тестовое окружение — mode = "pkcs12", без revocation»
crypto_backend = "openssl"
mode = "pkcs12"
pkcs12_path_pattern = "certs/${user}.p12" # относительно mountpoint USB
pkcs12_pin_prompt = "PKCS#12 password: "
usb_wait_seconds = 5
on_usb_removed = "lock"
usb_removed_grace_seconds = 5
suspend_grace_seconds = 0
monitor_fail_mode = "permissive"
[trust]
anchors = ["/etc/tessera/ca/test-ca.pem"]
[trust.revocation]
mode = "none"
[host_identity]
sources = ["hostname"]
fallback = "warn"
[[user_mapping]]
pam_user = "alice"
cert_subject_cn = "Alice"
[logging]
level = "debug"

Обоснование:

  • mode = "pkcs12": чтобы не возиться с реальным токеном на тестах.
  • monitor_fail_mode = "permissive": monitord падает на dev-машинах чаще, чем на production.
  • level = "debug": всё видно, для отладки.
  • revocation.mode = "none": тесты не должны зависеть от внешних сервисов.

Эту конфигурацию нельзя использовать на production. Маркер: в комментарии к файлу пишется # TEST CONFIG — DO NOT DEPLOY.

Секция [mac] опциональна. На сборке без feature astra-mac (Debian, Ubuntu, Astra без strict-mode) присутствие секции не запрещено — но cert_integrity = "required" отвергается на этапе загрузки конфига: stub-бэкенд не может применить метки и не должен молча пропускать аутентификацию, которая обязалась их применять.

ПолеТипПо умолчаниюОписание
cert_integrityenum"optional"Один из required / optional / ignore. См. ниже.
fallback_max_integrity.levelint (-128..127)Уровень fallback-метки, если расширение MAX_INTEGRITY отсутствует и cert_integrity = "optional".
fallback_max_integrity.categoriesstring (hex или CSV)Битовая маска категорий для fallback. Пустая строка = ''B.
runtimeenum"auto"Один из required / auto / disabled. См. ниже (0.3.7+).
warn_on_homedir_label_mismatchbooltrueЛогировать homedir_label_above_session_cap при расхождении.
  • required — сертификат обязан содержать MAX_INTEGRITY. Если расширения нет или DER битый, аутентификация отклоняется (mac_required_no_label / mac_parse_failed).
  • optional — расширение применяется при наличии. Если его нет:
    • есть [mac.fallback_max_integrity] → применяется fallback;
    • нет fallback → шаг применения метки пропускается (логируется mac_label_skipped).
  • ignore — расширение распарсивается для диагностики (mac_label_parsed), но не применяется. Безопасно для миграции парка машин без runtime МКЦ.

Compile-time feature astra-mac решает, может ли бинарь линковаться с libpdp. Поле runtime решает, будет ли бинарь действительно использовать настоящий backend в текущем процессе. Это важно для смешанного парка: один и тот же .deb ставится и на машины с МКЦ, и без, а поведение управляется через config.toml.

  • required — обязателен ParsecBackend + активное МКЦ-ядро (parsec_strict_mode() == 1). Если ядро не активно, аутентификация отклоняется с событием mac_runtime_required (ERROR). Требует собранный с astra-mac бинарь — иначе конфиг отвергается на старте.
  • auto (default) — на старте сессии пробуется parsec_strict_mode; если активен — настоящий ParsecBackend, иначе fallback на StubBackend с одноразовым событием mac_runtime_fallback (WARN). Подходит для дев-машин и смешанного парка.
  • disabled — всегда StubBackend, даже если бинарь собран с astra-mac. Используется на банкоматах без МКЦ-ядра, чтобы гарантированно не вызывать pdp_*. Логируется событие mac_runtime_disabled (INFO).

Валидация конфига:

  • runtime = "disabled" + cert_integrity = "required" отвергается на старте (логически несовместимо: stub не может прочитать или выставить метку, которую требует cert-политика).
  • runtime = "required" в бинаре без astra-mac отвергается на старте.

При open_session выбирается:

effective = intersect(cert_label, runtime_caps)

где runtime_caps — потолок, который libpdp возвращает из ipdp_get_caps(). Уровень эффективной метки — min(cert.level, caps.level); категории — cert.categories & caps.categories. Если после пересечения effective.level < cert.level — пишется событие mac_level_intersected; аналогично для категорий.

[mac]
cert_integrity = "optional"
[mac.fallback_max_integrity]
level = 0
categories = ""

См. docs/threat-model.md §«Privilege-escalation via MAC label» и docs/cert-issuance.md §«MAX_INTEGRITY».