Справочник по синтаксису 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"
| Последовательность экранирования | Литеральный символ |
|---|---|
| Новая строка (символ перевода строки) |
| Возврат каретки |
| Табуляция |
| Обратная косая черта ( |
| Двойная кавычка ( |
Можно экранировать 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 на основе последовательности соответствует этой последовательности упорядоченных событий:
-
Начните с события с:
- Категорией события
file - Значением
file.extensionравнымexe
- Категорией события
- За которым следует событие с категорией события
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")
Хотя это работает, это может быть избыточно и может замедлить скорость поиска. Для ускорения поиска можно сделать следующее:
- Добавьте новое поле,
file.extension, в индекс. Полеfile.extensionбудет содержать только расширение файла из поляfile.path. - Используйте трубу поступления данных, содержащую процессор
grokили другой инструмент предварительной обработки, для извлечения расширения файла из поляfile.pathперед индексированием. - Индексируйте извлеченное расширение файла в поле
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 не поддерживает:
-
Функции массивов:
- Функцию
match - Соединения
-
Ключевые слова, связанные с родословной:
-
child of -
descendant of -
event of
-
-
Следующие каналы:
-
Как запросы последовательностей обрабатывают совпадения
Запросы последовательностей не находят все потенциальные совпадения для последовательности. Такой подход слишком медленный и затратный для больших наборов данных событий. Вместо этого запрос последовательности обрабатывает ожидающие совпадения последовательности как конечный автомат:
- Каждый элемент события в запросе последовательности — состояние в автомате.
- Только одна ожидающая последовательность может быть в каждом состоянии одновременно.
- Если две ожидающие последовательности находятся в одном состоянии одновременно, более поздняя последовательность перезаписывает более раннюю.
- Если запрос включает
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"]
Чтобы найти совпадающие последовательности, запрос использует отдельные конечные автоматы для каждого уникального user.name значения. Основываясь на наборе данных, вы можете ожидать два конечных автомата: один для пользователя root и один для пользователя elkbee.
Ожидающие совпадения последовательностей перемещаются через состояния каждого автомата следующим образом:
{ "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