Coletar registros de autenticação do Duo

Compatível com:

Este documento explica como ingerir registros de autenticação do Duo no Google Security Operations. O analisador extrai os registros de mensagens formatadas em JSON. Ele transforma os dados de registro brutos no modelo de dados unificado (UDM), mapeando campos como usuário, dispositivo, aplicativo, local e detalhes de autenticação, além de processar vários fatores e resultados de autenticação para categorizar eventos de segurança. O analisador também realiza limpeza de dados, conversão de tipos e tratamento de erros para garantir a qualidade e a consistência dos dados.

Escolha entre dois métodos de coleta:

  • Opção 1: ingestão direta usando a API de terceiros
  • Opção 2: coletar registros usando a função do Cloud Run e o Google Cloud Storage

Antes de começar

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

  • Uma instância do Google SecOps
  • Acesso privilegiado ao painel de administração do Duo (a função de proprietário é necessária para criar aplicativos da API Admin)
  • Acesso privilegiado ao GCP se você estiver usando a opção 2

Opção 1: ingerir registros de autenticação do Duo usando a API de terceiros

Coletar os pré-requisitos do Duo (credenciais da API)

  1. Faça login no painel de administração do Duo como administrador com a função de Proprietário, Administrador ou Gerente de aplicativos.
  2. Acesse Aplicativos > Catálogo de aplicativos.
  3. Localize a entrada da API Admin no catálogo.
  4. Clique em + Adicionar para criar o aplicativo.
  5. Copie e salve em um local seguro os seguintes detalhes:
    • Chave de integração
    • Chave secreta
    • Nome do host da API (por exemplo, api-XXXXXXXX.duosecurity.com)
  6. Acesse a seção Permissões.
  7. Desmarque todas as opções de permissão, exceto Conceder leitura de registros.
  8. Clique em Salvar alterações.

Configurar um feed no Google SecOps para ingerir registros de autenticação do Duo

  1. Acesse Configurações do SIEM > Feeds.
  2. Clique em + Adicionar novo feed.
  3. No campo Nome do feed, insira um nome para o feed (por exemplo, Duo Authentication Logs).
  4. Selecione API de terceiros como o Tipo de fonte.
  5. Selecione Autenticação do Duo como o Tipo de registro.
  6. Clique em Próxima.
  7. Especifique valores para os seguintes parâmetros de entrada:
    • Nome de usuário: insira a chave de integração do Duo.
    • Secret: insira a chave secreta do Duo.
    • Nome do host da API: digite o nome do host da API (por exemplo, api-XXXXXXXX.duosecurity.com).
    • Namespace do recurso: opcional. O namespace do recurso.
    • Rótulos de ingestão: opcional. O rótulo a ser aplicado aos eventos deste feed.
  8. Clique em Próxima.
  9. Revise a nova configuração do feed na tela Finalizar e clique em Enviar.

Opção 2: ingerir registros de autenticação do Duo usando o Google Cloud Storage

Coletar credenciais da API Duo Admin

  1. Faça login no painel de administração do Duo.
  2. Acesse Aplicativos > Catálogo de aplicativos.
  3. Localize a API Admin no catálogo de aplicativos.
  4. Clique em + Adicionar para adicionar o aplicativo da API Admin.
  5. Copie e salve os seguintes valores:
    • Chave de integração (ikey)
    • Chave secreta (skey)
    • Nome do host da API (por exemplo, api-XXXXXXXX.duosecurity.com)
  6. Em Permissões, ative Conceder leitura de registros.
  7. Clique em Salvar alterações.

Criar um bucket do Google Cloud Storage

  1. Acesse o Console do Google Cloud.
  2. Selecione seu projeto ou crie um novo.
  3. No menu de navegação, acesse Cloud Storage > Buckets.
  4. Clique em Criar bucket.
  5. Informe os seguintes detalhes de configuração:

    Configuração Valor
    Nomeie seu bucket Insira um nome exclusivo globalmente, por exemplo, duo-auth-logs.
    Tipo de local Escolha com base nas suas necessidades (região, birregional, multirregional)
    Local Selecione o local (por exemplo, us-central1).
    Classe de armazenamento Padrão (recomendado para registros acessados com frequência)
    Controle de acesso Uniforme (recomendado)
    Ferramentas de proteção Opcional: ativar o controle de versões de objetos ou a política de retenção
  6. Clique em Criar.

Criar uma conta de serviço para a função do Cloud Run

A função do Cloud Run precisa de uma conta de serviço com permissões para gravar no bucket do GCS.

Criar conta de serviço

  1. No Console do GCP, acesse IAM e administrador > Contas de serviço.
  2. Clique em Criar conta de serviço.
  3. Informe os seguintes detalhes de configuração:
    • Nome da conta de serviço: insira duo-auth-collector-sa.
    • Descrição da conta de serviço: insira Service account for Cloud Run function to collect Duo authentication logs.
  4. Clique em Criar e continuar.
  5. Na seção Conceder acesso a essa conta de serviço ao projeto, adicione os seguintes papéis:
    1. Clique em Selecionar papel.
    2. Pesquise e selecione Administrador de objetos do Storage.
    3. Clique em + Adicionar outro papel.
    4. Pesquise e selecione Invocador do Cloud Run.
    5. Clique em + Adicionar outro papel.
    6. Pesquise e selecione Invocador do Cloud Functions.
  6. Clique em Continuar.
  7. Clique em Concluído.

Esses papéis são necessários para:

  • Administrador de objetos do Storage: grava registros em um bucket do GCS e gerencia arquivos de estado.
  • Invocador do Cloud Run: permite que o Pub/Sub invoque a função
  • Invocador do Cloud Functions: permite a invocação de funções

Conceder permissões do IAM no bucket do GCS

Conceda permissões de gravação à conta de serviço no bucket do GCS:

  1. Acesse Cloud Storage > Buckets.
  2. Clique no nome do bucket.
  3. Acesse a guia Permissões.
  4. Clique em Conceder acesso.
  5. Informe os seguintes detalhes de configuração:
    • Adicionar principais: insira o e-mail da conta de serviço (por exemplo, duo-auth-collector-sa@PROJECT_ID.iam.gserviceaccount.com).
    • Atribuir papéis: selecione Administrador de objetos do Storage.
  6. Clique em Salvar.

Criar tópico Pub/Sub

Crie um tópico do Pub/Sub em que o Cloud Scheduler vai publicar e a função do Cloud Run vai se inscrever.

  1. No Console do GCP, acesse Pub/Sub > Tópicos.
  2. Selecione Criar tópico.
  3. Informe os seguintes detalhes de configuração:
    • ID do tópico: insira duo-auth-trigger.
    • Não altere as outras configurações.
  4. Clique em Criar.

Criar uma função do Cloud Run para coletar registros

A função do Cloud Run é acionada por mensagens do Pub/Sub do Cloud Scheduler para buscar registros da API Duo Admin e gravá-los no GCS.

  1. No console do GCP, acesse o Cloud Run.
  2. Clique em Criar serviço.
  3. Selecione Função (use um editor in-line para criar uma função).
  4. Na seção Configurar, forneça os seguintes detalhes de configuração:

    Configuração Valor
    Nome do serviço duo-auth-collector
    Região Selecione a região que corresponde ao seu bucket do GCS (por exemplo, us-central1).
    Ambiente de execução Selecione Python 3.12 ou uma versão mais recente.
  5. Na seção Acionador (opcional):

    1. Clique em + Adicionar gatilho.
    2. Selecione Cloud Pub/Sub.
    3. Em Selecionar um tópico do Cloud Pub/Sub, escolha o tópico duo-auth-trigger.
    4. Clique em Salvar.
  6. Na seção Autenticação:

    1. Selecione Exigir autenticação.
    2. Confira o Identity and Access Management (IAM).
  7. Role a tela para baixo e abra Contêineres, rede, segurança.

  8. Acesse a guia Segurança:

    • Conta de serviço: selecione a conta de serviço duo-auth-collector-sa.
  9. Acesse a guia Contêineres:

    1. Clique em Variáveis e secrets.
    2. Clique em + Adicionar variável para cada variável de ambiente:
    Nome da variável Valor de exemplo
    GCS_BUCKET duo-auth-logs
    GCS_PREFIX duo/auth/
    STATE_KEY duo/auth/state.json
    DUO_IKEY DIXYZ...
    DUO_SKEY ****************
    DUO_API_HOSTNAME api-XXXXXXXX.duosecurity.com
    LIMIT 500
  10. Role a tela para baixo na guia Variáveis e secrets até Solicitações:

    • Tempo limite da solicitação: insira 600 segundos (10 minutos).
  11. Acesse a guia Configurações em Contêineres:

    • Na seção Recursos:
      • Memória: selecione 512 MiB ou mais.
      • CPU: selecione 1.
    • Clique em Concluído.
  12. Role até Ambiente de execução:

    • Selecione Padrão (recomendado).
  13. Na seção Escalonamento de revisão:

    • Número mínimo de instâncias: insira 0.
    • Número máximo de instâncias: insira 100 ou ajuste com base na carga esperada.
  14. Clique em Criar.

  15. Aguarde a criação do serviço (1 a 2 minutos).

  16. Depois que o serviço é criado, o editor de código inline é aberto automaticamente.

Adicionar código da função

  1. Insira main em Ponto de entrada da função.
  2. No editor de código em linha, crie dois arquivos:

    • Primeiro arquivo: main.py::
    #!/usr/bin/env python3
    # Cloud Run Function: Pull Duo Admin API v2 Authentication Logs to GCS (raw JSON pages)
    # Notes:
    # - Duo v2 requires mintime/maxtime in *milliseconds* (13-digit epoch).
    # - Pagination via metadata.next_offset ("<millis>,<txid>").
    # - We save state (mintime_ms) in ms to resume next run without gaps.
    
    import functions_framework
    from google.cloud import storage
    import os
    import json
    import time
    import hmac
    import hashlib
    import base64
    import email.utils
    import urllib.parse
    from urllib.request import Request, urlopen
    from urllib.error import HTTPError, URLError
    
    DUO_IKEY = os.environ["DUO_IKEY"]
    DUO_SKEY = os.environ["DUO_SKEY"]
    DUO_API_HOSTNAME = os.environ["DUO_API_HOSTNAME"].strip()
    GCS_BUCKET = os.environ["GCS_BUCKET"]
    GCS_PREFIX = os.environ.get("GCS_PREFIX", "duo/auth/").strip("/")
    STATE_KEY = os.environ.get("STATE_KEY", "duo/auth/state.json")
    LIMIT = min(int(os.environ.get("LIMIT", "500")), 1000)  # default 500, max 1000
    
    storage_client = storage.Client()
    
    def _canon_params(params: dict) -> str:
        parts = []
        for k in sorted(params.keys()):
            v = params[k]
            if v is None:
                continue
            parts.append(f"{urllib.parse.quote(str(k), '~')}={urllib.parse.quote(str(v), '~')}")
        return "&".join(parts)
    
    def _sign(method: str, host: str, path: str, params: dict) -> dict:
        now = email.utils.formatdate()
        canon = "\n".join([
            now,
            method.upper(),
            host.lower(),
            path,
            _canon_params(params)
        ])
        sig = hmac.new(
            DUO_SKEY.encode("utf-8"),
            canon.encode("utf-8"),
            hashlib.sha1
        ).hexdigest()
        auth = base64.b64encode(f"{DUO_IKEY}:{sig}".encode()).decode()
        return {
            "Date": now,
            "Authorization": f"Basic {auth}"
        }
    
    def _http(method: str, path: str, params: dict, timeout: int = 60, max_retries: int = 5) -> dict:
        host = DUO_API_HOSTNAME
        assert host.startswith("api-") and host.endswith(".duosecurity.com"), \
            "DUO_API_HOSTNAME must be like api-XXXXXXXX.duosecurity.com"
    
        qs = _canon_params(params)
        url = f"https://{host}{path}" + (f"?{qs}" if qs else "")
    
        attempt, backoff = 0, 1.0
        while True:
            req = Request(url, method=method.upper())
            req.add_header("Accept", "application/json")
            for k, v in _sign(method, host, path, params).items():
                req.add_header(k, v)
    
            try:
                with urlopen(req, timeout=timeout) as r:
                    return json.loads(r.read().decode("utf-8"))
            except HTTPError as e:
                if (e.code == 429 or 500 <= e.code <= 599) and attempt < max_retries:
                    time.sleep(backoff)
                    attempt += 1
                    backoff *= 2
                    continue
                raise
            except URLError:
                if attempt < max_retries:
                    time.sleep(backoff)
                    attempt += 1
                    backoff *= 2
                    continue
                raise
    
    def _read_state_ms() -> int | None:
        try:
            bucket = storage_client.bucket(GCS_BUCKET)
            blob = bucket.blob(STATE_KEY)
            if blob.exists():
                state_data = blob.download_as_text()
                val = json.loads(state_data).get("mintime")
                if val is None:
                    return None
                # Backward safety: if seconds were stored, convert to ms
                return int(val) * 1000 if len(str(int(val))) <= 10 else int(val)
        except Exception:
            return None
    
    def _write_state_ms(mintime_ms: int):
        bucket = storage_client.bucket(GCS_BUCKET)
        blob = bucket.blob(STATE_KEY)
        body = json.dumps({"mintime": int(mintime_ms)}).encode("utf-8")
        blob.upload_from_string(body, content_type="application/json")
    
    def _write_page(payload: dict, when_epoch_s: int, page: int) -> str:
        bucket = storage_client.bucket(GCS_BUCKET)
        key = f"{GCS_PREFIX}/{time.strftime('%Y/%m/%d', time.gmtime(when_epoch_s))}/duo-auth-{page:05d}.json"
        blob = bucket.blob(key)
        blob.upload_from_string(
            json.dumps(payload, separators=(",", ":")).encode("utf-8"),
            content_type="application/json"
        )
        return key
    
    def fetch_and_store():
        now_s = int(time.time())
        # Duo recommends a ~2-minute delay buffer; use maxtime = now - 120 seconds (in ms)
        maxtime_ms = (now_s - 120) * 1000
        mintime_ms = _read_state_ms() or (maxtime_ms - 3600 * 1000)  # 1 hour on first run
    
        page = 0
        total = 0
        next_offset = None
    
        while True:
            params = {
                "mintime": mintime_ms,
                "maxtime": maxtime_ms,
                "limit": LIMIT
            }
            if next_offset:
                params["next_offset"] = next_offset
    
            data = _http("GET", "/admin/v2/logs/authentication", params)
            _write_page(data, maxtime_ms // 1000, page)
            page += 1
    
            resp = data.get("response")
            items = resp if isinstance(resp, list) else []
            total += len(items)
    
            meta = data.get("metadata") or {}
            next_offset = meta.get("next_offset")
            if not next_offset:
                break
    
        # Advance window to maxtime_ms for next run
        _write_state_ms(maxtime_ms)
    
        return {
            "ok": True,
            "pages": page,
            "events": total,
            "next_mintime_ms": maxtime_ms
        }
    
    @functions_framework.cloud_event
    def main(cloud_event):
        """
        Cloud Run function triggered by Pub/Sub to fetch Duo authentication logs and write to GCS.
    
        Args:
            cloud_event: CloudEvent object containing Pub/Sub message
        """
        try:
            result = fetch_and_store()
            print(f"Successfully processed {result['events']} events in {result['pages']} pages")
            print(f"Next mintime_ms: {result['next_mintime_ms']}")
        except Exception as e:
            print(f"Error processing logs: {str(e)}")
            raise
    
    • Segundo arquivo: requirements.txt:
    functions-framework==3.*
    google-cloud-storage==2.*
    
  3. Clique em Implantar para salvar e implantar a função.

  4. Aguarde a conclusão da implantação (2 a 3 minutos).

Criar o job do Cloud Scheduler

O Cloud Scheduler publica mensagens no tópico do Pub/Sub em intervalos regulares, acionando a função do Cloud Run.

  1. No Console do GCP, acesse o Cloud Scheduler.
  2. Clique em Criar job.
  3. Informe os seguintes detalhes de configuração:

    Configuração Valor
    Nome duo-auth-collector-hourly
    Região Selecione a mesma região da função do Cloud Run
    Frequência 0 * * * * (a cada hora, na hora)
    Fuso horário Selecione o fuso horário (UTC recomendado)
    Tipo de destino Pub/Sub
    Tópico Selecione o tópico duo-auth-trigger.
    Corpo da mensagem {} (objeto JSON vazio)
  4. Clique em Criar.

Opções de frequência de programação

  • Escolha a frequência com base no volume de registros e nos requisitos de latência:

    Frequência Expressão Cron Caso de uso
    A cada 5 minutos */5 * * * * Alto volume e baixa latência
    A cada 15 minutos */15 * * * * Volume médio
    A cada hora 0 * * * * Padrão (recomendado)
    A cada 6 horas 0 */6 * * * Baixo volume, processamento em lote
    Diário 0 0 * * * Coleta de dados históricos

Testar o job do programador

  1. No console do Cloud Scheduler, encontre seu job.
  2. Clique em Forçar execução para acionar manualmente.
  3. Aguarde alguns segundos e acesse Cloud Run > Serviços > duo-auth-collector > Registros.
  4. Verifique se a função foi executada com sucesso.
  5. Verifique o bucket do GCS para confirmar se os registros foram gravados.

Recuperar a conta de serviço do Google SecOps

O Google SecOps usa uma conta de serviço exclusiva para ler dados do seu bucket do GCS. Você precisa conceder a essa conta de serviço acesso ao seu bucket.

Receber o e-mail da conta de serviço

  1. Acesse Configurações do SIEM > Feeds.
  2. Clique em Adicionar novo feed.
  3. Clique em Configurar um único feed.
  4. No campo Nome do feed, insira um nome para o feed (por exemplo, Duo Authentication Logs).
  5. Selecione Google Cloud Storage V2 como o Tipo de origem.
  6. Selecione Autenticação do Duo como o Tipo de registro.
  7. Clique em Receber conta de serviço. Um e-mail exclusivo da conta de serviço é exibido, por exemplo:

    chronicle-12345678@chronicle-gcp-prod.iam.gserviceaccount.com
    
  8. Copie esse endereço de e-mail para usar na próxima etapa.

Conceder permissões do IAM à conta de serviço do Google SecOps

A conta de serviço do Google SecOps precisa do papel de Leitor de objetos do Storage no seu bucket do GCS.

  1. Acesse Cloud Storage > Buckets.
  2. Clique no nome do bucket.
  3. Acesse a guia Permissões.
  4. Clique em Conceder acesso.
  5. Informe os seguintes detalhes de configuração:
    • Adicionar participantes: cole o e-mail da conta de serviço do Google SecOps.
    • Atribuir papéis: selecione Leitor de objetos do Storage.
  6. Clique em Salvar.

Configurar um feed no Google SecOps para ingerir registros de autenticação do Duo

  1. Acesse Configurações do SIEM > Feeds.
  2. Clique em Adicionar novo feed.
  3. Clique em Configurar um único feed.
  4. No campo Nome do feed, insira um nome para o feed (por exemplo, Duo Authentication Logs).
  5. Selecione Google Cloud Storage V2 como o Tipo de origem.
  6. Selecione Autenticação do Duo como o Tipo de registro.
  7. Clique em Próxima.
  8. Especifique valores para os seguintes parâmetros de entrada:

    • URL do bucket de armazenamento: insira o URI do bucket do GCS com o caminho do prefixo:

      gs://duo-auth-logs/duo/auth/
      
      • Substitua:

        • duo-auth-logs: o nome do bucket do GCS.
        • duo/auth/: prefixo/caminho da pasta opcional onde os registros são armazenados (deixe em branco para a raiz).
      • Exemplos:

        • Bucket raiz: gs://company-logs/
        • Com prefixo: gs://company-logs/duo-logs/
        • Com subpasta: gs://company-logs/duo/auth/
    • Opção de exclusão da fonte: selecione a opção de exclusão de acordo com sua preferência:

      • Nunca: nunca exclui arquivos após as transferências (recomendado para testes).
      • Excluir arquivos transferidos: exclui os arquivos após a transferência bem-sucedida.
      • Excluir arquivos transferidos e diretórios vazios: exclui arquivos e diretórios vazios após a transferência bem-sucedida.

    • Idade máxima do arquivo: inclui arquivos modificados no último número de dias. O padrão é de 180 dias.

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

Tabela de mapeamento do UDM

Campo de registro Mapeamento do UDM Lógica
access_device.browser target.resource.attribute.labels.value Se "access_device.browser" estiver presente, o valor será mapeado para a UDM.
access_device.hostname principal.hostname Se access_device.hostname estiver presente e não estiver vazio, o valor será mapeado para a UDM. Se estiver vazio e o event_type for USER_CREATION, o event_type será alterado para USER_UNCATEGORIZED. Se access_device.hostname estiver vazio e o campo hostname existir, o valor de hostname será usado.
access_device.ip principal.ip Se "access_device.ip" existir e for um endereço IPv4 válido, o valor dele será mapeado para a UDM. Se não for um endereço IPv4 válido, ele será adicionado como um valor de string a additional.fields com a chave access_device.ip.
access_device.location.city principal.location.city Se presente, o valor será mapeado para a UDM.
access_device.location.country principal.location.country_or_region Se presente, o valor será mapeado para a UDM.
access_device.location.state principal.location.state Se presente, o valor será mapeado para a UDM.
access_device.os principal.platform Se presente, o valor será traduzido para o valor correspondente do UDM (MAC, WINDOWS, LINUX).
access_device.os_version principal.platform_version Se presente, o valor será mapeado para a UDM.
application.key target.resource.id Se presente, o valor será mapeado para a UDM.
application.name target.application Se presente, o valor será mapeado para a UDM.
auth_device.ip target.ip Se estiver presente e não for "None", o valor será mapeado para a UDM.
auth_device.location.city target.location.city Se presente, o valor será mapeado para a UDM.
auth_device.location.country target.location.country_or_region Se presente, o valor será mapeado para a UDM.
auth_device.location.state target.location.state Se presente, o valor será mapeado para a UDM.
auth_device.name target.hostname OR target.user.phone_numbers Se auth_device.name estiver presente e for um número de telefone (após a normalização), ele será adicionado a target.user.phone_numbers. Caso contrário, ele será mapeado para target.hostname.
client_ip target.ip Se estiver presente e não for "None", o valor será mapeado para a UDM.
client_section target.resource.attribute.labels.value Se client_section estiver presente, o valor dele será mapeado para o UDM com a chave client_section.
dn target.user.userid Se "dn" estiver presente e "user.name" e "username" não estiverem, o userid será extraído do campo "dn" usando grok e mapeado para a UDM. O event_type é definido como USER_LOGIN.
event_type metadata.product_event_type AND metadata.event_type O valor é mapeado para "metadata.product_event_type". Também é usado para determinar que metadata.event_type: "authentication" se torna USER_LOGIN, "enrollment" se torna USER_CREATION e, se estiver vazio ou nenhum dos dois, se torna GENERIC_EVENT.
fator extensions.auth.mechanism AND extensions.auth.auth_details O valor é traduzido para o valor auth.mechanism correspondente da UDM (HARDWARE_KEY, REMOTE_INTERACTIVE, LOCAL, OTP). O valor original também é mapeado para "extensions.auth.auth_details".
nome do host principal.hostname Se estiver presente e access_device.hostname estiver vazio, o valor será mapeado para o UDM.
log_format target.resource.attribute.labels.value Se log_format estiver presente, o valor será mapeado para a UDM com a chave log_format.
loglevel._classuuid_ target.resource.attribute.labels.value Se loglevel._classuuid_ estiver presente, o valor será mapeado para a UDM com a chave class_uuid.
log_level.name target.resource.attribute.labels.value AND security_result.severity Se log_level.name estiver presente, o valor será mapeado para a UDM com o nome da chave. Se o valor for "info", security_result.severity será definido como "INFORMATIONAL".
log_logger.unpersistable target.resource.attribute.labels.value Se log_logger.unpersistable estiver presente, o valor dele será mapeado para a UDM com a chave "unpersistable".
log_namespace target.resource.attribute.labels.value Se log_namespace estiver presente, o valor dele será mapeado para a UDM com a chave log_namespace.
log_source target.resource.attribute.labels.value Se log_source estiver presente, o valor dele será mapeado para a UDM com a chave log_source.
msg security_result.summary Se estiver presente e o motivo estiver vazio, o valor será mapeado para a UDM.
reason security_result.summary Se presente, o valor será mapeado para a UDM.
resultado security_result.action_details AND security_result.action Se presente, o valor será mapeado para security_result.action_details. "success" ou "SUCCESS" se traduz em security_result.action ALLOW. Caso contrário, BLOCK.
server_section target.resource.attribute.labels.value Se server_section estiver presente, o valor será mapeado para a UDM com a chave server_section.
server_section_ikey target.resource.attribute.labels.value Se server_section_ikey estiver presente, o valor dele será mapeado para a UDM com a chave server_section_ikey.
status security_result.action_details AND security_result.action Se presente, o valor será mapeado para security_result.action_details. "Permitir" é traduzido como security_result.action ALLOW, e "Rejeitar" é traduzido como BLOCK.
timestamp metadata.event_timestamp AND event.timestamp O valor é convertido em um carimbo de data/hora e mapeado para metadata.event_timestamp e event.timestamp.
txid metadata.product_log_id AND network.session_id O valor é mapeado para metadata.product_log_id e network.session_id.
user.groups target.user.group_identifiers Todos os valores na matriz são adicionados a "target.user.group_identifiers".
user.key target.user.product_object_id Se presente, o valor será mapeado para a UDM.
user.name target.user.userid Se presente, o valor será mapeado para a UDM.
nome de usuário target.user.userid Se estiver presente e user.name não estiver, o valor será mapeado para a UDM. O event_type é definido como USER_LOGIN.
(Lógica do analisador) metadata.vendor_name Sempre definido como "DUO_SECURITY".
(Lógica do analisador) metadata.product_name Sempre definido como "MULTI-FACTOR_AUTHENTICATION".
(Lógica do analisador) metadata.log_type Extraído do campo "log_type" de nível superior do registro bruto.
(Lógica do analisador) extensions.auth.type Sempre definido como "SSO".

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