Keycloak-Logs erfassen
In diesem Dokument wird beschrieben, wie Sie Keycloak so konfigurieren, dass Logs mithilfe von Webhooks an Google Security Operations gesendet werden.
Keycloak ist eine Open-Source-Lösung für Identity and Access Management (IAM), die Funktionen für die Einmalanmeldung (SSO), die Nutzerföderation, das Identitäts-Brokering und die Anmeldung über soziale Netzwerke bietet. Es unterstützt die Protokolle OpenID Connect, OAuth 2.0 und SAML 2.0 und erfasst Nutzerereignisse (Anmeldung, Abmeldung, Registrierung, Passwortänderungen) und Administratorereignisse (Vorgänge zur Verwaltung von Nutzern, Clients, Realms und Rollen) für Sicherheitsprüfungen.
Hinweis
Folgende Voraussetzungen müssen erfüllt sein:
- Eine Google SecOps-Instanz
- Eine laufende Keycloak-Instanz (Version 20 oder höher empfohlen)
- Administratorzugriff auf die Keycloak Admin-Konsole
- Zugriff auf das Keycloak-Serverdateisystem oder den Container zum Bereitstellen von Erweiterungen
- Zugriff auf die Google Cloud Console (zum Erstellen von API-Schlüsseln)
Webhook-Feed in Google SecOps erstellen
Feed erstellen
- Rufen Sie die SIEM-Einstellungen > Feeds auf.
- Klicken Sie auf Neuen Feed hinzufügen.
- Klicken Sie auf der nächsten Seite auf Einen einzelnen Feed konfigurieren.
- Geben Sie im Feld Feedname einen Namen für den Feed ein, z. B.
Keycloak Events. - Wählen Sie Webhook als Quelltyp aus.
- Wählen Sie Keycloak als Protokolltyp aus.
- Klicken Sie auf Weiter.
- Geben Sie Werte für die folgenden Eingabeparameter an:
- Trennzeichen für Aufteilung (optional): Geben Sie
\nein, um mehrzeilige Ereignisse aufzuteilen. Da jeder Webhook-POST ein einzelnes Ereignis enthält, kann dieses Feld leer gelassen werden. - Asset-Namespace: Der Asset-Namespace
- Labels für Datenaufnahme: Das Label, das auf die Ereignisse aus diesem Feed angewendet werden soll
- Trennzeichen für Aufteilung (optional): Geben Sie
- Klicken Sie auf Weiter.
- Prüfen Sie die neue Feedkonfiguration auf dem Bildschirm Abschließen und klicken Sie dann auf Senden.
Secret-Schlüssel generieren und speichern
Nachdem Sie den Feed erstellt haben, müssen Sie einen Secret-Schlüssel für die Authentifizierung generieren:
- Klicken Sie auf der Feed-Detailseite auf Geheimen Schlüssel generieren.
- Ein Dialogfeld mit dem geheimen Schlüssel wird angezeigt.
- Kopieren und speichern Sie den geheimen Schlüssel sicher.
Wichtig: Der geheime Schlüssel wird nur einmal angezeigt und kann später nicht mehr abgerufen werden. Wenn Sie ihn verlieren, müssen Sie einen neuen geheimen Schlüssel generieren.
Feed-Endpunkt-URL abrufen
- Rufen Sie den Tab Details des Feeds auf.
- Kopieren Sie im Bereich Endpunktinformationen die Feed-Endpunkt-URL.
Das URL-Format lautet:
https://malachiteingestion-pa.googleapis.com/v2/unstructuredlogentries:batchCreateoder
https://<REGION>-malachiteingestion-pa.googleapis.com/v2/unstructuredlogentries:batchCreateSpeichern Sie diese URL für die nächsten Schritte.
Klicken Sie auf Fertig.
Google Cloud API-Schlüssel erstellen
Für die Authentifizierung in Chronicle ist ein API-Schlüssel erforderlich. Erstellen Sie in der Google Cloud Console einen eingeschränkten API-Schlüssel.
API-Schlüssel erstellen
- Rufen Sie die Seite „Anmeldedaten“ in der Google Cloud Console auf.
- Wählen Sie Ihr Projekt aus (das Projekt, das mit Ihrer Chronicle-Instanz verknüpft ist).
- Klicken Sie auf Anmeldedaten erstellen > API-Schlüssel.
- Ein API-Schlüssel wird erstellt und in einem Dialogfeld angezeigt.
- Klicken Sie auf API-Schlüssel bearbeiten, um den Schlüssel einzuschränken.
API-Schlüssel einschränken
- Auf der Seite mit den API-Schlüssel-Einstellungen:
- Name: Geben Sie einen aussagekräftigen Namen ein, z. B.
Chronicle Webhook API Key.
- Name: Geben Sie einen aussagekräftigen Namen ein, z. B.
- Gehen Sie unter API-Einschränkungen so vor:
- Wählen Sie Schlüssel einschränken aus.
- Suchen Sie im Drop-down-Menü APIs auswählen nach Google SecOps API (oder Chronicle API) und wählen Sie die API aus.
- Klicken Sie auf Speichern.
- Kopieren Sie den API-Schlüsselwert aus dem Feld API-Schlüssel oben auf der Seite.
- Speichern Sie den API-Schlüssel sicher.
Ereignisspeicher in Keycloak aktivieren
Bevor Sie die Webhook-Erweiterung konfigurieren, aktivieren Sie die Ereignisspeicherung in Keycloak, damit Ereignisse generiert und zur Weiterleitung verfügbar sind.
Nutzerereignisse aktivieren
- Melden Sie sich in der Keycloak Admin-Konsole an.
- Wählen Sie links oben im Drop-down-Menü den Bereich aus, den Sie im Blick behalten möchten.
- Rufen Sie die Realm-Einstellungen > Ereignisse auf.
- Wählen Sie den Untertab Einstellungen für Nutzerereignisse aus.
- Aktivieren Sie den Ein/Aus-Schalter Termine speichern.
- Legen Sie den Ablaufzeitraum fest (empfohlenes Minimum: 7 Tage).
- Klicken Sie auf Speichern.
Administratorereignisse aktivieren
- Wählen Sie auf demselben Tab Ereignisse den Untertab Einstellungen für Administratorereignisse aus.
- Aktivieren Sie den Ein/Aus-Schalter Termine speichern.
- Aktivieren Sie die Ein/Aus-Schaltfläche Darstellung einbeziehen, um alle Details der geänderten Objekte zu erfassen.
- Legen Sie den Ablaufzeitraum fest (empfohlenes Minimum: 7 Tage).
- Klicken Sie auf Speichern.
Webhook-Event-Listener-Erweiterung installieren
Keycloak enthält keinen nativen Webhook-Event-Listener. Installieren Sie die keycloak-events-Erweiterung aus Phase 2 (p2-inc), um die Webhook-Übermittlung zu aktivieren.
Erweiterung herunterladen und bereitstellen
Laden Sie die JAR-Datei der neuesten Version von der Seite „keycloak-events releases“ auf Maven Central herunter oder erstellen Sie sie aus dem Quellcode:
git clone https://github.com/p2-inc/keycloak-events.git cd keycloak-events mvn clean installKopieren Sie die resultierende Fat-JAR-Datei in das Keycloak-Verzeichnis
providers:cp target/keycloak-events-*.jar /opt/keycloak/providers/Erstellen Sie Keycloak neu und starten Sie es neu:
/opt/keycloak/bin/kc.sh build /opt/keycloak/bin/kc.sh start
Webhook-Event-Listener aktivieren
- Melden Sie sich in der Keycloak Admin-Konsole an.
- Wählen Sie im Drop-down-Menü für Realms das Ziel-Realm aus.
- Rufen Sie die Realm-Einstellungen > Ereignisse auf.
- Wählen Sie im Drop-down-Menü Event-Listener die Option ext-event-webhook aus.
- Klicken Sie auf Speichern.
Keycloak-Webhook konfigurieren
Webhook-URL erstellen
Kombinieren Sie die Chronicle-Endpunkt-URL und den API-Schlüssel:
<ENDPOINT_URL>?key=<API_KEY>Beispiel:
https://malachiteingestion-pa.googleapis.com/v2/unstructuredlogentries:batchCreate?key=AIzaSyD...
Webhook-Abo über die Keycloak REST API erstellen
Die Erweiterung keycloak-events bietet REST-Endpunkte zum Verwalten von Webhook-Abos. Verwenden Sie die Keycloak Admin REST API, um einen Webhook zu erstellen.
Schritt 1: Zugriffstoken abrufen
Fordern Sie mit einem Administratorkonto ein Zugriffstoken von Keycloak an:
TOKEN=$(curl -sS -X POST "https://<KEYCLOAK_HOST>/realms/master/protocol/openid-connect/token" \ -H "Content-Type: application/x-www-form-urlencoded" \ --data-urlencode "grant_type=password" \ --data-urlencode "client_id=admin-cli" \ --data-urlencode "username=<ADMIN_USERNAME>" \ --data-urlencode "password=<ADMIN_PASSWORD>" \ | sed -n 's/.*"access_token":"\([^"]*\)".*/\1/p')
Ersetzen Sie Folgendes:
<KEYCLOAK_HOST>: Der Hostname und Port Ihres Keycloak-Servers, z. B.keycloak.example.com:8443<ADMIN_USERNAME>: Ihr Keycloak-Administratornutzername<ADMIN_PASSWORD>: Ihr Keycloak-Administratorpasswort
Schritt 2: Webhook erstellen
Senden Sie eine POST-Anfrage, um das Webhook-Abo für den Zielbereich zu erstellen:
curl -sS -X POST "https://<KEYCLOAK_HOST>/realms/<REALM_NAME>/webhooks" \ -H "Authorization: Bearer ${TOKEN}" \ -H "Content-Type: application/json" \ -d '{ "enabled": "true", "url": "<ENDPOINT_URL>?key=<API_KEY>&secret=<SECRET_KEY>", "secret": "<WEBHOOK_HMAC_SECRET>", "eventTypes": ["*"] }'
Ersetzen Sie Folgendes:
<KEYCLOAK_HOST>: Der Hostname Ihres Keycloak-Servers<REALM_NAME>: Der Name des zu überwachenden Bereichs, z. B.masterodermy-realm<ENDPOINT_URL>: Die zuvor kopierte Chronicle-Feed-Endpunkt-URL<API_KEY>: Der zuvor erstellte Google Cloud API-Schlüssel<SECRET_KEY>: Der zuvor generierte geheime Schlüssel für Chronicle-Webhooks<WEBHOOK_HMAC_SECRET>: Ein beliebiger geheimer String für die HMAC-Signierung von Webhook-Nutzlasten (z. B.mySecretKey123)
Schritt 3: Webhook bestätigen
Prüfen Sie, ob der Webhook erstellt wurde, indem Sie alle Webhooks für den Bereich auflisten:
curl -sS -X GET "https://<KEYCLOAK_HOST>/realms/<REALM_NAME>/webhooks" \ -H "Authorization: Bearer ${TOKEN}" \ -H "Accept: application/json"
Die Antwort gibt eine Liste von Webhook-Objekten zurück. Prüfen Sie, ob Ihr Webhook mit "enabled": "true" und der richtigen URL angezeigt wird.
Webhook-Ereignistypen
Im Feld eventTypes wird ein Array von Ausdrücken akzeptiert, mit denen gefiltert wird, welche Ereignisse gesendet werden:
*– Alle Ereignisse senden (empfohlen für die SIEM-Integration)access.*: Alle Zugriffsereignisse sendenadmin.*: Alle Administratorereignisse sendenadmin.USER-*– Alle Administratorereignisse im Zusammenhang mit Nutzern sendenadmin-USER-CREATE: Nur Administratorereignisse zur Nutzererstellung senden
Format der Webhook-Nutzlast
Der Webhook sendet Ereignisse als HTTP-POST-Anfragen mit JSON-Nutzdaten. Beispiel für die Nutzlast eines Nutzerereignisses:
{ "id": "987865-1a2b-3c4d-9876-654321abc", "time": 1767799710612, "type": "LOGIN", "realmId": "12345abcde-1a2b-4d3c-9876-abcd456", "clientId": "account-console", "userId": "abcd456-1234-5678-abc9-987gfed654", "sessionId": "efghij-9876-abcd-456-11223344", "ipAddress": "203.0.113.45", "details": { "auth_method": "openid-connect", "auth_type": "code", "redirect_uri": "https://app.example.com/callback", "consent": "no_consent_required", "username": "jdoe" } }
Wiederholungsverhalten bei Webhooks
Die Erweiterung verwendet für Wiederholungsversuche einen automatischen exponentiellen Backoff, wenn eine Antwort ohne 2xx empfangen wird:
| Parameter | Standardwert | Beschreibung |
|---|---|---|
| backoffInitialInterval | 500 ms | Erstes Wiederholungsintervall |
| backoffMaxElapsedTime | 900.000 ms (15 Minuten) | Maximale Gesamtzeit für Wiederholungsversuche |
| backoffMaxInterval | 180.000 ms (3 Minuten) | Maximales Intervall zwischen Wiederholungsversuchen |
| backoffMultiplier | 5 | Multiplikator für jedes Wiederholungsintervall |
| backoffRandomizationFactor | 0,5 | Zufallsfaktor für Jitter |
Referenz zu Authentifizierungsmethoden
Chronicle-Webhook-Feeds unterstützen mehrere Authentifizierungsmethoden. Wählen Sie die Methode aus, die von Ihrem Anbieter unterstützt wird.
Methode 1: Benutzerdefinierte Header (empfohlen)
Wenn Ihr Anbieter benutzerdefinierte HTTP-Header unterstützt, sollten Sie diese Methode für eine bessere Sicherheit verwenden.
Anfrageformat:
POST <ENDPOINT_URL> HTTP/1.1 Content-Type: application/json x-goog-chronicle-auth: <API_KEY> x-chronicle-auth: <SECRET_KEY> { "event": "data", "timestamp": "2025-01-15T10:30:00Z" }
Vorteile:
- API-Schlüssel und Secret nicht in der URL sichtbar
- Sicherer (Header werden nicht in Webserver-Zugriffslogs protokolliert)
- Bevorzugte Methode, wenn der Anbieter sie unterstützt
Methode 2: Abfrageparameter
Wenn Ihr Anbieter keine benutzerdefinierten Headern unterstützt, hängen Sie die Anmeldedaten an die URL an.
URL-Format:
<ENDPOINT_URL>?key=<API_KEY>&secret=<SECRET_KEY>Beispiel:
https://malachiteingestion-pa.googleapis.com/v2/unstructuredlogentries:batchCreate?key=AIzaSyD...&secret=abcd1234...Anfrageformat:
POST <ENDPOINT_URL>?key=<API_KEY>&secret=<SECRET_KEY> HTTP/1.1 Content-Type: application/json { "event": "data", "timestamp": "2025-01-15T10:30:00Z" }
Nachteile:
- Anmeldedaten in der URL sichtbar
- Möglicherweise in Webserver-Zugriffsprotokollen protokolliert
- Weniger sicher als Header
Methode 3: Hybrid (URL + Header)
Bei einigen Konfigurationen wird der API-Schlüssel in der URL und der geheime Schlüssel im Header verwendet.
Anfrageformat:
POST <ENDPOINT_URL>?key=<API_KEY> HTTP/1.1 Content-Type: application/json x-chronicle-auth: <SECRET_KEY> { "event": "data", "timestamp": "2025-01-15T10:30:00Z" }
Namen von Authentifizierungsheadern
Chronicle akzeptiert die folgenden Headernamen für die Authentifizierung:
Für API-Schlüssel:
x-goog-chronicle-auth(empfohlen)X-Goog-Chronicle-Auth(Groß-/Kleinschreibung wird nicht berücksichtigt)
Geheimer Schlüssel:
x-chronicle-auth(empfohlen)X-Chronicle-Auth(Groß-/Kleinschreibung wird nicht berücksichtigt)
Webhook-Limits und Best Practices
Anfragelimits
| Limit | Wert |
|---|---|
| Maximale Anfragengröße | 4 MB |
| Maximale Anzahl von Abfragen pro Sekunde | 15.000 |
| Zeitlimit für Anfragen | 30 Sekunden |
| Wiederholungsverhalten | Automatisch mit exponentiellem Backoff |
UDM-Zuordnungstabelle
| Logfeld | UDM-Zuordnung | Logik |
|---|---|---|
| payload.client_id | additional.fields | Zusammengeführt mit Feldern, die aus „payload.client_id“ und „payload.realm_id“ erstellt wurden |
| payload.realm_id | additional.fields | |
| source_timestamp | metadata.event_timestamp | Gepasst mit Datumsfilter mit den Mustern ISO8601 und yyyy-MM-dd'T'HH:mm:ss.SSSZ |
| payload.ip_address | metadata.event_type | Auf „STATUS_UPDATE“ festgelegt, wenn „payload.ip_address“ nicht leer ist, andernfalls „USER_UNCATEGORIZED“, wenn „uuid“ nicht leer ist, andernfalls „GENERIC_EVENT“ |
| uuid | metadata.event_type | |
| payload.type | metadata.product_event_type | Wert direkt kopiert |
| payload.session_id | network.session_id | Wert direkt kopiert |
| payload.ip_address | principal.ip | Wert direkt kopiert |
| source_metadata.schema | principal.resource.attribute.labels | Zusammengeführt mit Labels, die aus source_metadata.schema, source_metadata.table, source_metadata.is_deleted (in String konvertiert), source_metadata.change_type, source_metadata.tx_id, source_metadata.lsn erstellt wurden |
| source_metadata.table | principal.resource.attribute.labels | |
| source_metadata.is_deleted | principal.resource.attribute.labels | |
| source_metadata.change_type | principal.resource.attribute.labels | |
| source_metadata.tx_id | principal.resource.attribute.labels | |
| source_metadata.lsn | principal.resource.attribute.labels | |
| uuid | principal.user.userid | Wert direkt kopiert |
| Objekt | security_result.detection_fields | Mit Labels zusammengeführt, die aus „object“, „read_method“ und „payload.id“ erstellt wurden |
| read_method | security_result.detection_fields | |
| payload.id | security_result.detection_fields | |
| redirect_uri | target.url | Wert direkt kopiert |
| Nutzername | target.user.userid | Wert direkt kopiert |
| metadata.product_name | metadata.product_name | Auf „KEYCLOAK“ festgelegt |
| metadata.vendor_name | metadata.vendor_name | Auf „KEYCLOAK“ festgelegt |
username" from "details_json |
target.user.userid |
Aus dem Änderungsprotokoll zugeordnet |
redirect_uri" from "details_json |
target.url |
Aus dem Änderungsprotokoll zugeordnet |
realm_id" and "client_id |
additional.fields |
Aus dem Änderungsprotokoll zugeordnet |
Änderungsprotokoll
Änderungsprotokoll für diesen Parser ansehen
Benötigen Sie weitere Hilfe? Antworten von Community-Mitgliedern und Google SecOps-Experten erhalten