Приветствую, уважаемый читатель!
Есть в Splunk операторы, которые создают фундамент для всех математических или аналитических запросов. Одним из таких операторов является stats. Как понятно из названия, он позволяет над группами событий выполнять различные статистические операции. Некоторые сценарии его использования покажу ниже.
Общий алгоритм использования оператора stats простой:
| ...| <получение событий из sourcetype или index>
| stats <функции и условия>
Т.е. берем набор событий, потенциально даже без какой-то группировки или полнотекстовой фильтрации, и подаём в оператор stats.
Основные функции stats:
count(): вычислить количество событий по какому-то значению в поле (field) или просто посчитать все события.
sum(): вычислить сумму значений в поле.
avg(): вычислить среднее значение в поле.
max(): вычислить максимальное значение поля.
min(): вычислить минимальное значение поля.
distinct_count() или dc(): вычислить уникальные значения поля.
values(): получить список всех уникальных значений поля.
list(): получить список всех значений поля, включая дубликаты.
Самые нужные функции на мой взгляд: count(), dc(), values(), list(). Вот по ним сразу перейдём к примерам.
Получить просто количество событий подбора паролей к SSH сгруппированное по уникальным IP
sourcetype="AuthLog" "Failed password"
| rex field=_raw "for\s(?<User>.{3,40})\sfrom" | rex mode=sed field=User "s/invalid\suser\s//"
| rex field=_raw "from\s(?<IP>.{8,16})\sport"
| rex field=_raw "port\s(?<portNumber>\d+)\s"
| iplocation IP
| stats count by IP
Теперь усложним условие - Получить количество событий подбора паролей к SSH сгруппированное по уникальным IP и уникальным пользователям + дополнительно для каждой такой связки значений (IP, пользователь) вывести все номера портов.
sourcetype="AuthLog" "Failed password"
| rex field=_raw "for\s(?<User>.{3,40})\sfrom" | rex mode=sed field=User "s/invalid\suser\s//"
| rex field=_raw "from\s(?<IP>.{8,16})\sport"
| rex field=_raw "port\s(?<portNumber>\d+)\s"
| iplocation IP
| stats values(portNumber) as portNumber, count by User, IP
Как вы видите, возможности stats count можно существенно детализировать через добавление полей после by, сколько полей перечислите - столько уникальных связок для расчёт и получите (главное не переусердствуйте :) ). Также, в данном примере совмещены и функция count и функция values(), функционально ограничений внутри stats нет никаких.
Отличия функции list() от values()
Функция list() выводит все значения в поле, а функция values() выводит уникальные значения в поле. Это очень важно понимать, т.к. если вы группируете события с использованием list - вы потенциально увидите кучу дубликатов, но если вам нужна ретроспектива внутри группировки иного выхода нет. Использование values хорошо вписывается, когда нужно на дашборд вывести сводную информацию по уникальности значений в поле.
Ниже пример list
sourcetype="AuthLog" "Failed password"
| rex field=_raw "for\s(?<User>.{3,40})\sfrom" | rex mode=sed field=User "s/invalid\suser\s//"
| rex field=_raw "from\s(?<IP>.{8,16})\sport"
| rex field=_raw "port\s(?<portNumber>\d+)\s"
| iplocation IP
| stats list(User) as User,list(_time) as time by IP
Ниже пример values
sourcetype="AuthLog" "Failed password"
| rex field=_raw "for\s(?<User>.{3,40})\sfrom" | rex mode=sed field=User "s/invalid\suser\s//"
| rex field=_raw "from\s(?<IP>.{8,16})\sport"
| rex field=_raw "port\s(?<portNumber>\d+)\s"
| iplocation IP
| stats values(User) as User,list(_time) as time by IP
Как видите, при совместном использовании 2-х функции username схлопнулись (values), но время доступа (list) отражается с учётом рестроспективы по времени. Это важно, когда вы коррелируете события через операторы join, search, map и т.д.
Комментариев нет:
Отправить комментарий