Для интеграции с Kaspersky MDR используется публичный API - MDR Console (kaspersky.com).
Документация по Open REST API Reference.
Через API есть возможность выполнить любые действия доступные во вкладке Incidents в MDR Web Portal, а именно:
- Авторизация
- Чтение, создание и редактирование инцидентов
- Получение истории изменения инцидентов
- Чтение и создание/удаление комментариев и вложений
- Чтение и реагирование на Response
- Получение информации об активах и тенантах
При выполнении HTTP запроса все данные передаются в json формате. При успешном запросе будет возвращен код 200, при возникновении ошибки причина будет указана в ответе.
Все методы API выполняются по следующей схеме
https://mdr.kaspersky.com/api/v1/<ClientID>/<API method path>
Все действия с API требуют активного токена доступа.
В системе используется два токена refresh_token и access_token.
- refresh_token требуется для обновления access_token и получения нового refresh_token.
- Срок действия первого refresh_token - 24 часа, то есть при генерации токена через Web Portal, его необходимо обновить в течение этого времени
- Срок действия всех следующих refresh_token - 7 дней
- access_token требуется для доступа к MDR
- Срок действия access_token 30 минут
Токен имеет несколько состояний:
- Pending activation - состояние токена после генерации. Токен ожидает активации, чтобы вернуть новые refresh_token и access_token
- Active - состояние токена, когда активен для использования access_token
- Idle - состояние токена, когда access_token стал неактивен (через 30 минут) и требует обновления с помощью refresh_token
- Expired - состояние токена, когда refresh_token стал просроченным (через 7 дней) и требуется ручная генерация нового токена через MDR Web Portal
Для получения токена, необходимо:
- перейте в Settings → API
- указать Connection Name (он будет использоваться как имя пользователя при - создании инцидентов/комментариев/вложений и т.д., так как токен доступа не привязан к конкретному пользователю)
- указать Role, чтобы определить права доступа для токена
- указать Tenant при необходимости
- нажать Generate
- после генерации будут получены:
- JWT Token - он же refresh_token, который требуется активировать, чтобы получить новую пару refresh_token и access_token
- ClientID - ID клиента для подключения по API. Требуется указывать при каждом запросе по API
Для обновления токена используется метод session/confirm: https://mdr.kaspersky.com/api/v1/<ClientID>/session/confirm
Детали запроса описаны в документации к MDR Web Portal Public API
В схеме объектов MDR есть Asset и Incident. Incident включает в себя Comment, Attachment, Response, а также ссылки на Asset.
В рамках взаимодействия по API, есть возможность сделать запрос с фильтром по полям актива и получить количество таких активов или их список в зависимости от метода
Зная asset_id, можно запросить детали по данному активу - это удобно, если в инциденте встретился актив и требуется получить по нему исчерпывающую информацию.
В рамках взаимодействия по API, есть возможность сделать запрос с фильтром по полям инцидента и получить количество таких инцидентов или их список в зависимости от метода.
Зная incident_id, можно запросить детали по конкретному инциденту.
Информация об инциденте содержит поля с Asset, Comments, Attachments и Responses. Поля являются списками (array) с объектами (dict), в которых есть краткая инфорация и id объекта, чтобы можно было запросить более детальную информацию по каждому объекту.
В рамках взаимодействия по API, есть возможность запрашивать информацию по вложениям внутри инцидента, а также скачивать и загружать новые вложения.
NOTE: Размер вложения в MDR может достигать нескольких ГБ, поэтому при интеграции имеет смысл загружать не все вложения, а только небольшие, фильтруя по размеру или расширению. Для больших вложения можно получать только ссылку для скачивания и передавать в локальную систему. Ссылка на вложение есть в деталях о вложении.
В рамках взаимодействия по API, есть возможность читать комментарии, чтобы получить последние обновления, а также создавать и удалять комментарии.
В рамках взаимодействия по API, есть возможность получить список всех Response внутри инцидента и ответить на них подтвердив или отклонив.
В связи с необходимостью поддерживать активный refresh_token и access_token, требуется на регулярной основе обновлять его. Для решения этой задачи можно использовать следующие варианты:
- обновлять токены при каждом подключении и проверке новых обновлений в MDR
- обновлять токены по расписанию, например, настроив crontab
- обновлять токены отдельным процессом, который будет запускать функцию обновления по таймауту
Для хранения refresh_token и access_token между подключениями к MDR лучше использовать отдельные файлы. При этом необходимо настроить соответствующие права доступа (400 или r-- --- ---), чтобы никто, кроме сервисной учетной записи (под которой работает интеграция) не имел доступа к токену.
Пример обновления токена:
import requests
client_id = "1f1f1f1f1f1fc144a4b9a3af6a6a6a6a6a"
refresh_token = open("./refresh_token", 'r').read()
url = f"https://mdr.kaspersky.com/api/v1/{client_id}/session/confirm"
json_data = {"refresh_token": refresh_token}
resp = requests.post(url = url, json = json_data, verfy = False)
access_token = resp.json().["access_token"]
refresh_token = resp.json().["refresh_token"]
Для получения обновлений по инцидентам есть возможность запрашивать все инциденты у которых update_time больше чем время предыдущей проверки обновлений. При необходимости получать только информацию о новых инцидентах можно использовать поле creation_time, которое должно быть больше чем время последней проверки обновлений.
Для этого необходимо выполнить запрос метода incidents/list, а в теле запроса задатать соответствующий фильтр (min_update_time для фильтра по полу update_time и min_creation_time для фильтра пополю creation_time, подробнее см. документацию по API). Для хранения информации о времени последнего обновления можно использовать временный файл (в примере ./last_check_time), который перезаписывается после каждого выполнения интеграции.
import requests
client_id = "1f1f1f1f1f1fc144a4b9a3af6a6a6a6a6a"
access_token = open("./access_token", "r").read()
headers = {"Authorization": f"Bearer {access_token}"}
url = f"https://mdr.kaspersky.com/api/v1/{client_id}/incidents/list"
last_check_time = int(open("./last_check_time", 'r').read())
json_data = {"min_update_time": last_check_time + 1}
resp = requests.post(url = url, headers = headers, json = json_data, verfy = False)
В переменную resp вернется массив (array) с инцидентами удовлетворяющими требованию. При необходимости есть возможность задать другие фильтры, такие как критичность или статус на случай, если нужно получать обновления не по всем инцидентам.
Чтобы понять, что именно обновилось в инциденте, можно пройтись по объектам (response, comment, attachment) и проверить их creation_time, если оно больше или равно чем время обновления инцидента, значит этот объект и был обновлен.
NOTE: Метод History
Есть возможность запросить историю с помощью метода incidents/history.
WARNING: Дублирование информации
Стоит помнить, что при двухсторонней интеграции, когда данные из локальной системы передаются в MDR, например, добавляется комментарий к инциденту, то такие обновления следует игнорировать и не записывать снова в локальную систему. Чтобы решить эту задачу, нужно фильтровать комментарии и вложения, где поле author_name совпадает с Connection Name, который задавался при выпуске токена.
При необходимости скачать вложение следует проверить его размер, чтобы не нагружать систему лишний раз и не подвешивать процесс на скачивание больших файлов, если его, например, 10ГБ.
При получении информации об инциденте, в поле attachments будет лежать массив с краткой информацией о вложениях. Структура с информацией содержит поля attachment_id и link, которые можно использовать для скачивания.
При использовании link, можно загрузить вложение по ссылке, которая будет выглядить следующим образом: https://mdr.kaspersky.com/<incident_id>/attachments/<attachment_id>
. Также эта ссылка будет полезна для передачи пользователю для скачивания файла через браузер.
При использовании attachment_id можно вызвать метод attachments/download
import requests
client_id = "1f1f1f1f1f1fc144a4b9a3af6a6a6a6a6a"
access_token = open("./access_token", 'r').read()
headers = {"Authorization": f"Bearer {access_token}"}
url = f"https://mdr.kaspersky.com/api/v1/{client_id}/attachments/download"
attachment_id = "KVB1FoIBEZqwtDpTd2h3"
json_data = {"attachment_id": attachment_id}
resp = requests.post(url = url, headers = headers, json = json_data, verfy = False)
with open("attachment", "wb") as f:
f.write(resp.content)
Для загрузки вложений в MDR требуется использовать метод attachments/upload.
import requests
import os
import json
client_id = "1f1f1f1f1f1fc144a4b9a3af6a6a6a6a6a"
access_token = open("./access_token", 'r').read()
headers = {"Authorization": f"Bearer {access_token}"}
url = f"https://mdr.kaspersky.com/api/v1/{client_id}/attachments/upload"
filepath = "files/file_to_upload.jpg"
filename = os.path.basename(filepath)
meta = {
"incident_id": incident_id,
"caption": "test message"
}
resp = requests.post(
url = url,
headers = headers,
files = { 'file': (filename, open(filepath, 'rb'), 'application/octet-stream') },
data = { 'meta': json.dumps(meta) },
verfy = False
)
В результате запросе при успешном выполнении в переменной resp будет краткая информация о загруженном вложении.