Recopila registros de GitLab
Descripción general
Este analizador extrae campos de los registros JSON de GitLab, los normaliza en el modelo de datos unificado (UDM) y enriquece los datos con contexto adicional. Controla varios tipos de eventos de GitLab, se enfoca en las acciones de los usuarios, el acceso a los recursos y los resultados de seguridad, y también procesa información relacionada con la red y la aplicación. El analizador también realiza una lógica basada en roles y acciones dentro de GitLab, clasifica los eventos y asigna las gravedades adecuadas.
Antes de comenzar
- Asegúrate de tener una instancia de Google SecOps.
- Asegúrate de tener acceso con privilegios a GitLab.
Configura un feed en Google SecOps para transferir los registros de GitLab
- Ve a Configuración de SIEM > Feeds.
- Haz clic en Agregar nueva.
- En el campo Nombre del feed, ingresa un nombre para el feed (por ejemplo, Registros de GitLab).
- Selecciona Webhook como el Tipo de origen.
- Selecciona Gitlab como el Tipo de registro.
- Haz clic en Siguiente.
- Opcional: Especifica valores para los siguientes parámetros de entrada:
- Delimitador de división: Es el delimitador que se usa para separar las líneas de registro, como
\n
. - Espacio de nombres de activos: Es el espacio de nombres de activos.
- Etiquetas de transferencia: Es la etiqueta que se aplica a los eventos de este feed.
- Delimitador de división: Es el delimitador que se usa para separar las líneas de registro, como
- Haz clic en Siguiente.
- Revisa la configuración del feed en la pantalla Finalizar y, luego, haz clic en Enviar.
- Haz clic en Generate Secret Key para generar una clave secreta que autentique este feed.
- Copia y almacena la clave secreta. No podrás volver a ver esta clave secreta. Si es necesario, puedes volver a generar una clave secreta nueva, pero esta acción hace que la clave secreta anterior quede obsoleta.
- En la pestaña Detalles, copia la URL del extremo del feed del campo Información del extremo. Debes especificar esta URL de extremo en tu aplicación cliente.
- Haz clic en Listo.
Crea una clave de API para el feed de webhook
Ve a consola de Google Cloud > Credenciales.
Haz clic en Crear credenciales y selecciona Clave de API.
Restringe el acceso de la clave de API a la API de Google Security Operations.
Especifica la URL del extremo
- En tu aplicación cliente, especifica la URL del extremo HTTPS que se proporciona en el feed de webhook.
Para habilitar la autenticación, especifica la clave de API y la clave secreta como parte del encabezado personalizado en el siguiente formato:
X-goog-api-key = API_KEY X-Webhook-Access-Key = SECRET
Recomendación: Especifica la clave de API como un encabezado en lugar de hacerlo en la URL. Si tu cliente de webhook no admite encabezados personalizados, puedes especificar la clave de API y la clave secreta con parámetros de consulta en el siguiente formato:
ENDPOINT_URL?key=API_KEY&secret=SECRET
Reemplaza lo siguiente:
ENDPOINT_URL
: Es la URL del extremo del feed.API_KEY
: Es la clave de API para autenticarse en Google Security Operations.SECRET
: Es la clave secreta que generaste para autenticar el feed.
Configura un webhook en GitLab para Google SecOps
- Abre tu navegador web y ve al proyecto de GitLab para el que deseas configurar el webhook.
- En tu proyecto, ve a Configuración > Webhooks.
- Haz clic en Agregar webhook nuevo.
- En el campo URL, pega la URL del extremo de SecOps de Google.
- Haz clic en Agregar encabezado personalizado.
- Escribe X-Webhook-Access-Key en el campo Header Name.
- En el campo Header Value, copia la clave secreta que se generó durante la configuración del feed de SecOps de Google.
- Haz clic en Agregar encabezado personalizado.
- Escribe X-goog-api-key en el campo Header Name.
- En el campo Header Value, copia la clave de API generada durante la configuración del feed de SecOps de Google. Nota: Para mejorar la seguridad, genera un token secreto y agrégalo a la configuración del webhook de GitLab y a la configuración correspondiente del feed de Google SecOps. Esto ayuda a verificar la autenticidad de los webhooks entrantes.
- Elige los eventos de GitLab que deben activar el webhook. Por ejemplo, puedes seleccionar Eventos de envío para enviar datos a Google SecOps cada vez que se envía código al repositorio. Considera cuidadosamente qué eventos son relevantes para tus necesidades de supervisión de seguridad. Demasiados eventos pueden generar una carga innecesaria.
- Para comprender mejor el propósito de los webhooks, asígnales un nombre significativo, como Webhook de SecOps de Google.
- Asegúrate de que esté seleccionada la casilla de verificación Habilitar verificación SSL. Esto es fundamental para la comunicación segura.
- Haz clic en Agregar webhook para guardar la configuración.
Tabla de asignación de UDM
Campo de registro | Asignación de UDM | Lógica |
---|---|---|
author_id |
principal.user.userid |
Se convirtió en una cadena. |
author_name |
principal.user.email_addresses |
Si el valor coincide con una regex de dirección de correo electrónico. |
author_name |
principal.user.user_display_name |
Si el valor no coincide con una regex de dirección de correo electrónico. |
details.as |
principal.resource.attribute.labels |
Se agregó como una etiqueta con la clave "as". |
details.add |
principal.resource.attribute.labels |
Se agregó como una etiqueta con la clave "add". |
details.as |
principal.user.role_name |
El valor del campo de registro sin procesar. |
details.as |
principal.user.attribute.roles.type |
Se establece en "ADMINISTRATOR" si details.as es "propietario", en "SERVICE_ACCOUNT" si details.as es "Developer", "Maintainer" o "Reporter", y en "TYPE_UNSPECIFIED" si details.as es "Guest". |
details.custom_message |
security_result.description |
El valor del campo de registro sin procesar. |
details.custom_message.action |
security_result.summary |
El valor del campo de registro sin procesar. |
details.entity_path |
target.file.full_path |
El valor del campo de registro sin procesar. |
details.target_id |
target.resource.id |
Se convirtió en una cadena. |
entity_path |
target.file.full_path |
El valor del campo de registro sin procesar. |
entity_type |
target.resource.attribute.labels |
Se agregó como una etiqueta con la clave "Tipo de entidad". |
event_type |
metadata.product_event_type |
El valor del campo de registro sin procesar. |
insertId |
metadata.product_log_id |
El valor del campo de registro sin procesar. |
ip_address |
principal.ip , principal.asset.ip |
El valor del campo de registro sin procesar. |
jsonPayload.action |
additional.fields |
Se agregó como un campo con la clave "action" y el valor de cadena. |
jsonPayload.controller |
additional.fields |
Se agregó como un campo con la clave "controller" y el valor de cadena. |
jsonPayload.correlation_id |
principal.asset_id |
Debe tener el prefijo “id:”. |
jsonPayload.cpu_s |
additional.fields |
Se agregó como un campo con la clave "cpu_s" y el valor de cadena. |
jsonPayload.details.custom_message.protocol |
network.application_protocol |
Se establece en "UNKNOWN_APPLICATION_PROTOCOL" si el valor es "web", de lo contrario, se convierte a mayúsculas. También se agregó como un campo adicional con la clave "Protocolo de aplicación" si el valor es "web". |
jsonPayload.mem_total_bytes |
additional.fields |
Se agregó como un campo con la clave "mem_total_bytes" y el valor de cadena. |
jsonPayload.meta_caller_id |
additional.fields |
Se agregó como un campo con la clave "Caller Id" y el valor de cadena. |
jsonPayload.meta_client_id |
target.user.userid |
El valor del campo de registro sin procesar. |
jsonPayload.meta_feature_category |
additional.fields |
Se agregó como un campo con la clave "Feature Category" y el valor de cadena. |
jsonPayload.meta_remote_ip |
principal.ip , principal.asset.ip |
El valor del campo de registro sin procesar, analizado como un array JSON y combinado en los campos de IP |
jsonPayload.meta_user |
principal.user.userid |
Se usa como resguardo si jsonPayload.username está vacío. |
jsonPayload.method |
network.http.method |
El valor del campo de registro sin procesar. |
jsonPayload.path |
target.process.file.full_path |
El valor del campo de registro sin procesar. |
jsonPayload.pid |
target.process.pid |
Se convirtió en una cadena. |
jsonPayload.remote_ip |
principal.ip , principal.asset.ip |
El valor del campo de registro sin procesar. |
jsonPayload.request_urgency |
additional.fields |
Se agregó como un campo con la clave "Request Urgency" y el valor de cadena. |
jsonPayload.severity |
security_result.severity |
Establece el valor en "INFORMATIONAL" si el valor es "INFO", en "ERROR" si el valor es "ERROR" y en "MEDIUM" si el valor es "NOTICE". |
jsonPayload.status |
network.http.response_code |
Se convierte en número entero si no es "ACTIVE". |
jsonPayload.ua |
network.http.user_agent |
El valor del campo de registro sin procesar. |
jsonPayload.username |
principal.user.userid |
El valor del campo de registro sin procesar. |
jsonPayload.worker_id |
principal.application |
El valor del campo de registro sin procesar. |
labels.instance_name |
principal.hostname , principal.asset.hostname |
Es el valor del campo de registro sin procesar, que se usa si el mensaje contiene "Removing user". |
logName |
security_result.category_details |
El valor del campo de registro sin procesar. |
message |
security_result.summary |
Es el valor del campo de registro sin procesar, que se usa si jsonPayload.severity es “ERROR”. |
protoPayload.@type |
additional.fields |
Se agregó como un campo con la clave "protoPayload type" y el valor de cadena. |
protoPayload.authenticationInfo.principalEmail |
principal.user.email_addresses , principal.user.userid |
El valor del campo de registro sin procesar. |
protoPayload.authenticationInfo.principalSubject |
additional.fields |
Se agregó como un campo con la clave "authenticationInfo principalSubject" y el valor de cadena. |
protoPayload.authenticationInfo.serviceAccountKeyName |
additional.fields |
Se agregó como un campo con la clave "authenticationInfo serviceAccountKeyName" y el valor de cadena. |
protoPayload.authorizationInfo |
target.resource.attribute.labels , security_result.action |
Los valores de este campo se agregan como etiquetas con claves que tienen el prefijo "authenticationInfo". security_result.action se establece en "ALLOW" si un valor dentro de granted es verdadero y en "BLOCK" si es falso. Los campos anidados, como resourceAttributes , también se agregan como etiquetas con claves que tienen el prefijo "authenticationInfo_resourceAttributes". |
protoPayload.methodName |
additional.fields |
Se agregó como un campo con la clave "protoPayload methodName" y el valor de cadena. |
protoPayload.request.@type |
additional.fields |
Se agregó como un campo con la clave "Request Type" y el valor de cadena. |
protoPayload.request.resource |
target.resource.attribute.labels |
Se agregó como una etiqueta con la clave "Request resource". |
protoPayload.requestMetadata.callerIp |
additional.fields |
Se agregó como un campo con la clave "requestMetadata callerIp" y el valor de cadena. |
protoPayload.requestMetadata.callerSuppliedUserAgent |
additional.fields |
Se agregó como un campo con la clave "requestMetadata callerSuppliedUserAgent" y el valor de cadena. |
protoPayload.serviceName |
additional.fields |
Se agregó como un campo con la clave "serviceName" y el valor de cadena. |
protoPayload.status.code |
additional.fields |
Se agregó como un campo con la clave "código de estado de protoPayload" y el valor de cadena. |
protoPayload.status.message |
additional.fields , target.user.email_addresses , target.user.userid |
Se agregó como un campo con la clave "protoPayload status message" y el valor de cadena. Si se puede extraer una dirección de correo electrónico del mensaje, se agrega a target.user.email_addresses y target.user.userid . |
receiveTimestamp |
metadata.event_timestamp , timestamp |
Se analiza como la marca de tiempo del evento. |
resource.labels.project_id |
target.resource.attribute.labels |
Se agregó como una etiqueta con la clave "Project id". |
resource.labels.zone |
target.cloud.availability_zone |
El valor del campo de registro sin procesar. |
resource.type |
target.cloud.environment |
Establece el valor en "GOOGLE_CLOUD_PLATFORM" si coincide con "gce". |
security_result.action |
security_result.action |
Derivado de protoPayload.authorizationInfo.granted . |
security_result.category_details |
security_result.category_details |
Se fusionó con logName . |
security_result.description |
security_result.description |
Derivado de jsonPayload.details.custom_message . |
security_result.severity |
security_result.severity |
Se deriva de severity o jsonPayload.severity . |
security_result.summary |
security_result.summary |
Se deriva de jsonPayload.details.custom_message.action o jsonPayload.message . |
severity |
security_result.severity |
Establece el valor en "INFORMATIONAL" si el valor es "INFO", en "ERROR" si el valor es "ERROR" y en "MEDIUM" si el valor es "NOTICE". |
sourceLocation |
principal.resource.attribute.labels |
Los valores de este campo se agregan como etiquetas. |
target_details |
target.resource.attribute.labels |
Se agregó como una etiqueta con la clave "Target Details". |
target_type |
target.resource.attribute.labels |
Se agregó como una etiqueta con la clave "tipo de objetivo". |
timestamp |
timestamp |
El valor del campo de registro sin procesar. Se establece en función de la presencia de campos principales y de destino. El valor predeterminado es "GENERIC_EVENT" si no se cumple ninguna condición específica. Los valores posibles son "USER_RESOURCE_UPDATE_CONTENT", "USER_RESOURCE_ACCESS" y "USER_UNCATEGORIZED". Se establece en “GITLAB”. Se establece en “GITLAB”. |
Cambios
2024-04-08
- Se asignó "custom_message.action" a "security_result.summary".
- Se asignó "ip_address" a "principal.ip".
- Se asignó "applicationProtocol" a "network.application_protocol".
- Se asignó "details.author_name"" a "principal.user.email_addresses"
- Se asignó "author_id" a "principal.user.userid".
- Se asignó "target_id" a "target.resource.id".
- Se asignó "details.entity_path" a "target.file.full_path".
- Se asignó "event_type" a "product_event_type".
- Se asignaron "target_type", "entity_type" y "target_details" a "resource.attribute.labels".
2023-10-20
- Se asignaron los campos que comienzan con "db_" a "additional_fields".
- Se asignaron los campos que comienzan con "redis_" a "additional_fields".
- Se asignó "severity" o "jsonPayload.severity" a "security_result.severity" cuando el valor es "ERROR" o "NOTICE".
- Se asignó "jsonPayload.correlation_id" a "principal.asset_id".
- Se asignaron los "campos no asignados de jsonPayload" a "additional_fields".
- Se asignó "jsonPayload.worker_id" a "principal.application".
- Se asignó "jsonPayload.method" a "network.http.method".
- Se asignó "jsonPayload.pid" a "target.process.pid".
- Se asignó "jsonPayload.status" a "network.http.response_code".
- Se asignó "resource.labels.zone" a "target.cloud.availability_zone".
- Se asignó "resource.type" a "target.cloud.environment".
- Se asignó "jsonPayload.meta_user" a "target.user.userid".
- Se asignó "jsonPayload.username" a "principal.user.userid".
- Se asignó "jsonPayload.remote_ip" a "principal.ip".
- Se asignó "jsonPayload.ua" a "network.http.user_agent".
- Se asignó "jsonPayload.meta_client_id" a "target.user.userid".
- Se asignó "jsonPayload.path" a "target.process.file.full_path".
- Se asignó "protoPayload.authenticationInfo.principalEmail" a "principal.user.email_addresses".
- Se asignaron campos adicionales en "protoPayload" a "additional.fields".
- Se proporcionó una verificación condicional que indica que el mapeo obligatorio está presente antes de asignar el "metadata.event_type".
2023-10-10
- Se asignó "jsonPayload.details.as" a "principal.resource.attribute.labels" y "principal.user.role_name".
- Establece "principal_role.type" en "ADMINISTRATOR" para los registros que tengan "jsonPayload.details.as" igual a "propietario".
- Establece "principal_role.type" en "SERVICE_ACCOUNT" para los registros que tengan "jsonPayload.details.as" configurado como "Developer", "Maintainer" o "Reporter".
- Establece "principal_role.type" en "TYPE_UNSPECIFIED" para los registros que tengan "jsonPayload.details.as" igual a "Guest".
- Se asignó "jsonPayload.details.add" a "principal.resource.attribute.labels".
- Se asignó "jsonPayload.entity_type" a "target.resource.attribute.labels".
2023-08-31
- Sin embargo, el analizador se creó recientemente.