Raccogliere i log WAF di Fastly
Panoramica
Questo parser estrae i campi dai log JSON di Fastly WAF, li trasforma e rinomina e li mappa all'UDM. Gestisce vari tipi di dati, converte i livelli di gravità e classifica gli eventi in base alle informazioni su IP e nome host disponibili. Gestisce inoltre potenziali errori di analisi e elimina le voci di log con formato non corretto.
Prima di iniziare
- Assicurati di avere un'istanza Google SecOps.
- Un account Fastly con accesso per configurare le impostazioni WAF.
Configura un feed in Google SecOps per importare i log WAF di Fastly
- Vai a Impostazioni SIEM > Feed.
- Fai clic su Aggiungi nuovo.
- Nel campo Nome feed, inserisci un nome per il feed (ad esempio Log WAF Fastly).
- Seleziona Webhook come Tipo di origine.
- Seleziona Fastly WAF come Tipo di log.
- Fai clic su Avanti.
- (Facoltativo) Specifica i valori per i seguenti parametri di input:
- Delimitatore di split: il delimitatore utilizzato per separare le righe di log, ad esempio
\n
. - Spazio dei nomi degli asset: lo spazio dei nomi degli asset.
- Etichette di importazione: l'etichetta applicata agli eventi di questo feed.
- Delimitatore di split: il delimitatore utilizzato per separare le righe di log, ad esempio
- Fai clic su Avanti.
- Controlla la configurazione del feed nella schermata Concludi e poi fai clic su Invia.
- Fai clic su Genera chiave segreta per generare una chiave segreta per autenticare questo feed.
- Copia e memorizza la chiave segreta. Non potrai più visualizzare questa chiave segreta. Se necessario, puoi rigenerare una nuova chiave segreta, ma questa azione rende obsoleta la chiave segreta precedente.
- Nella scheda Dettagli, copia l'URL dell'endpoint del feed dal campo Informazioni sull'endpoint. Devi specificare questo URL endpoint nell'applicazione client.
- Fai clic su Fine.
Crea una chiave API per il feed webhook
Vai alla console Google Cloud > Credenziali.
Fai clic su Crea credenziali e poi seleziona Chiave API.
Limita l'accesso della chiave API all'API Google Security Operations.
Specifica l'URL dell'endpoint
- Nell'applicazione client, specifica l'URL dell'endpoint HTTPS fornito nel feed webhook.
Attiva l'autenticazione specificando la chiave API e la chiave segreta nell'intestazione personalizzata nel seguente formato:
X-goog-api-key = API_KEY X-Webhook-Access-Key = SECRET
Consiglio: specifica la chiave API come intestazione anziché nell'URL.
Se il client webhook non supporta le intestazioni personalizzate, puoi specificare la chiave API e la chiave segreta utilizzando parametri di ricerca nel seguente formato:
ENDPOINT_URL?key=API_KEY&secret=SECRET
Sostituisci quanto segue:
ENDPOINT_URL
: l'URL dell'endpoint del feed.API_KEY
: la chiave API per l'autenticazione in Google Security Operations.SECRET
: la chiave segreta che hai generato per autenticare il feed.
Configurare il webhook in Fastly
- Accedi a Fastly.
- (Facoltativo) Seleziona un sito nel menu Siti (se ne hai più di uno).
- Seleziona Gestisci > Integrazioni del sito.
- Fai clic su Aggiungi integrazione del sito.
- Seleziona Webhook generico.
- URL webhook: inserisci ENDPOINT_URL di Google SecOps, seguito da API_KEY e SECRET.
- Posizionamento avviso: seleziona Tutte le attività o Attività specifiche.
- (Facoltativo) Se hai selezionato Attività specifica, vai al menu Attività e seleziona i tipi di attività che vuoi che l'webhook invii.
- Fai clic su Crea integrazione del sito.
Tabella di mappatura UDM
Campo log | Mappatura UDM | Logica |
---|---|---|
anomaly_score |
security_result.detection_fields[].key : "anomaly"security_result.detection_fields[].value : anomaly_score |
Se waf.score.anomaly è 0 o vuoto e anomaly_score non è vuoto o 0, il valore anomaly_score viene utilizzato per compilare l'array security_result.detection_fields con una chiave "anomaly" e il valore del campo anomaly_score . |
cache_status |
additional.fields[].key : "cache_status"additional.fields[].value.string_value : cache_status |
Il valore cache_status viene utilizzato per compilare l'array additional.fields con una chiave "cache_status" e il valore del campo cache_status . |
client_ip |
principal.ip : client_ip |
Il campo client_ip è mappato a principal.ip . |
connection.fastly_is_edge |
additional.fields[].key : "fastly_is_edge"additional.fields[].value.bool_value : connection.fastly_is_edge |
Il valore connection.fastly_is_edge viene utilizzato per compilare l'array additional.fields con una chiave "fastly_is_edge" e il valore del campo connection.fastly_is_edge . |
connection.fastly_is_shield |
additional.fields[].key : "fastly_is_shield"additional.fields[].value.bool_value : connection.fastly_is_shield |
Il valore connection.fastly_is_shield viene utilizzato per compilare l'array additional.fields con una chiave "fastly_is_shield" e il valore del campo connection.fastly_is_shield . |
connection.request_tls_version |
network.tls.version : connection.request_tls_version |
Il campo connection.request_tls_version è mappato a network.tls.version . |
fastly.server |
target.hostname : fastly.server |
Il campo fastly.server è mappato a target.hostname . |
fastly.service_id |
additional.fields[].key : "service_id"additional.fields[].value.string_value : fastly.service_id |
Il valore fastly.service_id viene utilizzato per compilare l'array additional.fields con una chiave "service_id" e il valore del campo fastly.service_id . |
geo.city |
principal.location.city : geo.city |
Il campo geo.city è mappato a principal.location.city . |
geo.country |
principal.location.country_or_region : geo.country |
Il campo geo.country è mappato a principal.location.country_or_region . |
geo.location |
principal.location.region_latitude : estratto da geo.location principal.location.region_longitude : estratto da geo.location |
La latitudine e la longitudine vengono estratte dal campo geo.location utilizzando un'espressione regolare e mappate rispettivamente a principal.location.region_latitude e principal.location.region_longitude . |
geo.region |
principal.location.state : geo.region |
Il campo geo.region è mappato a principal.location.state . |
host |
principal.hostname : host |
Il campo host è mappato a principal.hostname . |
request_headers.accept_charset |
additional.fields[].key : "accept_charset"additional.fields[].value.string_value : request_headers.accept_charset |
Il valore request_headers.accept_charset viene utilizzato per compilare l'array additional.fields con una chiave "accept_charset" e il valore del campo request_headers.accept_charset . |
request_headers.accept_language |
additional.fields[].key : "accept_language"additional.fields[].value.string_value : request_headers.accept_language |
Il valore request_headers.accept_language viene utilizzato per compilare l'array additional.fields con una chiave "accept_language" e il valore del campo request_headers.accept_language . |
request_headers.referer |
network.http.referral_url : request_headers.referer |
Il campo request_headers.referer è mappato a network.http.referral_url . |
request_headers.user_agent |
network.http.user_agent : request_headers.user_agent |
Il campo request_headers.user_agent è mappato a network.http.user_agent . |
request_id |
metadata.product_log_id : request_id |
Il campo request_id è mappato a metadata.product_log_id . |
request_method |
network.http.method : request_method |
Il campo request_method è mappato a network.http.method . |
response_headers.cache_control |
additional.fields[].key : "cache_control"additional.fields[].value.string_value : response_headers.cache_control |
Il valore response_headers.cache_control viene utilizzato per compilare l'array additional.fields con una chiave "cache_control" e il valore del campo response_headers.cache_control . |
response_headers.content_type |
additional.fields[].key : "content_type"additional.fields[].value.string_value : response_headers.content_type |
Il valore response_headers.content_type viene utilizzato per compilare l'array additional.fields con una chiave "content_type" e il valore del campo response_headers.content_type . |
response_state |
additional.fields[].key : "response_state"additional.fields[].value.string_value : response_state |
Il valore response_state viene utilizzato per compilare l'array additional.fields con una chiave "response_state" e il valore del campo response_state . |
response_status |
network.http.response_code : response_status |
Il campo response_status è mappato a network.http.response_code se il campo status è vuoto. |
rule_id |
security_result.rule_id : rule_id |
Se waf.rule_id è vuoto, il valore rule_id viene utilizzato per compilare security_result.rule_id . |
severity |
waf.severity : severity |
Il valore del campo severity viene copiato in waf.severity . |
size_bytes.request_header |
network.sent_bytes : size_bytes.request_header |
Il campo size_bytes.request_header è mappato a network.sent_bytes . |
size_bytes.response_header |
network.received_bytes : size_bytes.response_header |
Il campo size_bytes.response_header è mappato a network.received_bytes . |
status |
network.http.response_code : status |
Il campo status è mappato a network.http.response_code . |
timestamp |
metadata.event_timestamp : timestamp |
Il campo timestamp viene analizzato e mappato a metadata.event_timestamp . |
url |
target.url : url |
Il campo url è mappato a target.url . |
waf.blocked |
security_result.action : derivato |
Se waf.blocked è false, security_result.action è impostato su "ALLOW". Se waf.blocked è true, security_result.action è impostato su "BLOCK". |
waf.executed |
security_result.detection_fields[].key : "executed"security_result.detection_fields[].value : waf.executed |
Il valore waf.executed viene utilizzato per compilare l'array security_result.detection_fields con una chiave "executed" e il valore del campo waf.executed . |
waf.failures |
security_result.detection_fields[].key : "failures"security_result.detection_fields[].value : waf.failures |
Il valore waf.failures viene utilizzato per compilare l'array security_result.detection_fields con una chiave "errori" e il valore del campo waf.failures . |
waf.logged |
security_result.detection_fields[].key : "logged"security_result.detection_fields[].value : waf.logged |
Il valore waf.logged viene utilizzato per compilare l'array security_result.detection_fields con una chiave "logged" e il valore del campo waf.logged . |
waf.message |
metadata.description : waf.message |
Se waf.message non è vuoto, viene mappato a metadata.description . |
waf.rule_id |
security_result.rule_id : waf.rule_id |
Se waf.rule_id non è vuoto, viene mappato a security_result.rule_id . |
waf.score.anomaly |
security_result.detection_fields[].key : "anomaly"security_result.detection_fields[].value : waf.score.anomaly |
Se waf.score.anomaly non è 0 e non è vuoto, il valore viene utilizzato per compilare l'array security_result.detection_fields con una chiave "anomaly" e il valore del campo waf.score.anomaly . |
waf.score.http_violation |
security_result.detection_fields[].key : "http_violation"security_result.detection_fields[].value : waf.score.http_violation |
Se waf.score.http_violation non è 0 e non è vuoto, il valore viene utilizzato per compilare l'array security_result.detection_fields . |
waf.score.lfi |
security_result.detection_fields[].key : "lfi"security_result.detection_fields[].value : waf.score.lfi |
Logica simile a waf.score.http_violation . |
waf.score.php_injection |
security_result.detection_fields[].key : "php_injection"security_result.detection_fields[].value : waf.score.php_injection |
Logica simile a waf.score.http_violation . |
waf.score.rce |
security_result.detection_fields[].key : "rce"security_result.detection_fields[].value : waf.score.rce |
Logica simile a waf.score.http_violation . |
waf.score.rfi |
security_result.detection_fields[].key : "rfi"security_result.detection_fields[].value : waf.score.rfi |
Logica simile a waf.score.http_violation . |
waf.score.session_fixation |
security_result.detection_fields[].key : "session_fixation"security_result.detection_fields[].value : waf.score.session_fixation |
Logica simile a waf.score.http_violation . |
waf.score.sql_injection |
security_result.detection_fields[].key : "sql_injection"security_result.detection_fields[].value : waf.score.sql_injection |
Logica simile a waf.score.http_violation . |
waf.score.xss |
security_result.detection_fields[].key : "xss"security_result.detection_fields[].value : waf.score.xss |
Logica simile a waf.score.http_violation . |
waf.severity |
security_result.severity : derivatosecurity_result.severity_details : waf.severity |
Se waf.severity non è vuoto, ne determina il valore in base agli intervalli (<=3: ALTA, >3 e <=6: MEDIA, >6 e <=8: BASSA, altrimenti: UNKNOWN_SEVERITY).security_result.severity Anche il valore waf.severity originale è mappato a security_result.severity_details . |
waf_message |
metadata.description : waf_message |
Se waf.message è vuoto e waf_message non è vuoto, viene mappato a metadata.description . Se client_ip o host e fastly.server non sono vuoti, metadata.event_type viene impostato su "NETWORK_HTTP". In caso contrario, se client_ip o host non sono vuoti, metadata.event_type viene impostato su "STATUS_UPDATE". In caso contrario, viene impostato su "GENERIC_EVENT". Valore hardcoded. Valore hardcoded. Valore hardcoded. |
Modifiche
2022-06-06
- Parser appena creato.