Coletar registros do Keycloak

Compatível com:

Este documento explica como configurar o Keycloak para enviar registros ao Google Security Operations usando webhooks.

O Keycloak é uma solução de gerenciamento de identidade e acesso (IAM) de código aberto que oferece recursos de logon único (SSO), federação de usuários, corretagem de identidade e login social. Ele oferece suporte aos protocolos OpenID Connect, OAuth 2.0 e SAML 2.0 e rastreia eventos de usuários (login, logout, registro, mudanças de senha) e de administradores (operações de gerenciamento de usuários, clientes, domínios e funções) para auditoria de segurança.

Antes de começar

Verifique se você atende aos seguintes pré-requisitos:

  • Uma instância do Google SecOps
  • Uma instância do Keycloak em execução (recomendamos a versão 20 ou mais recente)
  • Acesso de administrador ao Admin Console do Keycloak
  • Acesso ao sistema de arquivos ou contêiner do servidor Keycloak para implantar extensões
  • Acesso ao console do Google Cloud (para criação de chaves de API)

Criar um feed de webhook no Google SecOps

Criar o feed

  1. Acesse Configurações do SIEM > Feeds.
  2. Clique em Adicionar novo feed.
  3. Na próxima página, clique em Configurar um único feed.
  4. No campo Nome do feed, insira um nome para o feed (por exemplo, Keycloak Events).
  5. Selecione Webhook como o Tipo de origem.
  6. Selecione Keycloak como o Tipo de registro.
  7. Clique em Próxima.
  8. Especifique valores para os seguintes parâmetros de entrada:
    • Delimitador de divisão (opcional): insira \n para dividir eventos de várias linhas. Cada POST de webhook contém um único evento, então esse campo pode ficar vazio.
    • Namespace do recurso: o namespace do recurso
    • Rótulos de ingestão: o rótulo a ser aplicado aos eventos deste feed
  9. Clique em Próxima.
  10. Revise a nova configuração do feed na tela Finalizar e clique em Enviar.

Gerar e salvar a chave secreta

Depois de criar o feed, gere uma chave secreta para autenticação:

  1. Na página de detalhes do feed, clique em Gerar chave secreta.
  2. Uma caixa de diálogo mostra a chave secreta.
  3. Copie e salve a chave secreta com segurança.

Importante: a chave secreta é exibida apenas uma vez e não pode ser recuperada depois. Se você perder a chave, será necessário gerar outra.

Receber o URL do endpoint do feed

  1. Acesse a guia Detalhes do feed.
  2. Na seção Informações do endpoint, copie o URL do endpoint do feed.
  3. O formato do URL é:

    https://malachiteingestion-pa.googleapis.com/v2/unstructuredlogentries:batchCreate
    

    ou

    https://<REGION>-malachiteingestion-pa.googleapis.com/v2/unstructuredlogentries:batchCreate
    
  4. Salve esse URL para as próximas etapas.

  5. Clique em Concluído.

Criar chave de API do Google Cloud

O Chronicle exige uma chave de API para autenticação. Crie uma chave de API restrita no console do Google Cloud.

Criar a chave de API

  1. Acesse a página "Credenciais" do console do Google Cloud.
  2. Selecione seu projeto (o projeto associado à sua instância do Chronicle).
  3. Clique em Criar credenciais > Chave de API.
  4. Uma chave de API é criada e mostrada em uma caixa de diálogo.
  5. Clique em Editar chave de API para restringir a chave.

Restringir a chave de API

  1. Na página de configurações da chave de API:
    • Nome: insira um nome descritivo, por exemplo, Chronicle Webhook API Key.
  2. Em Restrições de API:
    1. Selecione Restringir chave.
    2. No menu suspenso Selecionar APIs, pesquise e selecione API Google SecOps (ou API Chronicle).
  3. Clique em Salvar.
  4. Copie o valor da chave de API do campo Chave de API na parte de cima da página.
  5. Salve a chave de API com segurança.

Ativar o armazenamento de eventos no Keycloak

Antes de configurar a extensão de webhook, ative o armazenamento de eventos no Keycloak para que eles sejam gerados e estejam disponíveis para encaminhamento.

Ativar eventos do usuário

  1. Faça login no Admin Console do Keycloak.
  2. Selecione o realm que você quer monitorar no menu suspenso no canto superior esquerdo.
  3. Acesse Configurações do realm > Eventos.
  4. Selecione a subguia Configurações de eventos do usuário.
  5. Ative a opção Salvar eventos.
  6. Defina o período de Validade (mínimo recomendado: 7 dias).
  7. Clique em Salvar.

Ativar eventos de administrador

  1. Na mesma guia Eventos, selecione a subguia Configurações de eventos de administrador.
  2. Ative a opção Salvar eventos.
  3. Ative a opção Incluir representação para capturar todos os detalhes dos objetos alterados.
  4. Defina o período de Validade (mínimo recomendado: 7 dias).
  5. Clique em Salvar.

Instalar a extensão do listener de eventos de webhook

O Keycloak não inclui um listener de eventos de webhook nativo. Instale a extensão keycloak-events da Fase 2 (p2-inc) para ativar a entrega de webhook.

Baixar e implantar a extensão

  1. Faça o download do JAR da versão mais recente na página de versões do keycloak-events no Maven Central ou crie a partir da fonte:

    git clone https://github.com/p2-inc/keycloak-events.git
    cd keycloak-events
    mvn clean install
    
  2. Copie o arquivo JAR resultante para o diretório providers do Keycloak:

    cp target/keycloak-events-*.jar /opt/keycloak/providers/
    
  3. Recrie e reinicie o Keycloak:

    /opt/keycloak/bin/kc.sh build
    /opt/keycloak/bin/kc.sh start
    

Ativar o listener de eventos do webhook

  1. Faça login no Admin Console do Keycloak.
  2. Selecione o reino de destino no menu suspenso.
  3. Acesse Configurações do realm > Eventos.
  4. No menu suspenso Listeners de eventos, selecione ext-event-webhook.
  5. Clique em Salvar.

Configurar o webhook do Keycloak

Criar o URL do webhook

  • Combine o URL do endpoint do Chronicle e a chave de API:

    <ENDPOINT_URL>?key=<API_KEY>
    
  • Exemplo:

    https://malachiteingestion-pa.googleapis.com/v2/unstructuredlogentries:batchCreate?key=AIzaSyD...
    

Criar uma assinatura de webhook usando a API REST do Keycloak

A extensão keycloak-events fornece endpoints REST para gerenciar assinaturas de webhook. Use a API REST de administração do Keycloak para criar um webhook.

Etapa 1: receber um token de acesso

  • Solicite um token de acesso do Keycloak usando uma conta de administrador:

    TOKEN=$(curl -sS -X POST "https://<KEYCLOAK_HOST>/realms/master/protocol/openid-connect/token" \
      -H "Content-Type: application/x-www-form-urlencoded" \
      --data-urlencode "grant_type=password" \
      --data-urlencode "client_id=admin-cli" \
      --data-urlencode "username=<ADMIN_USERNAME>" \
      --data-urlencode "password=<ADMIN_PASSWORD>" \
      | sed -n 's/.*"access_token":"\([^"]*\)".*/\1/p')
    

Substitua:

  • <KEYCLOAK_HOST>: o nome do host e a porta do servidor Keycloak (por exemplo, keycloak.example.com:8443)
  • <ADMIN_USERNAME>: seu nome de usuário de administrador do Keycloak
  • <ADMIN_PASSWORD>: sua senha de administrador do Keycloak

Etapa 2: criar o webhook

  • Envie uma solicitação POST para criar a assinatura do webhook para o domínio de destino:

    curl -sS -X POST "https://<KEYCLOAK_HOST>/realms/<REALM_NAME>/webhooks" \
      -H "Authorization: Bearer ${TOKEN}" \
      -H "Content-Type: application/json" \
      -d '{
        "enabled": "true",
        "url": "<ENDPOINT_URL>?key=<API_KEY>&secret=<SECRET_KEY>",
        "secret": "<WEBHOOK_HMAC_SECRET>",
        "eventTypes": ["*"]
      }'
    

Substitua:

  • <KEYCLOAK_HOST>: o nome do host do servidor Keycloak
  • <REALM_NAME>: o nome do realm a ser monitorado (por exemplo, master ou my-realm)
  • <ENDPOINT_URL>: o URL do endpoint do feed do Chronicle copiado anteriormente
  • <API_KEY>: a chave de API do Google Cloud criada anteriormente
  • <SECRET_KEY>: a chave secreta do webhook do Chronicle gerada anteriormente
  • <WEBHOOK_HMAC_SECRET>: uma string secreta arbitrária para assinatura HMAC de payloads de webhook (por exemplo, mySecretKey123)

Etapa 3: verificar o webhook

  • Confirme se o webhook foi criado listando todos os webhooks do domínio:

    curl -sS -X GET "https://<KEYCLOAK_HOST>/realms/<REALM_NAME>/webhooks" \
      -H "Authorization: Bearer ${TOKEN}" \
      -H "Accept: application/json"
    

A resposta retorna uma lista de objetos de webhook. Verifique se o webhook aparece com "enabled": "true" e o URL correto.

Tipos de eventos de webhook

O campo eventTypes aceita uma matriz de expressões para filtrar quais eventos são enviados:

  • *: envia todos os eventos (recomendado para integração com SIEM).
  • access.*: envia todos os eventos de acesso
  • admin.*: envia todos os eventos de administrador.
  • admin.USER-*: envia todos os eventos de administrador relacionados aos usuários.
  • admin-USER-CREATE — Enviar apenas eventos de administrador de criação de usuário

Formato do payload do webhook

  • O webhook envia eventos como solicitações HTTP POST com payloads JSON. Exemplo de payload de evento do usuário:

    {
      "id": "987865-1a2b-3c4d-9876-654321abc",
      "time": 1767799710612,
      "type": "LOGIN",
      "realmId": "12345abcde-1a2b-4d3c-9876-abcd456",
      "clientId": "account-console",
      "userId": "abcd456-1234-5678-abc9-987gfed654",
      "sessionId": "efghij-9876-abcd-456-11223344",
      "ipAddress": "203.0.113.45",
      "details": {
        "auth_method": "openid-connect",
        "auth_type": "code",
        "redirect_uri": "https://app.example.com/callback",
        "consent": "no_consent_required",
        "username": "jdoe"
      }
    }
    

Comportamento de repetição do webhook

A extensão usa espera exponencial automática para novas tentativas quando uma resposta diferente de 2xx é recebida:

Parâmetro Valor padrão Descrição
backoffInitialInterval 500 ms Intervalo inicial de novas tentativas
backoffMaxElapsedTime 900.000 ms (15 min) Tempo total máximo de novas tentativas
backoffMaxInterval 180.000 ms (3 min) Intervalo máximo entre novas tentativas
backoffMultiplier 5 Multiplicador para cada intervalo de nova tentativa
backoffRandomizationFactor 0,5 Fator de randomização para jitter

Referência de métodos de autenticação

Os feeds de webhook do Chronicle são compatíveis com vários métodos de autenticação. Escolha o método compatível com seu fornecedor.

Se o fornecedor aceitar cabeçalhos HTTP personalizados, use esse método para aumentar a segurança.

  • Formato da solicitação:

    POST <ENDPOINT_URL> HTTP/1.1
    Content-Type: application/json
    x-goog-chronicle-auth: <API_KEY>
    x-chronicle-auth: <SECRET_KEY>
    
    {
            "event": "data",
            "timestamp": "2025-01-15T10:30:00Z"
    }
    

Vantagens:

  • A chave de API e o secret não estão visíveis no URL
  • Mais seguro (cabeçalhos não registrados em registros de acesso ao servidor da Web)
  • Método preferido quando o fornecedor oferece suporte

Método 2: parâmetros de consulta

Se o fornecedor não aceitar cabeçalhos personalizados, adicione as credenciais ao URL.

  • Formato do URL:

    <ENDPOINT_URL>?key=<API_KEY>&secret=<SECRET_KEY>
    
  • Exemplo:

    https://malachiteingestion-pa.googleapis.com/v2/unstructuredlogentries:batchCreate?key=AIzaSyD...&secret=abcd1234...
    
  • Formato da solicitação:

    POST <ENDPOINT_URL>?key=<API_KEY>&secret=<SECRET_KEY> HTTP/1.1
    Content-Type: application/json
    
    {
            "event": "data",
            "timestamp": "2025-01-15T10:30:00Z"
    }
    

Desvantagens:

  • Credenciais visíveis no URL
  • Podem ser registrados em registros de acesso ao servidor da Web.
  • Menos seguro que cabeçalhos

Método 3: híbrido (URL + cabeçalho)

Algumas configurações usam a chave de API no URL e a chave secreta no cabeçalho.

  • Formato da solicitação:

    POST <ENDPOINT_URL>?key=<API_KEY> HTTP/1.1
    Content-Type: application/json
    x-chronicle-auth: <SECRET_KEY>
    
    {
            "event": "data",
            "timestamp": "2025-01-15T10:30:00Z"
    }
    

Nomes dos cabeçalhos de autenticação

O Chronicle aceita os seguintes nomes de cabeçalho para autenticação:

Para chave de API:

  • x-goog-chronicle-auth (recomendado)
  • X-Goog-Chronicle-Auth (sem diferenciação de maiúsculas e minúsculas)

Para chave secreta:

  • x-chronicle-auth (recomendado)
  • X-Chronicle-Auth (sem diferenciação de maiúsculas e minúsculas)

Limites e práticas recomendadas de webhook

Limites de solicitações

Limite Valor
Tamanho máximo da solicitação 4 MB
QPS máximo (consultas por segundo) 15.000
Tempo limite da solicitação 30 segundos
Comportamento de repetição Automático com espera exponencial

Tabela de mapeamento do UDM

Campo de registro Mapeamento do UDM Lógica
payload.client_id additional.fields Mesclado com campos criados de payload.client_id, payload.realm_id
payload.realm_id additional.fields
source_timestamp metadata.event_timestamp Analisado usando o filtro de data com padrões ISO8601 e yyyy-MM-dd'T'HH:mm:ss.SSSZ
payload.ip_address metadata.event_type Definido como "STATUS_UPDATE" se payload.ip_address não estiver vazio. Caso contrário, "USER_UNCATEGORIZED" se uuid não estiver vazio. Caso contrário, "GENERIC_EVENT".
uuid metadata.event_type
payload.type metadata.product_event_type Valor copiado diretamente
payload.session_id network.session_id Valor copiado diretamente
payload.ip_address principal.ip Valor copiado diretamente
source_metadata.schema principal.resource.attribute.labels Mesclado com rótulos criados com base em source_metadata.schema, source_metadata.table, source_metadata.is_deleted (convertido em string), source_metadata.change_type, source_metadata.tx_id, source_metadata.lsn
source_metadata.table principal.resource.attribute.labels
source_metadata.is_deleted principal.resource.attribute.labels
source_metadata.change_type principal.resource.attribute.labels
source_metadata.tx_id principal.resource.attribute.labels
source_metadata.lsn principal.resource.attribute.labels
uuid principal.user.userid Valor copiado diretamente
objeto security_result.detection_fields Mesclado com rótulos criados com base em objeto, read_method, payload.id
read_method security_result.detection_fields
payload.id security_result.detection_fields
redirect_uri target.url Valor copiado diretamente
nome de usuário target.user.userid Valor copiado diretamente
metadata.product_name metadata.product_name Defina como "KEYCLOAK".
metadata.vendor_name metadata.vendor_name Defina como "KEYCLOAK".
username" from "details_json target.user.userid Mapeado do registro de mudanças
redirect_uri" from "details_json target.url Mapeado do registro de mudanças
realm_id" and "client_id additional.fields Mapeado do registro de mudanças

Registro de alterações

Ver o registro de alterações deste analisador

Precisa de mais ajuda? Receba respostas de membros da comunidade e profissionais do Google SecOps.