Zendesk CRM-Protokolle erfassen
In diesem Dokument wird beschrieben, wie Sie Zendesk CRM-Logs (Customer Relationship Management) mit Amazon S3 in Google Security Operations aufnehmen.
Hinweise
Prüfen Sie, ob folgende Voraussetzungen erfüllt sind:
- Eine Google SecOps-Instanz.
- Privilegierter Zugriff auf Zendesk.
- Privilegierter Zugriff auf AWS (S3, Identity and Access Management (IAM), Lambda, EventBridge).
Zendesk-Voraussetzungen
- Tarif und Rolle bestätigen
- Sie müssen Zendesk-Administrator sein, um API-Tokens oder OAuth-Clients zu erstellen. Die Audit Logs API ist nur im Enterprise-Abo verfügbar. Wenn Sie kein Enterprise-Konto haben, überspringen Sie
audit_logs
inRESOURCES
.
- Sie müssen Zendesk-Administrator sein, um API-Tokens oder OAuth-Clients zu erstellen. Die Audit Logs API ist nur im Enterprise-Abo verfügbar. Wenn Sie kein Enterprise-Konto haben, überspringen Sie
- API-Tokenzugriff aktivieren (einmalig)
- Gehen Sie im Admin Center zu Apps und Integrationen > APIs > API-Konfiguration.
- Aktivieren Sie API-Token-Zugriff zulassen.
- API-Token generieren (für die einfache Authentifizierung)
- Klicken Sie auf Apps und Integrationen > APIs > API-Tokens.
- Klicken Sie auf API-Token hinzufügen> (optional) Beschreibung hinzufügen> Speichern.
- Kopieren und speichern Sie jetzt das API-Token. Sie können es später nicht mehr aufrufen.
- Speichern Sie die Administrator-E-Mail-Adresse, mit der dieses Token authentifiziert wird.
- Von der Lambda verwendetes Format für die Basisauthentifizierung:
email_address/token:api_token
- Von der Lambda verwendetes Format für die Basisauthentifizierung:
- (Optional) OAuth-Client erstellen (für die Bearer-Authentifizierung anstelle eines API-Tokens)
- Rufen Sie Apps und Integrationen > APIs > OAuth-Clients > OAuth-Client hinzufügen auf.
- Geben Sie Name, Unique Identifier (eindeutige Kennung, automatisch), Redirect URLs (Umleitungs-URLs, kann Platzhalter sein, wenn Sie Tokens nur mit der API erstellen) ein und klicken Sie auf Save (Speichern).
- Erstellen Sie ein Zugriffstoken für die Integration und gewähren Sie die in dieser Anleitung erforderlichen Mindestbereiche:
tickets:read
(für inkrementelle Tickets)auditlogs:read
(für Audit-Logs; nur Enterprise)- Wenn Sie sich nicht sicher sind, funktioniert
read
auch für den schreibgeschützten Zugriff.
- Kopieren Sie das Zugriffstoken (fügen Sie es in
ZENDESK_BEARER_TOKEN
ein) und notieren Sie die Client-ID/den Clientschlüssel sicher (für zukünftige Token-Aktualisierungsabläufe).
Zendesk-Basis-URL notieren
- Verwenden Sie
https://<your_subdomain>.zendesk.com
(fügen Sie sie in die UmgebungsvariableZENDESK_BASE_URL
ein).
Was soll kopiert und für später gespeichert werden?
- Basis-URL (z. B.
https://acme.zendesk.com
) - E-Mail-Adresse des Administratornutzers (für die API-Token-Authentifizierung)
- API-Token (bei Verwendung von
AUTH_MODE=token
) - oder OAuth-Zugriffstoken (bei Verwendung von
AUTH_MODE=bearer
) - Optional: OAuth-Client-ID/Schlüssel für die Lebenszyklusverwaltung
- Verwenden Sie
AWS S3-Bucket und IAM für Google SecOps konfigurieren
- Erstellen Sie einen Amazon S3-Bucket. Folgen Sie dazu der Anleitung unter Bucket erstellen.
- Speichern Sie den Namen und die Region des Buckets zur späteren Verwendung (z. B.
zendesk-crm-logs
). - Erstellen Sie einen Nutzer gemäß dieser Anleitung: IAM-Nutzer erstellen.
- Wählen Sie den erstellten Nutzer aus.
- Wählen Sie den Tab Sicherheitsanmeldedaten aus.
- Klicken Sie im Abschnitt Zugriffsschlüssel auf Zugriffsschlüssel erstellen.
- Wählen Sie Drittanbieterdienst als Anwendungsfall aus.
- Klicken Sie auf Weiter.
- Optional: Fügen Sie ein Beschreibungstag hinzu.
- Klicken Sie auf Zugriffsschlüssel erstellen.
- Klicken Sie auf CSV-Datei herunterladen, um den Access Key (Zugriffsschlüssel) und den Secret Access Key (geheimer Zugriffsschlüssel) für die zukünftige Verwendung zu speichern.
- Klicken Sie auf Fertig.
- Wählen Sie den Tab Berechtigungen aus.
- Klicken Sie im Bereich Berechtigungsrichtlinien auf Berechtigungen hinzufügen.
- Wählen Sie Berechtigungen hinzufügen aus.
- Wählen Sie Richtlinien direkt anhängen aus.
- Suchen Sie nach der Richtlinie AmazonS3FullAccess.
- Wählen Sie die Richtlinie aus.
- Klicken Sie auf Weiter.
- Klicken Sie auf Berechtigungen hinzufügen.
IAM-Richtlinie und ‑Rolle für S3-Uploads konfigurieren
- Rufen Sie in der AWS-Konsole IAM > Richtlinien auf.
- Klicken Sie auf Richtlinie erstellen> Tab „JSON“.
- Kopieren Sie die folgende Richtlinie und fügen Sie sie ein.
Policy JSON (ersetzen Sie
zendesk-crm-logs
, wenn Sie einen anderen Bucket-Namen eingegeben haben):{ "Version": "2012-10-17", "Statement": [ { "Sid": "AllowPutObjects", "Effect": "Allow", "Action": "s3:PutObject", "Resource": "arn:aws:s3:::zendesk-crm-logs/*" }, { "Sid": "AllowGetStateObject", "Effect": "Allow", "Action": "s3:GetObject", "Resource": "arn:aws:s3:::zendesk-crm-logs/zendesk/crm/state.json" } ] }
Klicken Sie auf Weiter > Richtlinie erstellen.
Rufen Sie IAM > Rollen > Rolle erstellen > AWS-Service > Lambda auf.
Hängen Sie die neu erstellte Richtlinie an.
Geben Sie der Rolle den Namen
ZendeskCRMToS3Role
und klicken Sie auf Rolle erstellen.
Lambda-Funktion erstellen
- Rufen Sie in der AWS Console Lambda > Funktionen > Funktion erstellen auf.
- Klicken Sie auf Von Grund auf erstellen.
Geben Sie die folgenden Konfigurationsdetails an:
Einstellung Wert Name zendesk_crm_to_s3
Laufzeit Python 3.13 Architektur x86_64 Ausführungsrolle ZendeskCRMToS3Role
Nachdem die Funktion erstellt wurde, öffnen Sie den Tab Code, löschen Sie den Stub und fügen Sie den folgenden Code (
zendesk_crm_to_s3.py
) ein.#!/usr/bin/env python3 import os, json, time, base64 from urllib.request import Request, urlopen from urllib.error import HTTPError, URLError import boto3 S3_BUCKET = os.environ["S3_BUCKET"] S3_PREFIX = os.environ.get("S3_PREFIX", "zendesk/crm/") STATE_KEY = os.environ.get("STATE_KEY", "zendesk/crm/state.json") BASE_URL = os.environ["ZENDESK_BASE_URL"].rstrip("/") # e.g. https://your_subdomain.zendesk.com AUTH_MODE = os.environ.get("AUTH_MODE", "token").lower() # token|bearer EMAIL = os.environ.get("ZENDESK_EMAIL", "") API_TOKEN = os.environ.get("ZENDESK_API_TOKEN", "") BEARER = os.environ.get("ZENDESK_BEARER_TOKEN", "") RESOURCES = [r.strip() for r in os.environ.get("RESOURCES", "audit_logs,incremental_tickets").split(",") if r.strip()] MAX_PAGES = int(os.environ.get("MAX_PAGES", "20")) LOOKBACK = int(os.environ.get("LOOKBACK_SECONDS", "3600")) # 1h default HTTP_TIMEOUT = int(os.environ.get("HTTP_TIMEOUT", "60")) HTTP_RETRIES = int(os.environ.get("HTTP_RETRIES", "3")) s3 = boto3.client("s3") def _headers() -> dict: if AUTH_MODE == "bearer" and BEARER: return {"Authorization": f"Bearer {BEARER}", "Accept": "application/json"} if AUTH_MODE == "token" and EMAIL and API_TOKEN: token = base64.b64encode(f"{EMAIL}/token:{API_TOKEN}".encode()).decode() return {"Authorization": f"Basic {token}", "Accept": "application/json"} raise RuntimeError("Invalid auth settings: provide token (EMAIL + API_TOKEN) or BEARER") def _get_state() -> dict: try: obj = s3.get_object(Bucket=S3_BUCKET, Key=STATE_KEY) b = obj["Body"].read() return json.loads(b) if b else {"audit_logs": {}, "incremental_tickets": {}} except Exception: return {"audit_logs": {}, "incremental_tickets": {}} def _put_state(st: dict) -> None: s3.put_object( Bucket=S3_BUCKET, Key=STATE_KEY, Body=json.dumps(st, separators=(",", ":")).encode("utf-8"), ContentType="application/json", ) def _http_get_json(url: str) -> dict: attempt = 0 while True: try: req = Request(url, method="GET") for k, v in _headers().items(): req.add_header(k, v) with urlopen(req, timeout=HTTP_TIMEOUT) as r: return json.loads(r.read().decode("utf-8")) except HTTPError as e: if e.code in (429, 500, 502, 503, 504) and attempt < HTTP_RETRIES: ra = 1 + attempt try: ra = int(e.headers.get("Retry-After", ra)) except Exception: pass time.sleep(max(1, ra)) attempt += 1 continue raise except URLError: if attempt < HTTP_RETRIES: time.sleep(1 + attempt) attempt += 1 continue raise def _put_page(payload: dict, resource: str) -> str: ts = time.gmtime() key = f"{S3_PREFIX}/{time.strftime('%Y/%m/%d/%H%M%S', ts)}-zendesk-{resource}.json" s3.put_object( Bucket=S3_BUCKET, Key=key, Body=json.dumps(payload, separators=(",", ":")).encode("utf-8"), ContentType="application/json", ) return key def fetch_audit_logs(state: dict): """GET /api/v2/audit_logs.json with pagination via `next_page` (Zendesk).""" next_url = state.get("next_url") or f"{BASE_URL}/api/v2/audit_logs.json?page=1" pages = 0 written = 0 last_next = None while pages < MAX_PAGES and next_url: data = _http_get_json(next_url) _put_page(data, "audit_logs") written += len(data.get("audit_logs", [])) last_next = data.get("next_page") next_url = last_next pages += 1 return {"resource": "audit_logs", "pages": pages, "written": written, "next_url": last_next} def fetch_incremental_tickets(state: dict): """Cursor-based incremental export: /api/v2/incremental/tickets/cursor.json (pagination via `links.next`).""" next_link = state.get("next") if not next_link: start = int(time.time()) - LOOKBACK next_link = f"{BASE_URL}/api/v2/incremental/tickets/cursor.json?start_time={start}" pages = 0 written = 0 last_next = None while pages < MAX_PAGES and next_link: data = _http_get_json(next_link) _put_page(data, "incremental_tickets") written += len(data.get("tickets", [])) links = data.get("links") or {} next_link = links.get("next") last_next = next_link pages += 1 return {"resource": "incremental_tickets", "pages": pages, "written": written, "next": last_next} def lambda_handler(event=None, context=None): state = _get_state() summary = [] if "audit_logs" in RESOURCES: res = fetch_audit_logs(state.get("audit_logs", {})) state["audit_logs"] = {"next_url": res.get("next_url")} summary.append(res) if "incremental_tickets" in RESOURCES: res = fetch_incremental_tickets(state.get("incremental_tickets", {})) state["incremental_tickets"] = {"next": res.get("next")} summary.append(res) _put_state(state) return {"ok": True, "summary": summary} if __name__ == "__main__": print(lambda_handler())
Rufen Sie Konfiguration > Umgebungsvariablen auf.
Klicken Sie auf Bearbeiten> Neue Umgebungsvariable hinzufügen.
Geben Sie die in der folgenden Tabelle aufgeführten Umgebungsvariablen ein und ersetzen Sie die Beispielwerte durch Ihre Werte.
Umgebungsvariablen
Schlüssel Beispielwert S3_BUCKET
zendesk-crm-logs
S3_PREFIX
zendesk/crm/
STATE_KEY
zendesk/crm/state.json
ZENDESK_BASE_URL
https://your_subdomain.zendesk.com
AUTH_MODE
token
ZENDESK_EMAIL
analyst@example.com
ZENDESK_API_TOKEN
<api_token>
ZENDESK_BEARER_TOKEN
<leave empty unless using OAuth bearer>
RESOURCES
audit_logs,incremental_tickets
MAX_PAGES
20
LOOKBACK_SECONDS
3600
HTTP_TIMEOUT
60
Bleiben Sie nach dem Erstellen der Funktion auf der zugehörigen Seite oder öffnen Sie Lambda > Funktionen > Ihre Funktion.
Wählen Sie den Tab Konfiguration aus.
Klicken Sie im Bereich Allgemeine Konfiguration auf Bearbeiten.
Ändern Sie Zeitlimit in 5 Minuten (300 Sekunden) und klicken Sie auf Speichern.
EventBridge-Zeitplan erstellen
- Gehen Sie zu Amazon EventBridge > Scheduler > Create schedule (Amazon EventBridge > Scheduler > Zeitplan erstellen).
- Geben Sie die folgenden Konfigurationsdetails an:
- Wiederkehrender Zeitplan: Preis (
1 hour
). - Ziel: Ihre Lambda-Funktion
zendesk_crm_to_s3
. - Name:
zendesk_crm_to_s3-1h
.
- Wiederkehrender Zeitplan: Preis (
- Klicken Sie auf Zeitplan erstellen.
(Optional) IAM-Nutzer mit Lesezugriff und Schlüssel für Google SecOps erstellen
- Rufen Sie die AWS-Konsole > IAM > Nutzer > Nutzer hinzufügen auf.
- Klicken Sie auf Add users (Nutzer hinzufügen).
- Geben Sie die folgenden Konfigurationsdetails an:
- Nutzer: Geben Sie
secops-reader
ein. - Zugriffstyp: Wählen Sie Zugriffsschlüssel – programmatischer Zugriff aus.
- Nutzer: Geben Sie
- Klicken Sie auf Nutzer erstellen.
- Minimale Leseberechtigung (benutzerdefiniert) anhängen: Nutzer > secops-reader > Berechtigungen > Berechtigungen hinzufügen > Richtlinien direkt anhängen > Richtlinie erstellen.
JSON:
{ "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Action": ["s3:GetObject"], "Resource": "arn:aws:s3:::zendesk-crm-logs/*" }, { "Effect": "Allow", "Action": ["s3:ListBucket"], "Resource": "arn:aws:s3:::zendesk-crm-logs" } ] }
Name =
secops-reader-policy
.Klicken Sie auf Richtlinie erstellen> suchen/auswählen> Weiter> Berechtigungen hinzufügen.
Erstellen Sie einen Zugriffsschlüssel für
secops-reader
: Sicherheitsanmeldedaten > Zugriffsschlüssel.Klicken Sie auf Zugriffsschlüssel erstellen.
Laden Sie die Datei
.CSV
herunter. Sie fügen diese Werte in den Feed ein.
Feed in Google SecOps konfigurieren, um Zendesk CRM-Logs aufzunehmen
- Rufen Sie die SIEM-Einstellungen > Feeds auf.
- Klicken Sie auf + Neuen Feed hinzufügen.
- Geben Sie im Feld Feedname einen Namen für den Feed ein, z. B.
Zendesk CRM logs
. - Wählen Sie Amazon S3 V2 als Quelltyp aus.
- Wählen Sie Zendesk CRM als Logtyp aus.
- Klicken Sie auf Weiter.
- Geben Sie Werte für die folgenden Eingabeparameter an:
- S3-URI:
s3://zendesk-crm-logs/zendesk/crm/
- Optionen zum Löschen der Quelle: Wählen Sie die gewünschte Option zum Löschen aus.
- Maximales Dateialter: Dateien einschließen, die in den letzten Tagen geändert wurden. Der Standardwert ist 180 Tage.
- Zugriffsschlüssel-ID: Nutzerzugriffsschlüssel mit Zugriff auf den S3-Bucket.
- Geheimer Zugriffsschlüssel: Der geheime Schlüssel des Nutzers mit Zugriff auf den S3-Bucket.
- Asset-Namespace: Der Asset-Namespace.
- Aufnahmelabels: Das Label, das auf die Ereignisse aus diesem Feed angewendet wird.
- S3-URI:
- Klicken Sie auf Weiter.
- Prüfen Sie die neue Feedkonfiguration auf dem Bildschirm Abschließen und klicken Sie dann auf Senden.
Benötigen Sie weitere Hilfe? Antworten von Community-Mitgliedern und Google SecOps-Experten erhalten