Raccogliere i log di Google App Engine
Questo documento spiega come importare i log di Google App Engine in Google Security Operations utilizzando Google Cloud Storage V2.
Google App Engine è una piattaforma serverless completamente gestita per la creazione e il deployment di applicazioni web e API. App Engine genera automaticamente i log delle richieste per le richieste HTTP e i log dell'applicazione dal tuo codice. Questi log vengono inviati a Cloud Logging e possono essere esportati in Cloud Storage per l'importazione in Google Security Operations.
Prima di iniziare
Assicurati di disporre dei seguenti prerequisiti:
- Un'istanza Google SecOps
- Un progetto GCP con l'API Cloud Storage abilitata
- Autorizzazioni per creare e gestire bucket GCS
- Autorizzazioni per gestire le policy IAM nei bucket GCS
- Autorizzazioni per creare sink di Cloud Logging (roles/logging.configWriter)
- Un'applicazione App Engine attiva (ambiente standard o flessibile)
Creazione di un bucket Google Cloud Storage
- Vai alla console Google Cloud.
- Seleziona il tuo progetto o creane uno nuovo.
- Nel menu di navigazione, vai a Cloud Storage > Bucket.
- Fai clic su Crea bucket.
Fornisci i seguenti dettagli di configurazione:
Impostazione Valore Assegna un nome al bucket Inserisci un nome univoco globale (ad esempio appengine-logs-export).Tipo di località Scegli in base alle tue esigenze (regione singola, doppia regione, più regioni) Località Seleziona la posizione (ad esempio, us-central1).Classe di archiviazione Standard (consigliato per i log a cui si accede di frequente) Controllo dell'accesso Uniforme (consigliato) Strumenti di protezione (Facoltativo) Attiva il controllo delle versioni degli oggetti o la policy di conservazione Fai clic su Crea.
Configura Cloud Logging per esportare i log di App Engine in GCS
Cloud Logging utilizza i sink di log per instradare le voci di log verso destinazioni supportate, inclusi i bucket Cloud Storage. L'identità del writer del sink richiede il ruolo Creatore oggetti Storage (roles/storage.objectCreator) nel bucket di destinazione.
Crea un sink Cloud Logging
- Nella console Google Cloud, vai a Logging > Log Router.
- Fai clic su Crea sink.
- Fornisci i seguenti dettagli di configurazione:
- Nome sink: inserisci un nome descrittivo, ad esempio
appengine-to-gcs. - Descrizione sink: descrizione facoltativa.
- Nome sink: inserisci un nome descrittivo, ad esempio
- Fai clic su Avanti.
- Nella sezione Seleziona il servizio sink:
- Servizio sink: seleziona Bucket Cloud Storage.
- Seleziona bucket Cloud Storage: seleziona
appengine-logs-exportdal menu a discesa.
- Fai clic su Avanti.
Nella sezione Scegli i log da includere nel sink, inserisci una query di filtro per selezionare i log di App Engine. Il tipo di risorsa deve essere esattamente "gae_app".
Per tutti i log di App Engine (log di richiesta e dell'applicazione):
resource.type="gae_app"Solo per i log di richiesta di App Engine:
resource.type="gae_app" logName="projects/PROJECT_ID/logs/appengine.googleapis.com/request_log"Per i log delle applicazioni App Engine (stdout/stderr):
resource.type="gae_app" (logName="projects/PROJECT_ID/logs/stdout" OR logName="projects/PROJECT_ID/logs/stderr")Sostituisci
PROJECT_IDcon l'ID progetto GCP.Fai clic su Avanti.
Rivedi la configurazione e fai clic su Crea sink.
Concedi autorizzazioni all'identità di scrittura del sink
Dopo aver creato il sink, devi concedere all'identità di scrittura del sink il ruolo Storage Object Creator nel bucket di destinazione. L'identità del writer per il account di servizio ha un aspetto simile a: serviceAccount:service-123456789012@gcp-sa-logging.iam.gserviceaccount.com
- Nella pagina Router dei log, individua il sink appena creato.
- Fai clic sull'icona del menu (tre puntini verticali) accanto al nome del sink.
- Seleziona Visualizza dettagli del lavello.
- Copia l'identità Writer (indirizzo email del account di servizio).
- Vai a Cloud Storage > Bucket.
- Fai clic sul nome del bucket (
appengine-logs-export). - Vai alla scheda Autorizzazioni.
- Fai clic su Concedi l'accesso.
- Fornisci i seguenti dettagli di configurazione:
- Aggiungi entità: incolla l'identità del writer del sink (email del account di servizio).
- Assegna i ruoli: seleziona Storage Object Creator.
- Fai clic su Salva.
Recuperare il service account Google SecOps
Google SecOps utilizza un service account univoco per leggere i dati dal tuo bucket GCS. Devi concedere a questo service account l'accesso al tuo bucket.
Configura un feed in Google SecOps per importare i log di App Engine
- Vai a Impostazioni SIEM > Feed.
- Fai clic su Aggiungi nuovo feed.
- Fai clic su Configura un singolo feed.
- Nel campo Nome feed, inserisci un nome per il feed (ad esempio,
App Engine Logs). - Seleziona Google Cloud Storage V2 come Tipo di origine.
Seleziona GCP_APP_ENGINE come Tipo di log.
Fai clic su Ottieni service account.
Verrà visualizzata un'email univoca del service account, ad esempio:
chronicle-12345678@chronicle-gcp-prod.iam.gserviceaccount.comCopia l'indirizzo email. Lo utilizzerai nel prossimo passaggio.
Fai clic su Avanti.
Specifica i valori per i seguenti parametri di input:
URL del bucket di archiviazione: inserisci l'URI del bucket GCS con il percorso del prefisso:
gs://appengine-logs-export/Cloud Logging organizza i file di log esportati in gerarchie di directory per tipo di log e data. Il tipo di log può essere un nome composto come appengine.googleapis.com/request_log. I file vengono suddivisi e denominati in base ai periodi di tempo (ad esempio, 08:00:00_08:59:59_S0.json).
Opzione di eliminazione dell'origine: seleziona l'opzione di eliminazione in base alle tue preferenze:
- Mai: non elimina mai i file dopo i trasferimenti (opzione consigliata per i test).
- Elimina file trasferiti: elimina i file dopo il trasferimento riuscito.
- Elimina file trasferiti e directory vuote: elimina i file e le directory vuote dopo il trasferimento riuscito.
Età massima del file: includi i file modificati nell'ultimo numero di giorni. Il valore predefinito è 180 giorni.
Spazio dei nomi dell'asset: lo spazio dei nomi dell'asset.
Etichette di importazione: l'etichetta da applicare agli eventi di questo feed.
Fai clic su Avanti.
Controlla la nuova configurazione del feed nella schermata Finalizza e poi fai clic su Invia.
Concedi le autorizzazioni IAM al service account Google SecOps
Il service account Google SecOps deve avere il ruolo Visualizzatore oggetti Storage nel bucket GCS.
- Vai a Cloud Storage > Bucket.
- Fai clic sul nome del bucket (
appengine-logs-export). - Vai alla scheda Autorizzazioni.
- Fai clic su Concedi l'accesso.
- Fornisci i seguenti dettagli di configurazione:
- Aggiungi entità: incolla l'email del service account Google SecOps.
- Assegna i ruoli: seleziona Visualizzatore oggetti Storage.
Fai clic su Salva.
Informazioni sulla struttura dei log di App Engine
App Engine invia automaticamente sia i log delle richieste sia i log delle app a Cloud Logging. App Engine genera automaticamente i log per le richieste inviate alla tua app, quindi non è necessario scrivere i log delle richieste. Questa sezione spiega come scrivere i log delle app.
I log di richiesta App Engine contengono voci di log con campi protoPayload che contengono oggetti di tipo RequestLog con @type "type.googleapis.com/google.appengine.logging.v1.RequestLog". Il tipo di risorsa è "gae_app".
Per impostazione predefinita, il payload del log è una stringa di testo memorizzata nel campo textPayload della voce di log. Le stringhe vengono visualizzate come messaggi in Explorer log e sono associate al servizio e alla versione di App Engine che le hanno emesse.
Per scrivere log strutturati, scrivi i log sotto forma di una singola riga di JSON serializzato. Quando fornisci un log strutturato come dizionario JSON, alcuni campi speciali vengono rimossi da jsonPayload e scritti nel campo corrispondente della voce di log generata. Ad esempio, se il file JSON include una proprietà di gravità, questa viene rimossa da jsonPayload e viene visualizzata come gravità della voce di log.
Limitazioni note
Quando indirizzi i log dal sink di log a Cloud Storage, la destinazione Cloud Storage contiene solo i log delle richieste. App Engine scrive i log delle app in cartelle diverse.
Le voci di log con routing vengono salvate nei bucket Cloud Storage in batch orari. Potrebbero essere necessarie dalle 2 alle 3 ore prima che inizino a comparire le prime voci.
Nell'ambiente flessibile di App Engine, la registrazione funziona automaticamente. Tuttavia, i log vengono raccolti in un formato diverso. I log non verranno raggruppati per richieste e i log di stdout e stderr vengono raccolti separatamente.
Tabella di mappatura UDM
| Campo log | Mappatura UDM | Logic |
|---|---|---|
| jsonPayload.logger, taskTypeName, jsonPayload.@type, jsonPayload.backendTargetProjectNumber, jsonPayload.cacheDecision, resource.labels.version_id, resource.labels.module_id, logName, spanId, trace, protoPayload.@type, labels.clone_id, operation.producer | additional.fields | Unite alle etichette chiave-valore create da ogni campo |
| metadati | metadati | Rinominate dai metadati |
| receiveTimestamp | metadata.collected_timestamp | Analizzato utilizzando il filtro per data con RFC3339 |
| metadata.event_type | Imposta "USER_LOGIN" se has_principal, has_target, has_principal_user; "NETWORK_CONNECTION" se has_principal e has_target; "USER_UNCATEGORIZED" se non has_principal e has_target; "STATUS_UPDATE" se has_principal; "USER_UNCATEGORIZED" se has_principal_user; altrimenti "GENERIC_EVENT" | |
| metadata.extensions.auth.type | Imposta su "AUTHTYPE_UNSPECIFIED" se has_principal, has_target, has_principal_user | |
| insertId | metadata.product_log_id | Valore copiato direttamente |
| httpRequest.requestMethod,protoPayload.method | network.http.method | Valore di httpRequest.requestMethod se non è vuoto, altrimenti protoPayload.method |
| httpRequest.userAgent | network.http.parsed_user_agent | Convertito in parseduseragent |
| httpRequest.status | network.http.response_code | Convertito in stringa e poi in numero intero |
| httpRequest.userAgent | network.http.user_agent | Valore copiato direttamente |
| httpRequest.responseSize | network.received_bytes | Convertito in uinteger |
| httpRequest.requestSize | network.sent_bytes | Convertito in uinteger |
| entità | entità | Rinomina da entità se non è vuoto |
| protoPayload.host | principal.asset.hostname | Valore copiato direttamente |
| httpRequest.serverIp, protoPayload.ip | principal.asset.ip | Unito a server_ip da httpRequest.serverIp o protoPayload.ip |
| protoPayload.host | principal.hostname | Valore copiato direttamente |
| httpRequest.serverIp, protoPayload.ip | principal.ip | Unito a server_ip da httpRequest.serverIp o protoPayload.ip |
| protoPayload.appId | principal.resource.attribute.labels | Unito a appId_label contenente la chiave "appId" e il valore del campo |
| requestUser | principal.user.email_addresses | Unito a requestUser se corrisponde al pattern email |
| security_result | security_result | Unito da security_result |
| resource.labels.forwarding_rule_name | security_result.rule_labels | Unito a rule_label contenente la chiave "forwarding_rule_name" e il valore del campo |
| gravità | security_result.severity | Impostato su gravità se corrisponde a (?i)ERROR|CRITICAL, su INFORMATIONAL se corrisponde a (?i)INFO, su MEDIUM se corrisponde a (?i)WARN, su LOW se corrisponde a (?i)DEBUG, altrimenti su UNKNOWN_SEVERITY |
| jsonPayload.statusDetails | security_result.summary | Valore copiato direttamente |
| target | target | Rinomina dalla destinazione se non è vuoto |
| resource.labels.backend_service_name | target.application | Valore copiato direttamente |
| httpRequest.remoteIp, jsonPayload.remoteIp | target.asset.ip | Unito a remote_ip estratto da httpRequest.remoteIp o jsonPayload.remoteIp |
| resource.labels.project_id | target.cloud.project.name | Valore copiato direttamente |
| httpRequest.remoteIp, jsonPayload.remoteIp | target.ip | Unito a remote_ip estratto da httpRequest.remoteIp o jsonPayload.remoteIp |
| resource.labels.zone | target.resource.attribute.cloud.availability_zone | Valore copiato direttamente |
| resource.labels.target_proxy_name, resource.labels.url_map_name | target.resource.attribute.labels | Unite alle etichette di ogni origine |
| resource.type | target.resource.type | Valore copiato direttamente |
| httpRequest.requestUrl | target.url | Valore copiato direttamente |
| metadata.product_name | Impostato su "GCP_APP_ENGINE" | |
| metadata.vendor_name | Imposta su "GCP" |
Hai bisogno di ulteriore assistenza? Ricevi risposte dai membri della community e dai professionisti di Google SecOps.