文章二十二:ElasticSearch EQL事件查询语言

EQL简介和数据准备

EQL(Event Query Language) 是 Elasticsearch 专为事件型时序数据 (日志、指标、追踪数据)设计的查询语言,主打安全威胁狩猎场景,也可用于通用事件分析。

因为在使用eql进行查询时,数据最好支持Elastic Common Schema (ECS)风格,所以使用官网的数据为大家进行演示,数据的导入方式参照官网:Example: Detect threats with EQL | Elasticsearch Guide 8.17 | Elastic

或者是大家在查看eql的文章时,可以看到他的实例数据的位置

EQL的基本使用

最基本的使用:

复制代码
//规定了事件类型的查询
//es推荐中,eql的查询数据最好是符合ECS规范,event.category是规范中的字段,他就是事件类型
GET eql_test/_eql/search
{
  "query":"""
  process where process.pid == 2012
  """
}

//最基本的查询
GET eql_test/_eql/search
{
  "query":"""
  any where process.pid == 2012
  """
}

针对下面的例子,为大家带来和es的DSL的同义查询语句:

复制代码
GET eql_test/_eql/search
{
  "query":"""
  process where process.pid == 2012
  """
}


#结合上面的解释,DSL语句可以写为

GET eql_test/_search
{
  "query": {
    "bool": {
      "must": [
        {
          "term": {
            "event.category": "process"
          }
        },
        {
          "term": {
            "process.pid": {
              "value": "2012"
            }
          }
        }
      ]
    }
  }
}

使用any 进行查询时相当于的DSL是:

复制代码
//最基本的查询
GET eql_test/_eql/search
{
  "query":"""
  any where process.pid == 2012
  """
}

GET eql_test/_search
{
  "query":{
    "bool": {
      "must": [
        {
          "term": {
            "process.pid": {
              "value": "2012"
            }
          }
        }
      ]
    }
  }
}

自定义事件(查询条件字段):

在上面的内容中我们可以发现,在ecs的规范下,直接使用event.category作为事件的类型进行查询,但是在实际开发中我们可能在处理历史数据或者是在数据的字段设置上没有使用ecs的规则,这里我们可以使用参数event_category_field进行指定哪个字段作为检索的条件,来取代字段event.category..

具体的使用方式如下:

通过配置修改了事件的类型,使用事件type作为查询的条件

复制代码
GET eql_test/_eql/search
{
  "event_category_field":"event.type",
  "query": """
    creation where user.full_name == "bob"
    """
}

使用属性timestamp_field指定时间字段:

复制代码
GET eql_test/_eql/search
{
  "event_category_field":"event.type",
  "timestamp_field":"@timestamp",
  "query": """
    creation where user.full_name == "bob"
    """
}

使用size指定返回数据数量:

复制代码
GET eql_test/_eql/search
{
  "event_category_field":"event.type",
  "timestamp_field":"@timestamp",
  "size":100,
  "query": """
    creation where user.full_name == "bob"
    """
}

filter_path指定返回的字段:

复制代码
GET eql_test/_eql/search?filter_path=hits.total
{
  "event_category_field":"event.type",
  "timestamp_field":"@timestamp",
  "size":100,
  "query": """
    creation where user.full_name == "bob"
    """
}

fields进行字段控制:

复制代码
GET eql_test/_eql/search
{
  "event_category_field": "event.type",
  "timestamp_field": "@timestamp",
  "size": 100,
  "query": """
    creation where user.full_name == "bob"
    """,
  "fields": [
    "system.*",
    {
      "field": "@timestamp",
      "format": "epoch_millis"
    }
  ]
}

eql的高级使用:

runtime_mappin gs结合eql:

runtime_mappings是 ES 7.11+ 提供的查询时动态字段 能力:不修改索引 Mapping、不重索引,就在本次搜索里临时算出新字段,用于过滤 / 聚合 / 排序 / 返回。

注意点:使用脚本是需要使用emit()执行,不使用fields指明字段,这个字段可以用于计算和查询,但是不可以显示出来

复制代码
GET eql_test/_eql/search
{
  "runtime_mappings": {
    "logon_id_@timestamp": {
      "type": "keyword",
      "script": {
        "source": """
          if (doc['logon_id'].size() == 0) {
            return;
          }
          emit(doc['logon_id'].value + '_' + doc['@timestamp'].value.toString());
        """
      }
    }
  },
  "event_category_field": "event.type",
  "query": """
    creation where user.full_name == "bob"
    """,
  "fields": ["logon_id_@timestamp"]
}

Sequence序列查询

sequence = 按时间先后顺序发生的一连串事件。它不是查 "有没有这些事件",而是查:

事件 A 先发生 → 然后 事件 B 发生 → 然后 事件 C 发生必须严格按时间顺序!

复制代码
 GET eql_test/_eql/search
 {
   "wait_for_completion_timeout":"10ms",
   "query":"""
   sequence with maxspan = 1h
   [ process where user.full_name == "bob"]
   [ any where user.full_name == "bob"]
   """
 }

eql进行异步查询:

复制代码
 GET eql_test/_eql/search
 {
   "wait_for_completion_timeout":"10ms",
   "query":"""
   sequence with maxspan = 1h
   [ process where user.full_name == "bob"]
   [ any where user.full_name == "bob"]
   """
 }
 
 GET _eql/search/FkhjLVVPdmQyUkZPbWkwZHdoYVoxb2cdbmZWM1YwaEJSUVNSenVIeUxyazBGUTo2MDg0NjA

pipe管道:

在写eql语句的时候我们可以通过管道获取头或者是尾巴的数据

获取尾部数据的前两条

复制代码
 GET eql_test/_eql/search
 {
   "query":"""
   any where event.category=="process" | tail 2
   """
 }

获取头部数据的前两条

复制代码
  GET eql_test/_eql/search
 {
   "query":"""
   any where event.category=="process" | head 2
   """
 }
相关推荐
大模型探索者7 小时前
2026 企业智能体平台选型指南:从通用到行业深耕,怎么选?
大数据·人工智能
麻瓜生活睁不开眼8 小时前
Android16修改全局桌面视图边框四直角显示为弧边圆角
android·java·深度学习
dear_bi_MyOnly8 小时前
【MyBatis 操作数据库】
java·数据库·学习·mybatis·学习方法
2601_953720828 小时前
【计算机毕业设计】基于Spring Boot的心理健康咨询与评测系统的设计与实现
java·spring boot·后端
丈剑走天涯9 小时前
JDK 17 正式特性
java·开发语言
圣光SG10 小时前
Java操作题练习(七)
java·开发语言·算法
@航空母舰11 小时前
SpringBoot通过Map实现天然的策略模式
java·spring boot·后端
Co_Hui12 小时前
Java 并发编程
java
阿三081212 小时前
跨境电商售后自动化分级标准:哪些能全自动、哪些半自动、哪些禁止自动化
大数据·人工智能·自动化
long31613 小时前
Java 新手入门与实战开发指南
java·开发语言