ADG Оставить заявку
Блог Информационная безопасность 5 мин чтения

ГосСОПКА REST API 2024: аутентификация по сертификату и передача инцидентов через Ansible

НКЦКИ расширил REST API ГосСОПКА для субъектов КИИ. Разбираем структуру запроса, аутентификацию по клиентскому сертификату и автоматизацию отправки через Ansible playbook.

Контекст момента

ГосСОПКА расширила REST API для автоматической передачи сведений об инцидентах субъектами КИИ

НКЦКИ в ноябре обновил документацию по API ГосСОПКА: добавили несколько новых эндпоинтов, уточнили схему объектов и немного облегчили жизнь тем, кто хочет передавать инциденты не руками через веб-кабинет, а автоматически. Мы как раз заканчивали аналогичную задачу у нескольких клиентов - и заодно посмотрели, что изменилось и что это значит для тех, кто ещё не подключился.

Если коротко: API стал чуть более внятным, но количество нюансов в аутентификации и формате никуда не делось. Рассказываем, как это выглядит изнутри.

Что добавили в API

Основное изменение - это расширение набора методов для работы с инцидентами. Раньше API позволял отправить инцидент и получить статус приёма. Теперь появились методы для обновления уже переданного инцидента (PATCH), получения списка своих инцидентов с фильтрацией по статусу и периоду, а также метод для прикрепления файлов (артефактов, скриншотов, логов) к уже созданному инциденту.

Это полезно: прежде update-сценарий вынуждал либо создавать новый объект, либо идти в веб-интерфейс руками. Теперь можно нормально вести инцидент от начала до закрытия через одну точку входа.

Структура запроса на создание инцидента

Базовый POST-запрос выглядит так:

POST /api/v2/incidents
Content-Type: application/json

Тело в JSON, ключевые поля:

  • title - краткое наименование, до 200 символов; лучше сразу в читаемом виде, потому что именно оно попадает в реестр
  • description - развёрнутое описание события; поддерживает простой текст, без разметки
  • detected_at и occurred_at - метки времени в ISO 8601, обязательно с суффиксом Z (UTC); локальное время API не принимает, возвращает 422
  • severity - одно из четырёх значений: low, medium, high, critical; от этого поля зависит приоритет обработки на стороне НКЦКИ
  • category - тип инцидента из закрытого справочника; список значений есть в документации, но он периодически пополняется - стоит проверять актуальную версию
  • affected_objects - массив объектов с описанием затронутых активов: IP, hostname, тип объекта КИИ

Из практики: самая частая ошибка на первом запуске - формат detected_at. Передаёшь 2024-11-15T10:30:00+03:00, API отвечает 422 без внятного объяснения. Переводишь в UTC и добавляешь Z - проходит. Это поведение сохранилось и в новой версии, документация теперь явно про это написала, но всё равно ловим на каждом втором проекте.

Аутентификация: клиентский сертификат

Это самая нетривиальная часть, и тут всё осталось как было: API ГосСОПКА работает с двусторонним TLS. Сервер проверяет клиентский сертификат, выданный при регистрации субъекта в личном кабинете НКЦКИ.

Что нужно иметь:

  • Клиентский сертификат (.crt или .pem) и приватный ключ к нему - получаете при регистрации, храните в защищённом хранилище
  • Корневой сертификат НКЦКИ для проверки серверной стороны - скачивается с портала, обновляется редко, но следить стоит
  • Цепочка промежуточных сертификатов - если она есть, нужно передавать полностью; без этого TLS-рукопожатие может падать на разных клиентах по-разному

При запросе через curl это выглядит так:

curl -X POST https://api.gosopka.gov.ru/api/v2/incidents \
  --cert /path/to/client.crt \
  --key /path/to/client.key \
  --cacert /path/to/nktsci-ca.crt \
  -H "Content-Type: application/json" \
  -d @incident.json

На проде ключи и сертификаты держим в HashiCorp Vault или, если клиент без Vault, в зашифрованном Ansible vault-файле. Никаких plaintext-ключей в репозитории - это не обсуждается.

Ansible: плейбук для автоматической отправки

Для автоматизации мы используем Ansible playbook, который вызывается из pipeline при появлении нового инцидента. Задача забирает данные из SIEM (у нас это MaxPatrol или Kaspersky SIEM, в зависимости от клиента), формирует JSON и отправляет в ГосСОПКА.

Ключевой фрагмент - задача отправки через ansible.builtin.uri:

- name: Send incident to GosSOPKA
  ansible.builtin.uri:
    url: "{{ gosopka_api_url }}/api/v2/incidents"
    method: POST
    client_cert: "{{ gosopka_cert_path }}"
    client_key: "{{ gosopka_key_path }}"
    ca_path: "{{ gosopka_ca_path }}"
    body_format: json
    body:
      title: "{{ incident.title }}"
      description: "{{ incident.description }}"
      detected_at: "{{ incident.detected_at | to_datetime | strftime('%Y-%m-%dT%H:%M:%SZ') }}"
      occurred_at: "{{ incident.occurred_at | to_datetime | strftime('%Y-%m-%dT%H:%M:%SZ') }}"
      severity: "{{ incident.severity }}"
      category: "{{ incident.category }}"
      affected_objects: "{{ incident.affected_objects }}"
    status_code: [200, 201]
    validate_certs: true
  register: gosopka_response
  no_log: true

no_log: true здесь обязателен - иначе в логи Ansible попадут содержимое тела с деталями инцидента и заголовки, включая путь к сертификату.

Дата-фильтр to_datetime | strftime('%Y-%m-%dT%H:%M:%SZ') - это наш способ гарантировать UTC-формат вне зависимости от timezone хоста, на котором запускается плейбук. Без этого на серверах с московским временем инцидент создавался с неверными метками.

После успешной отправки сохраняем gosopka_response.json.id - это идентификатор инцидента в системе НКЦКИ, он нужен для последующих PATCH-запросов при обновлении статуса.

Мониторинг канала

Отдельная задача, которую часто упускают: сам канал передачи нужно мониторить независимо от логики отправки инцидентов.

Мы добавляем в мониторинг три вещи:

  • Срок действия клиентского сертификата - за 30 дней до истечения alert в Zabbix; если сертификат протухнет, передача молча перестанет работать
  • Доступность API-endpoint - простой HTTP-чек с клиентским сертификатом раз в 5 минут; если API недоступен, инцидент нужно поставить в очередь и отправить позже
  • Лог неуспешных отправок - отдельный файл, куда пишутся все 4xx/5xx ответы с телом запроса; без этого разобраться что пошло не так через неделю практически нереально

Очередь при недоступности - отдельная история. У нас простой вариант: Ansible пишет неотправленные инциденты в файл на диске, повторная задача смотрит в этот файл по расписанию. Не самое элегантное решение, зато прозрачное и без внешних зависимостей.

Что в итоге

Интеграция с ГосСОПКА через REST API решаема, новые возможности API (обновление и прикрепление артефактов) делают её немного более полноценной. Основные грабли - это формат дат и аккуратная работа с сертификатами - никуда не делись.

Если у вас КИИ первой категории и автоматической передачи инцидентов ещё нет - сейчас хороший момент это поправить: ручная отчётность через веб-форму всё меньше устраивает регулятора. О том, как мы выстраиваем подобные интеграции, можно спросить напрямую.

Контакт

Нужна такая же инженерная работа?

Опишите задачу и контекст. Ответим в течение рабочего дня, при необходимости подпишем NDA.