Coletar registros de auditoria do Slack
Este documento explica como ingerir registros de auditoria do Slack no Google Security Operations usando funções do Google Cloud Run. O analisador processa dois formatos de registros de auditoria do Slack. Primeiro, ele normaliza os valores booleanos e limpa os campos predefinidos. Em seguida, ele analisa o campo "message" como JSON, descartando mensagens que não são JSON. Dependendo da presença de campos específicos (date_create
e user_id
), o analisador aplica uma lógica diferente para mapear campos de registros brutos no UDM, incluindo metadados, principal, rede, destino e informações sobre, e cria um resultado de segurança.
Antes de começar
Verifique se você tem os pré-requisitos a seguir:
- Uma instância do Google SecOps
- Acesso privilegiado ao locatário do Slack Enterprise Grid e ao Admin Console
- Acesso privilegiado às funções do Cloud Run e ao Cloud Scheduler do GCP
Coletar os pré-requisitos dos registros de auditoria do Slack (ID do app, token OAuth, ID da organização)
- Faça login no Admin Console do Slack da sua organização do Enterprise Grid.
- Acesse https://api.slack.com/apps e clique em Criar novo app > Do zero.
- Insira o Nome do app e selecione o espaço de trabalho do Slack de desenvolvimento.
- Clique em Criar app.
- Acesse OAuth e permissões na barra lateral esquerda.
- Acesse a seção Escopos e adicione o seguinte Escopo do token do usuário:
- auditlogs:read
- Clique em Instalar no Workspace > Permitir.
- Depois de instalado, acesse Apps no nível da organização > Instalar na organização.
- Autorize o app com uma conta de proprietário/administrador da organização.
- Copie e salve com segurança o token OAuth do usuário que começa com
xoxp-
. Esse é o SLACK_ADMIN_TOKEN. - Copie seu ID da organização, que pode ser encontrado no Admin Console do Slack em Configurações e permissões > Configurações da organização.
Como configurar o diretório
- Crie um diretório na máquina local para a implantação da função do Cloud Run.
- Faça o download dos seguintes arquivos do repositório do GitHub de scripts de ingestão do Chronicle:
- Na pasta slack, faça o download de:
.env.yml
main.py
requirements.txt
- Na raiz do repositório, faça o download de todo o diretório common com todos os arquivos:
common/__init__.py
common/auth.py
common/env_constants.py
common/ingest.py
common/status.py
common/utils.py
- Na pasta slack, faça o download de:
- Coloque todos os arquivos baixados no diretório de implantação.
Sua estrutura de diretórios deve ser parecida com esta:
deployment_directory/
├─common/
│ ├─__init__.py
│ ├─auth.py
│ ├─env_constants.py
│ ├─ingest.py
│ ├─status.py
│ └─utils.py
├─.env.yml
├─main.py
└─requirements.txt
Criar secrets no Google Secret Manager
- No consoleGoogle Cloud , acesse Segurança > Secret Manager.
- Clique em Criar secret.
- Forneça os seguintes detalhes de configuração para a conta de serviço do Chronicle:
- Nome: insira
chronicle-service-account
. - Valor secreto: cole o conteúdo do arquivo JSON de autenticação de ingestão do Google SecOps.
- Nome: insira
- Clique em Criar secret.
Copie o nome do recurso secret no seguinte formato:
projects/<PROJECT_ID>/secrets/chronicle-service-account/versions/latest
Clique em Criar secret novamente para criar um segundo secret.
Forneça os seguintes detalhes de configuração para o token do Slack:
- Nome: insira
slack-admin-token
. - Valor da chave secreta: cole seu token OAuth de usuário do Slack (começando com
xoxp-
).
- Nome: insira
Clique em Criar secret.
Copie o nome do recurso secret no seguinte formato:
projects/<PROJECT_ID>/secrets/slack-admin-token/versions/latest
Como definir as variáveis de ambiente de execução necessárias
- Abra o arquivo
.env.yml
no diretório de implantação. Configure as variáveis de ambiente com seus 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"
- Substitua:
<your-chronicle-customer-id>
: seu ID de cliente do Google SecOps.<PROJECT_ID>
: o ID do projeto do Google Cloud .- CHRONICLE_REGION: defina como sua região do 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: intervalo de frequência (em minutos) em que a função é executada. Essa duração precisa ser a mesma do intervalo do job do Cloud Scheduler.
- Substitua:
Salve o arquivo
.env.yml
.
Como implantar a função do Cloud Run
- Abra um terminal ou o Cloud Shell no console Google Cloud .
Navegue até o diretório de implantação:
cd /path/to/deployment_directory
Execute o comando a seguir para implantar a função do 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>
- Substitua
<SERVICE_ACCOUNT_EMAIL>
pelo endereço de e-mail da conta de serviço que você quer que a função do Cloud Run use.
- Substitua
Aguarde a conclusão da implantação.
Depois da implantação, observe o URL da função na saída.
Configurar o Cloud Scheduler
- No consoleGoogle Cloud , acesse Cloud Scheduler > Criar job.
- Informe os seguintes detalhes de configuração:
- Nome: insira
slack-audit-scheduler
. - Região: selecione a mesma região em que você implantou a função do Cloud Run.
- Frequência: insira
*/5 * * * *
(executa a cada 5 minutos, correspondendo ao valorPOLL_INTERVAL
). - Fuso horário: selecione UTC.
- Tipo de destino: selecione HTTP.
- URL: insira o URL da função do Cloud Run na saída da implantação.
- Método HTTP: selecione POST.
- Cabeçalho de autenticação: selecione Adicionar token OIDC.
- Conta de serviço: selecione a mesma conta de serviço usada para a função do Cloud Run.
- Nome: insira
- Clique em Criar.
Tabela de mapeamento do UDM
Campo de registro | Mapeamento do UDM | Lógica |
---|---|---|
action |
metadata.product_event_type |
Mapeado diretamente do campo action no registro bruto. |
actor.type |
principal.labels.value |
Mapeado diretamente do campo actor.type , com a chave actor.type adicionada. |
actor.user.email |
principal.user.email_addresses |
Mapeado diretamente do campo actor.user.email . |
actor.user.id |
principal.user.product_object_id |
Mapeado diretamente do campo actor.user.id . |
actor.user.id |
principal.user.userid |
Mapeado diretamente do campo actor.user.id . |
actor.user.name |
principal.user.user_display_name |
Mapeado diretamente do campo actor.user.name . |
actor.user.team |
principal.user.group_identifiers |
Mapeado diretamente do campo actor.user.team . |
context.ip_address |
principal.ip |
Mapeado diretamente do campo context.ip_address . |
context.location.domain |
about.resource.attribute.labels.value |
Mapeado diretamente do campo context.location.domain , com a chave context.location.domain adicionada. |
context.location.id |
about.resource.id |
Mapeado diretamente do campo context.location.id . |
context.location.name |
about.resource.name |
Mapeado diretamente do campo context.location.name . |
context.location.name |
about.resource.attribute.labels.value |
Mapeado diretamente do campo context.location.name , com a chave context.location.name adicionada. |
context.location.type |
about.resource.resource_subtype |
Mapeado diretamente do campo context.location.type . |
context.session_id |
network.session_id |
Mapeado diretamente do campo context.session_id . |
context.ua |
network.http.user_agent |
Mapeado diretamente do campo context.ua . |
context.ua |
network.http.parsed_user_agent |
Informações analisadas do user agent derivadas do campo context.ua usando o filtro parseduseragent . |
country |
principal.location.country_or_region |
Mapeado diretamente do campo country . |
date_create |
metadata.event_timestamp.seconds |
O carimbo de data/hora da época do campo date_create é convertido em um objeto de carimbo de data/hora. |
details.inviter.email |
target.user.email_addresses |
Mapeado diretamente do campo details.inviter.email . |
details.inviter.id |
target.user.product_object_id |
Mapeado diretamente do campo details.inviter.id . |
details.inviter.name |
target.user.user_display_name |
Mapeado diretamente do campo details.inviter.name . |
details.inviter.team |
target.user.group_identifiers |
Mapeado diretamente do campo details.inviter.team . |
details.reason |
security_result.description |
Mapeado diretamente do campo details.reason ou, se for uma matriz, concatenado com vírgulas. |
details.type |
about.resource.attribute.labels.value |
Mapeado diretamente do campo details.type , com a chave details.type adicionada. |
details.type |
security_result.summary |
Mapeado diretamente do campo details.type . |
entity.app.id |
target.resource.id |
Mapeado diretamente do campo entity.app.id . |
entity.app.name |
target.resource.name |
Mapeado diretamente do campo entity.app.name . |
entity.channel.id |
target.resource.id |
Mapeado diretamente do campo entity.channel.id . |
entity.channel.name |
target.resource.name |
Mapeado diretamente do campo entity.channel.name . |
entity.channel.privacy |
target.resource.attribute.labels.value |
Mapeado diretamente do campo entity.channel.privacy , com a chave entity.channel.privacy adicionada. |
entity.file.filetype |
target.resource.attribute.labels.value |
Mapeado diretamente do campo entity.file.filetype , com a chave entity.file.filetype adicionada. |
entity.file.id |
target.resource.id |
Mapeado diretamente do campo entity.file.id . |
entity.file.name |
target.resource.name |
Mapeado diretamente do campo entity.file.name . |
entity.file.title |
target.resource.attribute.labels.value |
Mapeado diretamente do campo entity.file.title , com a chave entity.file.title adicionada. |
entity.huddle.date_end |
about.resource.attribute.labels.value |
Mapeado diretamente do campo entity.huddle.date_end , com a chave entity.huddle.date_end adicionada. |
entity.huddle.date_start |
about.resource.attribute.labels.value |
Mapeado diretamente do campo entity.huddle.date_start , com a chave entity.huddle.date_start adicionada. |
entity.huddle.id |
about.resource.attribute.labels.value |
Mapeado diretamente do campo entity.huddle.id , com a chave entity.huddle.id adicionada. |
entity.huddle.participants.0 |
about.resource.attribute.labels.value |
Mapeado diretamente do campo entity.huddle.participants.0 , com a chave entity.huddle.participants.0 adicionada. |
entity.huddle.participants.1 |
about.resource.attribute.labels.value |
Mapeado diretamente do campo entity.huddle.participants.1 , com a chave entity.huddle.participants.1 adicionada. |
entity.type |
target.resource.resource_subtype |
Mapeado diretamente do campo entity.type . |
entity.user.email |
target.user.email_addresses |
Mapeado diretamente do campo entity.user.email . |
entity.user.id |
target.user.product_object_id |
Mapeado diretamente do campo entity.user.id . |
entity.user.name |
target.user.user_display_name |
Mapeado diretamente do campo entity.user.name . |
entity.user.team |
target.user.group_identifiers |
Mapeado diretamente do campo entity.user.team . |
entity.workflow.id |
target.resource.id |
Mapeado diretamente do campo entity.workflow.id . |
entity.workflow.name |
target.resource.name |
Mapeado diretamente do campo entity.workflow.name . |
id |
metadata.product_log_id |
Mapeado diretamente do campo id . |
ip |
principal.ip |
Mapeado diretamente do campo ip . Determinado por uma lógica baseada no campo action . O padrão é USER_COMMUNICATION , mas muda para outros valores, como USER_CREATION , USER_LOGIN , USER_LOGOUT , USER_RESOURCE_ACCESS , USER_RESOURCE_UPDATE_PERMISSIONS ou USER_CHANGE_PERMISSIONS , com base no valor de action . Fixado no código como "SLACK_AUDIT". Definido como "Enterprise Grid" se date_create existir. Caso contrário, definido como "Registros de auditoria" se user_id existir. Fixado no código como "Slack". Fixado no código como "REMOTE". Defina como "SSO" se action contiver "user_login" ou "user_logout". Caso contrário, defina como "MACHINE". Não mapeado nos exemplos fornecidos. O padrão é "ALLOW", mas é definido como "BLOCK" se action for "user_login_failed". Defina como "Slack" se date_create existir. Caso contrário, defina como "SLACK" se user_id existir. |
user_agent |
network.http.user_agent |
Mapeado diretamente do campo user_agent . |
user_id |
principal.user.product_object_id |
Mapeado diretamente do campo user_id . |
username |
principal.user.product_object_id |
Mapeado diretamente do campo username . |
Precisa de mais ajuda? Receba respostas de membros da comunidade e profissionais do Google SecOps.