rustmistmcp
Асинхронный сервер Rust Model Context Protocol для облака HPE Juniper Mist
проект mechub — автоматизация сетевой безопасности под контролем владельца
Неофициальный проект сообщества. Это независимый проект сообщества, не связанный с Hewlett Packard Enterprise или Juniper Networks и не одобренный ими. Названия продуктов и товарные знаки используются исключительно для обозначения систем, с которыми взаимодействует программное обеспечение.
rustmistmcp предоставляет клиентам MCP доступ к облаку Juniper Mist: организациям, площадкам, точкам доступа, коммутаторам,
шлюзам, WLAN, клиентам, SLE и Marvis. Интерфейс инструментов ограничен и допускает аудит.
В отличие от rustjunosmcp, который взаимодействует по
NETCONF с отдельными устройствами SRX, и
rustpanosmcp, который обращается по XML-API к
отдельным межсетевым экранам PAN-OS, этот сервер работает с мультитенантной облачной плоскостью управления. Один запрос в контексте организации может охватить все площадки и точки доступа инфраструктуры, поэтому здесь ограничения области действия, ограниченные ответы и контроль изменений — не дополнительные украшения, а основа архитектуры.
Функциональная цель — реализовать возможности Mist из
nowireless4u/hpe-networking-mcp:
состояние площадок и SLE, инвентаризацию устройств и статистику, управление WLAN/SSID, подключение клиентов, события и тревоги, журналы аудита, RRM и обнаружение несанкционированных устройств, прошивки,
NAC/политики, гостевой доступ, вебхуки, планы этажей и Marvis. Всё это реализуется на Rust на основе mecmcp, а не в виде реестра на Python, созданного по спецификации.
В том проекте регистрируется порядка тысячи автоматически сгенерированных инструментов; здесь намеренно не будет такого количества. Весь смысл повторной реализации — в тщательно отобранном, ограниченном и задокументированном интерфейсе.
Связь с mecmcp
mecmcp — независимая от поставщика основа на Rust, общая для семейства серверов MCP от mechub. Этот репозиторий использует эту основу, а не является её форком:
| Задача | Где реализована |
|---|---|
Создание, вычисление дайджеста и проверка токенов, tokens.json, области действия, разрешения, контекст вызывающей стороны | mecmcp-auth |
| Атрибуция, события аудита, редактирование данных, приёмники | mecmcp-audit |
| Транспорт Streamable-HTTP, проверка Host/Origin, ограничения частоты запросов и параллелизма | mecmcp-transport |
| Основа CLI, настройка TLS, сигналы, корректное завершение работы | mecmcp-runtime |
| Контроль изменений: план → дайджест → подтверждение → применение → проверка | mecmcp-changeset |
| Реестр организаций, площадок и арендаторов | mecmcp-inventory |
| REST-клиент Mist, аутентификация по API-токену, модели ответов, набор инструментов | этот репозиторий |
Всё, что не относится к API Mist, находится в upstream-проекте. Если здесь появляется универсальный код аутентификации или транспорта, ему место в mecmcp.
В настоящее время временных исключений нет: исключение, зафиксированное в реестре
docs/UPSTREAM_COMPATIBILITY.md, — адаптер жизненного цикла токенов с типами Mist — было удалено после выполнения условия его удаления. Любое новое исключение необходимо зафиксировать там и указать объективное условие его удаления.
API
Mist предоставляет версионируемый REST API по адресу /api/v1 на облачных конечных точках для разных регионов. Хост определяется домашним регионом организации:
| Регион | Конечная точка |
|---|---|
| Global 01 | api.mist.com |
| EU 01 | api.eu.mist.com |
| GovCloud | api.gc1.mist.com |
Существуют и другие региональные облака. Актуальный список приведён в таблице Juniper Конечные точки API и глобальные регионы. Регион должен задаваться оператором, а не определяться предположительно.
API поставщика Mist поддерживает API-токены и внешний OAuth 2.0. API-токены передаются в заголовке Authorization: Token , могут создаваться для пользователя или организации и наследуют привилегии учётной записи, создавшей их. В версии 1 rustmistmcp намеренно реализована только аутентификация по API-токену; учётные данные OAuth не принимаются. HTTP-аутентификация Basic с учётными данными для входа в Juniper Mist считается устаревшей с сентября 2026 года и реализовываться здесь не будет.
Основные справочные материалы:
Конкретная карта конечных точек, правила пагинации и семантика ограничений частоты запросов проверяются непосредственно по действующему справочнику API до начала реализации клиентского кода. В этом README не будет описываться интерфейс, который ещё не проверен.
Статус
Основа реализована; проверка в рабочем режиме только для чтения на реальном арендаторе пройдена. В рабочей области есть каталог проверенных аудитом операций, строгие метаданные профилей, модели авторизации и контракт MistClient, привязанный к каталогу. Он проверяет входные данные операций Mist и связывает непрозрачные курсоры с настроенным источником. Работа над mecmcp#90 завершена, поэтому HttpMistClient — конкретная реализация HTTPS на основе mecmcp-http — создаётся через MistHandler::from_config в производственном сценарии.
Тестовое развёртывание подключилось к реальной организации Mist. 2026-08-10 через конечную точку, привязанную к loopback-интерфейсу, и bearer-токен с ограниченными разрешениями вызовы get_mist_self (getSelf), get_mist_org (getOrg) и list_mist_sites (listOrgSites) вернули данные арендатора с результатом result: ok за 92–325 мс. Это было условием завершения задачи #11, и оно выполнено.
Что ещё не сделано и не должно описываться как завершённое:
- Эта проверка не подтверждает полную готовность пакета к эксплуатации. Она проводилась только через loopback, без TLS, для одной организации, одного токена и трёх инструментов чтения. Контрольный список в
docs/PACKAGING_ACCEPTANCE.md — проверка имени хоста и цепочки TLS, отказ анонимным запросам и запросам с неверным bearer-токеном, точная проверка Host/Origin — ещё не пройден.
-
При запуске не выполняется проверка идентификатора через
/api/v1/self. Инструментget_mist_selfработает с реальным арендатором, но при запуске проверка/selfне выполняется, иLIVE_MIST_BLOCKERпо-прежнему указывает на этот пробел. -
Операции изменения реализованы только для объектов WAN edge из первого пакета. Первый пакет включает создание и обновление сетей, сервисов, политик сервисов, шаблонов шлюзов и профилей устройств; доступ к этим операциям возможен только через последовательность план → дайджест → подтверждение → применение. Операции удаления, а также назначение и отмена назначения профиля устройства
mist_configuredостаются недоступными. Изменения на реальном арендаторе не применялись.
Если обработчик создан без учётных данных, он использует BlockedMistClient, который не выполняет ввод-вывод; при отказе он возвращает сообщение LIVE_MIST_BLOCKER.
Обнаружение площадок
Инструменты для работы с площадками отказывают в запросах к площадкам, о которых обработчик уже не знает (см. раздел «API»). При запуске сервер вызывает listOrgSites для каждой организации из списка разрешённых, чтобы заполнить карту площадок до начала обслуживания запросов. Параметр --site-refresh-interval-secs (по умолчанию 300) задаёт интервал фонового обновления. Сервер повторяет обход с указанной периодичностью, поэтому добавленные или удалённые в Mist площадки обнаруживаются без перезапуска. Значение 0 отключает фоновую задачу: обнаружение выполняется только один раз при запуске.
Обновление представляет собой периодический фоновый опрос настроенного оператором источника Mist: запросы listOrgSites выполняются каждые site-refresh-interval-secs независимо от активности инструментов. Для этого используется тот же проверяемый по каталогу MistClient, что и для всех остальных операций чтения. Опрос не отражается в аудите отдельных инструментов, поскольку это операция чтения, обновляющая внутреннее состояние сервера, а не вызов со стороны клиента. Если запрос завершился ошибкой или при обновлении для одной организации достигнут установленный предел числа площадок, ранее известные площадки этой организации сохраняются; площадки других организаций не затрагиваются.
Общие примитивы TokenSecret, отмены и набора изменений используются повторно, а не реализуются заново. Названия заголовков Mist, политика каталога, схемы запросов и ответов, конечные состояния, классификация повторных попыток и развёртывание остаются в этом репозитории.
Граница предварительной упаковки и развертывания
Файлы Docker, архивов, systemd и LXC, добавленные в репозиторий, предназначены только для предварительной упаковки. LXC-контейнер, собранный из этих файлов для лаборатории, обслуживал реальный трафик арендаторов только для чтения (issue #11), однако это не означает, что упаковка прошла приемку: в ходе теста TLS не использовался, а прослушивание за пределами loopback-интерфейса не включалось. Поэтому пункты про TLS, Host/Origin и недействительный bearer-токен в docs/PACKAGING_ACCEPTANCE.md остаются непроверенными. Проверка запуска /api/v1/self не реализована, а изменения поддерживаются только для объектов WAN edge из batch-1 в рамках жизненного цикла change-set. Применение изменений в рабочей среде арендатора не выполнялось.
Нельзя заявлять о выпуске v1, пока этот список проверок не будет полностью пройден.
OCI-образ собирается в несколько этапов: для сборки используется Rust builder, зафиксированный по digest, а для runtime — distroless Debian 13, также зафиксированный по digest. В образе запускается только /usr/local/bin/rustmistmcp с UID/GID 65532; в runtime-образе нет shell, менеджера пакетов и средства загрузки во время выполнения. Данные CA поступают из базового distroless-образа.
Используйте неизменяемый digest образа, а не изменяемый тег. В примере Compose доступ предусмотрен только для чтения: удаляются все capabilities, включён режим no-new-privileges, ограничиваются число процессов и объём /tmp, каталог /etc/rustmistmcp монтируется только для чтения, а /var/lib/rustmistmcp — для чтения и записи. Не помещайте секреты Mist или bearer-токены в слои образа, переменные окружения Compose или аргументы команд.
В службе и OCI-команде, добавленных в репозиторий, используется точный HTTP-контракт общего CLI, доступного только через loopback: /etc/rustmistmcp/mist.json, хранилище bearer-токенов, порт 30030, JSON-аудит с редактированием HMAC и прямая передача данных в journald для systemd. В OCI-аудите используется JSON в stderr, а сокет журнала хоста не монтируется. Флага для состояния изменений и проверки готовности live-Mist нет. Теперь --version выводит имя и версию этого бинарного файла, поскольку работа над mecmcp#159 завершена. Поэтому идентификатор выпуска проверяется с помощью --version, --help, BUILD-INFO и значений SHA-256 артефакта и развернутого экземпляра.
Пример Compose предназначен только для Linux: host networking позволяет обращаться к прослушивателю контейнера 127.0.0.1:30030 с того же хоста, не открывая его для внешнего интерфейса. Перед запуском убедитесь, что файлы состояния и секретов, подключаемые через bind mount, доступны числовому UID/GID 65532:
packaging/container/state/tokens.json install -m 0600 /dev/null packaging/container/runtime/mist-api-token
Populate this before starting Compose; it is mounted at the path referenced
by mist.json and must never be put in an environment variable or command.
read -sp 'Mist API token: ' token && printf '%s' "$token" > packaging/container/runtime/mist-api-token && unset token
Mint the bearer token into the state mount before starting Compose. The
secret is printed once; store it in the client that will call this server.
rustmistmcp token add --tokens-file packaging/container/state/tokens.json
--name my-client --devices '' --tools ''
-f packaging/container/runtime/mist.json
Set modes before ownership so the files remain 0600 after chown.
chmod 0600 packaging/container/runtime/mist-api-token packaging/container/state/tokens.json
sudo chmod 0640 packaging/container/runtime/mist.json
sudo chown root:65532 packaging/container/runtime/mist.json
sudo chown 65532:65532 packaging/container/runtime/mist-api-token
packaging/container/state/tokens.json
sudo chown -R 65532:65532 packaging/container/state
sudo chown root:65532 packaging/container/runtime
RUSTMISTMCP_IMAGE='ghcr.io/mechubsec/rustmistmcp@sha256:'
docker compose -f packaging/container/compose.example.yaml up">
install -d -m 0750 packaging/container/runtime
install -d -m 0700 packaging/container/state
cp examples/mist.example.json packaging/container/runtime/mist.json
printf '%s\n' '{"version":1,"tokens":[]}' > packaging/container/state/tokens.json
install -m 0600 /dev/null packaging/container/runtime/mist-api-token
# Populate this before starting Compose; it is mounted at the path referenced
# by mist.json and must never be put in an environment variable or command.
read -sp 'Mist API token: ' token && printf '%s' "$token" > packaging/container/runtime/mist-api-token && unset token
# Mint the bearer token into the state mount before starting Compose. The
# secret is printed once; store it in the client that will call this server.
rustmistmcp token add --tokens-file packaging/container/state/tokens.json \
--name my-client --devices '*' --tools '*' \
-f packaging/container/runtime/mist.json
# Set modes before ownership so the files remain 0600 after chown.
chmod 0600 packaging/container/runtime/mist-api-token packaging/container/state/tokens.json
sudo chmod 0640 packaging/container/runtime/mist.json
sudo chown root:65532 packaging/container/runtime/mist.json
sudo chown 65532:65532 packaging/container/runtime/mist-api-token \
packaging/container/state/tokens.json
sudo chown -R 65532:65532 packaging/container/state
sudo chown root:65532 packaging/container/runtime
RUSTMISTMCP_IMAGE='ghcr.io/mechubsec/rustmistmcp@sha256:<verified-64-hex-digest>' \
docker compose -f packaging/container/compose.example.yaml up
Заполните Mist API token до передачи файлов во владение UID/GID 65532 и до выполнения up: после смены владельца непривилегированный оператор больше не сможет записать токен, а загрузчик учётных данных отклоняет пустой токен при запуске. Не помещайте значение в переменную окружения, аргумент команды, слой образа или файл Compose.
Добавление, просмотр, отзыв и ротация MCP bearer-токенов с правами выполняются общей функцией token_cmd::run_with_grant; частный адаптер с типом Mist, который ранее связывал эти операции, удалён. Новые токены, создаваемые командой token add, по-прежнему не содержат прав; общая команда сохраняет существующие проверенные значения MistGrant. Это хранилище bearer-токенов отделено от Mist API token, который используется исходящим клиентом.
Руководство по запуску в контейнере Docker
Пошаговые инструкции по запуску rustmistmcp в Docker, включая требования к настройке аудита и конфигурации для режима с двумя операторами или лабораторного режима, приведены в документе docs/HOW-TO-SETUP-DOCKER.md.
Требования для операторов LXC
Пошаговое руководство по сборке приведено в документе docs/HOW-TO-SETUP-LXC.md.
Документы по проверке безопасности
-
docs/THREAT_MODEL.md — границы доверия, субъекты безопасности, радиус воздействия в случае компрометации токена или агента в реальной организации Mist, а также действующие и запланированные меры защиты.
-
docs/TOKEN_ROLE_GUIDANCE.md — почему для исходящих запросов к Mist API следует использовать отдельный токен организации с минимально необходимыми правами, а не личный токен или токен суперадминистратора.
Развёртывайте сервер только в непривилегированном LXC-контейнере на Debian 13 с nesting=1.
Для целевой версии systemd параметр nesting=1 необходим, чтобы система корректно сообщала о состоянии точек монтирования.
Из гостевой системы невозможно подтвердить настройки непривилегированного режима и вложенной виртуализации на стороне хоста. Проверьте их по авторизованному реестру хостов, а затем явно подтвердите установщику, задав RUSTMISTMCP_LXC_HOST_PROOF=unprivileged=1,nesting=1. Установщик также откажется работать на системах, отличных от Debian 13 и LXC.
Не обращайтесь к Proxmox или арендатору Mist во время сборки пакета. Если отдельно получено разрешение на проверку готовности лабораторной среды, сначала убедитесь, что VMID 613 и его адрес не используются. Проверку разрешено выполнять только на заново созданном LXC с VMID 613. Не работайте с VMID 612 и не создавайте снимки посторонних гостевых систем.
Установщик архива проверяет контрольную сумму и полную структуру архива до внесения каких-либо изменений. Он не перезаписывает действующие конфигурацию, секреты, состояние или изменённый файл службы, если не задан параметр RUSTMISTMCP_FORCE_UNIT=1, и не включает службу автоматически.
Для предварительной проверки без внесения изменений и без прав root используйте packaging/lxc/install.sh --validate-only ARCHIVE ARCHIVE.sha256.
Примеры, не предназначенные для непосредственной работы, устанавливаются как /etc/rustmistmcp/mist.example.json и /etc/rustmistmcp/tokens.example.json. Настройте рабочие файлы вручную:
| Путь | Требуемый владелец и режим доступа | Назначение |
|---|---|---|
/usr/local/bin/rustmistmcp | root:root, 0755 | Исполняемый файл релиза |
/etc/rustmistmcp/mist.json | root:rustmistmcp, 0640 | Профиль Mist, доступный службе для чтения |
/etc/rustmistmcp/mist-api-token | rustmistmcp:rustmistmcp, 0600 | Учётные данные для исходящих запросов к Mist API v1 |
/var/lib/rustmistmcp/tokens.json | rustmistmcp:rustmistmcp, 0600 | Хранилище Bearer-токенов |
/etc/rustmistmcp/audit-hmac.key | rustmistmcp:rustmistmcp, 0600 | Ключ HMAC для аудита |
/var/lib/rustmistmcp/changeset-state.json | состояние пользователя службы, родительский каталог — 0700 | Путь к постоянному хранилищу состояния |
Размер постоянного журнала journald ограничен 512 MiB. До обработки реального трафика настройте пересылку журнала на удалённый сервер или в SIEM.
Запуск файлового аудита работает в режиме fail-closed (mecmcp#158): если файл --audit-log-file невозможно открыть, служба завершает запуск, а не продолжает работу без аудита. При этом journald остаётся базовым каналом доставки журналов.
Корректное завершение работы HTTP (mecmcp#156) настроено: сигналы SIGTERM и SIGINT останавливают приём запросов, после чего сервер ожидает завершения выполняющихся запросов не более 10 секунд. Это заданное поведение, а не подтверждённая под нагрузкой процедура завершения обработки запросов.
Для любого внешнего интерфейса привязки требуются TLS и точная настройка разрешённых значений Host и Origin. По умолчанию сервер доступен только через loopback.
Для каждого кандидата релиза собирайте проект из чистого дерева с помощью scripts/build-release.sh. Скрипт создаёт детерминированный архив rustmistmcp-v-.tar.gz, отдельный файл с контрольной суммой SHA-256 и BUILD-INFO. До развёртывания определите минимальную версию glibc, необходимую созданному бинарному файлу:
objdump -T bin/rustmistmcp | grep -oE 'GLIBC_[0-9]+\.[0-9]+' | sort -Vu | tail -1
Release CI создаёт контрольные суммы, SBOM, данные о происхождении сборки, OCI-образы для linux/amd64 и запись с неизменяемым digest. Обновите upstream-эталон и спецификацию один раз на этапе RC, заново сформируйте каталог, проверьте различия и убедитесь в отсутствии расхождений по функциональному соответствию до проведения отдельной приёмки развёртывания.
Далее выполните следующие задачи по порядку:
-
Реализуйте проверочный запрос идентификации при запуске к
/api/v1/self. Необходимый для него исходящийHttpMistClientуже добавлен вmecmcp#90, а инструментget_mist_selfподтверждает, что сам вызов работает с действующей организацией. -
Завершите оставшиеся пункты
docs/PACKAGING_ACCEPTANCE.md: TLS, проверку Host и Origin при доступе не через loopback, а также отклонение анонимных запросов и запросов с некорректным bearer-токеном. Проверка только для чтения через loopback, описанная в issue #11, эти сценарии не охватывала. -
Добавляйте операции изменения только через
mecmcp-changeset, никогда не выполняйте их напрямую. Проектирование описано в issue #14; разделениеexecuteреализовано вexecute_class.rs.
Основные принципы проектирования
-
Тщательно отобранные, а не сгенерированные инструменты. Инструменты выбираются и описываются вручную. Тысяча автоматически зарегистрированных конечных точек превращает поиск возможностей в задачу для модели, а не предоставляет ей дополнительные возможности.
-
Сначала чтение, затем запись. Доступ к каждому инструменту изменения возможен только через последовательность «план → digest → подтверждение → применение». Ни один инструмент не изменяет данные организации одним неподтверждённым вызовом.
-
Токены с ограниченной областью действия. Для Bearer-токенов явно задаются области действия по инструментам, организациям и сайтам. Отсутствие таких ограничений считается ошибкой конфигурации, а не упрощённым режимом.
-
Ограниченный ввод-вывод. Размеры запросов и ответов ограничены. Облачная плоскость управления может вернуть данные по всей инфраструктуре, но сервер не станет передавать такой объём без ограничений.
-
Аудируемость заложена в архитектуру. Атрибуция и редактирование конфиденциальных данных реализованы в
mecmcp-audit, поэтому каждый вызов можно связать с его инициатором, не раскрывая учётные данные в журналах. -
В репозитории нет секретов. Токены Mist API хранятся в файлах, которыми управляет оператор, вне системы контроля версий. В версии v1 не поддерживаются секреты клиента OAuth.
-
Секреты устройств скрываются до передачи данных модели. PSK для WLAN, общие секреты RADIUS/SNMP, а также ключи и токены API, возвращаемые Mist, удаляются с помощью
mecmcp-redactпри каждом чтении, предназначенном для модели, предварительном просмотре набора изменений и формировании ответа с планом. Для этого выполняется сопоставление по списку известных полей, содержащих учётные данные. Это не криптографическая гарантия: механизм лишь пытается обнаружить поля, ещё не учтённые в списке, и не делает безопасным хранение секретов в произвольных полях.
Инструменты WAN edge
Сервер предоставляет тщательно отобранный набор инструментов для чтения данных об организациях, сайтах, устройствах, WLAN, клиентах, SLE, событиях и диагностике. Перечисленные ниже инструменты для WAN edge предназначены для шлюзов SRX/SSR и подключений overlay-сети. Полный реестр инструментов см. в KNOWN_TOOLS файла crates/rustmistmcp/src/server/mod.rs.
| Инструмент | Описание |
|---|---|
apply_mist_change_set | Применить к Mist подтверждённый набор изменений. Проверяет подтверждение, выявляет расхождения, выполняет изменение и проверяет результат. |
approve_mist_change_set | Подтвердить запланированный набор изменений от имени второго участника. Подтверждающий должен отличаться от владельца. |
get_mist_change_set | Просмотреть подготовленный набор изменений: его состояние, владельца, значения до и после, а также статус подтверждения. Секретные поля в значениях до и после (PSK, общие секреты, ключи и токены API) скрываются; структурные поля и прочие метаданные сохраняются. |
get_mist_sle_impact | Получить список шлюзов, приложений или сводку по объектам, на которые влияет одна метрика SLE сайта. |
get_mist_wan_config | Получить объект конфигурации WAN edge по его идентификатору. Секретные поля (PSK туннелей в шаблонах шлюзов, общие секреты, ключи и токены API) скрываются; структурные поля и прочие метаданные сохраняются. |
get_mist_wan_edge_stats | Получить метрики шлюзов WAN edge для сайта или метрики аналитики для одного шлюза. |
list_mist_applications | Вывести список приложений, обнаруженных на сайте, подсчитать их количество или показать каталог приложений шлюзов. |
list_mist_wan_config | Вывести список объектов конфигурации WAN edge: сетей, служб, политик служб, шаблонов шлюзов или профилей устройств. Секретные поля (PSK туннелей в шаблонах шлюзов, общие секреты, ключи и токены API) скрываются; структурные поля и прочие метаданные сохраняются. |
list_mist_wan_edges | Вывести список шлюзов WAN edge (SRX/SSR) в организации или на сайте. |
plan_mist_change | Подготовить набор изменений для объекта конфигурации WAN edge: сети, службы, политики службы, шаблона шлюза или профиля устройства. Возвращает план, связанный с digest и готовый к подтверждению. Массивы заменяются целиком; значение null удаляет поле. Секретные поля в возвращаемых значениях до и после скрываются; сам процесс подготовки и применения плана работает с незамаскированными значениями. |
search_mist_bgp_peers | Найти статистику BGP-пиров WAN edge в организации или на сайте либо подсчитать их количество. |
search_mist_peer_paths | Найти статистику путей между узлами overlay-сети SD-WAN либо подсчитать количество путей по отдельному полю. |
search_mist_service_path_events | Найти события путей служб WAN edge для сайта либо подсчитать их количество. |
search_mist_tunnels | Найти статистику туннелей IPsec WAN edge либо подсчитать их количество по отдельному полю. |
Пересылка аудита в хранилище событий
Журнал аудита не хранится только на этом хосте. Сервер соответствует стандарту семейства: Стандарт пересылки аудита.
Запись аудита, которая существует только на машине, где она была создана, — это не журнал аудита, а всего лишь файл журнала на компьютере, оператор которого может быть тем самым лицом, к которому относится эта запись.
Текущий формат (уже действует)
--audit-format json \
--audit-log-file /var/lib/rustmistmcp/audit.jsonl
Формат JSON обязателен. Формат text предназначен для чтения в терминале и не подходит для автоматического разбора. Файл — артефакт для оператора, поэтому его необходимо ротировать: сервер никогда не очищает его содержимое.
Транспорт (описан, но пока не реализован)
Записи напрямую добавляются в ssdf.audit в SSDF в виде строк, связанных хеш-цепочкой, согласно объединённому контракту доказательств SSDF. Благодаря этому можно обнаружить удаление или изменение строки. Работа отслеживается в mecmcp#292.
Более простой вариант с syslog был разработан, но отклонён: он работает, однако записи не связаны в цепочку. При этом все остальные звенья процесса по своей конструкции позволяют обнаружить подмену: дайджесты плана связаны с согласованиями, каждое согласование указывает отдельный субъект, а token_verified_fields отделяет подтверждённые сведения о происхождении данных от заявленных. Если последнее звено не будет связано с цепочкой, эта гарантия исчезнет именно там, где она особенно важна аудитору. Обоснование зафиксировано в стандарте.
Как интерпретировать результат
В token_verified_fields перечислены поля происхождения данных, подлинность которых подтвердил токен.
Остальные поля этой группы — client_name, model_id, session_id — заявлены клиентом и ничем не аутентифицированы. Не считайте их равнозначными подтверждённым полям.
request_id позволяет связать событие транспортного уровня, событие обработчика и, в Junos, комментарий к фиксации изменений на устройстве.
Лицензия
Лицензия MIT.
--lab-mode
Флаг --lab-mode отменяет требование о втором субъекте для лабораторной среды с одним оператором, где контроль двумя лицами был бы лишь формальностью, а не реальной мерой контроля. По умолчанию режим выключен. Не включайте его там, где безопасность инфраструктуры имеет значение.
Что меняется и что остаётся без изменений:
-
Отмена требования применяется автоматически при создании набора изменений. Отдельной команды для отмены нет, а последовательность действий остаётся такой же, как в рабочей среде: подготовка → применение.
-
Планирование, дайджест плана, обнаружение дрейфа конфигурации и повторная проверка перед применением продолжают выполняться. Lab mode отменяет требование о втором проверяющем, но не отменяет регистрацию изменений.
-
Согласующий никогда не подставляется фиктивно. Для набора изменений, созданного с отменой требования, в записи о согласовании указывается
approver: nullиwaived: { reason: "lab-mode" }. Такая запись криптографически отличается от настоящего согласования двумя лицами и не может быть переименована задним числом. Это важно, если впоследствии потребуется доказать, какие изменения прошли с реальным разделением обязанностей. -
При запуске сервера режим сопровождается заметным предупреждением.
Если вы хотите в одиночку тестировать запись изменений, не отменяя контроль, создайте два токена с разными именами: один используйте для подготовки изменений, другой — для согласования. Субъект определяется именем токена, а самостоятельное согласование запрещено. Так один человек сможет пройти весь процесс, не нарушая контрольных требований. Этот вариант предпочтительнее везде, где сама процедура имеет значение.
Включение режима
Добавьте флаг в конфигурацию службы. При установке из пакета используйте дополнительный файл конфигурации, а не редактируйте поставляемый файл службы: иначе после обновления флаг может незаметно исчезнуть.
sudo systemctl edit rustmistmcp
При замене ExecStart необходимо указать команду полностью. Поэтому скопируйте поставляемую команду и добавьте флаг, а не сокращайте её:
[Service]
# Перед заменой очистите поставляемый ExecStart; иначе systemd добавит новую команду к существующей.
ExecStart=
ExecStart=/usr/local/bin/rustmistmcp \
--device-mapping /path/to/mist-profile.json \
--transport streamable-http \
--host 127.0.0.1 \
--port 30030 \
--tokens-file /path/to/tokens.json \
--lab-mode
sudo systemctl daemon-reload && sudo systemctl restart rustmistmcp
Убедитесь, что режим включился: проверьте журнал аудита на наличие предупреждения при запуске.
sudo journalctl -u rustmistmcp --since "1 minute ago" | grep -i "lab mode"
В журнале должно появиться сообщение: lab mode enabled: change sets are approved on creation with no second principal. Records carry approval_waiver=lab-mode. Do not run this against production devices.