Recopila registros de auditoría de Tines
En este documento, se explica cómo transferir registros de auditoría de Tines 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 Tines
- Acceso con privilegios a AWS (S3, Identity and Access Management [IAM], Lambda, EventBridge).
Obtén la URL de Tines
- En tu navegador, abre la IU de Tines para tu arrendatario.
- Copia el dominio de la barra de direcciones. Lo usarás como
TINES_BASE_URL
.- Formato:
https://<tenant-domain>
(por ejemplo,https://<tenant-domain>.tines.com
)
- Formato:
Crea una clave de API de servicio de Tines (recomendado) o una clave de API personal
Valores que se deben guardar para los pasos posteriores:
TINES_BASE_URL
: Por ejemplo,https://<domain>.tines.com
TINES_API_KEY
: Es el token que crearás en los siguientes pasos.
Opción 1: Clave de API de servicio (recomendada)
- Ve al menú de navegación > Claves de API.
- Haz clic en + Nueva clave.
- Selecciona Clave de API de servicio.
- Ingresa un nombre descriptivo (por ejemplo,
SecOps Audit Logs
). - Haz clic en Crear.
- Copia el token generado de inmediato y guárdalo de forma segura. Lo usarás como
TINES_API_KEY
.
Opción 2: Clave de API personal (si las claves de servicio no están disponibles)
- Ve al menú de navegación > Claves de API.
- Haz clic en + Nueva clave.
- Selecciona Clave de API personal.
- Ingresa un nombre descriptivo.
- Haz clic en Crear.
Copia el token generado y guárdalo de forma segura.
Otorga el permiso de lectura del registro de auditoría
- Accede como propietario del arrendatario (o pídele a uno que lo haga).
- Ve a Configuración > Administrador > Administración de usuarios (o haz clic en el nombre de tu equipo en el menú superior izquierdo y selecciona Usuarios).
- Busca el usuario de la cuenta de servicio asociado con tu clave de la API de Service (tendrá el mismo nombre que tu clave de API).
- Si usas una clave de API personal, busca tu propia cuenta de usuario.
- Haz clic en el usuario para abrir su perfil.
- En la sección Tenant permissions, habilita AUDIT_LOG_READ.
- Haz clic en Guardar.
(Opcional) Verifica el acceso a la API
Prueba el extremo con curl o cualquier cliente HTTP:
curl -X GET "https://<tenant-domain>/api/v1/audit_logs?per_page=1" \ -H "Authorization: Bearer <TINES_API_KEY>" \ -H "Content-Type: application/json"
Deberías recibir una respuesta JSON con las entradas del registro de auditoría.
También puedes verificar que existan registros de auditoría. Para ello, navega a Configuración > Supervisión > Registros de auditoría en la IU (se requiere el permiso AUDIT_LOG_READ).
Configura el bucket de AWS S3
- 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,
tines-audit-logs
).
Configura la política y el rol de IAM para las cargas de Lambda en S3
- En la consola de AWS, ve a IAM > Políticas > Crear política > pestaña JSON.
- Copia y pega la siguiente política.
JSON de la política (reemplaza
tines-audit-logs
si ingresaste un nombre de bucket diferente):{ "Version": "2012-10-17", "Statement": [ { "Sid": "AllowPutObjects", "Effect": "Allow", "Action": "s3:PutObject", "Resource": "arn:aws:s3:::tines-audit-logs/*" }, { "Sid": "AllowGetStateObject", "Effect": "Allow", "Action": "s3:GetObject", "Resource": "arn:aws:s3:::tines-audit-logs/tines/audit/state.json" } ] }
Haz clic en Siguiente > Crear política.
Asigna a la política el nombre
TinesLambdaS3Policy
.Ve a IAM > Roles > Crear rol > Servicio de AWS > Lambda.
Adjunta el
TinesLambdaS3Policy
que acabas de crear.Asigna el nombre
TinesAuditToS3Role
al 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 tines_audit_to_s3
Tiempo de ejecución Python 3.13 Arquitectura x86_64 Rol de ejecución TinesAuditToS3Role
Después de crear la función, abre la pestaña Code, borra el código auxiliar y pega el siguiente código (
tines_audit_to_s3.py
).#!/usr/bin/env python3 # Lambda: Pull Tines Audit Logs to S3 (no transform) import os, json, time, urllib.parse 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", "tines/audit/") STATE_KEY = os.environ.get("STATE_KEY", "tines/audit/state.json") LOOKBACK_SEC = int(os.environ.get("LOOKBACK_SECONDS", "3600")) # default 1h PAGE_SIZE = int(os.environ.get("PAGE_SIZE", "500")) # Max is 500 for Tines MAX_PAGES = int(os.environ.get("MAX_PAGES", "20")) TIMEOUT = int(os.environ.get("HTTP_TIMEOUT", "60")) HTTP_RETRIES = int(os.environ.get("HTTP_RETRIES", "3")) TINES_BASE_URL = os.environ["TINES_BASE_URL"] TINES_API_KEY = os.environ["TINES_API_KEY"] s3 = boto3.client("s3") def _iso(ts: float) -> str: return time.strftime("%Y-%m-%dT%H:%M:%SZ", time.gmtime(ts)) def _load_state() -> dict: try: obj = s3.get_object(Bucket=S3_BUCKET, Key=STATE_KEY) b = obj["Body"].read() return json.loads(b) if b else {} except Exception: return {} def _save_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 _req(url: str) -> dict: attempt = 0 while True: try: req = Request(url, method="GET") req.add_header("Authorization", f"Bearer {TINES_API_KEY}") req.add_header("Accept", "application/json") req.add_header("Content-Type", "application/json") with urlopen(req, timeout=TIMEOUT) as r: data = r.read() return json.loads(data.decode("utf-8")) except HTTPError as e: if e.code in (429, 500, 502, 503, 504) and attempt < HTTP_RETRIES: retry_after = 1 + attempt try: retry_after = int(e.headers.get("Retry-After", retry_after)) except Exception: pass time.sleep(max(1, retry_after)) attempt += 1 continue raise except URLError: if attempt < HTTP_RETRIES: time.sleep(1 + attempt) attempt += 1 continue raise def _write(payload, page: int) -> str: ts = time.gmtime() key = f"{S3_PREFIX}{time.strftime('%Y/%m/%d/%H%M%S', ts)}-tines-audit-{page:05d}.json" s3.put_object( Bucket=S3_BUCKET, Key=key, Body=json.dumps(payload, separators=(",", ":")).encode("utf-8"), ContentType="application/json", ) return key def _extract_items(payload) -> list: if isinstance(payload, list): return payload if isinstance(payload, dict): audit_logs = payload.get("audit_logs") if isinstance(audit_logs, list): return audit_logs return [] def _extract_newest_ts(items: list, current: str | None) -> str | None: newest = current for it in items: # Use created_at as the timestamp field t = it.get("created_at") if isinstance(t, str) and (newest is None or t > newest): newest = t return newest def lambda_handler(event=None, context=None): st = _load_state() since = st.get("since") or _iso(time.time() - LOOKBACK_SEC) page = 1 pages = 0 total = 0 newest_ts = since while pages < MAX_PAGES: # Build URL with query parameters # Note: Tines audit logs API uses 'after' parameter for filtering base_url = f"{TINES_BASE_URL.rstrip('/')}/api/v1/audit_logs" params = { "after": since, # Filter for logs created after this timestamp "page": page, "per_page": PAGE_SIZE } url = f"{base_url}?{urllib.parse.urlencode(params)}" payload = _req(url) _write(payload, page) items = _extract_items(payload) total += len(items) newest_ts = _extract_newest_ts(items, newest_ts) pages += 1 # Check if there's a next page using meta.next_page_number meta = payload.get("meta") or {} next_page = meta.get("next_page_number") if not next_page: break page = next_page if newest_ts and newest_ts != since: st["since"] = newest_ts _save_state(st) return {"ok": True, "pages": pages, "items": total, "since": st.get("since")} 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_BUCKET
tines-audit-logs
S3_PREFIX
tines/audit/
STATE_KEY
tines/audit/state.json
TINES_BASE_URL
https://your-tenant.tines.com
TINES_API_KEY
your-tines-api-key
LOOKBACK_SECONDS
3600
PAGE_SIZE
500
MAX_PAGES
20
HTTP_TIMEOUT
60
HTTP_RETRIES
3
Despué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
tines_audit_to_s3
. - Nombre:
tines-audit-1h
.
- Programación recurrente: Frecuencia (
- Haz clic en Crear programación.
Crea un usuario y claves de IAM de solo lectura para Google SecOps
- En la consola de AWS, ve a IAM > 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:::tines-audit-logs/*" }, { "Effect": "Allow", "Action": ["s3:ListBucket"], "Resource": "arn:aws:s3:::tines-audit-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 registros de auditoría de Tines
- 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,
Tines Audit Logs
). - Selecciona Amazon S3 V2 como el Tipo de fuente.
- Selecciona Tines como el Tipo de registro.
- Haz clic en Siguiente.
- Especifica valores para los siguientes parámetros de entrada:
- URI de S3:
s3://tines-audit-logs/tines/audit/
- 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.