Suggerimenti e risoluzione dei problemi durante la scrittura di analizzatori

Supportato in:

Questo documento descrive i problemi che potresti riscontrare durante la scrittura del codice del parser.

Quando scrivi il codice del parser, potresti riscontrare errori quando le istruzioni di analisi non funzionano come previsto. Le situazioni che potrebbero generare errori includono:

  • Un pattern Grok non va a buon fine
  • Un'operazione rename o replace non riesce
  • Errori di sintassi nel codice dell'analizzatore

Pratiche comuni nel codice del parser

Le sezioni seguenti descrivono le best practice, i suggerimenti e le soluzioni per aiutarti a risolvere i problemi.

Evita di utilizzare punti o trattini nei nomi delle variabili

L'utilizzo di trattini e punti nei nomi delle variabili può causare un comportamento imprevisto, spesso quando vengono eseguite operazioni merge per memorizzare i valori nei campi UDM. Potresti anche riscontrare problemi di analisi intermittenti.

Ad esempio, non utilizzare i seguenti nomi di variabili:

  • my.variable.result
  • my-variable-result

Utilizza invece il seguente nome di variabile: my_variable_result.

Non utilizzare termini con un significato speciale come nome di una variabile

Alcune parole, come event e timestamp, possono avere un significato speciale nel codice del parser.

La stringa event viene spesso utilizzata per rappresentare un singolo record UDM e viene utilizzata nell'istruzione @output. Se un messaggio di log include un campo denominato event o se definisci una variabile intermedia denominata event e il codice del parser utilizza la parola event nell'istruzione @output, viene visualizzato un messaggio di errore relativo a un conflitto di nomi.

Rinomina la variabile intermedia con un altro nome oppure utilizza il termine event1 come prefisso nei nomi dei campi UDM e nell'istruzione @output.

La parola timestamp rappresenta il timestamp del log non elaborato originale creato. Un valore impostato in questa variabile intermedia viene salvato nel campo UDMmetadata.event_timestamp. Il termine @timestamp rappresenta la data e l'ora in cui il log non elaborato è stato analizzato per creare un record UDM.

L'esempio seguente imposta il campo UDM metadata.event_timestamp sulla data e sull'ora di analisi del log non elaborato.

 # Save the log parse date and time to the timestamp variable
  mutate {
     rename => {
       "@timestamp" => "timestamp"
     }
   }

L'esempio seguente imposta il campo UDM metadata.event_timestamp sulla data e sull'ora estratte dal log non elaborato originale e archiviate nella variabile intermedia when.

   # Save the event timestamp to timestamp variable
   mutate {
     rename => {
       "when" => "timestamp"
     }
   }

Non utilizzare i seguenti termini come variabili:

  • collectiontimestamp
  • createtimestamp
  • event
  • nomefile
  • messaggio
  • spazio dei nomi
  • output
  • onerrorcount
  • timestamp
  • fuso orario

Memorizza ogni valore di dati in un campo UDM separato

Non memorizzare più campi in un singolo campo UDM concatenandoli con un delimitatore. Di seguito è riportato un esempio:

"principal.user.first_name" => "first:%{first_name},last:%{last_name}"

Memorizza invece ogni valore in un campo UDM separato.

"principal.user.first_name" => "%{first_name}"
"principal.user.last_name" => "%{last_name}"

Utilizza spazi anziché tabulazioni nel codice

Non utilizzare tabulazioni nel codice dell'analizzatore. Utilizza solo spazi e inserisci rientri di 2 spazi alla volta.

Non eseguire più azioni di unione in un'unica operazione

Se unisci più campi in un'unica operazione, potresti ottenere risultati incoerenti. Inserisci invece le istruzioni merge in operazioni separate.

Ad esempio, sostituisci il seguente esempio:

mutate {
  merge => {
      "security_result.category_details" => "category_details"
      "security_result.category_details" => "super_category_details"
  }
}

Con questo:

mutate {
  merge => {
    "security_result.category_details" => "category_details"
  }
}

mutate {
  merge => {
    "security_result.category_details" => "super_category_details"
  }
}

Scelta tra le espressioni condizionali if e if else

Se il valore condizionale che stai testando può avere una sola corrispondenza, utilizza l'istruzione condizionale if else. Questo approccio è leggermente più efficiente. Tuttavia, se hai uno scenario in cui il valore testato potrebbe corrispondere più di una volta, utilizza più istruzioni if distinte e ordina le istruzioni dal caso più generico a quello più specifico.

Scegli un insieme rappresentativo di file di log per testare le modifiche al parser

Una best practice è testare il codice del parser utilizzando esempi di log non elaborati con una vasta gamma di formati. In questo modo puoi trovare log o casi limite unici che il parser potrebbe dover gestire.

Aggiungere commenti descrittivi al codice dell'analizzatore

Aggiungi commenti al codice del parser che spieghino perché l'istruzione è importante, anziché cosa fa. Il commento aiuta chiunque gestisca il parser a seguire il flusso. Di seguito è riportato un esempio:

# only assign a Namespace if the source address is RFC 1918 or Loopback IP address
if [jsonPayload][id][orig_h] =~ /^(127(?:\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?))\{3\}$)|(10(?:\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?))\{3\}$)|(192\.168(?:\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?))\{2\}$)|(172\.(?:1[6-9]|2\d|3[0-1])(?:\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?))\{2\}$)/ {
  mutate {
    replace => {
      "event1.idm.read_only_udm.principal.namespace" => "%{resource.labels.project_id}"
    }
  }
}

Inizializza le variabili intermedie in anticipo

Prima di estrarre i valori dal log non elaborato originale, inizializza le variabili intermediate che verranno utilizzate per memorizzare i valori di test.

In questo modo viene evitato che venga restituito un errore che indica che la variabile intermedia non esiste.

L'istruzione seguente assegna il valore nella variabile product al campo UDM metadata.product_name.

mutate{
  replace => {
    "event1.idm.read_only_udm.metadata.product_name" => "%{product}"
  }
}

Se la variabile product non esiste, viene visualizzato il seguente errore:

"generic::invalid_argument: pipeline failed: filter mutate (4) failed: replace failure: field \"event1.idm.read_only_udm.metadata.product_name\": source field \"product\": field not set"

Puoi aggiungere un'istruzione on_error per rilevare l'errore. Di seguito è riportato un esempio:

mutate{
  replace => {
    "event1.idm.read_only_udm.metadata.product_name" => "%{product}"
    }
  on_error => "_error_does_not_exist"
  }

L'istruzione di esempio precedente rileva correttamente l'errore di analisi in una variabile intermedia booleana, chiamata _error_does_not_exist. Non consente di utilizzare la variabile product in un'istruzione condizionale, ad esempio if. Di seguito è riportato un esempio:

if [product] != "" {
  mutate{
    replace => {
      "event1.idm.read_only_udm.metadata.product_name" => "%{product}"
    }
  }
  on_error => "_error_does_not_exist"
}

L'esempio precedente restituisce il seguente errore perché la clausola condizionale if non supporta le istruzioni on_error:

"generic::invalid_argument: pipeline failed: filter conditional (4) failed: failed to evaluate expression: generic::invalid_argument: "product" not found in state data"

Per risolvere il problema, aggiungi un blocco di istruzioni separato che inizializza le variabili intermediate prima di eseguire le istruzioni del filtro di estrazione (json, csv, xml, kv o grok). Di seguito è riportato un esempio.

filter {
  # Initialize intermediate variables for any field you will use for a conditional check
  mutate {
    replace => {
      "timestamp" => ""
      "does_not_exist" => ""
    }
  }

  # load the logs fields from the message field
  json {
    source         => "message"
    array_function => "split_columns"
    on_error       => "_not_json"
  }
}

Lo snippet di codice del parser aggiornato gestisce i vari scenari utilizzando un'istruzione condizionale per verificare se il campo esiste. Inoltre, l'istruzione on_error gestisce gli errori che potrebbero verificarsi.

Converti SHA-256 in base64

Il seguente esempio estrae il valore SHA-256, lo codifica in base64, converte i dati codificati in una stringa esadecimale e poi sostituisce campi specifici con i valori estratti ed elaborati.

if [Sha256] != "" 
{
  base64
  {
  encoding => "RawStandard"
  source => "Sha256"
  target => "base64_sha256"
  on_error => "base64_message_error"
  }
  mutate
  {
    convert =>
    {
      "base64_sha256" => "bytestohex"
    }
    on_error => "already_a_string"
  }
  mutate
  {
    replace => 
  {
     "event.idm.read_only_udm.network.tls.client.certificate.sha256" => "%{base64_sha256}"
     "event.idm.read_only_udm.target.resource.name" => "%{Sha256}"
  }
  }
}

Gestire gli errori nelle istruzioni del parser

Non è raro che i log in entrata siano in un formato imprevisto o che abbiano dati con formattazione errata.

Puoi creare il parser per gestire questi errori. Una best practice è aggiungere gestori on_error al filtro di estrazione e poi testare la variabile intermedia prima di passare al segmento successivo della logica del parser.

L'esempio seguente utilizza il filtro di estrazione json con un'istruzione on_error per impostare la variabile booleana _not_json. Se _not_json è impostato su true, significa che la voce di log in arrivo non era in formato JSON valido e la voce di log non è stata analizzata correttamente. Se la variabile _not_json è false, la voce di log in arrivo era in formato JSON valido.

 # load the incoming log from the default message field
  json {
    source         => "message"
    array_function => "split_columns"
    on_error       => "_not_json"
  }

Puoi anche verificare se un campo è nel formato corretto. L'esempio seguente verifica se _not_json è impostato su true, a indicare che il log non era nel formato previsto.

 # Test that the received log matches the expected format
  if [_not_json] {
    drop { tag => "TAG_MALFORMED_MESSAGE" }
  } else {
    # timestamp is always expected
    if [timestamp] != "" {

      # ...additional parser logic goes here …

    } else {

      # if the timestamp field does not exist, it's not a log source
      drop { tag => "TAG_UNSUPPORTED" }
    }
  }

In questo modo, l'analisi non fallisce se i log vengono importati con un formato errato per il tipo di log specificato.

Utilizza il filtro drop con la variabile tag in modo che la condizione venga acquisita nella tabella delle metriche di importazione in BigQuery.

  • TAG_UNSUPPORTED
  • TAG_MALFORMED_ENCODING
  • TAG_MALFORMED_MESSAGE
  • TAG_NO_SECURITY_VALUE

Il filtro drop impedisce all'analizzatore di elaborare il log non elaborato, normalizzare i campi e creare un record UDM. Il log non elaborato originale viene comunque importato in Google Security Operations e può essere cercato utilizzando la ricerca dei log non elaborati in Google Security Operations.

Il valore passato alla variabile tag viene memorizzato nel campo drop_reason_code della tabella Metriche di importazione. Puoi eseguire una query ad hoc sulla tabella simile alla seguente:

SELECT
  log_type,
  drop_reason_code,
  COUNT(drop_reason_code) AS count
FROM `datalake.ingestion_metrics`
GROUP BY 1,2
ORDER BY 1 ASC

Risolvere i problemi relativi agli errori di convalida

Quando crei un parser, potresti riscontrare errori relativi alla convalida, ad esempio un campo obbligatorio non è impostato nel record UDM. L'errore potrebbe avere il seguente aspetto:

Error: generic::unknown: invalid event 0: LOG_PARSING_GENERATED_INVALID_EVENT: "generic::invalid_argument: udm validation failed: target field is not set"

Il codice del parser viene eseguito correttamente, ma il record UDM generato non include tutti i campi UDM obbligatori come definito dal valore impostato su metadata.event_type. Di seguito sono riportati altri esempi che possono causare questo errore:

  • Se metadata.event_type è USER_LOGIN e il campo UDM target.user value non è impostato.
  • Se metadata.event_type è NETWORK_CONNECTION e il target.hostnamecampo UDM non è impostato.

Per ulteriori informazioni sul campo UDM metadata.event_type e sui campi obbligatori, consulta la guida all'utilizzo di UDM.

Un'opzione per la risoluzione dei problemi relativi a questo tipo di errore è iniziare impostando valori statici per i campi UDM. Dopo aver definito tutti i campi UDM necessari, esamina il log non elaborato originale per vedere quali valori analizzare e salvare nel record UDM. Se il log non elaborato originale non contiene determinati campi, potrebbe essere necessario impostare valori predefiniti.

Di seguito è riportato un modello di esempio, specifico per un tipo di evento USER_LOGIN, che illustra questo approccio.

Tieni presente quanto segue:

  • Il modello inizializza le variabili intermedie e imposta ciascuna su una stringa statica.
  • Il codice nella sezione Assegnazione dei campi imposta i valori nelle variabili intermedie ai campi UDM.

Puoi espandere questo codice aggiungendo altre variabili intermedie e campi UDM. Dopo aver identificato tutti i campi UDM che devono essere compilati, svolgi i seguenti passaggi:

  • Nella sezione Configurazione input, aggiungi il codice che estrae i campi dal log non elaborato originale e imposta i valori sulle variabili intermedie.

  • Nella sezione Estrazione data, aggiungi il codice che estrae il timestamp dell'evento dal log non elaborato originale, lo trasforma e lo imposta sulla variabile intermedia.

  • Se necessario, sostituisci il valore inizializzato impostato in ogni variabile intermedia con una stringa vuota.

filter {
 mutate {
   replace => {
     # UDM > Metadata
     "metadata_event_timestamp"    => ""
     "metadata_vendor_name"        => "Example"
     "metadata_product_name"       => "Example SSO"
     "metadata_product_version"    => "1.0"
     "metadata_product_event_type" => "login"
     "metadata_product_log_id"     => "12345678"
     "metadata_description"        => "A user logged in."
     "metadata_event_type"         => "USER_LOGIN"

     # UDM > Principal
     "principal_ip"       => "192.168.2.10"

     # UDM > Target
     "target_application"            => "Example Connect"
     "target_user_user_display_name" => "Mary Smith"
     "target_user_userid"            => "mary@example.com"

     # UDM > Extensions
     "auth_type"          => "SSO"
     "auth_mechanism"     => "USERNAME_PASSWORD"

     # UDM > Security Results
     "securityResult_action"         => "ALLOW"
     "security_result.severity"       => "LOW"

   }
 }

 # ------------ Input Configuration  --------------
  # Extract values from the message using one of the extraction filters: json, kv, grok

 # ------------ Date Extract  --------------
 # If the  date {} function is not used, the default is the normalization process time

  # ------------ Field Assignment  --------------
  # UDM Metadata
  mutate {
    replace => {
      "event1.idm.read_only_udm.metadata.vendor_name"        =>  "%{metadata_vendor_name}"
      "event1.idm.read_only_udm.metadata.product_name"       =>  "%{metadata_product_name}"
      "event1.idm.read_only_udm.metadata.product_version"    =>  "%{metadata_product_version}"
      "event1.idm.read_only_udm.metadata.product_event_type" =>  "%{metadata_product_event_type}"
      "event1.idm.read_only_udm.metadata.product_log_id"     =>  "%{metadata_product_log_id}"
      "event1.idm.read_only_udm.metadata.description"        =>  "%{metadata_description}"
      "event1.idm.read_only_udm.metadata.event_type"         =>  "%{metadata_event_type}"
    }
  }

  # Set the UDM > auth fields
  mutate {
    replace => {
      "event1.idm.read_only_udm.extensions.auth.type"        => "%{auth_type}"
    }
    merge => {
      "event1.idm.read_only_udm.extensions.auth.mechanism"   => "auth_mechanism"
    }
  }

  # Set the UDM > principal fields
  mutate {
    merge => {
      "event1.idm.read_only_udm.principal.ip"                => "principal_ip"
    }
  }

  # Set the UDM > target fields
  mutate {
    replace => {
      "event1.idm.read_only_udm.target.user.userid"             =>  "%{target_user_userid}"
      "event1.idm.read_only_udm.target.user.user_display_name"  =>  "%{target_user_user_display_name}"
      "event1.idm.read_only_udm.target.application"             =>  "%{target_application}"
    }
  }

  # Set the UDM > security_results fields
  mutate {
    merge => {
      "security_result.action" => "securityResult_action"
    }
  }

  # Set the security result
  mutate {
    merge => {
      "event1.idm.read_only_udm.security_result" => "security_result"
    }
  }

 # ------------ Output the event  --------------
  mutate {
    merge => {
      "@output" => "event1"
    }
  }

}

Analizza il testo non strutturato utilizzando una funzione Grok

Quando utilizzi una funzione Grok per estrarre valori da testo non strutturato, puoi utilizzare pattern Grok e istruzioni di espressioni regolari predefiniti. I pattern Grok semplificano la lettura del codice. Se l'espressione regolare non include caratteri abbreviati (ad es. \w, \s), puoi copiare e incollare l'istruzione direttamente nel codice del parser.

Poiché i pattern Grok sono un livello di astrazione aggiuntivo nell'istruzione, possono complicare la risoluzione dei problemi quando si verifica un errore. Di seguito è riportato un esempio di funzione Grok che contiene sia pattern Grok predefiniti sia espressioni regolari.

grok {
  match => {
    "message" => [
      "%{NUMBER:when}\\s+\\d+\\s%{SYSLOGHOST:srcip} %{WORD:action}\\/%{NUMBER:returnCode} %{NUMBER:size} %{WORD:method} (?P<url>\\S+) (?P<username>.*?) %{WORD}\\/(?P<tgtip>\\S+).*"
    ]
  }
}

Un'istruzione di estrazione senza pattern Grok potrebbe avere un rendimento migliore. Ad esempio, l'esempio seguente richiede meno della metà dei passaggi di elaborazione per la corrispondenza. Per un'origine log con un volume potenzialmente elevato, questa è una considerazione importante.

Differenze tra le espressioni regolari RE2 e PCRE

I parser di Google Security Operations utilizzano RE2 come motore di espressioni regolari. Se conosci la sintassi PCRE, potresti notare delle differenze. Di seguito è riportato un esempio:

Di seguito è riportata un'istruzione PCRE: (?<_custom_field>\w+)\s

Di seguito è riportata un'istruzione RE2 per il codice del parser: (?P<_custom_field>\\w+)\\s

Assicurati di utilizzare l'interpretazione letterale dei caratteri di escape

Google Security Operations memorizza i dati dei log non elaborati in arrivo in formato JSON codificato. Questo serve per assicurarti che le stringhe di caratteri che sembrano essere una scorciatoia per le espressioni regolari vengano interpretate come stringa letterale. Ad esempio, \t viene interpretato come la stringa letterale anziché come un carattere di tabulazione.

L'esempio seguente è un log non elaborato originale e il log del formato codificato in JSON. Nota il carattere di escape aggiunto prima di ogni carattere barra inversa che circonda il termine entry.

Di seguito è riportato il log non elaborato originale:

field=\entry\

Di seguito è riportato il log convertito in formato con codifica JSON:

field=\\entry\\

Quando utilizzi un'espressione regolare nel codice del parser, devi aggiungere altri caratteri di escape se vuoi estrarre solo il valore. Per creare una corrispondenza con una barra rovesciata nel log non elaborato originale, utilizza quattro barre rovesciate nell'istruzione di estrazione.

Di seguito è riportata un'espressione regolare per il codice dell'analizzatore:

^field=\\\\(?P<_value>.*)\\\\$

Di seguito è riportato il risultato generato. Il gruppo denominato _value memorizza il termine entry:

"_value": "entry"

Quando sposti un'istruzione di espressione regolare standard nel codice del parser, inserisci caratteri di escape per le espressioni regolari abbreviate nell'istruzione di estrazione. Ad esempio, cambia \s in \\s.

Lascia invariati i caratteri speciali dell'espressione regolare quando vengono utilizzati due caratteri di escape nell'istruzione di estrazione. Ad esempio, \\ rimane invariato come \\.

Di seguito è riportata un'espressione regolare standard:

^.*?\\\"(?P<_user>[^\\]+)\\\"\s(?:(logged\son|logged\soff))\s.*?\\\"(?P<_device>[^\\]+)\\\"\.$

La seguente espressione regolare viene modificata per funzionare all'interno del codice del parser.

^.*?\\\"(?P<_user>[^\\\\]+)\\\"\\s(?:(logged\\son|logged\\soff))\\s.*?\\\"(?P<_device>[^\\\\]+)\\\"\\.$

La tabella seguente riassume quando un'espressione regolare standard deve includere caratteri di escape aggiuntivi prima di essere inclusa nel codice del parser.

Espressione regolare Espressione regolare modificata per il codice del parser Descrizione della modifica
\s
\\s
I caratteri di abbreviazione devono essere preceduti dal carattere di escape.
\.
\\.
I caratteri riservati devono essere preceduti dal carattere di escape.
\\"
\\\"
I caratteri riservati devono essere preceduti dal carattere di escape.
\]
\\]
I caratteri riservati devono essere preceduti dal carattere di escape.
\|
\\|
I caratteri riservati devono essere preceduti dal carattere di escape.
[^\\]+
[^\\\\]+
I caratteri speciali all'interno di un gruppo di classi di caratteri devono essere preceduti dal carattere di escape.
\\\\
\\\\
I caratteri speciali esterni a un gruppo di classi di caratteri o ai caratteri di abbreviazione non richiedono un carattere di escape aggiuntivo.

Le espressioni regolari devono includere un gruppo di cattura denominato

Un'espressione regolare, ad esempio "^.*$", è una sintassi RE2 valida. Tuttavia, nel codice del parser non va a buon fine con il seguente errore:

"ParseLogEntry failed: pipeline failed: filter grok (0) failed: failed to parse data with all match
patterns"

Devi aggiungere un gruppo di cattura valido all'espressione. Se utilizzi i pattern Grok, per impostazione predefinita includono un gruppo di cattura denominato. Quando utilizzi le sostituzioni di espressioni regolari, assicurati di includere un gruppo denominato.

Di seguito è riportato un esempio di espressione regolare nel codice del parser:

"^(?P<_catchall>.*$)"

Di seguito è riportato il risultato, che mostra il testo assegnato al gruppo denominato _catchall.

"_catchall": "User \"BOB\" logged on to workstation \"DESKTOP-01\"."

Utilizza un gruppo generico denominato per iniziare a creare l'espressione

Quando crei un'istruzione di estrazione, inizia con un'espressione che acquisisce più di quanto vuoi. Quindi, espandi l'espressione un campo alla volta.

L'esempio seguente inizia utilizzando un gruppo denominato (_catchall) che corrisponde all'intero messaggio. Quindi, genera l'espressione in modo graduale abbinando altre parti del testo. A ogni passaggio, il gruppo denominato _catchall contiene meno testo originale. Continua e esegui l'iterazione un passaggio alla volta per trovare una corrispondenza con il messaggio finché non avrai più bisogno del gruppo denominato _catchall.

Passaggio Espressione regolare nel codice del parser Output del gruppo di acquisizione denominato _catchall
1
"^(?P<_catchall>.*$)"
User \"BOB\" logged on to workstation \"DESKTOP-01\".
2
^User\s\\\"(?P<_catchall>.*$)
BOB\" logged on to workstation \"DESKTOP-01\".
3
^User\s\\\"(?P<_user>.*?)\\\"\s(?P<_catchall>.*$)
logged on to workstation \"DESKTOP-01\".
Continua finché l'espressione non corrisponde all'intera stringa di testo.

Caratteri di escape per i caratteri abbreviati nell'espressione regolare

Ricordati di eseguire l'escape dei caratteri di abbreviazione delle espressioni regolari quando utilizzi l'espressione nel codice del parser. Di seguito è riportato un esempio di stringa di testo e l'espressione regolare standard che estrae la prima parola, This.

  This is a sample log.

La seguente espressione regolare standard estrae la prima parola, This. Tuttavia, quando esegui questa espressione nel codice del parser, nel risultato manca la letteras.

Espressione regolare standard Output del gruppo di acquisizione denominato _firstWord
"^(?P<_firstWord>[^\s]+)\s.*$" "_firstWord": "Thi",

Questo perché le espressioni regolari nel codice del parser richiedono un carattere di sfuggita aggiuntivo aggiunto ai caratteri di abbreviazione. Nell'esempio precedente, \s deve essere modificato in \\s.

Espressione regolare rivista per il codice del parser Output del gruppo di acquisizione denominato _firstWord
"^(?P<_firstWord>[^\\s]+)\\s.*$" "_firstWord": "This",

Questo vale solo per i caratteri di abbreviazione, come \s, \r e \t. Altri caratteri, come ", non richiedono ulteriori interpretazioni letterali.

Un esempio completo

Questa sezione descrive le regole precedenti come esempio end-to-end. Ecco una stringa di testo non strutturata e l'espressione regolare standard scritta per analizzare la stringa. Infine, include l'espressione regolare modificata che funziona nel codice del parser.

Di seguito è riportata la stringa di testo originale.

User "BOB" logged on to workstation "DESKTOP-01".

Di seguito è riportata un'espressione regolare RE2 standard che analizza la stringa di testo.

^.*?\\\"(?P<_user>[^\\]+)\\\"\s(?:(logged\son|logged\soff))\s.*?\\\"(?P<_device>[^\\]+)\\\"\.$

Questa espressione estrae i seguenti campi.

Gruppo di corrispondenze Posizione del carattere Stringa di testo
Corrispondenza completa 0-53
User \"BOB\" logged on to workstation \"DESKTOP-01\".
Gruppo "_user" 7-10
BOB
Gruppo 2. 13-22
logged on
Gruppo "_device" 40-50
DESKTOP-01

Questa è l'espressione modificata. L'espressione regolare RE2 standard è stata modificata per funzionare nel codice del parser.

^.*?\\\"(?P<_user>[^\\\\]+)\\\"\\s(?:(logged\\son|logged\\soff))\\s.*?\\\"(?P<_device>[^\\\\]+)\\\"\\.$

Hai bisogno di ulteriore assistenza? Ricevi risposte dai membri della community e dai professionisti di Google SecOps.