{
    "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:elasticsearch.audit.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\\=\\[%{DATA:user.name}\\])?",
                    "ES_AUDIT_REALM": "(realm\\=\\[%{WORD:elasticsearch.audit.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_URI_PARAMS": "(params=\\[%{DATA:elasticsearch.audit.url.params}\\])?",
                    "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_URI_PARAMS},?\\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
            }
        },
        {
            "date": {
                "if": "ctx.event.timezone == null",
                "field": "elasticsearch.audit.@timestamp",
                "target_field": "@timestamp",
                "formats": [
                    "yyyy-MM-dd'T'HH:mm:ss,SSS"
                ],
                "on_failure": [{"append": {"field": "error.message", "value": "{{ _ingest.on_failure_message }}"}}]
            }
        },
        {
            "date": {
                "if": "ctx.event.timezone != null",
                "field": "elasticsearch.audit.@timestamp",
                "target_field": "@timestamp",
                "formats": [
                    "yyyy-MM-dd'T'HH:mm:ss,SSS"
                ],
                "timezone": "{{ event.timezone }}",
                "on_failure": [{"append": {"field": "error.message", "value": "{{ _ingest.on_failure_message }}"}}]
            }
        }
    ],
    "on_failure": [
        {
            "set": {
                "field": "error.message",
                "value": "{{ _ingest.on_failure_message }}"
            }
        }
    ]
}
