Collecter les journaux d'audit Slack
Ce document explique comment ingérer des journaux d'audit Slack dans Google Security Operations à l'aide de fonctions Google Cloud Run. L'analyseur gère deux formats de journaux d'audit Slack. Elle normalise d'abord les valeurs booléennes et efface les champs prédéfinis. Il analyse ensuite le champ "message" en tant que JSON, en supprimant les messages non JSON. En fonction de la présence de champs spécifiques (date_create
et user_id
), l'analyseur applique une logique différente pour mapper les champs de journaux bruts à l'UDM, y compris les métadonnées, les informations sur le principal, le réseau, la cible et les informations "À propos", et construit un résultat de sécurité.
Avant de commencer
Assurez-vous de remplir les conditions suivantes :
- Une instance Google SecOps
- Accès privilégié au locataire Slack Enterprise Grid et à la console d'administration
- Accès privilégié aux fonctions Cloud Run et Cloud Scheduler de GCP
Collecter les journaux d'audit Slack (ID d'application, jeton OAuth, ID d'organisation)
- Connectez-vous à la console d'administration Slack de votre organisation Enterprise Grid.
- Accédez à https://api.slack.com/apps, puis cliquez sur Create New App > From scratch (Créer une application > À partir de zéro).
- Saisissez le nom de l'application et sélectionnez votre espace de travail Slack de développement.
- Cliquez sur Créer une application.
- Accédez à OAuth et autorisations dans la barre latérale de gauche.
- Accédez à la section Scopes (Champs d'application) et ajoutez le champ d'application des jetons d'utilisateur suivant :
- auditlogs:read
- Cliquez sur Installer dans Workspace > Autoriser.
- Une fois l'application installée, accédez à Applications au niveau de l'organisation> Installer dans l'organisation.
- Autorisez l'application avec un compte propriétaire/administrateur de l'organisation.
- Copiez et enregistrez de manière sécurisée le jeton OAuth de l'utilisateur qui commence par
xoxp-
(il s'agit de votre SLACK_ADMIN_TOKEN). - Copiez votre ID d'organisation, que vous trouverez dans la console d'administration Slack sous Paramètres et autorisations > Paramètres de l'organisation.
Configurer le répertoire
- Créez un répertoire sur votre ordinateur local pour le déploiement de la fonction Cloud Run.
- Téléchargez les fichiers suivants à partir du dépôt GitHub des scripts d'ingestion Chronicle :
- Dans le dossier slack, téléchargez :
.env.yml
main.py
requirements.txt
- À partir de la racine du dépôt, téléchargez l'intégralité du répertoire common avec tous ses fichiers :
common/__init__.py
common/auth.py
common/env_constants.py
common/ingest.py
common/status.py
common/utils.py
- Dans le dossier slack, téléchargez :
- Placez tous les fichiers téléchargés dans votre répertoire de déploiement.
La structure de votre répertoire devrait se présenter comme suit :
deployment_directory/
├─common/
│ ├─__init__.py
│ ├─auth.py
│ ├─env_constants.py
│ ├─ingest.py
│ ├─status.py
│ └─utils.py
├─.env.yml
├─main.py
└─requirements.txt
Créer des secrets dans Google Secret Manager
- Dans la consoleGoogle Cloud , accédez à Sécurité > Secret Manager.
- Cliquez sur Créer un secret.
- Fournissez les informations de configuration suivantes pour le compte de service Chronicle :
- Nom : saisissez
chronicle-service-account
. - Valeur du secret : collez le contenu de votre fichier JSON d'authentification pour l'ingestion Google SecOps.
- Nom : saisissez
- Cliquez sur Créer un secret.
Copiez le nom de ressource secret au format suivant :
projects/<PROJECT_ID>/secrets/chronicle-service-account/versions/latest
Cliquez de nouveau sur Créer un secret pour créer un deuxième secret.
Fournissez les informations de configuration suivantes pour le jeton Slack :
- Nom : saisissez
slack-admin-token
. - Valeur secrète : collez votre jeton OAuth utilisateur Slack (commençant par
xoxp-
).
- Nom : saisissez
Cliquez sur Créer un secret.
Copiez le nom de ressource secret au format suivant :
projects/<PROJECT_ID>/secrets/slack-admin-token/versions/latest
Définir les variables d'environnement d'exécution requises
- Ouvrez le fichier
.env.yml
dans votre répertoire de déploiement. Configurez les variables d'environnement avec vos valeurs :
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"
- Remplacez l'élément suivant :
<your-chronicle-customer-id>
: ID client Google SecOps.<PROJECT_ID>
: ID de votre projet Google Cloud .- CHRONICLE_REGION : définissez la région Google SecOps. Valeurs valides :
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 : intervalle de fréquence (en minutes) auquel la fonction s'exécute. Cette durée doit être identique à l'intervalle de la tâche Cloud Scheduler.
- Remplacez l'élément suivant :
Enregistrez le fichier
.env.yml
.
Déployer la fonction Cloud Run
- Ouvrez un terminal ou Cloud Shell dans la console Google Cloud .
Accédez au répertoire de votre déploiement :
cd /path/to/deployment_directory
Exécutez la commande suivante pour déployer la fonction 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>
- Remplacez
<SERVICE_ACCOUNT_EMAIL>
par l'adresse e-mail du compte de service que vous souhaitez que votre fonction Cloud Run utilise.
- Remplacez
Attendez la fin du déploiement.
Une fois la fonction déployée, notez son URL dans le résultat.
Configurer Cloud Scheduler
- Dans la consoleGoogle Cloud , accédez à Cloud Scheduler > Créer un job.
- Fournissez les informations de configuration suivantes :
- Nom : saisissez
slack-audit-scheduler
. - Région : sélectionnez la même région que celle dans laquelle vous avez déployé la fonction Cloud Run.
- Fréquence : saisissez
*/5 * * * *
(l'exécution a lieu toutes les cinq minutes, ce qui correspond à la valeurPOLL_INTERVAL
). - Fuseau horaire : sélectionnez UTC.
- Type de cible : sélectionnez HTTP.
- URL : saisissez l'URL de la fonction Cloud Run à partir du résultat de déploiement.
- Méthode HTTP : sélectionnez POST.
- En-tête de l'authentification : sélectionnez Ajouter un jeton OIDC.
- Compte de service : sélectionnez le même compte de service que celui utilisé pour la fonction Cloud Run.
- Nom : saisissez
- Cliquez sur Créer.
Table de mappage UDM
Champ de journal | Mappage UDM | Logique |
---|---|---|
action |
metadata.product_event_type |
Directement mappé à partir du champ action dans le journal brut. |
actor.type |
principal.labels.value |
Directement mappé à partir du champ actor.type , avec la clé actor.type ajoutée. |
actor.user.email |
principal.user.email_addresses |
Mappé directement à partir du champ actor.user.email . |
actor.user.id |
principal.user.product_object_id |
Mappé directement à partir du champ actor.user.id . |
actor.user.id |
principal.user.userid |
Mappé directement à partir du champ actor.user.id . |
actor.user.name |
principal.user.user_display_name |
Mappé directement à partir du champ actor.user.name . |
actor.user.team |
principal.user.group_identifiers |
Mappé directement à partir du champ actor.user.team . |
context.ip_address |
principal.ip |
Mappé directement à partir du champ context.ip_address . |
context.location.domain |
about.resource.attribute.labels.value |
Directement mappé à partir du champ context.location.domain , avec la clé context.location.domain ajoutée. |
context.location.id |
about.resource.id |
Mappé directement à partir du champ context.location.id . |
context.location.name |
about.resource.name |
Mappé directement à partir du champ context.location.name . |
context.location.name |
about.resource.attribute.labels.value |
Directement mappé à partir du champ context.location.name , avec la clé context.location.name ajoutée. |
context.location.type |
about.resource.resource_subtype |
Mappé directement à partir du champ context.location.type . |
context.session_id |
network.session_id |
Mappé directement à partir du champ context.session_id . |
context.ua |
network.http.user_agent |
Mappé directement à partir du champ context.ua . |
context.ua |
network.http.parsed_user_agent |
Informations analysées sur l'agent utilisateur, dérivées du champ context.ua à l'aide du filtre parseduseragent . |
country |
principal.location.country_or_region |
Mappé directement à partir du champ country . |
date_create |
metadata.event_timestamp.seconds |
L'horodatage epoch du champ date_create est converti en objet d'horodatage. |
details.inviter.email |
target.user.email_addresses |
Mappé directement à partir du champ details.inviter.email . |
details.inviter.id |
target.user.product_object_id |
Mappé directement à partir du champ details.inviter.id . |
details.inviter.name |
target.user.user_display_name |
Mappé directement à partir du champ details.inviter.name . |
details.inviter.team |
target.user.group_identifiers |
Mappé directement à partir du champ details.inviter.team . |
details.reason |
security_result.description |
Directement mappé à partir du champ details.reason ou, s'il s'agit d'un tableau, concaténé avec des virgules. |
details.type |
about.resource.attribute.labels.value |
Directement mappé à partir du champ details.type , avec la clé details.type ajoutée. |
details.type |
security_result.summary |
Mappé directement à partir du champ details.type . |
entity.app.id |
target.resource.id |
Mappé directement à partir du champ entity.app.id . |
entity.app.name |
target.resource.name |
Mappé directement à partir du champ entity.app.name . |
entity.channel.id |
target.resource.id |
Mappé directement à partir du champ entity.channel.id . |
entity.channel.name |
target.resource.name |
Mappé directement à partir du champ entity.channel.name . |
entity.channel.privacy |
target.resource.attribute.labels.value |
Directement mappé à partir du champ entity.channel.privacy , avec la clé entity.channel.privacy ajoutée. |
entity.file.filetype |
target.resource.attribute.labels.value |
Directement mappé à partir du champ entity.file.filetype , avec la clé entity.file.filetype ajoutée. |
entity.file.id |
target.resource.id |
Mappé directement à partir du champ entity.file.id . |
entity.file.name |
target.resource.name |
Mappé directement à partir du champ entity.file.name . |
entity.file.title |
target.resource.attribute.labels.value |
Directement mappé à partir du champ entity.file.title , avec la clé entity.file.title ajoutée. |
entity.huddle.date_end |
about.resource.attribute.labels.value |
Directement mappé à partir du champ entity.huddle.date_end , avec la clé entity.huddle.date_end ajoutée. |
entity.huddle.date_start |
about.resource.attribute.labels.value |
Directement mappé à partir du champ entity.huddle.date_start , avec la clé entity.huddle.date_start ajoutée. |
entity.huddle.id |
about.resource.attribute.labels.value |
Directement mappé à partir du champ entity.huddle.id , avec la clé entity.huddle.id ajoutée. |
entity.huddle.participants.0 |
about.resource.attribute.labels.value |
Directement mappé à partir du champ entity.huddle.participants.0 , avec la clé entity.huddle.participants.0 ajoutée. |
entity.huddle.participants.1 |
about.resource.attribute.labels.value |
Directement mappé à partir du champ entity.huddle.participants.1 , avec la clé entity.huddle.participants.1 ajoutée. |
entity.type |
target.resource.resource_subtype |
Mappé directement à partir du champ entity.type . |
entity.user.email |
target.user.email_addresses |
Mappé directement à partir du champ entity.user.email . |
entity.user.id |
target.user.product_object_id |
Mappé directement à partir du champ entity.user.id . |
entity.user.name |
target.user.user_display_name |
Mappé directement à partir du champ entity.user.name . |
entity.user.team |
target.user.group_identifiers |
Mappé directement à partir du champ entity.user.team . |
entity.workflow.id |
target.resource.id |
Mappé directement à partir du champ entity.workflow.id . |
entity.workflow.name |
target.resource.name |
Mappé directement à partir du champ entity.workflow.name . |
id |
metadata.product_log_id |
Mappé directement à partir du champ id . |
ip |
principal.ip |
Mappé directement à partir du champ ip . Déterminé par une logique basée sur le champ action . La valeur par défaut est USER_COMMUNICATION , mais elle peut être remplacée par d'autres valeurs telles que USER_CREATION , USER_LOGIN , USER_LOGOUT , USER_RESOURCE_ACCESS , USER_RESOURCE_UPDATE_PERMISSIONS ou USER_CHANGE_PERMISSIONS en fonction de la valeur de action . Codé en dur sur "SLACK_AUDIT". Défini sur "Enterprise Grid" si date_create existe, sinon défini sur "Journaux d'audit" si user_id existe. Codé en dur sur "Slack". Codé en dur sur "REMOTE". Définissez sur "SSO" si action contient "user_login" ou "user_logout". Sinon, définissez-le sur "MACHINE". Non mappé dans les exemples fournis. La valeur par défaut est "ALLOW", mais elle est définie sur "BLOCK" si action est "user_login_failed". Définissez la valeur sur "Slack" si date_create existe, sinon définissez-la sur "SLACK" si user_id existe. |
user_agent |
network.http.user_agent |
Mappé directement à partir du champ user_agent . |
user_id |
principal.user.product_object_id |
Mappé directement à partir du champ user_id . |
username |
principal.user.product_object_id |
Mappé directement à partir du champ username . |
Vous avez encore besoin d'aide ? Obtenez des réponses de membres de la communauté et de professionnels Google SecOps.