Recolha registos de auditoria do Slack

Compatível com:

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)

  1. Inicie sessão na consola de administração do Slack para a sua organização do Enterprise Grid.
  2. Aceda a https://api.slack.com/apps e clique em Create New App > From scratch.
  3. Introduza o Nome da app e selecione o seu espaço de trabalho do Slack de desenvolvimento.
  4. Clique em Criar app.
  5. Navegue para OAuth e autorizações na barra lateral esquerda.
  6. Aceda à secção Âmbitos e adicione o seguinte âmbito do token de utilizador:
    • auditlogs:read
  7. Clique em Instalar no Workspace > Permitir.
  8. Depois de instalada, navegue para Apps ao nível da organização > Instalar na organização.
  9. Autorize a app com uma conta de proprietário/administrador da organização.
  10. Copie e guarde em segurança a chave OAuth do utilizador que começa com xoxp- (esta é a sua SLACK_ADMIN_TOKEN).
  11. 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

  1. Crie um novo diretório na sua máquina local para a implementação da função do Cloud Run.
  2. 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
  3. 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

  1. Na Google Cloud consola, aceda a Segurança > Secret Manager.
  2. Clique em Criar segredo.
  3. 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.
  4. Clique em Criar segredo.
  5. Copie o nome do recurso secreto no seguinte formato:

    projects/<PROJECT_ID>/secrets/chronicle-service-account/versions/latest
    
  6. Clique novamente em Criar segredo para criar um segundo segredo.

  7. 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-).
  8. Clique em Criar segredo.

  9. 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

  1. Abra o ficheiro .env.yml no diretório de implementação.
  2. 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 e southamerica-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.
  3. Guarde o ficheiro .env.yml.

Implementar a função do Cloud Run

  1. Abra um terminal ou o Cloud Shell na Google Cloud consola.
  2. Navegue para o diretório de implementação:

    cd /path/to/deployment_directory
    
  3. 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.
  4. Aguarde a conclusão da implementação.

  5. Após a implementação, tome nota do URL da função a partir da saída.

Configure o Cloud Scheduler

  1. Na Google Cloud consola, aceda a Cloud Scheduler > Criar tarefa.
  2. 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 valor POLL_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.
  3. 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.