Перейти к основному содержимому
Версия: 4.5.X

Нормализация событий c использованием GROK

Плагин позволяет извлекать и приводить к модели события Elastic Common Schema исходные события любого формата на основе паттернов, которые были указаны в patterns и definitions.

Если явно не указывать название полей событий в паттернах, то в полях маппинга оно отображаться не будет.

Существует возможность делать преобразования к типам int и float, задавать шаблоны даты и времени, используя конструкцию date("...")

Шаблон Grok паттерна: %{MATCHER:EXTRACT:FILTER}, где

MATCHER - правило (возможно, ссылка на другой паттерн), описывающее, что следует ожидать (NUMBER, WORD и т.д.)

EXTRACT - идентификатор, представляющий место назначения для фрагмента текста, совпавшего с MATCHER

FILTER - пост-процессор правила для его преобразования. Если не указывать, то преобразует найденное выражение к string. (Возможные фильтры: int, float)

Примеры всех MATCHER, которые могут использоваться по умолчанию находятся в файлах внутри этой директории. Все остальные матчеры можно создавать самостоятельно в defenitions

Примеры

1. Событие с полем Ctime, пример конфигурации:

Регулярное выражение :

processors:
- module: grok
from: Raw
patterns:
Komrad_Pattern: "%{COMMONAPACHELOG}"

Пример исходного события:

232.0.0.0 - - [30/Apr/2020:14:30:53 -0500] "GET /images/hm_bg.jpg HTTP/1.0" 200 24736

Результат:

ECS.HTTP.RequestBodyContent: /images/hm_bg.jpg
ECS.HTTP.RequestMethod: GET
ECS.HTTP.ResponseBodyBytes: 24736
ECS.HTTP.ResponseStatusCode: 200
ECS.HTTP.Version: 1.0
ECS.Source.Address: 232.0.0.0

CTime не отображается, т.к. это внутреннее событие event, но он был получен. В результате можно заметить преобразование к полям ECS. Это происходит, потому что внутри себя %\{COMMONAPACHELOG\} содержит другие регулярные выражения, у которых MATCHER является одним из свойств ECS. Определение же типа для свойств ECS задаётся заданными внутри KOMRAD дефолтными значениями.

2. Событие с полем ECS, пример конфигурации:

Регулярное выражение:

processors:
- module: grok
from: Raw
patterns:
Komrad_Pattern: "%{IP:Ecs.client.ip}:%{NUMBER:ecs.Client.port}"

Пример исходного события:

127.0.0.1:3900

Результат:

ECS.Client.IP: 127.0.0.1
ECS.Client.Port: 3900

3. Использование defenitions:

Регулярное выражение:

processors:
- module: grok
from: Raw
patterns:
MyParsingRule: "%{user_info} %{connection} %{server}"
definitions:
user_info: "%{WORD:user.name} id:%{NUMBER:user.id:int}"
connection: "connected on %{date(\"MM/dd/yyyy\"):connect.date}"
server: "on server %{NOTSPACE:server.name} in %{NOTSPACE:server.env}"

Пример исходного события:

john id:12345 connected on 11/08/2017 on server XYZ in production

Результат:

Connect.Date: 2017-11-08T00:00:00Z
Server.Env: production
Server.Name: XYZ
User.ID: 12345
User.Name: john

4. Парсинг простого log-сообщения:

Регулярное выражение :

processors:
- module: grok
from: Raw
patterns:
LOG_MESSAGE: "%{TIMESTAMP_ISO8601:timestamp} %{LOGLEVEL:level} %{GREEDYDATA:message}"

Пример исходного события:

2020-10-02T23:22:12.223222Z info start server

Результат:

Level: info
Message: start server
Timestamp: 2020-10-02T23:22:12.223222Z

5. Парсинг log-сообщения с определениями:

Регулярное выражение:

processors:
- module: grok
from: Raw
patterns:
message: "%{SYSLOGBASE} %{POSTFIX_QUEUEID:queue_id}: %{MSG:syslog_message}"
definitions:
POSTFIX_QUEUEID: "[0-9A-F]{10,11}"
MSG: "message-id=<%{GREEDYDATA}>"

Пример исходного события:

Jan  1 06:25:43 mailserver14 postfix/cleanup[21403]: BEF25A72965: message-id=<20130101142543.5828399CCAF@mailserver14.example.com>

Результат:

ECS.Host.Name: mailserver14
ECS.Process.Name: postfix/cleanup
ECS.Process.PID: 21403
QueueId: BEF25A72965
SyslogMessage: message-id=<20130101142543.5828399CCAF@mailserver14.example.com>

6. Парсинг результата работы системы:

Регулярное выражение:

processors:
- module: grok
from: Raw
patterns:
message: "Inventory error: %{DATA:error_message} for product %{INT:product_id}"

Пример исходного события:

Inventory error: out of memory processing thumbnail for product 7186

Результат:

ErrorMessage: out of memory processing thumbnail
ProductId: 7186

7. Парсинг с использованием фильтров:

Регулярное выражение:

processors:
- module: grok
from: Raw
patterns:
message: "%{WORD:type}: %{IP:ipclient} - %{IP:ipuser} [%{HTTPDATE:datetime}] \"%{WORD:method} %{URIPATHPARAM:request} %{WORD}/%{NUMBER:httpversion:float}\" %{WORD:status:int} %{NUMBER:bytes:integer} - %{NUMBER:responsetime:number}"

Пример исходного события:

info: ::ffff:127.0.0.1 - ::ffff:127.0.0.1 [26/Jun/2019:11:52:36 +0000] "OPTIONS /api/categories/5ced18e2a0c9a01e879ce704 HTTP/1.1" 200 19 - 0.652

Результат:

Bytes: 19
Datetime: 26/Jun/2019:11:52:36 +0000
Httpversion: 1.1
Ipclient: ::ffff:127.0.0.1
Ipuser: ::ffff:127.0.0.1
Method: OPTIONS
Request: /api/categories/5ced18e2a0c9a01e879ce704
Responsetime: 0.652
Status: 200
Type: info

В данном примере для полей: httpversion, status, bytes, responsetime мы указали фильтры: number, int, integer, float. На отображение результата это никак не повлияло, но тип полей этих событий при парсинге изменился со строки, на тот, который им присвоили.

Даты разбора

Сопоставитель даты преобразует вашу метку времени в формат EPOCH (единица измерения миллисекунды).

Регулярное выражениеПример исходного событияИзвлечённые поля
date: "%{date(\"HH:mm:ss\"):date}"14:20:152022-12-29T14:20:15Z
date: "%{date(\"hh:mm:ss a\"):date}"02:20:15 PM2022-12-29T14:20:15Z
date: "%{date(\"dd/MM/yyyy\"):date}"11/10/20142014-10-11T00:00:00Z
date: "%{date(\"EEE MMM dd HH:mm:ss yyyy\"):date}"Thu Jun 16 08:29:03 20162016-06-16T08:29:03Z
date: "%{date(\"EEE MMM d HH:mm:ss yyyy\"):date}"Tue Nov 1 08:29:03 20162016-11-01T08:29:03Z
date: "%{date(\"dd/MMM/yyyy:HH:mm:ss Z\"):date}"06/Mar/2013:01:36:30 +09002013-03-05T16:36:30Z
date: "%{date(\"yyyy-MM-dd’T’HH:mm:ss.SSSZZ\"):date}"2016-11-29T16:21:36.431+00:002016-11-29T16:21:36.431Z
date: "%{date(\"dd/MMM/yyyy:HH:mm:ss.SSS\"):date}"06/Feb/2009:12:14:14.6552009-02-06T12:14:14.655Z
date: "%{date(\"yyyy-MM-dd HH:mm:ss.SSS z\"):date}"2007-08-31 19:22:22.427 UTC2007-08-31 19:22:22.427 UTC
date: "%{date(\"EEE MMM dd HH:mm:ss yyyy\",\"Europe/Paris\"):date}"Thu Jun 16 08:29:03 20162016-06-16T06:29:03Z
date: "%{date(\"EEE MMM dd HH:mm:ss yyyy\",\"UTC+5\"):date}"Thu Jun 16 08:29:03 20162016-06-16T03:29:03Z

Пример заполнения полей:

processors:
- module: grok
from: Raw
patterns:
MyParsingRule: "%{date(\"EEE MMM dd HH:mm:ss yyyy\",\"UTC+5\"):date}"

Пример исходного события:

Thu Jun 16 08:29:03 2016

Результат:

Date: 2016-06-16T03:29:03Z

подсказка

Список всех часовых поясов

осторожно

Только Timezone GMT, UTC, CET, EET, HST, MST, EST работают валидно, во всех остальных случаях стоит пользоваться GMT/UTC (+-)XX:XX синтаксисом

Экранирование

Есть 2 возможности экранировать символы:

  • Экранировать надо через \\
  • Если надо использовать (или), то заменим кавычки " на ``, убираем экранирование " внутри строки, и добавляем экранирование на (и)

Пример:

Регулярное выражение или плагины в yaml

patterns:
# список паттернов для поиска
HTTP_ANSWER: "%{NOTSPACE:ECS.Service.Type}\\(%{NOTSPACE:ECS.Service.Name}:session\\): %{NOTSPACE:ECS.Event.Category} %{NOTSPACE:ECS.Event.Action} for user %{NOTSPACE:ECS.User.Name} by \\(uid=%{NOTSPACE:ECS.User.ID}\\)"
# вспомогательные паттерны, которые могут использоваться для "patterns",
# по умолчанию они не используются
definitions:
# список вспомогательных паттернов
# addition_info: "
# %{date(\"dd/MMM/yyyy\"):ECS.ELF.CreationDate}"

Пример исходного события

pam_unix(cron:session): session opened for user root by (uid=0)

Заполненные данные

ECS.Event.Action - opened

ECS.Event.Category - session

ECS.Service.Name - cron

ECS.Service.Type - pam_unix

ECS.User.ID - 0

ECS.User.Name - root

Standard

Есть паттерны по умолчанию, они отвечают за базовую нормализацию.

## COMMON LOG PATTERNS

BASE10NUM ([+-]?(?:[0-9]+(?:\.[0-9]+)?)|\.[0-9]+) //404
BASE16NUM (0[xX]?[0-9a-fA-F]+) //000000002
CISCOMAC (?:(?:[A-Fa-f0-9]{4}\.){2}[A-Fa-f0-9]{4}) //8041.a473.453b
CLIENT (?:%{IPV6}|%{IPV4}|%{HOSTNAME}|%{HOSTPORT}) //docs.etecs.ru
COMBINEDAPACHELOG %{COMMONAPACHELOG} %{QS:ECS.HTTP.RequestReferrer} %{QS:ECS.Observer.Name}
COMBINED_LOG_FORMAT %{COMMON_LOG_FORMAT} "%{DATA:ECS.HTTP.RequestReferrer}" "%{DATA:ECS.UserAgent.Original}"
COMMONAPACHELOG %{IPORHOST:ECS.Source.Address} %{USER:Ident} %{USER:Auth} \[%{HTTPDATE:CTime}\] "(?:%{WORD:ECS.HTTP.RequestMethod} %{NOTSPACE:ECS.HTTP.RequestBodyContent}(?: HTTP/%{NUMBER:ECS.HTTP.Version})?|%{DATA:ECS.HTTP.RequestBodyContent})" %{NUMBER:ECS.HTTP.ResponseStatusCode} (?:%{NUMBER:ECS.HTTP.ResponseBodyBytes}|-)
COMMONMAC (?:(?:[A-Fa-f0-9]{2}:){5}[A-Fa-f0-9]{2})
COMMON_LOG_FORMAT %{CLIENT:ECS.Source.IP} %{NOTSPACE:Ident} %{NOTSPACE:Auth} \[%{HTTPDATE:CTime:ts-httpd}\] "(?:%{WORD:ECS.HTTP.RequestMethod} %{NOTSPACE:ECS.HTTP.RequestBodyContent}(?: HTTP/%{NUMBER:ECS.HTTP.Version})?|%{DATA})" %{NUMBER:ECS.HTTP.ResponseStatusCode} (?:%{NUMBER:ECS.HTTP.ResponseBodyBytes}|-)
DATA .*?
DATE %{DATE_US}|%{DATE_EU}
DATESTAMP %{DATE}[- ]%{TIME}
DATESTAMP_OTHER %{DAY} %{MONTH} %{MONTHDAY} %{TIME} %{TZ} %{YEAR}
DATESTAMP_RFC822 %{DAY} %{MONTH} %{MONTHDAY} %{YEAR} %{TIME} %{TZ}
DATE_EU %{MONTHDAY}[./-]%{MONTHNUM}[./-]%{YEAR}
DATE_US %{MONTHNUM}[/-]%{MONTHDAY}[/-]%{YEAR} //11/5/2011
DAY (?:Mon(?:day)?|Tue(?:sday)?|Wed(?:nesday)?|Thu(?:rsday)?|Fri(?:day)?|Sat(?:urday)?|Sun(?:day)?)
DURATION %{NUMBER}[nuµm]?s
GREEDYDATA .*
HOST %{HOSTNAME} //docs.etecs.ru
HOSTNAME \b(?:[0-9A-Za-z][0-9A-Za-z-]{0,62})(?:\.(?:[0-9A-Za-z][0-9A-Za-z-]{0,62}))*(\.?|\b) //docs.etecs.ru
HOSTPORT %{IPORHOST}:%{POSINT}
HOUR (?:2[0123]|[01]?[0-9])
HTTPD20_ERRORLOG \[%{HTTPDERROR_DATE:CTime}\] \[%{LOGLEVEL:ECS.Log.Level}\] (?:\[client %{IPORHOST:ECS.Source.IP}\] ){0,1}%{GREEDYDATA:ECS.Base.Message}
HTTPD24_ERRORLOG \[%{HTTPDERROR_DATE:CTime}\] \[%{WORD:ECS.Event.Module}:%{LOGLEVEL:ECS.Log.Level}\] \[pid %{POSINT:ECS.Process.PID}:tid %{NUMBER:ECS.Process.ThreadID}\]( \(%{POSINT:Proxy.ErrorCode:int}\)%{DATA:Proxy.ErrorMessage}:)?( \[client %{IPORHOST:ECS.Source.Host}:%{POSINT:ECS.Source.Port}\])? %{DATA:ECS.HTTP.Error.Code}: %{GREEDYDATA:ECS.Base.Message}
HTTPDATE %{MONTHDAY}/%{MONTH}/%{YEAR}:%{TIME} %{INT}
HTTPDERROR_DATE %{DAY} %{MONTH} %{MONTHDAY} %{TIME} %{YEAR}
HTTPD_ERRORLOG %{HTTPD20_ERRORLOG}|%{HTTPD24_ERRORLOG}
INT (?:[+-]?(?:[0-9]+))
IP (?:%{IPV6}|%{IPV4})
IPORHOST (?:%{HOSTNAME}|%{IP})
IPV4 (?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?) //192.168.1.1
IPV6 ((([0-9A-Fa-f]{1,4}:){7}([0-9A-Fa-f]{1,4}|:))|(([0-9A-Fa-f]{1,4}:){6}(:[0-9A-Fa-f]{1,4}|((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3})|:))|(([0-9A-Fa-f]{1,4}:){5}(((:[0-9A-Fa-f]{1,4}){1,2})|:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3})|:))|(([0-9A-Fa-f]{1,4}:){4}(((:[0-9A-Fa-f]{1,4}){1,3})|((:[0-9A-Fa-f]{1,4})?:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){3}(((:[0-9A-Fa-f]{1,4}){1,4})|((:[0-9A-Fa-f]{1,4}){0,2}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){2}(((:[0-9A-Fa-f]{1,4}){1,5})|((:[0-9A-Fa-f]{1,4}){0,3}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){1}(((:[0-9A-Fa-f]{1,4}){1,6})|((:[0-9A-Fa-f]{1,4}){0,4}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(:(((:[0-9A-Fa-f]{1,4}){1,7})|((:[0-9A-Fa-f]{1,4}){0,5}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:)))(%.+)? //2001:0db8:85a3:0000:0000:8a2e:0370:7334
ISO8601_SECOND (?:%{SECOND}|60)
ISO8601_TIMEZONE (?:Z|[+-]%{HOUR}(?::?%{MINUTE}))
LOGLEVEL ([A-a]lert|ALERT|[T|t]race|TRACE|[D|d]ebug|DEBUG|[N|n]otice|NOTICE|[I|i]nfo|INFO|[W|w]arn?(?:ing)?|WARN?(?:ING)?|[E|e]rr?(?:or)?|ERR?(?:OR)?|[C|c]rit?(?:ical)?|CRIT?(?:ICAL)?|[F|f]atal|FATAL|[S|s]evere|SEVERE|EMERG(?:ENCY)?|[Ee]merg(?:ency)?)
MAC (?:%{CISCOMAC}|%{WINDOWSMAC}|%{COMMONMAC})
MINUTE (?:[0-5][0-9])
MONTH \b(?:Jan(?:uary)?|Feb(?:ruary)?|Mar(?:ch)?|Apr(?:il)?|May|Jun(?:e)?|Jul(?:y)?|Aug(?:ust)?|Sep(?:tember)?|Oct(?:ober)?|Nov(?:ember)?|Dec(?:ember)?)\b
MONTHDAY (?:(?:0[1-9])|(?:[12][0-9])|(?:3[01])|[1-9])
MONTHNUM (?:0?[1-9]|1[0-2])
NGUSER %{NGUSERNAME}
NGUSERNAME [a-zA-Z0-9\.\@\-\+_%]+
NONNEGINT \b(?:[0-9]+)\b
NOTSPACE \S+
NUMBER (?:%{BASE10NUM})
PATH (?:%{UNIXPATH}|%{WINPATH}) //C:\Windows\Logs или /home/echelon
POSINT \b(?:[1-9][0-9]*)\b
PROG (?:[\w._/%-]+)
QS %{QUOTEDSTRING}
QUOTEDSTRING "(**(\\.[^"\\]**)**)"|\'([^\'\\]**(\\.**)**)\'
RESPONSE_CODE %{NUMBER:ECS.HTTP.ResponseStatusCode}
RESPONSE_TIME %{DURATION:ECS.Event.Duration}
SECOND (?:(?:[0-5][0-9]|60)(?:[:.,][0-9]+)?)
SPACE \s*
SYSLOGBASE %{SYSLOGTIMESTAMP:CTime} (?:%{SYSLOGFACILITY} )?%{SYSLOGHOST:ECS.Host.Name} %{SYSLOGPROG}:
SYSLOGFACILITY <%{NONNEGINT:ECS.Log.SyslogFacilityCode}.%{NONNEGINT:ECS.Log.SyslogPriority}>
SYSLOGHOST %{IPORHOST}
SYSLOGPROG %{PROG:ECS.Process.Name}(?:\[%{POSINT:ECS.Process.PID}\])?
SYSLOGTIMESTAMP %{MONTH} +%{MONTHDAY} %{TIME}
TIME ([^0-9]?)%{HOUR}:%{MINUTE}(?::%{SECOND})([^0-9]?)
TIMESTAMP_ISO8601 %{YEAR}-%{MONTHNUM}-%{MONTHDAY}[T ]%{HOUR}:?%{MINUTE}(?::?%{SECOND})?%{ISO8601_TIMEZONE}?
TTY (?:/dev/(pts|tty([pq])?)(\w+)?/?(?:[0-9]+))
TZ (?:[PMCE][SD]T|UTC|GMT) //GMT
UNIXPATH (/[\w_%!$@:.,-]?/?)(\S+)? ///home/echelon
URI %{URIPROTO}://(?:%{USER}(?::[^@]*)?@)?(?:%{URIHOST})?(?:%{URIPATHPARAM})?
URIHOST %{IPORHOST}(?::%{POSINT:ECS.Source.Port})?
URIPARAM \?[A-Za-z0-9$.+!**'|(){},~@#%&/=:;_?\-\[\]]** //?application=&inf.name=eth0
URIPATH (?:/[A-Za-z0-9$.+!**'(){},~:;=@#%_\-]**)+ // //spinaltap.micro.umn.edu/00/Weather/California/Los%20Angeles
URIPATHPARAM %{URIPATH}(?:%{URIPARAM})? //s?application=&inf.name=eth0
URIPROTO [A-Za-z]+(\+[A-Za-z+]+)? //" http
USER %{USERNAME} //komrad
USERNAME [a-zA-Z0-9._-]+ //komrad
UUID [A-Fa-f0-9]{8}-(?:[A-Fa-f0-9]{4}-){3}[A-Fa-f0-9]{12} //9d3b594e-c94e-11ed-afa1-0242ac120002
WINDOWSMAC (?:(?:[A-Fa-f0-9]{2}-){5}[A-Fa-f0-9]{2}) //0A-00-27-00-00-11
WINPATH ([A-Za-z]:|\\)(?:\\[^\\?**]**)+ //C:\Windows\Logs
WORD \b\w+\b //komrad
YEAR (\d\d){1,2} //2023