Raccogli i log di Oracle NetSuite - NetSuite Applications Suite
Questo documento spiega come importare i log di Oracle NetSuite - NetSuite Applications Suite in Google Security Operations utilizzando Google Cloud Storage V2.
Oracle NetSuite è una piattaforma di pianificazione delle risorse aziendali (ERP) basata su cloud che fornisce funzionalità complete di gestione aziendale, tra cui gestione finanziaria, gestione dei rapporti con i clienti (CRM), e-commerce e gestione dell'inventario. NetSuite genera audit log estesi, tra cui tracce di accesso degli utenti, note di sistema che monitorano le modifiche ai record e log di accesso alle API che possono essere recuperati tramite l'API REST SuiteQL per il monitoraggio della sicurezza e la conformità.
Prima di iniziare
Assicurati di soddisfare i seguenti prerequisiti:
- Un'istanza Google SecOps
- Un progetto GCP con le API Cloud Storage, Cloud Run, Pub/Sub e Cloud Scheduler abilitate
- Autorizzazioni per creare e gestire bucket GCS
- Autorizzazioni per gestire le policy IAM sui bucket GCS
- Autorizzazioni per creare servizi Cloud Run, argomenti Pub/Sub e job Cloud Scheduler
- Un account NetSuite con accesso amministrativo
- Servizi web REST di NetSuite abilitati
- Autorizzazioni per creare record di integrazione e token di accesso in NetSuite
Configurare l'accesso all'API NetSuite
Per abilitare la raccolta dei log tramite l'API REST SuiteQL, devi abilitare i servizi web REST, creare un record di integrazione e generare le credenziali di autenticazione basata su token (TBA) in NetSuite.
Abilita le funzionalità NetSuite richieste
- Accedi al tuo account NetSuite come amministratore.
- Vai a Setup > Company > Enable Features.
- Fai clic sulla scheda SuiteCloud.
- Nella sezione SuiteScript, seleziona le seguenti caselle:
- Client SuiteScript
- Server SuiteScript
- Nella sezione SuiteTalk (servizi web), seleziona la seguente casella:
- Servizi web REST
- Nella sezione Gestisci autenticazione, seleziona la casella Autenticazione basata su token.
- Fai clic su Accetto nella pagina Termini di servizio di SuiteCloud.
- Fai clic su Salva.
Crea un record di integrazione
- In NetSuite, vai a Setup (Configurazione) > Integration (Integrazione) > Manage Integrations (Gestisci integrazioni) > New (Nuova).
- Nel campo Nome, inserisci
Google SecOps Integration. - Nel campo Descrizione, inserisci
Integration for Google Security Operations log collection. - Nel campo Stato, lascia selezionata l'opzione predefinita Abilitato.
- Fai clic sulla scheda Authentication (Autenticazione).
- Nella sezione Autenticazione basata su token, seleziona la casella Autenticazione basata su token.
- Lascia deselezionata la casella TBA: Authorization Flow (TBA: Authorization Flow).
- Seleziona la casella TBA: ISSUETOKEN ENDPOINT.
- Fai clic su Salva.
Nella pagina di conferma, copia e salva la chiave utente/Client ID e il Consumer Secret/Client Secret.
Creare un ruolo personalizzato per l'accesso API
- Vai a Setup (Configurazione) > Users/Roles (Utenti/Ruoli) > Manage Roles (Gestisci ruoli) > New (Nuovo).
- Nel campo Nome, inserisci
Google SecOps API Role. - Nel campo ID, inserisci
google_secops_api_role. - Fai clic sulla scheda secondaria Autorizzazioni.
- Fai clic sulla scheda secondaria Configurazione.
- Aggiungi le seguenti autorizzazioni con livello di accesso Completo:
- Accedere utilizzando i token di accesso
- Token di accesso utente
- Servizi web REST
- Fai clic sulla sottoscheda Report.
- Aggiungi le seguenti autorizzazioni con il livello di accesso Visualizza:
- SuiteAnalytics Workbook
- Fai clic sulla sottoscheda Elenchi.
- Aggiungi le seguenti autorizzazioni con il livello di accesso Visualizza:
- Audit trail degli accessi
- Fai clic su Salva.
Assegnare il ruolo a un utente
- Vai a Lists (Elenchi) > Employees (Dipendenti) > Employees (Dipendenti).
- Seleziona l'account utente da utilizzare per l'integrazione (o crea un nuovo utente di integrazione dedicato).
- Fai clic su Modifica.
- Fai clic sulla scheda Accesso.
- Nella sezione Ruoli, fai clic su Aggiungi.
- Seleziona Ruolo API Google SecOps dall'elenco a discesa.
- Fai clic su Salva.
Crea un token di accesso
- Accedi a NetSuite come utente a cui è stato assegnato il ruolo API Google SecOps.
- Vai a Configurazione > Utenti/Ruoli > Token di accesso > Nuovo.
- Nella pagina Token di accesso:
- Nell'elenco a discesa Nome applicazione, seleziona Integrazione di Google SecOps.
- Nell'elenco a discesa Utente, seleziona l'account utente a cui è stato assegnato il ruolo API Google SecOps.
- Nell'elenco a discesa Ruolo, seleziona Ruolo API Google SecOps.
- Il campo Nome token viene compilato automaticamente. Se preferisci, puoi modificarlo.
- Fai clic su Salva.
Nella pagina di conferma, copia e salva l'ID token e il segreto del token.
Trovare l'ID account NetSuite
- In NetSuite, vai a Configurazione > Azienda > Informazioni sull'azienda.
- Individua il campo ID account (visualizzato sotto l'impostazione Fuso orario).
- Copia e salva il tuo ID account (ad esempio,
1234567o1234567_SB1per gli account sandbox).
Verifica le autorizzazioni
Per verificare che l'account disponga delle autorizzazioni richieste:
- Accedi a NetSuite con l'utente a cui è stato assegnato il ruolo API Google SecOps.
- Vai a Configurazione > Utenti/Ruoli > Visualizza audit trail di accesso.
- Se riesci a visualizzare la pagina Traccia audit degli accessi, l'account dispone delle autorizzazioni necessarie.
- Se non riesci a visualizzare questa opzione, contatta l'amministratore di NetSuite per concedere l'autorizzazione Traccia di audit accesso nella sottoscheda Elenchi.
Testare l'accesso API
Testa le tue credenziali prima di procedere con l'integrazione:
# Replace with your actual values ACCOUNT_ID="your-account-id" # Replace underscores with hyphens in the account ID for the URL # For example: 1234567_SB1 becomes 1234567-sb1 URL_ACCOUNT_ID=$(echo "$ACCOUNT_ID" | tr '_' '-' | tr '[:upper:]' '[:lower:]') CONSUMER_KEY="your-consumer-key" CONSUMER_SECRET="your-consumer-secret" TOKEN_ID="your-token-id" TOKEN_SECRET="your-token-secret" # Test SuiteQL API access using OAuth 1.0 TBA # Note: This example requires the oauth1 CLI tool or Postman. # Use the following endpoint and headers to verify connectivity: # POST https://${URL_ACCOUNT_ID}.suitetalk.api.netsuite.com/services/rest/query/v1/suiteql?limit=5 # Headers: # Authorization: OAuth (with consumer key, token, HMAC-SHA256 signature) # Content-Type: application/json # Prefer: transient # Body: {"q": "SELECT id, date, status, user, emailaddress FROM LoginAudit ORDER BY date DESC"}
Una risposta positiva restituisce un oggetto JSON contenente i record LoginAudit.
Crea un bucket Google Cloud Storage
- Vai alla console Google Cloud.
- Seleziona il tuo progetto o creane uno nuovo.
- Nel menu di navigazione, vai a Cloud Storage > Bucket.
- Fai clic su Crea bucket.
Fornisci i seguenti dettagli di configurazione:
Impostazione Valore Assegna un nome al bucket Inserisci un nome globalmente univoco (ad esempio netsuite-audit-logs)Tipo di località Scegli in base alle tue esigenze (regione singola, a due regioni, multiregionale) Località Seleziona la posizione (ad esempio, us-central1).Classe di archiviazione Standard (consigliato per i log a cui si accede di frequente) Controllo dell'accesso Uniforme (consigliato) Strumenti di protezione (Facoltativo) Abilita il controllo delle versioni degli oggetti o la policy di conservazione Fai clic su Crea.
Crea un account di servizio per la funzione Cloud Run
La funzione Cloud Run richiede un account di servizio con autorizzazioni di scrittura nel bucket GCS e di invocazione da parte di Pub/Sub.
Crea service account
- Nella console Google Cloud, vai a IAM e amministrazione > Service account.
- Fai clic su Crea account di servizio.
- Fornisci i seguenti dettagli di configurazione:
- Nome del service account: inserisci
netsuite-audit-collector-sa - Descrizione service account: inserisci
Service account for Cloud Run function to collect NetSuite audit logs
- Nome del service account: inserisci
- Fai clic su Crea e continua.
- Nella sezione Concedi a questo account di servizio l'accesso al progetto, aggiungi i seguenti ruoli:
- Fai clic su Seleziona un ruolo.
- Cerca e seleziona Storage Object Admin.
- Fai clic su + Aggiungi un altro ruolo.
- Cerca e seleziona Cloud Run Invoker.
- Fai clic su + Aggiungi un altro ruolo.
- Cerca e seleziona Cloud Functions Invoker.
- Fai clic su Continua.
- Fai clic su Fine.
Questi ruoli sono obbligatori per:
- Storage Object Admin: scrive i log nel bucket GCS e gestisce i file di stato
- Cloud Run Invoker: consente a Pub/Sub di richiamare la funzione
- Cloud Functions Invoker: consente la chiamata della funzione
Concedi autorizzazioni IAM sul bucket GCS
- Vai a Cloud Storage > Bucket.
- Fai clic sul nome del bucket (
netsuite-audit-logs). - Vai alla scheda Autorizzazioni.
- Fai clic su Concedi l'accesso.
- Fornisci i seguenti dettagli di configurazione:
- Aggiungi entità: inserisci l'email del account di servizio (
netsuite-audit-collector-sa@PROJECT_ID.iam.gserviceaccount.com). - Assegna i ruoli: seleziona Storage Object Admin.
- Aggiungi entità: inserisci l'email del account di servizio (
- Fai clic su Salva.
Crea argomento Pub/Sub
- Nella console Google Cloud, vai a Pub/Sub > Argomenti.
- Fai clic su Crea argomento.
- Fornisci i seguenti dettagli di configurazione:
- ID argomento: inserisci
netsuite-audit-trigger - Lascia invariate le altre impostazioni predefinite.
- ID argomento: inserisci
- Fai clic su Crea.
Crea una funzione Cloud Run per raccogliere i log
La funzione Cloud Run verrà attivata dai messaggi Pub/Sub di Cloud Scheduler per recuperare i log dall'API REST SuiteQL di NetSuite e scriverli in GCS.
- Nella console Google Cloud, vai a Cloud Run.
- Fai clic su Crea servizio.
- Seleziona Funzione (utilizza la modifica in linea per creare una funzione).
Nella sezione Configura, fornisci i seguenti dettagli di configurazione:
Impostazione Valore Nome servizio netsuite-audit-collectorRegione Seleziona la regione corrispondente al tuo bucket GCS (ad esempio, us-central1)Tempo di esecuzione Seleziona Python 3.12 o versioni successive Nella sezione Trigger (facoltativo):
- Fai clic su + Aggiungi trigger.
- Seleziona Cloud Pub/Sub.
- In Seleziona un argomento Cloud Pub/Sub, scegli
netsuite-audit-trigger. - Fai clic su Salva.
Nella sezione Autenticazione:
- Seleziona Richiedi autenticazione.
- Controlla Identity and Access Management (IAM).
Scorri verso il basso ed espandi Container, networking, sicurezza.
Vai alla scheda Sicurezza:
- Service account: seleziona
netsuite-audit-collector-sa.
- Service account: seleziona
Vai alla scheda Container:
- Fai clic su Variabili e secret.
- Fai clic su + Aggiungi variabile per ogni variabile di ambiente:
Nome variabile Valore di esempio Descrizione GCS_BUCKETnetsuite-audit-logsNome bucket GCS GCS_PREFIXnetsuite-auditPrefisso per i file di log STATE_KEYnetsuite-audit/state.jsonPercorso file di stato NS_ACCOUNT_ID1234567ID account NetSuite NS_CONSUMER_KEYyour-consumer-keyChiave utente dal record di integrazione NS_CONSUMER_SECRETyour-consumer-secretSecret consumer dal record di integrazione NS_TOKEN_IDyour-token-idID token dal token di accesso NS_TOKEN_SECRETyour-token-secretSecret del token dal token di accesso MAX_RECORDS10000Numero massimo di record per esecuzione PAGE_SIZE1000Record per pagina SuiteQL LOOKBACK_HOURS24Periodo di riferimento iniziale Nella sezione Variabili e secret, scorri verso il basso fino a Richieste:
- Timeout richiesta: inserisci
600secondi (10 minuti)
- Timeout richiesta: inserisci
Vai alla scheda Impostazioni:
- Nella sezione Risorse:
- Memoria: seleziona 512 MiB o un valore superiore.
- CPU: seleziona 1
- Nella sezione Risorse:
Nella sezione Scalabilità della revisione:
- Numero minimo di istanze: inserisci
0 - Numero massimo di istanze: inserisci
100
- Numero minimo di istanze: inserisci
Fai clic su Crea.
Attendi la creazione del servizio (1-2 minuti).
Dopo aver creato il servizio, si aprirà automaticamente l'editor di codice incorporato.
Aggiungi codice per la funzione
- Inserisci main nel campo Entry point (Punto di ingresso).
Nell'editor di codice incorporato, crea due file:
- main.py:
import functions_framework from google.cloud import storage import json import os import urllib3 import hashlib import hmac import base64 import time import secrets import urllib.parse from datetime import datetime, timezone, timedelta # Initialize HTTP client with timeouts http = urllib3.PoolManager( timeout=urllib3.Timeout(connect=10.0, read=60.0), retries=False, ) # Initialize Storage client storage_client = storage.Client() # Environment variables GCS_BUCKET = os.environ.get('GCS_BUCKET') GCS_PREFIX = os.environ.get('GCS_PREFIX', 'netsuite-audit') STATE_KEY = os.environ.get('STATE_KEY', 'netsuite-audit/state.json') NS_ACCOUNT_ID = os.environ.get('NS_ACCOUNT_ID') NS_CONSUMER_KEY = os.environ.get('NS_CONSUMER_KEY') NS_CONSUMER_SECRET = os.environ.get('NS_CONSUMER_SECRET') NS_TOKEN_ID = os.environ.get('NS_TOKEN_ID') NS_TOKEN_SECRET = os.environ.get('NS_TOKEN_SECRET') MAX_RECORDS = int(os.environ.get('MAX_RECORDS', '10000')) PAGE_SIZE = int(os.environ.get('PAGE_SIZE', '1000')) LOOKBACK_HOURS = int(os.environ.get('LOOKBACK_HOURS', '24')) def get_netsuite_base_url(account_id): """Build the NetSuite REST API base URL from the account ID.""" url_account = account_id.replace('_', '-').lower() return f"https://{url_account}.suitetalk.api.netsuite.com" def generate_oauth_header(method, url, account_id, consumer_key, consumer_secret, token_id, token_secret): """Generate OAuth 1.0 Authorization header using HMAC-SHA256.""" timestamp = str(int(time.time())) nonce = secrets.token_hex(16) # Parse URL to separate base URL and query parameters parsed = urllib.parse.urlparse(url) base_url = f"{parsed.scheme}://{parsed.netloc}{parsed.path}" query_params = urllib.parse.parse_qs(parsed.query, keep_blank_values=True) # Build parameter string (OAuth params + query params) params = { 'oauth_consumer_key': consumer_key, 'oauth_token': token_id, 'oauth_nonce': nonce, 'oauth_timestamp': timestamp, 'oauth_signature_method': 'HMAC-SHA256', 'oauth_version': '1.0', } for key, values in query_params.items(): params[key] = values[0] # Sort parameters and create parameter string sorted_params = sorted(params.items()) param_string = '&'.join( f"{urllib.parse.quote(k, safe='')}={urllib.parse.quote(v, safe='')}" for k, v in sorted_params ) # Create signature base string signature_base = ( f"{method.upper()}&" f"{urllib.parse.quote(base_url, safe='')}&" f"{urllib.parse.quote(param_string, safe='')}" ) # Create signing key signing_key = ( f"{urllib.parse.quote(consumer_secret, safe='')}&" f"{urllib.parse.quote(token_secret, safe='')}" ) # Generate HMAC-SHA256 signature signature = base64.b64encode( hmac.new( signing_key.encode('utf-8'), signature_base.encode('utf-8'), hashlib.sha256 ).digest() ).decode('utf-8') # Build realm from account ID realm = account_id.replace('-', '_').upper() # Build Authorization header auth_header = ( f'OAuth realm="{realm}",' f'oauth_consumer_key="{consumer_key}",' f'oauth_token="{token_id}",' f'oauth_nonce="{nonce}",' f'oauth_timestamp="{timestamp}",' f'oauth_signature_method="HMAC-SHA256",' f'oauth_version="1.0",' f'oauth_signature="{urllib.parse.quote(signature, safe="")}"' ) return auth_header @functions_framework.cloud_event def main(cloud_event): """ Cloud Run function triggered by Pub/Sub to fetch NetSuite LoginAudit logs via SuiteQL and write to GCS. """ if not all([GCS_BUCKET, NS_ACCOUNT_ID, NS_CONSUMER_KEY, NS_CONSUMER_SECRET, NS_TOKEN_ID, NS_TOKEN_SECRET]): print('Error: Missing required environment variables') return try: bucket = storage_client.bucket(GCS_BUCKET) state = load_state(bucket) now = datetime.now(timezone.utc) if isinstance(state, dict) and state.get('last_event_time'): try: last_val = state['last_event_time'] if last_val.endswith('Z'): last_val = last_val[:-1] + '+00:00' last_time = datetime.fromisoformat(last_val) last_time = last_time - timedelta(minutes=2) except Exception as e: print(f"Warning: Could not parse last_event_time: {e}") last_time = now - timedelta(hours=LOOKBACK_HOURS) else: last_time = now - timedelta(hours=LOOKBACK_HOURS) print(f"Fetching logs from {last_time.isoformat()} to {now.isoformat()}") records, newest_time = fetch_login_audit(last_time, now) if not records: print("No new log records found.") save_state(bucket, now.isoformat()) return timestamp = now.strftime('%Y%m%d_%H%M%S') object_key = f"{GCS_PREFIX}/netsuite_audit_{timestamp}.ndjson" blob = bucket.blob(object_key) ndjson = '\n'.join( [json.dumps(r, ensure_ascii=False, default=str) for r in records] ) + '\n' blob.upload_from_string(ndjson, content_type='application/x-ndjson') print(f"Wrote {len(records)} records to gs://{GCS_BUCKET}/{object_key}") if newest_time: save_state(bucket, newest_time) else: save_state(bucket, now.isoformat()) print(f"Successfully processed {len(records)} records") except Exception as e: print(f'Error processing logs: {str(e)}') raise def fetch_login_audit(start_time, end_time): """ Fetch LoginAudit records from NetSuite SuiteQL API with pagination. Returns: Tuple of (records list, newest_event_time ISO string) """ base_url = get_netsuite_base_url(NS_ACCOUNT_ID) suiteql_endpoint = f"{base_url}/services/rest/query/v1/suiteql" start_str = start_time.strftime('%Y-%m-%d %H:%M:%S') end_str = end_time.strftime('%Y-%m-%d %H:%M:%S') query = ( "SELECT id, date, status, user, role, emailaddress, " "ipaddress, useragent, detail, requesturi, " "oauthaccesstokenname, oauthappname " "FROM LoginAudit " f"WHERE date BETWEEN TO_DATE('{start_str}', 'YYYY-MM-DD HH24:MI:SS') " f"AND TO_DATE('{end_str}', 'YYYY-MM-DD HH24:MI:SS') " "ORDER BY date ASC" ) records = [] newest_time = None offset = 0 backoff = 1.0 while True: if len(records) >= MAX_RECORDS: print(f"Reached max_records limit ({MAX_RECORDS})") break remaining = min(PAGE_SIZE, MAX_RECORDS - len(records)) url = f"{suiteql_endpoint}?limit={remaining}&offset={offset}" auth_header = generate_oauth_header( 'POST', url, NS_ACCOUNT_ID, NS_CONSUMER_KEY, NS_CONSUMER_SECRET, NS_TOKEN_ID, NS_TOKEN_SECRET ) headers = { 'Authorization': auth_header, 'Content-Type': 'application/json', 'Prefer': 'transient', 'User-Agent': 'GoogleSecOps-NetSuiteCollector/1.0', } body = json.dumps({'q': query}).encode('utf-8') try: response = http.request('POST', url, headers=headers, body=body) if response.status == 429: retry_after = int( response.headers.get('Retry-After', str(int(backoff))) ) print(f"Rate limited (429). Retrying after {retry_after}s...") time.sleep(retry_after) backoff = min(backoff * 2, 60.0) continue backoff = 1.0 if response.status != 200: print(f"HTTP Error: {response.status}") response_text = response.data.decode('utf-8') print(f"Response body: {response_text}") return records, newest_time data = json.loads(response.data.decode('utf-8')) page_results = data.get('items', []) if not page_results: print("No more results (empty page)") break page_num = (offset // PAGE_SIZE) + 1 print(f"Page {page_num}: Retrieved {len(page_results)} records") records.extend(page_results) for event in page_results: try: event_time = event.get('date') if event_time: if newest_time is None or event_time > newest_time: newest_time = event_time except Exception as e: print(f"Warning: Could not parse event time: {e}") has_more = data.get('hasMore', False) if not has_more: print("Reached last page (hasMore=false)") break offset += len(page_results) except Exception as e: print(f"Error fetching logs: {e}") return records, newest_time print(f"Retrieved {len(records)} total records") return records, newest_time def load_state(bucket): """Load state from GCS.""" try: blob = bucket.blob(STATE_KEY) if blob.exists(): return json.loads(blob.download_as_text()) except Exception as e: print(f"Warning: Could not load state: {e}") return {} def save_state(bucket, last_event_time_iso): """Save the last event timestamp to GCS state file.""" try: state = { 'last_event_time': last_event_time_iso, 'last_run': datetime.now(timezone.utc).isoformat() } blob = bucket.blob(STATE_KEY) blob.upload_from_string( json.dumps(state, indent=2), content_type='application/json' ) print(f"Saved state: last_event_time={last_event_time_iso}") except Exception as e: print(f"Warning: Could not save state: {e}")- requirements.txt:
functions-framework==3.* google-cloud-storage==2.* urllib3>=2.0.0Fai clic su Esegui il deployment per salvare la funzione ed eseguirne il deployment.
Attendi il completamento del deployment (2-3 minuti).
Crea job Cloud Scheduler
Cloud Scheduler pubblicherà messaggi nell'argomento Pub/Sub a intervalli regolari, attivando la funzione Cloud Run.
- Nella console Google Cloud, vai a Cloud Scheduler.
- Fai clic su Crea job.
Fornisci i seguenti dettagli di configurazione:
Impostazione Valore Nome netsuite-audit-collector-hourlyRegione Seleziona la stessa regione della funzione Cloud Run Frequenza 0 * * * *(ogni ora, allo scoccare dell'ora)Fuso orario Seleziona il fuso orario (consigliato UTC) Tipo di target Pub/Sub Argomento Seleziona netsuite-audit-triggerCorpo del messaggio {}(oggetto JSON vuoto)Fai clic su Crea.
Opzioni di frequenza di pianificazione
Scegli la frequenza in base al volume dei log e ai requisiti di latenza:
| Frequenza | Espressione cron | Caso d'uso |
|---|---|---|
| Ogni 5 minuti | */5 * * * * |
Volume elevato, bassa latenza |
| Ogni 15 minuti | */15 * * * * |
Volume medio |
| Ogni ora | 0 * * * * |
Standard (consigliato) |
| Ogni 6 ore | 0 */6 * * * |
Volume basso, elaborazione batch |
| Ogni giorno | 0 0 * * * |
Raccolta dei dati storici |
Testare l'integrazione
- Nella console Cloud Scheduler, individua il tuo job (
netsuite-audit-collector-hourly). - Fai clic su Forza esecuzione per attivare il job manualmente.
- Attendi alcuni secondi.
- Vai a Cloud Run > Servizi.
- Fai clic su
netsuite-audit-collector. - Fai clic sulla scheda Log.
Verifica che la funzione sia stata eseguita correttamente. Cerca:
Fetching logs from YYYY-MM-DDTHH:MM:SS+00:00 to YYYY-MM-DDTHH:MM:SS+00:00 Page 1: Retrieved X records Wrote X records to gs://netsuite-audit-logs/netsuite-audit/netsuite_audit_YYYYMMDD_HHMMSS.ndjson Successfully processed X recordsVai a Cloud Storage > Bucket.
Fai clic su
netsuite-audit-logs.Vai alla cartella
netsuite-audit/.Verifica che sia stato creato un nuovo file
.ndjsoncon il timestamp corrente.
Se nei log vengono visualizzati errori:
- HTTP 401: verifica che le credenziali OAuth (
NS_CONSUMER_KEY,NS_CONSUMER_SECRET,NS_TOKEN_ID,NS_TOKEN_SECRET) e le variabili di ambienteNS_ACCOUNT_IDsiano corrette - HTTP 403: verifica che il ruolo NetSuite disponga delle autorizzazioni richieste (servizi web REST, traccia di audit di accesso, cartella di lavoro SuiteAnalytics)
- HTTP 429: limitazione di frequenza. La funzione riproverà automaticamente con backoff esponenziale
- Variabili di ambiente mancanti: verifica che tutte le variabili richieste siano impostate nella configurazione della funzione Cloud Run
Recuperare il account di servizio Google SecOps
- Vai a Impostazioni SIEM > Feed.
- Fai clic su Aggiungi nuovo feed di notizie.
- Fai clic su Configura un singolo feed.
- Nel campo Nome feed, inserisci un nome per il feed (ad esempio,
NetSuite Audit Logs). - Seleziona Google Cloud Storage V2 come Tipo di origine.
- Seleziona Oracle NetSuite - NetSuite Applications Suite come Tipo di log.
Fai clic su Ottieni service account. Verrà visualizzato un indirizzo email del account di servizio univoco. Ad esempio:
chronicle-12345678@chronicle-gcp-prod.iam.gserviceaccount.comCopia questo indirizzo email per utilizzarlo nel passaggio successivo.
Fai clic su Avanti.
Specifica i valori per i seguenti parametri di input:
URL del bucket di archiviazione: inserisci l'URI del bucket GCS con il percorso del prefisso:
gs://netsuite-audit-logs/netsuite-audit/
- Opzione di eliminazione dell'origine: seleziona l'opzione di eliminazione in base alle tue preferenze:
- Mai: non elimina mai i file dopo i trasferimenti (opzione consigliata per i test).
- Elimina file trasferiti: elimina i file dopo il trasferimento riuscito.
- Elimina file trasferiti e directory vuote: elimina i file e le directory vuote dopo il trasferimento riuscito.
- Età massima dei file: includi i file modificati negli ultimi giorni (il valore predefinito è 180 giorni)
- Spazio dei nomi dell'asset: lo spazio dei nomi dell'asset
- Etichette di importazione: l'etichetta da applicare agli eventi di questo feed
Fai clic su Avanti.
Controlla la nuova configurazione del feed nella schermata Finalizza e poi fai clic su Invia.
Concedi le autorizzazioni IAM al account di servizio Google SecOps
Il account di servizio Google SecOps deve avere il ruolo Visualizzatore oggetti Storage nel tuo bucket GCS.
- Vai a Cloud Storage > Bucket.
- Fai clic su
netsuite-audit-logs. - Vai alla scheda Autorizzazioni.
- Fai clic su Concedi l'accesso.
- Fornisci i seguenti dettagli di configurazione:
- Aggiungi entità: incolla l'indirizzo email del account di servizio Google SecOps
- Assegna i ruoli: seleziona Storage Object Viewer
Fai clic su Salva.
Limiti di frequenza delle richieste API NetSuite
L'API NetSuite presenta i seguenti limiti di concorrenza e frequenza:
| Tipo di limite | Valore predefinito | Note |
|---|---|---|
| Richieste in parallelo | 15 richieste | Valido per le richieste API SOAP e API REST combinate per account |
| Risultati della query SuiteQL | Massimo 100.000 righe | Numero massimo di righe restituite per query SuiteQL |
| Oggetti per richiesta | Massimo 1000 oggetti | Numero massimo di oggetti restituiti per richiesta API |
La funzione Cloud Run gestisce automaticamente la limitazione di frequenza con backoff esponenziale. Se riscontri errori di limite di frequenza persistenti (HTTP 429), contatta l'assistenza NetSuite per aumentare i limiti API o modificare la frequenza di Cloud Scheduler.
Tabella di mappatura UDM
| Campo log | Mappatura UDM | Logica |
|---|---|---|
| utente | extensions.auth.type | Tipo di meccanismo di autenticazione utilizzato |
| data | metadata.event_timestamp | Timestamp in cui si è verificato l'evento |
| event_type | metadata.event_type | Tipo di evento (ad es. USER_LOGIN, NETWORK_CONNECTION) |
| security_result | security_result | Dettagli sul risultato di sicurezza dell'evento |
| oauthaccesstokenname | security_result.about.resource.attribute.labels | Etichette coppia chiave-valore che descrivono gli attributi della risorsa coinvolta nel risultato di sicurezza |
| secchallenge | security_result.about.resource.attribute.labels | |
| stato | security_result.summary | Descrizione riepilogativa del risultato di sicurezza |
| oauthappname | target.application | Nome dell'applicazione di destinazione |
| useragent | target.application | |
| ipaddress | target.ip | Indirizzo IP del target |
| requesturi | target.url | URL della risorsa di destinazione |
| emailaddress | target.user.email_addresses | Indirizzi email associati all'utente di destinazione |
| ruolo | target.user.role_name | Nome del ruolo assegnato all'utente di destinazione |
| utente | target.user.userid | Identificatore univoco dell'utente di destinazione |
Log delle modifiche
Visualizza il log delle modifiche per questo parser
Hai bisogno di ulteriore assistenza? Ricevi risposte dai membri della community e dai professionisti di Google SecOps.