Recopilar registros de monitorización continua de Qualys
Este código de analizador de Logstash primero extrae campos como la IP de origen, el usuario, el método y el protocolo de aplicación de los mensajes de registro sin procesar mediante patrones grok. A continuación, asigna campos específicos de los datos de registro sin procesar a sus campos correspondientes en el modelo de datos unificado (UDM), realiza conversiones de tipos de datos y enriquece los datos con etiquetas y metadatos adicionales antes de estructurar la salida en el formato UDM deseado.
Antes de empezar
Asegúrate de que cumples los siguientes requisitos previos:
- Instancia de Google Security Operations.
- Acceso privilegiado a Google Cloud.
- Acceso privilegiado a Qualys.
Habilita las APIs obligatorias:
- Inicia sesión en la Google Cloud consola.
- Ve a APIs y servicios > Biblioteca.
- Busca las siguientes APIs y habilítalas:
- Cloud Functions API
- API Scheduler de Cloud
- Cloud Pub/Sub (necesario para que Cloud Scheduler invoque funciones)
Crea un Google Cloud segmento de almacenamiento
- Inicia sesión en la Google Cloud consola.
Ve a la página Segmentos de Cloud Storage.
Haz clic en Crear.
Configure el segmento:
- Nombre: introduzca un nombre único que cumpla los requisitos de nombres de segmentos (por ejemplo, qualys-asset-bucket).
- Elige dónde quieres almacenar los datos: selecciona una ubicación.
- Elige una clase de almacenamiento para tus datos: selecciona una clase de almacenamiento predeterminada para el segmento o Autoclass para gestionar automáticamente la clase de almacenamiento.
- Elige cómo quieres controlar el acceso a los objetos: selecciona no para aplicar la prevención del acceso público y elige un modelo de control de acceso para los objetos del segmento.
- Clase de almacenamiento: elige la que mejor se adapte a tus necesidades (por ejemplo, Standard).
Haz clic en Crear.
Crear una cuenta de servicio de Google Cloud
- Inicia sesión en la Google Cloud consola.
- Ve a IAM y administración > Cuentas de servicio.
- Crear una nueva cuenta de servicio.
- Asigna un nombre descriptivo (por ejemplo, qualys-user).
- Asigna a la cuenta de servicio el rol Administrador de objetos de Storage en el segmento de GCS que has creado en el paso anterior.
- Asigna a la cuenta de servicio el rol Invocador de Cloud Functions.
- Crea una clave SSH para la cuenta de servicio.
- Descarga un archivo de clave JSON de la cuenta de servicio. Guarda este archivo de forma segura.
Opcional: Crea un usuario de API específico en Qualys
- Inicia sesión en la consola de Qualys.
- Ve a Usuarios.
- Haz clic en Nuevo > Usuario.
- Introduce la información general necesaria del usuario.
- Selecciona la pestaña Rol de usuario.
- Asegúrate de que el rol tenga marcada la casilla Acceso a la API.
- Haz clic en Guardar.
Identificar tu URL de API de Qualys específica
Opción 1
Identifique sus URLs tal como se indica en la sección Identificación de la plataforma.
Opción 2
- Inicia sesión en la consola de Qualys.
- Ve a Ayuda > Información.
- Desplázate para ver esta información en Centro de operaciones de seguridad (SOC).
- Copia la URL de la API de Qualys.
Configurar la función de Cloud
- Ve a Cloud Functions en la Google Cloud consola.
- Haz clic en Crear función.
Configura la función:
- Nombre: introduce un nombre para la función (por ejemplo, fetch-qualys-cm-alerts).
- Región: selecciona una región cercana a tu contenedor.
- Entorno de ejecución: Python 3.10 (o el entorno de ejecución que prefieras).
- Activador: elige el activador HTTP si es necesario o Cloud Pub/Sub para la ejecución programada.
- Autenticación: protege con autenticación.
- Escribe el código con un editor insertado:
```python from google.cloud import storage import requests import base64 import json # Google Cloud Storage Configuration BUCKET_NAME = "<bucket-name>" FILE_NAME = "qualys_cm_alerts.json" # Qualys API Credentials QUALYS_USERNAME = "<qualys-username>" QUALYS_PASSWORD = "<qualys-password>" QUALYS_BASE_URL = "https://<qualys_base_url>" def fetch_cm_alerts(): """Fetch alerts from Qualys Continuous Monitoring.""" auth = base64.b64encode(f"{QUALYS_USERNAME}:{QUALYS_PASSWORD}".encode()).decode() headers = { "Authorization": f"Basic {auth}", "Content-Type": "application/xml" } payload = """ <ServiceRequest> <filters> <Criteria field="alert.date" operator="GREATER">2024-01-01</Criteria> </filters> </ServiceRequest> """ response = requests.post(f"{QUALYS_BASE_URL}/qps/rest/2.0/search/cm/alert", headers=headers, data=payload) response.raise_for_status() return response.json() def upload_to_gcs(data): """Upload data to Google Cloud Storage.""" client = storage.Client() bucket = client.get_bucket(BUCKET_NAME) blob = bucket.blob(FILE_NAME) blob.upload_from_string(json.dumps(data, indent=2), content_type="application/json") def main(request): """Cloud Function entry point.""" try: alerts = fetch_cm_alerts() upload_to_gcs(alerts) return "Qualys CM alerts uploaded to Cloud Storage successfully!" except Exception as e: return f"An error occurred: {e}", 500 ```
Haz clic en Implementar después de completar la configuración.
Configurar Cloud Scheduler
- Ve a Cloud Scheduler en la Google Cloud consola.
- Haz clic en Crear trabajo.
Configura el trabajo:
- Nombre: escribe un nombre para el trabajo (por ejemplo, trigger-fetch-qualys-cm-alerts).
- Frecuencia: usa la sintaxis cron para especificar la programación (por ejemplo,
0 * * * *
para ejecutarla cada hora). - Zona horaria: define tu zona horaria preferida.
- Tipo de activador: elija HTTP.
- URL de activación: introduce la URL de Cloud Functions (que se encuentra en los detalles de la función después de la implementación).
- Método: elige POST.
Crea el trabajo.
Configurar feeds
Para configurar un feed, sigue estos pasos:
- Ve a Configuración de SIEM > Feeds.
- Haz clic en Añadir feed.
- En la página siguiente, haga clic en Configurar un solo feed.
- En el campo Nombre del feed, introduzca un nombre para el feed; por ejemplo, Registros de monitorización continua de Qualys.
- Selecciona Google Cloud Storage V2 como Tipo de origen.
- Seleccione Monitorización continua de Qualys como Tipo de registro.
- Haz clic en Siguiente.
Especifique los valores de los siguientes parámetros de entrada:
- URI del segmento de almacenamiento: el Google Cloud URI de origen del segmento de almacenamiento.
- Opciones de eliminación de la fuente: selecciona la opción de eliminación que prefieras.
Haz clic en Siguiente.
Revise la configuración de la nueva fuente en la pantalla Finalizar y, a continuación, haga clic en Enviar.
Tabla de asignación de UDM
Campo de registro | Asignación de UDM | Lógica |
---|---|---|
Alert.alertInfo.appVersion | metadata.product_version | Asignado directamente desde Alert.alertInfo.appVersion |
Alert.alertInfo.operatingSystem | principal.platform_version | Asignado directamente desde Alert.alertInfo.operatingSystem |
Alert.alertInfo.port | additional.fields.value.string_value | Se ha asignado directamente desde Alert.alertInfo.port y se ha añadido como par clave-valor en additional.fields con la clave "Alert port". |
Alert.alertInfo.protocol | network.ip_protocol | Asignado directamente desde Alert.alertInfo.protocol |
Alert.alertInfo.sslIssuer | network.tls.client.certificate.issuer | Asignado directamente desde Alert.alertInfo.sslIssuer |
Alert.alertInfo.sslName | additional.fields.value.string_value | Se asigna directamente desde Alert.alertInfo.sslName y se añade como un par clave-valor en additional.fields con la clave "Nombre SSL". |
Alert.alertInfo.sslOrg | additional.fields.value.string_value | Se asigna directamente desde Alert.alertInfo.sslOrg y se añade como un par clave-valor en additional.fields con la clave "SSL Org". |
Alert.alertInfo.ticketId | additional.fields.value.string_value | Se ha asignado directamente desde Alert.alertInfo.ticketId y se ha añadido como par clave-valor en additional.fields con la clave "Ticket Id". |
Alert.alertInfo.vpeConfidence | additional.fields.value.string_value | Se asigna directamente desde Alert.alertInfo.vpeConfidence y se añade como par clave-valor en additional.fields con la clave "VPE Confidence". |
Alert.alertInfo.vpeStatus | additional.fields.value.string_value | Se asigna directamente desde Alert.alertInfo.vpeStatus y se añade como par clave-valor en additional.fields con la clave "VPE Confidence". |
Alert.eventType | additional.fields.value.string_value | Se asigna directamente desde Alert.eventType y se añade como un par clave-valor en additional.fields con la clave "Event Type". |
Alert.hostname | principal.hostname | Asignado directamente desde Alert.hostname |
Alert.id | security_result.threat_id | Asignado directamente desde Alert.id |
Alert.ipAddress | principal.ip | Asignado directamente desde Alert.ipAddress |
Alert.profile.id | additional.fields.value.string_value | Se asigna directamente desde Alert.profile.id y se añade como un par clave-valor en additional.fields con la clave "Profile Id". |
Alert.profile.title | additional.fields.value.string_value | Se ha asignado directamente desde Alert.profile.title y se ha añadido como par clave-valor en additional.fields con la clave "Profile Title". |
Alert.qid | vulnerability.name | Asignado como "QID: Alert.qid |
Alert.source | additional.fields.value.string_value | Se asigna directamente desde Alert.source y se añade como par clave-valor en additional.fields con la clave "Alert Source" |
Alert.triggerUuid | metadata.product_log_id | Asignado directamente desde Alert.triggerUuid |
Alert.vulnCategory | additional.fields.value.string_value | Se asigna directamente desde Alert.vulnCategory y se añade como par clave-valor en additional.fields con la clave "Vulnerability Category" (Categoría de vulnerabilidad). |
Alert.vulnSeverity | vulnerability.severity | Asignación basada en el valor de Alert.vulnSeverity : 1-3: BAJO, 4-6: MEDIO, 7-8: ALTO |
Alert.vulnTitle | vulnerability.description | Asignado directamente desde Alert.vulnTitle |
Alert.vulnType | additional.fields.value.string_value | Se asigna directamente desde Alert.vulnType y se añade como par clave-valor en additional.fields con la clave "Vulnerability Type". |
Host | principal.ip | Analizado a partir de la línea de registro "Host: |
edr.client.ip_addresses | Copiados de principal.ip |
|
edr.client.hostname | Copiados de principal.hostname |
|
edr.raw_event_name | Se asigna el valor "STATUS_UPDATE" si están presentes Alert.ipAddress , Alert.hostname o src_ip . De lo contrario, se asigna el valor "GENERIC_EVENT". |
|
metadata.event_timestamp | Extraído de los campos Alert.eventDate o timestamp . Se da prioridad a Alert.eventDate si existe. De lo contrario, se usa timestamp . La marca de tiempo se convierte a UTC. |
|
metadata.event_type | La misma lógica que edr.raw_event_name |
|
metadata.log_type | Se ha definido como "QUALYS_CONTINUOUS_MONITORING". | |
metadata.product_name | Se ha definido como "QUALYS_CONTINUOUS_MONITORING". | |
metadata.vendor_name | Se ha definido como "QUALYS_CONTINUOUS_MONITORING". | |
network.application_protocol | Analizado a partir de la línea de registro " |
|
network.http.method | Analizado a partir de la línea de registro " |
|
timestamp | event.timestamp | Extraído de los campos Alert.eventDate o timestamp . Se da prioridad a Alert.eventDate si existe. De lo contrario, se usa timestamp . La marca de tiempo se convierte a UTC. |
¿Necesitas más ayuda? Recibe respuestas de los miembros de la comunidad y de los profesionales de Google SecOps.