Qualys-Asset-Kontextprotokolle erfassen
In diesem Dokument wird beschrieben, wie Sie Qualys-Asset-Kontext-Logs mit Google Cloud Storage in Google Security Operations aufnehmen.
Der Qualys-Asset-Kontext enthält Host-Asset-Inventardaten (IP-Adressen, DNS-Namen, Betriebssystem, Cloud-Anbietermetadaten und Tags) von der Qualys-Plattform. Da diese Daten aus der Qualys API abgerufen werden, fragt eine Cloud Run-Funktion regelmäßig die Qualys Host List API ab, konvertiert die XML-Antwort in JSON und schreibt sie in einen Cloud Storage-Bucket, in den Google SecOps sie aufnimmt.
Hinweis
Prüfen Sie, ob folgende Voraussetzungen erfüllt sind:
- Eine Google SecOps-Instanz
- Ein Google Cloud-Projekt mit aktivierten Cloud Storage-, Cloud Run-, Pub/Sub- und Cloud Scheduler-APIs
- Berechtigungen zum Erstellen und Verwalten von Cloud Storage-Buckets, Dienstkonten, Cloud Run Functions, Pub/Sub-Themen und Cloud Scheduler-Jobs
- Ein Qualys-Konto mit API-Zugriff (ein Nutzer mit der Rolle Manager oder einer Rolle mit API-Zugriff und Sichtbarkeit der Assets, die Sie erfassen möchten)
Cloud Storage-Bucket erstellen
- Öffnen Sie die Google Cloud Console.
- Wählen Sie Ihr Projekt aus oder erstellen Sie ein neues.
- Rufen Sie Cloud Storage > Buckets auf.
- Klicken Sie auf Bucket erstellen.
- Geben Sie die folgenden Konfigurationsdetails an:
- Bucket benennen: Geben Sie einen global eindeutigen Namen ein, z. B.
qualys-asset-context-logs. - Standorttyp: Wählen Sie je nach Bedarf „Region“, „Zwei Regionen“ oder „Mehrere Regionen“ aus.
- Standort: Wählen Sie den Standort aus, z. B.
us-central1. - Speicherklasse: Wählen Sie Standard aus.
- Zugriffssteuerung: Wählen Sie Einheitlich aus.
- Bucket benennen: Geben Sie einen global eindeutigen Namen ein, z. B.
- Klicken Sie auf Erstellen.
Qualys API-Anmeldedaten erfassen
- Melden Sie sich in der Qualys-Webanwendung an.
- API-Nutzer identifizieren oder erstellen:
- Rufen Sie Nutzer > Nutzerverwaltung auf.
- Verwenden Sie einen vorhandenen Nutzer oder klicken Sie auf Neu > Nutzer und weisen Sie die Rolle Administrator (oder eine Rolle mit API-Zugriff) zu.
- Notieren Sie sich den Nutzernamen und das Passwort des Nutzers.
Ermitteln Sie die URL Ihres Qualys-API-Servers. Sie ist spezifisch für Ihre Qualys-Plattform, z. B.
https://qualysapi.qg3.apps.qualys.com. Weitere Informationen finden Sie unter Qualys-Plattform ermitteln.
Dienstkonto für die Cloud Run-Funktion erstellen
- Rufen Sie IAM & Verwaltung > Dienstkonten auf.
- Klicken Sie auf Dienstkonto erstellen.
- Geben Sie die folgenden Konfigurationsdetails an:
- Name des Dienstkontos: Geben Sie
qualys-asset-context-saein. - Beschreibung des Dienstkontos: Geben Sie
Service account for Cloud Run function to collect Qualys asset context logsein.
- Name des Dienstkontos: Geben Sie
- Klicken Sie auf Erstellen und fortfahren.
- Weisen Sie die folgenden Rollen zu:
- Storage-Objekt-Administrator: Hostdatensätze in den Bucket schreiben.
- Cloud Run Invoker: Ermöglicht Pub/Sub, die Funktion aufzurufen.
- Klicken Sie auf Weiter und dann auf Fertig.
Dienstkonto Zugriff auf den Cloud Storage-Bucket gewähren
- Rufen Sie Cloud Storage > Buckets auf.
- Klicken Sie auf den Namen Ihres Buckets.
- Wechseln Sie zum Tab Berechtigungen.
- Klicken Sie auf Zugriff erlauben.
- Geben Sie die folgenden Konfigurationsdetails an:
- Hauptkonten hinzufügen: Geben Sie die E‑Mail-Adresse des Dienstkontos (
qualys-asset-context-sa@<PROJECT_ID>.iam.gserviceaccount.com) ein. - Rollen zuweisen: Wählen Sie Storage Object Admin aus.
- Hauptkonten hinzufügen: Geben Sie die E‑Mail-Adresse des Dienstkontos (
- Klicken Sie auf Speichern.
Pub/Sub-Thema erstellen
- Rufen Sie Pub/Sub > Themen auf.
- Klicken Sie auf Thema erstellen.
- Geben Sie im Feld Themen-ID den Wert
qualys-asset-context-triggerein. - 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. Sie ruft die Qualys FO Host List API auf, konvertiert die XML-Antwort in JSON und schreibt die Hostdatensätze in den Bucket.
- Rufen Sie Cloud Run auf.
- Klicken Sie auf Dienst erstellen.
- Wählen Sie Funktion aus, um den Inline-Code-Editor zu verwenden.
- Geben Sie die folgenden Konfigurationsdetails an:
- Servicename: Geben Sie
qualys-asset-context-collectorein. - Region: Wählen Sie die Region aus, die Ihrem Bucket entspricht (z. B.
us-central1). - Laufzeit: Wählen Sie Python 3.12 oder höher aus.
- Servicename: Geben Sie
- Im Abschnitt Trigger:
- Klicken Sie auf Trigger hinzufügen.
- Wählen Sie Cloud Pub/Sub aus.
- Wählen Sie unter Cloud Pub/Sub-Thema auswählen die Option
qualys-asset-context-triggeraus. - Klicken Sie auf Speichern.
- Wählen Sie im Bereich Authentifizierung die Option Authentifizierung erforderlich aus.
- Maximieren Sie Container, Netzwerk, Sicherheit und legen Sie auf dem Tab Sicherheit für Dienstkonto den Wert
qualys-asset-context-safest. Fügen Sie auf dem Tab Container > Variablen und Secrets die folgenden Umgebungsvariablen hinzu:
Variablenname Beispielwert GCS_BUCKETqualys-asset-context-logsGCS_PREFIXqualys-asset-context/QUALYS_BASE_URLhttps://qualysapi.qg3.apps.qualys.comQUALYS_USERNAMEyour-qualys-usernameQUALYS_PASSWORDyour-qualys-passwordTRUNCATION_LIMIT1000HTTP_TIMEOUT300MAX_PAGES50Legen Sie Request timeout (Zeitüberschreitung für Anfragen) auf
600Sekunden und Memory (Arbeitsspeicher) auf 512 MiB oder höher fest.Klicken Sie auf Erstellen. Nachdem der Dienst erstellt wurde, wird der Inline-Code-Editor geöffnet.
Funktionscode hinzufügen
- Geben Sie im Feld Funktionseinstiegspunkt den Wert
mainein. Ersetzen Sie im Inline-Code-Editor den Inhalt von
main.pydurch den folgenden Code:import functions_framework from google.cloud import storage import os import time import uuid import json import base64 import requests import xmltodict storage_client = storage.Client() GCS_BUCKET = os.environ.get('GCS_BUCKET') GCS_PREFIX = os.environ.get('GCS_PREFIX', 'qualys-asset-context/') QUALYS_BASE_URL = os.environ.get('QUALYS_BASE_URL') QUALYS_USERNAME = os.environ.get('QUALYS_USERNAME') QUALYS_PASSWORD = os.environ.get('QUALYS_PASSWORD') TRUNCATION_LIMIT = int(os.environ.get('TRUNCATION_LIMIT', '1000')) HTTP_TIMEOUT = int(os.environ.get('HTTP_TIMEOUT', '300')) MAX_PAGES = int(os.environ.get('MAX_PAGES', '50')) def _headers(): """Qualys FO API requires Basic auth and the X-Requested-With header.""" token = base64.b64encode(f'{QUALYS_USERNAME}:{QUALYS_PASSWORD}'.encode()).decode() return {'Authorization': f'Basic {token}', 'X-Requested-With': 'Cloud Run function'} def _extract_hosts(xml_text): """Parse the FO Host List XML into (list_of_host_dicts, next_page_url).""" doc = xmltodict.parse(xml_text) response = (doc.get('HOST_LIST_OUTPUT') or {}).get('RESPONSE') or {} host_list = (response.get('HOST_LIST') or {}).get('HOST') if host_list is None: hosts = [] elif isinstance(host_list, list): hosts = host_list else: hosts = [host_list] # When the result is truncated, RESPONSE contains <WARNING><URL>...</URL></WARNING>. warning = response.get('WARNING') next_url = warning.get('URL') if isinstance(warning, dict) else None return hosts, next_url def _write_hosts(bucket, hosts, page_num): """Write one batch of hosts to GCS as JSON, one host per line.""" ts_path = time.strftime('%Y/%m/%d', time.gmtime()) uniq = f'{int(time.time() * 1e6)}_{uuid.uuid4().hex[:8]}' key = f'{GCS_PREFIX}{ts_path}/qualys_asset_context_p{page_num:03d}_{uniq}.json' lines = [json.dumps(host, separators=(',', ':')) for host in hosts] bucket.blob(key).upload_from_string('\n'.join(lines), content_type='application/x-ndjson') return key @functions_framework.cloud_event def main(cloud_event): """Triggered by Pub/Sub to pull the Qualys host asset inventory and write it to GCS.""" if not all([GCS_BUCKET, QUALYS_BASE_URL, QUALYS_USERNAME, QUALYS_PASSWORD]): print('Error: missing required environment variables') return bucket = storage_client.bucket(GCS_BUCKET) session = requests.Session() session.headers.update(_headers()) url = f"{QUALYS_BASE_URL.rstrip('/')}/api/2.0/fo/asset/host/" params = { 'action': 'list', 'details': 'All', 'truncation_limit': TRUNCATION_LIMIT, # show_cloud_tags, host_metadata, and show_tags add the cloud provider # tags, cloud instance metadata, and asset tags that the parser maps. 'show_cloud_tags': 1, 'host_metadata': 'all', 'show_tags': 1, } pages = 0 total = 0 try: while pages < MAX_PAGES: resp = session.get(url, params=params, timeout=HTTP_TIMEOUT) resp.raise_for_status() hosts, next_url = _extract_hosts(resp.text) if hosts: _write_hosts(bucket, hosts, pages + 1) total += len(hosts) pages += 1 if not next_url: break # The pagination URL already includes every query parameter. url, params = next_url, None print(f'Wrote {total} hosts across {pages} pages') except Exception as e: print(f'Error collecting Qualys asset context: {e}') raiseErstellen Sie eine
requirements.txt-Datei mit folgendem Inhalt:functions-framework==3.* google-cloud-storage==2.* requests>=2.31.0 xmltodict>=0.13.0Klicken Sie auf Bereitstellen und warten Sie, bis die Bereitstellung abgeschlossen ist.
Cloud Scheduler-Job erstellen
- Rufen Sie Cloud Scheduler auf.
- Klicken Sie auf Job erstellen.
- Geben Sie die folgenden Konfigurationsdetails an:
- Name: Geben Sie
qualys-asset-context-collector-dailyein. - Region: Wählen Sie dieselbe Region wie die Cloud Run-Funktion aus.
- Häufigkeit: Geben Sie
0 */6 * * *ein (alle sechs Stunden). - Zeitzone: Wählen Sie UTC aus.
- Zieltyp: Wählen Sie Pub/Sub aus.
- Thema: Wählen Sie
qualys-asset-context-triggeraus. - Inhalt der Nachricht: Geben Sie
{}ein.
- Name: Geben Sie
- Klicken Sie auf Erstellen.
- Klicken Sie zum Prüfen der Einrichtung auf Ausführung erzwingen für den Job und sehen Sie dann in den Cloud Run-Logs und im Bucket nach, ob Hostdatensätze geschrieben wurden.
Feed in Google SecOps konfigurieren, um Qualys-Asset-Kontextlogs aufzunehmen
- Rufen Sie die SIEM-Einstellungen > Feeds auf.
- Klicken Sie auf Neuen Feed hinzufügen.
- Klicken Sie auf der nächsten Seite auf Einen einzelnen Feed konfigurieren.
- Geben Sie im Feld Feedname einen Namen für den Feed ein, z. B.
Qualys asset context logs. - Wählen Sie Google Cloud Storage V2 als Quelltyp aus.
- Wählen Sie Qualys-Asset-Kontext als Protokolltyp aus.
- Klicken Sie neben dem Feld Chronicle-Dienstkonto auf Dienstkonto abrufen und kopieren Sie die E‑Mail-Adresse des Dienstkontos.
- Klicken Sie auf Weiter.
- Geben Sie Werte für die folgenden Eingabeparameter an:
- Storage-Bucket-URI: Geben Sie
gs://qualys-asset-context-logs/qualys-asset-context/ein. Diese URL muss mit einem nachgestellten Schrägstrich (/) enden. - Optionen zum Löschen von Quellen: Wählen Sie die gewünschte Option zum Löschen aus.
- Maximales Dateialter: Dateien einschließen, die in den letzten Tagen geändert wurden. Der Standardwert ist 180 Tage.
- Storage-Bucket-URI: Geben Sie
- Klicken Sie auf Weiter.
- Prüfen Sie die neue Feedkonfiguration auf dem Bildschirm Abschließen und klicken Sie dann auf Senden.
Dem Google SecOps-Dienstkonto Zugriff auf den Bucket gewähren
- Rufen Sie Cloud Storage > Buckets auf.
- Klicken Sie auf den Namen Ihres Buckets.
- Wechseln Sie zum Tab Berechtigungen.
- Klicken Sie auf Zugriff erlauben.
- Geben Sie die folgenden Konfigurationsdetails an:
- Hauptkonten hinzufügen: Fügen Sie die E‑Mail-Adresse des Google SecOps-Dienstkontos aus der Feed-Einrichtung ein.
- Rollen zuweisen: Wählen Sie Storage Object Viewer (oder Storage Object Admin, wenn Sie eine Löschoption ausgewählt haben) aus.
- Klicken Sie auf Speichern.
UDM-Zuordnungstabelle
| Logfeld | UDM-Zuordnung | Logik |
|---|---|---|
ASSET_ID |
entity.asset.asset_id |
Direkt zugeordnet |
DNS_DATA.HOSTNAME |
entity.asset.hostname |
Direkt zugeordnet |
IP |
entity.asset.ip |
Zusammengeführt |
OS |
entity.asset.platform_software.platform |
Zugeordnet: (?i)windows → WINDOWS |
ID |
entity.asset.product_object_id |
Direkt zugeordnet |
dataset |
relations |
Zusammengeführt |
| – | entity.asset.platform_software.platform |
Konstante: WINDOWS |
| – | metadata.entity_type |
Konstante: ASSET |
| – | metadata.product_name |
Konstante: QUALYS ASSET CONTEXT |
| – | metadata.vendor_name |
Konstante: QUALYS ASSET CONTEXT |
DNS_DATA.HOSTNAME |
entity.entity.asset.hostname |
Aus dem Änderungsprotokoll zugeordnet |
Änderungsprotokoll
Änderungsprotokoll für diesen Parser ansehen
Benötigen Sie weitere Hilfe? Antworten von Community-Mitgliedern und Google SecOps-Experten erhalten