OAuth2-Proxy-Logs erfassen
In diesem Dokument wird beschrieben, wie Sie OAuth2 Proxy-Logs mit Google Cloud Storage V2 in Google Security Operations aufnehmen.
OAuth2 Proxy ist ein Reverse-Proxy der CNCF Sandbox, der die Authentifizierung über OAuth2-/OIDC-Anbieter (Google, GitHub, Keycloak, Azure AD und andere) ermöglicht, um Konten per E-Mail-Adresse, Domain oder Gruppe zu validieren. Es werden Authentifizierungsprotokolle (erfolgreiche/fehlgeschlagene Anmeldungen), Anfrageprotokolle (weitergeleitete HTTP-Anfragen mit Nutzeridentität) und Standardanwendungsprotokolle generiert. Da OAuth2 Proxy als Container in Kubernetes ausgeführt wird und alle Logs in stdout schreibt, wird ein Kubernetes-nativer Log-Collector (Fluentd) verwendet, um Logs zur Aufnahme in Google SecOps an einen GCS-Bucket weiterzuleiten.
Hinweis
Prüfen Sie, ob folgende Voraussetzungen erfüllt sind:
- Eine Google SecOps-Instanz
- Ein GCP-Projekt mit aktivierter Cloud Storage API
- Berechtigungen zum Erstellen und Verwalten von GCS-Buckets
- Berechtigungen zum Verwalten von IAM-Richtlinien für GCS-Buckets
- Ein laufender Kubernetes-Cluster mit bereitgestelltem OAuth2-Proxy (über Helm-Diagramm oder manuelle Bereitstellung)
kubectl-Zugriff auf den Kubernetes-Cluster mit Berechtigungen zum Erstellen von DaemonSets, ConfigMaps, Secrets und Namespaces- Ein JSON-Schlüssel für ein GCP-Dienstkonto mit der Berechtigung
storage.objects.createfür den Ziel-GCS-Bucket
Google Cloud Storage-Bucket erstellen
- Gehen Sie zur Google Cloud Console.
- Wählen Sie Ihr Projekt aus oder erstellen Sie ein neues.
- Rufen Sie im Navigationsmenü Cloud Storage > Buckets auf.
- Klicken Sie auf Bucket erstellen.
Geben Sie die folgenden Konfigurationsdetails an:
Einstellung Wert Bucket benennen Geben Sie einen global eindeutigen Namen ein, z. B. oauth2-proxy-logs-bucket.Standorttyp Wählen Sie die Option aus, die am besten zu Ihren Anforderungen passt (Region, Dual-Region, Multi-Region). Standort Wählen Sie den Speicherort aus, z. B. us-central1.Speicherklasse Standard (empfohlen für Logs, auf die häufig zugegriffen wird) Zugriffskontrolle Einheitlich (empfohlen) Schutztools Optional: Objektversionierung oder Aufbewahrungsrichtlinie aktivieren Klicken Sie auf Erstellen.
OAuth2-Proxy-Logging konfigurieren
OAuth2 Proxy schreibt drei Arten von Logs in stdout: Standardlogs, Authentifizierungslogs und Anfragelogs. Alle drei sind standardmäßig aktiviert. Damit die Logs möglichst viele sicherheitsrelevante Details enthalten, konfigurieren Sie OAuth2 Proxy mit den folgenden Logging-Flags.
Option 1: Über Helm-Diagrammwerte konfigurieren
Wenn OAuth2-Proxy mit dem offiziellen Helm-Diagramm bereitgestellt wird, fügen Sie Ihrer
values.yaml-Datei Folgendes hinzu: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}}"Wenden Sie die aktualisierten Helm-Werte an:
helm upgrade oauth2-proxy oauth2-proxy/oauth2-proxy -f values.yaml -n <your-namespace>
Option 2: Über Befehlszeilen-Flags konfigurieren
Wenn OAuth2 Proxy mit einem Kubernetes-Bereitstellungsmanifest bereitgestellt wird, fügen Sie der Containerspezifikation die folgenden Argumente hinzu:
args: - --standard-logging=true - --auth-logging=true - --request-logging=true - --silence-ping-logging=true
Option 3: Über Umgebungsvariablen konfigurieren
Legen Sie die folgenden Umgebungsvariablen für den OAuth2-Proxy-Container fest:
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"
OAuth2-Proxy-Logging überprüfen
Prüfen Sie nach dem Anwenden der Konfiguration, ob OAuth2-Proxy Logs generiert:
kubectl logs -l app=oauth2-proxy -n <your-namespace> --tail=20Die Ausgabe enthält Zeilen, die etwa so aussehen:
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
GCP-Dienstkonto für Fluentd erstellen
Für Fluentd ist ein GCP-Dienstkonto mit Schreibzugriff auf den GCS-Bucket erforderlich.
- Wechseln Sie in der GCP Console zu IAM und Verwaltung > Dienstkonten.
- Klicken Sie auf Dienstkonto erstellen.
- Geben Sie die folgenden Konfigurationsdetails an:
- Name des Dienstkontos: Geben Sie
fluentd-gcs-writerein. - Beschreibung des Dienstkontos: Geben Sie
Service account for Fluentd to write OAuth2 Proxy logs to GCSein.
- Name des Dienstkontos: Geben Sie
- Klicken Sie auf Erstellen und fortfahren.
- Gehen Sie im Bereich Diesem Dienstkonto Zugriff auf das Projekt erteilen so vor:
- Klicken Sie auf Rolle auswählen.
- Suchen Sie nach Storage Object Admin und wählen Sie die Rolle aus.
- Klicken Sie auf Weiter.
- Klicken Sie auf Fertig.
Dienstkontoschlüssel erstellen und herunterladen
- Klicken Sie in der Liste Dienstkonten auf das Dienstkonto
fluentd-gcs-writer. - Rufen Sie den Tab Schlüssel auf.
- Klicken Sie auf Schlüssel hinzufügen > Neuen Schlüssel erstellen.
- Wählen Sie JSON als Schlüsseltyp aus.
- Klicken Sie auf Erstellen.
- Speichern Sie die heruntergeladene JSON-Schlüsseldatei sicher. Diese Datei wird im nächsten Schritt verwendet.
Kubernetes-Secret für den Dienstkontoschlüssel erstellen
Erstellen Sie ein Kubernetes-Secret, das den Schlüssel des GCP-Dienstkontos im Namespace enthält, in dem Fluentd bereitgestellt wird:
kubectl create namespace logging kubectl create secret generic fluentd-gcs-key \ --from-file=service-account-key.json=<path-to-downloaded-key>.json \ -n logging
Fluentd-DaemonSet bereitstellen, um OAuth2-Proxy-Logs zu erfassen
Stellen Sie Fluentd als DaemonSet im Kubernetes-Cluster bereit, um Containerlogs von OAuth2-Proxy-Pods zu erfassen und an den GCS-Bucket weiterzuleiten.
Fluentd-ConfigMap erstellen
Erstellen Sie eine Datei mit dem Namen
fluentd-configmap.yamlund dem folgendem Inhalt: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>
Ersetzen Sie die folgenden Werte:
YOUR_GCP_PROJECT_ID: Ihre GCP-Projekt-ID (z. B.my-project-123456)oauth2-proxy-logs-bucket: Der Name des zuvor erstellten GCS-BucketsWenden Sie die ConfigMap an:
kubectl apply -f fluentd-configmap.yaml
Fluentd-DaemonSet erstellen
Erstellen Sie eine Datei mit dem Namen
fluentd-daemonset.yamlund dem folgendem Inhalt: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: {}Wenden Sie das DaemonSet an:
kubectl apply -f fluentd-daemonset.yaml
Fluentd-Bereitstellung prüfen
Prüfen Sie, ob Fluentd-Pods auf jedem Knoten ausgeführt werden:
kubectl get pods -n logging -l k8s-app=fluentd-gcsPrüfen Sie die Fluentd-Logs auf erfolgreiche GCS-Schreibvorgänge:
kubectl logs -l k8s-app=fluentd-gcs -n logging --tail=20Prüfen Sie, ob Logdateien im GCS-Bucket angezeigt werden:
- Rufen Sie in der GCP Console Cloud Storage > Buckets auf.
- Klicken Sie auf den Bucket (z. B.
oauth2-proxy-logs-bucket). - Rufen Sie den Ordner
oauth2-proxy-logs/auf. - Prüfen Sie, ob
.json-Dateien mit aktuellen Zeitstempeln vorhanden sind.
Google SecOps-Dienstkonto abrufen
Google SecOps verwendet ein eindeutiges Dienstkonto, um Daten aus Ihrem GCS-Bucket zu lesen. Sie müssen diesem Dienstkonto Zugriff auf Ihren Bucket gewähren.
E‑Mail-Adresse des Dienstkontos abrufen
- Rufen Sie die SIEM-Einstellungen > Feeds auf.
- Klicken Sie auf Neuen Feed hinzufügen.
- Klicken Sie auf Einzelnen Feed konfigurieren.
- Geben Sie im Feld Feedname einen Namen für den Feed ein, z. B.
OAuth2 Proxy Logs. - Wählen Sie Google Cloud Storage V2 als Quelltyp aus.
- Wählen Sie Kubernetes Auth Proxy als Log type (Protokolltyp) aus.
Klicken Sie auf Dienstkonto abrufen. Es wird eine eindeutige E-Mail-Adresse für das Dienstkonto angezeigt, z. B.:
chronicle-12345678@chronicle-gcp-prod.iam.gserviceaccount.comKopieren Sie diese E‑Mail-Adresse für den nächsten Schritt.
Klicken Sie auf Weiter.
Geben Sie Werte für die folgenden Eingabeparameter an:
Storage-Bucket-URL: Geben Sie den GCS-Bucket-URI mit dem Präfixpfad ein:
gs://oauth2-proxy-logs-bucket/oauth2-proxy-logs/Ersetzen Sie
oauth2-proxy-logs-bucketdurch den Namen Ihres GCS-Buckets.
Option zum Löschen der Quelle: Wählen Sie die gewünschte Option zum Löschen aus:
- Nie: Löscht nach Übertragungen nie Dateien (empfohlen für Tests).
- Übertragene Dateien löschen: Dateien werden nach der erfolgreichen Übertragung gelöscht.
Übertragene Dateien und leere Verzeichnisse löschen: Löscht Dateien und leere Verzeichnisse nach der erfolgreichen Übertragung.
Höchstalter der Datei: Dateien einbeziehen, die in den letzten Tagen geändert wurden (Standardwert: 180 Tage)
Asset-Namespace: Der Asset-Namespace
Labels für Datenaufnahme: Das Label, das auf die Ereignisse aus diesem Feed angewendet werden soll
Klicken Sie auf Weiter.
Prüfen Sie die neue Feedkonfiguration auf dem Bildschirm Abschließen und klicken Sie dann auf Senden.
Dem Google SecOps-Dienstkonto IAM-Berechtigungen gewähren
Das Google SecOps-Dienstkonto benötigt die Rolle Storage Object Viewer für Ihren GCS-Bucket.
- Rufen Sie Cloud Storage > Buckets auf.
- Klicken Sie auf den Namen Ihres Buckets (z. B.
oauth2-proxy-logs-bucket). - Wechseln Sie zum Tab Berechtigungen.
- Klicken Sie auf Zugriff erlauben.
- Geben Sie die folgenden Konfigurationsdetails an:
- Hauptkonten hinzufügen: Fügen Sie die E-Mail-Adresse des Google SecOps-Dienstkontos ein (z. B.
chronicle-12345678@chronicle-gcp-prod.iam.gserviceaccount.com). - Rollen zuweisen: Wählen Sie Storage Object Viewer aus.
- Hauptkonten hinzufügen: Fügen Sie die E-Mail-Adresse des Google SecOps-Dienstkontos ein (z. B.
- Klicken Sie auf Speichern.
OAuth2-Proxy-Log-Referenz
In der folgenden Tabelle werden die von OAuth2 Proxy generierten Logfelder und ihre sicherheitsrelevante Bedeutung beschrieben:
Authentifizierungsprotokollfelder
| Feld | Beispiel | Beschreibung |
|---|---|---|
| Kunde | 10.0.0.1 |
Client-/Remote-IP-Adresse (verwendet den X-Real-IP-Header, falls --reverse-proxy=true) |
| RequestID | 00010203-0405-4607-8809-0a0b0c0d0e0f |
Anfrage-ID aus dem X-Request-Id-Header (zufällige UUID, wenn leer) |
| Nutzername | user@example.com |
E‑Mail-Adresse oder Nutzername der Authentifizierungsanfrage |
| Zeitstempel | 2024/01/15 10:30:00 |
Datum und Uhrzeit des Authentifizierungsereignisses |
| Status | AuthSuccess |
Authentifizierungsergebnis: AuthSuccess, AuthFailure oder AuthError |
| Nachricht | Authenticated via OAuth2 |
Details zum Authentifizierungsversuch |
Anfragelogfelder
| Feld | Beispiel | Beschreibung |
|---|---|---|
| Kunde | 10.0.0.1 |
Client-/Remote-IP-Adresse |
| RequestID | 00010203-0405-4607-8809-0a0b0c0d0e0f |
Anfrage-ID |
| Nutzername | user@example.com |
E‑Mail-Adresse des authentifizierten Nutzers |
| Zeitstempel | 2024/01/15 10:30:01 |
Datum und Uhrzeit der Anfrage |
| Host | app.example.com |
Wert des Host-Headers |
| RequestMethod | GET |
HTTP-Anfragemethode |
| Upstream | 10.0.0.5:8080 |
Upstream-Server, der die Anfrage verarbeitet hat |
| RequestURI | /dashboard |
URI-Pfad der Anfrage |
| Protokoll | HTTP/1.1 |
Anfrageprotokoll |
| User-Agent | Mozilla/5.0 |
Vollständiger User-Agent-String |
| StatusCode | 200 |
HTTP-Antwort-Statuscode |
| ResponseSize | 1234 |
Größe der Antwort in Byte |
| RequestDuration | 0.005 |
Verarbeitungszeit der Anfrage in Sekunden |
UDM-Zuordnungstabelle
| Logfeld | UDM-Zuordnung | Logik |
|---|---|---|
| über | über | Informationen zum Ereignis |
| http_req_id_field | additional.fields | Zusätzliche Felder, die nicht vom Standard-UDM-Schema abgedeckt werden |
| 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 | Eine Beschreibung des Ereignisses |
| event_type | metadata.event_type | Ereignistyp |
| labels.request_id | metadata.product_log_id | Produktspezifische Log-Kennzeichnung |
| insertId | metadata.product_log_id | |
| jsonPayload.chartVersion | metadata.product_version | Produktversion |
| httpRequest.protocol | network.application_protocol | In der Netzwerkverbindung verwendetes Anwendungsprotokoll |
| network.direction | network.direction | Richtung des Netzwerkverkehrs |
| httpRequest.requestMethod | network.http.method | HTTP-Methode |
| http_method | network.http.method | |
| httpRequest.status | network.http.response_code | HTTP-Antwortcode |
| httpRequest.userAgent | network.http.user_agent | HTTP-User-Agent |
| requestMetadata.callerSuppliedUserAgent | network.http.user_agent | |
| labels.protocol | network.ip_protocol | IP-Protokoll |
| httpRequest.responseSize | network.received_bytes | Anzahl der empfangenen Byte |
| labels.total_received_bytes | network.received_bytes | |
| httpRequest.requestSize | network.sent_bytes | Anzahl der gesendeten Byte |
| labels.total_sent_bytes | network.sent_bytes | |
| jsonPayload.session | network.session_id | Sitzungs-ID |
| labels.service_authentication_policy | network.tls.cipher | TLS-Cipher Suite |
| Prinzipal | Prinzipal | Hauptkonto, das an dem Ereignis beteiligt ist |
| principal_hostname | principal.hostname | Hostname des Prinzipals |
| prin_userid | principal.user.userid | Nutzer-ID des Prinzipal |
| security_result | security_result | Ergebnis der Sicherheitsbewertung |
| Ziel | Ziel | Zielentität, die am Ereignis beteiligt ist |
| target_hostname | target.hostname | Hostname des Ziels |
| resource_sub_type | target.resource.resource_subtype | Untertyp der Zielressource |
| target_userid | target.user.userid | Nutzer-ID des Ziels |
| metadata.product_name | metadata.product_name | Produktname |
| metadata.vendor_name | metadata.vendor_name | Anbietername |
Änderungsprotokoll
Änderungsprotokoll für diesen Parser ansehen
Benötigen Sie weitere Hilfe? Antworten von Community-Mitgliedern und Google SecOps-Experten erhalten