Я расскажу о том, что мы с командой сделали для поднятия сервиса по сбору событий и низкоуровневой телеметрии на примере MacOS: как готовили архитектуру, с какими проблемами столкнулись и как их решали. Подробнее остановлюсь на возможностях osquery&Fleet и на том, какие must-have-события рекомендую собирать.
Немного о себе: я работаю в группе инфраструктурной безопасности в команде Ozon около двух лет. До этого я уже имела опыт работы с MacOS-устройствами, поэтому у меня есть представление о том, что это за «фрукт».
План
Что такое osquery и Fleet
Osquery — проект с открытым исходным кодом. По своей сути это полноценный фреймворк, который позволяет упростить низкоуровневый мониторинг ОС. Osquery подписывается на системные события и формирует SQL-like таблицы.
Таблицы предоставляют удобный доступ к следующей информации:
об установленных пакетах и ПО;
о конфигурации системы;
о пользователях;
а также позволяют проверить запущенные процессы, сетевые коннекты и т.д.
Получение информации из таблиц осуществляется при помощи SQL-запросов.
Для более эффективного контроля над выполнением запросов и использованием ресурсов мы запускаем osquery совместно с watchdog-процессом мониторинга. Если выполнение запроса потребляет слишком много ресурсов, watchdog «убивает» этот процесс исполнения запроса.
Чем больше устройств – тем выше ответственность сложнее справляться с большим парком устройств. И тут нам на помощь пришел…
Fleet — это инструмент для централизованного управления и конфигурации агентов osquery. Если устройство добавлено во Fleet, то изменять конфигурацию агентов становится намного проще, можно добавлять/изменять/удалять новые запросы. Также можно выполнять distributed queries, выполнение которых позволяет получать информацию условно «здесь и сейчас».
Всё это необходимо для:
довольно существенного расширения возможностей при расследовании инцидентов (компрометация устройства/учетной записи);
помощи в инвентаризации устройств;
обогащения события при инцидентах;
облегчения реализации дополнительных автоматизированных мониторингов.
Как мы выбирали ресурсы для сервиса по сбору событий
Мы изначально планировали провести тестирование с подключением 3000 устройств, чтобы проверить работоспособность цепочки поставки событий, а также нагрузку на БД и ноды, поэтому, изучив все рекомендации в документации Fleet и в сообществе в Slack, выбрали, что будем деплоиться на нескольких нодах приложения и БД (MySQL), а Redis будет в K8S. И всё это для отказоустойчивости будет в разных ДЦ.
По ресурсам много не потребовалось: 2vCPU, до 20 Gb объем HDD на нодах приложения и около 8 Gb RAM.
Для БД ресурсов взяли вдвое больше, чем для нод с приложением.
vCPU |
Storage (Gb) |
RAM |
Количество нод/tasks |
Наша конфигурация серверов | |||
Приложение |
|||
2 |
16 |
8 |
2 |
База данных MySQL |
|||
4 |
64 |
16 |
2 |
Рекомендации по документации fleet | |||
Приложение |
|||
1 |
- |
4 |
10 |
База данных MySQL |
|||
2 |
16 |
- |
- |
В целом таких ресурсов вполне достаточно для нормальной работы сервиса, загрузка минимальная, плюс Fleet удобно масштабировать горизонтально — мы это учитывали.
Архитектура поставки событий
Если кратко, то у нас есть 2 балансера (один пользовательский, другой сервисный), потому что хотелось явно разграничить доступы и роли — кто/куда ходит.
На пользовательский балансер выдаётся гранулярный и контролируемый внутренний доступ (по сертификатам). На сервисном балансере есть доступная API endpoint— /collector, чтобы события от агентов поступали вне корпоративной сети. Надеюсь, вы ещё не потеряли нить.
Далее в цепочке события от /collector поступают в file.d и от file.d — в SIEM, как в конечную точку приёма всех событий.
Также есть 4 API endpoint:
/api/v1/osquery/enroll
(для добавления устройств во Fleet);/api/v1/osquery/config
(для обновления и получения конфига Fleet);/api/v1/distributed/read
(для distributed query);/api/v1/distributed/write
(для distributed query).
Оба балансера проксируются на ноды, где поднято приложение Fleet.
Плюсы такой схемы (почему я рада такому решению):
нет необходимости ставить агента file.d на систему, file.d сам будет преобразовывать JSON, который поступает от osquery, для дальнейшей отправки в SIEM, а также выполнять функцию фильтрации;
есть разграничение по sourcetype на входе балансера;
file.d в K8s удобно масштабировать, повышается отказоустойчивость;
появляется возможность тротлить события (отбрасывает события, если пропускная способность конвейера становится выше настроенного порогового значения) внутри file.d → не нагружать SIEM.
Балансер используется, потому что существуют возможности:
тестировать разные решения отправки событий;
настроить API endpoint и отправлять события от разных источников в разные логически разделённые места хранения в SIEM;
балансировать нагрузку между нодами приложений.
file.d — внутренняя разработка Ozon Tech, написанная на Go. Это инструмент для построения конвейеров данных: чтения, обработки и вывода событий. В основном он разработан для чтения из файлов, но также поддерживает множество плагинов ввода/действия/вывода (input/action/output— https://github.com/ozontech/file.d/tree/master/plugin).
file.d по функционалу очень схож с другим инструментом конвейеров данных — Vector’ом от Datadog.
Конфигурация мониторингов
Мы хотели собирать только те события, которые нам нужны для реализации мониторингов, в том числе чтобы сократить объёмы логов и чтобы просто не собирать «мёртвый груз».
Конечно, первоначально глаза разбегаются и хочется собрать всё, и всё кажется нужным. Но когда мы собирали первую версию пакета, то столкнулись с тем, что событий становится слишком много, и мы, по прогнозам, приближались к тому, чтобы «налить» в SIEM слишком большой объём событий.
Далее кратко о конфигурации запросов.
В osquery доступно два основных типа логирования: snapshot, differential (и differential ignore removals).
Differential — это дифференциальные изменения между последним выполнением запроса и текущим выполнением. Каждая строка журнала представляет собой строку JSON, которая указывает, какие данные были добавлены/удалены.
Snapshot — это, если дословно, моментальный снимок набора результатов в «точный момент времени». Полный моментальный снимок записывается после каждого выполнения запроса. Необходимо понимать, что это будет большой объём данных.
Опираясь на эти рассуждения, применили следующий принцип выбора типа логирования: если таблица имеет большой объем данных или данные в ней меняются незначительно, то используется метод Differential, в остальных случаях применяется snapshot.
О периодичности запросов
Исходя из сути данных и частоты, в нашей конфигурации выбираем минимально допустимую частоту выполнения запросов, чтобы снизить нагрузку, но при этом иметь возможность полноценного контроля за устройством.
В результате анализа рекомендую собирать в качестве минимального набора следующие события с примером конфигурации, это так называемый must-have:
Что собирать (какие таблицы) |
Режим логирования |
Частота исполнения запроса (в секундах) |
Установленное ПО (apps) |
Snapshot |
86400 |
.bash_history (shell_history) |
Differential |
900 |
Сетевые интерфейсы (interface_details) |
Snapshot |
86400 |
Сетевые коннекты(process_open_sockets/processes/users) |
Differential |
3600 |
События процессов (process_events) |
Differential |
3600 |
Автозапуск (startup_items, crontab) |
Differential |
900 |
Залогиненные пользователи (logged_in_users) |
Snapshot |
3600 |
Встроенные СЗИ MacOS (disk_encryption/sip_config/gatekeeper/alf) |
Snapshot |
86400 |
Управление конфигурацией через fleetctl и REST API
Web UI, конечно, прикольно, но хотелось бы уметь управлять Fleet’ом не через интерфейс, плюс иметь возможность добавления интеграций.
Теперь кратко по каждому из инструментов.
Fleetctl — это CLI, который ставится отдельно, но с его помощью можно, например:
выполнить тот же функционал distributed queries;
посмотреть информацию об уже имеющихся queries;
посмотреть информацию о конфиге Fleet;
изменить конфигурацию Fleet;
есть возможность дебага Fleet.
Rest API — у Fleet есть классная API, с помощью которой можно сделать дополнительные интеграции и получить необходимую информацию. Например, интегрировать Fleet и SIEM для добавления информации о хостах в SIEM.
А также:
выполнить distributed queries к конкретному устройству (да, по ID);
листить все хосты (а также удалять хосты, получать информацию о конкретном хосте);
получить список пользователей, политик, ПО и т.д.
Заключение
Все мы знаем, что, насколько ни была бы защищена инфраструктура компании, её главным узким и самым уязвимым местом являются сотрудники. Преднамеренное или непреднамеренное действие может привести к грустным последствиям, поэтому собираемые события и автоматизированные мониторинги могут помочь выявить «атаку» на раннем этапе или же помочь в расследовании Incident response team — проанализировать случившееся и не допустить повторное.
Osquery и Fleet — прекрасная связка для мониторинга ОС. В текущих реалиях для задачи мониторинга безопасности такой open-source-инструмент поможет снизить риски компрометации инфраструктуры.
А в следующей статье, уже с коллегой, мы расскажем больше про аналитику и набор алертов, которые были нами реализованы.
Stay tuned. :)
igor_suhorukov
Насколько я помню, когда пробовал интеграцию QuestDB с osquery, не все события остаются при pull запросах в osquery, некоторая телеметрия может отправляться в центральное хранилище только демоном osqueryd.
The daemon also uses OS eventing APIs to record monitored file and directory changes, hardware events, network events, and more.
Как с этим дела у Fleet, он только в режиме pull работает и отправляет запросы на каждое из устройств?