Coletar registros de alertas do Dataminr

Compatível com:

Este documento explica como ingerir registros de alertas do Dataminr no Google Security Operations usando o Google Cloud Storage V2, uma função do Cloud Run e o Cloud Scheduler.

O Dataminr Pulse oferece inteligência em tempo real com tecnologia de IA de mais de 500.000 fontes de dados públicos globais, incluindo a deep e a dark web. A plataforma envia alertas antecipados sobre ameaças cibernéticas, vulnerabilidades, ataques de ransomware, violações de dados e riscos digitais emergentes que afetam sua organização e terceiros. A API Dataminr Pulse usa autenticação de credenciais de cliente do OAuth 2.0 e paginação baseada em cursor para recuperar alertas.

Antes de começar

Verifique se você tem os pré-requisitos a seguir:

  • Uma instância do Google SecOps
  • Um projeto do Google Cloud com as seguintes APIs ativadas:
    • API Cloud Storage
    • API Funções do Cloud Run
    • API Cloud Scheduler
    • API Cloud Pub/Sub
  • Permissões para criar e gerenciar buckets do GCS, funções do Cloud Run, tópicos do Pub/Sub e jobs do Cloud Scheduler
  • Permissões para gerenciar políticas do IAM em buckets do GCS
  • Uma conta ativa do Dataminr Pulse com acesso à API ativado
  • Credenciais da API Dataminr Pulse (ID e chave secreta do cliente)
  • Pelo menos uma lista de alertas do Dataminr Pulse configurada na sua conta do Dataminr

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, dataminr-alert-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.

Coletar credenciais do Dataminr

Para permitir que a função do Cloud Run recupere dados de alertas, você precisa de credenciais de API com autenticação de credenciais de cliente OAuth 2.0 do representante da sua conta do Dataminr.

Receber credenciais de API

  1. Entre em contato com o representante da sua conta do Dataminr ou com a equipe de suporte para solicitar acesso à API.
  2. Informe o seguinte:
    • Nome da sua organização
    • Caso de uso: integração com o SIEM do Google Chronicle
    • Acesso necessário: API Dataminr Pulse para risco cibernético
  3. A Dataminr provisiona credenciais de API e oferece:

    • ID do cliente: seu identificador exclusivo do cliente OAuth 2.0.
    • Chave secreta do cliente: sua chave secreta do cliente OAuth 2.0

Verificar credenciais da API

  • Para verificar se as suas credenciais estão funcionando, execute o seguinte comando:

    curl -X POST https://gateway.dataminr.com/auth/2/token \
      -H "Content-Type: application/x-www-form-urlencoded" \
      -d "client_id=YOUR_CLIENT_ID&client_secret=YOUR_CLIENT_SECRET&grant_type=api_key"
    

    Uma resposta bem-sucedida retorna um objeto JSON que contém um campo access_token:

    {
      "access_token": "eyJhbGciOiJSUzI1NiIsInR5cCI...",
      "token_type": "Bearer",
      "expire": 3600
    }
    

Coletar IDs de lista de alertas

  1. Faça login no aplicativo da Web Dataminr Pulse em https://app.dataminr.com.
  2. Acesse as listas de alertas (listas de observação) configuradas.
  3. Anote os IDs das listas de alertas que você quer ingerir no Google SecOps.

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

  1. No console do Google Cloud, 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 dataminr-alert-collector
    • Descrição da conta de serviço: insira Service account for Dataminr Alerts Cloud Run function to write alert data to GCS
  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 um papel, pesquise e selecione Administrador de objetos do Storage.
    2. Clique em Adicionar outro papel, pesquise e selecione Invocador do Cloud Run.
  6. Clique em Continuar.
  7. Clique em Concluído.

Conceder permissões do IAM no bucket do GCS

  1. Acesse Cloud Storage > Buckets.
  2. Clique no nome do bucket (por exemplo, dataminr-alert-logs).
  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, dataminr-alert-collector@PROJECT_ID.iam.gserviceaccount.com).
    • Atribuir papéis: selecione Administrador de objetos do Storage.
  6. Clique em Salvar.

Criar um tópico do Pub/Sub

O tópico do Pub/Sub aciona a função do Cloud Run quando uma mensagem é publicada pelo Cloud Scheduler.

  1. No console do Google Cloud, acesse Pub/Sub > Tópicos.
  2. Clique em Criar tópico.
  3. Informe os seguintes detalhes de configuração:
    • ID do tópico: insira dataminr-alert-trigger
    • Adicionar uma assinatura padrão: deixe marcada
  4. Clique em Criar.

Criar a função do Cloud Run

  1. No console do Google Cloud, acesse Funções do Cloud Run.
  2. Clique em Criar função.
  3. Informe os seguintes detalhes de configuração:

    Configuração Valor
    Ambiente 2ª geração
    Nome da função dataminr-alert-collector
    Região Selecione a mesma região do seu bucket do GCS.
    Tipo de gatilho Cloud Pub/Sub
    Tópico do Pub/Sub dataminr-alert-trigger
    Memória alocada 512 MiB
    Tempo limite 540 segundos
    Conta de serviço do ambiente de execução dataminr-alert-collector
  4. Clique em Próxima.

  5. Defina Ambiente de execução como Python 3.12.

  6. Defina o Ponto de entrada como main.

  7. No arquivo requirements.txt, adicione as seguintes dependências:

    functions-framework==3.*
    google-cloud-storage==2.*
    requests==2.*
    
  8. No arquivo main.py, cole o seguinte código:

    import functions_framework
    import json
    import os
    import logging
    import time
    from datetime import datetime, timedelta, timezone
    from google.cloud import storage
    import requests
    
    logger = logging.getLogger(__name__)
    logger.setLevel(logging.INFO)
    
    storage_client = storage.Client()
    
    TOKEN_URL = "https://gateway.dataminr.com/auth/2/token"
    ALERTS_URL = "https://gateway.dataminr.com/api/3/alerts"
    
    def _get_access_token(client_id: str, client_secret: str) -> str:
        """Obtain an OAuth 2.0 access token from Dataminr."""
        payload = {
            "client_id": client_id,
            "client_secret": client_secret,
            "grant_type": "api_key",
        }
        headers = {"Content-Type": "application/x-www-form-urlencoded"}
        resp = requests.post(TOKEN_URL, data=payload, headers=headers, timeout=30)
        resp.raise_for_status()
        token_data = resp.json()
        access_token = token_data.get("access_token")
        if not access_token:
            raise ValueError("No access_token in token response")
        logger.info("Successfully obtained Dataminr access token.")
        return access_token
    
    def _load_state(bucket_name: str, state_key: str) -> dict:
        """Load the last cursor (alertId) from GCS."""
        try:
            bucket = storage_client.bucket(bucket_name)
            blob = bucket.blob(state_key)
            if blob.exists():
                data = json.loads(blob.download_as_text())
                logger.info(f"Loaded state: {data}")
                return data
        except Exception as e:
            logger.warning(f"State read error: {e}")
        logger.info("No previous state found.")
        return {}
    
    def _save_state(bucket_name: str, state_key: str, state: dict) -> None:
        """Save the cursor state to GCS."""
        bucket = storage_client.bucket(bucket_name)
        blob = bucket.blob(state_key)
        blob.upload_from_string(
            json.dumps(state), content_type="application/json"
        )
        logger.info(f"Saved state: {state}")
    
    def _fetch_alerts(
        access_token: str,
        alert_lists: str,
        page_size: int,
        cursor: str = None,
    ) -> tuple:
        """Fetch a page of alerts from the Dataminr Pulse API."""
        headers = {
            "Authorization": f"Bearer {access_token}",
            "Accept": "application/json",
        }
        params = {
            "lists": alert_lists,
            "num": page_size,
        }
        if cursor:
            params["from"] = cursor
    
        resp = requests.get(
            ALERTS_URL, headers=headers, params=params, timeout=60
        )
    
        # Handle rate limiting via response headers
        rate_remaining = resp.headers.get("x-ratelimit-remaining")
        rate_reset = resp.headers.get("x-ratelimit-reset")
    
        if resp.status_code == 429:
            reset_time = int(rate_reset) if rate_reset else 60
            wait_seconds = max(reset_time - int(time.time()), 1)
            logger.warning(
                f"Rate limited. Waiting {wait_seconds}s before retry."
            )
            time.sleep(wait_seconds)
            resp = requests.get(
                ALERTS_URL, headers=headers, params=params, timeout=60
            )
    
        resp.raise_for_status()
    
        if rate_remaining is not None:
            logger.info(
                f"Rate limit remaining: {rate_remaining}, reset: {rate_reset}"
            )
    
        data = resp.json()
        alerts = data if isinstance(data, list) else data.get("data", [])
        return alerts
    
    @functions_framework.cloud_event
    def main(cloud_event):
        """Cloud Run function entry point triggered by Pub/Sub."""
        bucket_name = os.environ["GCS_BUCKET"]
        prefix = os.environ.get("GCS_PREFIX", "dataminr_alerts")
        state_key = os.environ.get("STATE_KEY", "dataminr_state/cursor.json")
        client_id = os.environ["CLIENT_ID"]
        client_secret = os.environ["CLIENT_SECRET"]
        alert_lists = os.environ["ALERT_LISTS"]
        max_records = int(os.environ.get("MAX_RECORDS", "1000"))
        page_size = min(int(os.environ.get("PAGE_SIZE", "40")), 40)
        lookback_hours = int(os.environ.get("LOOKBACK_HOURS", "24"))
    
        try:
            access_token = _get_access_token(client_id, client_secret)
            state = _load_state(bucket_name, state_key)
            cursor = state.get("last_cursor")
            is_first_run = cursor is None
    
            all_alerts = []
            total_fetched = 0
            pages_fetched = 0
    
            while total_fetched < max_records:
                logger.info(
                    f"Fetching page {pages_fetched + 1} (cursor: {cursor})..."
                )
                alerts = _fetch_alerts(
                    access_token, alert_lists, page_size, cursor=cursor
                )
    
                if not alerts:
                    logger.info("No more alerts returned. Stopping pagination.")
                    break
    
                # Filter by lookback window on first run (no prior cursor)
                if is_first_run:
                    cutoff_ms = int(
                        (
                            datetime.now(timezone.utc)
                            - timedelta(hours=lookback_hours)
                        ).timestamp()
                        * 1000
                    )
                    alerts = [
                        a for a in alerts if a.get("eventTime", 0) >= cutoff_ms
                    ]
    
                all_alerts.extend(alerts)
                total_fetched += len(alerts)
                pages_fetched += 1
    
                # Update cursor to the last alertId in this page
                last_alert = alerts[-1] if alerts else None
                if last_alert and "alertId" in last_alert:
                    cursor = last_alert["alertId"]
                else:
                    break
    
                # Stop if we received fewer alerts than requested
                if len(alerts) < page_size:
                    logger.info("Received partial page. Stopping pagination.")
                    break
    
            logger.info(
                f"Collected {len(all_alerts)} alerts across {pages_fetched} pages."
            )
    
            if not all_alerts:
                logger.info("No new alerts to write.")
                return "No new alerts", 200
    
            # Write alerts as NDJSON to GCS
            now_str = datetime.now(timezone.utc).strftime("%Y%m%dT%H%M%SZ")
            blob_path = f"{prefix}/{now_str}.ndjson"
            ndjson_body = "\n".join(
                json.dumps(alert, separators=(",", ":")) for alert in all_alerts
            )
    
            bucket = storage_client.bucket(bucket_name)
            blob = bucket.blob(blob_path)
            blob.upload_from_string(
                ndjson_body, content_type="application/x-ndjson"
            )
    
            _save_state(
                bucket_name,
                state_key,
                {
                    "last_cursor": cursor,
                    "last_run": datetime.now(timezone.utc).isoformat(),
                },
            )
    
            msg = (
                f"Wrote {len(all_alerts)} alerts to "
                f"gs://{bucket_name}/{blob_path}"
            )
            logger.info(msg)
            return msg, 200
    
        except Exception as e:
            logger.error(f"Error collecting Dataminr alerts: {e}")
            raise
    
  9. Clique em Implantar.

  10. Aguarde a implantação da função. O status muda para uma marca de seleção verde quando a implantação é concluída.

Configure as variáveis de ambiente

  1. Depois que a função for implantada, acesse Cloud Run Functions > dataminr-alert-collector.
  2. Clique em Editar e implantar nova revisão.
  3. Clique na guia Variáveis e secrets ou expanda Ambiente de execução, build, conexões e configurações de segurança para a 1ª geração.
  4. Adicione as seguintes variáveis de ambiente:

    Chave Valor de exemplo
    GCS_BUCKET dataminr-alert-logs
    GCS_PREFIX dataminr_alerts
    STATE_KEY dataminr_state/cursor.json
    CLIENT_ID Seu ID do cliente OAuth 2.0 do Dataminr
    CLIENT_SECRET Sua chave secreta do cliente OAuth 2.0 do Dataminr
    ALERT_LISTS IDs de lista de alertas do Dataminr separados por vírgulas
    MAX_RECORDS 1000
    PAGE_SIZE 40
    LOOKBACK_HOURS 24
  5. Clique em Implantar.

Criar um job do Cloud Scheduler

O Cloud Scheduler publica uma mensagem no tópico do Pub/Sub em uma programação, acionando a função do Cloud Run para pesquisar novos alertas no Dataminr Pulse.

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

    Configuração Valor
    Nome dataminr-alert-poll
    Região Selecione a mesma região da função.
    Frequência */5 * * * * (a cada 5 minutos)
    Fuso horário Selecione seu fuso horário (por exemplo, UTC).
  4. Clique em Continuar.

  5. Na seção Configurar a execução:

    • Tipo de destino: selecione Pub/Sub.
    • Tema: selecione dataminr-alert-trigger
    • Corpo da mensagem: insira {"poll": true}.
  6. Clique em Criar.

Verificar a função do Cloud Run

  1. No Cloud Scheduler, localize o job dataminr-alert-poll.
  2. Clique em Forçar execução para acionar uma execução imediata.
  3. Acesse Cloud Run Functions > dataminr-alert-collector > Registros.
  4. Verifique se a função foi executada com sucesso conferindo entradas de registro como:

    Successfully obtained Dataminr access token.
    Fetching page 1 (cursor: None)...
    Collected 35 alerts across 1 pages.
    Wrote 35 alerts to gs://dataminr-alert-logs/dataminr_alerts/20250115T103000Z.ndjson
    
  5. Acesse Cloud Storage > Buckets > dataminr-alert-logs.

  6. Navegue até o prefixo dataminr_alerts/.

  7. Verifique se os arquivos NDJSON estão sendo criados com dados de alerta do Dataminr.

Recuperar a conta de serviço do Google SecOps e configurar o feed

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, Dataminr Alerts).
  5. Selecione Google Cloud Storage V2 como o Tipo de origem.
  6. Selecione Alertas do Dataminr como o Tipo de registro.
  7. Clique em Receber conta de serviço.
  8. Um e-mail exclusivo da conta de serviço será exibido, por exemplo:

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

  10. Clique em Próxima.

  11. 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://dataminr-alert-logs/dataminr_alerts/
      
    • 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 ser concluída.
      • 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 nos últimos dias (o padrão é 180 dias).

    • Namespace do recurso: namespace do recurso.

    • Rótulos de ingestão: o rótulo a ser aplicado aos eventos deste feed (por exemplo, DATAMINR_ALERT).

  12. Clique em Próxima.

  13. Revise a nova configuração do feed na tela Finalizar e clique em Enviar.

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

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

  1. Acesse Cloud Storage > Buckets.
  2. Clique no nome do bucket (por exemplo, dataminr-alert-logs).
  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.

Tabela de mapeamento do UDM

Campo de registro Mapeamento do UDM Lógica
alertId metadata.product_log_id Valor copiado diretamente
alertType.color about.labels.alertType_color Valor copiado diretamente
alertType.id about.labels.alertType_id Valor copiado diretamente
alertType.name about.labels.alertType_name Valor copiado diretamente
availableRelatedAlerts about.labels.availableRelatedAlerts Convertido em string
caption metadata.description Valor copiado diretamente
cat.name security_result.category_details Valor copiado diretamente
cat.id security_result.detection_fields.categories_id Valor copiado diretamente
cat.idStr security_result.detection_fields.categories_idStr Valor copiado diretamente
cat.path security_result.detection_fields.categories_path Valor copiado diretamente
cat.requested security_result.detection_fields.categories_requested Valor copiado diretamente
cat.retired security_result.detection_fields.categories_retired Convertido em string
cat.topicType about.labels.categories_topicType Valor copiado diretamente
cat.name security_result.category Definido como POLICY_VIOLATION se cat.name == "Cybersecurity - Policy"; NETWORK_MALICIOUS se estiver em ["Cybersecurity - Threats & Vulnerabilities", "Cybersecurity - Crime & Malicious Activity", "Threats & Precautions", "Threats"]; NETWORK_SUSPICIOUS se =~ "Cybersecurity"; MAIL_PHISHING se =~ "Email and Web Servers"; DATA_EXFILTRATION se =~ "Data Exposure and Breaches"; POLICY_VIOLATION se =~ "Government, Policy, & Political Affairs"; PHISHING se =~ "(Malware
comp.dm_bucket.name security_result.about.resource.attribute.labels.dmbucket%{bucket.id} Valor copiado diretamente
comp.dm_sector.name security_result.about.resource.attribute.labels.dmsector%{sector.id} Valor copiado diretamente
comp.id security_result.about.resource.attribute.labels.companies_id Valor copiado diretamente
comp.idStr security_result.about.resource.attribute.labels.companies_idStr Valor copiado diretamente
comp.locations.city security_result.about.location.city Valor de loc.city se loc_index == 0
comp.locations.country, comp.locations.state.symbol security_result.about.location.country_or_region Concatenado como %{loc.country} - %{loc.state.symbol} se loc_index == 0 e ambos não estiverem vazios
comp.locations.postalCode security_result.about.resource.attribute.labels.locations_postalCode Valor copiado diretamente se loc_index == 0 e não estiver vazio
comp.locations.state.name security_result.about.location.state Valor copiado diretamente se loc_index == 0
comp.locations.city about.labels.loc_%{loc_index}_city Valor copiado diretamente se loc_index != 0 e não estiver vazio
comp.locations.country, comp.locations.state.symbol about.labels.loc_%{loc_index}_country_or_region Concatenado como %{loc.country} - %{loc.state.symbol} se loc_index != 0 e ambos não estiverem vazios
comp.locations.postalCode securityresult.about.resource.attribute.labels.locations%{loc_index}_postalCode Valor copiado diretamente se loc_index != 0 e não estiver vazio
comp.locations.state.name about.labels.loc_%{loc_index}_state_name Valor copiado diretamente se loc_index != 0 e não estiver vazio
comp.name security_result.about.resource.name Valor copiado diretamente
comp.requested security_result.about.resource.attribute.labels.companies_requested Valor copiado diretamente
comp.retired security_result.about.resource.attribute.labels.companies_retired Convertido em string
comp.ticker security_result.about.resource.attribute.labels.companies_ticker Valor copiado diretamente
comp.topicType security_result.about.resource.attribute.labels.companies_topicType Valor copiado diretamente
eventLocation.coordinates.0 principal.location.region_coordinates.latitude Valor copiado diretamente
eventLocation.coordinates.1 principal.location.region_coordinates.longitude Valor copiado diretamente
eventLocation.name principal.location.name Valor copiado diretamente
eventLocation.places principal.labels.location_places Unido de matriz com separador de vírgulas
eventLocation.probability principal.labels.eventLocation_probability Convertido em string
eventLocation.radius principal.labels.eventLocation_radius Convertido em string
eventMapLargeURL principal.labels.eventMapLargeURL Valor copiado diretamente
eventMapSmallURL principal.labels.eventMapSmallURL Valor copiado diretamente
eventTime @timestamp Convertido de ms de época para carimbo de data/hora
eventVolume about.labels.eventVolume Convertido em string
expandAlertURL metadata.url_back_to_product Valor copiado diretamente
expandMapURL principal.labels.expandMapURL Valor copiado diretamente
headerColor about.labels.headerColor Valor copiado diretamente
headerLabel about.labels.headerLabel Valor copiado diretamente
metadata.cyber.addresses.ip principal.ip Extraído usando o padrão grok se index == 0
metadata.cyber.addresses.port principal.port Valor copiado diretamente se index == 0, convertido em número inteiro
metadata.cyber.addresses.port principal.labels.addresses_%{index}_port Valor copiado diretamente se index != 0
metadata.cyber.addresses.version principal.labels.metadata_cyberaddresses%{index}_version Valor copiado diretamente
metadata.cyber.asns network.asn Valor copiado diretamente se index == 0
metadata.cyber.asns about.labels.metadatacyber%{index}_asn Valor copiado diretamente se index != 0
metadata.cyber.hashValues.value security_result.about.file.sha1 Valor copiado diretamente se type == SHA1, em letras minúsculas
metadata.cyber.hashValues.value security_result.about.file.sha256 Valor copiado diretamente se type == SHA256, em letras minúsculas
metadata.cyber.malwares security_result.associations.name Valor copiado diretamente
metadata.cyber.malwares security_result.associations.type Definido como MALWARE
metadata.cyber.orgs network.organization_name Valor copiado diretamente se index == 0
metadata.cyber.orgs about.labels.metadatacyber%{index}_orgs Valor copiado diretamente se index != 0
metadata.cyber.products principal.application Valor copiado diretamente se index == 0
metadata.cyber.products principal.labels.metadata_cyberproducts%{index} Valor copiado diretamente se index != 0
metadata.cyber.threats security_result.threat_name Valor copiado diretamente se index == 0
metadata.cyber.threats security_result.about.labels.metadata_cyberthreats%{index} Valor copiado diretamente se index != 0
metadata.cyber.URLs security_result.about.url Valor copiado diretamente se index == 0
metadata.cyber.URLs securityresult.about.labels.url%{index} Valor copiado diretamente se index != 0
metadata.cyber.malwares.0 security_result.category Definido como SOFTWARE_MALICIOUS se existir
metadata.cyber.vulnerabilities.cvss extensions.vulns.vulnerabilities.cvss_base_score Valor copiado diretamente
metadata.cyber.vulnerabilities.exploitPocLinks extensions.vulns.vulnerabilities.cve_description Unido da matriz com o separador " n"
metadata.cyber.vulnerabilities.id extensions.vulns.vulnerabilities.cve_id Valor copiado diretamente
metadata.cyber.vulnerabilities.products.productName extensions.vulns.vulnerabilities.about.application Valor copiado diretamente se index == 0
metadata.cyber.vulnerabilities.products.productVendor extensions.vulns.vulnerabilities.vendor Valor copiado diretamente se index == 0
metadata.cyber.vulnerabilities.products.productVersion extensions.vulns.vulnerabilities.about.platform_version Valor copiado diretamente se index == 0, espaços removidos
metadata.cyber.vulnerabilities.products.productName extensions.vulns.vulnerabilities.about.labels.productName_%{index} Valor copiado diretamente se index != 0
metadata.cyber.vulnerabilities.products.productVendor extensions.vulns.vulnerabilities.about.labels.productVendor_%{index} Valor copiado diretamente se index != 0
metadata.cyber.vulnerabilities.products.productVersion extensions.vulns.vulnerabilities.about.labels.productVersion_%{index} Valor copiado diretamente se o índice for diferente de 0, espaços removidos
parentAlertId about.labels.parentAlertId Valor copiado diretamente
post.languages.lang target.labels.post_languageslang%{index} Valor copiado diretamente
post.languages.position target.labels.post_languagesposition%{index} Convertido em string
post.link target.labels.post_link Valor copiado diretamente
post.media.link principal.resource.name Valor copiado diretamente se index == 0
post.media.description target.resource.attribute.labels.post_media_description Valor copiado diretamente se index == 0
post.media.display_url target.resource.attribute.labels.post_media_display_url Valor copiado diretamente se index == 0
post.media.isSafe target.resource.attribute.labels.post_media_isSafe Convertido para string se index == 0
post.media.media_url target.resource.attribute.labels.post_media_media_url Valor copiado diretamente se index == 0
post.media.sizes.large.h target.resource.attribute.labels.post_media_sizes_large_h Convertido para string se index == 0
post.media.sizes.large.resize target.resource.attribute.labels.post_media_sizes_large_resize Valor copiado diretamente se index == 0
post.media.sizes.large.w target.resource.attribute.labels.post_media_sizes_large_w Convertido para string se index == 0
post.media.sizes.medium.h target.resource.attribute.labels.post_media_sizes_medium_h Convertido para string se index == 0
post.media.sizes.medium.resize target.resource.attribute.labels.post_media_sizes_medium_resize Valor copiado diretamente se index == 0
post.media.sizes.medium.w target.resource.attribute.labels.post_media_sizes_medium_w Convertido para string se index == 0
post.media.sizes.small.h target.resource.attribute.labels.post_media_sizes_small_h Convertido para string se index == 0
post.media.sizes.small.resize target.resource.attribute.labels.post_media_sizes_small_resize Valor copiado diretamente se index == 0
post.media.sizes.small.w target.resource.attribute.labels.post_media_sizes_small_w Convertido para string se index == 0
post.media.sizes.thumb.h target.resource.attribute.labels.post_media_sizes_thumb_h Convertido para string se index == 0
post.media.sizes.thumb.resize target.resource.attribute.labels.post_media_sizes_thumb_resize Valor copiado diretamente se index == 0
post.media.sizes.thumb.w target.resource.attribute.labels.post_media_sizes_thumb_w Convertido para string se index == 0
post.media.source target.resource.attribute.labels.post_media_source Valor copiado diretamente se index == 0
post.media.thumbnail target.resource.attribute.labels.post_media_thumbnail Valor copiado diretamente se index == 0
post.media.title target.resource.attribute.labels.post_media_title Valor copiado diretamente se index == 0
post.media.url target.resource.attribute.labels.post_media_url Valor copiado diretamente se index == 0
post.media.video_info.duration_millis target.resource.attribute.labels.post_media_video_info_duration_millis Convertido para string se index == 0
post.media.video_info.aspect_ratio target.resource.attribute.labels.post_media_video_info_aspect_ratio Concatenado como %{med.video_info.aspect_ratio.0}, %{med.video_info.aspect_ratio.1} se index == 0
post.media.video_info.variants.bitrate target.resource.attribute.labels.post_media_video_info_variantsbitrate%{var_index} Convertido em string
post.media.video_info.variants.content_type target.resource.attribute.labels.post_media_video_info_variants_contenttype%{var_index} Valor copiado diretamente
post.media.video_info.variants.url target.resource.attribute.labels.post_media_video_info_variantsurl%{var_index} Valor copiado diretamente
post.media.type principal.resource.resource_subtype Valor copiado diretamente se index == 0
post.media.link about.resource.name Valor copiado diretamente se index != 0
post.media.description about.resource.attribute.labels.post_media_description Valor copiado diretamente se index != 0
post.media.display_url about.resource.attribute.labels.post_media_display_url Valor copiado diretamente se index != 0
post.media.isSafe about.resource.attribute.labels.post_media_isSafe Convertido em string se o índice for diferente de 0
post.media.media_url about.resource.attribute.labels.post_media_media_url Valor copiado diretamente se index != 0
post.media.sizes.large.h about.resource.attribute.labels.post_media_sizes_large_h Convertido em string se o índice != 0
post.media.sizes.large.resize about.resource.attribute.labels.post_media_sizes_large_resize Valor copiado diretamente se index != 0
post.media.sizes.large.w about.resource.attribute.labels.post_media_sizes_large_w Convertido em string se o índice != 0
post.media.sizes.medium.h about.resource.attribute.labels.post_media_sizes_medium_h Convertido em string se o índice != 0
post.media.sizes.medium.resize about.resource.attribute.labels.post_media_sizes_medium_resize Valor copiado diretamente se index != 0
post.media.sizes.medium.w about.resource.attribute.labels.post_media_sizes_medium_w Convertido em string se o índice != 0
post.media.sizes.small.h about.resource.attribute.labels.post_media_sizes_small_h Convertido em string se o índice != 0
post.media.sizes.small.resize about.resource.attribute.labels.post_media_sizes_small_resize Valor copiado diretamente se index != 0
post.media.sizes.small.w about.resource.attribute.labels.post_media_sizes_small_w Convertido em string se o índice != 0
post.media.sizes.thumb.h about.resource.attribute.labels.post_media_sizes_thumb_h Convertido em string se o índice != 0
post.media.sizes.thumb.resize about.resource.attribute.labels.post_media_sizes_thumb_resize Valor copiado diretamente se index != 0
post.media.sizes.thumb.w about.resource.attribute.labels.post_media_sizes_thumb_w Convertido em string se o índice != 0
post.media.source about.resource.attribute.labels.post_media_source Valor copiado diretamente se index != 0
post.media.thumbnail about.resource.attribute.labels.post_media_thumbnail Valor copiado diretamente se index != 0
post.media.title about.resource.attribute.labels.post_media_title Valor copiado diretamente se index != 0
post.media.url about.resource.attribute.labels.post_media_url Valor copiado diretamente se index != 0
post.media.video_info.duration_millis about.resource.attribute.labels.post_media_video_info_duration_millis Convertido em string se o índice != 0
post.media.video_info.aspect_ratio about.resource.attribute.labels.post_media_video_info_aspect_ratio Concatenado como %{med.video_info.aspect_ratio.0}, %{med.video_info.aspect_ratio.1} se index != 0
post.media.video_info.variants.bitrate about.resource.attribute.labels.post_media_video_info_variantsbitrate%{var_index} Convertido em string
post.media.video_info.variants.content_type about.resource.attribute.labels.post_media_video_info_variants_contenttype%{var_index} Valor copiado diretamente
post.media.video_info.variants.url about.resource.attribute.labels.post_media_video_info_variantsurl%{var_index} Valor copiado diretamente
post.media.type about.resource.resource_subtype Valor copiado diretamente se index != 0
post.translatedText target.labels.post_translatedText Valor copiado diretamente
post.text target.labels.post_text Valor copiado diretamente
post.timestamp target.resource.attribute.creation_time Convertido de ms de época para carimbo de data/hora
publisherCategory.color target.labels.publisherCategory_color Valor copiado diretamente
publisherCategory.name target.labels.publisherCategory_name Valor copiado diretamente
publisherCategory.shortName target.labels.publisherCategory_shortName Valor copiado diretamente
relatedTerms.url principal.labels.relatedTerms_%{terms.text} Valor copiado diretamente
relatedTermsQueryURL principal.labels.relatedTermsQueryURL Valor copiado diretamente
sect.id about.labels.sectors_id Valor copiado diretamente
sect.idStr about.labels.sectors_idStr Valor copiado diretamente
sect.name about.labels.sectors_name Valor copiado diretamente
sect.retired about.labels.sectors_retired Convertido em string
sect.topicType about.labels.sectors_topicType Valor copiado diretamente
source.channels.0 principal.application Valor copiado diretamente
source.displayName principal.user.user_display_name Valor copiado diretamente
source.link principal.url Valor copiado diretamente
source.verified principal.labels.source_verified Convertido em string
subCaption.bullets.content about.labels.subCaption_bullets_content Valor copiado diretamente
subCaption.bullets.media about.labels.subCaption_bullets_media Valor copiado diretamente
subCaption.bullets.source about.labels.subCaption_bullets_source Valor copiado diretamente
watchlist.id about.labels.watchlistsMatchedByType_id Valor copiado diretamente
watchlist.externalTopicIds about.labels.watchlistsMatchedByType_externalTopicIds Unido de matriz com separador de vírgulas
watchlist.name about.labels.watchlistsMatchedByType_name Valor copiado diretamente
watchlist.type about.labels.watchlistsMatchedByType_type Valor copiado diretamente
watchlist.userProperties.omnilist about.labels.watchlistsMatchedByType_userProperties_omnilist Valor copiado diretamente
watchlist.userProperties.uiListType about.labels.watchlistsMatchedByType_userProperties_uiListType Valor copiado diretamente
watchlist.userProperties.watchlistColor about.labels.watchlistsMatchedByType_userProperties_watchlistColor Valor copiado diretamente
watchlist.locationGroups.locations.id about.labels.watchlistsMatchedByTypelocationGroups%{lg_i}_locationsid%{loc_i} Valor copiado diretamente
watchlist.locationGroups.locations.lng about.labels.watchlistsMatchedByTypelocationGroups%{lg_i}_locationslng%{loc_i} Convertido em string se lg_i != 0 ou loc_i != 0
watchlist.locationGroups.locations.lat about.labels.watchlistsMatchedByTypelocationGroups%{lg_i}_locationslat%{loc_i} Convertido em string se lg_i != 0 ou loc_i != 0
watchlist.locationGroups.locations.name about.labels.watchlistsMatchedByTypelocationGroups%{lg_i}_locationsname%{loc_i} O valor é copiado diretamente se lg_i != 0 ou loc_i != 0
watchlist.locationGroups.id about.labels.watchlistsMatchedByType_locationGroupsid%{lg_i} Valor copiado diretamente
watchlist.locationGroups.name about.labels.watchlistsMatchedByType_locationGroupsname%{lg_i} Valor copiado diretamente
watchlist.locationGroups.locations.lng about.location.region_coordinates.longitude O valor é copiado diretamente se lg_i == 0 e loc_i == 0
watchlist.locationGroups.locations.lat about.location.region_coordinates.latitude O valor é copiado diretamente se lg_i == 0 e loc_i == 0
watchlist.locationGroups.locations.name about.location.name O valor é copiado diretamente se lg_i == 0 e loc_i == 0
source.entityName principal.hostname Valor copiado diretamente
metadata.event_type Definido como "GENERIC_EVENT"; mudado para "SCAN_HOST" se principal_ip ou principal.hostname não estiverem vazios

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