Beispiele für Parser-Erweiterungen

Unterstützt in:

Dieses Dokument enthält Beispiele für die Erstellung von Parsererweiterungen in verschiedenen Szenarien. Weitere Informationen zu Parsererweiterungen finden Sie unter Parsererweiterungen erstellen.

Beispiele für Parser-Erweiterungen

In den folgenden Attributtabellen finden Sie schnell den benötigten Beispielcode.

Beispiele für No-Code-Lösungen

Format der Logquelle Beispieltitel Beschreibung Parserkonzepte in diesem Beispiel
JSON
(Logtyp: GCP_IDS)
Felder extrahieren Felder aus einem Protokoll im JSON-Format extrahieren Kein Code
JSON
(Logtyp: WORKSPACE_ALERTS)
Felder mit dem Wert „Voraussetzung“ extrahieren Felder aus einem Protokoll im JSON-Format extrahieren und mit einer Vorbedingung in ein wiederkehrendes UDM-Feld normalisieren

Beispiele für Code-Snippets

Format der Logquelle Beispieltitel Beschreibung Parserkonzepte in diesem Beispiel
JSON
(Logtyp: GCP_IDS)
HTTP-User-Agent hinzufügen
  • Extrahiere den User-Agent des Netzwerk-HTTP-Parsers und erstelle eine target hostname aus der requestUrl.
  • Weisen Sie einen Namespace zu, damit assetbasierte Aliasierung und Datenanreicherung durchgeführt werden.
CSV
(Protokolltyp: MISP_IOC)
Extraktion beliebiger Felder in das additional-UDM-Objekt Felder werden in UDM > Entität > additional UDM-Objekt > Schlüssel/Wert-Paar extrahiert. additional UDM-Objekt
Syslog
(Logtyp: POWERSHELL)
Priorität und Schweregrad aus Syslog extrahieren Fügen Sie die Werte „Syslog Facility“ und „Severity“ in die Felder „UDM Security Result Priority“ und „Severity“ ein. Grok-basiert
JSON mit einem Syslog-Header
(Logtyp: WINDOWS_SYSMON)
Dekoration basierend auf einer bedingten Anweisung
  • Fügen Sie dem Feld metadata.description anhand einer Bedingungsanweisung und der Datentypen in Code-Snippets Dekorationen (Kontextinformationen) hinzu.
  • Wenn Sie einen Extraktionsfilter verwenden, wird der ursprüngliche Datentyp möglicherweise beibehalten.
  • In einer Grok-Bedingungsanweisung sollte der ursprüngliche Datentyp für die Auswertung des Felds verwendet werden.
  • Grok-basiert
  • Grok-Bedingte Anweisung
  • Der ursprüngliche Datentyp eines extrahierten Felds kann beibehalten werden.
  • In einer Grok-Bedingungsanweisung sollte der ursprüngliche Datentyp für die Auswertung des Felds verwendet werden.
JSON mit einem Syslog-Header
(Logtyp: WINDOWS_SYSMON)
Datentypen konvertieren
  • Datentypen in einer Parsererweiterung mit der Funktion convert konvertieren
  • Verwenden Sie on_error-Anweisungen, um eine ordnungsgemäße Fehlerbehandlung zu gewährleisten und Fehler bei der Parsererweiterung zu vermeiden.
  • Grok-basiert
  • Datentypen konvertieren
  • Verwenden Sie on_error-Anweisungen, um die Fehlerbehandlung zu definieren.
JSON mit einem Syslog-Header
(Logtyp: WINDOWS_SYSMON)
Temporäre Variablennamen für bessere Lesbarkeit Sie können in Code-Snippets temporäre Variablennamen verwenden und sie später so umbenennen, dass sie dem Namen des endgültigen UDM-Ereignisobjekts entsprechen. Das kann die Lesbarkeit insgesamt verbessern.
  • Grok-basiert
  • Verwenden Sie temporäre Variablennamen und benennen Sie sie später in die endgültigen UDM-Namen der Ausgabe um.
JSON mit einem Syslog-Header
(Logtyp: WINDOWS_SYSMON)
Wiederkehrende Felder Seien Sie vorsichtig, wenn Sie in Code-Snippets mit wiederkehrenden Feldern arbeiten, z. B. dem Feld „security_result“.
XML
(Protokolltyp: WINDOWS_DEFENDER_AV)
Extraktion beliebiger Felder in das additional-Objekt
  • Sie können den Wert „Plattformversion“ extrahieren und speichern, um beispielsweise Berichte zu veralteten Plattformversionen zu erstellen und nach diesen zu suchen.
  • In diesem Beispiel gibt es kein geeignetes standardmäßiges UDM-Feld. Daher werden die Informationen als benutzerdefiniertes Schlüssel/Wert-Paar im additional-Objekt gespeichert.
Das additional-Objekt wird verwendet, um die Informationen als benutzerdefiniertes Schlüssel/Wert-Paar zu speichern.
XML
(Protokolltyp: WINDOWS_DEFENDER_AV)
Zufällige Feldextraktion in den Haupthostnamen
  • Hostnamen aus einem FQDN extrahieren
  • Mit der bedingten Verarbeitung wird ermittelt, ob das Feld principal.hostname überschrieben werden soll.
  • In der Grok-Anweisung wird ein regulärer Ausdruck (Regex) verwendet, um das Feld hostname zu extrahieren. Der reguläre Ausdruck selbst verwendet eine benannte Erfassungsgruppe. Das bedeutet, dass alles, was innerhalb der Klammern übereinstimmt, im Feld hostname gespeichert wird. Dabei wird mit einem oder mehreren Zeichen übereinstimmt, bis ein Punkt gefunden wird. Dabei wird nur die hostname in einem FQDN erfasst.
Grok-overwrite-Anweisung
  • Beim Ausführen der UDM-VORSCHAU-AUSGABE wird jedoch der Fehler „LOG_PARSING_CBN_ERROR: Feld hostname ist bereits in den Daten vorhanden und kann nicht überschrieben werden“ zurückgegeben.
  • Innerhalb einer Grok-Anweisung kann eine benannte Erfassungsgruppe eine vorhandene Variable nicht überschreiben, es sei denn, dies wird explizit mit der overwrite-Anweisung angegeben. In diesem Szenario können wir entweder einen anderen Variablennamen für die benannte Erfassungsgruppe in der Grok-Anweisung verwenden oder (wie in diesem Beispiel gezeigt) die Überschreibungsanweisung verwenden, um die vorhandene Hostnamenvariable explizit zu überschreiben.
  • Grok-basiert
  • Mit der bedingten Verarbeitung wird festgelegt, ob ein Feld überschrieben werden soll.
  • Grok-Anweisung mit regulären Ausdrücken (Regex).
  • Grok-overwrite-Anweisung

JSON-Beispiele

Die folgenden Beispiele zeigen, wie Sie eine Parsererweiterung erstellen, bei der die Protokollquelle im JSON-Format ist.

No-Code – Felder extrahieren

Beispiele für Attribute:

  • Protokollquellenformat: JSON
  • Ansatz für die Datenzuordnung: No-Code
  • Protokolltyp: GCP_IDS
  • Zweck der Parsererweiterung: Felder extrahieren
  • Beschreibung:

    Mehrere netzwerkbezogene Felder werden nicht extrahiert. Da dieses Protokollbeispiel ein strukturiertes Protokoll im JSON-Format ist, können wir den No-Code-Ansatz (Datenfelder zuordnen) verwenden, um die Parsererweiterung zu erstellen.

    Die Originalfelder, die wir extrahieren möchten, sind:

    • total_packets (string)
    • elapsed_time (string)
    • total_bytes (string)

    Dies ist ein Beispiel für einen Roh-Logeintrag:

    {
    "insertId": "625a41542d64c124e7db097ae0906ccb-1@a3",
    "jsonPayload": {
      "destination_port": "80",
      "application": "incomplete",
      "ip_protocol": "tcp",
      "network": "projects/prj-p-shared-base/global/networks/shared-vpc-production",
      "start_time": "2024-10-29T21:14:59Z",
      "source_port": "41936",
      "source_ip_address": "35.191.200.157",
      "total_packets": "6",
      "elapsed_time": "0",
      "destination_ip_address": "192.168.0.11",
      "total_bytes": "412",
      "repeat_count": "1",
      "session_id": "1289742"
    },
    "resource": {
      "type": "ids.googleapis.com/Endpoint",
      "labels": {
        "resource_container": "projects/12345678910",
        "location": "europe-west4-a",
        "id": "p-europe-west4"
      }
    },
    "timestamp": "2024-10-29T21:15:21Z",
    "logName": "projects/prj-p-shared-base/logs/ids.googleapis.com%2Ftraffic",
    "receiveTimestamp": "2024-10-29T21:15:24.051990717Z"
    }
    

    Im Beispiel wird der No-Code-Ansatz verwendet, um eine Parsererweiterung mit der folgenden Datenfeldzuordnung zu erstellen:

    Voraussetzungs Voraussetzungsoperator Voraussetzungswert Pfad zu Rohdaten Zielfeld*
    jsonPayload.total_bytes NOT_EQUALS "" jsonPayload.total_bytes udm.principal.network.received_bytes
    jsonPayload.elapsed_time NOT_EQUALS "" jsonPayload.elapsed_time udm.principal.network.session_duration.seconds
    jsonPayload.total_packets NOT_EQUALS "" jsonPayload.total_packets udm.principal.network.received_packets

    Wenn Sie die Parsererweiterung ausführen, werden die drei extrahierten Felder dem principal.network-Objekt hinzugefügt.

    metadata.product_log_id = "625a41542d64c124e7db097ae0906ccb-1@a3"
    metadata.event_timestamp = "2024-10-29T21:14:59Z"
    metadata.event_type = "NETWORK_CONNECTION"
    metadata.vendor_name = "Google Cloud"
    metadata.product_name = "IDS"
    metadata.ingestion_labels[0].key = "label"
    metadata.ingestion_labels[0].value = "GCP_IDS"
    metadata.log_type = "GCP_IDS"
    principal.ip[0] = "35.191.200.157"
    principal.port = 41936
    principal.network.received_bytes = 412
    principal.network.session_duration.seconds = "0s"
    principal.network.received_packets = 6
    target.ip[0] = "192.168.0.11"
    target.port = 80
    target.application = "incomplete"
    observer.location.country_or_region = "EUROPE"
    observer.location.name = "europe-west4-a"
    observer.resource.name = "projects/12345678910"
    observer.resource.resource_type = "CLOUD_PROJECT"
    observer.resource.attribute.cloud.environment = "GOOGLE_CLOUD_PLATFORM"
    observer.resource.product_object_id = "p-europe-west4"
    network.ip_protocol = "TCP"
    network.session_id = "1289742"
    

No-code – Felder mit dem Wert der Vorbedingung extrahieren

Beispiele für Attribute:

  • Protokollquellenformat: JSON
  • Ansatz für die Datenzuordnung: No-Code
  • Protokolltyp: WORKSPACE_ALERTS
  • Zweck der Parsererweiterung: Felder mit dem Wert der Vorbedingung extrahieren
  • Beschreibung:

    Der ursprüngliche Parser extrahiert nicht die email address des Hauptnutzers, der von einer DLP-Benachrichtigung (Data Loss Prevention) betroffen ist.

    In diesem Beispiel wird eine Codeless-Parsererweiterung verwendet, um die email address zu extrahieren und in ein wiederholbares UDM-Feld mit einer Vorbedingung zu normalisieren.

    Wenn Sie mit wiederkehrenden Feldern in einer No-Code-Parsererweiterung arbeiten, müssen Sie angeben, ob Sie Folgendes tun möchten:

    • replace (alle Werte der wiederkehrenden Felder im vorhandenen UDM-Objekt überschreiben) oder
    • append (extrahierte Werte an wiederkehrende Felder anhängen)

    Weitere Informationen finden Sie im Abschnitt Wiederkehrende Felder.

    In diesem Beispiel werden alle vorhandenen E-Mail-Adressen im normalisierten Feld principal.user.email_address ersetzt.

    Mit Vorbedingungen können Sie bedingte Prüfungen vor der Ausführung eines Extraktionsvorgangs durchführen. In den meisten Fällen ist das Voraussetzungsfeld dasselbe Feld wie das Feld mit Rohdaten, das Sie extrahieren möchten, mit einem Voraussetzungsoperator von not Null, z. B. foo != "".

    Manchmal ist der Wert des Felds mit Rohdaten, den Sie extrahieren möchten, wie in unserem Beispiel, nicht in allen Logeinträgen vorhanden. In diesem Fall können Sie einen anderen Voraussetzungsfilter verwenden, um den Extraktionsvorgang zu filtern. In unserem Beispiel ist das Rohfeld triggeringUserEmail, das Sie extrahieren möchten, nur in Protokollen vorhanden, in denen type = Data Loss Prevention.

    Hier sind Beispielwerte, die in die Erweiterungsfelder des No-Code-Parsers eingegeben werden können:

    Voraussetzungs Voraussetzungsoperator Voraussetzungswert Pfad zu Rohdaten Zielfeld*
    type GLEICH Schutz vor Datenverlust data.ruleViolationInfo.triggeringUserEmail udm.principal.user.email_addresses

    Das folgende Beispiel zeigt die Felder der Parsererweiterung No-Code, die mit den Beispielwerten ausgefüllt sind:

    image2

    Wenn die Parsererweiterung ausgeführt wird, wird email_address dem principal.user-Objekt hinzugefügt.

    metadata.product_log_id = "Ug71LGqBr6Q="
    metadata.event_timestamp = "2022-12-18T12:17:35.154368Z"
    metadata.event_type = "USER_UNCATEGORIZED"
    metadata.vendor_name = "Google Workspace"
    metadata.product_name = "Google Workspace Alerts"
    metadata.product_event_type = "DlpRuleViolation"
    metadata.log_type = "WORKSPACE_ALERTS"
    additional.fields["resource_title"] = "bq-results-20221215-112933-1671103787123.csv"
    principal.user.email_addresses[0] = "foo.bar@altostrat.com"
    target.resource.name = "DRIVE"
    target.resource.resource_type = "STORAGE_OBJECT"
    target.resource.product_object_id = "1wLteoF3VHljS_8_ABCD_VVbhFTfcTQplJ5k1k7cL4r8"
    target.labels[0].key = "resource_title"
    target.labels[0].value = "bq-results-20221321-112933-1671103787697.csv"
    about[0].resource.resource_type = "CLOUD_ORGANIZATION"
    about[0].resource.product_object_id = "C01abcde2"
    security_result[0].about.object_reference.id = "ODU2NjEwZTItMWE2YS0xMjM0LWJjYzAtZTJlMWU2YWQzNzE3"
    security_result[0].category_details[0] = "Data Loss Prevention"
    security_result[0].rule_name = "Sensitive Projects Match"
    security_result[0].summary = "Data Loss Prevention"
    security_result[0].action[0] = "ALLOW"
    security_result[0].severity = "MEDIUM"
    security_result[0].rule_id = "rules/00abcdxs183abcd"
    security_result[0].action_details = "ALERT, DRIVE_WARN_ON_EXTERNAL_SHARING"
    security_result[0].alert_state = "ALERTING"
    security_result[0].detection_fields[0].key = "start_time"
    security_result[0].detection_fields[0].value = "2022-12-18T12:17:35.154368Z"
    security_result[0].detection_fields[1].key = "status"
    security_result[0].detection_fields[1].value = "NOT_STARTED"
    security_result[0].detection_fields[2].key = "trigger"
    security_result[0].detection_fields[2].value = "DRIVE_SHARE"
    security_result[0].rule_labels[0].key = "detector_name"
    security_result[0].rule_labels[0].value = "EMAIL_ADDRESS"
    network.email.to[0] = "foo.bar@altostrat.com"
    

Code-Snippet – HTTP-User-Agent hinzufügen

Beispiele für Attribute:

  • Protokollquellenformat: JSON
  • Ansatz für die Datenzuordnung: Code-Snippet
  • Protokolltyp: GCP_IDS
  • Zweck der Parsererweiterung: HTTP-User-Agent hinzufügen
  • Beschreibung:

    Dies ist ein Beispiel für einen nicht standardmäßigen UDM-Objekttyp, der vom No-Code-Ansatz nicht unterstützt wird und daher ein Code-Snippet erfordert. Der Standard-Parser extrahiert die Network HTTP Parser User Agent-Analyse nicht. Außerdem gilt aus Gründen der Einheitlichkeit:

    1. Aus dem requestUrl wird ein Target Hostname erstellt.
    2. Eine Namespace wird zugewiesen, damit assetbasierte Aliasierung und Datenanreicherung durchgeführt wird.
    # GCP_LOADBALANCING
    # owner: @owner
    # updated: 2022-12-23
    # Custom parser extension that:
    # 1) adds consistent Namespace 
    # 2) adds Parsed User Agent Object 
    filter {
        # Initialize placeholder
        mutate {
            replace => {
                "httpRequest.userAgent" => ""
                "httpRequest.requestUrl" => ""
            }
        }
        json {
            on_error => "not_json"
            source => "message"
            array_function => "split_columns"
        }
        if ![not_json] {
          #1 - Override Namespaces
            mutate {
                replace => {
                    "event1.idm.read_only_udm.principal.namespace" => "TMO"
                }
            }
            mutate {
                replace => {
                    "event1.idm.read_only_udm.target.namespace" => "TMO"
                }
            }
            mutate {
                replace => {
                    "event1.idm.read_only_udm.src.namespace" => "TMO"
                }
            }
            #2 - Parsed User Agent
            if [httpRequest][requestUrl]!= "" {
                grok {
                    match => {
                        "httpRequest.requestUrl" => ["\/\/(?P<_hostname>.*?)\/"]
                    }
                    on_error => "_grok_hostname_failed"
                }
                if ![_grok_hostname_failed] {
                    mutate {
                        replace => {
                            "event1.idm.read_only_udm.target.hostname" => "%{_hostname}"
                        }
                    }
                }
            }
            if [httpRequest][userAgent] != "" {
                mutate {
                    convert => {
                        "httpRequest.userAgent" => "parseduseragent"
                    }
                }
                #Map the converted "user_agent" to the new UDM field "http.parsed_user_agent".
                mutate {
                    rename => {
                        "httpRequest.userAgent" => "event1.idm.read_only_udm.network.http.parsed_user_agent"
                    }
                }
            }
            mutate {
                merge => {
                    "@output" => "event1"
                }
            }
        }
    }
    

CSV-Beispiel

Im folgenden Beispiel wird gezeigt, wie Sie eine Parsererweiterung erstellen, bei der die Protokollquelle im CSV-Format vorliegt.

Code-Snippet – Extrahieren beliebiger Felder in das additional-Objekt

Beispiele für Attribute:

  • Protokollquellenformat: CSV
  • Ansatz für die Datenzuordnung: Code-Snippet
  • Protokolltyp: MISP_IOC
  • Zweck der Parsererweiterung: Zufällige Felder in das additional-Objekt extrahieren
  • Beschreibung:

    In diesem Beispiel wird die UDM-Entitätskontext-Integration „MISP_IOC“ verwendet. Das UDM-Objekt vom Typ „Schlüssel/Wert-Paar“ vom Typ additional wird verwendet, um Kontextinformationen zu erfassen, die vom Standardparser nicht extrahiert werden, und um unternehmensspezifische Felder hinzuzufügen. Beispielsweise eine URL zu ihrer jeweiligen MISP-Instanz.

    Das ist die CSV-basierte Protokollquelle für dieses Beispiel:

    1 9d66d38a-14e1-407f-a4d1-90b82aa1d59f
    2 3908
    3 Network activity
    4 ip-dst
    5 117.253.154.123
    6
    7
    8 1687894564
    9
    10
    11
    12
    13
    14 DigitalSide Malware report\: MD5\: 59ce0baba11893f90527fc951ac69912
    15 ORGNAME
    16 DIGITALSIDE.IT
    17 0
    18 Medium
    19 0
    20 2023-06-23
    21 tlp:white,type:OSINT,source:DigitalSide.IT,source:urlhaus.abuse.ch
    22 1698036218

    Image

    # MISP_IOC
    # owner: @owner
    # updated: 2024-06-21
    # Custom parser extension that:
    # 1) adds a link back to internal MISP tenant 
    # 2) extracts missing fields into UDM > Entity > Additional fields
    filter {
        # Set the base URL for MISP. Remember to replace this placeholder!
        mutate {
            replace => {
                "misp_base_url" => "https://<YOUR_MISP_URL>"
            }
        }
        # Parse the CSV data from the 'message' field. Uses a comma as the separator.
        # The 'on_error' option handles lines that are not properly formatted CSV.
        csv {
            source => "message"
            separator => ","
            on_error => "broken_csv"
        }
        # If the CSV parsing was successful...
        if ![broken_csv] {
            # Rename the CSV columns to more descriptive names.
            mutate {
                rename => {
                    "column2" => "event_id"
                    "column8" => "object_timestamp"
                    "column16" => "event_source_org"
                    "column17" => "event_distribution"
                    "column19" => "event_analysis"
                    "column22" => "attribute_timestamp"
                }
            }
        }
        # Add a link to view the event in MISP, if an event ID is available.
        # "column2" => "event_id"
        if [event_id] != "" {
            mutate {
                replace => {
                    "additional_url.key" => "view_in_misp"
                    "additional_url.value.string_value" => "%{misp_base_url}/events/view/%{event_id}"
                }
            }
            mutate {
                merge => {
                    "event.idm.entity.additional.fields" => "additional_url"
                }
            }
        }
        # Add the object timestamp as an additional field, if available.
        # "column8" => "object_timestamp"
        if [object_timestamp] != "" {
            mutate {
                replace => {
                    "additional_object_timestamp.key" => "object_timestamp"
                    "additional_object_timestamp.value.string_value" => "%{object_timestamp}"
                }
            }
            mutate {
                merge => {
                    "event.idm.entity.additional.fields" => "additional_object_timestamp"
                }
            }
        }
        # Add the event source organization as an additional field, if available.
        # "column16" => "event_source_org"
        if [event_source_org] != "" {
            mutate {
                replace => {
                    "additional_event_source_org.key" => "event_source_org"
                    "additional_event_source_org.value.string_value" => "%{event_source_org}"
                }
            }
            mutate {
                merge => {
                    "event.idm.entity.additional.fields" => "additional_event_source_org"
                }
            }
        }
        # Add the event distribution level as an additional field, if available.
        # Maps numerical values to descriptive strings.
        # "column17" => "event_distribution"
        if [event_distribution] != "" {
            if [event_distribution] == "0" {
                mutate {
                    replace => {
                        "additional_event_distribution.value.string_value" => "YOUR_ORGANIZATION_ONLY"
                    }
                }
            } else if [event_distribution] == "1" {
                mutate {
                    replace => {
                        "additional_event_distribution.value.string_value" => "THIS_COMMUNITY_ONLY"
                    }
                }
            } else if [event_distribution] == "2" {
                mutate {
                    replace => {
                        "additional_event_distribution.value.string_value" => "CONNECTED_COMMUNITIES"
                    }
                }
            } else if [event_distribution] == "3" {
                mutate {
                    replace => {
                        "additional_event_distribution.value.string_value" => "ALL_COMMUNITIES"
                    }
                }
            } else if [event_distribution] == "4" {
                mutate {
                    replace => {
                        "additional_event_distribution.value.string_value" => "SHARING_GROUP"
                    }
                }
            } else if [event_distribution] == "5" {
                mutate {
                    replace => {
                        "additional_event_distribution.value.string_value" => "INHERIT_EVENT"
                    }
                }
            }
            mutate {
                replace => {
                    "additional_event_distribution.key" => "event_distribution"
                }
            }
            mutate {
                merge => {
                    "event.idm.entity.additional.fields" => "additional_event_distribution"
                }
            }
        }
        # Add the event analysis level as an additional field, if available.
        # Maps numerical values to descriptive strings.
        # "column19" => "event_analysis"
        if [event_analysis] != "" {
            if [event_analysis] == "0" {
                mutate {
                    replace => {
                        "additional_event_analysis.value.string_value" => "INITIAL"
                    }
                }
            } else if [event_analysis] == "1" {
                mutate {
                    replace => {
                        "additional_event_analysis.value.string_value" => "ONGOING"
                    }
                }
            } else if [event_analysis] == "2" {
                mutate {
                    replace => {
                        "additional_event_analysis.value.string_value" => "COMPLETE"
                    }
                }
            }
            mutate {
                replace => {
                    "additional_event_analysis.key" => "event_analysis"
                }
            }
            mutate {
                merge => {
                    "event.idm.entity.additional.fields" => "additional_event_analysis"
                }
            }
        }
        # Add the attribute timestamp as an additional field, if available.
        # "column22" => "attribute_timestamp" 
        if [attribute_timestamp] != "" {
            mutate {
                replace => {
                    "additional_attribute_timestamp.key" => "attribute_timestamp"
                    "additional_attribute_timestamp.value.string_value" => "%{attribute_timestamp}"
                }
            }
            mutate {
                merge => {
                    "event.idm.entity.additional.fields" => "additional_attribute_timestamp"
                }
            }
        }
        # Finally, merge the 'event' data into the '@output' field.
        mutate {
            merge => {
                "@output" => "event"
            }
        }
    }
    

    Wenn Sie die Parsererweiterung ausführen, werden die benutzerdefinierten Felder aus der CSV-Datei dem additional-Objekt hinzugefügt.

    metadata.product_entity_id = "9d66d38a-14e1-407f-a4d1-90b82aa1d59f"
    metadata.collected_timestamp = "2024-10-31T15:16:08Z"
    metadata.vendor_name = "MISP"
    metadata.product_name = "MISP"
    metadata.entity_type = "IP_ADDRESS"
    metadata.description = "ip-dst"
    metadata.interval.start_time = "2023-06-27T19:36:04Z"
    metadata.interval.end_time = "9999-12-31T23:59:59Z"
    metadata.threat[0].category_details[0] = "Network activity"
    metadata.threat[0].description = "tlp:white,type:OSINT,source:DigitalSide.IT,source:urlhaus.abuse.ch - additional info: DigitalSide Malware report: MD5: 59ce0baba11893f90527fc951ac69912"
    metadata.threat[0].severity_details = "Medium"
    metadata.threat[0].threat_feed_name = "DIGITALSIDE.IT"
    entity.ip[0] = "117.253.154.123"
    additional.fields["view_in_misp"] = "https:///events/view/3908"
    additional.fields["object_timestamp"] = "1687894564"
    additional.fields["event_source_org"] = "DIGITALSIDE.IT"
    additional.fields["event_distribution"] = "YOUR_ORGANIZATION_ONLY"
    additional.fields["event_analysis"] = "INITIAL"
    additional.fields["attribute_timestamp"] = "1698036218"
    

Grok-Beispiele

Die folgenden Beispiele zeigen, wie Sie Grok-basierte Parsererweiterungen erstellen.

Code-Snippet (und Grok) – Priorität und Schweregrad extrahieren

Beispiele für Attribute:

  • Logquellenformat: Syslog
  • Ansatz für die Datenzuordnung: Code-Snippet mit Grok
  • Protokolltyp: POWERSHELL
  • Zweck der Parsererweiterung: Priorität und Schweregrad extrahieren
  • Beschreibung:

    In diesem Beispiel wird eine Grok-basierte Parsererweiterung erstellt, um die Werte Syslog Facility und Severity in die Felder „UDM Security Result“ Priority und Severity zu extrahieren.

    filter {
        # Use grok to parse syslog messages. The on_error clause handles messages that don't match the pattern.
        grok {
            match => {
                "message" => [
                    # Extract message with syslog headers.
                    "(<%{POSINT:_syslog_priority}>)%{SYSLOGTIMESTAMP:datetime} %{DATA:logginghost}: %{GREEDYDATA:log_data}"
                ]
            }
            on_error => "not_supported_format"
        }
        # If the grok parsing failed, tag the event as unsupported and drop it.
        if ![not_supported_format] {
            if [_syslog_priority] != "" {
                if [_syslog_priority] =~ /0|8|16|24|32|40|48|56|64|72|80|88|96|104|112|120|128|136|144|152|160|168|176|184/ {
                    mutate { replace => { "_security_result.severity_details" => "EMERGENCY" } } 
                }
                if [_syslog_priority] =~ /1|9|17|25|33|41|49|57|65|73|81|89|97|105|113|121|129|137|145|153|161|169|177|185/ {
                    mutate { replace => { "_security_result.severity_details" => "ALERT" } } 
                }
                if [_syslog_priority] =~ /2|10|18|26|34|42|50|58|66|74|82|90|98|106|114|122|130|138|146|154|162|170|178|186/ {
                    mutate { replace => { "_security_result.severity_details" => "CRITICAL" } }
                }
                if [_syslog_priority] =~ /3|11|19|27|35|43|51|59|67|75|83|91|99|107|115|123|131|139|147|155|163|171|179|187/ {
                    mutate { replace => { "_security_result.severity_details" => "ERROR" } }
                }
                if [_syslog_priority] =~ /4|12|20|28|36|44|52|60|68|76|84|92|100|108|116|124|132|140|148|156|164|172|180|188/ {
                    mutate { replace => { "_security_result.severity_details" => "WARNING" } }
                }
                if [_syslog_priority] =~ /5|13|21|29|37|45|53|61|69|77|85|93|101|109|117|125|133|141|149|157|165|173|181|189/ {
                    mutate { replace => { "_security_result.severity_details" => "NOTICE" } }
                }
                if [_syslog_priority] =~ /6|14|22|30|38|46|54|62|70|78|86|94|102|110|118|126|134|142|150|158|166|174|182|190/ {
                    mutate { replace => { "_security_result.severity_details" => "INFORMATIONAL" } }
                }
                if [_syslog_priority] =~ /7|15|23|31|39|47|55|63|71|79|87|95|103|111|119|127|135|143|151|159|167|175|183|191/ {
                    mutate { replace => { "_security_result.severity_details" => "DEBUG" } }
                }
                # Facilities (mapped to priority)
                if [_syslog_priority] =~ /0|1|2|3|4|5|6|7/ { 
                    mutate { replace => { "_security_result.priority_details" => "KERNEL" } } 
                }
                if [_syslog_priority] =~ /8|9|10|11|12|13|14|15/ { 
                    mutate { replace => { "_security_result.priority_details" => "USER" } } 
                }
                if [_syslog_priority] =~ /16|17|18|19|20|21|22|23/ { 
                    mutate { replace => { "_security_result.priority_details" => "MAIL" } } 
                }
                if [_syslog_priority] =~ /24|25|26|27|28|29|30|31/ { 
                    mutate { replace => { "_security_result.priority_details" => "SYSTEM" } } 
                }
                if [_syslog_priority] =~ /32|33|34|35|36|37|38|39/ { 
                    mutate { replace => { "_security_result.priority_details" => "SECURITY" } } 
                }
                if [_syslog_priority] =~ /40|41|42|43|44|45|46|47/ { 
                    mutate { replace => { "_security_result.priority_details" => "SYSLOG" } } 
                }
                if [_syslog_priority] =~ /48|49|50|51|52|53|54|55/ { 
                    mutate { replace => { "_security_result.priority_details" => "LPD" } } 
                }
                if [_syslog_priority] =~ /56|57|58|59|60|61|62|63/ { 
                    mutate { replace => { "_security_result.priority_details" => "NNTP" } } 
                }
                if [_syslog_priority] =~ /64|65|66|67|68|69|70|71/ { 
                    mutate { replace => { "_security_result.priority_details" => "UUCP" } } 
                }
                if [_syslog_priority] =~ /72|73|74|75|76|77|78|79/ { 
                    mutate { replace => { "_security_result.priority_details" => "TIME" } } 
                }
                if [_syslog_priority] =~ /80|81|82|83|84|85|86|87/ { 
                    mutate { replace => { "_security_result.priority_details" => "SECURITY" } } 
                }
                if [_syslog_priority] =~ /88|89|90|91|92|93|94|95/ { 
                    mutate { replace => { "_security_result.priority_details" => "FTPD" } } 
                }
                if [_syslog_priority] =~ /96|97|98|99|100|101|102|103/ { 
                    mutate { replace => { "_security_result.priority_details" => "NTPD" } } 
                }
                if [_syslog_priority] =~ /104|105|106|107|108|109|110|111/ { 
                    mutate { replace => { "_security_result.priority_details" => "LOGAUDIT" } } 
                }
                if [_syslog_priority] =~ /112|113|114|115|116|117|118|119/ { 
                    mutate { replace => { "_security_result.priority_details" => "LOGALERT" } } 
                }
                if [_syslog_priority] =~ /120|121|122|123|124|125|126|127/ { 
                    mutate { replace => { "_security_result.priority_details" => "CLOCK" } } 
                }
                if [_syslog_priority] =~ /128|129|130|131|132|133|134|135/ { 
                    mutate { replace => { "_security_result.priority_details" => "LOCAL0" } } 
                }
                if [_syslog_priority] =~ /136|137|138|139|140|141|142|143/ { 
                    mutate { replace => { "_security_result.priority_details" => "LOCAL1" } } 
                }
                if [_syslog_priority] =~ /144|145|146|147|148|149|150|151/ { 
                    mutate { replace => { "_security_result.priority_details" => "LOCAL2" } } 
                }
                if [_syslog_priority] =~ /152|153|154|155|156|157|158|159/ { 
                    mutate { replace => { "_security_result.priority_details" => "LOCAL3" } } 
                }
                if [_syslog_priority] =~ /160|161|162|163|164|165|166|167/ { 
                    mutate { replace => { "_security_result.priority_details" => "LOCAL4" } } 
                }
                if [_syslog_priority] =~ /168|169|170|171|172|173|174|175/ { 
                    mutate { replace => { "_security_result.priority_details" => "LOCAL5" } } 
                }
                if [_syslog_priority] =~ /176|177|178|179|180|181|182|183/ { 
                    mutate { replace => { "_security_result.priority_details" => "LOCAL6" } } 
                }
                if [_syslog_priority] =~ /184|185|186|187|188|189|190|191/ { 
                    mutate { replace => { "_security_result.priority_details" => "LOCAL7" } } 
                }
                mutate {
                    merge => {
                        "event.idm.read_only_udm.security_result" => "_security_result"
                    }
                }
            }
            mutate {
                merge => {
                    "@output" => "event"
                }
            }
        }
    }
    

    Die Ergebnisse der Parsererweiterung werden im menschenlesbaren Format angezeigt.

    metadata.product_log_id = "6161053"
    metadata.event_timestamp = "2024-10-31T15:10:10Z"
    metadata.event_type = "PROCESS_LAUNCH"
    metadata.vendor_name = "Microsoft"
    metadata.product_name = "PowerShell"
    metadata.product_event_type = "600"
    metadata.description = "Info"
    metadata.log_type = "POWERSHELL"
    principal.hostname = "win-adfs.lunarstiiiness.com"
    principal.resource.name = "in_powershell"
    principal.resource.resource_subtype = "im_msvistalog"
    principal.asset.hostname = "win-adfs.lunarstiiiness.com"
    target.hostname = "Default Host"
    target.process.command_line = "C:\Program Files\Microsoft Azure AD Sync\Bin\miiserver.exe"
    target.asset.hostname = "Default Host"
    target.asset.asset_id = "Host ID:bf203e94-72cf-4649-84a5-fc02baedb75f"
    security_result[0].severity_details = "INFORMATIONAL"
    security_result[0].priority_details = "USER"
    

Code-Snippet (und Grok) – Ereignisdekoration, Namen temporärer Variablen und Datentypkonvertierung

Beispiele für Attribute:

  • Protokollquellenformat: JSON mit einer Syslog-Überschrift
  • Ansatz für die Datenzuordnung: Code-Snippet mit Grok
  • Protokolltyp: WINDOWS_SYSMON
  • Verwendung der Parsererweiterung: Dekorieren von Ereignissen, temporären Variablennamen und Datentypen
  • Beschreibung:

    In diesem Beispiel wird gezeigt, wie Sie beim Erstellen einer Parsererweiterung die folgenden Aktionen ausführen:

    Dekoration basierend auf einer bedingten Anweisung

    In diesem Beispiel werden Erklärungen dazu hinzugefügt, was die einzelnen Ereignistypen in WINDOWS_SYSMON bedeuten. Dabei wird die Ereignis-ID mit einer bedingten Anweisung geprüft und dann eine Description hinzugefügt. Beispiel: EventID 1 ist ein Process Creation-Ereignis.

    Wenn Sie einen Extraktionsfilter verwenden, z. B. JSON, wird der ursprüngliche Datentyp möglicherweise beibehalten.

    Im folgenden Beispiel wird der Wert EventID standardmäßig als Ganzzahl extrahiert. In der Bedingten Anweisung wird der Wert von EventID als Ganzzahl und nicht als String ausgewertet.

    if [EventID] == 1 {
      mutate {
        replace => {
          "_description" => "[1] Process creation"
        }
      }
    }
    

    Datentyp-Umwandlung

    Mit der Funktion „convert“ können Sie Datentypen in einer Parsererweiterung konvertieren.

    mutate {
      convert => {
        "EventID" => "string"
      }
      on_error => "_convert_EventID_already_string"
    }
    

    Temporäre Variablennamen für bessere Lesbarkeit

    Sie können in Code-Snippets temporäre Variablennamen verwenden und sie später so umbenennen, dass sie dem Namen des endgültigen UDM-Ereignisobjekts entsprechen. Das kann die Lesbarkeit insgesamt verbessern.

    Im folgenden Beispiel wird die Variable description in event.idm.read_only_udm.metadata.description umbenannt:

    mutate {
      rename => {
        "_description" => "event.idm.read_only_udm.metadata.description"
      }
    }
    

    Wiederkehrende Felder

    Die vollständige Parsererweiterung sieht so aus:

    filter {
    # initialize variable
    mutate {
      replace => {
        "EventID" => ""
      }
    }
    # Use grok to parse syslog messages.
    # The on_error clause handles messages that don't match the pattern.
    grok {
      match => {
        "message" => [
          "(<%{POSINT:_syslog_priority}>)%{SYSLOGTIMESTAMP:datetime} %{DATA:logginghost}: %{GREEDYDATA:log_data}"
        ]
      }
      on_error => "not_supported_format"
    }
    if ![not_supported_format] {
      json {
        source => "log_data"
        on_error => "not_json"
      }
      if ![not_json] {
        if [EventID] == 1 {
          mutate {
            replace => {
              "_description" => "[1] Process creation"
            }
          }
        }
        if [EventID] == 2 {
          mutate {
            replace => {
              "_description" => "[2] A process changed a file creation time"
            }
          }
        }
        if [EventID] == 3 {
          mutate {
            replace => {
              "_description" => "[3] Network connection"
            }
          }
        }
        if [EventID] == 4 {
          mutate {
            replace => {
              "_description" => "[4] Sysmon service state changed"
            }
          }
        }
        if [EventID] == 5 {
          mutate {
            replace => {
              "_description" => "[5] Process terminated"
            }
          }
        }
        if [EventID] == 6 {
          mutate {
            replace => {
              "_description" => "[6] Driver loaded"
            }
          }
        }
        if [EventID] == 7 {
          mutate {
            replace => {
              "_description" => "[7] Image loaded"
            }
          }
        }
        if [EventID] == 8 {
          mutate {
            replace => {
              "_description" => "[8] CreateRemoteThread"
            }
          }
        }
        if [EventID] == 9 {
          mutate {
            replace => {
              "_description" => "[9] RawAccessRead"
            }
          }
        }
        if [EventID] == 10 {
          mutate {
            replace => {
              "_description" => "[10] ProcessAccess"
            }
          }
        }
        if [EventID] == 11 {
          mutate {
            replace => {
              "_description" => "[11] FileCreate"
            }
          }
        }
        if [EventID] == 12 {
          mutate {
            replace => {
              "_description" => "[12] RegistryEvent (Object create and delete)"
            }
          }
        }
        if [EventID] == 13 {
          mutate {
            replace => {
              "_description" => "[13] RegistryEvent (Value Set)"
            }
          }
        }
        if [EventID] == 14 {
          mutate {
            replace => {
              "_description" => "[14] RegistryEvent (Key and Value Rename)"
            }
          }
        }
        if [EventID] == 15 {
          mutate {
            replace => {
              "_description" => "[15] FileCreateStreamHash"
            }
          }
        }
        if [EventID] == 16 {
          mutate {
            replace => {
              "_description" => "[16] ServiceConfigurationChange"
            }
          }
        }
        if [EventID] == 17 {
          mutate {
            replace => {
              "_description" => "[17] PipeEvent (Pipe Created)"
            }
          }
        }
        if [EventID] == 18 {
          mutate {
            replace => {
              "_description" => "[18] PipeEvent (Pipe Connected)"
            }
          }
        }
        if [EventID] == 19 {
          mutate {
            replace => {
              "_description" => "[19] WmiEvent (WmiEventFilter activity detected)"
            }
          }
        }
        if [EventID] == 20 {
          mutate {
            replace => {
              "_description" => "[20] WmiEvent (WmiEventConsumer activity detected)"
            }
          }
        }
        if [EventID] == 21 {
          mutate {
            replace => {
              "_description" => "[21] WmiEvent (WmiEventConsumerToFilter activity detected)"
            }
          }
        }
        if [EventID] == 22 {
          mutate {
            replace => {
              "_description" => "[22] DNSEvent (DNS query)"
            }
          }
        }
        if [EventID] == 23 {
          mutate {
            replace => {
              "_description" => "[23] FileDelete (File Delete archived)"
            }
          }
        }
        if [EventID] == 24 {
          mutate {
            replace => {
              "_description" => "[24] ClipboardChange (New content in the clipboard)"
            }
          }
        }
        if [EventID] == 25 {
          mutate {
            replace => {
              "_description" => "[25] ProcessTampering (Process image change)"
            }
          }
        }
        if [EventID] == 26 {
          mutate {
            replace => {
              "_description" => "[26] FileDeleteDetected (File Delete logged)"
            }
          }
        }
        if [EventID] == 255 {
          mutate {
            replace => {
              "_description" => "[255] Error"
            }
          }
        }
        mutate {
          rename => {
            "_description" => "event.idm.read_only_udm.metadata.description"
          }
        }
        statedump{}
        mutate {
          merge => {
            "@output" => "event"
          }
        }
      }
    }
    }
    

    Wenn die Parsererweiterung ausgeführt wird, wird die Dekoration dem Feld metadata.description hinzugefügt.

    metadata.product_log_id = "6008459"
    metadata.event_timestamp = "2024-10-31T14:41:53.442Z"
    metadata.event_type = "REGISTRY_CREATION"
    metadata.vendor_name = "Microsoft"
    metadata.product_name = "Microsoft-Windows-Sysmon"
    metadata.product_event_type = "12"
    metadata.description = "[12] RegistryEvent (Object create and delete)"
    metadata.log_type = "WINDOWS_SYSMON"
    additional.fields["thread_id"] = "3972"
    additional.fields["channel"] = "Microsoft-Windows-Sysmon/Operational"
    additional.fields["Keywords"] = "-9223372036854776000"
    additional.fields["Opcode"] = "Info"
    additional.fields["ThreadID"] = "3972"
    principal.hostname = "win-adfs.lunarstiiiness.com"
    principal.user.userid = "tim.smith_admin"
    principal.user.windows_sid = "S-1-5-18"
    principal.process.pid = "6856"
    principal.process.file.full_path = "C:\Windows\system32\wsmprovhost.exe"
    principal.process.product_specific_process_id = "SYSMON:{927d35bf-a374-6495-f348-000000002900}"
    principal.administrative_domain = "LUNARSTIIINESS"
    principal.asset.hostname = "win-adfs.lunarstiiiness.com"
    target.registry.registry_key = "HKU\S-1-5-21-3263964631-4121654051-1417071188-1116\Software\Policies\Microsoft\SystemCertificates\CA\Certificates"
    observer.asset_id = "5770385F:C22A:43E0:BF4C:06F5698FFBD9"
    observer.process.pid = "2556"
    about[0].labels[0].key = "Category ID"
    about[0].labels[0].value = "RegistryEvent"
    security_result[0].rule_name = "technique_id=T1553.004,technique_name=Install Root Certificate"
    security_result[0].summary = "Registry object added or deleted"
    security_result[0].severity = "INFORMATIONAL"
    security_result[1].rule_name = "EventID: 12"
    security_result[2].summary = "12"
    

XML-Beispiele

Die folgenden Beispiele zeigen, wie Sie eine Parsererweiterung erstellen, wenn die Protokollquelle im XML-Format vorliegt.

Code-Snippet – Extrahieren beliebiger Felder in das additional-Objekt

Beispiele für Attribute:

  • Logquellenformat: XML
  • Ansatz für die Datenzuordnung: Code-Snippet
  • Protokolltyp: WINDOWS_DEFENDER_AV
  • Zweck der Parsererweiterung: Beliebige Feldextraktion in das additional-Objekt
  • Beschreibung:

    In diesem Beispiel soll der Wert Platform Version extrahiert und gespeichert werden, damit beispielsweise Berichte zu outdated platform versions erstellt und nach outdated platform versions gesucht werden kann.

    Bei der Überprüfung des Dokuments Wichtige UDM-Felder wurde kein geeignetes standardmäßiges UDM-Feld gefunden. In diesem Beispiel wird daher das additional-Objekt verwendet, um diese Informationen als benutzerdefiniertes Schlüssel/Wert-Paar zu speichern.

    # Parser Extension for WINDOWS_DEFENDER_AV
    # 2024-10-29: cmmartin: Extracting 'Platform Version' into Additional
    filter {
        # Uses XPath to target the specific element(s)
        xml {
            source => "message"
                xpath => {
                    "/Event/EventData/Data[@Name='Platform version']" => "platform_version"
            }
            on_error => "_xml_error"
        }
        # Conditional processing: Only proceed if XML parsing was successful
        if ![_xml_error] {
            # Prepare the additional field structure using a temporary variable
            mutate{
                replace => {
                    "additional_platform_version.key" => "Platform Version"
                    "additional_platform_version.value.string_value" => "%{platform_version}"
                }
                on_error => "no_platform_version"
            }
            # Merge the additional field into the event1 structure.
            if ![no_platform_version] {
                mutate {
                    merge => {
                        "event1.idm.read_only_udm.additional.fields" => "additional_platform_version"
                    }
                }
            }
            mutate {
                merge => {
                    "@output" => "event1"
                }
            }
        }
    }
    

    Wenn Sie die UDM-VORSCHAU-AUSGABE ausführen, sehen Sie, dass das neue Feld erfolgreich hinzugefügt wurde.

    metadata.event_timestamp = "2024-10-29T14:08:52Z"
    metadata.event_type = "STATUS_HEARTBEAT"
    metadata.vendor_name = "Microsoft"
    metadata.product_name = "Windows Defender AV"
    metadata.product_event_type = "MALWAREPROTECTION_SERVICE_HEALTH_REPORT"
    metadata.description = "Endpoint Protection client health report (time in UTC)."
    metadata.log_type = "WINDOWS_DEFENDER_AV"
    additional.fields["Platform Version"] = "4.18.24080.9"
    principal.hostname = "win-dc-01.ad.1823127835827.altostrat.com"
    security_result[0].description = "EventID: 1151"
    security_result[0].action[0] = "ALLOW"
    security_result[0].severity = "LOW"
    

Code-Snippet (und Grok) – Extrahieren beliebiger Felder in den Haupthostnamen

Beispiele für Attribute:

  • Logquellenformat: XML
  • Ansatz für die Datenzuordnung: Code-Snippet mit Grok
  • Protokolltyp: WINDOWS_DEFENDER_AV
  • Zweck der Parsererweiterung: Beliebiges Feld in den Haupthostnamen extrahieren
  • Beschreibung:

    In diesem Beispiel soll der Wert Hostname aus einem FQDN extrahiert und das Feld principal.hostname überschrieben werden.

    In diesem Beispiel wird geprüft, ob das Feld „Computer name“ im Rohprotokoll ein FQDN enthält. In diesem Fall wird nur der Teil Hostname extrahiert und das UDM-Feld Principal Hostname überschrieben.

    Nach der Überprüfung des Parsers und des Dokuments Wichtige UDM-Felder ist klar, dass das Feld principal.hostname verwendet werden sollte.

    # Parser Extension for WINDOWS_DEFENDER_AV
    # 2024-10-29: Extract Hostname from FQDN and overwrite principal.hostname
    filter {
        # Uses XPath to target the specific element(s)
        xml {
            source => "message"
                xpath => {
                    "/Event/System/Computer" => "hostname"
            }
            on_error => "_xml_error"
        }
        # Conditional processing: Only proceed if XML parsing was successful
        if ![_xml_error] {
      # Extract all characters before the first dot in the hostname variable
            grok {
                match => { "hostname" => "(?<hostname>[^.]+)" }
            }
            mutate {
                replace => {
                    "event1.idm.read_only_udm.principal.hostname" => "%{hostname}"
                }
            }
            mutate {
                merge => {
                    "@output" => "event1"
                }
            }
        }
    }
    

    Bei dieser Parsererweiterung wird mit einer Grok-Anweisung ein regulärer Ausdruck (Regex) ausgeführt, um das Feld hostname zu extrahieren. Der reguläre Ausdruck selbst verwendet eine benannte Erfassungsgruppe. Das bedeutet, dass alles, was in den Klammern übereinstimmt, im Feld hostname gespeichert wird. Dabei wird mit einem oder mehreren Zeichen übereinstimmt, bis ein Punkt gefunden wird. Dabei wird nur die hostname in einer FQDN erfasst.

    Beim Ausführen der UDM-VORAUSSEHENDEN ERGEBNISAUSGABE wird jedoch ein Fehler zurückgegeben. Was ist der Grund dafür?

    generic::unknown: pipeline.ParseLogEntry failed:
     LOG_PARSING_CBN_ERROR: "generic::internal: pipeline failed: filter grok (2) failed: 
    field\ "hostname\" already exists in data and is not overwritable"
    

    Grok-overwrite-Anweisung

    Innerhalb einer Grok-Anweisung kann eine benannte Erfassungsgruppe eine vorhandene Variable nur dann überschreiben, wenn dies explizit mit der overwrite-Anweisung angegeben wird. In diesem Szenario können wir entweder einen anderen Variablennamen für die benannte Erfassungsgruppe in der Grok-Anweisung verwenden oder, wie im folgenden Code-Snippet gezeigt, die overwrite-Anweisung verwenden, um die vorhandene hostname-Variable explizit zu überschreiben.

    # Parser Extension for WINDOWS_DEFENDER_AV
    # 2024-10-29: cmmartin: Overwriting principal Hostname
    filter {
      xml {
        source => "message"
          xpath => {
            "/Event/System/Computer" => "hostname"
        }
        on_error => "_xml_error"
      }
      if ![_xml_error] {
        grok {
          match => { "hostname" => "(?<hostname>[^.]+)" }
          overwrite => ["hostname"]
          on_error => "_grok_hostname_error"
        }
        mutate {
          replace => {
            "event1.idm.read_only_udm.principal.hostname" => "%{hostname}"
          }
        }
        mutate {
          merge => {
            "@output" => "event1"
          }
        }
      }
    }
    

    Wenn Sie die UDM-VORAUSSEHEN-AUSGABE noch einmal ausführen, sehen Sie, dass das neue Feld hinzugefügt wurde, nachdem die hostname aus der FQDN extrahiert wurde.

    metadata.event_timestamp"2024-10-29T14:08:52Z"
    metadata.event_type"STATUS_HEARTBEAT"
    metadata.vendor_name"Microsoft"
    metadata.product_name"Windows Defender AV"
    metadata.product_event_type"MALWAREPROTECTION_SERVICE_HEALTH_REPORT"
    metadata.description"Endpoint Protection client health report (time in UTC)."
    metadata.log_type"WINDOWS_DEFENDER_AV"
    principal.hostname"win-dc-01"
    security_result[0].description"EventID: 1151"
    security_result[0].action[0]"ALLOW"
    security_result[0].severity"LOW"