server-monitor-manager/docs/security-model.md
Ochenstarik 4de849e3bf docs: add product horizons, approval policies and KAgent integration spec
Adopt the reviewed parts of the external vision document as repository
specifications, and record the work-order gates that keep unimplemented
subsystems from starting before their prerequisites are closed.

- product-horizons.md: four horizons with hard exit criteria; Horizon 0
  closes physical acceptance, signed delivery, the Monitor role and
  certificate rotation before anything new begins.
- approval-policies.md: nine approval modes over the existing binary
  confirmation, mapped onto ProvisioningJob, TTL and execution grants.
- integration-kagent.md: capability model split into read, request and
  never-grantable; untrusted-executor invariant for KAgent Worker;
  SO_PEERCRED on the discovery socket; API designed against entities
  that exist today.
- security-model.md: untrusted executors on a Node, the public web
  surface decision that must be recorded before that work starts, and
  never-grantable capabilities.
- roadmap.md: stages 14-18 for the adopted scope, pinned to horizons.

All three new documents state that nothing in them is implemented.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-06 18:31:09 +07:00

128 lines
13 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# Модель безопасности
## Защищаемые данные
- SSH, WireGuard, device и agent identities;
- topology, внутренние адреса, метрики и состояния Links;
- команды, терминальные сессии и аудит;
- права пользователей и AI-агентов.
## Границы доверия
Windows client, Hub и каждый Node считаются отдельными субъектами. Компрометация одного Node не должна выдавать ключи других узлов или право создавать новые Links.
Hub хранит только публичные WireGuard-ключи Node. Приватный ключ Node генерируется локально, не включается в enrollment token и не записывается на Hub.
## SSH monitoring MVP
Windows-клиент использует отдельный Ed25519-ключ только для forced-command. Этот ключ не используется для интерактивного терминала или AI-агента. Первый host key требует явного подтверждения fingerprint; последующие подключения проверяют сохранённый `known_hosts`.
Приватный ключ клиента защищается Windows DPAPI и доступом текущего пользователя. Профили серверов не содержат паролей.
## Регистрация Node
1. На Hub создаётся случайный enrollment token со сроком жизни не более 10 минут.
2. Node локально генерирует WireGuard-ключ.
3. Node предъявляет token и публичный ключ по защищённому каналу.
4. Hub атомарно помечает token использованным, регистрирует адрес и возвращает подтверждение, которое связывает token, публичный ключ и все параметры конфигурации.
5. Повторное использование, просроченный token и смена публичного ключа отклоняются.
До появления mTLS enrollment выполняется через отдельную ограниченную SSH-команду. Token не должен содержать приватный WireGuard-ключ.
## Operator identity Windows-клиента
Windows-клиент получает отдельный код `SMMDEV1`, показывает URL и SHA-256 fingerprint Control CA и продолжает регистрацию только после явного подтверждения пользователя. Приватный operator key создаётся локально, хранится в DPAPI current-user scope и не используется как SSH monitoring, terminal или Agent identity.
Сертификат `Agent` разрешает только heartbeat собственного `node_id`. Только сертификат с ролью `Operator` может читать общий inventory, изменять Links и подписываться на event stream. Сертификат `Automation` выдаётся по отдельному одноразовому token, привязан к одному source Node и разрешает только чтение его эффективных Link-grants без `reason`, общего inventory и чужих Links. Control service вызывает от root только отдельный wrapper с командами `link-connect` и `link-disconnect`; другие Hub-команды через него запрещены.
При перерегистрации Node Control Hub в одной SQLite-транзакции помечает старый сертификат `Revoked`, погашает ранее выданные enrollment tokens и переводит все связанные Links в желаемое состояние `Disabled`. Только после этого ограниченный firewall wrapper удаляет фактические правила. Новый token живёт 10 минут, а повтор запроса с тем же idempotency key не создаёт второй token и не повторяет firewall-операции. Windows-клиент требует отдельного подтверждения и не публикует token в event stream или аудит.
## Авторизация Links
- мониторинг read-only отделён от управления;
- Link всегда содержит source, destination, CIDR, протокол и порт;
- пустой список портов не означает разрешение всех портов;
- automation identity не наследует интерактивные права владельца;
- команды имеют TTL, nonce/idempotency key и версию политики;
- Hub проверяет имена и параметры повторно, независимо от проверки desktop client.
## Аудит
Записываются регистрация и удаление узла, изменение прав, создание, включение, истечение и отключение Link, а также ошибки применения. Секреты, приватные ключи и полный ввод терминала не журналируются.
Для первого MVP используется append-only JSONL с ограниченными правами и ротацией. После появления control service аудит переносится в SQLite с возможностью внешнего экспорта.
## Kill switch
Отключение Link должно:
1. немедленно удалить разрешающее правило на Hub;
2. записать желаемое состояние `Disabled` до отправки дополнительных команд;
3. запретить автоматическое восстановление после reboot/reconnect долговечным SQLite-marker, который снимается только после подтверждения firewall;
4. получить подтверждение применённой версии политики;
5. показывать `Partial`, если подтверждение одного из узлов отсутствует;
6. сохранить обязательную операцию для временно недоступного Node.
## Provisioning и VPN
Provisioning расширяет существующую модель ролей, но не предоставляет удалённый root shell:
- mutation создаёт только Operator и только для явно выбранного `node_id`;
- Agent получает задания исключительно своего Node;
- Automation identity не управляет ОС, пользователями, firewall или VPN;
- root helper принимает фиксированный action id и JSON строгой versioned schema через локальный Unix socket;
- helper повторно валидирует параметры, использует фиксированный `PATH` и отклоняет shell text, неизвестные поля, произвольные paths и symlinks;
- опасное задание имеет TTL, idempotency key, audit reason, отдельное подтверждение, verification и rollback;
- одновременно на Node не выполняются несовместимые опасные задания;
- неопределённый результат после disconnect получает `NeedsReconciliation`;
- повторная регистрация Node инвалидирует незавершённые опасные задания;
- VPN subscription secret шифруется на публичный ключ конкретного Node, а Control хранит только ciphertext и маскированные metadata;
- локальная emergency recovery может отключить managed VPN и восстановить SSH/firewall без Control Hub, но не запускает произвольную команду.
Подробный контракт приведён в [ТЗ Provisioning и Xray VPN](provisioning-vpn-requirements.md).
## Недоверенные исполнители на Node
Статус: инвариант для будущих модулей, реализация не начата.
Любой компонент, исполняющий на Node внешний код — прежде всего KAgent Worker, — считается недоверенным субъектом и изолируется от control plane, а не только от внешней сети. Сборка репозитория запускает его build-скрипты, поэтому «ограниченный набор возможностей» не означает ограниченного исполнения.
Обязательные условия:
- отдельный системный пользователь без sudo, отдельные каталоги и cgroup;
- нет доступа к сокету provisioning-helper и запрет членства в группе Agent;
- нет доступа к `agent.pfx`, `control-ca.crt`, `agent.env`, состоянию mesh и каталогу rollback;
- нет сетевого доступа к Control API;
- исполнение в контейнере с read-only rootfs, seccomp, AppArmor и сброшенными capabilities;
- системные лимиты дополняют изоляцию, но не заменяют её;
- задачный Link не может иметь destination Hub или другой недоверенный исполнитель.
Компрометация такого исполнителя не должна давать управления Node, доступа к другим Node или возможности создать Link. Подробности: [интеграция с KAgent](integration-kagent.md).
## Публичный интерфейс
Статус: решение не принято, работы не начаты.
Текущая модель держится на трёх утверждениях: у Node нет публичного входящего API, Control доступен только по mTLS, порт Control не открывается без ограничений firewall. Веб-интерфейс с аутентификацией по паролю вводит браузерный surface на Hub и вторую систему идентичности рядом с сертификатами устройств.
До начала работ над веб-интерфейсом требуется зафиксировать здесь:
- отдельный listener и порт, отношение к цепочке сертификатов Control;
- как веб-сессии соотносятся с mTLS-идентичностями в модели ролей;
- перечень операций, недоступных веб-сессии в принципе и требующих mTLS-идентичности — как минимум изменение firewall, ротация CA, удаление Node и экспорт секретов;
- привязка сессии к устройству, защита от CSRF, ограничение частоты и повторная аутентификация для операций повышенного риска.
## Невыдаваемые возможности
Часть возможностей не является настройкой и не может быть выдана никакой внешней идентичности: исполнение произвольных команд от root, ротация Control CA, чтение содержимого секретов, отключение аудита, удаление Node. Требование означает отсутствие соответствующего кода в пути внешней идентичности, а не значение по умолчанию.
Прецедент: сертификат `Automation` физически не может изменять Links. Та же строгость распространяется на все последующие внешние интеграции.
## Не входит в первый MVP
- выполнение произвольных root-команд;
- хранение пользовательских приватных SSH-ключей на Hub;
- автоматическое объединение всех серверов в flat network;
- публичный входящий API на Node;
- собственная криптография вместо SSH, TLS и WireGuard;
- автоматический failover между несколькими Hub.