Raccogliere i log WAF di Fastly
Panoramica
Questo parser estrae i campi dai log JSON di Fastly WAF, li trasforma e li rinomina e li mappa a UDM. Gestisce vari tipi di dati, converte i livelli di gravità e classifica gli eventi in base alle informazioni disponibili su IP e nome host. Gestisce anche potenziali errori di analisi ed elimina le voci di log non valide.
Prima di iniziare
Assicurati di soddisfare i seguenti prerequisiti:
- Istanza Google SecOps.
- Account Fastly con accesso per configurare le impostazioni WAF.
Configurare i feed
Esistono due diversi punti di accesso per configurare i feed nella piattaforma Google SecOps:
- Impostazioni SIEM > Feed
- Hub dei contenuti > Pacchetti di contenuti
Configura i feed da Impostazioni SIEM > Feed
Per configurare un feed:
- Vai a Impostazioni SIEM > Feed.
- Fai clic su Aggiungi nuovo feed.
- Nella pagina successiva, fai clic su Configura un singolo feed.
- Nel campo Nome feed, inserisci un nome per il feed (ad esempio, Fastly WAF Logs).
- 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 suddivisione: il delimitatore utilizzato per separare le righe di log, ad esempio
\n
.
- Delimitatore di suddivisione: il delimitatore utilizzato per separare le righe di log, ad esempio
- Fai clic su Avanti.
- Controlla la configurazione del feed nella schermata Finalizza 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 puoi visualizzare di nuovo 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 dell'endpoint nell'applicazione client.
- Fai clic su Fine.
Configurare i feed dall'hub dei contenuti
Specifica i valori per i seguenti campi:
- Delimitatore di suddivisione: il delimitatore utilizzato per separare le righe di log, ad esempio
\n
.
Opzioni avanzate
- Nome feed: un valore precompilato che identifica il feed.
- Tipo di origine: metodo utilizzato per raccogliere i log in Google SecOps.
- Spazio dei nomi dell'asset: lo spazio dei nomi associato al feed.
Etichette di importazione: etichette applicate a tutti gli eventi di questo feed.
Fai clic su Genera chiave segreta per generare una chiave segreta per autenticare questo feed.
Copia e memorizza la chiave segreta. Non puoi visualizzare di nuovo 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 dell'endpoint nell'applicazione client.
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
- Nella tua applicazione client, specifica l'URL dell'endpoint HTTPS fornito nel feed webhook.
Attiva l'autenticazione specificando la chiave API e la chiave segreta come parte dell'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 a Google Security Operations.SECRET
: la chiave segreta che hai generato per autenticare il feed.
Configura il webhook in Fastly
- Accedi a Fastly.
- (Facoltativo) Seleziona un sito nel menu Siti (se hai più di un sito).
- 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 avvisi: seleziona Tutte le attività o Attività specifica.
- (Facoltativo) Se hai selezionato Attività specifica, vai al menu Attività e seleziona i tipi di attività che vuoi che il webhook invii.
- Fai clic su Crea integrazione del sito.
Tabella di mappatura UDM
Campo log | Mappatura UDM | Logic |
---|---|---|
anomaly_score |
security_result.detection_fields[].key : "anomalia"security_result.detection_fields[].value : anomaly_score |
Se waf.score.anomaly è 0 o vuoto e anomaly_score non è vuoto o 0, il valore di anomaly_score viene utilizzato per compilare l'array security_result.detection_fields con una chiave "anomalia" e il valore del campo anomaly_score . |
cache_status |
additional.fields[].key : "cache_status"additional.fields[].value.string_value : cache_status |
Il valore di 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 popolare 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 : derivata |
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 "failures" 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 : "anomalia"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 : derivedsecurity_result.severity_details : waf.severity |
Se waf.severity non è vuoto, determina il valore di security_result.severity in base agli intervalli (<=3: HIGH, >3 e <=6: MEDIUM, >6 e <=8: LOW, altrimenti: UNKNOWN_SEVERITY). Anche il valore originale waf.severity è 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 è impostato su "NETWORK_HTTP". Altrimenti, se client_ip o host non sono vuoti, metadata.event_type è impostato su "STATUS_UPDATE". In caso contrario, è impostato su "GENERIC_EVENT". Valore hardcoded. Valore hardcoded. Valore hardcoded. |
Hai bisogno di ulteriore assistenza? Ricevi risposte dai membri della community e dai professionisti di Google SecOps.