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, Domain oder Gruppe zu validieren. Es werden Authentifizierungsprotokolle (Anmeldung erfolgreich/fehlgeschlagen), 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 Standort aus, z. B. us-central1.Speicherklasse Standard (empfohlen für Logs, auf die häufig zugegriffen wird) Zugriffskontrolle Einheitlich (empfohlen) Schutzmaßnahmen Optional: Objektversionsverwaltung 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-Chart bereitgestellt wird, fügen Sie der Datei
values.yamlFolgendes 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 prüfen
Prüfen Sie nach dem Anwenden der Konfiguration, ob OAuth2-Proxy Logs erstellt:
kubectl logs -l app=oauth2-proxy -n <your-namespace> --tail=20Die Ausgabe enthält Zeilen, die in 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 & 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.
- Im Abschnitt Diesem Dienstkonto Zugriff auf das Projekt erteilen:
- Klicken Sie auf Rolle auswählen.
- Suchen Sie nach Storage-Objekt-Administrator 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 an einem sicheren Ort. Diese Datei wird im nächsten Schritt verwendet.
Kubernetes-Secret für den Dienstkontoschlüssel erstellen
Erstellen Sie ein Kubernetes-Secret, das den GCP-Dienstkontoschlüssel 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-Deployment 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 Logtyp 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 Löschoption aus:
- Nie: Es werden nach Übertragungen nie Dateien gelöscht (empfohlen für Tests).
- Übertragene Dateien löschen: Dateien werden nach der erfolgreichen Übertragung gelöscht.
Übertragene Dateien und leere Verzeichnisse löschen: Dateien und leere Verzeichnisse werden nach der erfolgreichen Übertragung gelöscht.
Höchstalter für Dateien: Dateien einschließen, die in den letzten Tagen geändert wurden (Standard ist 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-Objekt-Betrachter 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-Objekt-Betrachter 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:
Felder für Authentifizierungslogs
| 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-Antwortstatuscode |
| ResponseSize | 1234 |
Antwortgröße 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 | Hauptentität, die an der Veranstaltung 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 an dem 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