Skip to content

Commit

Permalink
Ingest ES structured audit logs (#10352)
Browse files Browse the repository at this point in the history
This is a "forward port" of #8852.

In #8852, we taught Filebeat to ingest either structured or unstructured ES audit logs but the resulting fields conformed to the 6.x mapping structure.

In this PR we also teach Filebeat to ingest either structured or unstructured ES audit logs but the resulting fields conform to the 7.0 (ECS-based) mapping structure.
  • Loading branch information
ycombinator authored Jan 29, 2019
1 parent fd149bb commit 5e460ed
Show file tree
Hide file tree
Showing 13 changed files with 421 additions and 70 deletions.
3 changes: 3 additions & 0 deletions CHANGELOG.next.asciidoc
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,8 @@ https://github.com/elastic/beats/compare/v7.0.0-alpha2...master[Check the HEAD d
including `http.response.elapsed_time` (ECS). {pull}10188[10188], {pull}10274[10274]
- Rename multiple fields to `http.response.body.bytes`, from modules "apache", "iis",
"kibana", "nginx" and "traefik", including `http.response.content_length` (ECS). {pull}10188[10188]
- Ingesting Elasticsearch audit logs is only supported with Elasticsearch 6.5.0 and above {pull}10352[10352]
- Migrate Elasticsearch audit logs fields to ECS {pull}10352[10352]

*Heartbeat*

Expand Down Expand Up @@ -191,6 +193,7 @@ https://github.com/elastic/beats/compare/v7.0.0-alpha2...master[Check the HEAD d
- Teach elasticsearch/audit fileset to parse out some more fields. {issue}10134[10134] {pull}10137[10137]
- Add convert_timezone to nginx module. {issue}9839[9839] {pull}10148[10148]
- Add support for Percona in the `slowlog` fileset of `mysql` module. {issue}6665[6665] {pull}10227[10227]
- Added support for ingesting structured Elasticsearch audit logs {pull}10352[10352]

*Heartbeat*

Expand Down
35 changes: 23 additions & 12 deletions filebeat/docs/fields.asciidoc
Original file line number Diff line number Diff line change
Expand Up @@ -3911,6 +3911,17 @@ elasticsearch Module
*`elasticsearch.node.id`*::
+
--
type: keyword
example: DSiWcTyeThWtUXLB9J0BMw
ID of the node
--
*`elasticsearch.node.name`*::
+
--
Expand Down Expand Up @@ -3972,7 +3983,7 @@ The layer from which this event originated: rest, transport or ip_filter
--
*`elasticsearch.audit.origin_type`*::
*`elasticsearch.audit.origin.type`*::
+
--
type: keyword
Expand All @@ -3983,7 +3994,7 @@ Where the request originated: rest (request originated from a REST API request),
--
*`elasticsearch.audit.realm`*::
*`elasticsearch.audit.user.realm`*::
+
--
type: keyword
Expand All @@ -3992,7 +4003,7 @@ The authentication realm
--
*`elasticsearch.audit.roles`*::
*`elasticsearch.audit.user.roles`*::
+
--
type: keyword
Expand Down Expand Up @@ -4025,7 +4036,7 @@ Indices accessed by action
--
*`elasticsearch.audit.request`*::
*`elasticsearch.audit.request.name`*::
+
--
type: keyword
Expand All @@ -4036,39 +4047,39 @@ The type of request that was executed
--
*`elasticsearch.audit.event_type`*::
*`elasticsearch.audit.request_body`*::
+
--
type: alias
alias to: event.type
alias to: http.request.body.content
--
*`elasticsearch.audit.origin_address`*::
*`elasticsearch.audit.event_type`*::
+
--
type: alias
alias to: source.ip
alias to: event.type
--
*`elasticsearch.audit.uri`*::
*`elasticsearch.audit.origin_address`*::
+
--
type: alias
alias to: url.original
alias to: source.ip
--
*`elasticsearch.audit.request_body`*::
*`elasticsearch.audit.uri`*::
+
--
type: alias
alias to: http.request.body.content
alias to: url.original
--
Expand Down
4 changes: 4 additions & 0 deletions filebeat/module/elasticsearch/_meta/fields.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,10 @@
type: group
description: >
fields:
- name: node.id
description: "ID of the node"
example: "DSiWcTyeThWtUXLB9J0BMw"
type: keyword
- name: node.name
description: "Name of the node"
example: "vWNJsZ3"
Expand Down
16 changes: 8 additions & 8 deletions filebeat/module/elasticsearch/audit/_meta/fields.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,15 +6,15 @@
description: "The layer from which this event originated: rest, transport or ip_filter"
example: "rest"
type: keyword
- name: origin_type
- name: origin.type
description: "Where the request originated: rest (request originated from a REST API request), transport (request was received on the transport channel), local_node (the local node issued the request)"
example: "local_node"
type: keyword
- name: realm
- name: user.realm
description: "The authentication realm"
example": "active_directory"
type: keyword
- name: roles
- name: user.roles
description: "Roles to which the principal belongs"
example: [ "kibana_user", "beats_admin" ]
type: keyword
Expand All @@ -26,10 +26,14 @@
description: "Indices accessed by action"
example: [ "foo-2019.01.04", "foo-2019.01.03", "foo-2019.01.06" ]
type: keyword
- name: request
- name: request.name
description: "The type of request that was executed"
example: "ClearScrollRequest"
type: keyword
- name: request_body
type: alias
path: http.request.body.content
migration: true
- name: event_type
type: alias
path: event.type
Expand All @@ -42,10 +46,6 @@
type: alias
path: url.original
migration: true
- name: request_body
type: alias
path: http.request.body.content
migration: true
- name: principal
type: alias
path: user.name
Expand Down
132 changes: 132 additions & 0 deletions filebeat/module/elasticsearch/audit/ingest/pipeline-json.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,132 @@
{
"description": "Pipeline for parsing elasticsearch audit logs in JSON format",
"processors": [
{
"json": {
"field": "message",
"target_field": "elasticsearch.audit"
}
},
{
"dot_expander": {
"field": "event.action",
"path": "elasticsearch.audit"
}
},
{
"rename": {
"field": "elasticsearch.audit.event.action",
"target_field": "event.action"
}
},
{
"dot_expander": {
"field": "event.type",
"path": "elasticsearch.audit"
}
},
{
"rename": {
"field": "elasticsearch.audit.event.type",
"target_field": "elasticsearch.audit.layer"
}
},
{
"dot_expander": {
"field": "origin.address",
"path": "elasticsearch.audit"
}
},
{
"grok": {
"field": "elasticsearch.audit.origin.address",
"patterns": [
"\\[%{IPORHOST:source.ip}\\]:%{INT:source.port:int}",
"%{IPORHOST:source.ip}:%{INT:source.port:int}"
]
}
},
{
"rename": {
"field": "elasticsearch.audit.origin.address",
"target_field": "source.address"
}
},
{
"dot_expander": {
"field": "url.path",
"path": "elasticsearch.audit"
}
},
{
"dot_expander": {
"field": "url.query",
"path": "elasticsearch.audit"
}
},
{
"set": {
"if": "ctx.elasticsearch.audit?.url?.path != null && ctx.elasticsearch.audit?.url?.query == null",
"field": "url.original",
"value": "{{elasticsearch.audit.url.path}}"
}
},
{
"set": {
"if": "ctx.elasticsearch.audit?.url?.path != null && ctx.elasticsearch.audit?.url?.query != null",
"field": "url.original",
"value": "{{elasticsearch.audit.url.path}}?{{elasticsearch.audit.url.query}}"
}
},
{
"remove": {
"if": "ctx.elasticsearch.audit?.url?.path != null",
"field": "elasticsearch.audit.url.path"
}
},
{
"remove": {
"if": "ctx.elasticsearch.audit?.url?.query != null",
"field": "elasticsearch.audit.url.query"
}
},
{
"dot_expander": {
"field": "node.id",
"path": "elasticsearch.audit"
}
},
{
"dot_expander": {
"field": "node.name",
"path": "elasticsearch.audit"
}
},
{
"rename": {
"field": "elasticsearch.audit.node",
"target_field": "elasticsearch.node"
}
},
{
"dot_expander": {
"field": "user.name",
"path": "elasticsearch.audit"
}
},
{
"rename": {
"field": "elasticsearch.audit.user.name",
"target_field": "user.name"
}
}
],
"on_failure": [
{
"set": {
"field": "error.message",
"value": "{{ _ingest.on_failure_message }}"
}
}
]
}
63 changes: 63 additions & 0 deletions filebeat/module/elasticsearch/audit/ingest/pipeline-plaintext.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
{
"description": "Pipeline for parsing elasticsearch audit logs in plaintext format",
"processors": [
{
"grok": {
"field": "message",
"pattern_definitions": {
"ES_TIMESTAMP": "\\[%{TIMESTAMP_ISO8601:elasticsearch.audit.@timestamp}\\]",
"ES_NODE_NAME": "(\\[%{DATA:elasticsearch.node.name}\\])?",
"ES_AUDIT_LAYER": "\\[%{WORD:elasticsearch.audit.layer}\\]",
"ES_AUDIT_EVENT_TYPE": "\\[%{WORD:event.type}\\]",
"ES_AUDIT_ORIGIN_TYPE": "(origin_type\\=\\[%{WORD:elasticsearch.audit.origin.type}\\])?",
"ES_AUDIT_ORIGIN_ADDRESS": "(origin_address\\=\\[%{IPORHOST:source.ip}\\])?",
"ES_AUDIT_PRINCIPAL": "(principal\\=\\[%{WORD:user.name}\\])?",
"ES_AUDIT_REALM": "(realm\\=\\[%{WORD:elasticsearch.audit.user.realm}\\])?",
"ES_AUDIT_ROLES": "(roles\\=\\[%{DATA:elasticsearch.audit.user.roles}\\])?",
"ES_AUDIT_ACTION": "(action\\=\\[%{DATA:elasticsearch.audit.action}(\\[%{DATA:elasticsearch.audit.sub_action}\\])?\\])?",
"ES_AUDIT_URI": "(uri=\\[%{DATA:url.original}\\])?",
"ES_AUDIT_INDICES": "(indices\\=\\[%{DATA:elasticsearch.audit.indices}\\])?",
"ES_AUDIT_REQUEST": "(request\\=\\[%{WORD:elasticsearch.audit.request.name}\\])?",
"ES_AUDIT_REQUEST_BODY": "(request_body\\=\\[%{DATA:http.request.body.content}\\])?"
},
"patterns": [
"%{ES_TIMESTAMP}\\s*%{ES_NODE_NAME}\\s*%{ES_AUDIT_LAYER}\\s*%{ES_AUDIT_EVENT_TYPE}\\s*%{ES_AUDIT_ORIGIN_TYPE},?\\s*%{ES_AUDIT_ORIGIN_ADDRESS},?\\s*%{ES_AUDIT_PRINCIPAL},?\\s*%{ES_AUDIT_REALM},?\\s*%{ES_AUDIT_ROLES},?\\s*%{ES_AUDIT_ACTION},?\\s*%{ES_AUDIT_INDICES},?\\s*%{ES_AUDIT_URI},?\\s*%{ES_AUDIT_REQUEST},?\\s*%{ES_AUDIT_REQUEST_BODY},?"
]
}
},
{
"split": {
"field": "elasticsearch.audit.user.roles",
"separator": ",",
"ignore_missing": true
}
},
{
"split": {
"field": "elasticsearch.audit.indices",
"separator": ",",
"ignore_missing": true
}
},
{
"script": {
"lang": "painless",
"source": "if (ctx.elasticsearch.audit.sub_action != null) { ctx.elasticsearch.audit.action += '[' + ctx.elasticsearch.audit.sub_action + ']' }"
}
},
{
"remove": {
"field": "elasticsearch.audit.sub_action",
"ignore_missing": true
}
}
],
"on_failure": [
{
"set": {
"field": "error.message",
"value": "{{ _ingest.on_failure_message }}"
}
}
]
}
Loading

0 comments on commit 5e460ed

Please sign in to comment.