Collecter les journaux d'audit Tines
Ce document explique comment ingérer les journaux d'audit Tines dans Google Security Operations à l'aide d'Amazon S3.
Avant de commencer
Assurez-vous de remplir les conditions suivantes :
- Une instance Google SecOps.
- Accès privilégié à Tines.
- Accès privilégié à AWS (S3, Identity and Access Management (IAM), Lambda, EventBridge).
Obtenir l'URL Tines
- Dans votre navigateur, ouvrez l'interface utilisateur Tines pour votre locataire.
- Copiez le domaine à partir de la barre d'adresse. Vous l'utiliserez comme
TINES_BASE_URL
.- Format :
https://<tenant-domain>
(par exemple,https://<tenant-domain>.tines.com
).
- Format :
Créez une clé API de service Tines (recommandée) ou une clé API personnelle.
Valeurs à enregistrer pour les étapes ultérieures :
TINES_BASE_URL
: par exemple,https://<domain>.tines.com
TINES_API_KEY
: jeton que vous allez créer lors des prochaines étapes
Option 1 : Clé API de service (recommandée)
- Accédez au menu de navigation> Clés API.
- Cliquez sur + Nouvelle clé.
- Sélectionnez Clé API de service.
- Saisissez un nom descriptif (par exemple,
SecOps Audit Logs
). - Cliquez sur Créer.
- Copiez immédiatement le jeton généré et enregistrez-le de manière sécurisée. Vous l'utiliserez comme
TINES_API_KEY
.
Option 2 : Clé API personnelle (si les clés de service ne sont pas disponibles)
- Accédez au menu de navigation> Clés API.
- Cliquez sur + Nouvelle clé.
- Sélectionnez Clé API personnelle.
- Saisissez un nom descriptif.
- Cliquez sur Créer.
Copiez le jeton généré et enregistrez-le de manière sécurisée.
Accorder l'autorisation de lecture des journaux d'audit
- Connectez-vous en tant que propriétaire du locataire (ou demandez-lui de le faire).
- Accédez à Paramètres > Administration > Administration des utilisateurs (ou cliquez sur le nom de votre équipe dans le menu en haut à gauche, puis sélectionnez Utilisateurs).
- Recherchez l'utilisateur du compte de service associé à votre clé API Service (il aura le même nom que votre clé API).
- Si vous utilisez une clé API personnelle, recherchez plutôt votre propre compte utilisateur.
- Cliquez sur l'utilisateur pour ouvrir son profil.
- Dans la section Autorisations du locataire, activez AUDIT_LOG_READ.
- Cliquez sur Enregistrer.
(Facultatif) Vérifier l'accès à l'API
Testez le point de terminaison à l'aide de curl ou de n'importe quel client 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"
Vous devriez recevoir une réponse JSON contenant des entrées de journaux d'audit.
Vous pouvez également vérifier l'existence des journaux d'audit en accédant à Paramètres > Surveillance > Journaux d'audit dans l'interface utilisateur (nécessite l'autorisation AUDIT_LOG_READ).
Configurer un bucket AWS S3
- Créez un bucket Amazon S3 en suivant ce guide de l'utilisateur : Créer un bucket.
- Enregistrez le Nom et la Région du bucket pour référence ultérieure (par exemple,
tines-audit-logs
).
Configurer la stratégie et le rôle IAM pour les importations Lambda S3
- Dans la console AWS, accédez à IAM> Stratégies> Créer une stratégie> onglet JSON.
- Copiez et collez le règlement suivant.
JSON de la règle (remplacez
tines-audit-logs
si vous avez saisi un autre nom de bucket) :{ "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" } ] }
Cliquez sur Suivant > Créer une règle.
Nommez la règle
TinesLambdaS3Policy
.Accédez à IAM > Rôles > Créer un rôle > Service AWS > Lambda.
Joignez le
TinesLambdaS3Policy
que vous venez de créer.Nommez le rôle
TinesAuditToS3Role
, puis cliquez sur Créer un rôle.
Créer la fonction Lambda
- Dans la console AWS, accédez à Lambda > Fonctions > Créer une fonction.
- Cliquez sur Créer à partir de zéro.
Fournissez les informations de configuration suivantes :
Paramètre Valeur Nom tines_audit_to_s3
Durée d'exécution Python 3.13 Architecture x86_64 Rôle d'exécution TinesAuditToS3Role
Une fois la fonction créée, ouvrez l'onglet Code, supprimez le stub et collez le code suivant (
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())
Accédez à Configuration > Variables d'environnement.
Cliquez sur Modifier > Ajouter une variable d'environnement.
Saisissez les variables d'environnement fournies dans le tableau suivant, en remplaçant les exemples de valeurs par les vôtres.
Variables d'environnement
Clé Exemple de valeur 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
Une fois la fonction créée, restez sur sa page (ou ouvrez Lambda > Fonctions > votre-fonction).
Accédez à l'onglet Configuration.
Dans le panneau Configuration générale, cliquez sur Modifier.
Définissez le délai avant expiration sur 5 minutes (300 secondes), puis cliquez sur Enregistrer.
Créer une programmation EventBridge
- Accédez à Amazon EventBridge> Scheduler> Create schedule.
- Fournissez les informations de configuration suivantes :
- Planning récurrent : Tarif (
1 hour
). - Cible : votre fonction Lambda
tines_audit_to_s3
. - Nom :
tines-audit-1h
.
- Planning récurrent : Tarif (
- Cliquez sur Créer la programmation.
Créer un utilisateur et des clés IAM en lecture seule pour Google SecOps
- Dans la console AWS, accédez à IAM > Utilisateurs.
- Cliquez sur Add users (Ajouter des utilisateurs).
- Fournissez les informations de configuration suivantes :
- Utilisateur : saisissez
secops-reader
. - Type d'accès : sélectionnez Clé d'accès – Accès programmatique.
- Utilisateur : saisissez
- Cliquez sur Créer un utilisateur.
- Associez une stratégie de lecture minimale (personnalisée) : Utilisateurs > secops-reader > Autorisations > Ajouter des autorisations > Associer des stratégies directement > Créer une stratégie.
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" } ] }
Nom =
secops-reader-policy
.Cliquez sur Créer une règle> recherchez/sélectionnez > Suivant> Ajouter des autorisations.
Créez une clé d'accès pour
secops-reader
: Identifiants de sécurité > Clés d'accès.Cliquez sur Créer une clé d'accès.
Téléchargez le fichier
.CSV
. (Vous collerez ces valeurs dans le flux.)
Configurer un flux dans Google SecOps pour ingérer les journaux d'audit Tines
- Accédez à Paramètres SIEM> Flux.
- Cliquez sur + Ajouter un flux.
- Dans le champ Nom du flux, saisissez un nom pour le flux (par exemple,
Tines Audit Logs
). - Sélectionnez Amazon S3 V2 comme type de source.
- Sélectionnez Tines comme Type de journal.
- Cliquez sur Suivant.
- Spécifiez les valeurs des paramètres d'entrée suivants :
- URI S3 :
s3://tines-audit-logs/tines/audit/
- Options de suppression de la source : sélectionnez l'option de suppression de votre choix.
- Âge maximal des fichiers : incluez les fichiers modifiés au cours des derniers jours. La valeur par défaut est de 180 jours.
- ID de clé d'accès : clé d'accès utilisateur ayant accès au bucket S3.
- Clé d'accès secrète : clé secrète de l'utilisateur ayant accès au bucket S3.
- Espace de noms de l'élément : espace de noms de l'élément.
- Libellés d'ingestion : libellé appliqué aux événements de ce flux.
- URI S3 :
- Cliquez sur Suivant.
- Vérifiez la configuration de votre nouveau flux sur l'écran Finaliser, puis cliquez sur Envoyer.
Vous avez encore besoin d'aide ? Obtenez des réponses de membres de la communauté et de professionnels Google SecOps.