Raccogliere i log del proxy OAuth2
Questo documento spiega come importare i log di OAuth2 Proxy in Google Security Operations utilizzando Google Cloud Storage V2.
OAuth2 Proxy è un reverse proxy CNCF Sandbox che fornisce l'autenticazione utilizzando provider OAuth2/OIDC (Google, GitHub, Keycloak, Azure AD e altri) per convalidare gli account per email, dominio o gruppo. Genera log di autenticazione (accesso riuscito/non riuscito), log delle richieste (richieste HTTP proxy con identità utente) e log delle applicazioni standard. Poiché OAuth2 Proxy viene eseguito come container in Kubernetes e scrive tutti i log in stdout, viene utilizzato un agente di raccolta di log nativo di Kubernetes (Fluentd) per inoltrare i log a un bucket GCS per l'importazione di Google SecOps.
Prima di iniziare
Assicurati di soddisfare i seguenti prerequisiti:
- Un'istanza Google SecOps
- Un progetto GCP con l'API Storage Cloud abilitata
- Autorizzazioni per creare e gestire bucket GCS
- Autorizzazioni per gestire le policy IAM nei bucket GCS
- Un cluster Kubernetes in esecuzione con OAuth2 Proxy di cui è stato eseguito il deployment (tramite grafico Helm o deployment manuale)
kubectlaccesso al cluster Kubernetes con autorizzazioni per creare DaemonSet, ConfigMap, Secret e spazi dei nomi- Una chiave JSON del account di servizio Google Cloud con autorizzazione
storage.objects.createsul bucket GCS di destinazione
Crea 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 oauth2-proxy-logs-bucket).Tipo di località Scegli in base alle tue esigenze (regione singola, a due regioni, multiregionale) 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 la registrazione proxy OAuth2
OAuth2 Proxy scrive tre tipi di log in stdout: log standard, log di autenticazione e log delle richieste. Tutte e tre sono abilitate per impostazione predefinita. Per assicurarti che i log contengano il massimo livello di dettagli pertinenti alla sicurezza, configura OAuth2 Proxy con i seguenti flag di logging.
Opzione 1: configura tramite i valori del grafico Helm
Se OAuth2 Proxy viene implementato utilizzando il grafico Helm ufficiale, aggiungi quanto segue al file
values.yaml:config: configFile: |- standard_logging = true auth_logging = true request_logging = true silence_ping_logging = true standard_logging_format = "[{{.Timestamp}}] [{{.File}}] {{.Message}}" auth_logging_format = "{{.Client}} - {{.RequestID}} - {{.Username}} [{{.Timestamp}}] [{{.Status}}] {{.Message}}" request_logging_format = "{{.Client}} - {{.RequestID}} - {{.Username}} [{{.Timestamp}}] {{.Host}} {{.RequestMethod}} {{.Upstream}} {{.RequestURI}} {{.Protocol}} {{.UserAgent}} {{.StatusCode}} {{.ResponseSize}} {{.RequestDuration}}"Applica i valori Helm aggiornati:
helm upgrade oauth2-proxy oauth2-proxy/oauth2-proxy -f values.yaml -n <your-namespace>
Opzione 2: configura tramite i flag della riga di comando
Se OAuth2 Proxy viene implementato utilizzando un manifest di deployment Kubernetes, aggiungi i seguenti argomenti alla specifica del container:
args: - --standard-logging=true - --auth-logging=true - --request-logging=true - --silence-ping-logging=true
Opzione 3: configura tramite le variabili di ambiente
Imposta le seguenti variabili di ambiente nel container proxy OAuth2:
env: - name: OAUTH2_PROXY_STANDARD_LOGGING value: "true" - name: OAUTH2_PROXY_AUTH_LOGGING value: "true" - name: OAUTH2_PROXY_REQUEST_LOGGING value: "true" - name: OAUTH2_PROXY_SILENCE_PING_LOGGING value: "true"
Verifica la registrazione di OAuth2 Proxy
Dopo aver applicato la configurazione, verifica che OAuth2 Proxy stia producendo log:
kubectl logs -l app=oauth2-proxy -n <your-namespace> --tail=20L'output include righe simili alle seguenti:
10.0.0.1 - abc123 - user@example.com [2024/01/15 10:30:00] [AuthSuccess] Authenticated via OAuth2 10.0.0.1 - abc123 - user@example.com [2024/01/15 10:30:01] example.com GET 10.0.0.5:8080 "/dashboard" HTTP/1.1 "Mozilla/5.0" 200 1234 0.005
Crea un account di servizio Google Cloud per Fluentd
Fluentd richiede un account di servizio Google Cloud con accesso in scrittura al bucket GCS.
- Nella console Google Cloud, vai a IAM e amministrazione > Service account.
- Fai clic su Crea account di servizio.
- Fornisci i seguenti dettagli di configurazione:
- Nome del service account: inserisci
fluentd-gcs-writer - Descrizione service account: inserisci
Service account for Fluentd to write OAuth2 Proxy logs to GCS
- Nome del service account: inserisci
- Fai clic su Crea e continua.
- Nella sezione Concedi a questo account di servizio l'accesso al progetto:
- Fai clic su Seleziona un ruolo.
- Cerca e seleziona Storage Object Admin.
- Fai clic su Continua.
- Fai clic su Fine.
Crea e scarica la chiave del account di servizio
- Nell'elenco Service account, fai clic sul account di servizio
fluentd-gcs-writer. - Vai alla scheda Chiavi.
- Fai clic su Aggiungi chiave > Crea nuova chiave.
- Seleziona JSON come tipo di chiave.
- Fai clic su Crea.
- Salva in modo sicuro il file della chiave JSON scaricato. Questo file viene utilizzato nel passaggio successivo.
Crea il secret Kubernetes per la chiave del account di servizio
Crea un secret Kubernetes contenente la chiave del account di servizio Google Cloud nello spazio dei nomi in cui verrà eseguito il deployment di Fluentd:
kubectl create namespace logging kubectl create secret generic fluentd-gcs-key \ --from-file=service-account-key.json=<path-to-downloaded-key>.json \ -n logging
Esegui il deployment di Fluentd DaemonSet per raccogliere i log del proxy OAuth2
Esegui il deployment di Fluentd come DaemonSet nel cluster Kubernetes per raccogliere i log dei container dai pod proxy OAuth2 e inoltrarli al bucket GCS.
Crea ConfigMap Fluentd
Crea un file denominato
fluentd-configmap.yamlcon i seguenti contenuti:apiVersion: v1 kind: ConfigMap metadata: name: fluentd-gcs-config namespace: logging data: fluent.conf: | <source> @type tail read_from_head true tag kubernetes.* path /var/log/containers/*oauth2-proxy*.log pos_file /var/log/fluentd-oauth2-proxy.log.pos <parse> @type regexp expression /^(?<time>[^ ]+) (?<stream>stdout|stderr) [^ ]* (?<log>.*)$/ time_format %Y-%m-%dT%H:%M:%S.%N%z </parse> </source> <filter kubernetes.**> @type kubernetes_metadata @id filter_kube_metadata </filter> <match kubernetes.**> @type gcs project YOUR_GCP_PROJECT_ID keyfile /etc/secrets/service-account-key.json bucket oauth2-proxy-logs-bucket path oauth2-proxy-logs/%Y/%m/%d/ object_key_format %{path}%{time_slice}_%{hostname}_%{index}.%{file_extension} <buffer tag,time> @type file path /var/log/fluentd/gcs timekey 300 timekey_wait 60 timekey_use_utc true chunk_limit_size 10MB </buffer> <format> @type json </format> </match>
Sostituisci i seguenti valori:
YOUR_GCP_PROJECT_ID: Il tuo ID progetto Google Cloud (ad esempio,my-project-123456)oauth2-proxy-logs-bucket: il nome del bucket GCS creato in precedenzaApplica ConfigMap:
kubectl apply -f fluentd-configmap.yaml
Crea Fluentd DaemonSet
Crea un file denominato
fluentd-daemonset.yamlcon i seguenti contenuti:apiVersion: apps/v1 kind: DaemonSet metadata: name: fluentd-gcs namespace: logging labels: k8s-app: fluentd-gcs spec: selector: matchLabels: k8s-app: fluentd-gcs template: metadata: labels: k8s-app: fluentd-gcs spec: tolerations: - key: node-role.kubernetes.io/control-plane effect: NoSchedule - key: node-role.kubernetes.io/master effect: NoSchedule containers: - name: fluentd-gcs image: fluent/fluentd-kubernetes-daemonset:v1-debian-gcs resources: limits: memory: 512Mi requests: cpu: 100m memory: 200Mi volumeMounts: - name: fluentd-gcs-config-volume mountPath: /fluentd/etc/fluent.conf subPath: fluent.conf readOnly: true - name: fluentd-gcs-secrets-volume mountPath: /etc/secrets/service-account-key.json subPath: service-account-key.json readOnly: true - name: varlog mountPath: /var/log - name: dockercontainerlogdirectory mountPath: /var/log/pods readOnly: true - name: fluentd-buffer mountPath: /var/log/fluentd terminationGracePeriodSeconds: 30 volumes: - name: fluentd-gcs-config-volume configMap: name: fluentd-gcs-config - name: fluentd-gcs-secrets-volume secret: secretName: fluentd-gcs-key - name: varlog hostPath: path: /var/log - name: dockercontainerlogdirectory hostPath: path: /var/log/pods - name: fluentd-buffer emptyDir: {}Applica il DaemonSet:
kubectl apply -f fluentd-daemonset.yaml
Verifica il deployment di Fluentd
Verifica che i pod Fluentd siano in esecuzione su ogni nodo:
kubectl get pods -n logging -l k8s-app=fluentd-gcsControlla i log di Fluentd per verificare che le scritture GCS siano state eseguite correttamente:
kubectl logs -l k8s-app=fluentd-gcs -n logging --tail=20Verifica che i file di log vengano visualizzati nel bucket GCS:
- Vai a Cloud Storage > Bucket nella console di GCP.
- Fai clic sul bucket (ad esempio,
oauth2-proxy-logs-bucket). - Vai alla cartella
oauth2-proxy-logs/. - Verifica che i file
.jsonsiano presenti con timestamp recenti.
Recuperare il account di servizio Google SecOps
Google SecOps utilizza un account di servizio univoco per leggere i dati dal tuo bucket GCS. Devi concedere a questo account di servizio l'accesso al tuo bucket.
Recupera l'email del account di servizio
- 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,
OAuth2 Proxy Logs). - Seleziona Google Cloud Storage V2 come Tipo di origine.
- Seleziona Kubernetes Auth Proxy come Tipo di log.
Fai clic su Ottieni service account. Verrà visualizzata un'email del account di servizio univoca, ad esempio:
chronicle-12345678@chronicle-gcp-prod.iam.gserviceaccount.comCopia questo indirizzo email per utilizzarlo nel passaggio successivo.
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://oauth2-proxy-logs-bucket/oauth2-proxy-logs/Sostituisci
oauth2-proxy-logs-bucketcon il nome del tuo bucket GCS.
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 i 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 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 account di servizio Google SecOps
Il account di servizio Google SecOps deve avere il ruolo Visualizzatore oggetti Storage nel bucket GCS.
- Vai a Cloud Storage > Bucket.
- Fai clic sul nome del bucket (ad esempio
oauth2-proxy-logs-bucket). - Vai alla scheda Autorizzazioni.
- Fai clic su Concedi l'accesso.
- Fornisci i seguenti dettagli di configurazione:
- Aggiungi entità: incolla l'email dell'account di servizio Google SecOps (ad esempio,
chronicle-12345678@chronicle-gcp-prod.iam.gserviceaccount.com). - Assegna i ruoli: seleziona Visualizzatore oggetti Storage
- Aggiungi entità: incolla l'email dell'account di servizio Google SecOps (ad esempio,
- Fai clic su Salva.
Riferimento ai log del proxy OAuth2
La tabella seguente descrive i campi di log generati da OAuth2 Proxy e la loro rilevanza per la sicurezza:
Campi dei log di autenticazione
| Campo | Esempio | Descrizione |
|---|---|---|
| Client | 10.0.0.1 |
Indirizzo IP client/remoto (utilizza l'intestazione X-Real-IP se --reverse-proxy=true) |
| RequestID | 00010203-0405-4607-8809-0a0b0c0d0e0f |
ID richiesta dall'intestazione X-Request-Id (UUID casuale se vuoto) |
| Nome utente | user@example.com |
Email o nome utente della richiesta di autenticazione |
| Timestamp | 2024/01/15 10:30:00 |
Data e ora dell'evento di autenticazione |
| Stato | AuthSuccess |
Risultato dell'autenticazione: AuthSuccess, AuthFailure o AuthError |
| Messaggio | Authenticated via OAuth2 |
Dettagli del tentativo di autenticazione |
Campi dei log delle richieste
| Campo | Esempio | Descrizione |
|---|---|---|
| Client | 10.0.0.1 |
Indirizzo IP client/remoto |
| RequestID | 00010203-0405-4607-8809-0a0b0c0d0e0f |
ID richiesta |
| Nome utente | user@example.com |
Email dell'utente autenticato |
| Timestamp | 2024/01/15 10:30:01 |
Data e ora della richiesta |
| Host | app.example.com |
Valore dell'intestazione Host |
| RequestMethod | GET |
Metodo di richiesta HTTP |
| Upstream | 10.0.0.5:8080 |
Server upstream che ha gestito la richiesta |
| RequestURI | /dashboard |
Percorso URI della richiesta |
| Protocollo | HTTP/1.1 |
Protocollo richiesta |
| UserAgent | Mozilla/5.0 |
Stringa completa dello user agent |
| StatusCode | 200 |
Codice di stato risposta HTTP |
| ResponseSize | 1234 |
Dimensioni della risposta in byte |
| RequestDuration | 0.005 |
Tempo di elaborazione della richiesta in secondi |
Tabella di mappatura UDM
| Campo log | Mappatura UDM | Logica |
|---|---|---|
| about | about | Informazioni sull'evento |
| http_req_id_field | additional.fields | Campi aggiuntivi non coperti dallo schema UDM standard |
| http_req_path_field | additional.fields | |
| k8s_pod_app_field | additional.fields | |
| k8s_pod_template_hash_field | additional.fields | |
| k8s_pod_tls_mode_field | additional.fields | |
| k8s_pod_canonical_revision_field | additional.fields | |
| k8s_pod_canonical_name_field | additional.fields | |
| pod_name | additional.fields | |
| cntnr_name | additional.fields | |
| destination_canonical_revision | additional.fields | |
| requested_server | additional.fields | |
| nodename_label | additional.fields | |
| componentName_label | additional.fields | |
| componentVersion_label | additional.fields | |
| azureResourceID_label | additional.fields | |
| producer_label | additional.fields | |
| first_label | additional.fields | |
| last_label | additional.fields | |
| meta_name | additional.fields | |
| resource_version_label | additional.fields | |
| request_apiVersion | additional.fields | |
| request_kind_label | additional.fields | |
| request_type_label | additional.fields | |
| response_apiVersion | additional.fields | |
| response_kind_label | additional.fields | |
| response_type_label | additional.fields | |
| jsonPayload.message | metadata.description | Descrizione dell'evento |
| event_type | metadata.event_type | Tipo di evento |
| labels.request_id | metadata.product_log_id | Identificatore log specifico del prodotto |
| insertId | metadata.product_log_id | |
| jsonPayload.chartVersion | metadata.product_version | Versione del prodotto |
| httpRequest.protocol | network.application_protocol | Protocollo applicativo utilizzato nella connessione di rete |
| network.direction | network.direction | Direzione del traffico di rete |
| httpRequest.requestMethod | network.http.method | Metodo HTTP |
| http_method | network.http.method | |
| httpRequest.status | network.http.response_code | Codice di risposta HTTP |
| httpRequest.userAgent | network.http.user_agent | User agent HTTP |
| requestMetadata.callerSuppliedUserAgent | network.http.user_agent | |
| labels.protocol | network.ip_protocol | Protocollo IP |
| httpRequest.responseSize | network.received_bytes | Numero di byte ricevuti |
| labels.total_received_bytes | network.received_bytes | |
| httpRequest.requestSize | network.sent_bytes | Numero di byte inviati |
| labels.total_sent_bytes | network.sent_bytes | |
| jsonPayload.session | network.session_id | Identificatore sessione |
| labels.service_authentication_policy | network.tls.cipher | Suite di crittografia TLS |
| entità | entità | Entità principale coinvolta nell'evento |
| principal_hostname | principal.hostname | Nome host dell'entità |
| prin_userid | principal.user.userid | ID utente dell'entità |
| security_result | security_result | Risultato della valutazione della sicurezza |
| target | target | Entità target coinvolta nell'evento |
| target_hostname | target.hostname | Nome host della destinazione |
| resource_sub_type | target.resource.resource_subtype | Sottotipo della risorsa di destinazione |
| target_userid | target.user.userid | ID utente della destinazione |
| metadata.product_name | metadata.product_name | Nome del prodotto |
| metadata.vendor_name | metadata.vendor_name | Nome fornitore |
Log delle modifiche
Visualizza il log delle modifiche per questo parser
Hai bisogno di ulteriore assistenza? Ricevi risposte dai membri della community e dai professionisti di Google SecOps.