File: //usr/share/filebeat/module/iis/error/ingest/pipeline.yml
description: Pipeline for parsing IIS error logs. Requires the geoip plugin.
processors:
- set:
field: event.ingested
value: '{{_ingest.timestamp}}'
- rename:
field: message
target_field: event.original
- grok:
field: event.original
patterns:
- '%{TIMESTAMP_ISO8601:iis.error.time} %{IPORHOST:source.address} %{NUMBER:source.port:long}
%{IPORHOST:destination.address} %{IPORHOST:destination.port:long} (?:HTTP/%{NUMBER:http.version}|-)
(?:%{WORD:http.request.method}|-) (?:-|%{NOTSPACE:_tmp.url_orig}) (?:%{NUMBER}|-)
(?:%{NUMBER:http.response.status_code:long}|-) (?:%{NUMBER}|-) (?:-|%{NOTSPACE:iis.error.reason_phrase})
(?:-|%{NOTSPACE:iis.error.queue_name})'
- '%{TIMESTAMP_ISO8601:iis.error.time} %{IPORHOST:source.address} %{NUMBER:source.port:long}
%{IPORHOST:destination.address} %{IPORHOST:destination.port:long} (?:HTTP/%{NUMBER:http.version}|-)
(?:%{WORD:http.request.method}|-) (?:-|%{NOTSPACE:_tmp.url_orig}) (?:%{NUMBER:http.response.status_code:long}|-)
(?:%{NUMBER}|-) (?:-|%{NOTSPACE:iis.error.reason_phrase}) (?:-|%{NOTSPACE:iis.error.queue_name})'
ignore_missing: true
- uri_parts:
field: _tmp.url_orig
ignore_failure: true
- set:
field: url.original
value: "{{{_tmp.url_orig}}}"
ignore_failure: true
if: ctx?._tmp?.url_orig != null && ctx?.url?.original == null
- remove:
field:
- _tmp
ignore_missing: true
- set:
copy_from: '@timestamp'
field: event.created
- date:
field: iis.error.time
target_field: '@timestamp'
formats:
- yyyy-MM-dd HH:mm:ss
- remove:
field: iis.error.time
- grok:
field: destination.address
patterns:
- '%{NOZONEIP:destination.ip}'
pattern_definitions:
NOZONEIP: '[^%]*'
- grok:
field: source.address
patterns:
- '%{NOZONEIP:source.ip}'
pattern_definitions:
NOZONEIP: '[^%]*'
- geoip:
field: source.ip
target_field: source.geo
ignore_failure: true
- geoip:
database_file: GeoLite2-ASN.mmdb
field: source.ip
target_field: source.as
properties:
- asn
- organization_name
ignore_missing: true
- rename:
field: source.as.asn
target_field: source.as.number
ignore_missing: true
- rename:
field: source.as.organization_name
target_field: source.as.organization.name
ignore_missing: true
- set:
field: event.kind
value: event
- append:
field: event.category
value: web
- append:
field: event.category
value: network
if: "ctx?.source?.ip != null && ctx?.destination?.ip != null"
- append:
field: event.type
value: connection
if: "ctx?.source?.ip != null && ctx?.destination?.ip != null"
- append:
field: related.ip
value: "{{source.ip}}"
if: "ctx?.source?.ip != null"
- append:
field: related.ip
value: "{{destination.ip}}"
if: "ctx?.destination?.ip != null"
- set:
field: event.outcome
value: success
if: "ctx?.http?.response?.status_code != null && ctx.http.response.status_code < 400"
- set:
field: event.outcome
value: failure
if: "ctx?.http?.response?.status_code != null && ctx.http.response.status_code >= 400"
- script:
lang: painless
description: This script processor iterates over the whole document to remove fields with null values.
source: |
void handleMap(Map map) {
for (def x : map.values()) {
if (x instanceof Map) {
handleMap(x);
} else if (x instanceof List) {
handleList(x);
}
}
map.values().removeIf(v -> v == null);
}
void handleList(List list) {
for (def x : list) {
if (x instanceof Map) {
handleMap(x);
} else if (x instanceof List) {
handleList(x);
}
}
}
handleMap(ctx);
on_failure:
- set:
field: error.message
value: '{{ _ingest.on_failure_message }}'