Recopila registros del CRM de Zendesk
En este documento, se explica cómo transferir registros de la administración de relaciones con clientes (CRM) de Zendesk a Google Security Operations con Amazon S3.
Antes de comenzar
Asegúrate de cumplir con los siguientes requisitos previos:
- Es una instancia de Google SecOps.
- Acceso privilegiado a Zendesk
- Acceso con privilegios a AWS (S3, Identity and Access Management [IAM], Lambda, EventBridge).
Obtén los requisitos previos de Zendesk
- Confirmar plan y rol
- Debes ser administrador de Zendesk para crear tokens de API o clientes de OAuth. La API de Audit Logs solo está disponible en el plan Enterprise. (Si tu cuenta no es de Enterprise, omite
audit_logsenRESOURCES).
- Debes ser administrador de Zendesk para crear tokens de API o clientes de OAuth. La API de Audit Logs solo está disponible en el plan Enterprise. (Si tu cuenta no es de Enterprise, omite
- Activa el acceso al token de API (único)
- En el Centro de administración, ve a Apps y integraciones > APIs > Configuración de la API.
- Habilita Permitir acceso al token de API.
- Genera un token de API (para la autenticación básica)
- Ve a Apps and integrations > APIs > API tokens.
- Haz clic en Agregar token de API > (opcionalmente) agrega una descripción > Guardar.
- Copia y guarda el token de API ahora (no podrás volver a verlo).
- Guarda el correo electrónico del administrador que se autenticará con este token.
- Formato de autenticación básica que usa Lambda:
email_address/token:api_token
- Formato de autenticación básica que usa Lambda:
- (Opcional) Crea un cliente de OAuth (para la autenticación de portador en lugar del token de API)
- Ve a Apps and integrations > APIs > OAuth clients > Add OAuth client.
- Completa los campos Nombre, Identificador único (automático), URLs de redireccionamiento (puede ser un marcador de posición si solo generas tokens con la API) y Guardar.
- Crea un token de acceso para la integración y otorga los permisos mínimos que requiere esta guía:
tickets:read(para entradas incrementales)auditlogs:read(para Registros de auditoría; solo para empresas)- Si no sabes qué elegir,
readtambién funciona para el acceso de solo lectura.
- Copia el token de acceso (pégalo en
ZENDESK_BEARER_TOKEN) y registra el ID y el secreto del cliente de forma segura (para futuros flujos de actualización de tokens).
Registra tu URL base de Zendesk
- Usa
https://<your_subdomain>.zendesk.com(pégalo en la variable de entornoZENDESK_BASE_URL).
Qué copiar y guardar para más tarde
- URL base (por ejemplo,
https://acme.zendesk.com) - Dirección de correo electrónico del usuario administrador (para la autenticación con token de API)
- Token de API (si usas
AUTH_MODE=token) - o token de acceso de OAuth (si se usa
AUTH_MODE=bearer) - (Opcional) ID y secreto del cliente de OAuth para la administración del ciclo de vida
- Usa
Configura el bucket de AWS S3 y el IAM para Google SecOps
- Crea un bucket de Amazon S3 siguiendo esta guía del usuario: Crea un bucket
- Guarda el Nombre y la Región del bucket para futuras referencias (por ejemplo,
zendesk-crm-logs). - Crea un usuario siguiendo esta guía del usuario: Cómo crear un usuario de IAM.
- Selecciona el usuario creado.
- Selecciona la pestaña Credenciales de seguridad.
- Haz clic en Crear clave de acceso en la sección Claves de acceso.
- Selecciona Servicio de terceros como Caso de uso.
- Haz clic en Siguiente.
- Opcional: Agrega una etiqueta de descripción.
- Haz clic en Crear clave de acceso.
- Haz clic en Descargar archivo .CSV para guardar la clave de acceso y la clave de acceso secreta para consultarlas en el futuro.
- Haz clic en Listo.
- Selecciona la pestaña Permisos.
- Haz clic en Agregar permisos en la sección Políticas de permisos.
- Selecciona Agregar permisos.
- Selecciona Adjuntar políticas directamente.
- Busca la política AmazonS3FullAccess.
- Selecciona la política.
- Haz clic en Siguiente.
- Haz clic en Agregar permisos.
Configura la política y el rol de IAM para las cargas de S3
- En la consola de AWS, ve a IAM > Políticas.
- Haz clic en Crear política > pestaña JSON.
- Copia y pega la siguiente política.
JSON de la política (reemplaza
zendesk-crm-logssi ingresaste un nombre de bucket diferente):{ "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" } ] }Haz clic en Siguiente > Crear política.
Ve a IAM > Roles > Crear rol > Servicio de AWS > Lambda.
Adjunta la política recién creada.
Asigna el nombre
ZendeskCRMToS3Roleal rol y haz clic en Crear rol.
Crea la función Lambda
- En la consola de AWS, ve a Lambda > Functions > Create function.
- Haz clic en Author from scratch.
Proporciona los siguientes detalles de configuración:
Configuración Valor Nombre zendesk_crm_to_s3Tiempo de ejecución Python 3.13 Arquitectura x86_64 Rol de ejecución ZendeskCRMToS3RoleDespués de crear la función, abre la pestaña Code, borra el código auxiliar y pega el siguiente código (
zendesk_crm_to_s3.py).#!/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())Ve a Configuration > Environment variables.
Haz clic en Editar > Agregar nueva variable de entorno.
Ingresa las variables de entorno que se proporcionan en la siguiente tabla y reemplaza los valores de ejemplo por tus valores.
Variables de entorno
Clave Valor de ejemplo S3_BUCKETzendesk-crm-logsS3_PREFIXzendesk/crm/STATE_KEYzendesk/crm/state.jsonZENDESK_BASE_URLhttps://your_subdomain.zendesk.comAUTH_MODEtokenZENDESK_EMAILanalyst@example.comZENDESK_API_TOKEN<api_token>ZENDESK_BEARER_TOKEN<leave empty unless using OAuth bearer>RESOURCESaudit_logs,incremental_ticketsMAX_PAGES20LOOKBACK_SECONDS3600HTTP_TIMEOUT60Después de crear la función, permanece en su página (o abre Lambda > Funciones > tu-función).
Selecciona la pestaña Configuración.
En el panel Configuración general, haz clic en Editar.
Cambia Tiempo de espera a 5 minutos (300 segundos) y haz clic en Guardar.
Crea una programación de EventBridge
- Ve a Amazon EventBridge > Scheduler > Create schedule.
- Proporciona los siguientes detalles de configuración:
- Programación recurrente: Frecuencia (
1 hour) - Destino: Tu función Lambda
zendesk_crm_to_s3. - Nombre:
zendesk_crm_to_s3-1h.
- Programación recurrente: Frecuencia (
- Haz clic en Crear programación.
(Opcional) Crea un usuario y claves de IAM de solo lectura para Google SecOps
- Ve a Consola de AWS > IAM > Usuarios > Agregar usuarios.
- Haz clic en Agregar usuarios.
- Proporciona los siguientes detalles de configuración:
- Usuario: Ingresa
secops-reader. - Tipo de acceso: Selecciona Clave de acceso: Acceso programático.
- Usuario: Ingresa
- Haz clic en Crear usuario.
- Adjunta una política de lectura mínima (personalizada): Usuarios > secops-reader > Permisos > Agregar permisos > Adjuntar políticas directamente > Crear política.
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" } ] }Nombre =
secops-reader-policy.Haz clic en Crear política > busca o selecciona > Siguiente > Agregar permisos.
Crea una clave de acceso para
secops-reader: Credenciales de seguridad > Claves de acceso.Haz clic en Crear clave de acceso.
Descarga el
.CSV. (Pegarás estos valores en el feed).
Configura un feed en Google SecOps para transferir los registros del CRM de Zendesk
- Ve a Configuración de SIEM > Feeds.
- Haz clic en + Agregar feed nuevo.
- En el campo Nombre del feed, ingresa un nombre para el feed (por ejemplo,
Zendesk CRM logs). - Selecciona Amazon S3 V2 como el Tipo de fuente.
- Selecciona Zendesk CRM como el Tipo de registro.
- Haz clic en Siguiente.
- Especifica valores para los siguientes parámetros de entrada:
- URI de S3:
s3://zendesk-crm-logs/zendesk/crm/ - Opciones de borrado de la fuente: Selecciona la opción de borrado según tu preferencia.
- Antigüedad máxima del archivo: Incluye los archivos modificados en la cantidad de días especificada. El valor predeterminado es de 180 días.
- ID de clave de acceso: Clave de acceso del usuario con acceso al bucket de S3.
- Clave de acceso secreta: Clave secreta del usuario con acceso al bucket de S3.
- Espacio de nombres del recurso: Es el espacio de nombres del recurso.
- Etiquetas de transmisión: Es la etiqueta que se aplica a los eventos de este feed.
- URI de S3:
- Haz clic en Siguiente.
- Revisa la nueva configuración del feed en la pantalla Finalizar y, luego, haz clic en Enviar.
¿Necesitas más ayuda? Obtén respuestas de miembros de la comunidad y profesionales de Google SecOps.