Recopila registros de auditoría de Slack
En este documento, se explica cómo transferir Registros de auditoría de Slack a Google Security Operations con Cloud Run Functions de Google. El analizador controla dos formatos de registros de auditoría de Slack. Primero normaliza los valores booleanos y borra los campos predefinidos. Luego, analiza el campo "message" como JSON y descarta los mensajes que no son JSON. Según 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 UDM, incluida la información de metadatos, principal, red, destino y acerca de, y construye un resultado de seguridad.
Antes de comenzar
Asegúrate de cumplir con los siguientes requisitos previos:
- Una instancia de Google SecOps
- Acceso con privilegios al arrendatario de Slack Enterprise Grid y a la Consola del administrador
- Acceso privilegiado a las funciones de Cloud Run y Cloud Scheduler de GCP
Recopila los requisitos previos de los registros de auditoría de Slack (ID de app, token de OAuth y ID de organización)
- Accede a la Consola del administrador de Slack de tu organización de Enterprise Grid.
- Ve a https://api.slack.com/apps y haz clic en Crear una app nueva > Desde cero.
- Ingresa el Nombre de la app y selecciona tu Espacio de trabajo de Slack de desarrollo.
- Haz clic en Crear app.
- Navega a OAuth y permisos en la barra lateral izquierda.
- Ve a la sección Alcances y agrega el siguiente Alcance de token de usuario:
- auditlogs:read
- Haz clic en Instalar en Workspace > Permitir.
- Una vez instalado, navega a Org Level Apps > Install to Organization.
- Autoriza la app con una cuenta de administrador o propietario de la organización.
- Copia y guarda de forma segura el token de OAuth del usuario que comienza con
xoxp-
(este es tu SLACK_ADMIN_TOKEN). - Copia tu ID de organización, que se encuentra en la Consola del administrador de Slack en Configuración y permisos > Configuración de la organización.
Cómo configurar el directorio
- Crea un directorio nuevo en tu máquina local para la implementación de la función de Cloud Run.
- Descarga los siguientes archivos del repositorio de GitHub de Chronicle ingestion-scripts:
- En la carpeta slack, descarga lo siguiente:
.env.yml
main.py
requirements.txt
- Desde la raíz del repositorio, descarga todo el directorio common con todos sus archivos:
common/__init__.py
common/auth.py
common/env_constants.py
common/ingest.py
common/status.py
common/utils.py
- En la carpeta slack, descarga lo siguiente:
- Coloca todos los archivos descargados en tu directorio de implementación.
La estructura de tu directorio debería verse así:
deployment_directory/
├─common/
│ ├─__init__.py
│ ├─auth.py
│ ├─env_constants.py
│ ├─ingest.py
│ ├─status.py
│ └─utils.py
├─.env.yml
├─main.py
└─requirements.txt
Crea 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 para la cuenta de servicio de Chronicle:
- Nombre: Ingresa
chronicle-service-account
. - Valor del secreto: Pega el contenido de tu archivo JSON de autenticación de la transferencia de SecOps de Google.
- Nombre: Ingresa
- Haz clic en Crear secreto.
Copia el nombre del recurso secreto en el siguiente formato:
projects/<PROJECT_ID>/secrets/chronicle-service-account/versions/latest
Vuelve a hacer clic en Crear secreto para crear un segundo secreto.
Proporciona los siguientes detalles de configuración para el token de Slack:
- Nombre: Ingresa
slack-admin-token
. - Valor del secreto: Pega tu token de OAuth de usuario de Slack (comienza con
xoxp-
).
- Nombre: Ingresa
Haz clic en Crear secreto.
Copia el nombre del recurso secreto en el siguiente formato:
projects/<PROJECT_ID>/secrets/slack-admin-token/versions/latest
Cómo configurar las variables de entorno de ejecución requeridas
- Abre el archivo
.env.yml
en 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"
- Reemplaza lo siguiente:
<your-chronicle-customer-id>
: Es tu ID de cliente de Google SecOps.<PROJECT_ID>
: El ID de tu proyecto de Google Cloud .- CHRONICLE_REGION: Se establece en 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-northeast2
,southamerica-east1
. - POLL_INTERVAL: Es el intervalo de frecuencia (en minutos) con el que se ejecuta la función. Esta duración debe ser la misma que el intervalo del trabajo de Cloud Scheduler.
- Reemplaza lo siguiente:
Guarda el archivo
.env.yml
.
Implementa la Cloud Run Function
- Abre una terminal o Cloud Shell en la Google Cloud consola.
Navega al directorio de implementación:
cd /path/to/deployment_directory
Ejecuta el siguiente comando para implementar 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>
- Reemplaza
<SERVICE_ACCOUNT_EMAIL>
por la dirección de correo electrónico de la cuenta de servicio que deseas que use tu función de Cloud Run.
- Reemplaza
Espera a que se complete la implementación.
Una vez que se implemente, anota la URL de la función del resultado.
Configura Cloud Scheduler
- En la Google Cloud consola, ve a Cloud Scheduler > Crear trabajo.
- Proporciona los siguientes detalles de configuración:
- Nombre: Ingresa
slack-audit-scheduler
. - Región: Selecciona la misma región en la que implementaste la Cloud Run Function.
- Frecuencia: Ingresa
*/5 * * * *
(se ejecuta cada 5 minutos, lo que coincide con el valor dePOLL_INTERVAL
). - Zona horaria: Selecciona UTC.
- Tipo de destino: Selecciona HTTP.
- URL: Ingresa la URL de la función de Cloud Run que se muestra en el resultado de la implementación.
- Método HTTP: Selecciona POST.
- Encabezado de autenticación: Selecciona Agregar token de OIDC.
- Cuenta de servicio: Selecciona la misma cuenta de servicio que se usó para la función de Cloud Run.
- Nombre: Ingresa
- 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 en el registro sin procesar. |
actor.type |
principal.labels.value |
Se asigna directamente desde el campo actor.type , con la clave actor.type agregada. |
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 agregada. |
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 agregada. |
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 |
Es la información analizada del usuario-agente que se deriva del campo context.ua con 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 é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 un array, se concatena con comas. |
details.type |
about.resource.attribute.labels.value |
Se asigna directamente desde el campo details.type , con la clave details.type agregada. |
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 agregada. |
entity.file.filetype |
target.resource.attribute.labels.value |
Se asigna directamente desde el campo entity.file.filetype , con la clave entity.file.filetype agregada. |
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 agregada. |
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 agregada. |
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 agregada. |
entity.huddle.id |
about.resource.attribute.labels.value |
Se asigna directamente desde el campo entity.huddle.id , con la clave entity.huddle.id agregada. |
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 agregada. |
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 agregada. |
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 . Se determina según 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 , según el valor de action . Está 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 . Se codificó de forma rígida como "Slack". Se codificó de forma rígida como "REMOTE". Se establece en "SSO" si action contiene "user_login" o "user_logout". De lo contrario, configúralo como "MACHINE". No se asigna en los ejemplos proporcionados. El valor predeterminado es "ALLOW", pero se establece en "BLOCK" si action es "user_login_failed". Se establece en "Slack" si existe date_create ; de lo contrario, se establece en "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? Obtén respuestas de miembros de la comunidad y profesionales de Google SecOps.