Recolha registos de auditoria do Slack
Este documento explica como carregar registos de auditoria do Slack para o Google Security Operations através de funções do Google Cloud Run. O analisador processa dois formatos de registos de auditoria do Slack. Primeiro, normaliza os valores booleanos e limpa os campos predefinidos. Em seguida, analisa o campo "message" como JSON, processando as mensagens não JSON ao ignorá-las. Consoante a presença de campos específicos (date_create
e user_id
), o analisador aplica uma lógica diferente para mapear os campos de registo não processados para o UDM, incluindo metadados, principal, rede, destino e informações sobre, e cria um resultado de segurança.
Antes de começar
Certifique-se de que cumpre os seguintes pré-requisitos:
- Uma instância do Google SecOps
- Acesso privilegiado ao inquilino do Slack Enterprise Grid e à consola do administrador
- Acesso privilegiado às funções do Cloud Run e ao Cloud Scheduler da GCP
Pré-requisitos para recolher registos de auditoria do Slack (ID da app, token OAuth e ID da organização)
- Inicie sessão na consola de administração do Slack para a sua organização do Enterprise Grid.
- Aceda a https://api.slack.com/apps e clique em Create New App > From scratch.
- Introduza o Nome da app e selecione o seu espaço de trabalho do Slack de desenvolvimento.
- Clique em Criar app.
- Navegue para OAuth e autorizações na barra lateral esquerda.
- Aceda à secção Âmbitos e adicione o seguinte âmbito do token de utilizador:
- auditlogs:read
- Clique em Instalar no Workspace > Permitir.
- Depois de instalada, navegue para Apps ao nível da organização > Instalar na organização.
- Autorize a app com uma conta de proprietário/administrador da organização.
- Copie e guarde em segurança a chave OAuth do utilizador que começa com
xoxp-
(esta é a sua SLACK_ADMIN_TOKEN). - Copie o seu ID da organização, que pode encontrar na consola de administração do Slack em Definições e autorizações > Definições da organização.
Configurar o diretório
- Crie um novo diretório na sua máquina local para a implementação da função do Cloud Run.
- Transfira os seguintes ficheiros do repositório GitHub chronicle-ingestion-scripts:
- Na pasta slack, transfira:
.env.yml
main.py
requirements.txt
- A partir da raiz do repositório, transfira todo o diretório common com todos os respetivos ficheiros:
common/__init__.py
common/auth.py
common/env_constants.py
common/ingest.py
common/status.py
common/utils.py
- Na pasta slack, transfira:
- Coloque todos os ficheiros transferidos no diretório de implementação.
A estrutura do diretório deve ter o seguinte aspeto:
deployment_directory/
├─common/
│ ├─__init__.py
│ ├─auth.py
│ ├─env_constants.py
│ ├─ingest.py
│ ├─status.py
│ └─utils.py
├─.env.yml
├─main.py
└─requirements.txt
Crie Secrets no Google Secret Manager
- Na Google Cloud consola, aceda a Segurança > Secret Manager.
- Clique em Criar segredo.
- Forneça os seguintes detalhes de configuração para a conta de serviço do Chronicle:
- Nome: introduza
chronicle-service-account
. - Valor secreto: cole o conteúdo do seu ficheiro JSON de autenticação de carregamento do Google SecOps.
- Nome: introduza
- Clique em Criar segredo.
Copie o nome do recurso secreto no seguinte formato:
projects/<PROJECT_ID>/secrets/chronicle-service-account/versions/latest
Clique novamente em Criar segredo para criar um segundo segredo.
Faculte os seguintes detalhes de configuração para o token do Slack:
- Nome: introduza
slack-admin-token
. - Valor secreto: cole o seu símbolo OAuth de utilizador do Slack (começando por
xoxp-
).
- Nome: introduza
Clique em Criar segredo.
Copie o nome do recurso secreto no seguinte formato:
projects/<PROJECT_ID>/secrets/slack-admin-token/versions/latest
Definir as variáveis de ambiente de tempo de execução necessárias
- Abra o ficheiro
.env.yml
no diretório de implementação. Configure as variáveis de ambiente com os 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 o seguinte:
<your-chronicle-customer-id>
: o seu ID de cliente do Google SecOps.<PROJECT_ID>
: o ID do seu Google Cloud projeto.- CHRONICLE_REGION: definido para a 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
esouthamerica-east1
. - POLL_INTERVAL: intervalo de frequência (em minutos) em que a função é executada. Esta duração tem de ser igual ao intervalo da tarefa do Cloud Scheduler.
- Substitua o seguinte:
Guarde o ficheiro
.env.yml
.
Implementar a função do Cloud Run
- Abra um terminal ou o Cloud Shell na Google Cloud consola.
Navegue para o diretório de implementação:
cd /path/to/deployment_directory
Execute o seguinte comando para implementar 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 email da conta de serviço que quer que a sua função do Cloud Run use.
- Substitua
Aguarde a conclusão da implementação.
Após a implementação, tome nota do URL da função a partir da saída.
Configure o Cloud Scheduler
- Na Google Cloud consola, aceda a Cloud Scheduler > Criar tarefa.
- Indique os seguintes detalhes de configuração:
- Nome: introduza
slack-audit-scheduler
. - Região: selecione a mesma região onde implementou a função do Cloud Run.
- Frequência: introduza
*/5 * * * *
(executa-se a cada 5 minutos, correspondendo ao valorPOLL_INTERVAL
). - Fuso horário: selecione UTC.
- Tipo de destino: selecione HTTP.
- URL: introduza o URL da função do Cloud Run a partir da saída da implementação.
- Método HTTP: selecione POST.
- Cabeçalho de autorizaçã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: introduza
- Clique em Criar.
Tabela de mapeamento da UDM
Campo de registo | Mapeamento de UDM | Lógica |
---|---|---|
action |
metadata.product_event_type |
Mapeado diretamente a partir do campo action no registo não processado. |
actor.type |
principal.labels.value |
Mapeado diretamente a partir do campo actor.type , com a chave actor.type adicionada. |
actor.user.email |
principal.user.email_addresses |
Mapeado diretamente a partir do campo actor.user.email . |
actor.user.id |
principal.user.product_object_id |
Mapeado diretamente a partir do campo actor.user.id . |
actor.user.id |
principal.user.userid |
Mapeado diretamente a partir do campo actor.user.id . |
actor.user.name |
principal.user.user_display_name |
Mapeado diretamente a partir do campo actor.user.name . |
actor.user.team |
principal.user.group_identifiers |
Mapeado diretamente a partir do campo actor.user.team . |
context.ip_address |
principal.ip |
Mapeado diretamente a partir do campo context.ip_address . |
context.location.domain |
about.resource.attribute.labels.value |
Mapeado diretamente a partir do campo context.location.domain , com a chave context.location.domain adicionada. |
context.location.id |
about.resource.id |
Mapeado diretamente a partir do campo context.location.id . |
context.location.name |
about.resource.name |
Mapeado diretamente a partir do campo context.location.name . |
context.location.name |
about.resource.attribute.labels.value |
Mapeado diretamente a partir do campo context.location.name , com a chave context.location.name adicionada. |
context.location.type |
about.resource.resource_subtype |
Mapeado diretamente a partir do campo context.location.type . |
context.session_id |
network.session_id |
Mapeado diretamente a partir do campo context.session_id . |
context.ua |
network.http.user_agent |
Mapeado diretamente a partir do campo context.ua . |
context.ua |
network.http.parsed_user_agent |
Informações do agente do utilizador analisadas derivadas do campo context.ua através do filtro parseduseragent . |
country |
principal.location.country_or_region |
Mapeado diretamente a partir do campo country . |
date_create |
metadata.event_timestamp.seconds |
A indicação de tempo de época do campo date_create é convertida num objeto de indicação de tempo. |
details.inviter.email |
target.user.email_addresses |
Mapeado diretamente a partir do campo details.inviter.email . |
details.inviter.id |
target.user.product_object_id |
Mapeado diretamente a partir do campo details.inviter.id . |
details.inviter.name |
target.user.user_display_name |
Mapeado diretamente a partir do campo details.inviter.name . |
details.inviter.team |
target.user.group_identifiers |
Mapeado diretamente a partir do campo details.inviter.team . |
details.reason |
security_result.description |
Mapeado diretamente a partir do campo details.reason ou, se for uma matriz, concatenado com vírgulas. |
details.type |
about.resource.attribute.labels.value |
Mapeado diretamente a partir do campo details.type , com a chave details.type adicionada. |
details.type |
security_result.summary |
Mapeado diretamente a partir do campo details.type . |
entity.app.id |
target.resource.id |
Mapeado diretamente a partir do campo entity.app.id . |
entity.app.name |
target.resource.name |
Mapeado diretamente a partir do campo entity.app.name . |
entity.channel.id |
target.resource.id |
Mapeado diretamente a partir do campo entity.channel.id . |
entity.channel.name |
target.resource.name |
Mapeado diretamente a partir do campo entity.channel.name . |
entity.channel.privacy |
target.resource.attribute.labels.value |
Mapeado diretamente a partir do campo entity.channel.privacy , com a chave entity.channel.privacy adicionada. |
entity.file.filetype |
target.resource.attribute.labels.value |
Mapeado diretamente a partir do campo entity.file.filetype , com a chave entity.file.filetype adicionada. |
entity.file.id |
target.resource.id |
Mapeado diretamente a partir do campo entity.file.id . |
entity.file.name |
target.resource.name |
Mapeado diretamente a partir do campo entity.file.name . |
entity.file.title |
target.resource.attribute.labels.value |
Mapeado diretamente a partir do campo entity.file.title , com a chave entity.file.title adicionada. |
entity.huddle.date_end |
about.resource.attribute.labels.value |
Mapeado diretamente a partir 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 a partir do campo entity.huddle.date_start , com a chave entity.huddle.date_start adicionada. |
entity.huddle.id |
about.resource.attribute.labels.value |
Mapeado diretamente a partir do campo entity.huddle.id , com a chave entity.huddle.id adicionada. |
entity.huddle.participants.0 |
about.resource.attribute.labels.value |
Mapeado diretamente a partir 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 a partir do campo entity.huddle.participants.1 , com a chave entity.huddle.participants.1 adicionada. |
entity.type |
target.resource.resource_subtype |
Mapeado diretamente a partir do campo entity.type . |
entity.user.email |
target.user.email_addresses |
Mapeado diretamente a partir do campo entity.user.email . |
entity.user.id |
target.user.product_object_id |
Mapeado diretamente a partir do campo entity.user.id . |
entity.user.name |
target.user.user_display_name |
Mapeado diretamente a partir do campo entity.user.name . |
entity.user.team |
target.user.group_identifiers |
Mapeado diretamente a partir do campo entity.user.team . |
entity.workflow.id |
target.resource.id |
Mapeado diretamente a partir do campo entity.workflow.id . |
entity.workflow.name |
target.resource.name |
Mapeado diretamente a partir do campo entity.workflow.name . |
id |
metadata.product_log_id |
Mapeado diretamente a partir do campo id . |
ip |
principal.ip |
Mapeado diretamente a partir do campo ip . Determinado pela lógica com base no campo action . A predefiniçã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 . Codificado de forma rígida para "SLACK_AUDIT". Definido como "Enterprise Grid" se date_create existir. Caso contrário, é definido como "Registos de auditoria" se user_id existir. Codificado de forma rígida para "Slack". Codificado de forma rígida como "REMOTE". Definido como "SSO" se action contiver "user_login" ou "user_logout". Caso contrário, defina como "MACHINE". Não mapeado nos exemplos fornecidos. A predefinição é "ALLOW", mas é definida como "BLOCK" se action for "user_login_failed". Definido como "Slack" se date_create existir. Caso contrário, definido como "SLACK" se user_id existir. |
user_agent |
network.http.user_agent |
Mapeado diretamente a partir do campo user_agent . |
user_id |
principal.user.product_object_id |
Mapeado diretamente a partir do campo user_id . |
username |
principal.user.product_object_id |
Mapeado diretamente a partir do campo username . |
Precisa de mais ajuda? Receba respostas de membros da comunidade e profissionais da Google SecOps.