rust-panosmcp
Асинхронный сервер Model Context Protocol на Rust для межсетевых экранов Palo Alto Networks PAN-OS
проект mechub — автоматизация сетевой безопасности под полным контролем владельца
Неофициальный проект сообщества. Это независимый проект сообщества, не связанный с Palo Alto Networks и не одобренный этой компанией. Названия продуктов и товарные знаки используются только для обозначения систем, с которыми взаимодействует программное обеспечение.
В репозитории представлена версия v0.16.2: сервер с защитой по bearer-токену, структурированным журналированием аудита, контролируемым жизненным циклом кандидатной конфигурации PAN-OS и защищённой упаковкой релизов. Аутентификацию и аудит обеспечивают общие крейты mecmcp-auth и mecmcp-audit.
Цель проекта — создать компактный, быстрый и готовый к эксплуатации сервер с таким же
уровнем безопасности, как у rust-junosmcp: аутентификацией по bearer-токену, ограничениями
доступа к устройствам и инструментам для каждого токена, TLS, строгими правилами запрета
небезопасной привязки к удалённым интерфейсам, ограничениями на размер входных
и выходных данных, аудируемыми операциями изменения конфигурации и эффективным повторным
использованием подключений.
Архитектура и план разработки описаны в PLAN.md. Границы
безопасности и блокирующие выпуск меры контроля зафиксированы в
Структура рабочего пространства
rust-panosmcp/ # MCP binary and stdio adapter
rust-panosmcp-auth/ # bearer and secret-handling foundations
rust-panosmcp-core/ # inventory, PAN-OS client, validation, tool logic
config/ # secret-free inventory examples
docs/ # operator guidance and phase notes
fuzz/ # isolated cargo-fuzz workspace
packaging/ # distroless/container and systemd assets
scripts/ # release, matrix, fuzz, and benchmark gates
Быстрый старт
Установка
Выберите один из трёх способов установки:
Архив релиза (Linux x86_64)
Скачайте последнюю версию со страницы релизов на GitHub. Файлы релиза имеют формат имени rust-panosmcp-v0.16.2-x86_64-unknown-linux-gnu.tar.gz; рядом с каждым архивом доступен соответствующий файл .sha256.
# Download and verify
curl -LO https://github.com/mechubsec/rustpanosmcp/releases/download/v0.16.2/rust-panosmcp-v0.16.2-x86_64-unknown-linux-gnu.tar.gz
curl -LO https://github.com/mechubsec/rustpanosmcp/releases/download/v0.16.2/rust-panosmcp-v0.16.2-x86_64-unknown-linux-gnu.tar.gz.sha256
sha256sum -c rust-panosmcp-v0.16.2-x86_64-unknown-linux-gnu.tar.gz.sha256
# Extract
tar xzf rust-panosmcp-v0.16.2-x86_64-unknown-linux-gnu.tar.gz
cd rust-panosmcp-v0.16.2
# Install the binary and systemd assets
sudo install -m 0755 bin/rust-panosmcp /usr/local/bin/rust-panosmcp
sudo install -m 0644 packaging/systemd/rust-panosmcp.sysusers /usr/lib/sysusers.d/rust-panosmcp.conf
sudo install -m 0644 packaging/systemd/rust-panosmcp.tmpfiles /usr/lib/tmpfiles.d/rust-panosmcp.conf
sudo install -m 0644 packaging/systemd/rust-panosmcp.service /etc/systemd/system/rust-panosmcp.service
# Create the service user and directories
sudo systemd-sysusers
sudo systemd-tmpfiles --create
# Generate the HMAC key for audit redaction (required).
# Guarded: NEVER overwrite an existing key. The key is what makes an HMAC-redacted
# device identifier comparable across audit history, so replacing it silently
# breaks correlation with every record already written. These steps are safe to
# re-run during an upgrade only because of this guard.
sudo sh -c '[ -f /etc/rust-panosmcp/audit-hmac.key ] ||
head -c 32 /dev/urandom | base64 > /etc/rust-panosmcp/audit-hmac.key'
sudo chmod 0600 /etc/rust-panosmcp/audit-hmac.key
sudo chown rust-panosmcp:rust-panosmcp /etc/rust-panosmcp/audit-hmac.key
# Start the service
sudo systemctl daemon-reload
sudo systemctl enable --now rust-panosmcp
Эти команды создают отдельного системного пользователя rust-panosmcp и подготавливают каталоги /etc/rust-panosmcp (конфигурация, владелец — root) и /var/lib/rust-panosmcp (состояние). HMAC-ключ в /etc/rust-panosmcp/audit-hmac.key необходим для маскирования идентификаторов устройств в журналах аудита — без него служба не запустится. В распакованном архиве есть примеры конфигурации в каталоге config/. Перед запуском возьмите devices.example.json и tokens.example.json за основу для файлов в /etc/rust-panosmcp. Подробнее об устройстве systemd см. в каталоге packaging/systemd/.
LXC (Debian 13)
Для выделенного непривилегированного контейнера LXC на Proxmox или отдельной системы systemd-nspawn в архив релиза включён идемпотентный установщик, автоматизирующий описанную выше последовательность действий. Полное руководство по настройке, включая создание контейнера, см. в HOW-TO-SETUP-LXC.md.
# Download and verify
curl -LO https://github.com/mechubsec/rustpanosmcp/releases/download/v0.16.2/rust-panosmcp-v0.16.2-x86_64-unknown-linux-gnu.tar.gz
curl -LO https://github.com/mechubsec/rustpanosmcp/releases/download/v0.16.2/rust-panosmcp-v0.16.2-x86_64-unknown-linux-gnu.tar.gz.sha256
sha256sum -c rust-panosmcp-v0.16.2-x86_64-unknown-linux-gnu.tar.gz.sha256
# Extract and run the installer
tar xzf rust-panosmcp-v0.16.2-x86_64-unknown-linux-gnu.tar.gz
cd rust-panosmcp-v0.16.2
sudo packaging/lxc/install.sh
# Configure the inventory and mint the first token
sudo vi /etc/rust-panosmcp/devices.json
sudo rust-panosmcp token add \
--tokens-file /var/lib/rust-panosmcp/tokens.json \
--name initial-token \
--devices fw-example \
--tools list_devices,gather_device_facts,execute_panos_op,get_panos_config
# Start the service
sudo systemctl enable --now rust-panosmcp.service
Установщик создаёт пользователя rust-panosmcp и каталоги с помощью systemd-sysusers и systemd-tmpfiles, устанавливает бинарный файл и unit-файл, создаёт пустой tokens.json с правами доступа 0600 и не перезаписывает существующий /var/lib/rust-panosmcp/mutation-state.json (журнал аудита наборов изменений). По умолчанию служба принимает подключения по адресу http://127.0.0.1:30031/mcp. Параметры переопределения переменных среды и особенности обновления описаны в packaging/lxc/install.sh.
Docker / GHCR
Предварительно собранные образы публикуются в ghcr.io/mechubsec/rustpanosmcp при выпуске каждого релизного тега. Процесс сборки описан в .github/workflows/release-image.yml. Полное руководство по настройке, включая режимы с двумя участниками и для лабораторной среды, см. в HOW-TO-SETUP-DOCKER.md.
# Pull the image
docker pull ghcr.io/mechubsec/rustpanosmcp:latest
По умолчанию CMD привязывает сервер к 127.0.0.1:30031 внутри контейнера. Поэтому обычный запуск
docker run без -p, --host, --allowed-host и --allowed-origin
завершится без ошибок, но сервер будет недоступен извне контейнера. Используйте
HOW-TO-SETUP-DOCKER.md, чтобы запустить docker run в рабочем режиме с двумя участниками
или в лабораторном режиме. В руководстве приведены нужная публикация порта и флаги,
которые уже передаются во встроенном ENTRYPOINT. Также можно воспользоваться
включённым файлом compose.example.yaml.
Запуск с Docker (stdio)
Для MCP-клиентов, которые запускают сервер через stdin/stdout, подготовьте файл инвентаризации той же структуры, что и config/devices.example.json:
{
"version": 1,
"policy": {
"mode": "allowlist",
"allow": ["show system info", "show interface all"]
},
"devices": [
{
"name": "panos-demo",
"endpoint": "https://panos-demo.example.net",
"vsys": "vsys1",
"api_key": { "type": "env", "name": "PANOS_DEMO_API_KEY" },
"tags": ["lab", "read-only"]
}
]
}
Перед запуском контейнера экспортируйте переменную API-ключа. Такой способ передачи позволяет не указывать ключ в командной строке, однако доступ к Docker daemon всё ещё может раскрыть значения переменных среды при проверке контейнера. Для более надёжной защиты используйте описанный ниже в разделе конфигурации вариант с API-ключом в файле ({"type":"file","path":"/protected/path"}) и подключите этот файл только для чтения с правами 0600.
export PANOS_DEMO_API_KEY=replace-with-runtime-secret
Настройте файлы инвентаризации и состояния так, чтобы контейнерный пользователь (uid:gid 65532:65532) имел к ним права на чтение и запись. Файлы с секретами должны иметь права 0600. На уровне процесса stdio не обеспечивает аутентификацию: запускающий процесс может использовать все устройства из подключённого файла инвентаризации и все инструменты. Ограничьте доступ, включив в этот файл только необходимые устройства и используя роль PAN-OS API только для чтения. Каталог состояния должен быть доступен для записи, поскольку сервер сохраняет в нём состояние аудита.
mkdir -p state
chmod 0600 devices.json
sudo chown 65532:65532 devices.json state
docker run --rm -i \
--user 65532:65532 \
-e PANOS_DEMO_API_KEY \
-v "$PWD/devices.json:/etc/rust-panosmcp/devices.json:ro" \
-v "$PWD/state:/var/lib/rust-panosmcp" \
ghcr.io/mechubsec/rustpanosmcp:0.15.0 \
--transport stdio
В ENTRYPOINT образа уже указаны пути к конфигурации, токену, состоянию и ключу аудита, поэтому не добавляйте эти флаги после имени образа. Путь к токену используется только для HTTP. Эта команда не запускает HTTP и не включает TLS для прослушивателя: параметр --transport stdio заменяет CMD образа, в том числе параметры привязки HTTP и порта. Подключение к межсетевому экрану по-прежнему выполняется через HTTPS с учётом настроек доверия TLS из файла инвентаризации.
Сборка из исходного кода
Требуется Rust версии 1.89 или новее (MSRV).
git clone https://github.com/mechubsec/rustpanosmcp.git
cd rustpanosmcp
cargo build --release --locked
./target/release/rust-panosmcp --version
Запуск (stdio)
Возьмите за основу config/devices.example.json, не добавляйте реальный файл инвентаризации в Git и задайте секрет среды, на который он ссылается:
export PANOS_LAB_API_KEY='runtime-secret'
cargo run --locked --release -- --device-mapping /absolute/path/devices.json
Запуск (streamable-http с аутентификацией)
Сначала создайте токен с минимальными привилегиями, затем запустите TLS-транспорт Streamable HTTP:
cargo run --locked --release -- \
--device-mapping /etc/rust-panosmcp/devices.json \
token add \
--tokens-file /etc/rust-panosmcp/tokens.json \
--name read-only-client \
--devices fw-example \
--tools list_devices,gather_device_facts,execute_panos_op,get_panos_config
cargo run --locked --release -- \
--device-mapping /etc/rust-panosmcp/devices.json \
--transport streamable-http \
--host 0.0.0.0 --port 30031 \
--tokens-file /etc/rust-panosmcp/tokens.json \
--tls-cert /etc/rust-panosmcp/server.crt \
--tls-key /etc/rust-panosmcp/server.key \
--allowed-host mcp.example.net \
--allowed-origin https://client.example.net
Надёжно сохраните stdout первой команды: новый bearer-секрет отображается только один раз. Информацию о ротации токенов, перезагрузке, правилах отказа, развёртывании за обратным прокси и настройках безопасности по умолчанию см. в docs/PHASE2_OPERATIONS.md. Сведения об инвентаризации и настройках TLS межсетевого экрана для Phase 1 приведены в docs/PHASE1_OPERATIONS.md.
Далее: Изучите рабочий процесс ролей reader, writer и reviewer в MCP.
Статус
В Phase 1 реализованы проверенный список устройств и поставщики секретов, строгая проверка HTTPS с системными корневыми сертификатами, пользовательским CA или точным закреплением сертификата узла, асинхронные вызовы PAN-OS XML API с пулом соединений, типизированные ошибки, тайм-ауты, отмена запросов, ограничения объёма вывода и семафор для каждого устройства.
В Phase 2 добавлены bearer-токены, в которых хранятся только дайджесты, точные области действия для устройств и инструментов, атомарная перезагрузка списка устройств и токенов, TLS Streamable HTTP, проверка Host/Origin, ограничения размера тела запроса, лимиты частоты запросов по IP и токену, а также трассировка запросов, безопасная для аудита. Оба транспорта используют одни и те же 27 инструментов, описанных ниже в справочнике инструментов MCP. Область действия токена * даёт доступ только к 16 инструментам для чтения (list_devices, gather_device_facts, execute_panos_op, get_panos_config, list_panos_entries, get_panos_entry_digest, list_panorama_device_groups, list_panorama_templates, get_panorama_push_status, list_panos_rulebase_entries, get_panos_ha_state, get_panos_license_info, get_panos_content_status, get_panos_software_status, test_panos_security_policy_match, query_panos_logs); для 11 инструментов управления жизненным циклом и изменения конфигурации необходимо явно указать их названия.
В Phase 3 добавлены включаемые по желанию отпечатки candidate-конфигурации, строгая политика XPath, блокировки конфигурации PAN-OS, последовательная обработка запросов для каждого устройства, применение изменений, просмотр различий и полная проверка, частичный откат с областью действия администратора, согласование заданий и структурированный аудит изменений. Для инструментов записи требуются явно заданные области действия токена; * по-прежнему предоставляет доступ только для чтения.
В Phase 4 добавлены distroless-образ с закреплённым дайджестом и запуском от непривилегированного пользователя, защищённый модуль systemd, рекомендации по развёртыванию с доступом только для чтения, матрица семейств выпусков PAN-OS, пять целей для фаззинга парсеров, побайтно воспроизводимые архивы, документация по безопасности и эксплуатации, а также опубликованные результаты измерений для Rust и Python.
В v0.2 добавлены сохраняемые наборы изменений из нескольких действий, разрешения на XPath и действия с привязкой к токену и сроком действия, сериализация по канонической конечной точке и независимое подтверждение, привязанное к точным владельцу, устройству, отпечатку и дайджесту действий. Подтверждённые наборы применяются под одной блокировкой конфигурации PAN-OS. Если последующее действие завершается ошибкой, изменения автоматически откатываются от имени администратора. Далее используется существующий жизненный цикл: просмотр различий, полная проверка, фиксация или отмена. См. docs/V0.2_CHANGE_SETS.md.
В v0.2.1 снятие блокировки конфигурации PAN-OS стало подтверждаемым переходом состояния: записи о фиксации или отмене сбрасывают config_lock_held только после того, как устройство подтвердит снятие блокировки. Если снять блокировку не удалось, это состояние сохраняется как indeterminate и требует явного согласования. Также в docs/V0.2.1_ACCEPTANCE.md зафиксированы результаты проверки TLS с настройками доверия по умолчанию и развёртывания в лабораторной среде.
В v0.2.2 обновлены поддерживаемый граф зависимостей Rust и GitHub Actions; при этом интерфейсы инструментов PAN-OS, авторизации, списка устройств и состояний изменения конфигурации из v0.2.1 сохранены. Опубликованный выпуск и результаты контролируемого развёртывания в лабораторной среде приведены в docs/V0.2.2_ACCEPTANCE.md. Поддержка multi-vsys, HA и Panorama пока отложена.
В v0.3.0 аутентификация переведена на общий crate mecmcp-auth. Собственные реализации токенов, хранилища и файлов токенов в этом репозитории заменены общим crate, тестируемым отдельно. Набор инструментов PAN-OS, области авторизации, список устройств и интерфейсы состояний изменения конфигурации не изменились. Изменились два аспекта, важные для операторов: файл tokens.json должен иметь права доступа 0600, иначе сервер откажется запускаться; версия конверта на диске теперь сохраняется при записи, поэтому файл, затронутый этим выпуском, останется читаемым для предыдущего выпуска. Инструкции по обновлению см. в CHANGELOG.md.
Полностью пройдены тесты приёмки для HTTPS-заглушки, сквозных сценариев MCP и межсетевого экрана panosvm в лабораторной среде, настроенной явно. Phase 1 завершён; воспроизводимые результаты приведены в docs/PHASE1_ACCEPTANCE.md.
Результаты приёмки Phase 2 приведены в docs/PHASE2_ACCEPTANCE.md. Результаты приёмки изменений конфигурации — в docs/PHASE3_ACCEPTANCE.md, требования к эксплуатации — в docs/PHASE3_OPERATIONS.md.
Результаты приёмки выпуска Phase 4 приведены в docs/PHASE4_ACCEPTANCE.md. Развёртывание в production-среде, ротация, резервное копирование и восстановление, а также обновления описаны в docs/OPERATIONS.md. См. также docs/COMPATIBILITY.md, docs/BENCHMARKS.md и SECURITY.md. Рекомендации по созданию учётных записей администраторов PAN-OS с минимально необходимыми привилегиями (они отличаются от описанных выше bearer-ролей MCP) см. в docs/PANOS_ADMIN_ROLES.md.
Справочник по инструментам MCP
Сервер предоставляет 27 инструментов MCP, сгруппированных по типу операций:
Инструменты только для чтения
-
list_devices— Возвращает список устройств PAN-OS, доступных авторизованному пользователю, и безопасные метаданные; никогда не выдаёт ключи API. -
gather_device_facts— Получает с авторизованного устройства имя хоста, модель, серийный номер, версию, IP-адрес управления и время работы. -
execute_panos_op— Выполняет на авторизованном устройстве команду PAN-OS XML только для чтения с корневым элементом ``; объём вывода ограничен. -
get_panos_config— Читает running- или candidate-конфигурацию PAN-OS по проверенному XPath/configна авторизованном устройстве. -
list_panos_entries— Постранично получает дочерние элементы `` контейнера со списком правил или объектов в виде структурированного JSON. Если rulebase слишком велик, результат помечается как усечённый, а не возвращается ошибка. -
get_panos_entry_digest— Получает запись конфигурации PAN-OS по указанному XPath и вычисляет её хеш; инструмент предназначен для выявления изменений отдельного правила. -
list_panorama_device_groups— Возвращает список групп устройств Panorama и серийные номера входящих в них межсетевых экранов. -
list_panorama_templates— Возвращает список шаблонов Panorama и имена объявленных в них переменных. -
get_panorama_push_status— Получает общий статус задания commit-all/push в Panorama и статус для каждого целевого межсетевого экрана по идентификатору задания. -
list_panos_rulebase_entries— Возвращает правила безопасности, правила NAT, адресные объекты или объекты служб для vsys в виде структурированного JSON с постраничной выдачей и отметкой об усечении. -
get_panos_ha_state— Получает на авторизованном устройстве состояние высокой доступности PAN-OS: включена ли она, режим, состояние локального узла и партнёра. -
get_panos_license_info— Получает на авторизованном устройстве сведения о лицензиях PAN-OS: функцию, серийный номер, дату выдачи, срок действия и статус истечения. -
get_panos_content_status— Получает на авторизованном устройстве сведения о версии контента PAN-OS: версию, дату выпуска, статус загрузки и актуальность. -
get_panos_software_status— Получает на авторизованном устройстве сведения о версии программного обеспечения PAN-OS: версию, дату выпуска, статус загрузки, актуальность и наличие более новой версии. -
test_panos_security_policy_match— Проверяет, какому правилу безопасности PAN-OS будет соответствовать смоделированный пакет, если такое правило найдётся, на авторизованном устройстве. -
query_panos_logs— Получает за ограниченный период журналы PAN-OS: traffic, threat, system или config. Результат всегда ограничен по объёму.
Инструменты жизненного цикла candidate-конфигурации (изменение конфигурации)
-
get_candidate_fingerprint— Возвращает отпечаток SHA-256 для всех поддеревьев candidate-конфигурации, разрешённых оператору. -
stage_panos_config— Добавляет в candidate-конфигурацию PAN-OS одно изменение: set или delete, ограниченное политикой и проверяемое по ожидаемому отпечатку. -
diff_panos_candidate— Возвращает ограниченную сводку изменений PAN-OS для candidate-конфигурации с указанным отпечатком. -
validate_panos_candidate— Проверяет подготовленную candidate-конфигурацию и разрешает фиксацию только для той же конфигурации с тем же отпечатком. -
commit_panos_candidate— Фиксирует только успешно проверенную операцию с точным отпечатком candidate-конфигурации. -
discard_panos_candidate— Отменяет подготовленную операцию с помощью частичного отката candidate-конфигурации с областью действия администратора. -
get_panos_operation— Возвращает безопасный статус принадлежащей пользователю операции жизненного цикла candidate-конфигурации PAN-OS.
Инструменты для наборов изменений (v0.2+)
-
create_panos_change_set— Планирует и сохраняет от 1 до 64 упорядоченных действий над candidate-конфигурацией PAN-OS с учётом списка устройств и областей XPath/действий, разрешённых для токена. -
approve_panos_change_set— Подтверждает точный дайджест набора изменений, если срок его действия не истёк; подтверждение собственного набора запрещено. -
get_panos_change_set— Возвращает точные действия, дайджест, подтверждение, срок действия и состояние операции для проверки или восстановления. -
apply_panos_change_set— Применяет независимо подтверждённый набор изменений с одной блокировкой конечной точки и конфигурации; при частичной ошибке выполняется откат.
Для инструментов записи требуются явно заданные области действия токена; разрешения * по-прежнему предоставляют доступ только для чтения.
Configuration
Три примера файлов в config/ демонстрируют доступные параметры конфигурации:
-
devices.example.json — перечень устройств с настройками аутентификации, режимами проверки TLS (системные корневые сертификаты, пользовательский CA или точное закрепление конечного сертификата), ограничениями параллельных операций для каждого устройства и необязательным переопределением администратора для операций с кандидатами.
-
tokens.example.json — структура хранилища токенов Bearer: хранение только дайджестов, списки разрешённых устройств и инструментов для каждого токена, необязательные разрешения на изменение (корни XPath, допустимые действия) и временные метки истечения срока действия.
-
devices.mutation.example.json — вариант перечня устройств с примерами настройки корней для изменений и полей рабочего процесса кандидатов, доступных администратору.
В файлах перечня устройств учётные данные не хранятся напрямую: api_key каждого устройства содержит ссылку — {"type": "env", "name": "VAR_NAME"} для переменной среды или {"type": "file", "path": "/protected/path"} для секретного файла с ограниченными правами доступа.
Политика команд (execute_panos_op, test_panos_security_policy_match)
Параметр верхнего уровня policy в файле перечня устройств определяет, какие операционные команды будет выполнять execute_panos_op. То же правило применяется к команде ``, которую формирует сервер и выполняет test_panos_security_policy_match:
mode: "allowlist"(запрет при отсутствии явного разрешения; режим по умолчанию) — команда отклоняется, если не соответствует записи вallow(или вallowed_pipes, если вывод передаётся по каналу).
Именно к этому режиму приводится новый файл перечня устройств и файл без раздела policy. В config/devices.example.json приведён начальный набор команд только для чтения:
"policy": {
"mode": "allowlist",
"allow": [
"show system info",
"show interface all",
"show routing route",
"show running security-policy",
"show session info",
"test security-policy-match"
]
}
Записи списка разрешённых команд сопоставляются с точными путями тегов элементов из XML-структуры самой команды, а не с текстом CLI. Сокращения не раскрываются: например, сокращённая команда sh sys info будет отклонена так же, как и любая другая команда, которой нет в allow. Для выполнения test_panos_security_policy_match в режиме allowlist обязательна запись test security-policy-match. Без неё каждый вызов будет отклонён независимо от остальных настроек.
mode: "blocklist"(разрешение по умолчанию при отсутствии запрета; устаревший режим) — разрешены все команды, кроме тех, что соответствуют правилу запрета вblocklist.commandsустройства. Для обратной совместимости файл перечня устройств с правилами запрета, но без явного ключаpolicy.mode, загружается в этом режиме. При запуске сервер выводит одно предупреждение WARN, поскольку в режимеblocklistс разрешением по умолчанию нет списка разрешённых команд, который мог бы подстраховать при отсутствии подходящего правила.
Для новых развёртываний следует указывать mode: "allowlist".
Каждое устройство может расширить общие списки policy.allow и policy.allowed_pipes, добавив собственные записи в массивы blocklist.allow и blocklist.allowed_pipes. Они объединяются так же, как сейчас объединяются правила запрета blocklist.commands.
При любом отклонении команды — в обоих режимах — в журнал аудита записывается причина, указанная базовой библиотекой политики.
Журнал аудита
В версии v0.4.0 добавлено структурированное журналирование аудита с помощью общей библиотеки mecmcp-audit. Для каждого вызова инструмента создаётся одно событие с указанием вызывающей стороны, целевых устройств, результата и продолжительности выполнения.
Аудит жизненного цикла набора изменений предоставляет отдельное подтверждение согласования: событие approve_panos_change_set содержит идентификатор набора изменений и дайджест его отпечатка. Это подтверждает, что другой субъект проверил именно тот дайджест, который позднее был применён через apply_panos_change_set.
Параметры аудита
-
--audit-format {text|json}— формат событий:text(по умолчанию, для чтения человеком) илиjson(для машинного разбора). -
--audit-log-file— записывать события аудита в файл. -
--audit-journald— отправлять события аудита в журнал systemd. -
--audit-redact— заменять указанные поля (имена устройств, идентификаторы вызывающей стороны) псевдонимами на основе HMAC, чтобы передавать журнал в SIEM без раскрытия операционных идентификаторов. -
--audit-hmac-key-file— путь к ключу HMAC для редактирования данных; обязателен, если включён--audit-redact.
Все способы назначения аудита необязательны и могут использоваться одновременно. Если способ назначения не указан, события аудита не создаются.
Передача в хранилище событий
Журнал аудита не должен оставаться на этом хосте. Этот сервер следует общему для семейства продуктов стандарту — AUDIT-FORWARDING-STANDARD.md.
Запись аудита, существующая только на машине, где она была создана, — это не журнал аудита, а файл на компьютере, оператор которого может быть тем, о ком эта запись составлена.
Формирование записей (реализовано сейчас)
--audit-format json \
--audit-log-file /var/lib/rust-panosmcp/audit.jsonl
Формат JSON обязателен. Формат text предназначен для чтения в терминале и не подходит для машинного разбора. Файл — это артефакт, предназначенный для оператора; его необходимо ротировать, поскольку сервер никогда не очищает его содержимое.
Передача данных (описана, но пока не реализована)
Записи напрямую добавляются в ssdf.audit в виде строк с хеш-цепочкой согласно объединённому контракту SSDF для доказательных данных. Благодаря этому можно обнаружить удаление или изменение строки. Работа отслеживается в mecmcp#292.
Более простой вариант передачи через syslog был разработан, но отклонён: он работоспособен, однако записи в нём не связаны хеш-цепочкой. Все остальные звенья этой схемы изначально защищены от незаметного изменения: дайджесты плана связывают согласования, согласования указывают отдельного субъекта, а token_verified_fields отделяет подтверждённые данные о происхождении от заявленных. Незащищённый последний этап лишил бы систему этой гарантии именно там, где она необходима аудитору. Обоснование зафиксировано в стандарте.
Интерпретация результатов
token_verified_fields указывает поля происхождения данных, достоверность которых подтверждена токеном.
Остальные поля этой группы — client_name, model_id, session_id — заявлены клиентом и ничем не аутентифицированы. Не считайте их равноценными подтверждённым полям.
request_id связывает событие транспортного уровня, событие обработчика и (в Junos) комментарий к фиксации на устройстве.
Безопасность
Полную информацию см. в документах THREAT_MODEL.md и SECURITY.md. Основные положения:
-
Для HTTP обязательна аутентификация — используются токены Bearer, хранение которых ограничено дайджестами SHA-256; секреты в открытом виде не сохраняются.
-
По умолчанию доступны только loopback-интерфейсы — для HTTP за пределами loopback требуется TLS или явный параметр
--allow-insecure-bind; для TLS за пределами loopback требуется--allowed-host. -
Проверка TLS всегда включена — используются системные корневые сертификаты, пользовательский пакет CA или точное закрепление конечного сертификата; доверие при первом использовании и отключение проверки не поддерживаются.
-
Ограниченный ввод-вывод — ограничение размера вывода (512 KiB по умолчанию, максимум 5 MiB), ограничение размера тела запроса (1 MiB по умолчанию), тайм-ауты для всех вызовов PAN-OS.
-
Изменения проходят аудит — операции с кандидатами выполняются последовательно для каждого устройства, фиксируют субъекта и отпечаток, требуют явной фиксации после проверки и сохраняют состояние блокировок и заданий для последующего восстановления.
Справочник CLI
Проверенный JSON-файл инвентаризации устройств [по умолчанию: devices.json]
-t, --transport
Транспорт MCP [по умолчанию: stdio] [допустимые значения: stdio, streamable-http]
-H, --host
Числовой адрес привязки для Streamable HTTP [по умолчанию: 127.0.0.1]
-p, --port
TCP-порт для Streamable HTTP [по умолчанию: 30031]
--tokens-file
Абсолютный путь к файлу токенов-носителей, содержащему только дайджесты
--state-file
Абсолютный путь к закрытому JSON-файлу для хранения состояния наборов изменений и операций
--lab-mode
Запустить без контроля двух лиц: наборы изменений одобряются при создании
--approval-timeout-secs
Срок действия одобрения набора изменений в секундах [по умолчанию: 900]
--allow-plane-owned-writes
Разрешить деструктивные операции на устройствах под управлением управляющей плоскости
--allow-direct-commit
Разрешить фиксировать операцию без одобрения набора изменений
--tls-cert
Абсолютный путь к сертификату в формате PEM; требуется --tls-key
--tls-key
Абсолютный путь к закрытому ключу в формате PEM; требуется --tls-cert
--allow-no-auth
Отключить аутентификацию по токену-носителю для локального интерфейса loopback, используемого только при разработке
--allow-insecure-bind
Разрешить незашифрованное подключение не через loopback за доверенным TLS-прокси
--allowed-host
Дополнительное допустимое значение HTTP Host. Для нескольких значений указывайте параметр повторно
--allowed-origin
Допустимый URL источника браузера. Для нескольких значений указывайте параметр повторно
--ip-rate-per-minute
Максимальное число запросов от одного IP-адреса за скользящую минуту [по умолчанию: 120]
--token-rate-per-minute
Максимальное число запросов от одного аутентифицированного токена за скользящую минуту [по умолчанию: 240]
--request-body-limit
Максимальный размер тела запроса Streamable HTTP в байтах [по умолчанию: 1048576]
--max-inflight-requests
Максимальное число одновременных запросов в обработке от всех клиентов. 0 = без ограничений [по умолчанию: 64]
--max-inflight-requests-per-token
Максимальное число одновременных запросов в обработке для одного токена-носителя. 0 = без ограничений [по умолчанию: 16]
--max-inflight-requests-per-target
Максимальное число одновременных запросов в обработке для одного целевого устройства. 0 = без ограничений [по умолчанию: 4]
--max-sessions
Максимальное число одновременных сессий MCP. 0 = без ограничений [по умолчанию: 128]
--max-sessions-per-token
Максимальное число одновременных сессий MCP для одного токена-носителя. 0 = без ограничений [по умолчанию: 16]
--enable-metrics
Публиковать метрики Prometheus без аутентификации по адресу /metrics (только для streamable-http)
--audit-format
Формат журнала аудита: text или json [по умолчанию: text]
--audit-log-file
Необязательный путь к отдельному JSON-файлу журнала аудита
--audit-journald
Включить приёмник аудита journald для событий с target="audit"
--audit-redact
Необязательная политика маскирования отдельных полей (например, devices=hmac,host=drop)
--audit-hmac-key-file
Файл ключа HMAC для маскирования данных аудита (обязателен, если в audit-redact запрошен hmac)
--ssdf-audit-endpoint
Конечная точка ClickHouse для приёмника данных SSDF. Включает конвейер
--ssdf-audit-server-id
Идентификатор цепочки для этого средства записи. Обязателен, если задана конечная точка
--ssdf-audit-database
База данных ClickHouse с таблицей аудита [по умолчанию: ssdf]
--ssdf-audit-user
Учётная запись только для записи INSERT [по умолчанию: ssdf_audit]
--ssdf-audit-password-file
Файл с паролем учётной записи для записи. Права доступа должны быть 0600
--ssdf-audit-verify-user
Учётная запись только для чтения SELECT, используемая для чтения верхней границы и хвостовых записей [по умолчанию: ssdf_audit_verify]
--ssdf-audit-verify-password-file
Файл с паролем учётной записи для чтения. Права доступа должны быть 0600
--ssdf-audit-ca-file
Сертификат центра сертификации в формате PEM для проверки сертификата ClickHouse. Обязателен для https://
--ssdf-audit-outbox
Надёжная очередь исходящих данных для закрытых сегментов. Обязательна, если задана конечная точка
--ssdf-audit-ledger
Журнал доставки. Обязателен, если задана конечная точка
--ssdf-audit-interval-secs
Интервал между попытками доставки в секундах. Должен быть положительным [по умолчанию: 30]
--ssdf-audit-records-per-segment
Число записей в сегменте до его закрытия и помещения в очередь [по умолчанию: 64]
-h, --help
Показать справку (подробности — с помощью '--help')
-V, --version
Показать версию
Подкоманды Token: add Создать токен, сохранить только его дайджест и однократно вывести секрет list Показать имена токенов и области действия без секретов и дайджестов revoke Отозвать токен по имени rotate Заменить секрет токена, сохранив его области действия set-scopes Заменить области действия или права на изменение токена, сохранив его секрет
Подкоманды State: resolve Пометить операцию с неопределённым результатом как завершённую после ручной сверки с PAN-OS">
Secure, async MCP server for PAN-OS firewalls
Usage: rust-panosmcp [OPTIONS] [COMMAND]
Commands:
token Manage the digest-only bearer-token store
state Perform offline recovery on the private mutation-state file
help Print this message or the help of the given subcommand(s)
Options:
-f, --device-mapping <DEVICE_MAPPING>
Проверенный JSON-инвентарь устройств [по умолчанию: devices.json]
-t, --transport <TRANSPORT>
Транспорт MCP [по умолчанию: stdio] [допустимые значения: stdio, streamable-http]
-H, --host <HOST>
Числовой адрес привязки для Streamable HTTP [по умолчанию: 127.0.0.1]
-p, --port <PORT>
TCP-порт для Streamable HTTP [по умолчанию: 30031]
--tokens-file <TOKENS_FILE>
Абсолютный путь к файлу токенов Bearer, содержащему только дайджесты
--state-file <STATE_FILE>
Абсолютный путь к закрытому JSON-файлу для постоянного хранения наборов изменений и состояния операций
--lab-mode
Запуск без контроля по принципу двух лиц: наборы изменений утверждаются при создании
--approval-timeout-secs <APPROVAL_TIMEOUT_SECS>
Время действия утверждения набора изменений в секундах [по умолчанию: 900]
--allow-plane-owned-writes
Разрешить деструктивные операции на устройствах, принадлежащих плоскости управления
--allow-direct-commit
Разрешить фиксацию операции без утверждения набора изменений
--tls-cert <TLS_CERT>
Абсолютный путь к сертификату PEM; требует `--tls-key`
--tls-key <TLS_KEY>
Абсолютный путь к закрытому ключу PEM; требует `--tls-cert`
--allow-no-auth
Отключить Bearer-аутентификацию для локального интерфейса разработки
--allow-insecure-bind
Разрешить незашифрованное подключение не к loopback-интерфейсу за доверенным TLS-прокси
--allowed-host <ALLOWED_HOST>
Дополнительное допустимое значение HTTP Host. Для нескольких значений укажите параметр повторно
--allowed-origin <ALLOWED_ORIGIN>
Допустимый URL источника браузера. Для нескольких значений укажите параметр повторно
--ip-rate-per-minute <IP_RATE_PER_MINUTE>
Допустимое число запросов от одного исходного IP-адреса за скользящий минутный интервал [по умолчанию: 120]
--token-rate-per-minute <TOKEN_RATE_PER_MINUTE>
Допустимое число запросов на один аутентифицированный токен за скользящий минутный интервал [по умолчанию: 240]
--request-body-limit <REQUEST_BODY_LIMIT>
Максимальный размер тела запроса Streamable HTTP в байтах [по умолчанию: 1048576]
--max-inflight-requests <MAX_INFLIGHT_REQUESTS>
Максимальное число одновременно обрабатываемых запросов от всех вызывающих сторон. 0 = без ограничений [по умолчанию: 64]
--max-inflight-requests-per-token <MAX_INFLIGHT_REQUESTS_PER_TOKEN>
Максимальное число одновременно обрабатываемых запросов на один токен Bearer. 0 = без ограничений [по умолчанию: 16]
--max-inflight-requests-per-target <MAX_INFLIGHT_REQUESTS_PER_TARGET>
Максимальное число одновременно обрабатываемых запросов на целевое устройство. 0 = без ограничений [по умолчанию: 4]
--max-sessions <MAX_SESSIONS>
Максимальное число одновременных сеансов MCP. 0 = без ограничений [по умолчанию: 128]
--max-sessions-per-token <MAX_SESSIONS_PER_TOKEN>
Максимальное число одновременных сеансов MCP на один токен Bearer. 0 = без ограничений [по умолчанию: 16]
--enable-metrics
Открыть доступ к метрикам Prometheus без аутентификации по адресу /metrics (только для streamable-http)
--audit-format <AUDIT_FORMAT>
Формат журнала аудита: `text` или `json` [по умолчанию: text]
--audit-log-file <AUDIT_LOG_FILE>
Необязательный путь к отдельному файлу журнала аудита в формате JSON
--audit-journald
Включить приём аудиторских событий journald с `target="audit"`
--audit-redact <AUDIT_REDACT>
Необязательная политика маскирования отдельных полей (например, `devices=hmac,host=drop`)
--audit-hmac-key-file <AUDIT_HMAC_KEY_FILE>
Файл ключа HMAC для маскирования аудита (обязателен, если в audit-redact запрошен hmac)
--ssdf-audit-endpoint <SSDF_AUDIT_ENDPOINT>
Конечная точка ClickHouse для приёмника свидетельств SSDF. Включает конвейер
--ssdf-audit-server-id <SSDF_AUDIT_SERVER_ID>
Идентификатор цепочки для этого средства записи. Обязателен, если указана конечная точка
--ssdf-audit-database <SSDF_AUDIT_DATABASE>
База данных ClickHouse с таблицей аудита [по умолчанию: ssdf]
--ssdf-audit-user <SSDF_AUDIT_USER>
Учётная запись с правами только на INSERT [по умолчанию: ssdf_audit]
--ssdf-audit-password-file <SSDF_AUDIT_PASSWORD_FILE>
Файл с паролем учётной записи для записи. Права доступа должны быть 0600
--ssdf-audit-verify-user <SSDF_AUDIT_VERIFY_USER>
Учётная запись с правами только на SELECT для чтения верхней границы и хвоста [по умолчанию: ssdf_audit_verify]
--ssdf-audit-verify-password-file <SSDF_AUDIT_VERIFY_PASSWORD_FILE>
Файл с паролем учётной записи для чтения. Права доступа должны быть 0600
--ssdf-audit-ca-file <SSDF_AUDIT_CA_FILE>
Корневой сертификат PEM для проверки сертификата ClickHouse. Обязателен для `https://`
--ssdf-audit-outbox <SSDF_AUDIT_OUTBOX>
Надёжная очередь исходящих данных для закрытых сегментов. Обязательна, если указана конечная точка
--ssdf-audit-ledger <SSDF_AUDIT_LEDGER>
Журнал доставки. Обязателен, если указана конечная точка
--ssdf-audit-interval-secs <SSDF_AUDIT_INTERVAL_SECS>
Интервал между попытками доставки в секундах. Должен быть положительным числом [по умолчанию: 30]
--ssdf-audit-records-per-segment <SSDF_AUDIT_RECORDS_PER_SEGMENT>
Число записей в сегменте, после которого сегмент закрывается и помещается в очередь [по умолчанию: 64]
-h, --help
Показать справку (подробности: '--help')
-V, --version
Показать версию
Подкоманды для токенов:
add Создать токен, сохранить только его дайджест и однократно вывести секрет
list Показать имена токенов и области действия без секретов и дайджестов
revoke Отозвать токен с указанным именем
rotate Заменить секрет токена, сохранив его области действия
set-scopes Заменить области действия или разрешения на изменение, сохранив секрет токена
Подкоманды для состояния:
resolve Пометить неопределённую операцию как завершённую после ручной сверки PAN-OS
--lab-mode
--lab-mode отменяет требование второго субъекта для лабораторной среды с одним оператором, где контроль по принципу «двух человек» был бы лишь формальностью. По умолчанию режим отключён; его следует оставить отключённым везде, где важна безопасность инфраструктуры.
Что меняется и что остаётся без изменений:
-
Отмена требования применяется автоматически при создании набора изменений. Отдельной команды для отмены нет, а последовательность действий остаётся такой же, как в production: создание → применение.
-
Планирование, дайджест плана, обнаружение отклонений и повторная проверка во время применения выполняются по-прежнему. Lab mode отменяет требование второго проверяющего, но не удаляет запись об изменении.
-
Одобрение никогда не подделывается. В записи набора изменений, созданного с отменой требования, указывается
approver: nullиapproval_waiver: "lab-mode", а также сохраняется дайджест отмены, рассчитанный по(change_set_id, plan_digest, owner, approved_at). Его можно криптографически отличить от настоящего одобрения двумя людьми, и задним числом переименовать его нельзя. Это важно, если впоследствии потребуется подтвердить, какие изменения действительно прошли разделение обязанностей. -
При каждом запуске сервера с включённым режимом выводится заметное предупреждение.
Чтобы тестировать запись в одиночку, не отменяя контроль, создайте два токена с разными именами: одним создайте набор изменений, другим одобрите его. Субъектом считается имя токена, а самоодобрение запрещено. Так один человек сможет пройти весь жизненный цикл изменений, сохранив контроль. Это предпочтительный вариант везде, где формальная процедура имеет значение.
Включение режима
Добавьте флаг в unit сервиса. При установке из пакета используйте drop-in-файл, а не редактируйте поставляемый unit: иначе обновление может незаметно удалить настройку.
sudo systemctl edit rust-panosmcp
При замене ExecStart его нужно указать полностью. Поэтому скопируйте поставляемую команду и добавьте флаг, не сокращая её. Удаление других аргументов может незаметно изменить расположение файла состояния или настройки транспорта:
[Service]
# Перед заменой очистите поставляемый ExecStart: иначе systemd добавит новую команду к существующей.
ExecStart=
ExecStart=/usr/local/bin/rust-panosmcp \
--device-mapping /etc/rust-panosmcp/devices.json \
--transport streamable-http \
--host 127.0.0.1 \
--port 30031 \
--tokens-file /var/lib/rust-panosmcp/tokens.json \
--state-file /var/lib/rust-panosmcp/mutation-state.json \
--lab-mode
Перед применением сверьте команду с packaging/systemd/rust-panosmcp.service: именно поставляемые аргументы являются эталоном, а этот пример может устареть.
sudo systemctl daemon-reload && sudo systemctl restart rust-panosmcp
Убедитесь, что настройка вступила в силу. В текстовом сообщении при запуске используется lab mode, а в описании результата — approval_waiver=lab-mode:
sudo journalctl -u rust-panosmcp --since='5 minutes ago' | grep -i lab
Ожидаемый вывод:
Aug 15 12:34:56 host rust-panosmcp[1234]: 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.
Для токенов утверждающих требуется значение human
approve_panos_change_set принимает только второго субъекта, чей токен помечен как actor_type: human. Токенам, выпущенным без --actor-type, присваивается значение unknown; в качестве утверждающих они не принимаются. Токены типа agent также не подходят. Выпускайте токены утверждающих командой rust-panosmcp token add ... --actor-type human. Сеансы stdio не содержат сведений о вызывающей стороне и не могут использоваться для одобрения; одобрение выполняется через аутентифицированный HTTP.
--allow-direct-commit
Если commit_panos_candidate вызывается для операции, созданной непосредственно через stage_config, а не через create_panos_change_set / approve_panos_change_set / apply_panos_change_set, он выполняет подготовку, проверку и фиксацию в рамках одного жизненного цикла без независимой проверки вторым субъектом: для неё просто нет набора изменений. По умолчанию этот режим отключён: без указанного флага фиксация отклоняется до любого обращения к межсетевому экрану — одинаково для stdio и HTTP. В stdio отсутствует контекст вызывающей стороны, поэтому этот способ не может считаться более доверенным, чем аутентифицированный сеанс.
Остаточный риск. --allow-direct-commit — это обходной путь, а не устранение проблемы. Оператор, включающий этот флаг, принимает решение о том, что для данного развёртывания допустимо выполнять именно этот сценарий без независимой проверки. Это решение:
-
Сопровождается заметным сообщением при запуске, как и в случае с
--lab-mode. -
Фиксируется в журнале при каждом вызове. Для вызова
commit_panos_candidate, выполненного с включённым флагом, в записи аудита указываетсяdirect_commit_allowed=true. Отказ также фиксируется:authorization=deniedиreason=direct_commit_disabled.
Флаг не добавляет проверку вторым субъектом — он лишь делает заметным выполнение операции без такой проверки. По возможности используйте процесс с набором изменений (create_panos_change_set → approve_panos_change_set → apply_panos_change_set), а этот флаг оставьте для операций, которые действительно невозможно выполнить по этой схеме.
Включите флаг так же, как --lab-mode: добавьте --allow-direct-commit в ExecStart unit сервиса через systemd drop-in-файл, полностью скопировав поставляемую команду. Убедитесь, что настройка вступила в силу. В отличие от сообщения о lab mode, это сообщение намеренно не включено в схему аудита с данными по отдельным вызовам, поэтому найдите обычное сообщение при запуске:
sudo journalctl -u rust-panosmcp --since='5 minutes ago' | grep -i "allow-direct-commit is enabled"
Проверка
cargo fmt --all -- --check
cargo clippy --workspace --all-targets --all-features -- -D warnings
cargo test --workspace --locked
cargo check --manifest-path fuzz/Cargo.toml --bins --locked
scripts/verify-packaging.sh
Создайте детерминированный архив релиза с помощью scripts/build-release.sh либо
скомпилируйте проект дважды и проверьте побайтовое совпадение результатов с помощью
scripts/verify-reproducible-build.sh. Инструкции по установке в контейнере и через systemd
приведены в руководстве для операторов.
Лицензия
Лицензия MIT.
проект mechub · детерминированность определяет результат · модель объясняет · человек одобряет