Плагин http-scraping
Введение
Плагин http-scraping
позволяет отправлять HTTP-запросы на различные хосты и создавать событие на основе возвращаемого ответа. Если сравнивать этот плагин с функционалом HTTP-коллектора, то можно представить их как подходы pull и push.
"Push" - подход HTTP-коллектора работает следующим образом: источник, у которого есть событие, сам посылает его на коллектор (т.е. событие "проталкивается" на коллектор).
"Pull" - подход плагина http-scraping
же работает иначе: источник, у которого есть событие, отдает его по HTTP. Коллектор с плагином делает запрос на сервер-источник, чтобы это событие получить (т.е. событие "извлекается" коллектором).
Помимо создания событий на основе тела ответа данный плагин также может быть полезен, чтобы отслеживать задержку ответа либо следить за состоянием TLS-сертификатов сервера.
Конфигурация
Конфигурация плагина состоит из объекта http-scraping
, в котором имеется два поля:
targets
- список целей для HTTP-запросов. Схожих с scrape_config в Prometheus. Их структура будет описана далее.include-response-headers
- список заголовков ответа, которые будут включены в сформированное событие.
Вложенность в объект http-scraping
требуется для идентификации плагина.
Конфигурация цели включает в себя множество полей. Рассмотрим их:
- headers - заголовки запроса в виде словаря "строка-строка".
- query - query-параметры URL, в конфигурации задаются как словарь, где ключом является строка, а значением - либо строка, либо массив строк.
- url - URL запроса.
- body - тело запроса.
- method - метод запроса. По умолчанию равен GET.
- username - имя пользователя для Basic Auth.
- password - пароль пользователя для Basic Auth.
- bearer-token-file - путь к файлу с токеном для авторизации (для авторизации на основе токенов)
- tls - параметры TLS. Схожи с параметрами в конфигурационных файлах сервисов KOMRAD с единственным исключением: вместо того, чтобы указывать, выключен ли TLS (
disable: false
), здесь указывается, включен ли он (enable: true
). - period - частота запросов в виде
time.Duration
. Задается строкой по типу "2s", "5h" и т.п. - timeout - таймаут для запроса, задается в виде
time.Duration
- deduplication0 - подход к дедупликации событий. Рассмотрим его позже.
Пример конфигурации:
http-scraping:
include-response-headers:
- Date
- Expires
targets:
- headers:
Cookie: "session=session_key"
query:
plain_param: param
list_param:
- param1
- param2
url: example.com/api/path
body: '{"hello": "world"}'
method: POST
tls:
enabled: true
TrustedCA: "/path/to/cert"
system-pool: true
period: 15s
timeout: 3m
deduplication: none
Дедупликация событий
Для дедупликации событий в цели можно использовать параметр deduplication
в конфигурации одной цели. Основной механизм работы дедупликации - плагин запоминает определенный параметр ответа цели, который в дальнейшем сравнивается с аналогичным параметром нового ответа. Если они совпадают - новое событие не создается. Далее перечислены возможные стратегии дедупликации:
Стратегия | Принцип работы |
---|---|
none | Дедупликация отсутствует |
body | События дедуплицируются на основе тела ответа |
response_code | События дедуплицируются на основе кода состояния ответа |
error | События дедуплицируются на основе произошедшей (или нет) ошибки |
Например, мы дедуплицируем события на основе кода состояния ответа. Допустим, у нас следующая последовательность кодов ответа: 200 500 500 200 200. Тогда в результате получим 3 события: 200 500 200, т.к. вторые (и так далее) события убираются.
Парсинг ответа
Плагин парсит множество полей, связанных с HTTP-соединением. В таблице ниже перечислены извлекаемые поля:
Поле | Значение | Когда добавляется к событию |
---|---|---|
ECS.Destination.Address | Адрес сервера | При создании подключения (обычно TCP) |
ECS.Destination.Domain | Домен сервера | При начале DNS-запроса |
ECS.Destination.IP | IP сервера | В конце DNS- запроса |
ECS.Event.Duration | Длительность запроса | После получения ответа |
ECS.Event.Start | Время начала запроса | После получения ответа |
ECS.Event.End | Время конца запроса (время получения ответа) | После получения ответа |
ECS.HTTP.ResponseBodyContent | Тело ответа | После получения ответа |
ECS.HTTP.ResponseBodyBytes | Размер тела ответа в байтах | После получения ответа |
ECS.HTTP.Version | Версия HTTP | После получения ответа |
ECS.HTTP.Header.* | Значения заголовков, заданных в поле include-response-headers | После получения ответа |
ECS.TLS.Version | Версия TLS | После получения ответа |
ECS.TLS.Cipher | Алгоритм шифрования TLS | После получения ответа |
ECS.TLS.Resumed | Было ли соединение TLS возобновлено | После получения ответа |
ECS.TLS.Established | Было ли соединение TLS успешно установлено | После получения ответа |
ECS.TLS.ServerIssuer | Издатель сертификата сервера | После получения ответа либо при неудачном рукопожатии TLS |
ECS.TLS.ServerNotAfter | Время окончания сертификата сервера | После получения ответа либо при неудачном рукопожатии TLS |
ECS.TLS.ServerNotBefore | Время начала действия сертификата сервера | После получения ответа либо при неудачном рукопожатии TLS |
ECS.TLS.ServerSubject | Субъект сертификата сервера | После получения ответа либо при неудачном рукопожатии TLS |
Примеры
Сбор логов аудита Jira
Поскольку плагин http-scraping
не имеет сложную логику построения запросов (например, на основе шаблонов, использующих предыдущий ответ) и не сохраняет в долговечном месте информацию, то полноценный сбор логов без потерь организовать невозможно. Но пока есть базовый вариант, позволяющий ухватить их часть. Попробуем описать, как это сделать.
Для начала вам нужны права администратора, чтобы получить доступ к логам аудита (самому их можно посмотреть в Администрирование -> Система -> Журнал
). Как т олько права получены, необходимо выпустить персональный токен доступа. Для этого переходим в свой профиль и открываем вкладку Персональные токены доступа
. В этой вкладке нажимаем кнопку Создать токен
, и далее задаем токену имя и срок действия. После создания копируем токен и сохраняем его в файл, он нам понадобиться.
Далее создаем плагин со следующим содержанием:
http-scraping:
targets:
- query:
limit: 1
url: 'https://jira.npo-echelon.ru/rest/auditing/1.0/events'
method: GET
bearer-token-file: "путь к сохраненному файлу с токеном"
period: 30s
timeout: 1m
deduplication: body
После этого включаем плагин на коллекторе, после чего с заданной периодичностью (если есть новые записи в логе) будем получать события. Можем попробовать добавить парсер для них. Чтобы это сделать, я использую плагин json
в processors
, созданный с помощью эвристического анализа (и слегка измененный мною):
processors:
- module: json
patterns:
- expr: entities.0.affectedObjects
to: AffectedObjects
- expr: entities.0.author.avatarUri
to: AuthorAvatarUri
- expr: entities.0.author.id
to: AuthorId
- expr: entities.0.author.name
to: AuthorName
- expr: entities.0.author.type
to: AuthorType
- expr: entities.0.author.uri
to: AuthorUri
- expr: entities.0.changedValues
to: ChangedValues
- expr: entities.0.method
to: Method
- expr: entities.0.source
to: Source
- expr: entities.0.system
to: System
- expr: entities.0.timestamp
to: Timestamp
- expr: entities.0.type.action
to: TypeAction
- expr: entities.0.type.actionI18nKey
to: TypeActionI18NKey
- expr: entities.0.type.category
to: TypeCategory
- expr: entities.0.type.categoryI18nKey
to: TypeCategoryI18NKey
После этого получим события, в которых есть информация как о HTTP-ответе (задержка ответа, код состояния, сертификат и т.д.), так и информация о самом логе. Эту информацию можно использовать дальше для фильтрации и корреляции.
Проверка здоровья сервиса
В разработке сервисов есть паттерн "проверки здоровья" (healthcheck), помогающий узнать, работает ли сервис исправно или есть какие-то неполадки. Для этого в HTTP API добавляется дополнительный маршрут (обычно, его называют /health
), который в нормальной ситуации возвращает код состояния 200 и какую-то информацию (например, о состоянии системы). Если информации нет, можно возвращать просто какой-либо текст (например, текст кода состояния).
Можем использовать плагин http-scraping
для того, чтобы создавать события, когда сервис нездоров. В качестве примера используем сам KOMRAD.
Для сбора информации о здоровье используем следующий конфиг:
http-scraping:
targets:
- url: 'https://npo-echelon-komrad.ru/api/health'
method: GET
tls:
enabled: true
TrustedCA: "{путь к CA сертификату}"
system-pool: true
period: 30s
timeout: 15s
deduplication: response_code
Чтобы отфильтровывать события с успешным кодом возврата, можем использовать плагин if
:
processors:
- module: if
cel:
- event.vars("ECS.HTTP.ResponseStatusCode") != 200
Обнаружение истечения срока действия TLS-сертификата
Плагин http-scraping
можно использовать для обнаружения истекших сертификатов. Для этих целей можно использовать любой URL, например, для проверки здоровья из предыдущего примера.
Для пример а возьмём проверку сертификатов на KOMRAD, используя ту же ручку.
Чтобы извлекать из этого сервера события, используем следующую конфигурацию:
http-scraping:
targets:
- url: 'https://npo-echelon-komrad.ru/health'
method: GET
tls:
enabled: true
TrustedCA: "{путь к сгенерированному корневому сертификату}"
period: 15s
timeout: 5s
После за пуска плагина будем получать события, где в поле ECS.TLS.ServerNotAfter
будет указана дата окончания действия сертификата. Можем использовать ее для фильтрации и корреляции.
Например, можем использовать плагин deny
для отсечения событий с сертификатами с долгим сроком валидности:
processors:
- module: deny
cel:
- event.vars("ECS.TLS.ServerNotAfter") != null && (event.vars("ECS.TLS.ServerNotAfter") - now() > duration("72h"))
- module: assign
assign:
- target: CertIsGoingToBeExpired
cel: "true"
В данном плагине deny
отсеиваются все события, оставшийся срок действия сертификата которых превышает три дня. Также с помощью модуля assign
добавляется поле, указывающее на скорое истечение сертификата.
После применения плагинов http-scraping
и deny
мы будем получать только те события от http-scraping
, в которых срок действия сертификата подходит к концу.
Отслеживание высокой задержки HTTP-запросов
С помощью плагина http-scraping
совместно с deny
или assign
можно отслеживать высокую задержку HTTP-ответа от сервера. Для этого в конфигурации необходимо "нацелить" http-scraping
на нужный URL. Например:
http-scraping:
targets:
- url: http://npo-echelon-komrad.ru:health/
method: GET
body: Hello HTTP body!
period: 20s
В данном случае я написал простой сервер, который при запросе на "/" с методом POST засыпает на две секунды, а затем возвращает тело запроса в ответе.
Чтобы отследить высокую задержку, можно написать еще один плагин. Я решил использовать assign
, чтобы обогатить событие новым полем:
processors:
- module: assign
assign:
- target: HighLatency
cel: event.vars("ECS.Event.Duration") != null && event.vars("ECS.Event.Duration") > duration("1s")
Этот плагин записывает в поле HighLatency
то, длился ли запрос больше одной секунды.