PingIDM-Protokolle (ehemals ForgeRock OpenIDM) erfassen

Parserversion:4.0

Unterstützt in:

In diesem Dokument wird beschrieben, wie Sie PingIDM-Logs (früher ForgeRock OpenIDM) mit Google Cloud Storage V2 in Google Security Operations aufnehmen.

PingIDM ist eine Plattform zur Identitätsverwaltung, die Nutzerbereitstellung, Synchronisierung, Passwortverwaltung und Zugriffssteuerung bietet. Es werden Identitätslebenszyklus-Ereignisse, Authentifizierungsversuche, Abgleichsvorgänge und Konfigurationsänderungen in Audit-Logs protokolliert, auf die über REST zugegriffen werden kann.

Hinweis

Folgende Voraussetzungen müssen erfüllt sein:

  • Eine Google SecOps-Instanz.
  • Ein GCP-Projekt mit aktivierter Cloud Storage API.
  • Berechtigungen zum Erstellen und Verwalten von GCS-Buckets und IAM-Richtlinien.
  • Berechtigungen zum Erstellen von Cloud Run-Diensten, Pub/Sub-Themen und Cloud Scheduler-Jobs.
  • Privilegierter Zugriff auf eine ForgeRock OpenIDM- oder PingIDM-Instanz mit Administratoranmeldedaten.

Google Cloud Storage-Bucket erstellen

  1. Gehen Sie zur Google Cloud Console.
  2. Wählen Sie Ihr Projekt aus oder erstellen Sie ein neues.
  3. Rufen Sie im Navigationsmenü Cloud Storage > Buckets auf.
  4. Klicken Sie auf Bucket erstellen.
  5. Geben Sie die folgenden Konfigurationsdetails an:

    Einstellung Wert
    Bucket benennen Geben Sie einen global eindeutigen Namen ein, z. B. forgerock-openidm-audit-logs.
    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
  6. Klicken Sie auf Erstellen.

ForgeRock OpenIDM-Anmeldedaten erfassen

ForgeRock OpenIDM-Basis-URL abrufen

  1. Melden Sie sich in Ihrer ForgeRock OpenIDM- oder PingIDM-Instanz an.
  2. Notieren Sie sich die Basis-URL aus der Adressleiste des Browsers.
    • Format: https://openidm.example.com
    • Fügen Sie keine nachgestellten Schrägstriche oder Pfade wie /admin ein.

Administratoranmeldedaten abrufen

  1. Rufen Sie Administratoranmeldedaten für Ihre ForgeRock OpenIDM-Instanz ab.
  2. Folgendes wird benötigt:
    • Nutzername: Administratornutzername (z.B. openidm-admin)
    • Passwort: Administratorpasswort

Berechtigungen prüfen

  1. Melden Sie sich in ForgeRock OpenIDM an.
  2. Gehen Sie zu Konfigurieren > Systemeinstellungen > Prüfung.
  3. Wenn Sie die Audit-Konfiguration und die Themen sehen können, haben Sie die erforderlichen Berechtigungen.
  4. Wenn Sie diese Option nicht sehen, bitten Sie Ihren Administrator, Ihnen Leseberechtigungen für den Audit-Log zu erteilen.

API-Zugriff testen

  • Testen Sie Ihre Anmeldedaten, bevor Sie mit der Integration fortfahren:

    # Replace with your actual credentials
    OPENIDM_BASE_URL="[https://openidm.example.com](https://openidm.example.com)"
    OPENIDM_USERNAME="openidm-admin"
    OPENIDM_PASSWORD="your-admin-password"
    
    # Test API access to authentication audit topic
    curl -v \
        -H "X-OpenIDM-Username: ${OPENIDM_USERNAME}" \
        -H "X-OpenIDM-Password: ${OPENIDM_PASSWORD}" \
        -H "Accept-API-Version: resource=1.0" \
        -H "Accept: application/json" \
        "${OPENIDM_BASE_URL}/openidm/audit/authentication?_queryFilter=true&_pageSize=1"
    

Erwartete Antwort: HTTP 200 mit JSON-Datei, die Prüfereignisse enthält.

Dienstkonto für Cloud Run-Funktion erstellen

Für die Cloud Run-Funktion ist ein Dienstkonto mit Berechtigungen zum Schreiben in den GCS-Bucket und zum Aufrufen durch Pub/Sub erforderlich.

Dienstkonto erstellen

  1. Wechseln Sie in der GCP Console zu IAM und Verwaltung > Dienstkonten.
  2. Klicken Sie auf Dienstkonto erstellen.
  3. Geben Sie die folgenden Konfigurationsdetails an:
    • Name des Dienstkontos: forgerock-openidm-collector-sa
    • Beschreibung des Dienstkontos: Service account for Cloud Run function to collect ForgeRock OpenIDM logs
  4. Klicken Sie auf Erstellen und fortfahren.
  5. Fügen Sie im Abschnitt Diesem Dienstkonto Zugriff auf das Projekt erteilen die folgenden Rollen hinzu:
    1. Storage-Objekt-Administrator: Zum Schreiben von Logs in den GCS-Bucket und zum Verwalten von Statusdateien.
    2. Cloud Run Invoker: Damit Pub/Sub die Funktion aufrufen kann.
    3. Cloud Functions Invoker: Zum Zulassen des Funktionsaufrufs.
  6. Klicken Sie auf Weiter und dann auf Fertig.

IAM-Berechtigungen für GCS-Bucket erteilen

  1. Rufen Sie Cloud Storage > Buckets auf.
  2. Klicken Sie auf den Namen Ihres Buckets (z.B. forgerock-openidm-audit-logs).
  3. Wechseln Sie zum Tab Berechtigungen.
  4. Klicken Sie auf Zugriff erlauben.
  5. Geben Sie die folgenden Konfigurationsdetails an:
    • Hauptkonten hinzufügen: Geben Sie die E-Mail-Adresse des Dienstkontos ein (z.B. forgerock-openidm-collector-sa@PROJECT_ID.iam.gserviceaccount.com).
    • Rollen zuweisen: Wählen Sie Storage Object Admin aus.
  6. Klicken Sie auf Speichern.

Pub/Sub-Thema erstellen

  1. Rufen Sie in der GCP Console Pub/Sub > Themen auf.
  2. Klicken Sie auf Thema erstellen.
  3. Geben Sie die folgenden Konfigurationsdetails an:
    • Themen-ID: forgerock-openidm-trigger
    • Übernehmen Sie die anderen Einstellungen.
  4. Klicken Sie auf Erstellen.

Cloud Run-Funktion zum Erfassen von Logs erstellen

  1. Rufen Sie in der GCP Console Cloud Run auf.
  2. Klicken Sie auf Dienst erstellen.
  3. Wählen Sie Funktion aus, um eine Funktion mit einem Inline-Editor zu erstellen.
  4. Geben Sie im Abschnitt Konfigurieren die folgenden Konfigurationsdetails an:

    Einstellung Wert
    Dienstname forgerock-openidm-collector
    Region Wählen Sie die Region aus, die Ihrem GCS-Bucket entspricht (z. B. us-central1).
    Laufzeit Wählen Sie Python 3.12 oder höher aus.
  5. Im Abschnitt Trigger:

    1. Klicken Sie auf + Trigger hinzufügen.
    2. Wählen Sie Cloud Pub/Sub aus.
    3. Wählen Sie unter Cloud Pub/Sub-Thema auswählen die Option forgerock-openidm-trigger aus.
    4. Klicken Sie auf Speichern.
  6. Im Abschnitt Authentifizierung:

    1. Wählen Sie Authentifizierung erforderlich aus.
    2. Weitere Informationen finden Sie unter Identity and Access Management (IAM).
  7. Scrollen Sie nach unten und maximieren Sie Container, Netzwerk, Sicherheit.

  8. Rufen Sie den Tab Sicherheit auf:

    • Dienstkonto: Wählen Sie forgerock-openidm-collector-sa aus.
  9. Rufen Sie den Tab Container auf:

    1. Klicken Sie auf Variablen und Secrets.
    2. Klicken Sie für jede Umgebungsvariable auf + Variable hinzufügen:
    Variablenname Beispielwert Beschreibung
    GCS_BUCKET forgerock-openidm-audit-logs Name des GCS-Buckets
    GCS_PREFIX openidm Präfix für Logdateien
    STATE_KEY openidm/state.json Pfad der Statusdatei
    OPENIDM_BASE_URL https://openidm.example.com OpenIDM-Basis-URL
    OPENIDM_USERNAME openidm-admin OpenIDM-Administratornutzername
    OPENIDM_PASSWORD your-admin-password OpenIDM-Administratorpasswort
    AUDIT_TOPICS access,activity,authentication,config,sync Kommagetrennte Themen
    PAGE_SIZE 100 Einträge pro Seite
    MAX_PAGES 50 Maximale Anzahl von Seiten pro Thema
  10. Im Abschnitt Anfragen:

    • Zeitüberschreitung für Anfrage: 600 Sekunden.
  11. Gehen Sie zum Tab Einstellungen:

    • Ressourcen: 512 MiB Arbeitsspeicher, 1 CPU.
  12. Klicken Sie auf Erstellen. Nachdem der Dienst erstellt wurde, wird der Inline-Code-Editor geöffnet.

Funktionscode hinzufügen

  1. Geben Sie main in das Feld Einstiegspunkt ein.
  2. Erstellen Sie im Editor zwei Dateien:

    • main.py:
    import functions_framework
    from google.cloud import storage
    import json
    import os
    import urllib3
    from datetime import datetime, timezone
    
    # Initialize HTTP client with timeouts
    http = urllib3.PoolManager(
        timeout=urllib3.Timeout(connect=5.0, read=30.0),
        retries=False,
    )
    
    # Initialize Storage client
    storage_client = storage.Client()
    
    # Environment variables
    GCS_BUCKET = os.environ.get('GCS_BUCKET')
    GCS_PREFIX = os.environ.get('GCS_PREFIX', 'openidm')
    STATE_KEY = os.environ.get('STATE_KEY', 'openidm/state.json')
    OPENIDM_BASE_URL = os.environ.get('OPENIDM_BASE_URL')
    OPENIDM_USERNAME = os.environ.get('OPENIDM_USERNAME')
    OPENIDM_PASSWORD = os.environ.get('OPENIDM_PASSWORD')
    AUDIT_TOPICS = os.environ.get('AUDIT_TOPICS', 'access,activity,authentication,config,sync').split(',')
    PAGE_SIZE = int(os.environ.get('PAGE_SIZE', '100'))
    MAX_PAGES = int(os.environ.get('MAX_PAGES', '50'))
    
    @functions_framework.cloud_event
    def main(cloud_event):
        """
        Cloud Run function triggered by Pub/Sub to fetch ForgeRock OpenIDM logs and write to GCS.
        """
        if not all([GCS_BUCKET, OPENIDM_BASE_URL, OPENIDM_USERNAME, OPENIDM_PASSWORD]):
            print('Error: Missing required environment variables')
            return
    
        try:
            bucket = storage_client.bucket(GCS_BUCKET)
            state = load_state(bucket, STATE_KEY)
    
            all_events = []
            for topic in AUDIT_TOPICS:
                topic = topic.strip()
                print(f"Fetching audit logs for topic: {topic}")
                events = fetch_audit_logs(topic, state.get(topic, {}))
                all_events.extend(events)
    
                if events:
                    latest_timestamp = max(e.get('timestamp', '') for e in events)
                    state[topic] = {
                        'last_timestamp': latest_timestamp,
                        'last_run': datetime.now(timezone.utc).isoformat(),
                        'events_count': len(events)
                    }
    
            if all_events:
                write_to_gcs(bucket, all_events)
                save_state(bucket, STATE_KEY, state)
                print(f"Successfully processed {len(all_events)} audit events")
            else:
                print("No new audit events to process")
    
        except Exception as e:
            print(f'Error processing logs: {str(e)}')
            raise
    
    def load_state(bucket, key):
        try:
            blob = bucket.blob(key)
            if blob.exists():
                return json.loads(blob.download_as_text())
        except Exception as e:
            print(f"Warning: Could not load state: {e}")
        return {}
    
    def save_state(bucket, key, state):
        try:
            blob = bucket.blob(key)
            blob.upload_from_string(json.dumps(state, indent=2), content_type='application/json')
        except Exception as e:
            print(f"Warning: Could not save state: {e}")
    
    def fetch_audit_logs(topic, topic_state):
        base_url = OPENIDM_BASE_URL.rstrip('/')
        all_events = []
        last_timestamp = topic_state.get('last_timestamp')
        query_filter = 'true' if not last_timestamp else f'timestamp gt "{last_timestamp}"'
        page_offset = 0
        page_count = 0
    
        while page_count < MAX_PAGES:
            try:
                url = f"{base_url}/openidm/audit/{topic}"
                params = {
                    '_queryFilter': query_filter,
                    '_pageSize': str(PAGE_SIZE),
                    '_pagedResultsOffset': str(page_offset),
                    '_sortKeys': 'timestamp'
                }
    
                headers = {
                    'X-OpenIDM-Username': OPENIDM_USERNAME,
                    'X-OpenIDM-Password': OPENIDM_PASSWORD,
                    'Accept-API-Version': 'resource=1.0',
                    'Accept': 'application/json'
                }
    
                response = http.request('GET', url, fields=params, headers=headers)
                if response.status != 200:
                    print(f"API error for topic {topic}: {response.status}")
                    break
    
                data = json.loads(response.data.decode('utf-8'))
                events = data.get('result', [])
                if not events:
                    break
    
                all_events.extend(events)
                page_offset += PAGE_SIZE
                page_count += 1
                if len(events) < PAGE_SIZE:
                    break
            except Exception as e:
                print(f"Error for topic {topic}: {str(e)}")
                break
        return all_events
    
    def write_to_gcs(bucket, events):
        timestamp = datetime.now(timezone.utc).strftime('%Y%m%d_%H%M%S')
        filename = f"{GCS_PREFIX}/openidm_audit_{timestamp}.json"
        ndjson_content = '\n'.join([json.dumps(event) for event in events])
        bucket.blob(filename).upload_from_string(ndjson_content, content_type='application/x-ndjson')
    
    • requirements.txt:
    functions-framework==3.*
    google-cloud-storage==2.*
    urllib3>=2.0.0
    
  3. Klicken Sie auf Bereitstellen. Die Bereitstellung dauert 2–3 Minuten.

Cloud Scheduler-Job erstellen

  1. Rufen Sie in der GCP Console Cloud Scheduler auf.
  2. Klicken Sie auf Job erstellen.
  3. Geben Sie die folgenden Konfigurationsdetails an:

    Einstellung Wert
    Name forgerock-openidm-collector-hourly
    Region Dieselbe Region wie die Cloud Run-Funktion auswählen
    Frequenz 0 * * * * (jede Stunde)
    Zeitzone Zeitzone auswählen (UTC empfohlen)
    Zieltyp Pub/Sub
    Thema forgerock-openidm-trigger
    Inhalt der Nachricht {}
  4. Klicken Sie auf Erstellen.

Optionen für die Häufigkeit des Zeitplans

Häufigkeit Cron-Ausdruck Anwendungsfall
Alle 5 Minuten */5 * * * * Hohes Volumen, niedrige Latenz
Stündlich 0 * * * * Standard (empfohlen)
Täglich 0 0 * * * Batch-Sammlung

Integration testen

  1. Klicken Sie in Cloud Scheduler für Ihren Job auf Ausführung erzwingen.
  2. Prüfen Sie den Lauf in den Cloud Run-Logs. Suchen Sie nach: Successfully processed X audit events.
  3. Prüfen Sie, ob in Ihrem Cloud Storage-Bucket im Ordner openidm/ eine neue Datei json vorhanden ist.

Google SecOps-Dienstkonto abrufen

Feed in Google SecOps konfigurieren

  1. Rufen Sie die SIEM-Einstellungen > Feeds auf.
  2. Klicken Sie auf Neuen Feed hinzufügen > Einzelnen Feed konfigurieren.
  3. Feed name: ForgeRock OpenIDM Audit Logs.
  4. Quelltyp: Google Cloud Storage V2.
  5. Logtyp: FORGEROCK_OPENIDM.
  6. Klicken Sie auf Dienstkonto abrufen und kopieren Sie die angegebene E-Mail-Adresse (z.B. chronicle-12345...).
  7. Klicken Sie auf Weiter.
  8. Storage-Bucket-URL: gs://forgerock-openidm-audit-logs/openidm/.
  9. Option zum Löschen von Quellen: Wählen Sie die gewünschte Option aus (z.B. Nie).
  10. Klicken Sie auf Weiter, prüfen Sie die Angaben und klicken Sie auf Senden.

IAM-Berechtigungen gewähren

  1. Rufen Sie Cloud Storage > Buckets auf.
  2. Wählen Sie Ihren Bucket aus und klicken Sie auf den Tab Berechtigungen.
  3. Klicken Sie auf Zugriff erlauben.
  4. Hauptkonten hinzufügen: Fügen Sie die E‑Mail-Adresse des Google SecOps-Dienstkontos ein.
  5. Rollen zuweisen: Wählen Sie Storage Object Viewer aus.
  6. Klicken Sie auf Speichern.

UDM-Zuordnungstabelle

Logfeld UDM-Zuordnung Logik
fluenttag_label, topic_label, context_roles_label additional.fields Schlüssel/Wert-Paare für den Kontext.
Via intermediary.hostname Hostname des Proxys/Vermittlers.
x_forwarded_ip, caller.callerIps intermediary.ip IP-Adresse des Vermittlers.
timestamp metadata.event_timestamp Zeitstempel des Ereignisses.
transactionId metadata.product_deployment_id Eindeutige Transaktions-ID.
eventName metadata.product_event_type Ereignisname von ForgeRock.
_id metadata.product_log_id Eindeutige Protokoll-ID.
request_method network.http.method Verwendete HTTP-Methode.
response.statusCode network.http.response_code HTTP-Statuscode.
user_agent network.http.user_agent Vollständiger User-Agent-String.
client.ip, context.ipAddress principal.ip Quell-IP-Adresse des Akteurs.
userId, principalData.0 principal.user.userid ID des handelnden Nutzers.
security_action security_result.action Sicherheitsentscheidung getroffen.
level security_result.severity Zugeordneter Schweregrad.
server.ip target.ip IP-Adresse des Zielsystems.
http.request.path target.url Ziel-URL/Pfad
– metadata.product_name Auf ForgeRock OpenIDM festgelegt.
– metadata.vendor_name Auf ForgeRock festlegen.
elapsed_time" and "X-Content-Type-Options additional.fields Aus dem Änderungsprotokoll zugeordnet
trackingIds.0 metadata.product_log_id Aus dem Änderungsprotokoll zugeordnet
context.userRolesProperty", "context.authenticationId", and "context.authenticationIdProperty principal.user.attribute.roles Aus dem Änderungsprotokoll zugeordnet
context.component", "context.moduleId", and "context.queryId principal.resource.attribute.labels Aus dem Änderungsprotokoll zugeordnet
context.roles", "_normalized.fieldNames", and "_eventId 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