Spec-Zone.ru › Elasticsearch 7
›Руководство по Elasticsearch [7.17] ›Поиск EQL

Справочник по синтаксису EQL

Основной синтаксис

Запросы EQL требуют категории события и условия соответствия. Ключевое слово where соединяет их.

event_category where condition

Категория события — это индексированное значение поля категории события. По умолчанию API поиска EQL использует поле event.category из Elastic Common Schema (ECS). Вы можете указать другое поле категории события, используя параметр API event_category_field.

Например, следующий запрос EQL сопоставляет события с категорией события process и значением поля process.name равным svchost.exe:

process where process.name == "svchost.exe"

Сопоставление любой категории событий

Чтобы сопоставить события любой категории, используйте ключевое слово any. Вы также можете использовать ключевое слово any для поиска документов без поля категории события.

Например, следующий запрос EQL сопоставляет любые документы со значением поля network.protocol равным http:

any where network.protocol == "http"

Экранирование категории события

Используйте двойные кавычки (") или тройные двойные кавычки (""") для экранирования категорий событий, которые:

  • Содержат специальный символ, такой как дефис (-) или точку (.)
  • Содержат пробел
  • Начинаются с цифры
".my.event.category"
"my-event-category"
"my event category"
"6eventcategory"

""".my.event.category"""
"""my-event-category"""
"""my event category"""
"""6eventcategory"""

Экранирование имени поля

Используйте обратные кавычки (`) для экранирования имён полей, которые:

  • Содержат дефис (-)
  • Содержат пробел
  • Начинаются с цифры
`my-field`
`my field`
`6myfield`

Используйте двойные обратные кавычки (``) для экранирования обратных кавычек (`) в имени поля.

my`field -> `my``field`

Условия

Условие состоит из одного или нескольких критериев, которым должно соответствовать событие. Вы можете указать и комбинировать эти критерии, используя следующие операторы. Большинство операторов EQL по умолчанию чувствительны к регистру.

Операторы сравнения

<   <=   ==   :   !=   >=   >
< (меньше)
Возвращает true, если значение слева от оператора меньше значения справа. В противном случае возвращает false.
<= (меньше или равно)
Возвращает true, если значение слева от оператора меньше или равно значению справа. В противном случае возвращает false.
== (равно, чувствительно к регистру)
Возвращает true, если значения слева и справа от оператора равны. В противном случае возвращает false. Подстановочные знаки не поддерживаются.
: (равно, нечувствительно к регистру)
Возвращает true, если строки слева и справа от оператора равны. В противном случае возвращает false. Может использоваться только для сравнения строк. Поддерживает подстановочные знаки и поиски в списках.
!= (не равно, чувствительно к регистру)
Возвращает true, если значения слева и справа от оператора не равны. В противном случае возвращает false. Подстановочные знаки не поддерживаются.
>= (больше или равно)
Возвращает true, если значение слева от оператора больше или равно значению справа. В противном случае возвращает false. При сравнении строк оператор использует лексикографический порядок, чувствительный к регистру.
> (больше)
Возвращает true, если значение слева от оператора больше значения справа. В противном случае возвращает false. При сравнении строк оператор использует лексикографический порядок, чувствительный к регистру.

= не поддерживается как оператор равенства. Используйте == или : вместо него.

Ключевые слова для сравнения шаблонов

my_field like  "VALUE*"         // case-sensitive wildcard matching
my_field like~ "value*"         // case-insensitive wildcard matching

my_field regex  "VALUE[^Z].?"   // case-sensitive regex matching
my_field regex~ "value[^z].?"   // case-insensitive regex matching
like (чувствительно к регистру)
Возвращает true, если строка слева от ключевого слова соответствует шаблону подстановочных знаков справа. Поддерживает поиски в списках. Может использоваться только для сравнения строк. Для нечувствительного к регистру сопоставления используйте like~.
regex (чувствительно к регистру)
Возвращает true, если строка слева от ключевого слова соответствует регулярному выражению справа. Для поддерживаемого синтаксиса регулярных выражений см. Синтаксис регулярных выражений. Поддерживает поиски в списках. Может использоваться только для сравнения строк. Для нечувствительного к регистру сопоставления используйте regex~.
Ограничения для сравнений

Вы не можете объединять сравнения. Вместо этого используйте логический оператор между сравнениями. Например, foo < bar <= baz не поддерживается. Однако вы можете переписать выражение как foo < bar and bar <= baz, которое поддерживается.

Вы также не можете сравнивать одно поле с другим, даже если поля изменены с помощью функции.

Пример
Следующий запрос EQL сравнивает значение поля process.parent_name со статическим значением foo. Это сравнение поддерживается.

Однако запрос также сравнивает значение поля process.parent.name со значением поля process.name. Это сравнение не поддерживается и вернёт ошибку для всего запроса.

process where process.parent.name == "foo" and process.parent.name == process.name

Вместо этого вы можете переписать запрос, чтобы сравнить оба поля process.parent.name и process.name со статическими значениями.

process where process.parent.name == "foo" and process.name == "foo"

Логические операторы

and  or  not
and
Возвращает true только если условие слева и справа оба возвращают true. В противном случае возвращает false.
or
Возвращает true, если одно из условий слева или справа true. В противном случае возвращает false.
not
Возвращает true, если условие справа false.

Операторы поиска

my_field in ("Value-1", "VALUE2", "VAL3")                 // case-sensitive
my_field in~ ("value-1", "value2", "val3")                // case-insensitive

my_field not in ("Value-1", "VALUE2", "VAL3")             // case-sensitive
my_field not in~ ("value-1", "value2", "val3")            // case-insensitive

my_field : ("value-1", "value2", "val3")                  // case-insensitive

my_field like  ("Value-*", "VALUE2", "VAL?")              // case-sensitive
my_field like~ ("value-*", "value2", "val?")              // case-insensitive

my_field regex  ("[vV]alue-[0-9]", "VALUE[^2].?", "VAL3") // case-sensitive
my_field regex~  ("value-[0-9]", "value[^2].?", "val3")   // case-sensitive
in (чувствительно к регистру)
Возвращает true, если значение содержится в предоставленном списке. Для нечувствительного к регистру сопоставления используйте in~.
not in (чувствительно к регистру)
Возвращает true, если значение не содержится в предоставленном списке. Для нечувствительного к регистру сопоставления используйте not in~.
: (нечувствительно к регистру)
Возвращает true, если строка содержится в предоставленном списке. Может использоваться только для сравнения строк.
like (чувствительно к регистру)
Возвращает true, если строка соответствует шаблону подстановочных знаков в предоставленном списке. Может использоваться только для сравнения строк. Для нечувствительного к регистру сопоставления используйте like~.
regex (чувствительно к регистру)
Возвращает true, если строка соответствует шаблону регулярного выражения в предоставленном списке. Для поддерживаемого синтаксиса регулярных выражений см. Синтаксис регулярных выражений. Может использоваться только для сравнения строк. Для нечувствительного к регистру сопоставления используйте regex~.

Математические операторы

+  -  *  /  %
+ (сложение)
Складывает значения слева и справа от оператора.
- (вычитание)
Вычитает значение справа от оператора из значения слева.
* (умножение)
Умножает значения слева и справа от оператора.
/ (деление)

Делит значение слева от оператора на значение справа.

Если и делимое, и делитель — целые числа, операция деления (\) округляет любые возвращаемые числа с плавающей точкой до ближайшего целого в меньшую сторону. Чтобы избежать округления, преобразуйте делимое или делитель в число с плавающей точкой.

Пример
Поле process.args_count — целое числовое поле long, содержащее количество аргументов процесса.

Пользователь, вероятно, ожидает, что следующий запрос EQL будет соответствовать только событиям со значением process.args_count равным 4.

process where ( 4 / process.args_count ) == 1

Однако запрос EQL соответствует событиям со значением process.args_count равным 3 или 4.

Для событий со значением process.args_count равным 3 операция деления возвращает число с плавающей точкой 1.333..., которое округляется до 1.

Чтобы соответствовать только событиям со значением process.args_count равным 4, преобразуйте либо делимое, либо делитель в число с плавающей точкой.

Следующий запрос EQL изменяет целое число 4 на эквивалентное число с плавающей точкой 4.0.

process where ( 4.0 / process.args_count ) == 1
% (остаток от деления)
Делит значение слева от оператора на значение справа. Возвращает только остаток.

Соответствие любому условию

Для соответствия событиям только по категории события используйте условие where true.

Например, следующий запрос EQL соответствует любым событиям file:

file where true

Для соответствия любому событию можно объединить ключевое слово any с условием where true:

any where true

Необязательные поля

По умолчанию запрос EQL может содержать только поля, которые существуют в наборе данных, по которому выполняется поиск. Поле существует в наборе данных, если оно имеет явное, динамическое или динамическое отображение. Если запрос EQL содержит поле, которого нет, он возвращает ошибку.

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

Пример
В следующем запросе поле user.id необязательное.

network where ?user.id != null

Если поле user.id существует в наборе данных, по которому выполняется поиск, запрос соответствует любому событию network, содержащему значение user.id. Если поле user.id не существует в наборе данных, EQL интерпретирует запрос как:

network where null != null

В этом случае запрос не соответствует ни одному событию.

Проверка существования поля

Чтобы соответствовать событиям, содержащим любое значение для поля, сравните поле с null с использованием оператора !=:

?my_field != null

Чтобы соответствовать событиям, не содержащим значения поля, сравните поле с null с использованием оператора ==:

?my_field == null

Строки

Строки заключены в двойные кавычки (").

"hello world"

Строки в одинарных кавычках (') не поддерживаются.

Символы экранирования в строке

При использовании в строке специальные символы, такие как возврат каретки или двойные кавычки ("), должны быть экранированы предшествующей обратной косой чертой (\).

"example \r of \" escaped \n characters"
Последовательность экранирования Литеральный символ

\n

Новая строка (символ перевода строки)

\r

Возврат каретки

\t

Табуляция

\\

Обратная косая черта (\)

\"

Двойная кавычка (")

Можно экранировать Unicode-символы, используя шестнадцатеричную последовательность экранирования \u{XXXXXXXX}. Шестнадцатеричное значение может иметь длину от 2 до 8 символов и регистронезависимо. Значения, короче 8 символов, дополняются нулями. Эти последовательности экранирования можно использовать для включения непечатаемых или символов с направлением справа налево (RTL) в ваши строки. Например, можно экранировать маркер справа налево (RLM) как \u{200f}, \u{200F} или \u{0000200f}.

Символ одинарной кавычки (') зарезервирован для будущего использования. Вы не можете использовать экранированную одинарную кавычку (\') для литеральных строк. Используйте вместо этого экранированную двойную кавычку (\").

Необработанные строки

Необработанные строки рассматривают специальные символы, такие как обратные косые черты (\), как литеральные символы. Необработанные строки заключены в три двойные кавычки (""").

"""Raw string with a literal double quote " and blackslash \ included"""

Необработанная строка не может содержать три последовательных двойные кавычки ("""). Вместо этого используйте обычную строку с последовательностью экранирования \".

"String containing \"\"\" three double quotes"

Подстановочные знаки

При сравнении строк с использованием оператора : или ключевого слова like можно использовать подстановочные знаки * и ? для сопоставления определённых шаблонов. Подстановочный знак * соответствует нулю или более символам:

my_field : "doc*"     // Matches "doc", "docs", or "document" but not "DOS"
my_field : "*doc"     // Matches "adoc" or "asciidoc"
my_field : "d*c"      // Matches "doc" or "disc"

my_field like "DOC*"  // Matches "DOC", "DOCS", "DOCs", or "DOCUMENT" but not "DOS"
my_field like "D*C"   // Matches "DOC", "DISC", or "DisC"

Подстановочный знак ? соответствует ровно одному символу:

my_field : "doc?"     // Matches "docs" but not "doc", "document", or "DOS"
my_field : "?doc"     // Matches "adoc" but not "asciidoc"
my_field : "d?c"      // Matches "doc" but not "disc"

my_field like "DOC?"  // Matches "DOCS" or "DOCs" but not "DOC", "DOCUMENT", or "DOS"
my_field like "D?c"   // Matches "DOC" but not "DISC"

Оператор : и ключевое слово like также поддерживают подстановочные знаки в поиске по спискам:

my_field : ("doc*", "f*o", "ba?", "qux")
my_field like ("Doc*", "F*O", "BA?", "QUX")

Последовательности

Вы можете использовать последовательности EQL для описания и сопоставления упорядоченной последовательности событий. Каждый элемент последовательности — это категория события и условие события, заключенные в квадратные скобки ([ ]). События перечислены в хронологическом порядке, начиная с самого последнего.

sequence
  [ event_category_1 where condition_1 ]
  [ event_category_2 where condition_2 ]
  ...

Пример
Следующий запрос EQL на основе последовательности соответствует этой последовательности упорядоченных событий:

  1. Начните с события с:

    • Категорией события file
    • Значением file.extension равным exe
  2. За которым следует событие с категорией события process
sequence
  [ file where file.extension == "exe" ]
  [ process where true ]

with maxspan оператор

Можно использовать with maxspan для ограничения последовательности заданным временным интервалом. Все события в соответствующей последовательности должны произойти в течение этого интервала, начиная со временной метки первого события.

maxspan принимает аргументы единиц времени.

sequence with maxspan=30s
  [ event_category_1 where condition_1 ] by field_baz
  [ event_category_2 where condition_2 ] by field_bar
  ...

Пример
Следующий запрос последовательности использует значение maxspan равное 15m (15 минут). События в соответствующей последовательности должны произойти в течение 15 минут от временной метки первого события.

sequence with maxspan=15m
  [ file where file.extension == "exe" ]
  [ process where true ]

by ключевое слово

Используйте ключевое слово by в запросе последовательности, чтобы соответствовать только событиям, которые имеют одинаковые значения, даже если эти значения находятся в разных полях. Эти общие значения называются ключами объединения. Если ключ объединения должен находиться в одном поле для всех событий, используйте sequence by.

sequence by field_foo
  [ event_category_1 where condition_1 ] by field_baz
  [ event_category_2 where condition_2 ] by field_bar
  ...

Пример
Следующий запрос последовательности использует ключевое слово by, чтобы ограничить соответствующие события:

  • Событиями с одинаковым значением user.name
  • Событиями file со значением file.path равным значению поля process последующего события process.executable.
sequence
  [ file where file.extension == "exe" ] by user.name, file.path
  [ process where true ] by user.name, process.executable

Поскольку поле user.name используется во всех событиях последовательности, его можно включить с помощью sequence by. Следующая последовательность эквивалентна предыдущей.

sequence by user.name
  [ file where file.extension == "exe" ] by file.path
  [ process where true ] by process.executable

Вы можете комбинировать sequence by и with maxspan для ограничения последовательности как значениями полей, так и временным интервалом.

sequence by field_foo with maxspan=30s
  [ event_category_1 where condition_1 ]
  [ event_category_2 where condition_2 ]
  ...

Пример
Следующий запрос последовательности использует sequence by и with maxspan, чтобы сопоставлять только последовательность событий, которые:

  • Имеют одинаковые значения поля user.name
  • Произошли в течение 15m (15 минут) от первого сопоставленного события
sequence by user.name with maxspan=15m
  [ file where file.extension == "exe" ]
  [ process where true ]

Дополнительные поля by

По умолчанию ключ объединения должен быть значением поля, не являющегося null. Чтобы разрешить ключи объединения null, используйте оператор ? для обозначения поля by как необязательного. Это также полезно, если вы не уверены, содержит ли набор данных, который вы ищете, поле by.

Пример
Следующий запрос последовательности использует sequence by, чтобы ограничить сопоставленные события:

  • События с одинаковым значением поля process.pid, исключая значения null. Если поле process.pid не существует в наборе данных, который вы ищете, запрос возвращает ошибку.
  • События с одинаковым значением поля process.entity_id, включая значения null. Если событие не содержит поле process.entity_id, его значение process.entity_id считается null. Это относится даже если поле process.pid не существует в наборе данных, который вы ищете.
sequence by process.pid, ?process.entity_id
  [process where process.name == "regsvr32.exe"]
  [network where true]

until ключевое слово

Вы можете использовать ключевое слово until, чтобы указать событие истечения срока действия для последовательности. Если это событие истечения срока действия происходит между сопоставленными событиями в последовательности, последовательность истекает и не считается соответствием. Если событие истечения срока действия происходит после сопоставленных событий в последовательности, последовательность по-прежнему считается соответствием. Событие истечения срока действия не включается в результаты.

sequence
  [ event_category_1 where condition_1 ]
  [ event_category_2 where condition_2 ]
  ...
until [ event_category_3 where condition_3 ]

Пример
Набор данных содержит следующие последовательности событий, сгруппированные по общим идентификаторам:

A, B
A, B, C
A, C, B

Следующий запрос EQL ищет в наборе данных последовательности, содержащие событие A, за которым следует событие B. Событие C используется как событие истечения срока действия.

sequence by ID
  A
  B
until C

Запрос соответствует последовательностям A, B и A, B, C, но не A, C, B.

Ключевое слово until может быть полезным при поиске последовательностей процессов в журналах событий Windows.

В Windows идентификатор процесса (PID) уникален только во время работы процесса. После завершения процесса его PID может быть повторно использован.

Вы можете искать последовательность событий с одинаковым значением PID, используя ключевые слова by и sequence by.

Пример
Следующий запрос EQL использует ключевое слово sequence by, чтобы сопоставить последовательность событий, которые имеют одинаковое значение process.pid.

sequence by process.pid
  [ process where event.type == "start" and process.name == "cmd.exe" ]
  [ process where file.extension == "exe" ]

Однако из-за повторного использования PID это может привести к сопоставленной последовательности, которая содержит события, относящиеся к разным процессам. Чтобы предотвратить ложные срабатывания, вы можете использовать ключевое слово until, чтобы завершить сопоставление последовательностей перед событием завершения процесса.

Следующий запрос EQL использует ключевое слово until, чтобы завершать последовательности перед событиями process со значением event.type, равным stop. Эти события указывают на завершение процесса.

sequence by process.pid
  [ process where event.type == "start" and process.name == "cmd.exe" ]
  [ process where file.extension == "exe" ]
until [ process where event.type == "stop" ]

with runs оператор

Используйте оператор with runs для последовательного выполнения одних и тех же критериев событий в запросе последовательности. Например:

sequence
  [ process where event.type == "creation" ]
  [ library where process.name == "regsvr32.exe" ] with runs=3
  [ registry where true ]

эквивалентно:

sequence
  [ process where event.type == "creation" ]
  [ library where process.name == "regsvr32.exe" ]
  [ library where process.name == "regsvr32.exe" ]
  [ library where process.name == "regsvr32.exe" ]
  [ registry where true ]

Значение runs должно быть между 1 и 100 (включительно).

Вы можете использовать оператор with runs с ключевым словом by. Например:

sequence
  [ process where event.type == "creation" ] by process.executable
  [ library where process.name == "regsvr32.exe" ] by dll.path with runs=3

Функции

Вы можете использовать функции EQL для преобразования типов данных, выполнения математических операций, манипулирования строками и т. д. Список поддерживаемых функций см. в Справочнике по функциям.

Функции без учета регистра

Большинство функций EQL по умолчанию чувствительны к регистру. Чтобы сделать функцию нечувствительной к регистру, используйте оператор ~ после имени функции:

stringContains(process.name,".exe")  // Matches ".exe" but not ".EXE" or ".Exe"
stringContains~(process.name,".exe") // Matches ".exe", ".EXE", or ".Exe"

Влияние функций на производительность поиска

Использование функций в запросах EQL может привести к замедлению скорости поиска. Если вы часто используете функции для преобразования индексированных данных, вы можете ускорить поиск, внеся эти изменения во время индексирования. Однако это часто означает замедление скорости индексирования.

Пример
Индекс содержит поле file.path. file.path содержит полный путь к файлу, включая расширение файла.

При выполнении поисков EQL пользователи часто используют функцию endsWith с полем file.path для сопоставления расширений файлов:

file where endsWith(file.path,".exe") or endsWith(file.path,".dll")

Хотя это работает, это может быть избыточно и может замедлить скорость поиска. Для ускорения поиска можно сделать следующее:

  1. Добавьте новое поле, file.extension, в индекс. Поле file.extension будет содержать только расширение файла из поля file.path.
  2. Используйте трубу поступления данных, содержащую процессор grok или другой инструмент предварительной обработки, для извлечения расширения файла из поля file.path перед индексированием.
  3. Индексируйте извлеченное расширение файла в поле file.extension.

Эти изменения могут замедлить индексирование, но позволят ускорить поиск. Пользователи могут использовать поле file.extension вместо нескольких вызовов функции endsWith:

file where file.extension in ("exe", "dll")

Рекомендуется тестировать и проводить бенчмаркинг любых изменений индексирования перед их развертыванием в рабочей среде. См. Настройка для скорости индексирования и Настройка для скорости поиска.

Трубы

Трубы EQL фильтруют, агрегируют и обрабатывают события, возвращаемые запросом EQL. Вы можете использовать трубы для сужения результатов запроса EQL или сделать их более конкретными.

Трубы разделяются с помощью символа трубы (|).

event_category where condition | pipe

Пример
Следующий запрос EQL использует трубу tail, чтобы вернуть только 10 самых последних событий, соответствующих запросу.

authentication where agent.id == 4624
| tail 10

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

Список поддерживаемых труб см. в Справочнике по трубам.

Ограничения

EQL имеет следующие ограничения.

EQL использует параметр fields

EQL извлекает значения полей с помощью параметра API поиска fields. Любые ограничения параметра fields также применяются к запросам EQL. Например, если _source отключен для любых возвращаемых полей или на уровне индекса, значения нельзя получить.

Сравнение полей

Вы не можете использовать операторы сравнения EQL для сравнения поля с другим полем. Это относится даже если поля изменены с помощью функции.

Поля типа текста не поддерживаются

Поиск EQL не поддерживает поля типа text. Чтобы выполнить поиск по полю text, используйте параметр API поиска EQL filter.

EQL-поиск по вложенным полям

Вы не можете использовать EQL для поиска значений поля типа nested или подполей поля nested. Однако потоки данных и индексы, содержащие отображения полей nested, в противном случае поддерживаются.

Отличия от синтаксиса Endgame EQL

Elasticsearch EQL отличается от синтаксиса Elasticsearch Endgame EQL следующим образом:

  • В Elasticsearch EQL большинство операторов чувствительны к регистру. Например, process_name == "cmd.exe" не эквивалентно process_name == "Cmd.exe".
  • В Elasticsearch EQL функции чувствительны к регистру. Чтобы сделать функцию нечувствительной к регистру, используйте ~, например, endsWith~(process_name, ".exe").
  • Для сравнения на равенство, нечувствительного к регистру, используйте оператор :. Оба * и ? являются признанными символами подстановочных значений.
  • Операторы == и != не расширяют символы подстановки. Например, process_name == "cmd*.exe" интерпретирует * как буквенный символ звёздочки, а не как символ подстановки.
  • Для сопоставления с подстановкой используйте ключевое слово like при чувствительности к регистру и like~ при нечувствительности к регистру. Оператор : эквивалентен like~.
  • Для сопоставления с регулярными выражениями используйте regex или regex~.
  • = нельзя заменить оператором ==.
  • Строки в одинарных кавычках (') не поддерживаются. Используйте двойные кавычки (") вместо них.
  • ?" и ?' не обозначают сырые строки. Используйте тройные двойные кавычки (""") вместо них.
  • Elasticsearch EQL не поддерживает:

    • Функции массивов:

      • arrayContains
      • arrayCount
      • arraySearch
    • Функцию match
    • Соединения
    • Ключевые слова, связанные с родословной:

      • child of
      • descendant of
      • event of
    • Следующие каналы:

      • count
      • filter
      • sort
      • unique
      • unique_count

Как запросы последовательностей обрабатывают совпадения

Запросы последовательностей не находят все потенциальные совпадения для последовательности. Такой подход слишком медленный и затратный для больших наборов данных событий. Вместо этого запрос последовательности обрабатывает ожидающие совпадения последовательности как конечный автомат:

  • Каждый элемент события в запросе последовательности — состояние в автомате.
  • Только одна ожидающая последовательность может быть в каждом состоянии одновременно.
  • Если две ожидающие последовательности находятся в одном состоянии одновременно, более поздняя последовательность перезаписывает более раннюю.
  • Если запрос включает by поля, запрос использует отдельный конечный автомат для каждого уникального by значения поля.
Пример

Набор данных содержит следующие process события в возрастающем хронологическом порядке:

{ "index" : { "_id": "1" } }
{ "user": { "name": "root" }, "process": { "name": "attrib" }, ...}
{ "index" : { "_id": "2" } }
{ "user": { "name": "root" }, "process": { "name": "attrib" }, ...}
{ "index" : { "_id": "3" } }
{ "user": { "name": "elkbee" }, "process": { "name": "bash" }, ...}
{ "index" : { "_id": "4" } }
{ "user": { "name": "root" }, "process": { "name": "bash" }, ...}
{ "index" : { "_id": "5" } }
{ "user": { "name": "root" }, "process": { "name": "bash" }, ...}
{ "index" : { "_id": "6" } }
{ "user": { "name": "elkbee" }, "process": { "name": "attrib" }, ...}
{ "index" : { "_id": "7" } }
{ "user": { "name": "root" }, "process": { "name": "attrib" }, ...}
{ "index" : { "_id": "8" } }
{ "user": { "name": "elkbee" }, "process": { "name": "bash" }, ...}
{ "index" : { "_id": "9" } }
{ "user": { "name": "root" }, "process": { "name": "cat" }, ...}
{ "index" : { "_id": "10" } }
{ "user": { "name": "elkbee" }, "process": { "name": "cat" }, ...}
{ "index" : { "_id": "11" } }
{ "user": { "name": "root" }, "process": { "name": "cat" }, ...}

Запрос последовательности EQL ищет совпадения в наборе данных:

sequence by user.name
  [process where process.name == "attrib"]
  [process where process.name == "bash"]
  [process where process.name == "cat"]

Элементы события запроса соответствуют следующим состояниям:

  • Состояние A: [process where process.name == "attrib"]
  • Состояние B: [process where process.name == "bash"]
  • Завершённое: [process where process.name == "cat"]
sequence state machine

Чтобы найти совпадающие последовательности, запрос использует отдельные конечные автоматы для каждого уникального user.name значения. Основываясь на наборе данных, вы можете ожидать два конечных автомата: один для пользователя root и один для пользователя elkbee.

separate state machines

Ожидающие совпадения последовательностей перемещаются через состояния каждого автомата следующим образом:

{ "index" : { "_id": "1" } }
{ "user": { "name": "root" }, "process": { "name": "attrib" }, ...}
// Creates sequence [1] in state A for the "root" user.
//
// +------------------------"root"------------------------+
// |  +-----------+     +-----------+     +------------+  |
// |  |  State A  |     |  State B  |     |  Complete  |  |
// |  +-----------+     +-----------+     +------------+  |
// |  |    [1]    |     |           |     |            |  |
// |  +-----------+     +-----------+     +------------+  |
// +------------------------------------------------------+

{ "index" : { "_id": "2" } }
{ "user": { "name": "root" }, "process": { "name": "attrib" }, ...}
// Creates sequence [2] in state A for "root", overwriting sequence [1].
//
// +------------------------"root"------------------------+
// |  +-----------+     +-----------+     +------------+  |
// |  |  State A  |     |  State B  |     |  Complete  |  |
// |  +-----------+     +-----------+     +------------+  |
// |  |    [2]    |     |           |     |            |  |
// |  +-----------+     +-----------+     +------------+  |
// +------------------------------------------------------+

{ "index" : { "_id": "3" } }
{ "user": { "name": "elkbee" }, "process": { "name": "bash" }, ...}
// Nothing happens. The "elkbee" user has no pending sequence to move
// from state A to state B.
//
// +-----------------------"elkbee"-----------------------+
// |  +-----------+     +-----------+     +------------+  |
// |  |  State A  |     |  State B  |     |  Complete  |  |
// |  +-----------+     +-----------+     +------------+  |
// |  |           |     |           |     |            |  |
// |  +-----------+     +-----------+     +------------+  |
// +------------------------------------------------------+

{ "index" : { "_id": "4" } }
{ "user": { "name": "root" }, "process": { "name": "bash" }, ...}
// Sequence [2] moves out of state A for "root".
// State B for "root" now contains [2, 4].
// State A for "root" is empty.
//
// +------------------------"root"------------------------+
// |  +-----------+     +-----------+     +------------+  |
// |  |  State A  |     |  State B  |     |  Complete  |  |
// |  +-----------+ --> +-----------+     +------------+  |
// |  |           |     |   [2, 4]  |     |            |  |
// |  +-----------+     +-----------+     +------------+  |
// +------------------------------------------------------+

{ "index" : { "_id": "5" } }
{ "user": { "name": "root" }, "process": { "name": "bash" }, ...}
// Nothing happens. State A is empty for "root".
//
// +------------------------"root"------------------------+
// |  +-----------+     +-----------+     +------------+  |
// |  |  State A  |     |  State B  |     |  Complete  |  |
// |  +-----------+     +-----------+     +------------+  |
// |  |           |     |   [2, 4]  |     |            |  |
// |  +-----------+     +-----------+     +------------+  |
// +------------------------------------------------------+

{ "index" : { "_id": "6" } }
{ "user": { "name": "elkbee" }, "process": { "name": "attrib" }, ...}
// Creates sequence [6] in state A for "elkbee".
//
// +-----------------------"elkbee"-----------------------+
// |  +-----------+     +-----------+     +------------+  |
// |  |  State A  |     |  State B  |     |  Complete  |  |
// |  +-----------+     +-----------+     +------------+  |
// |  |    [6]    |     |           |     |            |  |
// |  +-----------+     +-----------+     +------------+  |
// +------------------------------------------------------+

{ "index" : { "_id": "7" } }
{ "user": { "name": "root" }, "process": { "name": "attrib" }, ...}
// Creates sequence [7] in state A for "root".
// Sequence [2, 4] remains in state B for "root".
//
// +------------------------"root"------------------------+
// |  +-----------+     +-----------+     +------------+  |
// |  |  State A  |     |  State B  |     |  Complete  |  |
// |  +-----------+     +-----------+     +------------+  |
// |  |    [7]    |     |   [2, 4]  |     |            |  |
// |  +-----------+     +-----------+     +------------+  |
// +------------------------------------------------------+

{ "index" : { "_id": "8" } }
{ "user": { "name": "elkbee" }, "process": { "name": "bash" }, ...}
// Sequence [6, 8] moves to state B for "elkbee".
// State A for "elkbee" is now empty.
//
// +-----------------------"elkbee"-----------------------+
// |  +-----------+     +-----------+     +------------+  |
// |  |  State A  |     |  State B  |     |  Complete  |  |
// |  +-----------+ --> +-----------+     +------------+  |
// |  |           |     |   [6, 8]  |     |            |  |
// |  +-----------+     +-----------+     +------------+  |
// +------------------------------------------------------+

{ "index" : { "_id": "9" } }
{ "user": { "name": "root" }, "process": { "name": "cat" }, ...}
// Sequence [2, 4, 9] is complete for "root".
// State B for "root" is now empty.
// Sequence [7] remains in state A.
//
// +------------------------"root"------------------------+
// |  +-----------+     +-----------+     +------------+  |
// |  |  State A  |     |  State B  |     |  Complete  |  |
// |  +-----------+     +-----------+ --> +------------+  |
// |  |    [7]    |     |           |     |  [2, 4, 9] |
// |  +-----------+     +-----------+     +------------+  |
// +------------------------------------------------------+

{ "index" : { "_id": "10" } }
{ "user": { "name": "elkbee" }, "process": { "name": "cat" }, ...}
// Sequence [6, 8, 10] is complete for "elkbee".
// State A and B for "elkbee" are now empty.
//
// +-----------------------"elkbee"-----------------------+
// |  +-----------+     +-----------+     +------------+  |
// |  |  State A  |     |  State B  |     |  Complete  |  |
// |  +-----------+     +-----------+ --> +------------+  |
// |  |           |     |           |     | [6, 8, 10] |
// |  +-----------+     +-----------+     +------------+  |
// +------------------------------------------------------+

{ "index" : { "_id": "11" } }
{ "user": { "name": "root" }, "process": { "name": "cat" }, ...}
// Nothing happens.
// The machines for "root" and "elkbee" remain the same.
//
// +------------------------"root"------------------------+
// |  +-----------+     +-----------+     +------------+  |
// |  |  State A  |     |  State B  |     |  Complete  |  |
// |  +-----------+     +-----------+     +------------+  |
// |  |    [7]    |     |           |     |  [2, 4, 9] |
// |  +-----------+     +-----------+     +------------+  |
// +------------------------------------------------------+
//
// +-----------------------"elkbee"-----------------------+
// |  +-----------+     +-----------+     +------------+  |
// |  |  State A  |     |  State B  |     |  Complete  |  |
// |  +-----------+     +-----------+     +------------+  |
// |  |           |     |           |     | [6, 8, 10] |
// |  +-----------+     +-----------+     +------------+  |
// +------------------------------------------------------+

© 2023-2025 Elasticsearch
As of September 2024, Elasticsearch is available under a choice of three licenses: the Server Side Public License (SSPL), the Elastic License, or the AGPLv3 (OSI approved).
Elasticsearch and the Elasticsearch logo are trademarks of Elasticsearch B.V., registered in the U.S. and in other countries.
https://www.elastic.co/guide/en/elasticsearch/reference/7.17/eql-syntax.html

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API