文章二十二: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
   """
 }
相关推荐
liulilittle1 小时前
LLAMA-CLI 运行千问3.6(R9-7945HX+64G+RTX40608G)
java·前端·llama
后端漫漫2 小时前
Redis 键值对序列化
java·redis
icestone20002 小时前
智能客服如何按客户类型切换话术?一套支持“渠道标签 + 用户自选 + 对话推断“的分类架构设计
大数据·人工智能·ai编程
Lenyiin2 小时前
《LeetCode 顺序刷题》61 - 70
java·c++·python·算法·leetcode·lenyiin
敲代码的瓦龙2 小时前
Android?基础UI控件!!!
java·开发语言
Hesionberger2 小时前
LeetCode 78:子集生成全攻略
java·开发语言·数据结构·python·算法·leetcode·职场和发展
bzmK1DTbd2 小时前
Swagger API文档:Java RESTful服务的自动生成
java·开发语言·restful
前端之虎陈随易2 小时前
为什么今天还会有新语言?MoonBit 想解决什么问题?
大数据·linux·javascript·人工智能·算法·microsoft·typescript
G.晴天2 小时前
Linux常用命令练习流程
java·linux·运维·服务器·tomcat