Beispiele für Parser-Erweiterungen

Unterstützt in:

In diesem Dokument finden Sie Beispiele für die Erstellung von Parsererweiterungen in verschiedenen Szenarien. Weitere Informationen zu Parser-Erweiterungen finden Sie unter Parser-Erweiterungen erstellen.

Beispiele für Parser-Erweiterungen

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

No-Code-Beispiele

Format der Logquelle Beispieltitel Beschreibung Parserkonzepte in diesem Beispiel
JSON
(Log-Typ: GCP_IDS)
Felder extrahieren Felder aus einem Log im JSON-Format extrahieren. Kein Code
JSON
(Log-Typ: WORKSPACE_ALERTS)
Felder mit dem Precondition Value extrahieren Felder aus einem Log im JSON-Format extrahieren und in ein wiederholtes UDM-Feld mit einer Vorbedingung normalisieren.

Beispiele für Code-Snippets

Format der Logquelle Beispieltitel Beschreibung Parserkonzepte in diesem Beispiel
JSON
(Logtyp: `GCP_IDS`)
HTTP-User-Agent hinzufügen
  • Extrahieren Sie den User-Agent des Network HTTP Parser und erstellen Sie ein target hostname aus dem requestUrl.
  • Weisen Sie einen Namespace zu, um Asset-basiertes Aliasing und Anreicherung zu ermöglichen.
CSV
(Protokolltyp: MISP_IOC)
Beliebige Felder in das UDM-Objekt additional extrahieren Extrahiert Felder in UDM > Entity > additional UDM-Objekt > Schlüssel/Wert-Paar additional UDM-Objekt
Syslog
(Logtyp: POWERSHELL)
Priorität und Schweregrad aus dem Syslog extrahieren Extrahieren Sie die Syslog-Einrichtungs- und Schweregradwerte in die Felder UDM Security Result Priority und Severity. Grok-basiert
JSON mit Syslog-Header
(Logtyp: WINDOWS_SYSMON)
Formatierung basierend auf einer bedingten Anweisung
  • Fügt dem Feld metadata.description basierend auf einer Konditionalanweisung und dem Verständnis der Datentypen in Code-Snippets Dekoration (Kontextinformationen) hinzu.
  • Wenn Sie einen Extraktionsfilter verwenden, kann der ursprüngliche Datentyp beibehalten werden.
  • In einer Grok-Bedingungsanweisung sollte der ursprüngliche Datentyp verwendet werden, um das Feld auszuwerten.
  • Grok-basiert
  • Bedingte Anweisung für Grok
  • Der ursprüngliche Datentyp eines extrahierten Felds kann beibehalten werden.
  • In einer Grok-Bedingungsanweisung sollte der ursprüngliche Datentyp verwendet werden, um das Feld auszuwerten.
JSON mit Syslog-Header
(Logtyp: WINDOWS_SYSMON)
Datentypen konvertieren
  • Datentypen in einer Parsererweiterung mit der Funktion convert konvertieren.
  • Verwenden Sie on_error-Anweisungen, um Fehler richtig zu behandeln und Parsererweiterungsfehler zu vermeiden.
  • Grok-basiert
  • Datentypen konvertieren
  • Verwenden Sie on_error-Anweisungen, um die Fehlerbehandlung zu ermöglichen.
JSON mit 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 umbenennen, damit sie dem Namen des endgültigen UDM-Ereignisobjekts entsprechen. Das kann die allgemeine Lesbarkeit verbessern.
  • Grok-basiert
  • Verwenden Sie temporäre Variablennamen und benennen Sie sie später in die endgültigen UDM-Namen um.
JSON mit Syslog-Header
(Logtyp: WINDOWS_SYSMON)
Wiederkehrende Felder Seien Sie vorsichtig, wenn Sie mit wiederholten Feldern in Code-Snippets arbeiten, z. B. mit dem Feld „security_result“.
XML
(Logtyp: WINDOWS_DEFENDER_AV)
Beliebige Felder in das additional-Objekt extrahieren
  • Extrahieren und speichern Sie den Wert für die Plattformversion, um beispielsweise Berichte zu erstellen und nach veralteten Plattformversionen zu suchen.
  • In diesem Beispiel gibt es kein geeignetes Standard-UDM-Feld. Daher wird das additional-Objekt verwendet, um die Informationen als benutzerdefiniertes Schlüssel/Wert-Paar zu speichern.
Das additional-Objekt wird verwendet, um die Informationen als benutzerdefiniertes Schlüssel/Wert-Paar zu speichern.
XML
(Logtyp: WINDOWS_DEFENDER_AV)
Beliebige Felder in „Principal Hostname“ extrahieren
  • Extrahieren Sie den Hostnamen aus einem FQDN.
  • Mit der bedingten Verarbeitung wird festgelegt, ob das Feld principal.hostname überschrieben werden soll.
  • Die Grok-Anweisung verwendet einen regulären Ausdruck (Regex), um das Feld hostname zu extrahieren. Im regulären Ausdruck wird eine benannte Erfassungsgruppe verwendet. Das bedeutet, dass alles, was in den Klammern gefunden wird, im Feld mit dem Namen hostname gespeichert wird. Es werden ein oder mehrere Zeichen erfasst, bis ein Punkt gefunden wird. Damit wird nur die hostname innerhalb eines FQDN erfasst.
Grok overwrite statement
  • Beim Ausführen von PREVIEW UDM OUTPUT wird jedoch der folgende Fehler zurückgegeben: „LOG_PARSING_CBN_ERROR: Field hostname already exists in data and is not overwritable“ (LOG_PARSING_CBN_ERROR: Feld hostname ist bereits in den Daten vorhanden und kann nicht überschrieben werden).
  • Innerhalb einer Grok-Anweisung kann eine benannte Erfassungsgruppe eine vorhandene Variable nur überschreiben, wenn dies explizit mit der overwrite-Anweisung angegeben wird. In diesem Fall 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 Hostname-Variable 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, CSV, XML, Syslog und KV Vorhandene Zuordnungen entfernen Entfernen Sie vorhandene Zuordnungen, indem Sie die Werte für UDM-Felder entfernen.

JSON-Beispiele

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

No-Code – Felder extrahieren

Beispielattribute:

  • Logquellenformat: JSON
  • Ansatz für die Datenzuordnung: No-Code
  • Logtyp: GCP_IDS
  • Zweck der Parsererweiterung: Felder extrahieren.
  • Beschreibung:

    Mehrere netzwerkbezogene Felder werden nicht extrahiert. Da es sich bei diesem Logbeispiel um ein strukturiertes Log im JSON-Format handelt, können wir die Parsererweiterung mit dem No-Code-Ansatz (Datenfelder zuordnen) erstellen.

    Die ursprünglichen Felder, die wir extrahieren möchten, sind:

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

    Dies ist der Beispiel-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:

    Precondition Path Precondition Operator Precondition Value Rohdatenpfad 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 die Parser-Erweiterung ausgeführt wird, 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 Precondition Value extrahieren

Beispielattribute:

  • Logquellenformat: JSON
  • Ansatz für die Datenzuordnung: No-Code
  • Protokolltyp: WORKSPACE_ALERTS
  • Zweck der Parsererweiterung: Felder mit Precondition Value extrahieren.
  • Beschreibung:

    Der ursprüngliche Parser extrahiert die email address des primären Nutzers, der von einer DLP-Warnung (Data Loss Prevention, Schutz vor Datenverlust) betroffen ist, nicht.

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

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

    • replace (alle Werte von wiederkehrenden Feldern im vorhandenen UDM-Objekt überschreiben) oder
    • append: Die extrahierten Werte werden an wiederholte Felder angehängt.

    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 vor einem Extraktionsvorgang bedingte Prüfungen durchführen. In den meisten Fällen ist das Vorbedingungsfeld dasselbe Feld wie das Rohdatenfeld, das Sie extrahieren möchten, mit einem Vorbedingungsoperator von not Null, z. B. foo != "".

    Manchmal ist der Wert für Rohdatenfeld, den Sie extrahieren möchten, jedoch nicht in allen Logeinträgen vorhanden, wie in unserem Beispiel. In diesem Fall können Sie ein anderes Precondition Field (Feld für Vorbedingungen) verwenden, um den Extraktionsvorgang zu filtern. In unserem Beispiel ist das Rohfeld triggeringUserEmail, das Sie extrahieren möchten, nur in Logs vorhanden, in denen type = Data Loss Prevention.

    Dies sind die Beispielwerte, die in die Felder der No-Code-Parsererweiterung eingegeben werden müssen:

    Precondition Path Precondition Operator Precondition Value Rohdatenpfad Zielfeld*
    type GLEICH Schutz vor Datenverlust data.ruleViolationInfo.triggeringUserEmail udm.principal.user.email_addresses

    Im folgenden Beispiel sehen Sie die Felder der no-code-Parsererweiterung mit den Beispielwerten:

    image2

    Wenn die Parser-Erweiterung 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

Beispielattribute:

  • Logquellenformat: JSON
  • Ansatz für die Datenzuordnung: Code-Snippet
  • Logtyp: 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 die Verwendung eines Code-Snippets erfordert. Mit dem Standardparser wird die Network HTTP Parser User Agent-Analyse nicht extrahiert. Außerdem gilt Folgendes:

    1. Aus dem requestUrl wird ein Target Hostname erstellt.
    2. Es wird ein Namespace zugewiesen, um sicherzustellen, dass Asset-basiertes Aliasing und die Anreicherung durchgeführt werden.
    # 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 Logquelle im CSV-Format vorliegt.

Code-Snippet – Beliebige Felder in das additional-Objekt extrahieren

Beispielattribute:

  • Format der Log-Quelle: CSV
  • Ansatz für die Datenzuordnung: Code-Snippet
  • Logtyp: MISP_IOC
  • Zweck der Parsererweiterung: Beliebige Felder in das Objekt additional extrahieren.
  • Beschreibung:

    In diesem Beispiel wird die Integration des UDM-Entitätskontexts MISP_IOC verwendet. Das Schlüssel/Wert-Paar-UDM-Objekt additional wird verwendet, um Kontextinformationen zu erfassen, die nicht vom Standardparser extrahiert werden, und um organisationsspezifische Felder hinzuzufügen. Beispielsweise eine URL zurück zu ihrer spezifischen MISP-Instanz.

    Das ist die CSV-basierte Log-Quelle 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 die Parser-Erweiterung ausgeführt wird, 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 auf Grok basierende Parsererweiterungen erstellen.

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

Beispielattribute:

  • 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 auf Grok basierende Parsererweiterung erstellt, um die Werte Syslog Facility and Severity in die UDM-Sicherheitsergebnis-Felder 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"
                }
            }
        }
    }
    

    Wenn Sie sich die Ergebnisse der Parser-Erweiterung ansehen, wird das menschenlesbare 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, temporäre Variablennamen und Datentypkonvertierung

Beispielattribute:

  • Logquellenformat: JSON mit Syslog-Header
  • Ansatz für die Datenzuordnung: Code-Snippet mit Grok
  • Logtyp: WINDOWS_SYSMON
  • Zweck der Parsererweiterung: Ereignisse ergänzen, temporäre 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 (Kontextinformationen) dazu hinzugefügt, was die einzelnen Ereignistypen in WINDOWS_SYSMON bedeuten. Dabei wird eine bedingte Anweisung verwendet, um die EventID zu prüfen. Anschließend wird ein Description hinzugefügt. EventID 1 ist beispielsweise ein Process Creation-Ereignis.

    Wenn Sie beispielsweise einen Extraktionsfilter für JSON verwenden, kann der ursprüngliche Datentyp beibehalten werden.

    Im folgenden Beispiel wird der Wert EventID standardmäßig als Ganzzahl extrahiert. In der Bedingungsanweisung wird der Wert 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 umbenennen, damit 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 Parser-Erweiterung 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 Sie die Parsererweiterung ausführen, 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, bei der die Protokollquelle im XML-Format vorliegt.

Code-Snippet – Beliebige Felder in das additional-Objekt extrahieren

Beispielattribute:

  • Format der Logquelle: XML
  • Ansatz für die Datenzuordnung: Code-Snippet
  • Protokolltyp: WINDOWS_DEFENDER_AV
  • Zweck der Parsererweiterung: Beliebige Felder in das additional-Objekt extrahieren
  • Beschreibung:

    Ziel dieses Beispiels ist es, den Wert Platform Version zu extrahieren und zu speichern, um beispielsweise Berichte zu outdated platform versions erstellen und danach zu suchen.

    Nachdem wir das Dokument Wichtige UDM-Felder geprüft haben, konnten wir kein geeignetes Standard-UDM-Feld finden. In diesem Beispiel wird 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 PREVIEW-UDM-AUSGABE ausführen, sehen Sie, dass das neue Feld 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) – Beliebige Felder in „Principal Hostname“ extrahieren

Beispielattribute:

  • Format der Logquelle: XML
  • Ansatz für die Datenzuordnung: Code-Snippet mit Grok
  • Protokolltyp: WINDOWS_DEFENDER_AV
  • Zweck der Parsererweiterung: Beliebige Felder in „Principal Hostname“ extrahieren
  • Beschreibung:

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

    In diesem Beispiel wird geprüft, ob das Rohlogfeld Computer name ein FQDN enthält. Wenn ja, wird nur der Hostname-Teil extrahiert und das UDM-Feld Principal Hostname überschrieben.

    Nachdem Sie sich den Parser und das Dokument Wichtige UDM-Felder angesehen haben, 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"
                }
            }
        }
    }
    

    Diese Parsererweiterung verwendet eine Grok-Anweisung, um einen regulären Ausdruck (Regex) auszuführen und das Feld hostname zu extrahieren. Im regulären Ausdruck wird eine benannte Erfassungsgruppe verwendet. Das bedeutet, dass alles, was in den Klammern gefunden wird, im Feld hostname gespeichert wird. Es werden ein oder mehrere Zeichen erfasst, bis ein Punkt gefunden wird. Dabei wird nur das hostname innerhalb eines FQDN erfasst.

    Beim Ausführen von PREVIEW UDM OUTPUT wird jedoch ein Fehler zurückgegeben. Warum ist das so?

    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 überschreiben, wenn dies explizit mit der overwrite-Anweisung angegeben wird. In diesem Fall können wir entweder einen anderen Variablennamen für die benannte Erfassungsgruppe in der Grok-Anweisung verwenden oder, wie im folgenden Code-Snippet-Beispiel 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 PREVIEW UDM OUTPUT noch einmal ausführen, sehen Sie, dass das neue Feld hinzugefügt wurde, nachdem hostname aus 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"
    

Beispiele für JSON, CSV, XML, Syslog und KV

In den folgenden Beispielen wird gezeigt, wie Sie eine Parsererweiterung erstellen, bei der die Logquelle im JSON-, CSV-, XML-, Syslog- oder KV-Format vorliegt.

Code-Snippet – Vorhandene Zuordnungen entfernen

Beispielattribute:

  • Format der Logquelle: JSON, CSV, Syslog, XML und KV
  • Ansatz für die Datenzuordnung: Code-Snippet
  • Zweck der Parsererweiterung: Werte für UDM-Felder entfernen
  • Beschreibung:

    Ziel dieser Beispiele ist es, vorhandene Zuordnungen zu entfernen, indem die Werte für UDM-Felder entfernt werden.

    Im folgenden Beispiel wird der Wert für das Feld string entfernt:

    filter {
       mutate{
         replace => {
             "event.idm.read_only_udm.metadata.vendor_name" => ""
         }
       }
       mutate {
         merge => {
           "@output" => "event"
         }
      }
    }
    

    Im folgenden Beispiel wird der Wert für das Feld integer entfernt:

    filter {
       mutate {
         replace => {
           "principal_port" => "0"
         }
     }
       mutate {
         convert => {
           "principal_port" => "integer"
         }
     }
       mutate {
         rename => {
           "principal_port" => "event.idm.read_only_udm.principal.port"
         }
     }
       mutate {
         merge => {
           "@output" => "event"
         }
      }
    }
    

    Im folgenden Beispiel wird der Wert für das Feld float entfernt:

    filter {
       mutate {
           replace => {
             "security_result_object.risk_score" => "0.0" 
           }
           convert => {
             "security_result_object.risk_score" => "float"
           }
           on_error => "default_risk_score_conversion_failed"
         }
       mutate {
           merge => {
               "event.idm.read_only_udm.security_result" => "security_result_object"
           }
           on_error => "security_result_merge_failed"
         }
       mutate {
         merge => {
           "@output" => "event"
         }
     }
    }
    

    Im folgenden Beispiel wird der Wert für das Feld boolean entfernt:

    filter {
       mutate{
           replace => {
               "tls_established" => "false"
           }
      }
       mutate {
         convert => {
           "tls_established" => "boolean"
         }
       }
       mutate {
         rename => {
           "tls_established" => "event.idm.read_only_udm.network.tls.established"
         }
       }
       mutate {
         merge => {
           "@output" => "event"
         }
      }
    }
    

    Im folgenden Beispiel wird der Wert für das Feld extension entfernt:

    filter {
       mutate {
           replace => {
              "event.idm.read_only_udm.extensions.auth.auth_details" => ""
           }
           on_error => "logon_type_not_set"
       }
       mutate {
         merge => {
           "@output" => "event"
         }
      }
    }
    

    Benötigen Sie weitere Hilfe? Antworten von Community-Mitgliedern und Google SecOps-Experten erhalten