API ВЕГА
English

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 01api.mist.com
EU 01api.eu.mist.com
GovCloudapi.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/rustmistmcproot:root, 0755Исполняемый файл релиза
/etc/rustmistmcp/mist.jsonroot:rustmistmcp, 0640Профиль Mist, доступный службе для чтения
/etc/rustmistmcp/mist-api-tokenrustmistmcp:rustmistmcp, 0600Учётные данные для исходящих запросов к Mist API v1
/var/lib/rustmistmcp/tokens.jsonrustmistmcp:rustmistmcp, 0600Хранилище Bearer-токенов
/etc/rustmistmcp/audit-hmac.keyrustmistmcp: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.