Tenable-Audit-Logs erfassen

Unterstützt in:

In diesem Dokument wird beschrieben, wie Sie Tenable-Audit-Logs mit Cloud Storage V2 in Google Security Operations aufnehmen.

Tenable Vulnerability Management (früher Tenable.io) ist eine cloudbasierte Plattform zur Verwaltung von Sicherheitslücken (cloud.tenable.com), in deren Aktivitätsprotokoll Nutzerauthentifizierung, API-Zugriff, Konfigurationsänderungen und administrative Aktionen aufgezeichnet werden. Die Tenable Vulnerability Management REST API bietet programmatischen Zugriff auf diese Aktivitätslog-Ereignisse.

Hinweis

Prüfen Sie, ob folgende Voraussetzungen erfüllt sind:

  • Eine Google SecOps-Instanz
  • Ein Google Cloud -Projekt mit aktivierter Cloud Storage API
  • Berechtigungen zum Erstellen und Verwalten von Cloud Storage-Buckets
  • Berechtigungen zum Verwalten von IAM-Richtlinien (Identity and Access Management) für Cloud Storage-Buckets
  • Berechtigungen zum Erstellen von Cloud Run-Diensten, Pub/Sub-Themen und Cloud Scheduler-Jobs
  • Privilegierter Zugriff auf Tenable Vulnerability Management (cloud.tenable.com) mit der Rolle Administrator
  • Tenable Vulnerability Management-API-Schlüssel (Zugriffsschlüssel und geheimer Schlüssel), die in einem Nutzerkonto mit der Rolle Administrator generiert wurden

Cloud Storage-Bucket erstellen

  1. Gehen Sie zur Google Cloud Console.
  2. Wählen Sie Ihr Projekt aus oder erstellen Sie ein neues.
  3. Rufen Sie im Navigationsmenü Cloud Storage > Buckets auf.
  4. Klicken Sie auf Bucket erstellen.
  5. Geben Sie die folgenden Konfigurationsdetails an:

    Einstellung Wert
    Bucket benennen Geben Sie einen global eindeutigen Namen ein, z. B. tenable-audit-logs.
    Standorttyp Wählen Sie die Option aus, die am besten zu Ihren Anforderungen passt (Region, Dual-Region, Multi-Region).
    Standort Wählen Sie den Speicherort aus, z. B. us-central1.
    Speicherklasse Standard (empfohlen für Logs, auf die häufig zugegriffen wird)
    Zugriffskontrolle Einheitlich (empfohlen)
    Schutztools Optional: Objektversionierung oder Aufbewahrungsrichtlinie aktivieren
  6. Klicken Sie auf Erstellen.

Tenable Vulnerability Management API-Anmeldedaten erfassen

API-Schlüssel generieren

  1. Melden Sie sich in Tenable Vulnerability Management an.
  2. Klicken Sie auf einer beliebigen Seite oben rechts auf den blauen Nutzerkreis und dann auf Mein Profil. Die Seite Mein Konto wird angezeigt.
  3. Rufen Sie den Tab API-Schlüssel auf.
  4. Klicken Sie auf Generieren. Das Fenster API-Schlüssel generieren wird mit einer Warnung angezeigt.

    „Achtung: Beim Generieren von Schlüsseln werden alle vorhandenen API-Schlüssel für dieses Nutzerkonto ersetzt, einschließlich der Schlüssel, die bereits von anderen Integrationen verwendet werden. Verwenden Sie ein separates Nutzerkonto für diese Integration oder aktualisieren Sie jede Anwendung, die die vorherigen Schlüssel verwendet hat.“

  5. Prüfen Sie die Warnung und klicken Sie auf Generieren.

  6. Kopieren Sie die folgenden Details und speichern Sie sie an einem sicheren Ort:

    • Zugriffsschlüssel: Der API-Zugriffsschlüssel
    • Geheimer Schlüssel: Der geheime API-Schlüssel

API-Zugriff prüfen

  • Testen Sie Ihre Anmeldedaten, bevor Sie mit der Integration fortfahren:

    # Replace with your actual credentials
    ACCESS_KEY="your-access-key"
    SECRET_KEY="your-secret-key"
    
    curl -s -H "X-ApiKeys: accessKey=${ACCESS_KEY};secretKey=${SECRET_KEY}" \
        "https://cloud.tenable.com/audit-log/v1/events?limit=1" | head -c 500
    

Berechtigungen prüfen

So prüfen Sie, ob das Konto die erforderlichen Berechtigungen hat:

  1. Melden Sie sich in Tenable Vulnerability Management an.
  2. Klicken Sie in der linken Navigationsleiste auf Einstellungen.
  3. Klicken Sie auf die Kachel Zugriffssteuerung.
  4. Klicken Sie auf den Tab Nutzer und dann auf das Nutzerkonto, das für diese Integration verwendet wird.
  5. Prüfen Sie, ob das Konto die Rolle Administrator hat. Für den Aktivitätsprotokoll-Endpunkt ist die Nutzerrolle „Administrator“ erforderlich. Keine benutzerdefinierte Rolle gewährt Zugriff auf das Aktivitätsprotokoll und für jede andere Rolle wird eine HTTP 403-Antwort zurückgegeben.

  6. Wenn Sie nicht über die erforderlichen Berechtigungen verfügen, wenden Sie sich an Ihren Tenable Vulnerability Management-Administrator.

Dienstkonto für die Cloud Run-Funktion erstellen

Für die Cloud Run-Funktion ist ein Dienstkonto mit Berechtigungen zum Schreiben in den Cloud Storage-Bucket und zum Aufrufen durch Pub/Sub erforderlich.

Erstellen Sie das Dienstkonto:

  1. Wechseln Sie in der GCP Console zu IAM und Verwaltung > Dienstkonten.
  2. Klicken Sie auf Dienstkonto erstellen.
  3. Geben Sie die folgenden Konfigurationsdetails an:
    • Name des Dienstkontos: Geben Sie tenable-audit-collector-sa ein.
    • Beschreibung des Dienstkontos: Geben Sie Service account for Cloud Run function to collect Tenable Audit logs ein.
  4. Klicken Sie auf Erstellen und fortfahren.
  5. Fügen Sie im Abschnitt Diesem Dienstkonto Zugriff auf das Projekt erteilen die folgenden Rollen hinzu:
    1. Klicken Sie auf Rolle auswählen.
    2. Suchen Sie nach Storage Object Admin und wählen Sie die Rolle aus.
    3. Klicken Sie auf + Weitere Rolle hinzufügen.
    4. Suchen Sie nach Cloud Run Invoker und wählen Sie die Rolle aus.
    5. Klicken Sie auf + Weitere Rolle hinzufügen.
    6. Suchen Sie nach Cloud Functions Invoker und wählen Sie die Rolle aus.
  6. Klicken Sie auf Weiter.
  7. Klicken Sie auf Fertig.

Diese Rollen sind für Folgendes erforderlich:

  • Storage-Objekt-Administrator: Schreibt Logs in den Cloud Storage-Bucket und verwaltet Statusdateien.
  • Cloud Run-Aufrufer: Ermöglicht Pub/Sub, die Funktion aufzurufen.
  • Cloud Functions-Invoker: Ermöglicht den Funktionsaufruf

IAM-Berechtigungen für den Cloud Storage-Bucket gewähren

Gewähren Sie dem Dienstkonto Schreibberechtigungen für den Cloud Storage-Bucket:

  1. Rufen Sie Cloud Storage > Buckets auf.
  2. Klicken Sie auf den Namen Ihres Buckets (z. B. tenable-audit-logs).
  3. Wechseln Sie zum Tab Berechtigungen.
  4. Klicken Sie auf Zugriff erlauben.
  5. Geben Sie die folgenden Konfigurationsdetails an:
    • Hauptkonten hinzufügen: Geben Sie die E-Mail-Adresse des Dienstkontos ein (z. B. tenable-audit-collector-sa@PROJECT_ID.iam.gserviceaccount.com).
    • Rollen zuweisen: Wählen Sie Storage Object Admin aus.
  6. Klicken Sie auf Speichern.

Pub/Sub-Thema erstellen

Erstellen Sie ein Pub/Sub-Thema, in dem Cloud Scheduler veröffentlicht und das von der Cloud Run-Funktion abonniert wird.

  1. Rufen Sie in der GCP Console Pub/Sub > Themen auf.
  2. Klicken Sie auf Thema erstellen.
  3. Geben Sie die folgenden Konfigurationsdetails an:
    • Themen-ID: Geben Sie tenable-audit-trigger ein.
    • Übernehmen Sie die anderen Einstellungen.
  4. Klicken Sie auf Erstellen.

Cloud Run-Funktion zum Erfassen von Logs erstellen

Die Cloud Run-Funktion wird durch Pub/Sub-Nachrichten von Cloud Scheduler ausgelöst, um Logs aus der Tenable Vulnerability Management REST API abzurufen und in Cloud Storage zu schreiben.

  1. Rufen Sie in der GCP Console Cloud Run auf.
  2. Klicken Sie auf Dienst erstellen.
  3. Wählen Sie Funktion aus, um eine Funktion mit einem Inline-Editor zu erstellen.
  4. Geben Sie im Abschnitt Konfigurieren die folgenden Konfigurationsdetails an:

    Einstellung Wert
    Dienstname tenable-audit-collector
    Region Wählen Sie die Region aus, die Ihrem Cloud Storage-Bucket entspricht (z. B. us-central1).
    Laufzeit Wählen Sie Python 3.12 oder höher aus.
  5. Im Abschnitt Trigger (optional):

    1. Klicken Sie auf + Trigger hinzufügen.
    2. Wählen Sie Cloud Pub/Sub aus.
    3. Wählen Sie unter Cloud Pub/Sub-Thema auswählen das Thema tenable-audit-trigger aus.
    4. Klicken Sie auf Speichern.
  6. Im Abschnitt Authentifizierung:

    1. Wählen Sie Authentifizierung erforderlich aus.
    2. Weitere Informationen finden Sie unter Identity and Access Management (IAM).
  7. Scrollen Sie nach unten und maximieren Sie Container, Netzwerk, Sicherheit.

  8. Rufen Sie den Tab Sicherheit auf:

    • Dienstkonto: Wählen Sie das Dienstkonto tenable-audit-collector-sa aus.
  9. Rufen Sie den Tab Container auf:

    1. Klicken Sie auf Variablen und Secrets.
    2. Klicken Sie für jede Umgebungsvariable auf + Variable hinzufügen:
    Variablenname Beispielwert Beschreibung
    GCS_BUCKET tenable-audit-logs Name des Cloud Storage-Buckets
    GCS_PREFIX tenable Präfix für Logdateien
    STATE_KEY tenable-state.json Statuspfad außerhalb des Log-Präfixes
    TENABLE_ACCESS_KEY your-access-key Tenable Vulnerability Management-Zugriffsschlüssel
    TENABLE_SECRET_KEY your-secret-key Secret-Schlüssel für Tenable Vulnerability Management
    MAX_RECORDS 5000 Maximale Anzahl von Datensätzen pro Ausführung
    PAGE_SIZE 1000 Einträge pro Seite
    LOOKBACK_HOURS 24 Anfänglicher Rückschauzeitraum
    OVERLAP_MINUTES 2 Minuten, die vor dem Wasserzeichen noch einmal gelesen werden, um spät indexierte Ereignisse zu erfassen
  10. Gehen Sie im Bereich Variablen und Secrets zu Anfragen:

    • Zeitlimit für die Anfrage: Geben Sie 600 Sekunden (10 Minuten) ein.
  11. Gehen Sie zum Tab Einstellungen:

    • Im Abschnitt Ressourcen:
      • Arbeitsspeicher: Wählen Sie 512 MiB oder höher aus.
      • CPU: Wählen Sie 1 aus.
  12. Im Abschnitt Versionsskalierung:

    • Mindestanzahl von Instanzen: Geben Sie 0 ein.
    • Maximale Anzahl von Instanzen: Geben Sie 100 ein (oder passen Sie den Wert an die erwartete Last an).
  13. Klicken Sie auf Erstellen.

  14. Warten Sie, bis der Dienst erstellt wurde (1–2 Minuten).

  15. Nachdem der Dienst erstellt wurde, wird automatisch der Inline-Code-Editor geöffnet.

Funktionscode hinzufügen

  1. Geben Sie main in das Feld Einstiegspunkt ein.
  2. Erstellen Sie im Inline-Code-Editor zwei Dateien:

    • Erste Datei: main.py:
    import functions_framework
    from google.cloud import storage
    from google.cloud.exceptions import NotFound
    import json
    import os
    import re
    import urllib3
    from datetime import datetime, timezone, timedelta
    import time
    
    # Initialize HTTP client with timeouts
    http = urllib3.PoolManager(
      timeout=urllib3.Timeout(connect=5.0, read=30.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', 'tenable')
    # STATE_KEY must stay OUTSIDE GCS_PREFIX. The feed ingests every object under
    # its bucket URI and, with a deletion option selected, deletes what it
    # transferred. A state file inside the prefix would be ingested as log data and
    # then deleted, resetting collection and re-ingesting duplicates.
    STATE_KEY = os.environ.get('STATE_KEY', 'tenable-state.json')
    TENABLE_ACCESS_KEY = os.environ.get('TENABLE_ACCESS_KEY')
    TENABLE_SECRET_KEY = os.environ.get('TENABLE_SECRET_KEY')
    MAX_RECORDS = int(os.environ.get('MAX_RECORDS', '5000'))
    # The audit-log API accepts a limit up to 10000.
    PAGE_SIZE = int(os.environ.get('PAGE_SIZE', '1000'))
    LOOKBACK_HOURS = int(os.environ.get('LOOKBACK_HOURS', '24'))
    # The query re-reads this many minutes before the watermark so that events
    # Tenable indexes late are still collected. Re-read events are dropped by id.
    OVERLAP_MINUTES = int(os.environ.get('OVERLAP_MINUTES', '2'))
    
    TENABLE_API_BASE = 'https://cloud.tenable.com'
    
    class FetchError(Exception):
      """Raised when the Tenable API call fails.
    
      The watermark must never advance on a failed fetch, otherwise every event in
      the failed window is skipped permanently.
      """
    
    def parse_datetime(value: str) -> datetime:
      """Parse a Tenable `received` timestamp into an aware datetime.
    
      Tenable returns ISO 8601 with either whole seconds (2018-12-31T23:09:40Z) or
      fractional seconds (2024-01-16T15:12:47.334Z). Fractional digits are trimmed
      to microseconds because fromisoformat accepts at most six.
      """
      text = str(value).strip()
      if text.endswith('Z'):
        text = text[:-1] + '+00:00'
      text = re.sub(r'\.(\d{6})\d+', r'.\1', text)
      dt = datetime.fromisoformat(text)
      if dt.tzinfo is None:
        dt = dt.replace(tzinfo=timezone.utc)
      return dt.astimezone(timezone.utc)
    
    @functions_framework.cloud_event
    def main(cloud_event):
      """Fetch Tenable Vulnerability Management activity log events and write them to Cloud Storage.
    
      Args:
        cloud_event: CloudEvent object containing the Pub/Sub message.
      """
      if not all([GCS_BUCKET, TENABLE_ACCESS_KEY, TENABLE_SECRET_KEY]):
        # Raise rather than return: a bare return acks the Pub/Sub message and
        # reports the run as successful, silently discarding the schedule tick.
        raise RuntimeError('Missing required environment variables')
    
      bucket = storage_client.bucket(GCS_BUCKET)
      state = load_state(bucket, STATE_KEY)
    
      now = datetime.now(timezone.utc)
      watermark = None
      if state.get('last_event_time'):
        watermark = parse_datetime(state['last_event_time'])
      seen_ids = set(state.get('seen_ids', []))
    
      if watermark is None:
        start_time = now - timedelta(hours=LOOKBACK_HOURS)
      else:
        start_time = watermark - timedelta(minutes=OVERLAP_MINUTES)
    
      print(f"Fetching logs from {start_time.isoformat()} to {now.isoformat()}")
    
      # A FetchError propagates: the run fails, the watermark is untouched, and the
      # next invocation retries the same window.
      records, newest_event_time = fetch_logs(
        start_time=start_time,
        page_size=PAGE_SIZE,
        max_records=MAX_RECORDS,
      )
    
      # Drop events already written by an earlier run. Without this the overlap
      # window re-emits its events on every invocation, and an idle tenant has its
      # newest events rewritten to a new object every hour.
      fresh = [r for r in records if str(r.get('id', '')) not in seen_ids]
      print(f"Fetched {len(records)} records, {len(fresh)} new after deduplication")
    
      if not fresh:
        print("No new log records found. Watermark left unchanged.")
        return
    
      if not newest_event_time:
        raise FetchError('Records were returned but no `received` timestamp could be parsed')
    
      timestamp = now.strftime('%Y%m%dT%H%M%SZ')
      object_key = f"{GCS_PREFIX}/logs_{timestamp}.ndjson"
      blob = bucket.blob(object_key)
    
      ndjson = '\n'.join(json.dumps(record, ensure_ascii=False) for record in fresh) + '\n'
      blob.upload_from_string(ndjson, content_type='application/x-ndjson')
    
      print(f"Wrote {len(fresh)} records to gs://{GCS_BUCKET}/{object_key}")
    
      # Advance the watermark only after the data is durably written.
      new_watermark = parse_datetime(newest_event_time)
      if watermark and new_watermark < watermark:
        new_watermark = watermark
    
      # Retain only the ids still inside the overlap window, so the state file
      # stays small while covering every event the next query can re-read.
      cutoff = new_watermark - timedelta(minutes=OVERLAP_MINUTES)
      retained = []
      for record in records:
        received = record.get('received')
        if not received:
          continue
        try:
          if parse_datetime(received) >= cutoff:
            retained.append(str(record.get('id', '')))
        except ValueError:
          continue
    
      save_state(bucket, STATE_KEY, {
        'last_event_time': new_watermark.isoformat(),
        'seen_ids': sorted(i for i in set(retained) if i),
      })
    
      print(f"Successfully processed {len(fresh)} records")
    
    def load_state(bucket, key):
      """Read the collector state from Cloud Storage.
    
      Only a missing object is treated as a cold start. Any other error is raised:
      swallowing it would silently reset collection to the full lookback window and
      re-ingest that entire period.
      """
      blob = bucket.blob(key)
      try:
        return json.loads(blob.download_as_text())
      except NotFound:
        print('No state file found. Starting from the lookback window.')
        return {}
    
    def save_state(bucket, key, state: dict):
      """Write the collector state to Cloud Storage.
    
      Failures are raised, not logged. If the state write fails after the data was
      uploaded, the next run repeats the same window and duplicates it.
      """
      blob = bucket.blob(key)
      blob.upload_from_string(
        json.dumps(state, indent=2),
        content_type='application/json',
      )
      print(f"Saved state: last_event_time={state.get('last_event_time')}")
    
    def fetch_logs(start_time: datetime, page_size: int, max_records: int):
      """Fetch audit events from the Tenable Vulnerability Management API.
    
      Uses offset pagination, which is what the endpoint documents: the request
      accepts `limit` (maximum 10000) and `offset`, and the response `pagination`
      object returns `offset`, `limit`, `count` and `total`.
    
      Args:
        start_time: Exclusive lower bound for the `received` timestamp
        page_size: Records per page (the API accepts up to 10000)
        max_records: Maximum total records to fetch in one run
    
      Returns:
        Tuple of (records list, newest `received` value as an ISO 8601 string).
    
      Raises:
        FetchError: on any API or transport failure, so the caller cannot mistake
          a failed fetch for an empty result and advance the watermark.
      """
      endpoint = f"{TENABLE_API_BASE}/audit-log/v1/events"
    
      headers = {
        'X-ApiKeys': f'accessKey={TENABLE_ACCESS_KEY};secretKey={TENABLE_SECRET_KEY}',
        'Accept': 'application/json',
        'User-Agent': 'GoogleSecOps-TenableAuditCollector/1.0'
      }
    
      records = []
      newest_time = None
      page_num = 0
      backoff = 1.0
      rate_limit_retries = 0
      MAX_RATE_LIMIT_RETRIES = 5
      offset = 0
    
      while True:
        page_num += 1
    
        if len(records) >= max_records:
          # Stop cleanly. The remaining events stay ahead of the watermark and
          # are collected by the next run.
          print(f"Reached max_records limit ({max_records})")
          break
    
        # Every parameter is rebuilt per page. `sort=received:asc` is required:
        # a time watermark is only correct over an ascending scan, otherwise a
        # truncated run advances the watermark past events it never read.
        params = {
          'f': f'date.gt:{start_time.strftime("%Y-%m-%dT%H:%M:%SZ")}',
          'sort': 'received:asc',
          'limit': min(page_size, max_records - len(records)),
          'offset': offset,
        }
        url = f"{endpoint}?" + '&'.join(f"{k}={v}" for k, v in params.items())
    
        try:
          response = http.request('GET', url, headers=headers)
        except Exception as e:
          raise FetchError(f'Request to {endpoint} failed: {e}') from e
    
        if response.status == 429:
          rate_limit_retries += 1
          if rate_limit_retries > MAX_RATE_LIMIT_RETRIES:
            raise FetchError('Rate limited repeatedly; giving up without advancing the watermark')
          raw_retry_after = response.headers.get('Retry-After')
          try:
            # Retry-After may also be an HTTP date, which int() cannot parse.
            retry_after = int(raw_retry_after) if raw_retry_after else int(backoff)
          except (TypeError, ValueError):
            retry_after = int(backoff)
          print(f"Rate limited (429). Retrying after {retry_after}s...")
          time.sleep(retry_after)
          backoff = min(backoff * 2, 30.0)
          continue
    
        backoff = 1.0
        rate_limit_retries = 0
    
        if response.status != 200:
          body = response.data.decode('utf-8')
          raise FetchError(f'HTTP {response.status} from the Tenable audit log API: {body}')
    
        try:
          data = json.loads(response.data.decode('utf-8'))
        except json.JSONDecodeError as e:
          raise FetchError(f'Malformed JSON response from the Tenable audit log API: {e}') from e
    
        page_results = data.get('events', [])
    
        if not page_results:
          print("No more results (empty page)")
          break
    
        print(f"Page {page_num}: Retrieved {len(page_results)} events")
        records.extend(page_results)
    
        for event in page_results:
          received = event.get('received')
          if not received:
            continue
          try:
            if newest_time is None or parse_datetime(received) > parse_datetime(newest_time):
              newest_time = received
          except ValueError as e:
            print(f"Warning: Could not parse event time {received!r}: {e}")
    
        offset += len(page_results)
        total = data.get('pagination', {}).get('total')
        if total is not None and offset >= total:
          print("No more pages (all matching events retrieved)")
          break
    
      print(f"Retrieved {len(records)} total records from {page_num} pages")
      return records, newest_time
    

    • Zweite Datei: requirements.txt:
    functions-framework==3.*
    google-cloud-storage==2.*
    urllib3>=2.0.0
    
  3. Klicken Sie auf Bereitstellen, um die Funktion zu speichern und bereitzustellen.

  4. Warten Sie, bis die Bereitstellung abgeschlossen ist (2–3 Minuten).

Cloud Scheduler-Job erstellen

Cloud Scheduler veröffentlicht in regelmäßigen Abständen Nachrichten im Pub/Sub-Thema und löst so die Cloud Run-Funktion aus.

  1. Rufen Sie in der GCP Console Cloud Scheduler auf.
  2. Klicken Sie auf Job erstellen.
  3. Geben Sie die folgenden Konfigurationsdetails an:

    Einstellung Wert
    Name tenable-audit-collector-hourly
    Region Dieselbe Region wie die Cloud Run-Funktion auswählen
    Frequenz 0 * * * * (stündlich zur vollen Stunde)
    Zeitzone Zeitzone auswählen (UTC empfohlen)
    Zieltyp Pub/Sub
    Thema Wählen Sie das Thema tenable-audit-trigger aus.
    Inhalt der Nachricht {} (leeres JSON-Objekt)
  4. Klicken Sie auf Erstellen.

Optionen für die Häufigkeit des Zeitplans

Wählen Sie die Häufigkeit basierend auf dem Logvolumen und den Latenzanforderungen aus:

Häufigkeit Cron-Ausdruck Anwendungsfall
Alle 5 Minuten */5 * * * * Hohes Volumen, niedrige Latenz
Alle 15 Minuten */15 * * * * Mittleres Suchvolumen
Stündlich 0 * * * * Standard (empfohlen)
Alle 6 Stunden 0 */6 * * * Geringes Volumen, Batchverarbeitung
Täglich 0 0 * * * Erhebung von Verlaufsdaten

Integration testen

  1. Suchen Sie in der Cloud Scheduler-Konsole nach Ihrem Job.
  2. Klicken Sie auf Ausführung erzwingen, um den Job manuell auszulösen.
  3. Warten Sie einige Sekunden.
  4. Rufen Sie Cloud Run > Dienste auf.
  5. Klicken Sie auf tenable-audit-collector.
  6. Klicken Sie auf den Tab Logs.
  7. Prüfen Sie, ob die Funktion erfolgreich ausgeführt wurde. Darauf sollten Sie achten:

    Fetching logs from YYYY-MM-DDTHH:MM:SS+00:00 to YYYY-MM-DDTHH:MM:SS+00:00
    Page 1: Retrieved X events
    Fetched X records, Y new after deduplication
    Wrote Y records to gs://tenable-audit-logs/tenable/logs_YYYYMMDDTHHMMSSZ.ndjson
    Saved state: last_event_time=YYYY-MM-DDTHH:MM:SS+00:00
    Successfully processed Y records
    
  8. Rufen Sie Cloud Storage > Buckets auf.

  9. Klicken Sie auf den Namen Ihres Buckets (tenable-audit-logs).

  10. Rufen Sie den Ordner tenable/ auf.

  11. Prüfen Sie, ob eine neue .ndjson-Datei mit dem aktuellen Zeitstempel erstellt wurde.

Wenn bei einem Lauf nichts Neues angekommen ist, protokolliert die Funktion No new log records found. Watermark left unchanged. und schreibt kein Objekt. Das ist so vorgesehen: Wenn dieselben Ereignisse noch einmal geschrieben werden, werden sie in Google SecOps dupliziert.

Wenn in den Logs Fehler angezeigt werden:

  • HTTP 401: API-Schlüssel in Umgebungsvariablen prüfen
  • HTTP 403: Das Konto ist kein Administratorkonto. Für den Endpunkt für das Aktivitätsprotokoll ist die Nutzerrolle „Administrator“ [64] erforderlich.
  • HTTP 429: Ratenbegrenzung. Die Funktion versucht es mit Backoff-Wiederholungen und schlägt dann fehl, ohne das Watermark zu erhöhen. Es werden also keine Ereignisse übersprungen.
  • Fehlende Umgebungsvariablen: Prüfen Sie, ob alle erforderlichen Variablen festgelegt sind.

Feed in Google SecOps konfigurieren, um Tenable-Audit-Logs aufzunehmen

  1. Rufen Sie die SIEM-Einstellungen > Feeds auf.
  2. Klicken Sie auf Neuen Feed hinzufügen.
  3. Klicken Sie auf Einzelnen Feed konfigurieren.
  4. Geben Sie im Feld Feedname einen Namen für den Feed ein, z. B. Tenable Audit Logs.
  5. Wählen Sie Google Cloud Storage V2 als Quelltyp aus.
  6. Wählen Sie Tenable Audit als Log type (Logtyp) aus.
  7. Klicken Sie auf Dienstkonto abrufen. Es wird eine eindeutige E-Mail-Adresse für das Dienstkonto angezeigt, z. B.:

    chronicle-12345678@chronicle-gcp-prod.iam.gserviceaccount.com
    
  8. Kopieren Sie diese E-Mail-Adresse.

  9. Klicken Sie auf Weiter.

  10. Geben Sie Werte für die folgenden Eingabeparameter an:

    • Storage-Bucket-URL: Geben Sie den Cloud Storage-Bucket-URI mit dem Präfixpfad ein:

      gs://tenable-audit-logs/tenable/
      
      • Ersetzen Sie:
        • tenable-audit-logs: Name Ihres Cloud Storage-Bucket.
        • tenable: Optionales Präfix/Ordnerpfad, in dem Logs gespeichert werden (für den Stamm leer lassen).
    • Option zum Löschen der Quelle: Wählen Sie die gewünschte Option zum Löschen aus:

      • Dateien nie löschen: Dateien werden nie aus der Quelle gelöscht (empfohlen für Tests).
      • Übertragene Dateien und leere Verzeichnisse löschen: Dateien und leere Verzeichnisse werden nach einem erfolgreichen Abruf aus der Quelle gelöscht.

    • Höchstalter der Datei: Dateien einbeziehen, die in den letzten Tagen geändert wurden (Standardwert: 180 Tage)

    • Asset-Namespace: Der Asset-Namespace

    • Labels für Datenaufnahme: Das Label, das auf die Ereignisse aus diesem Feed angewendet werden soll

  11. Klicken Sie auf Weiter.

  12. Prüfen Sie die neue Feedkonfiguration auf dem Bildschirm Abschließen und klicken Sie dann auf Senden.

Dem Google SecOps-Dienstkonto IAM-Berechtigungen gewähren

Das Google SecOps-Dienstkonto benötigt zwei Rollen für Ihren Cloud Storage-Bucket: Storage-Objekt-Betrachter zum Lesen der Logobjekte und eine Rolle auf Bucket-Ebene zum Lesen der Bucket-Metadaten.

  1. Rufen Sie Cloud Storage > Buckets auf.
  2. Klicken Sie auf den Namen Ihres Buckets.
  3. Wechseln Sie zum Tab Berechtigungen.
  4. Klicken Sie auf Zugriff erlauben.
  5. Geben Sie die folgenden Konfigurationsdetails an:
    • Hauptkonten hinzufügen: Fügen Sie die E‑Mail-Adresse des Google SecOps-Dienstkontos ein.
    • Rollen zuweisen: Wählen Sie die folgenden beiden Optionen aus:
      • Storage Object Viewer: Liest die Logobjekte.
      • Leser alter Storage-Buckets: Berechtigt zum Lesen der Bucket-Metadaten. Wenn Sie die Löschoption Übertragene Dateien und leere Verzeichnisse löschen ausgewählt haben, wählen Sie stattdessen Storage Legacy Bucket Writer aus. Dadurch wird auch die Löschberechtigung erteilt.
  6. Klicken Sie auf Speichern.

UDM-Zuordnungstabelle

Logfeld UDM-Zuordnung Logik
crud_label additional.fields Zusammengeführt
fields_label additional.fields Zusammengeführt
field_name extensions.auth.mechanism Zugeordnet: X-Access-Type → mech_label
mech_label extensions.auth.mechanism Zusammengeführt
extension_value extensions.auth.type Direkt zugeordnet
description metadata.description Direkt zugeordnet
received metadata.event_timestamp Als ISO8601 geparst
has_principal metadata.event_type Zugeordnete Werte (insgesamt 5, z.B. true → USER_LOGIN, true → USER_CREATION, true → `USER...
has_user metadata.event_type Zugeordnet: true → USER_UNCATEGORIZED
action metadata.product_event_type Direkt zugeordnet
id metadata.product_log_id Direkt zugeordnet
field_name principal.asset.ip Zugeordnet: X-Forwarded-For → ip
ip principal.asset.ip Zusammengeführt
field_name principal.ip Zugeordnet: X-Forwarded-For → ip
ip principal.ip Zusammengeführt
actor.name principal.user.email_addresses Zusammengeführt
actor.id principal.user.userid Direkt zugeordnet
AUTH_VIOLOATION security_result.category Zusammengeführt
is_failure security_result.category Zugeordnet: true → AUTH_VIOLOATION
is_anonymous_label security_result.detection_fields Zusammengeführt
is_failure_label security_result.detection_fields Zusammengeführt
target1.name target.user.email_addresses Zusammengeführt
target1.type target.user.role_name Direkt zugeordnet
target1.id target.user.userid Direkt zugeordnet
– extensions.auth.type Konstante: AUTHTYPE_UNSPECIFIED
– metadata.event_type Konstante: USER_LOGIN
– metadata.product_name Konstante: TENABLE AUDIT
– metadata.vendor_name Konstante: TENABLE

Änderungsprotokoll

Änderungsprotokoll für diesen Parser ansehen

Benötigen Sie weitere Hilfe? Antworten von Community-Mitgliedern und Google SecOps-Experten erhalten