Recoger registros de auditoría de Slack
En este documento se explica cómo ingerir registros de auditoría de Slack en Google Security Operations mediante funciones de Google Cloud Run. El analizador gestiona dos formatos de registros de auditoría de Slack. Primero normaliza los valores booleanos y borra los campos predefinidos. A continuación, analiza el campo "message" como JSON y gestiona los mensajes que no están en formato JSON descartándolos. En función de la presencia de campos específicos (date_create y user_id), el analizador aplica una lógica diferente para asignar los campos de registro sin procesar al modelo de datos unificado, incluida la información de metadatos, principal, red, destino y acerca de, y crea un resultado de seguridad.
Antes de empezar
Asegúrate de que cumples los siguientes requisitos previos:
- Una instancia de Google SecOps
- Acceso privilegiado al arrendatario de Slack Enterprise Grid y a la consola de administración
- Acceso privilegiado a las funciones de Cloud Run y Cloud Scheduler de GCP
Requisitos previos para recoger registros de auditoría de Slack (ID de aplicación, token de OAuth e ID de organización)
- Inicia sesión en la consola de administración de Slack de tu organización Enterprise Grid.
- Ve a https://api.slack.com/apps y haz clic en Create New App > From scratch (Crear aplicación > desde cero).
- Introduce el Nombre de la aplicación y selecciona tu Espacio de trabajo de Slack de desarrollo.
- Haz clic en Create App (Crear aplicación).
- En la barra lateral de la izquierda, ve a OAuth y permisos.
- Ve a la sección Scopes (Ámbitos) y añade el siguiente User Token Scope (Ámbito de token de usuario):
- auditlogs:read
- Haz clic en Instalar en Workspace > Permitir.
- Una vez instalada, ve a Aplicaciones a nivel de organización > Instalar en la organización.
- Autoriza la aplicación con una cuenta de propietario o administrador de la organización.
- Copia y guarda de forma segura el token de OAuth de usuario que empieza por
xoxp-(este es tu SLACK_ADMIN_TOKEN). - Copia tu ID de organización, que se encuentra en la consola de administración de Slack, en Ajustes y permisos > Ajustes de la organización.
Configurar el directorio
- Crea un directorio en tu máquina local para la implementación de la función de Cloud Run.
- Descarga los siguientes archivos del repositorio de GitHub ingestion-scripts de Chronicle:
- En la carpeta slack, descarga lo siguiente:
.env.ymlmain.pyrequirements.txt
- Desde la raíz del repositorio, descarga todo el directorio common con todos sus archivos:
common/__init__.pycommon/auth.pycommon/env_constants.pycommon/ingest.pycommon/status.pycommon/utils.py
- En la carpeta slack, descarga lo siguiente:
- Coloca todos los archivos descargados en el directorio de implementación.
La estructura de tu directorio debería ser similar a esta:
deployment_directory/
├─common/
│ ├─__init__.py
│ ├─auth.py
│ ├─env_constants.py
│ ├─ingest.py
│ ├─status.py
│ └─utils.py
├─.env.yml
├─main.py
└─requirements.txt
Crear secretos en Google Secret Manager
- En la Google Cloud consola, ve a Seguridad > Secret Manager.
- Haz clic en Crear secreto.
- Proporciona los siguientes detalles de configuración de la cuenta de servicio de Chronicle:
- Nombre: escribe
chronicle-service-account. - Valor secreto: pega el contenido de tu archivo JSON de autenticación de ingestión de Google SecOps.
- Nombre: escribe
- Haz clic en Crear secreto.
Copia el nombre de recurso del secreto con el siguiente formato:
projects/<PROJECT_ID>/secrets/chronicle-service-account/versions/latestVuelve a hacer clic en Crear secreto para crear un segundo secreto.
Proporciona los siguientes detalles de configuración del token de Slack:
- Nombre: escribe
slack-admin-token. - Valor de secreto: pega tu token de OAuth de usuario de Slack (empieza por
xoxp-).
- Nombre: escribe
Haz clic en Crear secreto.
Copia el nombre de recurso del secreto con el siguiente formato:
projects/<PROJECT_ID>/secrets/slack-admin-token/versions/latest
Definir las variables de entorno de tiempo de ejecución necesarias
- Abre el archivo
.env.ymlen el directorio de implementación. Configura las variables de entorno con tus valores:
CHRONICLE_CUSTOMER_ID: "<your-chronicle-customer-id>" CHRONICLE_REGION: us CHRONICLE_SERVICE_ACCOUNT: "projects/<PROJECT_ID>/secrets/chronicle-service-account/versions/latest" CHRONICLE_NAMESPACE: "" POLL_INTERVAL: "5" SLACK_ADMIN_TOKEN: "projects/<PROJECT_ID>/secrets/slack-admin-token/versions/latest"- Sustituye lo siguiente:
<your-chronicle-customer-id>: tu ID de cliente de Google SecOps.<PROJECT_ID>: tu ID de proyecto Google Cloud .- CHRONICLE_REGION asigna tu región de Google SecOps. Valores válidos:
us,asia-northeast1,asia-south1,asia-southeast1,australia-southeast1,europe,europe-west2,europe-west3,europe-west6,europe-west9,europe-west12,me-central1,me-central2,me-west1,northamerica-northeast2ysouthamerica-east1. - POLL_INTERVAL intervalo de frecuencia (en minutos) con el que se ejecuta la función. Esta duración debe ser la misma que el intervalo de la tarea de Cloud Scheduler.
- Sustituye lo siguiente:
Guarda el archivo
.env.yml.
Desplegar la función de Cloud Run
- Abre un terminal o Cloud Shell en la consola. Google Cloud
Ve al directorio de implementación:
cd /path/to/deployment_directoryEjecuta el siguiente comando para desplegar la función de Cloud Run:
gcloud functions deploy slack-audit-to-chronicle \ --entry-point main \ --trigger-http \ --runtime python39 \ --env-vars-file .env.yml \ --timeout 300s \ --memory 512MB \ --service-account <SERVICE_ACCOUNT_EMAIL>- Sustituye
<SERVICE_ACCOUNT_EMAIL>por la dirección de correo de la cuenta de servicio que quieras que use tu función de Cloud Run.
- Sustituye
Espera a que se complete la implementación.
Una vez desplegada, anota la URL de la función del resultado.
Configurar Cloud Scheduler
- En la consola deGoogle Cloud , ve a Cloud Scheduler > Crear trabajo.
- Proporcione los siguientes detalles de configuración:
- Nombre: escribe
slack-audit-scheduler. - Región: selecciona la misma región en la que has implementado la función de Cloud Run.
- Frecuencia: introduce
*/5 * * * *(se ejecuta cada 5 minutos, lo que coincide con el valor dePOLL_INTERVAL). - Zona horaria: selecciona UTC.
- Tipo de destino: selecciona HTTP.
- URL: introduce la URL de la función de Cloud Run del resultado de la implementación.
- Método HTTP: selecciona POST.
- Encabezado de autorización: selecciona Añadir token de OIDC.
- Cuenta de servicio: selecciona la misma cuenta de servicio que se ha usado para la función de Cloud Run.
- Nombre: escribe
- Haz clic en Crear.
Tabla de asignación de UDM
| Campo de registro | Asignación de UDM | Lógica |
|---|---|---|
action |
metadata.product_event_type |
Se asigna directamente desde el campo action del registro sin procesar. |
actor.type |
principal.labels.value |
Se asigna directamente desde el campo actor.type, con la clave actor.type añadida. |
actor.user.email |
principal.user.email_addresses |
Se asigna directamente desde el campo actor.user.email. |
actor.user.id |
principal.user.product_object_id |
Se asigna directamente desde el campo actor.user.id. |
actor.user.id |
principal.user.userid |
Se asigna directamente desde el campo actor.user.id. |
actor.user.name |
principal.user.user_display_name |
Se asigna directamente desde el campo actor.user.name. |
actor.user.team |
principal.user.group_identifiers |
Se asigna directamente desde el campo actor.user.team. |
context.ip_address |
principal.ip |
Se asigna directamente desde el campo context.ip_address. |
context.location.domain |
about.resource.attribute.labels.value |
Se asigna directamente desde el campo context.location.domain, con la clave context.location.domain añadida. |
context.location.id |
about.resource.id |
Se asigna directamente desde el campo context.location.id. |
context.location.name |
about.resource.name |
Se asigna directamente desde el campo context.location.name. |
context.location.name |
about.resource.attribute.labels.value |
Se asigna directamente desde el campo context.location.name, con la clave context.location.name añadida. |
context.location.type |
about.resource.resource_subtype |
Se asigna directamente desde el campo context.location.type. |
context.session_id |
network.session_id |
Se asigna directamente desde el campo context.session_id. |
context.ua |
network.http.user_agent |
Se asigna directamente desde el campo context.ua. |
context.ua |
network.http.parsed_user_agent |
Información analizada del user-agent derivada del campo context.ua mediante el filtro parseduseragent. |
country |
principal.location.country_or_region |
Se asigna directamente desde el campo country. |
date_create |
metadata.event_timestamp.seconds |
La marca de tiempo de la época del campo date_create se convierte en un objeto de marca de tiempo. |
details.inviter.email |
target.user.email_addresses |
Se asigna directamente desde el campo details.inviter.email. |
details.inviter.id |
target.user.product_object_id |
Se asigna directamente desde el campo details.inviter.id. |
details.inviter.name |
target.user.user_display_name |
Se asigna directamente desde el campo details.inviter.name. |
details.inviter.team |
target.user.group_identifiers |
Se asigna directamente desde el campo details.inviter.team. |
details.reason |
security_result.description |
Se asigna directamente desde el campo details.reason o, si es una matriz, se concatena con comas. |
details.type |
about.resource.attribute.labels.value |
Se asigna directamente desde el campo details.type, con la clave details.type añadida. |
details.type |
security_result.summary |
Se asigna directamente desde el campo details.type. |
entity.app.id |
target.resource.id |
Se asigna directamente desde el campo entity.app.id. |
entity.app.name |
target.resource.name |
Se asigna directamente desde el campo entity.app.name. |
entity.channel.id |
target.resource.id |
Se asigna directamente desde el campo entity.channel.id. |
entity.channel.name |
target.resource.name |
Se asigna directamente desde el campo entity.channel.name. |
entity.channel.privacy |
target.resource.attribute.labels.value |
Se asigna directamente desde el campo entity.channel.privacy, con la clave entity.channel.privacy añadida. |
entity.file.filetype |
target.resource.attribute.labels.value |
Se asigna directamente desde el campo entity.file.filetype, con la clave entity.file.filetype añadida. |
entity.file.id |
target.resource.id |
Se asigna directamente desde el campo entity.file.id. |
entity.file.name |
target.resource.name |
Se asigna directamente desde el campo entity.file.name. |
entity.file.title |
target.resource.attribute.labels.value |
Se asigna directamente desde el campo entity.file.title, con la clave entity.file.title añadida. |
entity.huddle.date_end |
about.resource.attribute.labels.value |
Se asigna directamente desde el campo entity.huddle.date_end, con la clave entity.huddle.date_end añadida. |
entity.huddle.date_start |
about.resource.attribute.labels.value |
Se asigna directamente desde el campo entity.huddle.date_start, con la clave entity.huddle.date_start añadida. |
entity.huddle.id |
about.resource.attribute.labels.value |
Se asigna directamente desde el campo entity.huddle.id, con la clave entity.huddle.id añadida. |
entity.huddle.participants.0 |
about.resource.attribute.labels.value |
Se asigna directamente desde el campo entity.huddle.participants.0, con la clave entity.huddle.participants.0 añadida. |
entity.huddle.participants.1 |
about.resource.attribute.labels.value |
Se asigna directamente desde el campo entity.huddle.participants.1, con la clave entity.huddle.participants.1 añadida. |
entity.type |
target.resource.resource_subtype |
Se asigna directamente desde el campo entity.type. |
entity.user.email |
target.user.email_addresses |
Se asigna directamente desde el campo entity.user.email. |
entity.user.id |
target.user.product_object_id |
Se asigna directamente desde el campo entity.user.id. |
entity.user.name |
target.user.user_display_name |
Se asigna directamente desde el campo entity.user.name. |
entity.user.team |
target.user.group_identifiers |
Se asigna directamente desde el campo entity.user.team. |
entity.workflow.id |
target.resource.id |
Se asigna directamente desde el campo entity.workflow.id. |
entity.workflow.name |
target.resource.name |
Se asigna directamente desde el campo entity.workflow.name. |
id |
metadata.product_log_id |
Se asigna directamente desde el campo id. |
ip |
principal.ip |
Se asigna directamente desde el campo ip. Determinado por la lógica basada en el campo action. El valor predeterminado es USER_COMMUNICATION, pero cambia a otros valores, como USER_CREATION, USER_LOGIN, USER_LOGOUT, USER_RESOURCE_ACCESS, USER_RESOURCE_UPDATE_PERMISSIONS o USER_CHANGE_PERMISSIONS, en función del valor de action. Codificado como "SLACK_AUDIT". Se establece en "Enterprise Grid" si existe date_create. De lo contrario, se establece en "Registros de auditoría" si existe user_id. Codificado como "Slack". Codificado como "REMOTE". Asigna el valor "SSO" si action contiene "user_login" o "user_logout". De lo contrario, asigna el valor "MACHINE". No se ha asignado en los ejemplos proporcionados. El valor predeterminado es "ALLOW", pero se define como "BLOCK" si action es "user_login_failed". Se asigna el valor "Slack" si existe date_create. De lo contrario, se asigna el valor "SLACK" si existe user_id. |
user_agent |
network.http.user_agent |
Se asigna directamente desde el campo user_agent. |
user_id |
principal.user.product_object_id |
Se asigna directamente desde el campo user_id. |
username |
principal.user.product_object_id |
Se asigna directamente desde el campo username. |
¿Necesitas más ayuda? Recibe respuestas de los miembros de la comunidad y de los profesionales de Google SecOps.