Архитектура AutoGov
July 12, 2026 · View on GitHub
Документ описывает, как реализация соответствует архитектурным решениям ТЗ §4 и почему ядро спроектировано как платформа с плагинами (Требование ТЗ-0).
Поток данных
┌─────────┐ observations ┌───────────┐ events ┌────────────────┐
│ AGENT │ ───────────────▶ │ Ingest API │ ─────────▶ │ Event Bus │
│ (host) │ mTLS/bearer │ (dedup) │ │ (pub/sub) │
└─────────┘ outbound-only └───────────┘ └───────┬────────┘
│ observation.*
┌───────▼────────┐
│ Module Runtime │
│ M1 discovery │
│ M2 honeynodes │ (stub)
│ M3 selfhealing │ (stub)
│ M4 autodoc │ (stub)
└───────┬────────┘
┌───────────────┬────────────────────┬──────┘
▼ ▼ ▼
┌────────────┐ ┌────────────┐ finding.* events
│ Asset Store │ │ Risk Engine│ │
│ (inventory) │ │ (scoring) │ ▼
└────────────┘ └────────────┘ ┌──────────────┐
│ │ Notifier │──▶ SIEM / webhook / email
▼ └──────────────┘
Web UI / Public API (RBAC + аудит)
Ключевые решения (ТЗ §4.2) и их реализация
Разделение «Агент ↔ Control Plane»
Агент (internal/agent) только собирает и нормализует данные; вся аналитика
(скоринг, корреляция, модули) — в control plane. Это даёт лёгкий, аудируемый
агент и позволяет добавлять модули M2–M4 без обновления агента.
Outbound-only агент, mTLS (ТЗ §4.2, §9)
Агент сам инициирует исходящее соединение (agent.ship); он не открывает
портов (нет EXPOSE в Dockerfile.agent). mTLS: клиентский сертификат в
agent.buildClient, проверка цепочки для /ingest в server.checkAgentAuth.
Событийная шина (ТЗ §4.2)
internal/bus — in-process pub/sub с одним детерминированным циклом доставки.
Подписка по шаблону типа события (observation.*, finding.*, точное имя).
Развязывает сбор от анализа и даёт точки расширения: M3 подпишется на
workflow.error, M2 — на honeynode.access.
Плагинная модель (ТЗ-0)
internal/modules.Runtime + интерфейс Module:
type Module interface {
Name() string
Subscriptions() []string
Handle(ctx, ev, *API) error
}
Модуль взаимодействует с платформой только через modules.API
(Store + Bus + Logger + PublishFinding/PublishEvent). Он не имеет доступа к
внутренностям ядра. Это и есть проверяемая граница: если будущему модулю
понадобится менять ядро — контракт нарушен (ТЗ §6). Тест
plugin_test.go показывает, что M2 встаёт на ту же шину/хранилище и выдаёт
находку, ничего не меняя в ядре.
Многосигнальный детект (ТЗ §5.1)
Модуль discovery нормализует наблюдения от разных коллекторов в один и тот
же Instance через детерминированный StableID. Разные коллекторы
накапливаются в Instance.DetectedBy, а store.UpsertInstance объединяет
сигналы (эскалирует exposure, берёт максимум confidence). Так один инстанс,
увиденный и по файловой системе, и по сети, — это один актив с высокой
уверенностью, а случайный контейнер с совпавшим портом (один слабый сигнал) —
отсеивается (см. TestMultiSignalReducesFalsePositives).
Идемпотентность (ТЗ §8.2)
Каждое наблюдение получает ID один раз в момент сбора (collect.NewObservation).
store.MarkEventSeen отбрасывает повторы (буфер дедупликации с обрезкой).
Находки имеют стабильный ID на инстанс — повторный скан обновляет находку
на месте, а не плодит дубли.
Privacy by design (ТЗ §7, §9)
- Модель данных
CredentialRefхранитType/TargetSystem/Fingerprint, но не значение. agent/sanitize.SplitEnvделит env на: имена (метаданные), секреты (имя→SHA-256-отпечаток, значение отброшено) и узкий allowlist несекретной конфигурации (DB_TYPEи т.п.) для целей детекта.sanitize.Scrubвычищает высокоэнтропийные токены из свободных строк (cmdline, cron-команды) перед отправкой.
On-prem egress-guard (ТЗ §8.4)
notify.EgressGuard.Check в режиме onprem (без allow_external_egress)
разрешает только приватные/loopback-адреса. Проверка выполняется при
конструировании notify.Manager — конфиг с внешним syslog/webhook ломает
старт, а не «молча» осуществляет трансграничную передачу.
Хранилище
internal/store — потокобезопасное хранилище со снапшотом state.json
(атомарная запись через temp+rename) и append-only JSONL для аудита и сырых
событий. Без внешней БД: одно-контейнерная установка для on-prem/air-gapped.
Интерфейс узкий — SQL-бэкенд можно подставить позже без изменения модулей.
Что намеренно упрощено в MVP
- Шина — in-process (для масштаба ТЗ §8.1 «до ~10 000 инстансов» достаточно); вынос в внешнюю очередь — точка расширения, контракт не меняется.
- PDF-генератор минимальный (кириллица транслитерируется); машиночитаемый источник истины — JSON-отчёт.
- M2–M4 — заглушки-контракты; полная реализация — Э3–Э4.