APIs de pesquisa assíncrona
A plataforma de pesquisa no Google Security Operations permite usar APIs assíncronas para consultas de longa duração que retornam grandes conjuntos de até 1 milhão de resultados. Com essas APIs, é possível iniciar pesquisas em fontes de dados, incluindo eventos do Modelo de Dados Unificado (UDM), detecções, tabelas de dados e Gráfico de Contexto de Entidade (ECG), sem bloquear o aplicativo. Ao executar uma consulta de pesquisa usando uma API de operação de longa duração (LRO, na sigla em inglês), você recebe um ID de operação. Use esse ID para monitorar o status de funcionamento da operação e receber os resultados página por página.
Pré-requisitos
Para usar APIs de operação de longa duração, o principal de chamada precisa de permissões específicas do Identity and Access Management (IAM).
Para realizar as ações a seguir, você precisa ter as permissões do IAM correspondentes:
- Iniciar uma pesquisa:
chronicle.searchSessions.search - Resultados da lista:
chronicle.searchedResults.listno recursoSearchSession.
Verifique se o principal que faz a chamada tem um papel que concede essas permissões, por exemplo, o papel de Leitor da API Chronicle, Editor da API Chronicle ou Administrador da API Chronicle.
Fazer uma pesquisa usando APIs LRO
Siga estas etapas para fazer uma pesquisa usando as APIs LRO:
Iniciar a pesquisa
Envie uma solicitação POST para o método personalizado search na instância do Google SecOps.
- Endpoint:
POST /{$api_version}/projects/{project}/locations/{location}/instances/{instance}:search - Método:
Search - Corpo da solicitação:
SearchRequest
O exemplo a seguir mostra um objeto SearchRequest:
{
"parent": "projects/PROJECT_NUMBER/locations/LOCATION/instances/INSTANCE_ID",
"query": "metadata.event_type = \"USER_LOGIN\"",
"time_range": {},
"start_time": "2026-03-16T14:40:13Z",
"endTime": "2026-03-16T15:40:13Z",
"dialect": "YL2"
}
A solicitação exige os seguintes parâmetros principais:
query: a string de consulta de pesquisa.time_range: o intervalo de tempo da pesquisa.dialect: especifica o dialeto do idioma comoYL2.- O dialeto
SQLnão é compatível com a recuperação assíncrona de resultados de LRO usandoListSearchedResults(searchedResults.list). - O dialeto
RAW_LOGestá em pré-lançamento e pode retornar um erro501 UNIMPLEMENTEDse não estiver ativado para sua instância.
- O dialeto
result_limit: opcional. O número máximo de linhas a serem materializadas. O valor padrão é10000, e o valor máximo é1000000.simulated_data_visibility(ousimulatedDataVisibilityem JSON): opcional. Controla se os resultados da pesquisa incluem eventos simulados. Defina comoSIMULATED_DATA_INCLUDEDpara incluir eventos simulados nos resultados da pesquisa. Se não for especificado, o padrão seráSIMULATED_DATA_EXCLUDED, que exclui eventos simulados.
Essa chamada retorna um objeto google.longrunning.Operation.
O exemplo a seguir mostra uma resposta de operação bem-sucedida:
{
"name": "projects/PROJECT_NUMBER/locations/LOCATION/instances/INSTANCE_ID/operations/OPERATION_ID",
"metadata": {
"@type": "[type.googleapis.com/google.cloud.chronicle.v1main.SearchOperationMetadata](https://type.googleapis.com/google.cloud.chronicle.v1main.SearchOperationMetadata)",
"state": "RUNNING",
"start_time": "2026-03-13T10:00:00Z"
}
}
O campo state: RUNNING indica que a pesquisa está em andamento.
Monitorar a operação
Consulte o status da LRO usando o método GetOperation padrão do serviço google.longrunning.Operations. Use o valor name da resposta anterior.
- Endpoint:
GET /{$api_version}/projects/{project}/locations/{location}/instances/{instance}/operations/{operationID}
Continue sondando até que o campo done na resposta GetOperation retorne
true.
- Se a operação for bem-sucedida, o campo
metadata.statevai retornarSUCCEEDED, e o campo de resposta vai conter o recursoSearchSessioncriado. - Se a operação falhar, o campo
donevai retornartrue, e o campo de erro vai conter os detalhes da falha relacionada.
O exemplo a seguir mostra uma resposta GetOperation bem-sucedida:
{
"name": "projects/PROJECT_NUMBER/locations/LOCATION/instances/INSTANCE_ID/operations/OPERATION_ID",
"metadata": {
"@type": "[type.googleapis.com/google.cloud.chronicle.v1main.SearchOperation](https://type.googleapis.com/google.cloud.chronicle.v1main.SearchOperation) Metadata",
"state": "SUCCEEDED",
"startTime": "2026-03-16T15:42:11.037506921Z"
},
"endTime": "2026-03-16T15:42:17.504730842Z",
"expireTime": "2026-03-17T15:42:17.504731874Z",
"progress": 100,
"done": true,
"response": {
"@type": "[type.googleapis.com/google.cloud.chronicle.v1main.SearchSession](https://type.googleapis.com/google.cloud.chronicle.v1main.SearchSession)",
"name": "projects/PROJECT_NUMBER/locations/LOCATION/instances/INSTANCE_ID/searchSessions/SEARCH_SESSION_ID",
"query": "metadata.event_type = \"USER_LOGIN\"",
"timeRange": {},
"startTime": "2026-03-16T14:40:13Z",
"endTime": "2026-03-16T15:40:13Z",
"dialect": "YL2",
"metadata": {
"operationId": "OPERATION_ID",
"startTime": "2026-03-16T15:42:11.037506921Z",
"endTime": "2026-03-16T15:42:17.504730842Z",
"expireTime": "2026-03-17T15:42:17.504731874Z",
"resultRowCount": 10000,
"moreDataAvailable": true
}
}
}
O formato do nome do recurso SearchSession é
projects/{project}/locations/{location}/instances/{instance}/searchSessions/{search_session}.
A resposta bem-sucedida contém os seguintes campos principais:
done: quando definido comotrue, a operação é concluída.state: quando definido comoSUCCEEDED, a pesquisa foi concluída com sucesso.response.name: o nome do recurso doSearchSession. Use esse valor como a propriedade pai na próxima etapa.response.metadata.resultRowCount: indica o número total de linhas encontradas.response.metadata.moreDataAvailable: indica que o número de resultados disponíveis excede o limite de retorno definido.
Listar operações de LRO
Para listar operações de LRO, use o método ListOperations do serviço
google.longrunning.Operations. Use o valor name da resposta anterior.
- Endpoint:
GET /{$api_version}/projects/{project}/locations/{location}/instances/{instance}
Para listar as operações de LRO de pesquisa das últimas 24 horas, especifique o filtro name:"operations/s-lro-", incluindo o hífen final.
O exemplo a seguir mostra uma solicitação ListOperations bem-sucedida:
google.longrunning.ListOperationsRequest {
name: "projects/PROJECT_NUMBER/locations/LOCATION/instances/INSTANCE_ID"
filter: "name:\"operations/s-lro-\""
page_size: 100
}
O exemplo a seguir mostra uma resposta ListOperations bem-sucedida:
{
operations {
name: "projects/PROJECT_NUMBER/locations/LOCATION/instances/INSTANCE_ID/operations/OPERATION_ID_1"
metadata {
type_url: "[type.googleapis.com/google.cloud.chronicle.v1main.SearchOperation](https://type.googleapis.com/google.cloud.chronicle.v1main.SearchOperation) Metadata"
value: "\b\002\022\f\b\367\304\363\316\006\020\317\352\232\240\003\032\f\b\237\307\363\316\006\020\326\334\351\311\001\"\f\b\237\352\370\316\006\020\352\342\351\311\001(d"
}
done: true
response {
type_url: "[type.googleapis.com/google.cloud.chronicle.v1main.SearchSession](https://type.googleapis.com/google.cloud.chronicle.v1main.SearchSession)"
value: "\n\213\001projects/PROJECT_NUMBER/locations/LOCATION/instances/INSTANCE_ID/searchSessions/OPERATION_ID_11022\bip != \"\"\032\020\n\006\b\251\255\334\316\006\022\006\b\351\345\336\316\006\0012\\\n*OPERATION_ID_1\022\f\b\367\304\363\316\006\020\317\352\232\240\003\032\f\b\237\307\363\316\006\020\326\334\351\311\001\"\f\b\237\352\370\316\006\020\352\342\351\311\001(\300\204=0\001"
}
}
operations {
name: "projects/PROJECT_NUMBER/locations/LOCATION/instances/INSTANCE_ID/operations/OPERATION_ID_2"
metadata {
type_url: "[type.googleapis.com/google.cloud.chronicle.v1main.SearchOperationMetadata](https://type.googleapis.com/google.cloud.chronicle.v1main.SearchOperationMetadata)"
value: "\b\002\022\f\b\200\305\363\316\006\020\324\262\367\225\001\032\v\b\241\307\363\316\006\020\321\261\333?\"\v\b\241\352\370\316\006\020\317\264\333?(d"
}
done: true
response {
type_url: "[type.googleapis.com/google.cloud.chronicle.v1main.SearchSession](https://type.googleapis.com/google.cloud.chronicle.v1main.SearchSession)"
value: "\n\213\001projects/PROJECT_NUMBER/locations/LOCATION/instances/INSTANCE_ID/searchSessions/OPERATION_ID_2\022\bip != \"\"\0321020\n\006\b\251\255\334\316\006\022\006\b\351\345\336\316\006\0012Z\n*OPERATION_ID_2\022\f\b\200\305\363\316\006\0201324\262\367\225\001\032\v\b\241\307\363\316\006\020\321\261\333?\"\v\b\241\352\370\316\006\020\317\264\333?(\300\204=0\001"
}
}
}
Buscar os resultados
Depois que o estado da operação retornar SUCCEEDED, use o método ListSearchedResults()
para recuperar os resultados da pesquisa.
- Endpoint:
GET /{$api_version}/{parent=projects/*/locations/*/instances/*/searchSessions/*}/searchedResults - Método:
ListSearchedResults - Parâmetros de solicitação:
ListSearchedResultsRequest
O exemplo a seguir mostra um ListSearchedResultsRequest que recupera três
resultados e ignora os cinco primeiros:
// GET
/v1alpha/projects/PROJECT_NUMBER/locations/LOCATION/instances/INSTANCE_ID/searchSessions/SEARCH_SESSION_ID/searchedResults?page_size=3&skip=5
A solicitação aceita os seguintes parâmetros de consulta:
page_size: o número máximo de resultados a serem retornados por página. O valor padrão é 100, e o valor máximo é 10.000.page_token: o token de umListSearchedResultsResponseanterior usado para recuperar a próxima página.order_by(ouorderByem JSON): opcional. O campo usado para ordenar os resultados. Quando você omiteorder_by, os resultados do evento de UDM são classificados porudm.metadata.event_timestampem ordem decrescente por padrão, retornando os eventos mais recentes primeiro. Quando você especifica um caminho de campo emorder_bysem um sufixo de direção, comoudm.principal.hostname, os resultados são classificados em ordem crescente por padrão. Não anexeasc, porque o sufixoascnão é compatível e retorna um erro400 INVALID_ARGUMENT. Para classificar os resultados em ordem decrescente, adicione o sufixodescao caminho do campo, comoudm.metadata.event_timestamp desc. Não é possível classificar várias colunas.UDM events (eventRecord): use caminhos totalmente qualificados no campoudm, comoudm.metadata.event_timestamp descouudm.principal.hostname. Nomes de colunas comohostname,user,process nameeevent typetambém são aceitos.A ordem de classificação padrão é
udm.metadata.event_timestampem ordem decrescente, que retorna os eventos mais recentes primeiro.Entities / ECG (entityContextRecord): use caminhos no campoentity, comograph.entity.ipougraph.entity.ip desc.data tables (dataTableRecord): use o formato%<table_alias>.<column_name>. Por exemplo,%dt.user desc.O valor padrão é a primeira coluna da tabela de dados.
Detections (DetectionRecord): use a palavra-chavedetectionseguida pelo caminho, por exemplo,detection.id.Mesclagens: para eventos e entidades, use a variável de marcador de posição que os define. Para todas as outras fontes, o formato permanece o mesmo.
Exemplo:
- ECG (junção UDM-ECG): entidade:
$e1.graph.entity.hostname - UDM (todas as junções com UDM):
$e1.principal.ip - Tabela de dados (mesclagem de tabela de dados do UDM):
%<table_alias>.<column_name>
Também há suporte para aliases predefinidos, como
hostname,user,process nameeevent type. Para isso, use o formato$e1.hostname.at.- ECG (junção UDM-ECG): entidade:
skip: opcional. O número de resultados a serem pulados. Não use esse parâmetro compage_token.- A classificação padrão (
udm.metadata.event_timestamp) não é exclusiva em eventos que compartilham o mesmo carimbo de data/hora. Além disso, a ordem de classificação dos resultados da pesquisa é definida na primeira chamadaListSearchedResults(searchedResults.list). - Ao paginar com
skip, especialmente em solicitações paralelas, especifique um campo de classificação exclusivo, comoudm.metadata.id, no parâmetroorder_by. Como alternativa, busque a primeira página antes de enviar solicitaçõesskipparalelas para que a ordem de classificação já esteja definida.
- A classificação padrão (
O exemplo a seguir mostra uma resposta ListSearchedResultsResponse bem-sucedida:
{
"searchedResults": [
{
"name":
"projects/PROJECT_NUMBER/locations/LOCATION/instances/INSTANCE_ID/searchSessions/SEARCH_SESSION_ID/searchedResults/
RESULT_ID",
"resultRow": {
"eventRecord": {
"event": {
"name":
"projects/PROJECT_NUMBER/locations/LOCATION/instances/INSTANCE_ID/events/EVENT_ID",
"udm": {
"metadata": {
"eventTimestamp": "2026-03-16T14:45:18Z",
"eventType": "USER_LOGIN",
"vendorName": "Microsoft",
"productName": "Azure AD"
}
},
//... other UDM fields
}
//... other UDM fields
"eventLogToken":
"EVENT_LOG_TOKEN"
}
},
{ }
},
{
"name": "projects/PROJECT_NUMBER/locations/
LOCATION/instances/INSTANCE_ID</span>
/searchSessions/SEARCH_SESSION_ID/searchedResults/RESULT_ID", "resultRow": {
"eventRecord": {
//... Similar UDM event structure...
}
}
},
{
""name": "projects/PROJECT_NUMBER/locations/
LOCATION/instances/INSTANCE_ID</span>
/searchSessions/SEARCH_SESSION_ID/searchedResults/RESULT_ID", "resultRow": {
"eventRecord": {
//... Similar UDM event structure...
}
}
}
],
"totalSize": 10000,
"columnNames": [],
"columnSchema": {},
"nextPageToken": "CAKYASAB"
}
Para buscar a página seguinte de resultados, use o valor nextPageToken retornado
no parâmetro de consulta page_token da próxima solicitação ListSearchedResults.
O campo resultRow contém os dados reais.
Continue chamando ListSearchedResults com o valor next_page_token de cada resposta. Quando next_page_token retornar vazio, todos os resultados terão sido recuperados.
A seguir
Para mais informações sobre métodos, campos de solicitação e resposta e tipos, consulte a seguinte documentação de referência da API:
Precisa de mais ajuda? Receba respostas de membros da comunidade e profissionais do Google SecOps.