ДокументацияИнженерия контента9. Сквозной разбор — подключение «Acme SIEM»

Сквозной разбор — подключение «Acme SIEM»

Почему это важно. Предыдущие главы покрывали каждый этап изолированно. Эта глава соединяет их в единую сборку: вымышленный SIEM под названием Acme SIEM проходит от «не подключён» до рабочего экрана кейса и запущенного плейбука, используя только механизмы, которые существуют в продукте. Каждое имя экрана, кнопки и поля ниже — реальное. Пройдите её один раз против собственного тестового источника, и конвейер перестаёт быть абстрактным.

Сборка следует порядку из главы 1 §1.5: коннектор → образец данных → типы инцидентов → классификатор → кастомное поле → маппер → layout → плейбук → проверка.

9.1. Цель и пример алерта

Acme SIEM поднимает алерты аутентификации. Мы хотим два исхода:

  • Алерт brute-force становится кейсом типа Brute Force Login.
  • Алерт authentication-anomaly становится кейсом типа Authentication Anomaly.

В обоих экран кейса должен показать имя алерта, severity, когда он произошёл, внешнюю ссылку, нормализованную MITRE Technique и дедуплицированный список Tags; а на создании должен отработать небольшой плейбук.

Вот репрезентативный фид Acme SIEM — JSON-массив из двух событий (второе отличается в основном по category), с полями на верхнем уровне и именованными в стиле SIEM (sourceip, а не source.ip):

[
  {
    "alertid": "ACME-2026-004417",
    "alertname": "Multiple failed logons then success",
    "category": "brute_force",
    "severity": "high",
    "sourceip": "203.0.113.44",
    "destinationip": "10.12.4.7",
    "hostname": "FIN-WKS-118",
    "username": "j.okafor",
    "useremail": "j.okafor@acme.example",
    "eventcount": 42,
    "mitretechnique": "  t1110  ",
    "tags": ["auth", "", "brute-force", "auth"],
    "detectedtime": "2026-07-17T09:14:22Z"
  },
  {
    "alertid": "ACME-2026-004418",
    "alertname": "Impossible-travel sign-in",
    "category": "auth_anomaly",
    "severity": "medium",
    "sourceip": "198.51.100.9",
    "destinationip": "10.12.4.7",
    "hostname": "FIN-WKS-204",
    "username": "s.haddad",
    "useremail": "s.haddad@acme.example",
    "eventcount": 1,
    "mitretechnique": "  t1078  ",
    "tags": ["auth", "anomaly", "anomaly"],
    "detectedtime": "2026-07-17T09:20:05Z"
  }
]

Две детали намеренны: mitretechnique имеет окружающие пробелы и нижний регистр (мы почистим его цепочкой трансформеров), а tags содержит пустую строку и дубликат (мы почистим его фильтром).

9.2. Шаг 1 — создание коннектора и инстанса

Маршрут: /settings/connectors · Права: connectors.view, connectors.manage

  1. Откройте Settings → Integrations → Connectors.
  2. В левом списке коннекторов кликните New Integration. В редакторе коннектора задайте Name = Acme SIEM, Type = SIEM, Source Key = acme_siem и добавьте поля схемы, которые нужны источнику (для REST-источника: URL API и ключ API). Сохраните коннектор.
  3. Выберите Acme SIEM в списке; редактор инстанса откроется справа. Создайте инстанс:
    • Instance NameAcme SOC.
    • Source Instance Keyacme-soc (без пробелов; это как алерты привязываются к этому инстансу).
    • Заполните секции схемы коннектора. Поля сгруппированы в Connect (учётные данные / URL), Collect (что тянуть), Runtime & network (прокси, таймаут, сертификат) и General.
    • Задайте Source Reliability, если используете threat-скоринг (по умолчанию B).
    • Кликните Advanced Settings, чтобы раскрыть Fetch interval, Active, Use by default и Auto enrichment. Включите Active. Если Acme SIEM будет опрашиваться, также включите fetch и задайте Fetch interval; если он будет проталкивать в /ingest, оставьте fetch выключенным.
  4. Кликните Test, чтобы проверить подключение (реальные коннекторы возвращают модальное окно статуса), затем Save (или Save & Exit).

Две входные двери. Инстанс с включённым fetch тянет алерты по своему интервалу; источник без цикла fetch может проталкивать в POST /api/v1/ingest (§9.10). В любом случае алерт входит в тот же конвейер ingest, и применяются классификатор и маппер этого инстанса.

9.3. Шаг 2 — загрузка примера алерта в конструктор классификатора

Маршрут: /admin/incident-types · Права: incident_types.view, incident_types.manage

Вам нужны реальные имена полей, прежде чем классифицировать или маппить, так что сначала загрузите образец.

  1. В области Collect редактора инстанса кликните New Classifier (это открывает конструктор классификатора для этого инстанса). Вы также можете дойти до него из Objects Setup → Incident Types → classifier.
  2. Наверху конструктора подтвердите Connector: Acme SIEM и Instance: Acme SOC.
  3. В Get data: выберите, как загрузить события:
    • Pull from instance — забрать живые события (затем Pull).
    • Generate sample — синтезировать события из формы коннектора.
    • Paste JSON — кликните Load, и в диалоге Paste Sample Events вставьте массив из §9.1, затем Load.
  4. Левая панель заполняется загруженными событиями (используйте стрелки ◀ ▶, чтобы пролистывать их), а центральная панель показывает JSON-дерево события. Теперь у вас есть конкретные имена полей для работы.

9.4. Шаг 3 — создание двух типов инцидентов

Маршрут: /admin/incident-types?tab=classification&classificationTab=objects

Классификатор может маршрутизировать только к существующим типам инцидентов, так что создайте их сейчас.

  1. Откройте библиотеку объектов (Back to Classification & Mapping из классификатора, затем представление objectsIncidents).
  2. Кликните New Incident Type, задайте отображаемое имя Brute Force Login, сохраните.
  3. Повторите для Authentication Anomaly.

9.5. Шаг 4 — построение правил классификации

Обратно в конструкторе классификатора (Objects Setup → Incident Types → classifier):

  1. Дайте классификатору имя (напр. Acme SIEM classifier) в поле имени.
  2. В центральной панели — «Select the field that identifies the incident type» — задайте поле классификатора. Кликните category в JSON-дереве или наберите путь напрямую. SOARForge собирает отдельные значения этого поля по загруженным событиям: здесь brute_force и auth_anomaly.
  3. Правая панель перечисляет ваши типы инцидентов под Incident Types. Перетащите значение brute_force на Brute Force Login, а auth_anomaly на Authentication Anomaly (каждый тип показывает зону Drop values here). Значение, оставленное несопоставленным, остаётся неклассифицированным.
  4. Задайте fallback: в Direct unclassified events to выберите fallback-тип инцидента (напр. Authentication Anomaly), чтобы несовпавший алерт всё же становился кейсом.
  5. Кликните Save Version. Появляется подтверждение «Classifier saved».

Классификатор решает тип первым. Ветки (Specific) входящего маппера на тип завязаны на это решение — так что если Specific-ветка, кажется, никогда не отрабатывает, проверьте, что классификатор действительно маршрутизирует алерт к этому типу, прежде чем подозревать маппер.

9.6. Шаг 5 — создание кастомного поля

Маршрут: /admin/incident-types?...classificationTab=objectsIncidents

Платформа поставляет много встроенных полей, но «MITRE Technique» — наше, чтобы его добавить.

  1. В библиотеке объектов выберите Incidents, откройте список полей и кликните New Incident Field.
  2. Задайте Field Type = Text, подпись = MITRE Technique. Machine-имя генерируется за вас (напр. mitre_technique) — это ключ, на который ссылаются маппер и layout.
  3. Сохраните. Поле теперь доступно как цель маппера и в библиотеке полей layout-а.

Создайте поле до того, как маппить или размещать его. Кастомное поле, которого не существует, не может быть целью маппера или элементом layout-а. Это самая частая ошибка «задом наперёд» (см. гл. 1).

9.7. Шаг 6 — маппинг полей во входящем маппере

Маршрут: /admin/incident-typesincoming mapper

Откройте входящий маппер инстанса (из области Collect инстанса, New Incoming Mapper / Open Incoming Mapping Editor, или через Objects Setup → Incident Types → incoming-mappers). Заголовок читается Incoming Mapping Editor.

Загрузите данные источника. Как в классификаторе, используйте элемент Data: (Pull instance / Schema/sample / Upload JSON), чтобы редактор знал имена полей источника.

Scope. Оставьте Scope: Common для маппингов, применимых к каждому типу инцидента; переключитесь на Specific и выберите Branch: (тип инцидента) для маппингов на тип. Для этого разбора смаппьте всё в Common.

Смаппьте шесть полей. Для каждого целевого поля задайте его путь источника (кликните поле в исходном JSON или наберите путь) и, где отмечено, добавьте трансформеры/фильтры:

Целевое поле Путь источника Трансформеры / Фильтры
Name alertname
Severity severity
Occurred detectedtime
Source Ref alertid
MITRE Technique (custom) mitretechnique Трансформеры: trimtoUpperCase
Tags tags Фильтры: compact, unique
  • Для MITRE Technique откройте расширенное меню строки поля и под Transformers кликните Add transformer дважды: сначала trim (срезает окружающие пробелы), затем toUpperCase (нормализует t1110 T1110). Трансформеры гоняются по порядку, сверху вниз.
  • Для Tags откройте Add filter под разделом Where и добавьте compact (отбрасывает пустую строку), затем unique (убирает дубликат), превращая ["auth","","brute-force","auth"] в ["auth","brute-force"].

Добавление не-встроенных целей. Вендорские поля без встроенного дома — sourceip, hostname, username — можно добавить вводом Add custom incident field (e.g. email.subject) внизу списка целей, затем Add. Они попадают в custom_fields кейса и адресуемы как incident.<key>.

Кликните Save Mapper.

Куда идут сопоставленные данные. Всё, что пишет маппер, попадает в колонку custom_fields — никогда в raw_json, который хранит нетронутый оригинал. Подтвердите маппинг, сравнив incident.rawJSON.mitretechnique (что прибыло) с сопоставленным incident.mitre_technique (что произвёл трансформер).

9.8. Шаг 7 — размещение поля на layout-е

Маршрут: /admin/layouts · Права: layouts.view, layouts.manage

  1. Откройте Objects Setup → Layouts и отредактируйте layout, привязанный к Brute Force Login (или создайте один для типа инцидента).
  2. В Layout Builder найдите библиотеку полей слева. Наберите MITRE в Search fields, чтобы найти MITRE Technique.
  3. Перетащите поле из библиотеки на секцию холста. Подправьте его подпись/видимость в панели свойств справа при необходимости.
  4. Кликните Save. (Используйте 📋 History, чтобы откатиться при необходимости.)

Повторите для layout-а Authentication Anomaly, если хотите видеть поле на обоих типах.

9.9. Шаг 8 — сборка минимального плейбука

Маршрут: /playbooks · Право: cases.view (модуль: cases)

Плейбук из четырёх узлов: start, ветвление по severity, извлечение индикаторов, оставить заметку.

  1. Откройте Playbooks и кликните, чтобы создать новый плейбук. Редактор показывает Node Palette слева, холст посередине и панель Properties справа (она появляется, когда выбран узел).
  2. На холсте уже есть узел Start (Flow Control). Перетащите эти из палитры на холст:
    • Из LogicCondition.
    • Из ActionsExtract Indicators.
    • Из Flow ControlNote.
  3. Соедините узлы, перетаскивая от ручки-выхода одного узла к входу следующего: Start → Condition, затем выход True Condition → Extract Indicators → Note. (У узла Condition есть выходы True / False; проложите False к Note тоже, если хотите, чтобы оба пути заканчивались там.)
  4. Выберите каждый узел и настройте его в панели Properties — например, настройте Condition проверять ${incident.severity} равно high и подтвердите, что узел Extract Indicators гоняется против кейса.
  5. Назовите плейбук (напр. Acme SIEM triage) и Save (можно добавить change note при сохранении версии).

Что и когда гоняется. Этот плейбук — часть контента, как любая другая; прикрепите его к post-processing типа инцидента или запустите с кейса. Его результаты пишутся в колонку context_outputs кейса, где их могут читать виджеты layout-а и другие автоматизации.

9.10. Шаг 9 — сквозная проверка

Отправьте один тестовый алерт и проследите его через конвейер.

  1. Протолкните тестовый алерт. Если инстанс не опрашивает, отправьте POST-ом brute-force событие на эндпоинт ingest. source — это Source Key коннектора, а sourceInstanceSource Instance Key инстанса, так что платформа применяет классификатор и маппер этого инстанса:

    curl -X POST https://<your-host>/api/v1/ingest \
      -H "Content-Type: application/json" \
      -H "X-Ingest-API-Key: <your-ingest-api-key>" \
      -d '{
        "source": "acme_siem",
        "sourceInstance": "acme-soc",
        "sourceRef": "ACME-2026-004417",
        "payload": {
          "alertid": "ACME-2026-004417",
          "alertname": "Multiple failed logons then success",
          "category": "brute_force",
          "severity": "high",
          "sourceip": "203.0.113.44",
          "hostname": "FIN-WKS-118",
          "username": "j.okafor",
          "mitretechnique": "  t1110  ",
          "tags": ["auth", "", "brute-force", "auth"],
          "detectedtime": "2026-07-17T09:14:22Z"
        }
      }'
    

    Эндпоинт возвращает 202 Accepted — кейса ещё нет; он строится мгновением позже из очереди soar.ingest.

  2. Подтвердите кейс. Через несколько секунд откройте Cases. Новый кейс должен появиться с типом Brute Force Login (классификатор маршрутизировал category: "brute_force").

  3. Проверьте поля. На экране кейса: Name = имя алерта, Severity = high, Occurred = detected time, а ваш кастомный MITRE Technique = T1110 (обрезан и в верхнем регистре) — виден, потому что вы поместили его на layout. Tags должны читаться auth, brute-force (пустое и дубликат убраны).

  4. Проверьте плейбук. Подтвердите, что плейбук отработал (его выводы на кейсе) и что индикаторы вроде source IP извлечены.

Если что-то из этого не так, пройдите конвейер по порядку: неверный тип → классификатор; пустое/некорректное поле → маппер (сравните с incident.rawJSON); поле отсутствует на экране → layout; плейбук не отработал → его привязка/триггер.

Распространённые ошибки

  • 202 прочитан как «кейс создан». Вызов ingest принимается асинхронно. Ищите кейс мгновением позже, а не в HTTP-ответе.
  • Поля образца под обёрткой. В этом разборе поля алерта на верхнем уровне, так что поле классификатора — category, а источник маппера — sourceip. Если ваш реальный источник вкладывает всё под payload, ваши пути становятся payload.category / payload.sourceip — всегда читайте реальное JSON-дерево в конструкторе, а не предполагайте.
  • Поле классификатора с одним значением. Классификатор маршрутизирует отдельные значения одного поля. Если у каждого загруженного события одна и та же category, вы получаете одну корзину и не можете разбить на два типа — выберите поле, которое действительно варьируется, или загрузите различающиеся события.
  • Маппинг в поле, которого ещё нет. Создайте кастомное поле MITRE Technique до маппинга в него и до размещения на layout-е; иначе оно не предлагается как цель или элемент layout-а.
  • Путаница трансформер vs фильтр. trim и toUpperCaseтрансформеры (они переформовывают значение) и живут под Add transformer; compact и uniqueфильтры (они оставляют/отбрасывают элементы в списке) и живут под Add filter. Применение фильтра списка к скаляру или строкового трансформера к массиву не делает ничего полезного.
  • Рассинхрон source key на /ingest. Если source в payload не совпадает с Source Key коннектора, платформа не может привязать алерт к классификатору и мапперу этого инстанса, и откатывается к дефолтам.
  • Редактирование layout-а до того, как маппер заполнит поле. Размещённое поле отрисовывается пустым, пока маппер его действительно не запишет — сначала проверьте маппинг, затем доверяйте layout-у.