Spec-Zone.ru › Elasticsearch 8
›Руководство по Elasticsearch [8.17]

Поиск с помощью EQL

Язык запросов событий (EQL) — это язык запросов для данных временных рядов на основе событий, таких как журналы, метрики и трассы.

Преимущества EQL

  • EQL позволяет выражать отношения между событиями.
    Многие языки запросов позволяют сопоставлять отдельные события. EQL позволяет сопоставлять последовательность событий по разным категориям событий и временным интервалам.
  • EQL имеет небольшой порог вхождения.
    Синтаксис EQL похож на другие распространённые языки запросов, такие как SQL. EQL позволяет интуитивно писать и читать запросы, что обеспечивает быстрый и итеративный поиск.
  • EQL разработан для использования в задачах безопасности.
    Хотя его можно использовать для любых данных на основе событий, EQL мы создали для охоты за угрозами. EQL поддерживает не только поиск индикаторов компрометации (IOC), но и может описывать активность, выходящую за рамки IOC.

Необходимые поля

За исключением примерных запросов, запросы EQL требуют, чтобы в потоке или индексе данных, которые ищутся, существовало поле timestamp. По умолчанию EQL использует поле @timestamp из Elastic Common Schema (ECS).

Запросы EQL также требуют поля категории события, если вы не используете ключевое слово any для поиска документов без поля категории события. По умолчанию EQL использует поле ECS event.category.

Чтобы использовать другое поле timestamp или категорию события, см. Указание поля timestamp или категории события.

Хотя для использования EQL схема не требуется, мы рекомендуем использовать ECS. Запросы EQL по умолчанию разработаны для работы с основными полями ECS.

Выполнение поиска EQL

Используйте API поиска EQL для выполнения базового запроса EQL.

resp = client.eql.search(
    index="my-data-stream",
    query="\n    process where process.name == \"regsvr32.exe\"\n  ",
)
print(resp)
response = client.eql.search(
  index: 'my-data-stream',
  body: {
    query: "\n    process where process.name == \"regsvr32.exe\"\n  "
  }
)
puts response
const response = await client.eql.search({
  index: "my-data-stream",
  query: '\n    process where process.name == "regsvr32.exe"\n  ',
});
console.log(response);
GET /my-data-stream/_eql/search
{
  "query": """
    process where process.name == "regsvr32.exe"
  """
}

По умолчанию базовые запросы EQL возвращают 10 самых последних совпадающих событий в свойстве hits.events. Эти совпадения сортируются по timestamp, преобразованному в миллисекунды с момента эпохи Unix, в порядке возрастания.

{
  "is_partial": false,
  "is_running": false,
  "took": 60,
  "timed_out": false,
  "hits": {
    "total": {
      "value": 2,
      "relation": "eq"
    },
    "events": [
      {
        "_index": ".ds-my-data-stream-2099.12.07-000001",
        "_id": "OQmfCaduce8zoHT93o4H",
        "_source": {
          "@timestamp": "2099-12-07T11:07:09.000Z",
          "event": {
            "category": "process",
            "id": "aR3NWVOs",
            "sequence": 4
          },
          "process": {
            "pid": 2012,
            "name": "regsvr32.exe",
            "command_line": "regsvr32.exe  /s /u /i:https://...RegSvr32.sct scrobj.dll",
            "executable": "C:\\Windows\\System32\\regsvr32.exe"
          }
        }
      },
      {
        "_index": ".ds-my-data-stream-2099.12.07-000001",
        "_id": "xLkCaj4EujzdNSxfYLbO",
        "_source": {
          "@timestamp": "2099-12-07T11:07:10.000Z",
          "event": {
            "category": "process",
            "id": "GTSmSqgz0U",
            "sequence": 6,
            "type": "termination"
          },
          "process": {
            "pid": 2012,
            "name": "regsvr32.exe",
            "executable": "C:\\Windows\\System32\\regsvr32.exe"
          }
        }
      }
    ]
  }
}

Используйте параметр size, чтобы получить меньшее или большее количество совпадений:

resp = client.eql.search(
    index="my-data-stream",
    query="\n    process where process.name == \"regsvr32.exe\"\n  ",
    size=50,
)
print(resp)
const response = await client.eql.search({
  index: "my-data-stream",
  query: '\n    process where process.name == "regsvr32.exe"\n  ',
  size: 50,
});
console.log(response);
GET /my-data-stream/_eql/search
{
  "query": """
    process where process.name == "regsvr32.exe"
  """,
  "size": 50
}

Поиск последовательности событий

Используйте синтаксис последовательностей EQL sequence syntax, чтобы найти серию упорядоченных событий. Перечислите элементы события в восходящем хронологическом порядке, расположив самое последнее событие в конце списка:

resp = client.eql.search(
    index="my-data-stream",
    query="\n    sequence\n      [ process where process.name == \"regsvr32.exe\" ]\n      [ file where stringContains(file.name, \"scrobj.dll\") ]\n  ",
)
print(resp)
const response = await client.eql.search({
  index: "my-data-stream",
  query:
    '\n    sequence\n      [ process where process.name == "regsvr32.exe" ]\n      [ file where stringContains(file.name, "scrobj.dll") ]\n  ',
});
console.log(response);
GET /my-data-stream/_eql/search
{
  "query": """
    sequence
      [ process where process.name == "regsvr32.exe" ]
      [ file where stringContains(file.name, "scrobj.dll") ]
  """
}

Свойство ответа hits.sequences содержит 10 последних совпадающих последовательностей.

{
  ...
  "hits": {
    "total": ...,
    "sequences": [
      {
        "events": [
          {
            "_index": ".ds-my-data-stream-2099.12.07-000001",
            "_id": "OQmfCaduce8zoHT93o4H",
            "_source": {
              "@timestamp": "2099-12-07T11:07:09.000Z",
              "event": {
                "category": "process",
                "id": "aR3NWVOs",
                "sequence": 4
              },
              "process": {
                "pid": 2012,
                "name": "regsvr32.exe",
                "command_line": "regsvr32.exe  /s /u /i:https://...RegSvr32.sct scrobj.dll",
                "executable": "C:\\Windows\\System32\\regsvr32.exe"
              }
            }
          },
          {
            "_index": ".ds-my-data-stream-2099.12.07-000001",
            "_id": "yDwnGIJouOYGBzP0ZE9n",
            "_source": {
              "@timestamp": "2099-12-07T11:07:10.000Z",
              "event": {
                "category": "file",
                "id": "tZ1NWVOs",
                "sequence": 5
              },
              "process": {
                "pid": 2012,
                "name": "regsvr32.exe",
                "executable": "C:\\Windows\\System32\\regsvr32.exe"
              },
              "file": {
                "path": "C:\\Windows\\System32\\scrobj.dll",
                "name": "scrobj.dll"
              }
            }
          }
        ]
      }
    ]
  }
}

Используйте with maxspan, чтобы ограничить совпадающие последовательности временным интервалом:

resp = client.eql.search(
    index="my-data-stream",
    query="\n    sequence with maxspan=1h\n      [ process where process.name == \"regsvr32.exe\" ]\n      [ file where stringContains(file.name, \"scrobj.dll\") ]\n  ",
)
print(resp)
const response = await client.eql.search({
  index: "my-data-stream",
  query:
    '\n    sequence with maxspan=1h\n      [ process where process.name == "regsvr32.exe" ]\n      [ file where stringContains(file.name, "scrobj.dll") ]\n  ',
});
console.log(response);
GET /my-data-stream/_eql/search
{
  "query": """
    sequence with maxspan=1h
      [ process where process.name == "regsvr32.exe" ]
      [ file where stringContains(file.name, "scrobj.dll") ]
  """
}

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

resp = client.eql.search(
    index="my-data-stream",
    query="\n    sequence with maxspan=1d\n      [ process where process.name == \"cmd.exe\" ]\n      ![ process where stringContains(process.command_line, \"ocx\") ]\n      [ file where stringContains(file.name, \"scrobj.dll\") ]\n  ",
)
print(resp)
const response = await client.eql.search({
  index: "my-data-stream",
  query:
    '\n    sequence with maxspan=1d\n      [ process where process.name == "cmd.exe" ]\n      ![ process where stringContains(process.command_line, "ocx") ]\n      [ file where stringContains(file.name, "scrobj.dll") ]\n  ',
});
console.log(response);
GET /my-data-stream/_eql/search
{
  "query": """
    sequence with maxspan=1d
      [ process where process.name == "cmd.exe" ]
      ![ process where stringContains(process.command_line, "ocx") ]
      [ file where stringContains(file.name, "scrobj.dll") ]
  """
}

Отсутствующие события указаны в ответе как missing": true:

{
  ...
  "hits": {
    "total": ...,
    "sequences": [
      {
        "events": [
          {
            "_index": ".ds-my-data-stream-2023.07.04-000001",
            "_id": "AnpTIYkBrVQ2QEgsWg94",
            "_source": {
              "@timestamp": "2099-12-07T11:06:07.000Z",
              "event": {
                "category": "process",
                "id": "cMyt5SZ2",
                "sequence": 3
              },
              "process": {
                "pid": 2012,
                "name": "cmd.exe",
                "executable": "C:\\Windows\\System32\\cmd.exe"
              }
            }
          },
          {
            "_index": "",
            "_id": "",
            "_source": {},
            "missing": true
          },
          {
            "_index": ".ds-my-data-stream-2023.07.04-000001",
            "_id": "BHpTIYkBrVQ2QEgsWg94",
            "_source": {
              "@timestamp": "2099-12-07T11:07:10.000Z",
              "event": {
                "category": "file",
                "id": "tZ1NWVOs",
                "sequence": 5
              },
              "process": {
                "pid": 2012,
                "name": "regsvr32.exe",
                "executable": "C:\\Windows\\System32\\regsvr32.exe"
              },
              "file": {
                "path": "C:\\Windows\\System32\\scrobj.dll",
                "name": "scrobj.dll"
              }
            }
          }
        ]
      }
    ]
  }
}

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

resp = client.eql.search(
    index="my-data-stream",
    query="\n    sequence with maxspan=1h\n      [ process where process.name == \"regsvr32.exe\" ] by process.pid\n      [ file where stringContains(file.name, \"scrobj.dll\") ] by process.pid\n  ",
)
print(resp)
const response = await client.eql.search({
  index: "my-data-stream",
  query:
    '\n    sequence with maxspan=1h\n      [ process where process.name == "regsvr32.exe" ] by process.pid\n      [ file where stringContains(file.name, "scrobj.dll") ] by process.pid\n  ',
});
console.log(response);
GET /my-data-stream/_eql/search
{
  "query": """
    sequence with maxspan=1h
      [ process where process.name == "regsvr32.exe" ] by process.pid
      [ file where stringContains(file.name, "scrobj.dll") ] by process.pid
  """
}

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

resp = client.eql.search(
    index="my-data-stream",
    query="\n    sequence by process.pid with maxspan=1h\n      [ process where process.name == \"regsvr32.exe\" ]\n      [ file where stringContains(file.name, \"scrobj.dll\") ]\n  ",
)
print(resp)
const response = await client.eql.search({
  index: "my-data-stream",
  query:
    '\n    sequence by process.pid with maxspan=1h\n      [ process where process.name == "regsvr32.exe" ]\n      [ file where stringContains(file.name, "scrobj.dll") ]\n  ',
});
console.log(response);
GET /my-data-stream/_eql/search
{
  "query": """
    sequence by process.pid with maxspan=1h
      [ process where process.name == "regsvr32.exe" ]
      [ file where stringContains(file.name, "scrobj.dll") ]
  """
}

Свойство hits.sequences.join_keys содержит общие значения полей.

{
  ...
  "hits": ...,
    "sequences": [
      {
        "join_keys": [
          2012
        ],
        "events": ...
      }
    ]
  }
}

Используйте until ключевое слово, чтобы указать событие завершения для последовательностей. Совпадающие последовательности должны заканчиваться до этого события.

resp = client.eql.search(
    index="my-data-stream",
    query="\n    sequence by process.pid with maxspan=1h\n      [ process where process.name == \"regsvr32.exe\" ]\n      [ file where stringContains(file.name, \"scrobj.dll\") ]\n    until [ process where event.type == \"termination\" ]\n  ",
)
print(resp)
const response = await client.eql.search({
  index: "my-data-stream",
  query:
    '\n    sequence by process.pid with maxspan=1h\n      [ process where process.name == "regsvr32.exe" ]\n      [ file where stringContains(file.name, "scrobj.dll") ]\n    until [ process where event.type == "termination" ]\n  ',
});
console.log(response);
GET /my-data-stream/_eql/search
{
  "query": """
    sequence by process.pid with maxspan=1h
      [ process where process.name == "regsvr32.exe" ]
      [ file where stringContains(file.name, "scrobj.dll") ]
    until [ process where event.type == "termination" ]
  """
}

Примеры событий, не упорядоченных по времени

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

Нажмите, чтобы показать примерные данные, используемые в примерах ниже
resp = client.indices.create(
    index="my-index-000001",
    mappings={
        "properties": {
            "ip": {
                "type": "ip"
            },
            "version": {
                "type": "version"
            },
            "missing_keyword": {
                "type": "keyword"
            },
            "@timestamp": {
                "type": "date"
            },
            "type_test": {
                "type": "keyword"
            },
            "@timestamp_pretty": {
                "type": "date",
                "format": "dd-MM-yyyy"
            },
            "event_type": {
                "type": "keyword"
            },
            "event": {
                "properties": {
                    "category": {
                        "type": "alias",
                        "path": "event_type"
                    }
                }
            },
            "host": {
                "type": "keyword"
            },
            "os": {
                "type": "keyword"
            },
            "bool": {
                "type": "boolean"
            },
            "uptime": {
                "type": "long"
            },
            "port": {
                "type": "long"
            }
        }
    },
)
print(resp)

resp1 = client.indices.create(
    index="my-index-000002",
    mappings={
        "properties": {
            "ip": {
                "type": "ip"
            },
            "@timestamp": {
                "type": "date"
            },
            "@timestamp_pretty": {
                "type": "date",
                "format": "yyyy-MM-dd"
            },
            "type_test": {
                "type": "keyword"
            },
            "event_type": {
                "type": "keyword"
            },
            "event": {
                "properties": {
                    "category": {
                        "type": "alias",
                        "path": "event_type"
                    }
                }
            },
            "host": {
                "type": "keyword"
            },
            "op_sys": {
                "type": "keyword"
            },
            "bool": {
                "type": "boolean"
            },
            "uptime": {
                "type": "long"
            },
            "port": {
                "type": "long"
            }
        }
    },
)
print(resp1)

resp2 = client.indices.create(
    index="my-index-000003",
    mappings={
        "properties": {
            "host_ip": {
                "type": "ip"
            },
            "@timestamp": {
                "type": "date"
            },
            "date": {
                "type": "date"
            },
            "event_type": {
                "type": "keyword"
            },
            "event": {
                "properties": {
                    "category": {
                        "type": "alias",
                        "path": "event_type"
                    }
                }
            },
            "missing_keyword": {
                "type": "keyword"
            },
            "host": {
                "type": "keyword"
            },
            "os": {
                "type": "keyword"
            },
            "bool": {
                "type": "boolean"
            },
            "uptime": {
                "type": "long"
            },
            "port": {
                "type": "long"
            }
        }
    },
)
print(resp2)

resp3 = client.bulk(
    index="my-index-000001",
    refresh=True,
    operations=[
        {
            "index": {
                "_id": 1
            }
        },
        {
            "@timestamp": "1234567891",
            "@timestamp_pretty": "12-12-2022",
            "missing_keyword": "test",
            "type_test": "abc",
            "ip": "10.0.0.1",
            "event_type": "alert",
            "host": "doom",
            "uptime": 0,
            "port": 1234,
            "os": "win10",
            "version": "1.0.0",
            "id": 11
        },
        {
            "index": {
                "_id": 2
            }
        },
        {
            "@timestamp": "1234567892",
            "@timestamp_pretty": "13-12-2022",
            "event_type": "alert",
            "type_test": "abc",
            "host": "CS",
            "uptime": 5,
            "port": 1,
            "os": "win10",
            "version": "1.2.0",
            "id": 12
        },
        {
            "index": {
                "_id": 3
            }
        },
        {
            "@timestamp": "1234567893",
            "@timestamp_pretty": "12-12-2022",
            "event_type": "alert",
            "type_test": "abc",
            "host": "farcry",
            "uptime": 1,
            "port": 1234,
            "bool": False,
            "os": "win10",
            "version": "2.0.0",
            "id": 13
        },
        {
            "index": {
                "_id": 4
            }
        },
        {
            "@timestamp": "1234567894",
            "@timestamp_pretty": "13-12-2022",
            "event_type": "alert",
            "type_test": "abc",
            "host": "GTA",
            "uptime": 3,
            "port": 12,
            "os": "slack",
            "version": "10.0.0",
            "id": 14
        },
        {
            "index": {
                "_id": 5
            }
        },
        {
            "@timestamp": "1234567895",
            "@timestamp_pretty": "17-12-2022",
            "event_type": "alert",
            "host": "sniper 3d",
            "uptime": 6,
            "port": 1234,
            "os": "fedora",
            "version": "20.1.0",
            "id": 15
        },
        {
            "index": {
                "_id": 6
            }
        },
        {
            "@timestamp": "1234568896",
            "@timestamp_pretty": "17-12-2022",
            "event_type": "alert",
            "host": "doom",
            "port": 65123,
            "bool": True,
            "os": "redhat",
            "version": "20.10.0",
            "id": 16
        },
        {
            "index": {
                "_id": 7
            }
        },
        {
            "@timestamp": "1234567897",
            "@timestamp_pretty": "17-12-2022",
            "missing_keyword": "yyy",
            "event_type": "failure",
            "host": "doom",
            "uptime": 15,
            "port": 1234,
            "bool": True,
            "os": "redhat",
            "version": "20.2.0",
            "id": 17
        },
        {
            "index": {
                "_id": 8
            }
        },
        {
            "@timestamp": "1234567898",
            "@timestamp_pretty": "12-12-2022",
            "missing_keyword": "test",
            "event_type": "success",
            "host": "doom",
            "uptime": 16,
            "port": 512,
            "os": "win10",
            "version": "1.2.3",
            "id": 18
        },
        {
            "index": {
                "_id": 9
            }
        },
        {
            "@timestamp": "1234567899",
            "@timestamp_pretty": "15-12-2022",
            "missing_keyword": "test",
            "event_type": "success",
            "host": "GTA",
            "port": 12,
            "bool": True,
            "os": "win10",
            "version": "1.2.3",
            "id": 19
        },
        {
            "index": {
                "_id": 10
            }
        },
        {
            "@timestamp": "1234567893",
            "missing_keyword": None,
            "ip": "10.0.0.5",
            "event_type": "alert",
            "host": "farcry",
            "uptime": 1,
            "port": 1234,
            "bool": True,
            "os": "win10",
            "version": "1.2.3",
            "id": 110
        }
    ],
)
print(resp3)

resp4 = client.bulk(
    index="my-index-000002",
    refresh=True,
    operations=[
        {
            "index": {
                "_id": 1
            }
        },
        {
            "@timestamp": "1234567991",
            "type_test": "abc",
            "ip": "10.0.0.1",
            "event_type": "alert",
            "host": "doom",
            "uptime": 0,
            "port": 1234,
            "op_sys": "win10",
            "id": 21
        },
        {
            "index": {
                "_id": 2
            }
        },
        {
            "@timestamp": "1234567992",
            "type_test": "abc",
            "event_type": "alert",
            "host": "CS",
            "uptime": 5,
            "port": 1,
            "op_sys": "win10",
            "id": 22
        },
        {
            "index": {
                "_id": 3
            }
        },
        {
            "@timestamp": "1234567993",
            "type_test": "abc",
            "@timestamp_pretty": "2022-12-17",
            "event_type": "alert",
            "host": "farcry",
            "uptime": 1,
            "port": 1234,
            "bool": False,
            "op_sys": "win10",
            "id": 23
        },
        {
            "index": {
                "_id": 4
            }
        },
        {
            "@timestamp": "1234567994",
            "event_type": "alert",
            "host": "GTA",
            "uptime": 3,
            "port": 12,
            "op_sys": "slack",
            "id": 24
        },
        {
            "index": {
                "_id": 5
            }
        },
        {
            "@timestamp": "1234567995",
            "event_type": "alert",
            "host": "sniper 3d",
            "uptime": 6,
            "port": 1234,
            "op_sys": "fedora",
            "id": 25
        },
        {
            "index": {
                "_id": 6
            }
        },
        {
            "@timestamp": "1234568996",
            "@timestamp_pretty": "2022-12-17",
            "ip": "10.0.0.5",
            "event_type": "alert",
            "host": "doom",
            "port": 65123,
            "bool": True,
            "op_sys": "redhat",
            "id": 26
        },
        {
            "index": {
                "_id": 7
            }
        },
        {
            "@timestamp": "1234567997",
            "@timestamp_pretty": "2022-12-17",
            "event_type": "failure",
            "host": "doom",
            "uptime": 15,
            "port": 1234,
            "bool": True,
            "op_sys": "redhat",
            "id": 27
        },
        {
            "index": {
                "_id": 8
            }
        },
        {
            "@timestamp": "1234567998",
            "ip": "10.0.0.1",
            "event_type": "success",
            "host": "doom",
            "uptime": 16,
            "port": 512,
            "op_sys": "win10",
            "id": 28
        },
        {
            "index": {
                "_id": 9
            }
        },
        {
            "@timestamp": "1234567999",
            "ip": "10.0.0.1",
            "event_type": "success",
            "host": "GTA",
            "port": 12,
            "bool": False,
            "op_sys": "win10",
            "id": 29
        }
    ],
)
print(resp4)

resp5 = client.bulk(
    index="my-index-000003",
    refresh=True,
    operations=[
        {
            "index": {
                "_id": 1
            }
        },
        {
            "@timestamp": "1334567891",
            "host_ip": "10.0.0.1",
            "event_type": "alert",
            "host": "doom",
            "uptime": 0,
            "port": 12,
            "os": "win10",
            "id": 31
        },
        {
            "index": {
                "_id": 2
            }
        },
        {
            "@timestamp": "1334567892",
            "event_type": "alert",
            "host": "CS",
            "os": "win10",
            "id": 32
        },
        {
            "index": {
                "_id": 3
            }
        },
        {
            "@timestamp": "1334567893",
            "event_type": "alert",
            "host": "farcry",
            "bool": True,
            "os": "win10",
            "id": 33
        },
        {
            "index": {
                "_id": 4
            }
        },
        {
            "@timestamp": "1334567894",
            "event_type": "alert",
            "host": "GTA",
            "os": "slack",
            "bool": True,
            "id": 34
        },
        {
            "index": {
                "_id": 5
            }
        },
        {
            "@timestamp": "1234567895",
            "event_type": "alert",
            "host": "sniper 3d",
            "os": "fedora",
            "id": 35
        },
        {
            "index": {
                "_id": 6
            }
        },
        {
            "@timestamp": "1234578896",
            "host_ip": "10.0.0.1",
            "event_type": "alert",
            "host": "doom",
            "bool": True,
            "os": "redhat",
            "id": 36
        },
        {
            "index": {
                "_id": 7
            }
        },
        {
            "@timestamp": "1234567897",
            "event_type": "failure",
            "missing_keyword": "test",
            "host": "doom",
            "bool": True,
            "os": "redhat",
            "id": 37
        },
        {
            "index": {
                "_id": 8
            }
        },
        {
            "@timestamp": "1234577898",
            "event_type": "success",
            "host": "doom",
            "os": "win10",
            "id": 38,
            "date": "1671235200000"
        },
        {
            "index": {
                "_id": 9
            }
        },
        {
            "@timestamp": "1234577899",
            "host_ip": "10.0.0.5",
            "event_type": "success",
            "host": "GTA",
            "bool": True,
            "os": "win10",
            "id": 39
        }
    ],
)
print(resp5)
response = client.indices.create(
  index: 'my-index-000001',
  body: {
    mappings: {
      properties: {
        ip: {
          type: 'ip'
        },
        version: {
          type: 'version'
        },
        missing_keyword: {
          type: 'keyword'
        },
        "@timestamp": {
          type: 'date'
        },
        type_test: {
          type: 'keyword'
        },
        "@timestamp_pretty": {
          type: 'date',
          format: 'dd-MM-yyyy'
        },
        event_type: {
          type: 'keyword'
        },
        event: {
          properties: {
            category: {
              type: 'alias',
              path: 'event_type'
            }
          }
        },
        host: {
          type: 'keyword'
        },
        os: {
          type: 'keyword'
        },
        bool: {
          type: 'boolean'
        },
        uptime: {
          type: 'long'
        },
        port: {
          type: 'long'
        }
      }
    }
  }
)
puts response

response = client.indices.create(
  index: 'my-index-000002',
  body: {
    mappings: {
      properties: {
        ip: {
          type: 'ip'
        },
        "@timestamp": {
          type: 'date'
        },
        "@timestamp_pretty": {
          type: 'date',
          format: 'yyyy-MM-dd'
        },
        type_test: {
          type: 'keyword'
        },
        event_type: {
          type: 'keyword'
        },
        event: {
          properties: {
            category: {
              type: 'alias',
              path: 'event_type'
            }
          }
        },
        host: {
          type: 'keyword'
        },
        op_sys: {
          type: 'keyword'
        },
        bool: {
          type: 'boolean'
        },
        uptime: {
          type: 'long'
        },
        port: {
          type: 'long'
        }
      }
    }
  }
)
puts response

response = client.indices.create(
  index: 'my-index-000003',
  body: {
    mappings: {
      properties: {
        host_ip: {
          type: 'ip'
        },
        "@timestamp": {
          type: 'date'
        },
        date: {
          type: 'date'
        },
        event_type: {
          type: 'keyword'
        },
        event: {
          properties: {
            category: {
              type: 'alias',
              path: 'event_type'
            }
          }
        },
        missing_keyword: {
          type: 'keyword'
        },
        host: {
          type: 'keyword'
        },
        os: {
          type: 'keyword'
        },
        bool: {
          type: 'boolean'
        },
        uptime: {
          type: 'long'
        },
        port: {
          type: 'long'
        }
      }
    }
  }
)
puts response

response = client.bulk(
  index: 'my-index-000001',
  refresh: true,
  body: [
    {
      index: {
        _id: 1
      }
    },
    {
      "@timestamp": '1234567891',
      "@timestamp_pretty": '12-12-2022',
      missing_keyword: 'test',
      type_test: 'abc',
      ip: '10.0.0.1',
      event_type: 'alert',
      host: 'doom',
      uptime: 0,
      port: 1234,
      os: 'win10',
      version: '1.0.0',
      id: 11
    },
    {
      index: {
        _id: 2
      }
    },
    {
      "@timestamp": '1234567892',
      "@timestamp_pretty": '13-12-2022',
      event_type: 'alert',
      type_test: 'abc',
      host: 'CS',
      uptime: 5,
      port: 1,
      os: 'win10',
      version: '1.2.0',
      id: 12
    },
    {
      index: {
        _id: 3
      }
    },
    {
      "@timestamp": '1234567893',
      "@timestamp_pretty": '12-12-2022',
      event_type: 'alert',
      type_test: 'abc',
      host: 'farcry',
      uptime: 1,
      port: 1234,
      bool: false,
      os: 'win10',
      version: '2.0.0',
      id: 13
    },
    {
      index: {
        _id: 4
      }
    },
    {
      "@timestamp": '1234567894',
      "@timestamp_pretty": '13-12-2022',
      event_type: 'alert',
      type_test: 'abc',
      host: 'GTA',
      uptime: 3,
      port: 12,
      os: 'slack',
      version: '10.0.0',
      id: 14
    },
    {
      index: {
        _id: 5
      }
    },
    {
      "@timestamp": '1234567895',
      "@timestamp_pretty": '17-12-2022',
      event_type: 'alert',
      host: 'sniper 3d',
      uptime: 6,
      port: 1234,
      os: 'fedora',
      version: '20.1.0',
      id: 15
    },
    {
      index: {
        _id: 6
      }
    },
    {
      "@timestamp": '1234568896',
      "@timestamp_pretty": '17-12-2022',
      event_type: 'alert',
      host: 'doom',
      port: 65_123,
      bool: true,
      os: 'redhat',
      version: '20.10.0',
      id: 16
    },
    {
      index: {
        _id: 7
      }
    },
    {
      "@timestamp": '1234567897',
      "@timestamp_pretty": '17-12-2022',
      missing_keyword: 'yyy',
      event_type: 'failure',
      host: 'doom',
      uptime: 15,
      port: 1234,
      bool: true,
      os: 'redhat',
      version: '20.2.0',
      id: 17
    },
    {
      index: {
        _id: 8
      }
    },
    {
      "@timestamp": '1234567898',
      "@timestamp_pretty": '12-12-2022',
      missing_keyword: 'test',
      event_type: 'success',
      host: 'doom',
      uptime: 16,
      port: 512,
      os: 'win10',
      version: '1.2.3',
      id: 18
    },
    {
      index: {
        _id: 9
      }
    },
    {
      "@timestamp": '1234567899',
      "@timestamp_pretty": '15-12-2022',
      missing_keyword: 'test',
      event_type: 'success',
      host: 'GTA',
      port: 12,
      bool: true,
      os: 'win10',
      version: '1.2.3',
      id: 19
    },
    {
      index: {
        _id: 10
      }
    },
    {
      "@timestamp": '1234567893',
      missing_keyword: nil,
      ip: '10.0.0.5',
      event_type: 'alert',
      host: 'farcry',
      uptime: 1,
      port: 1234,
      bool: true,
      os: 'win10',
      version: '1.2.3',
      id: 110
    }
  ]
)
puts response

response = client.bulk(
  index: 'my-index-000002',
  refresh: true,
  body: [
    {
      index: {
        _id: 1
      }
    },
    {
      "@timestamp": '1234567991',
      type_test: 'abc',
      ip: '10.0.0.1',
      event_type: 'alert',
      host: 'doom',
      uptime: 0,
      port: 1234,
      op_sys: 'win10',
      id: 21
    },
    {
      index: {
        _id: 2
      }
    },
    {
      "@timestamp": '1234567992',
      type_test: 'abc',
      event_type: 'alert',
      host: 'CS',
      uptime: 5,
      port: 1,
      op_sys: 'win10',
      id: 22
    },
    {
      index: {
        _id: 3
      }
    },
    {
      "@timestamp": '1234567993',
      type_test: 'abc',
      "@timestamp_pretty": '2022-12-17',
      event_type: 'alert',
      host: 'farcry',
      uptime: 1,
      port: 1234,
      bool: false,
      op_sys: 'win10',
      id: 23
    },
    {
      index: {
        _id: 4
      }
    },
    {
      "@timestamp": '1234567994',
      event_type: 'alert',
      host: 'GTA',
      uptime: 3,
      port: 12,
      op_sys: 'slack',
      id: 24
    },
    {
      index: {
        _id: 5
      }
    },
    {
      "@timestamp": '1234567995',
      event_type: 'alert',
      host: 'sniper 3d',
      uptime: 6,
      port: 1234,
      op_sys: 'fedora',
      id: 25
    },
    {
      index: {
        _id: 6
      }
    },
    {
      "@timestamp": '1234568996',
      "@timestamp_pretty": '2022-12-17',
      ip: '10.0.0.5',
      event_type: 'alert',
      host: 'doom',
      port: 65_123,
      bool: true,
      op_sys: 'redhat',
      id: 26
    },
    {
      index: {
        _id: 7
      }
    },
    {
      "@timestamp": '1234567997',
      "@timestamp_pretty": '2022-12-17',
      event_type: 'failure',
      host: 'doom',
      uptime: 15,
      port: 1234,
      bool: true,
      op_sys: 'redhat',
      id: 27
    },
    {
      index: {
        _id: 8
      }
    },
    {
      "@timestamp": '1234567998',
      ip: '10.0.0.1',
      event_type: 'success',
      host: 'doom',
      uptime: 16,
      port: 512,
      op_sys: 'win10',
      id: 28
    },
    {
      index: {
        _id: 9
      }
    },
    {
      "@timestamp": '1234567999',
      ip: '10.0.0.1',
      event_type: 'success',
      host: 'GTA',
      port: 12,
      bool: false,
      op_sys: 'win10',
      id: 29
    }
  ]
)
puts response

response = client.bulk(
  index: 'my-index-000003',
  refresh: true,
  body: [
    {
      index: {
        _id: 1
      }
    },
    {
      "@timestamp": '1334567891',
      host_ip: '10.0.0.1',
      event_type: 'alert',
      host: 'doom',
      uptime: 0,
      port: 12,
      os: 'win10',
      id: 31
    },
    {
      index: {
        _id: 2
      }
    },
    {
      "@timestamp": '1334567892',
      event_type: 'alert',
      host: 'CS',
      os: 'win10',
      id: 32
    },
    {
      index: {
        _id: 3
      }
    },
    {
      "@timestamp": '1334567893',
      event_type: 'alert',
      host: 'farcry',
      bool: true,
      os: 'win10',
      id: 33
    },
    {
      index: {
        _id: 4
      }
    },
    {
      "@timestamp": '1334567894',
      event_type: 'alert',
      host: 'GTA',
      os: 'slack',
      bool: true,
      id: 34
    },
    {
      index: {
        _id: 5
      }
    },
    {
      "@timestamp": '1234567895',
      event_type: 'alert',
      host: 'sniper 3d',
      os: 'fedora',
      id: 35
    },
    {
      index: {
        _id: 6
      }
    },
    {
      "@timestamp": '1234578896',
      host_ip: '10.0.0.1',
      event_type: 'alert',
      host: 'doom',
      bool: true,
      os: 'redhat',
      id: 36
    },
    {
      index: {
        _id: 7
      }
    },
    {
      "@timestamp": '1234567897',
      event_type: 'failure',
      missing_keyword: 'test',
      host: 'doom',
      bool: true,
      os: 'redhat',
      id: 37
    },
    {
      index: {
        _id: 8
      }
    },
    {
      "@timestamp": '1234577898',
      event_type: 'success',
      host: 'doom',
      os: 'win10',
      id: 38,
      date: '1671235200000'
    },
    {
      index: {
        _id: 9
      }
    },
    {
      "@timestamp": '1234577899',
      host_ip: '10.0.0.5',
      event_type: 'success',
      host: 'GTA',
      bool: true,
      os: 'win10',
      id: 39
    }
  ]
)
puts response
const response = await client.indices.create({
  index: "my-index-000001",
  mappings: {
    properties: {
      ip: {
        type: "ip",
      },
      version: {
        type: "version",
      },
      missing_keyword: {
        type: "keyword",
      },
      "@timestamp": {
        type: "date",
      },
      type_test: {
        type: "keyword",
      },
      "@timestamp_pretty": {
        type: "date",
        format: "dd-MM-yyyy",
      },
      event_type: {
        type: "keyword",
      },
      event: {
        properties: {
          category: {
            type: "alias",
            path: "event_type",
          },
        },
      },
      host: {
        type: "keyword",
      },
      os: {
        type: "keyword",
      },
      bool: {
        type: "boolean",
      },
      uptime: {
        type: "long",
      },
      port: {
        type: "long",
      },
    },
  },
});
console.log(response);

const response1 = await client.indices.create({
  index: "my-index-000002",
  mappings: {
    properties: {
      ip: {
        type: "ip",
      },
      "@timestamp": {
        type: "date",
      },
      "@timestamp_pretty": {
        type: "date",
        format: "yyyy-MM-dd",
      },
      type_test: {
        type: "keyword",
      },
      event_type: {
        type: "keyword",
      },
      event: {
        properties: {
          category: {
            type: "alias",
            path: "event_type",
          },
        },
      },
      host: {
        type: "keyword",
      },
      op_sys: {
        type: "keyword",
      },
      bool: {
        type: "boolean",
      },
      uptime: {
        type: "long",
      },
      port: {
        type: "long",
      },
    },
  },
});
console.log(response1);

const response2 = await client.indices.create({
  index: "my-index-000003",
  mappings: {
    properties: {
      host_ip: {
        type: "ip",
      },
      "@timestamp": {
        type: "date",
      },
      date: {
        type: "date",
      },
      event_type: {
        type: "keyword",
      },
      event: {
        properties: {
          category: {
            type: "alias",
            path: "event_type",
          },
        },
      },
      missing_keyword: {
        type: "keyword",
      },
      host: {
        type: "keyword",
      },
      os: {
        type: "keyword",
      },
      bool: {
        type: "boolean",
      },
      uptime: {
        type: "long",
      },
      port: {
        type: "long",
      },
    },
  },
});
console.log(response2);

const response3 = await client.bulk({
  index: "my-index-000001",
  refresh: "true",
  operations: [
    {
      index: {
        _id: 1,
      },
    },
    {
      "@timestamp": "1234567891",
      "@timestamp_pretty": "12-12-2022",
      missing_keyword: "test",
      type_test: "abc",
      ip: "10.0.0.1",
      event_type: "alert",
      host: "doom",
      uptime: 0,
      port: 1234,
      os: "win10",
      version: "1.0.0",
      id: 11,
    },
    {
      index: {
        _id: 2,
      },
    },
    {
      "@timestamp": "1234567892",
      "@timestamp_pretty": "13-12-2022",
      event_type: "alert",
      type_test: "abc",
      host: "CS",
      uptime: 5,
      port: 1,
      os: "win10",
      version: "1.2.0",
      id: 12,
    },
    {
      index: {
        _id: 3,
      },
    },
    {
      "@timestamp": "1234567893",
      "@timestamp_pretty": "12-12-2022",
      event_type: "alert",
      type_test: "abc",
      host: "farcry",
      uptime: 1,
      port: 1234,
      bool: false,
      os: "win10",
      version: "2.0.0",
      id: 13,
    },
    {
      index: {
        _id: 4,
      },
    },
    {
      "@timestamp": "1234567894",
      "@timestamp_pretty": "13-12-2022",
      event_type: "alert",
      type_test: "abc",
      host: "GTA",
      uptime: 3,
      port: 12,
      os: "slack",
      version: "10.0.0",
      id: 14,
    },
    {
      index: {
        _id: 5,
      },
    },
    {
      "@timestamp": "1234567895",
      "@timestamp_pretty": "17-12-2022",
      event_type: "alert",
      host: "sniper 3d",
      uptime: 6,
      port: 1234,
      os: "fedora",
      version: "20.1.0",
      id: 15,
    },
    {
      index: {
        _id: 6,
      },
    },
    {
      "@timestamp": "1234568896",
      "@timestamp_pretty": "17-12-2022",
      event_type: "alert",
      host: "doom",
      port: 65123,
      bool: true,
      os: "redhat",
      version: "20.10.0",
      id: 16,
    },
    {
      index: {
        _id: 7,
      },
    },
    {
      "@timestamp": "1234567897",
      "@timestamp_pretty": "17-12-2022",
      missing_keyword: "yyy",
      event_type: "failure",
      host: "doom",
      uptime: 15,
      port: 1234,
      bool: true,
      os: "redhat",
      version: "20.2.0",
      id: 17,
    },
    {
      index: {
        _id: 8,
      },
    },
    {
      "@timestamp": "1234567898",
      "@timestamp_pretty": "12-12-2022",
      missing_keyword: "test",
      event_type: "success",
      host: "doom",
      uptime: 16,
      port: 512,
      os: "win10",
      version: "1.2.3",
      id: 18,
    },
    {
      index: {
        _id: 9,
      },
    },
    {
      "@timestamp": "1234567899",
      "@timestamp_pretty": "15-12-2022",
      missing_keyword: "test",
      event_type: "success",
      host: "GTA",
      port: 12,
      bool: true,
      os: "win10",
      version: "1.2.3",
      id: 19,
    },
    {
      index: {
        _id: 10,
      },
    },
    {
      "@timestamp": "1234567893",
      missing_keyword: null,
      ip: "10.0.0.5",
      event_type: "alert",
      host: "farcry",
      uptime: 1,
      port: 1234,
      bool: true,
      os: "win10",
      version: "1.2.3",
      id: 110,
    },
  ],
});
console.log(response3);

const response4 = await client.bulk({
  index: "my-index-000002",
  refresh: "true",
  operations: [
    {
      index: {
        _id: 1,
      },
    },
    {
      "@timestamp": "1234567991",
      type_test: "abc",
      ip: "10.0.0.1",
      event_type: "alert",
      host: "doom",
      uptime: 0,
      port: 1234,
      op_sys: "win10",
      id: 21,
    },
    {
      index: {
        _id: 2,
      },
    },
    {
      "@timestamp": "1234567992",
      type_test: "abc",
      event_type: "alert",
      host: "CS",
      uptime: 5,
      port: 1,
      op_sys: "win10",
      id: 22,
    },
    {
      index: {
        _id: 3,
      },
    },
    {
      "@timestamp": "1234567993",
      type_test: "abc",
      "@timestamp_pretty": "2022-12-17",
      event_type: "alert",
      host: "farcry",
      uptime: 1,
      port: 1234,
      bool: false,
      op_sys: "win10",
      id: 23,
    },
    {
      index: {
        _id: 4,
      },
    },
    {
      "@timestamp": "1234567994",
      event_type: "alert",
      host: "GTA",
      uptime: 3,
      port: 12,
      op_sys: "slack",
      id: 24,
    },
    {
      index: {
        _id: 5,
      },
    },
    {
      "@timestamp": "1234567995",
      event_type: "alert",
      host: "sniper 3d",
      uptime: 6,
      port: 1234,
      op_sys: "fedora",
      id: 25,
    },
    {
      index: {
        _id: 6,
      },
    },
    {
      "@timestamp": "1234568996",
      "@timestamp_pretty": "2022-12-17",
      ip: "10.0.0.5",
      event_type: "alert",
      host: "doom",
      port: 65123,
      bool: true,
      op_sys: "redhat",
      id: 26,
    },
    {
      index: {
        _id: 7,
      },
    },
    {
      "@timestamp": "1234567997",
      "@timestamp_pretty": "2022-12-17",
      event_type: "failure",
      host: "doom",
      uptime: 15,
      port: 1234,
      bool: true,
      op_sys: "redhat",
      id: 27,
    },
    {
      index: {
        _id: 8,
      },
    },
    {
      "@timestamp": "1234567998",
      ip: "10.0.0.1",
      event_type: "success",
      host: "doom",
      uptime: 16,
      port: 512,
      op_sys: "win10",
      id: 28,
    },
    {
      index: {
        _id: 9,
      },
    },
    {
      "@timestamp": "1234567999",
      ip: "10.0.0.1",
      event_type: "success",
      host: "GTA",
      port: 12,
      bool: false,
      op_sys: "win10",
      id: 29,
    },
  ],
});
console.log(response4);

const response5 = await client.bulk({
  index: "my-index-000003",
  refresh: "true",
  operations: [
    {
      index: {
        _id: 1,
      },
    },
    {
      "@timestamp": "1334567891",
      host_ip: "10.0.0.1",
      event_type: "alert",
      host: "doom",
      uptime: 0,
      port: 12,
      os: "win10",
      id: 31,
    },
    {
      index: {
        _id: 2,
      },
    },
    {
      "@timestamp": "1334567892",
      event_type: "alert",
      host: "CS",
      os: "win10",
      id: 32,
    },
    {
      index: {
        _id: 3,
      },
    },
    {
      "@timestamp": "1334567893",
      event_type: "alert",
      host: "farcry",
      bool: true,
      os: "win10",
      id: 33,
    },
    {
      index: {
        _id: 4,
      },
    },
    {
      "@timestamp": "1334567894",
      event_type: "alert",
      host: "GTA",
      os: "slack",
      bool: true,
      id: 34,
    },
    {
      index: {
        _id: 5,
      },
    },
    {
      "@timestamp": "1234567895",
      event_type: "alert",
      host: "sniper 3d",
      os: "fedora",
      id: 35,
    },
    {
      index: {
        _id: 6,
      },
    },
    {
      "@timestamp": "1234578896",
      host_ip: "10.0.0.1",
      event_type: "alert",
      host: "doom",
      bool: true,
      os: "redhat",
      id: 36,
    },
    {
      index: {
        _id: 7,
      },
    },
    {
      "@timestamp": "1234567897",
      event_type: "failure",
      missing_keyword: "test",
      host: "doom",
      bool: true,
      os: "redhat",
      id: 37,
    },
    {
      index: {
        _id: 8,
      },
    },
    {
      "@timestamp": "1234577898",
      event_type: "success",
      host: "doom",
      os: "win10",
      id: 38,
      date: "1671235200000",
    },
    {
      index: {
        _id: 9,
      },
    },
    {
      "@timestamp": "1234577899",
      host_ip: "10.0.0.5",
      event_type: "success",
      host: "GTA",
      bool: true,
      os: "win10",
      id: 39,
    },
  ],
});
console.log(response5);
PUT /my-index-000001
{
    "mappings": {
        "properties": {
            "ip": {
                "type":"ip"
            },
            "version": {
                "type": "version"
            },
            "missing_keyword": {
                "type": "keyword"
            },
            "@timestamp": {
              "type": "date"
            },
            "type_test": {
                "type": "keyword"
            },
            "@timestamp_pretty": {
              "type": "date",
              "format": "dd-MM-yyyy"
            },
            "event_type": {
              "type": "keyword"
            },
            "event": {
              "properties": {
                "category": {
                  "type": "alias",
                  "path": "event_type"
                }
              }
            },
            "host": {
              "type": "keyword"
            },
            "os": {
              "type": "keyword"
            },
            "bool": {
              "type": "boolean"
            },
            "uptime" : {
              "type" : "long"
            },
            "port" : {
              "type" : "long"
            }
        }
    }
}

PUT /my-index-000002
{
    "mappings": {
        "properties": {
            "ip": {
                "type":"ip"
            },
            "@timestamp": {
              "type": "date"
            },
            "@timestamp_pretty": {
              "type": "date",
              "format": "yyyy-MM-dd"
            },
            "type_test": {
                "type": "keyword"
            },
            "event_type": {
              "type": "keyword"
            },
            "event": {
              "properties": {
                "category": {
                  "type": "alias",
                  "path": "event_type"
                }
              }
            },
            "host": {
              "type": "keyword"
            },
            "op_sys": {
              "type": "keyword"
            },
            "bool": {
              "type": "boolean"
            },
            "uptime" : {
              "type" : "long"
            },
            "port" : {
              "type" : "long"
            }
        }
    }
}

PUT /my-index-000003
{
    "mappings": {
        "properties": {
            "host_ip": {
                "type":"ip"
            },
            "@timestamp": {
              "type": "date"
            },
            "date": {
              "type": "date"
            },
            "event_type": {
              "type": "keyword"
            },
            "event": {
              "properties": {
                "category": {
                  "type": "alias",
                  "path": "event_type"
                }
              }
            },
            "missing_keyword": {
                "type": "keyword"
            },
            "host": {
              "type": "keyword"
            },
            "os": {
              "type": "keyword"
            },
            "bool": {
              "type": "boolean"
            },
            "uptime" : {
              "type" : "long"
            },
            "port" : {
              "type" : "long"
            }
        }
    }
}

POST /my-index-000001/_bulk?refresh
{"index":{"_id":1}}
{"@timestamp":"1234567891","@timestamp_pretty":"12-12-2022","missing_keyword":"test","type_test":"abc","ip":"10.0.0.1","event_type":"alert","host":"doom","uptime":0,"port":1234,"os":"win10","version":"1.0.0","id":11}
{"index":{"_id":2}}
{"@timestamp":"1234567892","@timestamp_pretty":"13-12-2022","event_type":"alert","type_test":"abc","host":"CS","uptime":5,"port":1,"os":"win10","version":"1.2.0","id":12}
{"index":{"_id":3}}
{"@timestamp":"1234567893","@timestamp_pretty":"12-12-2022","event_type":"alert","type_test":"abc","host":"farcry","uptime":1,"port":1234,"bool":false,"os":"win10","version":"2.0.0","id":13}
{"index":{"_id":4}}
{"@timestamp":"1234567894","@timestamp_pretty":"13-12-2022","event_type":"alert","type_test":"abc","host":"GTA","uptime":3,"port":12,"os":"slack","version":"10.0.0","id":14}
{"index":{"_id":5}}
{"@timestamp":"1234567895","@timestamp_pretty":"17-12-2022","event_type":"alert","host":"sniper 3d","uptime":6,"port":1234,"os":"fedora","version":"20.1.0","id":15}
{"index":{"_id":6}}
{"@timestamp":"1234568896","@timestamp_pretty":"17-12-2022","event_type":"alert","host":"doom","port":65123,"bool":true,"os":"redhat","version":"20.10.0","id":16}
{"index":{"_id":7}}
{"@timestamp":"1234567897","@timestamp_pretty":"17-12-2022","missing_keyword":"yyy","event_type":"failure","host":"doom","uptime":15,"port":1234,"bool":true,"os":"redhat","version":"20.2.0","id":17}
{"index":{"_id":8}}
{"@timestamp":"1234567898","@timestamp_pretty":"12-12-2022","missing_keyword":"test","event_type":"success","host":"doom","uptime":16,"port":512,"os":"win10","version":"1.2.3","id":18}
{"index":{"_id":9}}
{"@timestamp":"1234567899","@timestamp_pretty":"15-12-2022","missing_keyword":"test","event_type":"success","host":"GTA","port":12,"bool":true,"os":"win10","version":"1.2.3","id":19}
{"index":{"_id":10}}
{"@timestamp":"1234567893","missing_keyword":null,"ip":"10.0.0.5","event_type":"alert","host":"farcry","uptime":1,"port":1234,"bool":true,"os":"win10","version":"1.2.3","id":110}

POST /my-index-000002/_bulk?refresh
{"index":{"_id":1}}
{"@timestamp":"1234567991","type_test":"abc","ip":"10.0.0.1","event_type":"alert","host":"doom","uptime":0,"port":1234,"op_sys":"win10","id":21}
{"index":{"_id":2}}
{"@timestamp":"1234567992","type_test":"abc","event_type":"alert","host":"CS","uptime":5,"port":1,"op_sys":"win10","id":22}
{"index":{"_id":3}}
{"@timestamp":"1234567993","type_test":"abc","@timestamp_pretty":"2022-12-17","event_type":"alert","host":"farcry","uptime":1,"port":1234,"bool":false,"op_sys":"win10","id":23}
{"index":{"_id":4}}
{"@timestamp":"1234567994","event_type":"alert","host":"GTA","uptime":3,"port":12,"op_sys":"slack","id":24}
{"index":{"_id":5}}
{"@timestamp":"1234567995","event_type":"alert","host":"sniper 3d","uptime":6,"port":1234,"op_sys":"fedora","id":25}
{"index":{"_id":6}}
{"@timestamp":"1234568996","@timestamp_pretty":"2022-12-17","ip":"10.0.0.5","event_type":"alert","host":"doom","port":65123,"bool":true,"op_sys":"redhat","id":26}
{"index":{"_id":7}}
{"@timestamp":"1234567997","@timestamp_pretty":"2022-12-17","event_type":"failure","host":"doom","uptime":15,"port":1234,"bool":true,"op_sys":"redhat","id":27}
{"index":{"_id":8}}
{"@timestamp":"1234567998","ip":"10.0.0.1","event_type":"success","host":"doom","uptime":16,"port":512,"op_sys":"win10","id":28}
{"index":{"_id":9}}
{"@timestamp":"1234567999","ip":"10.0.0.1","event_type":"success","host":"GTA","port":12,"bool":false,"op_sys":"win10","id":29}

POST /my-index-000003/_bulk?refresh
{"index":{"_id":1}}
{"@timestamp":"1334567891","host_ip":"10.0.0.1","event_type":"alert","host":"doom","uptime":0,"port":12,"os":"win10","id":31}
{"index":{"_id":2}}
{"@timestamp":"1334567892","event_type":"alert","host":"CS","os":"win10","id":32}
{"index":{"_id":3}}
{"@timestamp":"1334567893","event_type":"alert","host":"farcry","bool":true,"os":"win10","id":33}
{"index":{"_id":4}}
{"@timestamp":"1334567894","event_type":"alert","host":"GTA","os":"slack","bool":true,"id":34}
{"index":{"_id":5}}
{"@timestamp":"1234567895","event_type":"alert","host":"sniper 3d","os":"fedora","id":35}
{"index":{"_id":6}}
{"@timestamp":"1234578896","host_ip":"10.0.0.1","event_type":"alert","host":"doom","bool":true,"os":"redhat","id":36}
{"index":{"_id":7}}
{"@timestamp":"1234567897","event_type":"failure","missing_keyword":"test","host":"doom","bool":true,"os":"redhat","id":37}
{"index":{"_id":8}}
{"@timestamp":"1234577898","event_type":"success","host":"doom","os":"win10","id":38,"date":"1671235200000"}
{"index":{"_id":9}}
{"@timestamp":"1234577899","host_ip":"10.0.0.5","event_type":"success","host":"GTA","bool":true,"os":"win10","id":39}

Запрос образца указывает по меньшей мере один ключ объединения, используя by ключевое слово, и до пяти фильтров:

resp = client.eql.search(
    index="my-index*",
    query="\n    sample by host\n      [any where uptime > 0]\n      [any where port > 100]\n      [any where bool == true]\n  ",
)
print(resp)
const response = await client.eql.search({
  index: "my-index*",
  query:
    "\n    sample by host\n      [any where uptime > 0]\n      [any where port > 100]\n      [any where bool == true]\n  ",
});
console.log(response);
GET /my-index*/_eql/search
{
  "query": """
    sample by host
      [any where uptime > 0]
      [any where port > 100]
      [any where bool == true]
  """
}

По умолчанию свойство ответа hits.sequences содержит до 10 образцов. Каждый образец имеет набор join_keys и массив с одним совпадающим событием для каждого из фильтров. События возвращаются в порядке соответствия фильтрам:

{
  ...
  "hits": {
    "total": {
      "value": 2,
      "relation": "eq"
    },
    "sequences": [
      {
        "join_keys": [
          "doom"                                      
        ],
        "events": [
          {                                           
            "_index": "my-index-000001",
            "_id": "7",
            "_source": {
              "@timestamp": "1234567897",
              "@timestamp_pretty": "17-12-2022",
              "missing_keyword": "yyy",
              "event_type": "failure",
              "host": "doom",
              "uptime": 15,
              "port": 1234,
              "bool": true,
              "os": "redhat",
              "version": "20.2.0",
              "id": 17
            }
          },
          {                                           
            "_index": "my-index-000001",
            "_id": "1",
            "_source": {
              "@timestamp": "1234567891",
              "@timestamp_pretty": "12-12-2022",
              "missing_keyword": "test",
              "type_test": "abc",
              "ip": "10.0.0.1",
              "event_type": "alert",
              "host": "doom",
              "uptime": 0,
              "port": 1234,
              "os": "win10",
              "version": "1.0.0",
              "id": 11
            }
          },
          {                                           
            "_index": "my-index-000001",
            "_id": "6",
            "_source": {
              "@timestamp": "1234568896",
              "@timestamp_pretty": "17-12-2022",
              "event_type": "alert",
              "host": "doom",
              "port": 65123,
              "bool": true,
              "os": "redhat",
              "version": "20.10.0",
              "id": 16
            }
          }
        ]
      },
      {
        "join_keys": [
          "farcry"                                    
        ],
        "events": [
          {
            "_index": "my-index-000001",
            "_id": "3",
            "_source": {
              "@timestamp": "1234567893",
              "@timestamp_pretty": "12-12-2022",
              "event_type": "alert",
              "type_test": "abc",
              "host": "farcry",
              "uptime": 1,
              "port": 1234,
              "bool": false,
              "os": "win10",
              "version": "2.0.0",
              "id": 13
            }
          },
          {
            "_index": "my-index-000001",
            "_id": "10",
            "_source": {
              "@timestamp": "1234567893",
              "missing_keyword": null,
              "ip": "10.0.0.5",
              "event_type": "alert",
              "host": "farcry",
              "uptime": 1,
              "port": 1234,
              "bool": true,
              "os": "win10",
              "version": "1.2.3",
              "id": 110
            }
          },
          {
            "_index": "my-index-000003",
            "_id": "3",
            "_source": {
              "@timestamp": "1334567893",
              "event_type": "alert",
              "host": "farcry",
              "bool": true,
              "os": "win10",
              "id": 33
            }
          }
        ]
      }
    ]
  }
}

События в первом образце имеют значение doom для поля host.

Это событие соответствует первому фильтру.

Это событие соответствует второму фильтру.

Это событие соответствует третьему фильтру.

События во втором образце имеют значение farcry для поля host.

Вы можете указать несколько ключей объединения:

resp = client.eql.search(
    index="my-index*",
    query="\n    sample by host\n      [any where uptime > 0]   by os\n      [any where port > 100]   by op_sys\n      [any where bool == true] by os\n  ",
)
print(resp)
const response = await client.eql.search({
  index: "my-index*",
  query:
    "\n    sample by host\n      [any where uptime > 0]   by os\n      [any where port > 100]   by op_sys\n      [any where bool == true] by os\n  ",
});
console.log(response);
GET /my-index*/_eql/search
{
  "query": """
    sample by host
      [any where uptime > 0]   by os
      [any where port > 100]   by op_sys
      [any where bool == true] by os
  """
}

Этот запрос вернёт образцы, где каждое из событий имеет одинаковое значение для os или op_sys, а также для host. Например:

{
  ...
  "hits": {
    "total": {
      "value": 2,
      "relation": "eq"
    },
    "sequences": [
      {
        "join_keys": [
          "doom",                                      
          "redhat"
        ],
        "events": [
          {
            "_index": "my-index-000001",
            "_id": "7",
            "_source": {
              "@timestamp": "1234567897",
              "@timestamp_pretty": "17-12-2022",
              "missing_keyword": "yyy",
              "event_type": "failure",
              "host": "doom",
              "uptime": 15,
              "port": 1234,
              "bool": true,
              "os": "redhat",
              "version": "20.2.0",
              "id": 17
            }
          },
          {
            "_index": "my-index-000002",
            "_id": "6",
            "_source": {
              "@timestamp": "1234568996",
              "@timestamp_pretty": "2022-12-17",
              "ip": "10.0.0.5",
              "event_type": "alert",
              "host": "doom",
              "port": 65123,
              "bool": true,
              "op_sys": "redhat",
              "id": 26
            }
          },
          {
            "_index": "my-index-000001",
            "_id": "6",
            "_source": {
              "@timestamp": "1234568896",
              "@timestamp_pretty": "17-12-2022",
              "event_type": "alert",
              "host": "doom",
              "port": 65123,
              "bool": true,
              "os": "redhat",
              "version": "20.10.0",
              "id": 16
            }
          }
        ]
      },
      {
        "join_keys": [
          "farcry",
          "win10"
        ],
        "events": [
          {
            "_index": "my-index-000001",
            "_id": "3",
            "_source": {
              "@timestamp": "1234567893",
              "@timestamp_pretty": "12-12-2022",
              "event_type": "alert",
              "type_test": "abc",
              "host": "farcry",
              "uptime": 1,
              "port": 1234,
              "bool": false,
              "os": "win10",
              "version": "2.0.0",
              "id": 13
            }
          },
          {
            "_index": "my-index-000002",
            "_id": "3",
            "_source": {
              "@timestamp": "1234567993",
              "type_test": "abc",
              "@timestamp_pretty": "2022-12-17",
              "event_type": "alert",
              "host": "farcry",
              "uptime": 1,
              "port": 1234,
              "bool": false,
              "op_sys": "win10",
              "id": 23
            }
          },
          {
            "_index": "my-index-000001",
            "_id": "10",
            "_source": {
              "@timestamp": "1234567893",
              "missing_keyword": null,
              "ip": "10.0.0.5",
              "event_type": "alert",
              "host": "farcry",
              "uptime": 1,
              "port": 1234,
              "bool": true,
              "os": "win10",
              "version": "1.2.3",
              "id": 110
            }
          }
        ]
      }
    ]
  }
}

События в данном образце имеют значение doom для поля host и значение redhat для поля os или op_sys.

По умолчанию ответ запроса образца содержит до 10 образцов с одним образцом на каждый набор уникальных ключей объединения. Используйте параметр size, чтобы получить меньший или больший набор образцов. Чтобы получить больше одного образца на набор ключей объединения, используйте параметр max_samples_per_key. Пайпы не поддерживаются для запросов образцов.

resp = client.eql.search(
    index="my-index*",
    max_samples_per_key=2,
    size=20,
    query="\n    sample\n      [any where uptime > 0]   by host,os\n      [any where port > 100]   by host,op_sys\n      [any where bool == true] by host,os\n  ",
)
print(resp)
const response = await client.eql.search({
  index: "my-index*",
  max_samples_per_key: 2,
  size: 20,
  query:
    "\n    sample\n      [any where uptime > 0]   by host,os\n      [any where port > 100]   by host,op_sys\n      [any where bool == true] by host,os\n  ",
});
console.log(response);
GET /my-index*/_eql/search
{
  "max_samples_per_key": 2,     
  "size": 20,                   
  "query": """
    sample
      [any where uptime > 0]   by host,os
      [any where port > 100]   by host,op_sys
      [any where bool == true] by host,os
  """
}

Получить до 2 образцов на набор ключей объединения.

Получить до 20 образцов в общей сложности.

Получение выбранных полей

По умолчанию каждый результат поиска включает документ _source, который представляет собой весь JSON-объект, предоставленный при индексировании документа.

Вы можете использовать параметр запроса filter_path, чтобы отфильтровать ответ API. Например, следующий поиск возвращает только метку времени и PID из _source каждого соответствующего события.

resp = client.eql.search(
    index="my-data-stream",
    filter_path="hits.events._source.@timestamp,hits.events._source.process.pid",
    query="\n    process where process.name == \"regsvr32.exe\"\n  ",
)
print(resp)
const response = await client.eql.search({
  index: "my-data-stream",
  filter_path: "hits.events._source.@timestamp,hits.events._source.process.pid",
  query: '\n    process where process.name == "regsvr32.exe"\n  ',
});
console.log(response);
GET /my-data-stream/_eql/search?filter_path=hits.events._source.@timestamp,hits.events._source.process.pid
{
  "query": """
    process where process.name == "regsvr32.exe"
  """
}

API возвращает следующий ответ.

{
  "hits": {
    "events": [
      {
        "_source": {
          "@timestamp": "2099-12-07T11:07:09.000Z",
          "process": {
            "pid": 2012
          }
        }
      },
      {
        "_source": {
          "@timestamp": "2099-12-07T11:07:10.000Z",
          "process": {
            "pid": 2012
          }
        }
      }
    ]
  }
}

Вы также можете использовать параметр fields для извлечения и форматирования определенных полей в ответе. Это поле идентично параметру API поиска fields.

Поскольку он обращается к отображениям индекса, параметр fields предоставляет несколько преимуществ по сравнению с непосредственным указанием на _source. В частности, параметр fields:

  • Возвращает каждое значение стандартизированным способом, соответствующим типу отображения
  • Принимает многопольные и псевдонимы полей
  • Форматирует даты и пространственные типы данных
  • Извлекает значения временных полей
  • Возвращает поля, рассчитанные скриптом во время индексирования
  • Возвращает поля из связанных индексов, используя вспомогательные временные поля

Следующий запрос поиска использует параметр fields для извлечения значений для поля event.type, всех полей, начинающихся с process., и поля @timestamp. Запрос также использует параметр запроса filter_path для исключения _source каждого совпадения.

resp = client.eql.search(
    index="my-data-stream",
    filter_path="-hits.events._source",
    query="\n    process where process.name == \"regsvr32.exe\"\n  ",
    fields=[
        "event.type",
        "process.*",
        {
            "field": "@timestamp",
            "format": "epoch_millis"
        }
    ],
)
print(resp)
const response = await client.eql.search({
  index: "my-data-stream",
  filter_path: "-hits.events._source",
  query: '\n    process where process.name == "regsvr32.exe"\n  ',
  fields: [
    "event.type",
    "process.*",
    {
      field: "@timestamp",
      format: "epoch_millis",
    },
  ],
});
console.log(response);
GET /my-data-stream/_eql/search?filter_path=-hits.events._source
{
  "query": """
    process where process.name == "regsvr32.exe"
  """,
  "fields": [
    "event.type",
    "process.*",                
    {
      "field": "@timestamp",
      "format": "epoch_millis"  
    }
  ]
}

Принимаются как полные имена полей, так и шаблоны с подстановкой.

Используйте параметр format для применения пользовательского формата для значений поля.

Ответ включает значения в виде плоского списка в разделе fields для каждого совпадения.

{
  ...
  "hits": {
    "total": ...,
    "events": [
      {
        "_index": ".ds-my-data-stream-2099.12.07-000001",
        "_id": "OQmfCaduce8zoHT93o4H",
        "fields": {
          "process.name": [
            "regsvr32.exe"
          ],
          "process.name.keyword": [
            "regsvr32.exe"
          ],
          "@timestamp": [
            "4100324829000"
          ],
          "process.command_line": [
            "regsvr32.exe  /s /u /i:https://...RegSvr32.sct scrobj.dll"
          ],
          "process.command_line.keyword": [
            "regsvr32.exe  /s /u /i:https://...RegSvr32.sct scrobj.dll"
          ],
          "process.executable.keyword": [
            "C:\\Windows\\System32\\regsvr32.exe"
          ],
          "process.pid": [
            2012
          ],
          "process.executable": [
            "C:\\Windows\\System32\\regsvr32.exe"
          ]
        }
      },
      ....
    ]
  }
}

Использование временных полей

Используйте параметр runtime_mappings для извлечения и создания временных полей во время поиска. Используйте параметр fields для включения временных полей в ответ.

Следующий поиск создаёт временное поле day_of_week из @timestamp и возвращает его в ответе.

resp = client.eql.search(
    index="my-data-stream",
    filter_path="-hits.events._source",
    runtime_mappings={
        "day_of_week": {
            "type": "keyword",
            "script": "emit(doc['@timestamp'].value.dayOfWeekEnum.toString())"
        }
    },
    query="\n    process where process.name == \"regsvr32.exe\"\n  ",
    fields=[
        "@timestamp",
        "day_of_week"
    ],
)
print(resp)
const response = await client.eql.search({
  index: "my-data-stream",
  filter_path: "-hits.events._source",
  runtime_mappings: {
    day_of_week: {
      type: "keyword",
      script: "emit(doc['@timestamp'].value.dayOfWeekEnum.toString())",
    },
  },
  query: '\n    process where process.name == "regsvr32.exe"\n  ',
  fields: ["@timestamp", "day_of_week"],
});
console.log(response);
GET /my-data-stream/_eql/search?filter_path=-hits.events._source
{
  "runtime_mappings": {
    "day_of_week": {
      "type": "keyword",
      "script": "emit(doc['@timestamp'].value.dayOfWeekEnum.toString())"
    }
  },
  "query": """
    process where process.name == "regsvr32.exe"
  """,
  "fields": [
    "@timestamp",
    "day_of_week"
  ]
}

API возвращает:

{
  ...
  "hits": {
    "total": ...,
    "events": [
      {
        "_index": ".ds-my-data-stream-2099.12.07-000001",
        "_id": "OQmfCaduce8zoHT93o4H",
        "fields": {
          "@timestamp": [
            "2099-12-07T11:07:09.000Z"
          ],
          "day_of_week": [
            "MONDAY"
          ]
        }
      },
      ....
    ]
  }
}

Указание поля метки времени или категории событий

API поиска EQL по умолчанию использует поля @timestamp и event.category из ECS. Чтобы указать другие поля, используйте параметры timestamp_field и event_category_field:

resp = client.eql.search(
    index="my-data-stream",
    timestamp_field="file.accessed",
    event_category_field="file.type",
    query="\n    file where (file.size > 1 and file.type == \"file\")\n  ",
)
print(resp)
const response = await client.eql.search({
  index: "my-data-stream",
  timestamp_field: "file.accessed",
  event_category_field: "file.type",
  query: '\n    file where (file.size > 1 and file.type == "file")\n  ',
});
console.log(response);
GET /my-data-stream/_eql/search
{
  "timestamp_field": "file.accessed",
  "event_category_field": "file.type",
  "query": """
    file where (file.size > 1 and file.type == "file")
  """
}

Поле категории событий должно быть отображено как поле типа keyword. Поле метки времени должно быть отображено как поле типа date. date_nanos поля метки времени не поддерживаются. Вы не можете использовать поле nested или подполя поля nested в качестве поля метки времени или поля категории событий.

Указание разрыва сортировки

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

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

Чтобы указать поле разрыва сортировки, используйте параметр tiebreaker_field. Если вы используете ECS, рекомендуется использовать event.sequence в качестве поля разрыва сортировки.

resp = client.eql.search(
    index="my-data-stream",
    tiebreaker_field="event.sequence",
    query="\n    process where process.name == \"cmd.exe\" and stringContains(process.executable, \"System32\")\n  ",
)
print(resp)
const response = await client.eql.search({
  index: "my-data-stream",
  tiebreaker_field: "event.sequence",
  query:
    '\n    process where process.name == "cmd.exe" and stringContains(process.executable, "System32")\n  ',
});
console.log(response);
GET /my-data-stream/_eql/search
{
  "tiebreaker_field": "event.sequence",
  "query": """
    process where process.name == "cmd.exe" and stringContains(process.executable, "System32")
  """
}

Фильтрация с помощью Query DSL

Параметр filter использует Query DSL для ограничения документов, на которых выполняется запрос EQL.

resp = client.eql.search(
    index="my-data-stream",
    filter={
        "range": {
            "@timestamp": {
                "gte": "now-1d/d",
                "lt": "now/d"
            }
        }
    },
    query="\n    file where (file.type == \"file\" and file.name == \"cmd.exe\")\n  ",
)
print(resp)
const response = await client.eql.search({
  index: "my-data-stream",
  filter: {
    range: {
      "@timestamp": {
        gte: "now-1d/d",
        lt: "now/d",
      },
    },
  },
  query:
    '\n    file where (file.type == "file" and file.name == "cmd.exe")\n  ',
});
console.log(response);
GET /my-data-stream/_eql/search
{
  "filter": {
    "range": {
      "@timestamp": {
        "gte": "now-1d/d",
        "lt": "now/d"
      }
    }
  },
  "query": """
    file where (file.type == "file" and file.name == "cmd.exe")
  """
}

Выполнение асинхронного поиска EQL

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

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

resp = client.eql.search(
    index="my-data-stream",
    wait_for_completion_timeout="2s",
    query="\n    process where process.name == \"cmd.exe\"\n  ",
)
print(resp)
const response = await client.eql.search({
  index: "my-data-stream",
  wait_for_completion_timeout: "2s",
  query: '\n    process where process.name == "cmd.exe"\n  ',
});
console.log(response);
GET /my-data-stream/_eql/search
{
  "wait_for_completion_timeout": "2s",
  "query": """
    process where process.name == "cmd.exe"
  """
}

Если запрос не завершится в течение установленного таймаута, поиск становится асинхронным и возвращает ответ, который включает:

  • Идентификатор поиска
  • Значение is_partial равное true, указывающее на то, что результаты поиска неполные
  • Значение is_running равное true, указывающее на то, что поиск выполняется

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

{
  "id": "FmNJRUZ1YWZCU3dHY1BIOUhaenVSRkEaaXFlZ3h4c1RTWFNocDdnY2FSaERnUTozNDE=",
  "is_partial": true,
  "is_running": true,
  "took": 2000,
  "timed_out": false,
  "hits": ...
}

Чтобы проверить прогресс асинхронного поиска, используйте API получения асинхронного поиска EQL с идентификатором поиска. Укажите желаемое время ожидания полных результатов в параметре wait_for_completion_timeout.

resp = client.eql.get(
    id="FmNJRUZ1YWZCU3dHY1BIOUhaenVSRkEaaXFlZ3h4c1RTWFNocDdnY2FSaERnUTozNDE=",
    wait_for_completion_timeout="2s",
)
print(resp)
response = client.eql.get(
  id: 'FmNJRUZ1YWZCU3dHY1BIOUhaenVSRkEaaXFlZ3h4c1RTWFNocDdnY2FSaERnUTozNDE=',
  wait_for_completion_timeout: '2s'
)
puts response
const response = await client.eql.get({
  id: "FmNJRUZ1YWZCU3dHY1BIOUhaenVSRkEaaXFlZ3h4c1RTWFNocDdnY2FSaERnUTozNDE=",
  wait_for_completion_timeout: "2s",
});
console.log(response);
GET /_eql/search/FmNJRUZ1YWZCU3dHY1BIOUhaenVSRkEaaXFlZ3h4c1RTWFNocDdnY2FSaERnUTozNDE=?wait_for_completion_timeout=2s

Если значение is_running ответа равно false, асинхронный поиск завершён. Если значение is_partial равно false, возвращаемые результаты поиска завершены.

{
  "id": "FmNJRUZ1YWZCU3dHY1BIOUhaenVSRkEaaXFlZ3h4c1RTWFNocDdnY2FSaERnUTozNDE=",
  "is_partial": false,
  "is_running": false,
  "took": 2000,
  "timed_out": false,
  "hits": ...
}

Другой более лёгкий способ проверки прогресса асинхронного поиска – использование API получения статуса асинхронного поиска EQL с идентификатором поиска.

resp = client.eql.get_status(
    id="FmNJRUZ1YWZCU3dHY1BIOUhaenVSRkEaaXFlZ3h4c1RTWFNocDdnY2FSaERnUTozNDE=",
)
print(resp)
response = client.eql.get_status(
  id: 'FmNJRUZ1YWZCU3dHY1BIOUhaenVSRkEaaXFlZ3h4c1RTWFNocDdnY2FSaERnUTozNDE='
)
puts response
const response = await client.eql.getStatus({
  id: "FmNJRUZ1YWZCU3dHY1BIOUhaenVSRkEaaXFlZ3h4c1RTWFNocDdnY2FSaERnUTozNDE=",
});
console.log(response);
GET /_eql/search/status/FmNJRUZ1YWZCU3dHY1BIOUhaenVSRkEaaXFlZ3h4c1RTWFNocDdnY2FSaERnUTozNDE=
{
  "id": "FmNJRUZ1YWZCU3dHY1BIOUhaenVSRkEaaXFlZ3h4c1RTWFNocDdnY2FSaERnUTozNDE=",
  "is_running": false,
  "is_partial": false,
  "expiration_time_in_millis": 1611690295000,
  "completion_status": 200
}

Изменение периода хранения результатов поиска

По умолчанию API поиска EQL хранит асинхронные запросы в течение пяти дней. После этого периода все запросы и их результаты удаляются. Используйте параметр keep_alive для изменения этого периода хранения:

resp = client.eql.search(
    index="my-data-stream",
    keep_alive="2d",
    wait_for_completion_timeout="2s",
    query="\n    process where process.name == \"cmd.exe\"\n  ",
)
print(resp)
const response = await client.eql.search({
  index: "my-data-stream",
  keep_alive: "2d",
  wait_for_completion_timeout: "2s",
  query: '\n    process where process.name == "cmd.exe"\n  ',
});
console.log(response);
GET /my-data-stream/_eql/search
{
  "keep_alive": "2d",
  "wait_for_completion_timeout": "2s",
  "query": """
    process where process.name == "cmd.exe"
  """
}

Вы можете использовать параметр keep_alive API получения асинхронного поиска EQL, чтобы позже изменить период хранения. Новый период хранения начнётся после выполнения запроса.

resp = client.eql.get(
    id="FmNJRUZ1YWZCU3dHY1BIOUhaenVSRkEaaXFlZ3h4c1RTWFNocDdnY2FSaERnUTozNDE=",
    keep_alive="5d",
)
print(resp)
response = client.eql.get(
  id: 'FmNJRUZ1YWZCU3dHY1BIOUhaenVSRkEaaXFlZ3h4c1RTWFNocDdnY2FSaERnUTozNDE=',
  keep_alive: '5d'
)
puts response
const response = await client.eql.get({
  id: "FmNJRUZ1YWZCU3dHY1BIOUhaenVSRkEaaXFlZ3h4c1RTWFNocDdnY2FSaERnUTozNDE=",
  keep_alive: "5d",
});
console.log(response);
GET /_eql/search/FmNJRUZ1YWZCU3dHY1BIOUhaenVSRkEaaXFlZ3h4c1RTWFNocDdnY2FSaERnUTozNDE=?keep_alive=5d

Используйте API удаления асинхронного поиска EQL, чтобы вручную удалить асинхронный поиск EQL, прежде чем закончится период keep_alive. Если поиск всё ещё выполняется, Elasticsearch отменяет запрос на поиск.

resp = client.eql.delete(
    id="FmNJRUZ1YWZCU3dHY1BIOUhaenVSRkEaaXFlZ3h4c1RTWFNocDdnY2FSaERnUTozNDE=",
)
print(resp)
response = client.eql.delete(
  id: 'FmNJRUZ1YWZCU3dHY1BIOUhaenVSRkEaaXFlZ3h4c1RTWFNocDdnY2FSaERnUTozNDE='
)
puts response
const response = await client.eql.delete({
  id: "FmNJRUZ1YWZCU3dHY1BIOUhaenVSRkEaaXFlZ3h4c1RTWFNocDdnY2FSaERnUTozNDE=",
});
console.log(response);
DELETE /_eql/search/FmNJRUZ1YWZCU3dHY1BIOUhaenVSRkEaaXFlZ3h4c1RTWFNocDdnY2FSaERnUTozNDE=

Сохранение синхронных поисков EQL

По умолчанию API поиска EQL сохраняет только асинхронные поиски. Чтобы сохранить синхронный поиск, установите keep_on_completion в значение true:

resp = client.eql.search(
    index="my-data-stream",
    keep_on_completion=True,
    wait_for_completion_timeout="2s",
    query="\n    process where process.name == \"cmd.exe\"\n  ",
)
print(resp)
const response = await client.eql.search({
  index: "my-data-stream",
  keep_on_completion: true,
  wait_for_completion_timeout: "2s",
  query: '\n    process where process.name == "cmd.exe"\n  ',
});
console.log(response);
GET /my-data-stream/_eql/search
{
  "keep_on_completion": true,
  "wait_for_completion_timeout": "2s",
  "query": """
    process where process.name == "cmd.exe"
  """
}

Ответ включает идентификатор поиска. is_partial и is_running установлены в значение false, что указывает на то, что поиск EQL был синхронным и вернул полные результаты.

{
  "id": "FjlmbndxNmJjU0RPdExBTGg0elNOOEEaQk9xSjJBQzBRMldZa1VVQ2pPa01YUToxMDY=",
  "is_partial": false,
  "is_running": false,
  "took": 52,
  "timed_out": false,
  "hits": ...
}

Используйте API получения результатов асинхронного поиска EQL, чтобы получить те же результаты позже:

resp = client.eql.get(
    id="FjlmbndxNmJjU0RPdExBTGg0elNOOEEaQk9xSjJBQzBRMldZa1VVQ2pPa01YUToxMDY=",
)
print(resp)
response = client.eql.get(
  id: 'FjlmbndxNmJjU0RPdExBTGg0elNOOEEaQk9xSjJBQzBRMldZa1VVQ2pPa01YUToxMDY='
)
puts response
const response = await client.eql.get({
  id: "FjlmbndxNmJjU0RPdExBTGg0elNOOEEaQk9xSjJBQzBRMldZa1VVQ2pPa01YUToxMDY=",
});
console.log(response);
GET /_eql/search/FjlmbndxNmJjU0RPdExBTGg0elNOOEEaQk9xSjJBQzBRMldZa1VVQ2pPa01YUToxMDY=

Сохраненные синхронные поиски всё ещё подчиняются периоду хранения параметра keep_alive. По окончании этого периода поиск и его результаты удаляются.

Также можно проверить только статус сохранённого синхронного поиска без результатов, используя API получения статуса асинхронного поиска EQL.

Также можно вручную удалить сохранённые синхронные поиски, используя API удаления асинхронного поиска EQL.

Запуск поиска EQL по кластерам

Эта функциональность находится в техническом предварительном просмотре и может быть изменена или удалена в будущих версиях. Elastic будет работать над устранением любых проблем, но функции в техническом предварительном просмотре не подпадают под SLA поддержки официальных функций GA.

API поиска EQL поддерживает поиск по кластерам. Однако локальные и удаленные кластеры должны использовать одну и ту же версию Elasticsearch, если у них версии предшествуют 7.17.7 (включительно) или предшествуют 8.5.1 (включительно).

Следующий запрос обновления настроек кластера добавляет два удалённых кластера: cluster_one и cluster_two.

resp = client.cluster.put_settings(
    persistent={
        "cluster": {
            "remote": {
                "cluster_one": {
                    "seeds": [
                        "127.0.0.1:9300"
                    ]
                },
                "cluster_two": {
                    "seeds": [
                        "127.0.0.1:9301"
                    ]
                }
            }
        }
    },
)
print(resp)
response = client.cluster.put_settings(
  body: {
    persistent: {
      cluster: {
        remote: {
          cluster_one: {
            seeds: [
              '127.0.0.1:9300'
            ]
          },
          cluster_two: {
            seeds: [
              '127.0.0.1:9301'
            ]
          }
        }
      }
    }
  }
)
puts response
const response = await client.cluster.putSettings({
  persistent: {
    cluster: {
      remote: {
        cluster_one: {
          seeds: ["127.0.0.1:9300"],
        },
        cluster_two: {
          seeds: ["127.0.0.1:9301"],
        },
      },
    },
  },
});
console.log(response);
PUT /_cluster/settings
{
  "persistent": {
    "cluster": {
      "remote": {
        "cluster_one": {
          "seeds": [
            "127.0.0.1:9300"
          ]
        },
        "cluster_two": {
          "seeds": [
            "127.0.0.1:9301"
          ]
        }
      }
    }
  }
}

Чтобы указать поток данных или индекс на удалённом кластере, используйте синтаксис <cluster>:<target>.

resp = client.eql.search(
    index="cluster_one:my-data-stream,cluster_two:my-data-stream",
    query="\n    process where process.name == \"regsvr32.exe\"\n  ",
)
print(resp)
const response = await client.eql.search({
  index: "cluster_one:my-data-stream,cluster_two:my-data-stream",
  query: '\n    process where process.name == "regsvr32.exe"\n  ',
});
console.log(response);
GET /cluster_one:my-data-stream,cluster_two:my-data-stream/_eql/search
{
  "query": """
    process where process.name == "regsvr32.exe"
  """
}

Настройки EQL-разрыва цепи

Соответствующие настройки разрыва цепи можно найти на странице Разрывов цепи.

© 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/8.17/eql.html

Spec-Zone.ru

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