Coletar registros do Censys
Este documento explica como ingerir registros do Censys no Google Security Operations usando o Google Cloud Storage V2.
A Censys oferece gerenciamento abrangente de superfície de ataque e inteligência da Internet pela API. Com essa integração, é possível coletar eventos de descoberta de host, eventos de risco e mudanças de recursos do Censys ASM e encaminhá-los para o Google SecOps para análise e monitoramento.
Antes de começar
Verifique se você atende os seguintes pré-requisitos:
- Uma instância do Google SecOps
- Um projeto do GCP com a API Cloud Storage ativada
- Permissões para criar e gerenciar buckets do GCS
- Permissões para gerenciar políticas do IAM em buckets do GCS
- Permissões para criar serviços do Cloud Run, tópicos do Pub/Sub e jobs do Cloud Scheduler
- Acesso privilegiado ao Censys ASM
Coletar credenciais da API do Censys
- Faça login no console do Censys ASM em app.censys.io.
- Acesse Integrações na parte de cima da página.
- Copie e salve a chave de API e o ID da organização.
- Anote o URL base da API:
https://api.platform.censys.io
Criar um bucket do Google Cloud Storage
- Acesse o Console do Google Cloud.
- Selecione seu projeto ou crie um novo.
- No menu de navegação, acesse Cloud Storage > Buckets.
- Clique em Criar bucket.
Informe os seguintes detalhes de configuração:
Configuração Valor Nomeie seu bucket Insira um nome exclusivo globalmente, por exemplo, censys-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 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
- No Console do GCP, acesse IAM e administrador > Contas de serviço.
- Clique em Criar conta de serviço.
- Informe os seguintes detalhes de configuração:
- Nome da conta de serviço: insira
censys-data-collector-sa. - Descrição da conta de serviço: insira
Service account for Cloud Run function to collect Censys logs.
- Nome da conta de serviço: insira
- Clique em Criar e continuar.
- Na seção Conceder acesso a essa conta de serviço ao projeto, adicione os seguintes papéis:
- Clique em Selecionar papel.
- Pesquise e selecione Administrador de objetos do Storage.
- Clique em + Adicionar outro papel.
- Pesquise e selecione Invocador do Cloud Run.
- Clique em + Adicionar outro papel.
- Pesquise e selecione Invocador do Cloud Functions.
- Clique em Continuar.
- 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:
- Acesse Cloud Storage > Buckets.
- Clique no nome do bucket.
- Acesse a guia Permissões.
- Clique em Conceder acesso.
- Informe os seguintes detalhes de configuração:
- Adicionar principais: insira o e-mail da conta de serviço (por exemplo,
censys-data-collector-sa@PROJECT_ID.iam.gserviceaccount.com). - Atribuir papéis: selecione Administrador de objetos do Storage.
- Adicionar principais: insira o e-mail da conta de serviço (por exemplo,
- 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.
- No Console do GCP, acesse Pub/Sub > Tópicos.
- Selecione Criar tópico.
- Informe os seguintes detalhes de configuração:
- ID do tópico: insira
censys-data-trigger. - Não altere as outras configurações.
- ID do tópico: insira
- 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 ASM do Censys e gravá-los no GCS.
- No console do GCP, acesse o Cloud Run.
- Clique em Criar serviço.
- Selecione Função (use um editor in-line para criar uma função).
Na seção Configurar, forneça os seguintes detalhes de configuração:
Configuração Valor Nome do serviço censys-data-collectorRegiã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. Na seção Acionador (opcional):
- Clique em + Adicionar gatilho.
- Selecione Cloud Pub/Sub.
- Em Selecionar um tópico do Cloud Pub/Sub, escolha o tópico do Pub/Sub (
censys-data-trigger). - Clique em Salvar.
Na seção Autenticação:
- Selecione Exigir autenticação.
- Confira o Identity and Access Management (IAM).
- Role a tela para baixo e abra Contêineres, rede, segurança.
- Acesse a guia Segurança:
- Conta de serviço: selecione a conta de serviço (
censys-data-collector-sa).
- Conta de serviço: selecione a conta de serviço (
Acesse a guia Contêineres:
- Clique em Variáveis e secrets.
Clique em + Adicionar variável para cada variável de ambiente:
Nome da variável Valor de exemplo GCS_BUCKETcensys-logsGCS_PREFIXcensys/STATE_KEYcensys/state.jsonCENSYS_API_KEYyour-censys-api-keyCENSYS_ORG_IDyour-organization-idAPI_BASEhttps://api.platform.censys.io
Role a tela para baixo na guia Variáveis e secrets até Solicitações:
- Tempo limite da solicitação: insira
600segundos (10 minutos).
- Tempo limite da solicitação: insira
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.
- Na seção Recursos:
Role até Ambiente de execução:
- Selecione Padrão (recomendado).
Na seção Escalonamento de revisão:
- Número mínimo de instâncias: insira
0. - Número máximo de instâncias: insira
100ou ajuste com base na carga esperada.
- Número mínimo de instâncias: insira
Clique em Criar.
Aguarde a criação do serviço (1 a 2 minutos).
Depois que o serviço é criado, o editor de código inline é aberto automaticamente.
Adicionar código da função
- Insira main em Ponto de entrada da função.
No editor de código em linha, crie dois arquivos:
- Primeiro arquivo: main.py::
import functions_framework from google.cloud import storage import json import urllib3 import gzip import os from datetime import datetime, timedelta, timezone from typing import Dict, List, Any, Optional from urllib.parse import urlencode # Initialize HTTP client with timeouts http = urllib3.PoolManager( timeout=urllib3.Timeout(connect=5.0, read=30.0), retries=False, ) # Initialize Storage client storage_client = storage.Client() @functions_framework.cloud_event def main(cloud_event): """ Cloud Run function triggered by Pub/Sub to fetch logs from Censys ASM API and write to GCS. Args: cloud_event: CloudEvent object containing Pub/Sub message """ # Get environment variables bucket_name = os.environ.get('GCS_BUCKET') prefix = os.environ.get('GCS_PREFIX', 'censys/') state_key = os.environ.get('STATE_KEY', 'censys/state.json') censys_api_key = os.environ.get('CENSYS_API_KEY') censys_org_id = os.environ.get('CENSYS_ORG_ID') api_base = os.environ.get('API_BASE', 'https://api.platform.censys.io') if not all([bucket_name, censys_api_key, censys_org_id]): print('Error: Missing required environment variables') return try: collector = CensysCollector( bucket_name=bucket_name, prefix=prefix, state_key=state_key, api_key=censys_api_key, org_id=censys_org_id, api_base=api_base ) # Get last collection time last_collection_time = collector.get_last_collection_time() current_time = datetime.now(timezone.utc) print(f'Collecting events since {last_collection_time}') # Collect different types of events logbook_events = collector.collect_logbook_events() risk_events = collector.collect_risks_events() # Save events to GCS collector.save_events_to_gcs(logbook_events, 'logbook') collector.save_events_to_gcs(risk_events, 'risks') # Update state collector.save_collection_time(current_time) print(f'Successfully processed {len(logbook_events)} logbook events and {len(risk_events)} risk events') except Exception as e: print(f'Error processing logs: {str(e)}') raise class CensysCollector: def __init__(self, bucket_name: str, prefix: str, state_key: str, api_key: str, org_id: str, api_base: str): self.bucket_name = bucket_name self.prefix = prefix self.state_key = state_key self.headers = { 'Authorization': f'Bearer {api_key}', 'X-Organization-ID': org_id, 'Content-Type': 'application/json' } self.api_base = api_base self.bucket = storage_client.bucket(bucket_name) def get_last_collection_time(self) -> Optional[datetime]: """Get the last collection timestamp from GCS state file.""" try: blob = self.bucket.blob(self.state_key) if blob.exists(): state_data = blob.download_as_text() state = json.loads(state_data) return datetime.fromisoformat(state.get('last_collection_time', '2024-01-01T00:00:00Z')) except Exception as e: print(f'No state file found or error reading state: {e}') return datetime.now(timezone.utc) - timedelta(hours=1) def save_collection_time(self, collection_time: datetime): """Save the current collection timestamp to GCS state file.""" state = {'last_collection_time': collection_time.strftime('%Y-%m-%dT%H:%M:%SZ')} blob = self.bucket.blob(self.state_key) blob.upload_from_string( json.dumps(state), content_type='application/json' ) def collect_logbook_events(self, cursor: str = None) -> List[Dict[str, Any]]: """Collect logbook events from Censys ASM API using cursor-based pagination.""" events = [] url = f"{self.api_base}/v3/logbook" params = {} if cursor: params['cursor'] = cursor try: query_string = urlencode(params) if params else '' full_url = f"{url}?{query_string}" if query_string else url response = http.request('GET', full_url, headers=self.headers) # Handle rate limiting with exponential backoff if response.status == 429: retry_after = int(response.headers.get('Retry-After', '60')) print(f'Rate limited (429). Retrying after {retry_after}s...') import time time.sleep(retry_after) return self.collect_logbook_events(cursor) if response.status != 200: print(f'API request failed with status {response.status}: {response.data}') return [] data = json.loads(response.data.decode('utf-8')) events.extend(data.get('logbook_entries', [])) # Handle cursor-based pagination next_cursor = data.get('next_cursor') if next_cursor: events.extend(self.collect_logbook_events(next_cursor)) print(f'Collected {len(events)} logbook events') return events except Exception as e: print(f'Error collecting logbook events: {e}') return [] def collect_risks_events(self) -> List[Dict[str, Any]]: """Collect risk events from Censys ASM API.""" events = [] url = f"{self.api_base}/v3/risks" try: response = http.request('GET', url, headers=self.headers) # Handle rate limiting with exponential backoff if response.status == 429: retry_after = int(response.headers.get('Retry-After', '60')) print(f'Rate limited (429). Retrying after {retry_after}s...') import time time.sleep(retry_after) return self.collect_risks_events() if response.status != 200: print(f'API request failed with status {response.status}: {response.data}') return [] data = json.loads(response.data.decode('utf-8')) events.extend(data.get('risks', [])) print(f'Collected {len(events)} risk events') return events except Exception as e: print(f'Error collecting risk events: {e}') return [] def save_events_to_gcs(self, events: List[Dict[str, Any]], event_type: str): """Save events to GCS in compressed NDJSON format.""" if not events: return timestamp = datetime.now(timezone.utc).strftime('%Y%m%d_%H%M%S') filename = f"{self.prefix}{event_type}_{timestamp}.json.gz" try: # Convert events to newline-delimited JSON ndjson_content = '\n'.join(json.dumps(event, separators=(',', ':')) for event in events) # Compress with gzip gz_bytes = gzip.compress(ndjson_content.encode('utf-8')) blob = self.bucket.blob(filename) blob.upload_from_string( gz_bytes, content_type='application/gzip' ) print(f'Saved {len(events)} {event_type} events to {filename}') except Exception as e: print(f'Error saving {event_type} events to GCS: {e}') raise- Segundo arquivo: requirements.txt:
functions-framework==3.* google-cloud-storage==2.* urllib3>=2.0.0Clique em Implantar para salvar e implantar a função.
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.
- No Console do GCP, acesse o Cloud Scheduler.
- Clique em Criar job.
Informe os seguintes detalhes de configuração:
Configuração Valor Nome censys-data-collector-hourlyRegiã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 do Pub/Sub ( censys-data-trigger).Corpo da mensagem {}(objeto JSON vazio)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 a integração
- No console do Cloud Scheduler, encontre seu job.
- Clique em Executar à força para acionar o job manualmente.
- Aguarde alguns segundos.
- Acesse Cloud Run > Serviços.
- Clique no nome da função (
censys-data-collector). - Clique na guia Registros.
Verifique se a função foi executada com sucesso. Procure o seguinte:
Collecting events since YYYY-MM-DDTHH:MM:SS+00:00 Collected X logbook events Collected X risk events Saved X logbook events to censys/logbook_YYYYMMDD_HHMMSS.json.gz Saved X risks events to censys/risks_YYYYMMDD_HHMMSS.json.gz Successfully processed X logbook events and X risk eventsAcesse Cloud Storage > Buckets.
Clique no nome do bucket.
Navegue até a pasta de prefixo (
censys/).Verifique se os novos arquivos
.json.gzforam criados com o carimbo de data/hora atual.
Se você encontrar erros nos registros:
- HTTP 401: verifique as credenciais da API nas variáveis de ambiente
- HTTP 403: verifique se a conta tem as permissões necessárias
- HTTP 429: limitação de taxa. A função vai tentar novamente automaticamente com espera.
- Variáveis de ambiente ausentes: verifique se todas as variáveis necessárias estão definidas.
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
- Acesse Configurações do SIEM > Feeds.
- Clique em Adicionar novo feed.
- Clique em Configurar um único feed.
- No campo Nome do feed, insira um nome para o feed (por exemplo,
Censys logs). - Selecione Google Cloud Storage V2 como o Tipo de origem.
- Selecione CENSYS como o Tipo de registro.
- Clique em Receber conta de serviço.
Um e-mail exclusivo da conta de serviço será exibido, por exemplo:
chronicle-12345678@chronicle-gcp-prod.iam.gserviceaccount.comCopie 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.
- Acesse Cloud Storage > Buckets.
- Clique no nome do bucket.
- Acesse a guia Permissões.
- Clique em Conceder acesso.
- 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.
- Clique em Salvar.
Configurar um feed no Google SecOps para ingerir registros do Censys
- Acesse Configurações do SIEM > Feeds.
- Clique em Adicionar novo feed.
- Clique em Configurar um único feed.
- No campo Nome do feed, insira um nome para o feed (por exemplo,
Censys logs). - Selecione Google Cloud Storage V2 como o Tipo de origem.
- Selecione CENSYS como o Tipo de registro.
- Clique em Próxima.
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://censys-logs/censys/Substitua:
censys-logs: o nome do bucket do GCS.censys/: prefixo/caminho da pasta opcional onde os registros são armazenados (deixe em branco para a raiz).
Exemplos:
- Bucket raiz:
gs://censys-logs/ - Com prefixo:
gs://censys-logs/censys/
- Bucket raiz:
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.
Clique em Próxima.
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 |
|---|---|---|
| assetId | read_only_udm.principal.asset.hostname | Se o campo "assetId" não for um endereço IP, ele será mapeado para "principal.asset.hostname". |
| assetId | read_only_udm.principal.asset.ip | Se o campo "assetId" for um endereço IP, ele será mapeado para "principal.asset.ip". |
| assetId | read_only_udm.principal.hostname | Se o campo "assetId" não for um endereço IP, ele será mapeado para "principal.hostname". |
| assetId | read_only_udm.principal.ip | Se o campo "assetId" for um endereço IP, ele será mapeado para "principal.ip". |
| associatedAt | read_only_udm.security_result.detection_fields.value | O campo "associatedAt" é mapeado para "security_result.detection_fields.value". |
| autonomousSystem.asn | read_only_udm.additional.fields.value.string_value | O campo "autonomousSystem.asn" é convertido em uma string e mapeado para "additional.fields.value.string_value" com a chave "autonomousSystem_asn". |
| autonomousSystem.bgpPrefix | read_only_udm.additional.fields.value.string_value | O campo "autonomousSystem.bgpPrefix" é mapeado para "additional.fields.value.string_value" com a chave "autonomousSystem_bgpPrefix". |
| banner | read_only_udm.principal.resource.attribute.labels.value | O campo de banner é mapeado para principal.resource.attribute.labels.value com a chave "banner". |
| nuvem | read_only_udm.metadata.vendor_name | O campo "cloud" é mapeado para "metadata.vendor_name". |
| comments.refUrl | read_only_udm.network.http.referral_url | O campo "comments.refUrl" é mapeado para "network.http.referral_url". |
| data.cve | read_only_udm.additional.fields.value.string_value | O campo "data.cve" é mapeado para "additional.fields.value.string_value" com a chave "data_cve". |
| data.cvss | read_only_udm.additional.fields.value.string_value | O campo "data.cvss" é mapeado para "additional.fields.value.string_value" com a chave "data_cvss". |
| data.ipAddress | read_only_udm.principal.asset.ip | Se o campo "data.ipAddress" não for igual ao campo "assetId", ele será mapeado para "principal.asset.ip". |
| data.ipAddress | read_only_udm.principal.ip | Se o campo "data.ipAddress" não for igual ao campo "assetId", ele será mapeado para "principal.ip". |
| data.location.city | read_only_udm.principal.location.city | Se o campo "location.city" estiver vazio, o campo "data.location.city" será mapeado para "principal.location.city". |
| data.location.countryCode | read_only_udm.principal.location.country_or_region | Se o campo "location.country" estiver vazio, o campo "data.location.countryCode" será mapeado para "principal.location.country_or_region". |
| data.location.latitude | read_only_udm.principal.location.region_coordinates.latitude | Se os campos "location.coordinates.latitude" e "location.geoCoordinates.latitude" estiverem vazios, o campo "data.location.latitude" será convertido em um ponto flutuante e mapeado para "principal.location.region_coordinates.latitude". |
| data.location.longitude | read_only_udm.principal.location.region_coordinates.longitude | Se os campos "location.coordinates.longitude" e "location.geoCoordinates.longitude" estiverem vazios, o campo "data.location.longitude" será convertido em um ponto flutuante e mapeado para "principal.location.region_coordinates.longitude". |
| data.location.province | read_only_udm.principal.location.state | Se o campo "location.province" estiver vazio, o campo "data.location.province" será mapeado para "principal.location.state". |
| data.mailServers | read_only_udm.additional.fields.value.list_value.values.string_value | Cada elemento na matriz data.mailServers é mapeado para uma entrada additional.fields separada com a chave "Servidores de e-mail" e value.list_value.values.string_value definido como o valor do elemento. |
| data.names.forwardDns[].name | read_only_udm.network.dns.questions.name | Cada elemento na matriz data.names.forwardDns é mapeado para uma entrada network.dns.questions separada com o campo "name" definido como o campo "name" do elemento. |
| data.nameServers | read_only_udm.additional.fields.value.list_value.values.string_value | Cada elemento na matriz data.nameServers é mapeado para uma entrada additional.fields separada com a chave "Name nameServers" e value.list_value.values.string_value definido como o valor do elemento. |
| data.protocols[].transportProtocol | read_only_udm.network.ip_protocol | Se o campo data.protocols[].transportProtocol for um dos seguintes: TCP, EIGRP, ESP, ETHERIP, GRE, ICMP, IGMP, IP6IN4, PIM, UDP ou VRRP, ele será mapeado para network.ip_protocol. |
| data.protocols[].transportProtocol | read_only_udm.principal.resource.attribute.labels.value | O campo data.protocols[].transportProtocol é mapeado para principal.resource.attribute.labels.value com a chave "data_protocols {index}". |
| http.request.headers[].key, http.request.headers[].value.headers.0 | read_only_udm.network.http.user_agent | Se o campo "key" de http.request.headers[] for "User-Agent", o campo correspondente "value.headers.0" de http.request.headers[] será mapeado para "network.http.user_agent". |
| http.request.headers[].key, http.request.headers[].value.headers.0 | read_only_udm.network.http.parsed_user_agent | Se o campo "key" de http.request.headers[] for "User-Agent", o campo correspondente http.request.headers[].value.headers.0 será analisado como uma string de user agent e mapeado para network.http.parsed_user_agent. |
| http.request.headers[].key, http.request.headers[].value.headers.0 | read_only_udm.principal.resource.attribute.labels.key, read_only_udm.principal.resource.attribute.labels.value | Para cada elemento na matriz http.request.headers, o campo "key" é mapeado para "principal.resource.attribute.labels.key", e o campo "value.headers.0" é mapeado para "principal.resource.attribute.labels.value". |
| http.request.uri | read_only_udm.principal.asset.hostname | A parte do nome do host do campo http.request.uri é extraída e mapeada para principal.asset.hostname. |
| http.request.uri | read_only_udm.principal.hostname | A parte do nome do host do campo http.request.uri é extraída e mapeada para principal.hostname. |
| http.response.body | read_only_udm.principal.resource.attribute.labels.value | O campo "http.response.body" é mapeado para "principal.resource.attribute.labels.value" com a chave "http_response_body". |
| http.response.headers[].key, http.response.headers[].value.headers.0 | read_only_udm.target.hostname | Se o campo "key" de http.response.headers[] for "Server", o campo correspondente "value.headers.0" de http.response.headers[] será mapeado para "target.hostname". |
| http.response.headers[].key, http.response.headers[].value.headers.0 | read_only_udm.principal.resource.attribute.labels.key, read_only_udm.principal.resource.attribute.labels.value | Para cada elemento na matriz "http.response.headers", o campo "key" é mapeado para "principal.resource.attribute.labels.key", e o campo "value.headers.0" é mapeado para "principal.resource.attribute.labels.value". |
| http.response.statusCode | read_only_udm.network.http.response_code | O campo "http.response.statusCode" é convertido em um número inteiro e mapeado para "network.http.response_code". |
| ip | read_only_udm.target.asset.ip | O campo "ip" é mapeado para "target.asset.ip". |
| ip | read_only_udm.target.ip | O campo "ip" é mapeado para "target.ip". |
| isSeed | read_only_udm.additional.fields.value.string_value | O campo "isSeed" é convertido em uma string e mapeado para "additional.fields.value.string_value" com a chave "isSeed". |
| location.city | read_only_udm.principal.location.city | O campo "location.city" é mapeado para "principal.location.city". |
| location.continent | read_only_udm.additional.fields.value.string_value | O campo "location.continent" é mapeado para "additional.fields.value.string_value" com a chave "location_continent". |
| location.coordinates.latitude | read_only_udm.principal.location.region_coordinates.latitude | O campo "location.coordinates.latitude" é convertido em um ponto flutuante e mapeado para "principal.location.region_coordinates.latitude". |
| location.coordinates.longitude | read_only_udm.principal.location.region_coordinates.longitude | O campo "location.coordinates.longitude" é convertido em um ponto flutuante e mapeado para "principal.location.region_coordinates.longitude". |
| location.country | read_only_udm.principal.location.country_or_region | O campo "location.country" é mapeado para "principal.location.country_or_region". |
| location.geoCoordinates.latitude | read_only_udm.principal.location.region_coordinates.latitude | Se o campo "location.coordinates.latitude" estiver vazio, o campo "location.geoCoordinates.latitude" será convertido em um ponto flutuante e mapeado para "principal.location.region_coordinates.latitude". |
| location.geoCoordinates.longitude | read_only_udm.principal.location.region_coordinates.longitude | Se o campo "location.coordinates.longitude" estiver vazio, o campo "location.geoCoordinates.longitude" será convertido em um ponto flutuante e mapeado para "principal.location.region_coordinates.longitude". |
| location.postalCode | read_only_udm.additional.fields.value.string_value | O campo "location.postalCode" é mapeado para "additional.fields.value.string_value" com a chave "Postal code". |
| location.province | read_only_udm.principal.location.state | O campo "location.province" é mapeado para "principal.location.state". |
| operação | read_only_udm.security_result.action_details | O campo "operation" é mapeado para "security_result.action_details". |
| perspectiveId | read_only_udm.principal.group.product_object_id | O campo "perspectiveId" é mapeado para "principal.group.product_object_id". |
| porta | read_only_udm.principal.port | O campo de porta é convertido em um número inteiro e mapeado para principal.port. |
| risks[].severity, risks[].title | read_only_udm.security_result.category_details | O campo risks[].severity é concatenado com o campo risks[].title e mapeado para security_result.category_details. |
| serviceName | read_only_udm.network.application_protocol | Se o campo "serviceName" for "HTTP" ou "HTTPS", ele será mapeado para "network.application_protocol". |
| sourceIp | read_only_udm.principal.asset.ip | O campo "sourceIp" é mapeado para "principal.asset.ip". |
| sourceIp | read_only_udm.principal.ip | O campo "sourceIP" é mapeado para "principal.ip". |
| timestamp | read_only_udm.metadata.event_timestamp | O campo de carimbo de data/hora é analisado como um carimbo de data/hora e mapeado para "metadata.event_timestamp". |
| transportFingerprint.id | read_only_udm.metadata.product_log_id | O campo transportFingerprint.id é convertido em uma string e mapeado para metadata.product_log_id. |
| transportFingerprint.raw | read_only_udm.additional.fields.value.string_value | O campo "transportFingerprint.raw" é mapeado para "additional.fields.value.string_value" com a chave "transportFingerprint_raw". |
| tipo | read_only_udm.metadata.product_event_type | O campo "type" é mapeado para "metadata.product_event_type". |
| - | read_only_udm.metadata.product_name | O valor "CENSYS_ASM" é atribuído a metadata.product_name. |
| - | read_only_udm.metadata.vendor_name | O valor "CENSYS" é atribuído a metadata.vendor_name. |
| - | read_only_udm.metadata.event_type | O tipo de evento é determinado com base na presença de campos específicos: NETWORK_CONNECTION se has_princ_machine_id e has_target_machine forem verdadeiros e has_network_flow for falso, NETWORK_DNS se has_network_flow for verdadeiro, STATUS_UPDATE se has_princ_machine_id for verdadeiro e GENERIC_EVENT caso contrário. |
Precisa de mais ajuda? Receba respostas de membros da comunidade e profissionais do Google SecOps.