Recopila registros de Qualys Virtual Scanner
Este analizador transforma los registros de Qualys Virtual Scanner con formato JSON sin procesar en un formato estructurado que se ajusta al UDM de Google Security Operations. Extrae campos relevantes, como información de recursos, detalles de análisis y vulnerabilidades detectadas, y los asigna a los campos de UDM correspondientes para una representación y un análisis coherentes.
Antes de comenzar
Asegúrate de cumplir con los siguientes requisitos previos:
- Instancia de Google Security Operations.
- Acceso con privilegios a Google Cloud.
- Acceso con privilegios a Qualys.
Habilita las APIs obligatorias:
- Accede a la consola de Google Cloud .
- Ve a APIs y servicios > Biblioteca.
- Busca las siguientes APIs y habilítalas:
- API de Cloud Functions
- API de Cloud Scheduler
- Cloud Pub/Sub (obligatorio para que Cloud Scheduler invoque funciones)
Crea un bucket de almacenamiento de Google Cloud
- Accede a la consola de Google Cloud .
Ve a la página Buckets de Cloud Storage.
Haz clic en Crear.
Configura el bucket:
- Nombre: Ingresa un nombre único que cumpla con los requisitos de nombre de bucket (por ejemplo, qualys-vscanner-bucket).
- Elige dónde almacenar tus datos: Selecciona una ubicación.
- Elige una clase de almacenamiento para tus datos: selecciona una clase de almacenamiento predeterminada para el bucket o selecciona Autoclass para la administración automática de clases de almacenamiento.
- Elige cómo controlar el acceso a los objetos: selecciona no para aplicar la prevención del acceso público y selecciona un modelo de control de acceso para los objetos del bucket.
- Clase de almacenamiento: Elige según tus necesidades (por ejemplo, Estándar).
Haz clic en Crear.
Crea una cuenta de servicio de Google Cloud
- Ve a IAM y administración > Cuentas de servicio.
- Cree una cuenta de servicio nueva
- Asígnale un nombre descriptivo (por ejemplo, qualys-user).
- Otorga a la cuenta de servicio el rol de administrador de objetos de almacenamiento en el bucket de Cloud Storage que creaste en el paso anterior.
- Otorga a la cuenta de servicio el rol de Invocador de Cloud Functions.
- Crea una clave SSH para la cuenta de servicio.
- Descarga un archivo de claves JSON para la cuenta de servicio. Mantén este archivo seguro.
Opcional: Crea un usuario de API dedicado en Qualys
- Accede a la consola de Qualys.
- Ve a Usuarios.
- Haz clic en Nuevo > Usuario.
- Ingresa la Información general requerida para el usuario.
- Selecciona la pestaña Rol del usuario.
- Asegúrate de que el rol tenga seleccionada la casilla de verificación Acceso a la API.
- Haz clic en Guardar.
Identifica la URL específica de la API de Qualys
Opción 1
Identifica tus URLs como se menciona en la identificación de la plataforma.
Opción 2
- Accede a la consola de Qualys.
- Ve a Ayuda > Acerca de.
- Desplázate para ver esta información en Centro de operaciones de seguridad (SOC).
- Copia la URL de la API de Qualys.
Configura la Cloud Function
- Ve a Cloud Functions en la consola de Google Cloud .
- Haz clic en Crear función.
Configura la función:
- Nombre: Ingresa un nombre para tu función (por ejemplo, fetch-qualys-vscanner).
- Región: Selecciona una región cercana a tu bucket.
- 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 directo:
```python from google.cloud import storage import requests import base64 import json # Google Cloud Storage Configuration BUCKET_NAME = "<bucket-name>" FILE_NAME = "qualys_virtual_scanners.json" # Qualys API Credentials QUALYS_USERNAME = "qualys-username" QUALYS_PASSWORD = "<qualys-password>" QUALYS_BASE_URL = "https://<qualys_base_url>" # for example, https://qualysapi.qualys.com def fetch_virtual_scanners(): """Fetch Virtual Scanner details from Qualys.""" auth = base64.b64encode(f"{QUALYS_USERNAME}:{QUALYS_PASSWORD}".encode()).decode() headers = { "Authorization": f"Basic {auth}", "Content-Type": "application/xml" } url = f"{QUALYS_BASE_URL}/api/2.0/fo/scanner/" payload = { "action": "list", "scanner_type": "virtual" } response = requests.post(url, headers=headers, data=payload) response.raise_for_status() return response.text # Qualys API returns XML data 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(data, content_type="application/xml") def main(request): """Cloud Function entry point.""" try: scanners = fetch_virtual_scanners() upload_to_gcs(scanners) return "Qualys Virtual Scanners data 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.
Configura Cloud Scheduler
- Ve a Cloud Scheduler en la consola de Google Cloud .
- Haz clic en Crear trabajo.
Configura el trabajo:
- Nombre: Ingresa un nombre para tu trabajo (por ejemplo, trigger-fetch-qualys-vscanner).
- Frecuencia: Usa la sintaxis de cron para especificar la programación (por ejemplo, 0 0 * * * para que se ejecute diariamente a la medianoche).
- Zona horaria: Establece tu zona horaria preferida.
- Tipo de activador: Elige HTTP.
- URL del activador: ingresa la URL de Cloud Function (se encuentra en los detalles de la función después de la implementación).
- Método: Elige POST.
Crea el trabajo.
Configura feeds
Para configurar un feed, sigue estos pasos:
- Ve a Configuración > Administración de datos > Feeds. Si estás en una plataforma solo de SIEM, ve a Configuración > Feeds.
- Haz clic en Agregar feed nuevo.
- En la página siguiente, haz clic en Configurar un solo feed.
- En el campo Nombre del feed, ingresa un nombre para el feed, por ejemplo, Registros del escáner virtual de Qualys.
- Selecciona Google Cloud Storage V2 como el Tipo de fuente.
- Selecciona Qualys Virtual Scanner como el Tipo de registro.
- Haz clic en Siguiente.
Especifica valores para los siguientes parámetros de entrada:
- URI del bucket de almacenamiento: Es el URI de origen del bucket de almacenamiento de Google Cloud .
- Opción de eliminación del código fuente: Selecciona la opción de eliminación según tu preferencia.
Haz clic en Siguiente.
Revisa la configuración de tu feed de noticias nuevo en la pantalla Finalizar y, luego, haz clic en Enviar.
Tabla de asignación de UDM
| Campo de registro | Asignación de UDM | Lógica |
|---|---|---|
| ASSET_ID | entity.entity.asset.asset_id | Asignación directa del campo ASSET_ID. |
| CLOUD_PROVIDER_TAGS.CLOUD_TAG.NAME | entity.relations.entity.resource.attribute.labels.key | Asignación directa del campo CLOUD_PROVIDER_TAGS.CLOUD_TAG.NAME. |
| CLOUD_PROVIDER_TAGS.CLOUD_TAG.VALUE | entity.relations.entity.resource.attribute.labels.value | Asignación directa del campo CLOUD_PROVIDER_TAGS.CLOUD_TAG.VALUE. |
| CLOUD_RESOURCE_ID | entity.relations.entity.resource.id | Asignación directa del campo CLOUD_RESOURCE_ID. |
| DETECTION_LIST.DETECTION.FIRST_FOUND_DATETIME | entity.metadata.threat.first_discovered_time | Asignación directa desde el campo DETECTION_LIST.DETECTION.FIRST_FOUND_DATETIME, convertido en marca de tiempo. |
| DETECTION_LIST.DETECTION.FIRST_REOPENED_DATETIME | entity.metadata.threat.detection_fields.value | Asignación directa del campo DETECTION_LIST.DETECTION.FIRST_REOPENED_DATETIME. La clave está codificada como "FIRST_REOPENED_DATETIME". |
| DETECTION_LIST.DETECTION.IS_DISABLED | entity.metadata.threat.detection_fields.value | Asignación directa del campo DETECTION_LIST.DETECTION.IS_DISABLED. La clave está codificada como "IS_DISABLED". |
| DETECTION_LIST.DETECTION.LAST_FIXED_DATETIME | entity.metadata.threat.detection_fields.value | Asignación directa del campo DETECTION_LIST.DETECTION.LAST_FIXED_DATETIME. La clave está codificada como "LAST_FIXED_DATETIME". |
| DETECTION_LIST.DETECTION.LAST_FOUND_DATETIME | entity.metadata.threat.detection_fields.value | Asignación directa del campo DETECTION_LIST.DETECTION.LAST_FOUND_DATETIME. La clave está codificada como "LAST_FOUND_DATETIME". |
| DETECTION_LIST.DETECTION.LAST_PROCESSED_DATETIME | entity.metadata.threat.detection_fields.value | Asignación directa del campo DETECTION_LIST.DETECTION.LAST_PROCESSED_DATETIME. La clave está codificada como "LAST_PROCESSED_DATETIME". |
| DETECTION_LIST.DETECTION.LAST_REOPENED_DATETIME | entity.metadata.threat.detection_fields.value | Asignación directa del campo DETECTION_LIST.DETECTION.LAST_REOPENED_DATETIME. La clave está codificada como "LAST_REOPENED_DATETIME". |
| DETECTION_LIST.DETECTION.LAST_TEST_DATETIME | entity.metadata.threat.detection_fields.value | Asignación directa del campo DETECTION_LIST.DETECTION.LAST_TEST_DATETIME. La clave está codificada como "LAST_TEST_DATETIME". |
| DETECTION_LIST.DETECTION.LAST_UPDATE_DATETIME | entity.metadata.threat.detection_fields.value | Asignación directa del campo DETECTION_LIST.DETECTION.LAST_UPDATE_DATETIME. La clave está codificada como "LAST_UPDATE_DATETIME". |
| DETECTION_LIST.DETECTION.PORT | entity.metadata.threat.detection_fields.value | Asignación directa del campo DETECTION_LIST.DETECTION.PORT. La clave está codificada como "PORT". |
| DETECTION_LIST.DETECTION.PROTOCOL | entity.metadata.threat.detection_fields.value | Asignación directa del campo DETECTION_LIST.DETECTION.PROTOCOL. La clave está codificada como "PROTOCOL". |
| DETECTION_LIST.DETECTION.QID | entity.metadata.threat.detection_fields.value | Asignación directa del campo DETECTION_LIST.DETECTION.QID. La clave está codificada como "QID". |
| DETECTION_LIST.DETECTION.RESULTS | entity.metadata.threat.summary | Asignación directa del campo DETECTION_LIST.DETECTION.RESULTS. |
| DETECTION_LIST.DETECTION.SEVERITY | entity.metadata.threat.severity_details | Asignación directa del campo DETECTION_LIST.DETECTION.SEVERITY. |
| DETECTION_LIST.DETECTION.SSL | entity.metadata.threat.detection_fields.value | Asignación directa del campo DETECTION_LIST.DETECTION.SSL. La clave está codificada como "SSL". |
| DETECTION_LIST.DETECTION.STATUS | entity.metadata.threat.detection_fields.value | Asignación directa del campo DETECTION_LIST.DETECTION.STATUS. La clave está codificada como "STATUS". |
| DETECTION_LIST.DETECTION.TIMES_FOUND | entity.metadata.threat.detection_fields.value | Asignación directa del campo DETECTION_LIST.DETECTION.TIMES_FOUND. La clave está codificada como "TIMES_FOUND". |
| DETECTION_LIST.DETECTION.TIMES_REOPENED | entity.metadata.threat.detection_fields.value | Asignación directa del campo DETECTION_LIST.DETECTION.TIMES_REOPENED. La clave está codificada como "TIMES_REOPENED". |
| DETECTION_LIST.DETECTION.TYPE | entity.metadata.threat.severity | Se asignó desde el campo DETECTION_LIST.DETECTION.TYPE. Si el valor es "info" (no distingue mayúsculas de minúsculas), se asigna a "INFORMATIONAL". De lo contrario, se agrega como un campo de detección con la clave "TYPE". |
| DETECTION_LIST.DETECTION.UNIQUE_VULN_ID | entity.metadata.threat.detection_fields.value | Asignación directa del campo DETECTION_LIST.DETECTION.UNIQUE_VULN_ID. La clave está codificada como "UNIQUE_VULN_ID". |
| DNS | entity.entity.asset.hostname | Se asigna desde el campo DNS si DNS_DATA.HOSTNAME está vacío. |
| DNS_DATA.HOSTNAME | entity.entity.asset.hostname | Asignación directa del campo DNS_DATA.HOSTNAME. |
| EC2_INSTANCE_ID | entity.relations.entity.resource.product_object_id | Asignación directa del campo EC2_INSTANCE_ID. |
| ID | entity.entity.asset.product_object_id | Asignación directa del campo ID. |
| ID | entity.metadata.product_entity_id | Asignación directa del campo ID. |
| IP | entity.entity.ip | Asignación directa del campo IP. |
| LAST_SCAN_DATETIME | entity.metadata.interval.start_time | Asignación directa desde el campo LAST_SCAN_DATETIME, convertido en marca de tiempo. |
| METADATA.AZURE.ATTRIBUTE.NAME | entity.relations.entity.resource.attribute.labels.key | Asignación directa del campo METADATA.AZURE.ATTRIBUTE.NAME. |
| METADATA.AZURE.ATTRIBUTE.VALUE | entity.relations.entity.resource.attribute.labels.value | Asignación directa del campo METADATA.AZURE.ATTRIBUTE.VALUE. |
| SO | entity.entity.asset.platform_software.platform | Se asignó desde el campo OS. Si el valor contiene "windows" (no distingue mayúsculas de minúsculas), se asigna a "WINDOWS". Si contiene "Linux" (no distingue mayúsculas de minúsculas), se asigna a "LINUX". |
| TAGS.TAG.NAME | entity.relations.entity.resource.attribute.labels.key | Asignación directa del campo TAGS.TAG.NAME. |
| TAGS.TAG.TAG_ID | entity.relations.entity.resource.attribute.labels.value | Se asignó desde el campo TAGS.TAG.TAG_ID. El valor tiene el prefijo "TAG_ID: ". |
| entity.metadata.collected_timestamp | Es la marca de tiempo de la entrada de registro. | |
| entity.metadata.entity_type | Se determina en función de la presencia del campo IP. Si IP está presente, se establece en "IP_ADDRESS". De lo contrario, se establece en "ASSET". |
|
| entity.metadata.interval.end_time | Se codifica de forma fija en un valor de marca de tiempo muy grande (253,402,300,799 segundos). | |
| entity.metadata.product_name | Se codifica como "QUALYS_VIRTUAL_SCANNER". | |
| entity.metadata.vendor_name | Se codifica como "QUALYS_VIRTUAL_SCANNER". | |
| entity.relations.entity.resource.resource_type | Si CLOUD_SERVICE es "VM", se establece en "VIRTUAL_MACHINE". |
|
| entity.relations.entity_type | Está codificado como "RESOURCE". | |
| entity.relations.relationship | Está codificado como "MEMBER". |
Registro de cambios
Consulta el registro de cambios de este analizador
¿Necesitas más ayuda? Obtén respuestas de miembros de la comunidad y profesionales de Google SecOps.