Raccogliere i log JSON di Box Collaboration
Questo documento spiega come importare i log JSON di Box Collaboration in Google Security Operations utilizzando AWS S3 tramite la pianificazione di Lambda ed EventBridge. Il parser elabora i log degli eventi di Box in formato JSON, mappandoli a un modello UDM (Unified Data Model). Estrae i campi pertinenti dai log non elaborati, esegue trasformazioni dei dati come la ridenominazione e l'unione e arricchisce i dati con informazioni intermedie prima di restituire i dati sugli eventi strutturati.
Prima di iniziare
- Istanza Google SecOps
- Accesso privilegiato a Box (console di amministrazione + console per gli sviluppatori)
- Accesso privilegiato ad AWS (S3, IAM, Lambda, EventBridge) nella stessa regione in cui prevedi di archiviare i log
Configura la console per sviluppatori Box (credenziali client)
- Accedi alla console per sviluppatori di Box.
- Crea un'app personalizzata con autenticazione server (concessione delle credenziali client).
- Imposta Application Access (Accesso alle applicazioni) = App + Enterprise Access (App + Accesso aziendale).
- In Ambiti delle applicazioni, attiva Gestisci proprietà aziendali.
- Nella Console di amministrazione > App > Gestore app personalizzate, autorizza l'app tramite l'ID client.
- Copia e salva l'ID client e il * client secret in una posizione sicura.
- Vai alla Console di amministrazione > Account e fatturazione > Informazioni sull'account.
- Copia e salva l'ID enterprise in un luogo sicuro.
Configura il bucket AWS S3 e IAM per Google SecOps
- Crea un bucket Amazon S3 seguendo questa guida utente: Creazione di un bucket
- Salva il nome e la regione del bucket per riferimento futuro (ad esempio,
box-collaboration-logs
). - Crea un utente seguendo questa guida: Creazione di un utente IAM.
- Seleziona l'utente creato.
- Seleziona la scheda Credenziali di sicurezza.
- Fai clic su Crea chiave di accesso nella sezione Chiavi di accesso.
- Seleziona Servizio di terze parti come Caso d'uso.
- Fai clic su Avanti.
- (Facoltativo) Aggiungi un tag di descrizione.
- Fai clic su Crea chiave di accesso.
- Fai clic su Scarica file CSV per salvare la chiave di accesso e la chiave di accesso segreta per un utilizzo successivo.
- Fai clic su Fine.
- Seleziona la scheda Autorizzazioni.
- Fai clic su Aggiungi autorizzazioni nella sezione Criteri per le autorizzazioni.
- Seleziona Aggiungi autorizzazioni.
- Seleziona Allega direttamente i criteri.
- Cerca e seleziona il criterio AmazonS3FullAccess.
- Fai clic su Avanti.
- Fai clic su Aggiungi autorizzazioni.
Configura il ruolo e il criterio IAM per i caricamenti S3
- Nella console AWS, vai a IAM > Policy > Crea policy > Scheda JSON.
Inserisci la seguente policy:
{ "Version": "2012-10-17", "Statement": [ { "Sid": "AllowPutBoxObjects", "Effect": "Allow", "Action": ["s3:PutObject"], "Resource": "arn:aws:s3:::box-collaboration-logs/*" }, { "Sid": "AllowGetStateObject", "Effect": "Allow", "Action": ["s3:GetObject"], "Resource": "arn:aws:s3:::box-collaboration-logs/box/collaboration/state.json" } ] }
- Sostituisci
box-collaboration-logs
se hai inserito un nome bucket diverso.
- Sostituisci
Fai clic su Avanti > Crea policy.
Vai a IAM > Ruoli > Crea ruolo > Servizio AWS > Lambda.
Allega il criterio appena creato.
Assegna al ruolo il nome
WriteBoxToS3Role
e fai clic su Crea ruolo.
Crea la funzione Lambda
- Nella console AWS, vai a Lambda > Funzioni > Crea funzione.
- Fai clic su Crea autore da zero.
Fornisci i seguenti dettagli di configurazione:
Impostazione Valore Nome box_collaboration_to_s3
Tempo di esecuzione Python 3.13 Architettura x86_64 Ruolo di esecuzione WriteBoxToS3Role
Dopo aver creato la funzione, apri la scheda Codice, elimina lo stub e inserisci il seguente codice (
box_collaboration_to_s3.py
):#!/usr/bin/env python3 # Lambda: Pull Box Enterprise Events to S3 (no transform) import os, json, time, urllib.parse from urllib.request import Request, urlopen from urllib.error import HTTPError, URLError import boto3 TOKEN_URL = "https://api.box.com/oauth2/token" EVENTS_URL = "https://api.box.com/2.0/events" CID = os.environ["BOX_CLIENT_ID"] CSECRET = os.environ["BOX_CLIENT_SECRET"] ENT_ID = os.environ["BOX_ENTERPRISE_ID"] STREAM_TYPE = os.environ.get("STREAM_TYPE", "admin_logs_streaming") LIMIT = int(os.environ.get("LIMIT", "500")) BUCKET = os.environ["S3_BUCKET"] PREFIX = os.environ.get("S3_PREFIX", "box/collaboration/") STATE_KEY = os.environ.get("STATE_KEY", "box/collaboration/state.json") s3 = boto3.client("s3") def get_state(): try: obj = s3.get_object(Bucket=BUCKET, Key=STATE_KEY) data = json.loads(obj["Body"].read()) return data.get("stream_position") except Exception: return None def put_state(pos): body = json.dumps({"stream_position": pos}, separators=(",", ":")).encode("utf-8") s3.put_object(Bucket=BUCKET, Key=STATE_KEY, Body=body, ContentType="application/json") def get_token(): body = urllib.parse.urlencode({ "grant_type": "client_credentials", "client_id": CID, "client_secret": CSECRET, "box_subject_type": "enterprise", "box_subject_id": ENT_ID, }).encode() req = Request(TOKEN_URL, data=body, method="POST") req.add_header("Content-Type", "application/x-www-form-urlencoded") with urlopen(req, timeout=30) as r: tok = json.loads(r.read().decode()) return tok["access_token"] def fetch_events(token, stream_position=None, timeout=60, max_retries=5): params = {"stream_type": STREAM_TYPE, "limit": LIMIT, "stream_position": stream_position or "now"} qs = urllib.parse.urlencode(params) attempt, backoff = 0, 1.0 while True: try: req = Request(f"{EVENTS_URL}?{qs}", method="GET") req.add_header("Authorization", f"Bearer {token}") with urlopen(req, timeout=timeout) as r: return json.loads(r.read().decode()) except HTTPError as e: if e.code == 429 and attempt < max_retries: ra = e.headers.get("Retry-After") delay = int(ra) if (ra and ra.isdigit()) else int(backoff) time.sleep(max(1, delay)); attempt += 1; backoff *= 2; continue if 500 <= e.code <= 599 and attempt < max_retries: time.sleep(backoff); attempt += 1; backoff *= 2; continue raise except URLError: if attempt < max_retries: time.sleep(backoff); attempt += 1; backoff *= 2; continue raise def write_chunk(data): ts = time.strftime("%Y/%m/%d/%H%M%S", time.gmtime()) key = f"{PREFIX}/{ts}-box-events.json" s3.put_object(Bucket=BUCKET, Key=key, Body=json.dumps(data, separators=(",", ":")).encode("utf-8"), ContentType="application/json") return key def lambda_handler(event=None, context=None): token = get_token() pos = get_state() total, idx = 0, 0 while True: page = fetch_events(token, pos) entries = page.get("entries") or [] if not entries: next_pos = page.get("next_stream_position") or pos if next_pos and next_pos != pos: put_state(next_pos) break # уникальный ключ ts = time.strftime("%Y/%m/%d/%H%M%S", time.gmtime()) key = f"{PREFIX}/{ts}-box-events-{idx:03d}.json" s3.put_object(Bucket=BUCKET, Key=key, Body=json.dumps(page, separators=(",", ":")).encode("utf-8"), ContentType="application/json") idx += 1 total += len(entries) pos = page.get("next_stream_position") or pos if pos: put_state(pos) if len(entries) < LIMIT: break return {"ok": True, "written": total, "next_stream_position": pos}
Vai a Configurazione > Variabili di ambiente > Modifica > Aggiungi nuova variabile di ambiente.
Inserisci le seguenti variabili di ambiente, sostituendole con i tuoi valori:
Chiave Esempio S3_BUCKET
box-collaboration-logs
S3_PREFIX
box/collaboration/
STATE_KEY
box/collaboration/state.json
BOX_CLIENT_ID
Inserisci l'ID client Box BOX_CLIENT_SECRET
Inserisci il client secret di Box BOX_ENTERPRISE_ID
Inserisci l'ID azienda Box STREAM_TYPE
admin_logs_streaming
LIMIT
500
Dopo aver creato la funzione, rimani sulla relativa pagina (o apri Lambda > Funzioni > la tua funzione).
Seleziona la scheda Configurazione.
Nel riquadro Configurazione generale, fai clic su Modifica.
Modifica Timeout impostando 10 minuti (600 secondi) e fai clic su Salva.
Pianifica la funzione Lambda (EventBridge Scheduler)
- Vai a Amazon EventBridge > Scheduler > Crea pianificazione.
- Fornisci i seguenti dettagli di configurazione:
- Programma ricorrente: Tariffa (
15 min
). - Destinazione: la tua funzione Lambda.
- Nome:
box-collaboration-schedule-15min
- Programma ricorrente: Tariffa (
- Fai clic su Crea pianificazione.
Configura un feed in Google SecOps per importare i log di Box
- Vai a Impostazioni SIEM > Feed.
- Fai clic su Aggiungi nuovo feed.
- Nel campo Nome feed, inserisci un nome per il feed (ad esempio,
Box Collaboration
). - Seleziona Amazon S3 V2 come Tipo di origine.
- Seleziona Casella come Tipo di log.
- Fai clic su Avanti.
- Specifica i valori per i seguenti parametri di input:
- URI S3: l'URI del bucket (il formato deve essere
s3://box-collaboration-logs/box/collaboration/
). Sostituiscibox-collaboration-logs
: utilizza il nome effettivo del bucket. - Opzioni di eliminazione dell'origine: seleziona l'opzione di eliminazione in base alle tue preferenze.
- Età massima del file: includi i file modificati nell'ultimo numero di giorni. Il valore predefinito è 180 giorni.
- ID chiave di accesso: chiave di accesso utente con accesso al bucket S3.
- Chiave di accesso segreta: chiave segreta dell'utente con accesso al bucket S3.
- Spazio dei nomi dell'asset: lo spazio dei nomi dell'asset.
- Etichette di importazione: l'etichetta da applicare agli eventi di questo feed.
- URI S3: l'URI del bucket (il formato deve essere
- Fai clic su Avanti.
- Controlla la nuova configurazione del feed nella schermata Finalizza e poi fai clic su Invia.
Tabella di mappatura UDM
Campo log | Mappatura UDM | Logic |
---|---|---|
additional_details.ekm_id | additional.fields | Valore estratto da additional_details.ekm_id |
additional_details.service_id | additional.fields | Valore estratto da additional_details.service_id |
additional_details.service_name | additional.fields | Valore estratto da additional_details.service_name |
additional_details.shared_link_id | additional.fields | Valore estratto da additional_details.shared_link_id |
additional_details.size | target.file.size | Valore estratto da additional_details.size |
additional_details.version_id | additional.fields | Valore estratto da additional_details.version_id |
created_at | metadata.event_timestamp | Valore tratto da created_at |
created_by.id | principal.user.userid | Valore tratto da created_by.id |
created_by.login | principal.user.email_addresses | Valore tratto da created_by.login |
created_by.name | principal.user.user_display_name | Valore tratto da created_by.name |
event_id | metadata.product_log_id | Valore estratto da event_id |
event_type | metadata.product_event_type | Valore estratto da event_type |
ip_address | principal.ip | Valore tratto da ip_address |
source.item_id | target.file.product_object_id | Valore tratto da source.item_id |
source.item_name | target.file.full_path | Valore tratto da source.item_name |
source.item_type | Non mappato | |
source.login | target.user.email_addresses | Valore tratto da source.login |
source.name | target.user.user_display_name | Valore tratto da source.name |
source.owned_by.id | target.user.userid | Valore estratto da source.owned_by.id |
source.owned_by.login | target.user.email_addresses | Valore tratto da source.owned_by.login |
source.owned_by.name | target.user.user_display_name | Valore tratto da source.owned_by.name |
source.parent.id | Non mappato | |
source.parent.name | Non mappato | |
source.parent.type | Non mappato | |
source.type | Non mappato | |
tipo | metadata.log_type | Valore tratto dal tipo |
metadata.vendor_name | Valore hardcoded | |
metadata.product_name | Valore hardcoded | |
security_result.action | Derivato da event_type. Se event_type è FAILED_LOGIN, BLOCK; se event_type è USER_LOGIN, ALLOW; altrimenti UNSPECIFIED. | |
extensions.auth.type | Derivato da event_type. Se event_type è USER_LOGIN o ADMIN_LOGIN, allora MACHINE, altrimenti UNSPECIFIED. | |
extensions.auth.mechanism | Derivato da event_type. Se event_type è USER_LOGIN o ADMIN_LOGIN, USERNAME_PASSWORD, altrimenti UNSPECIFIED. |
Hai bisogno di ulteriore assistenza? Ricevi risposte dai membri della community e dai professionisti di Google SecOps.