APIs de búsqueda asíncrona

Compatible con:

La plataforma de búsqueda de Google Security Operations te permite usar APIs asíncronas para consultas de larga duración que devuelven conjuntos de resultados grandes de hasta 1 millón de resultados. Estas APIs te permiten iniciar búsquedas en fuentes de datos, incluidos los eventos del modelo de datos unificado (UDM), las detecciones, las tablas de datos y el gráfico de contexto de entidades (ECG), sin bloquear tu aplicación. Cuando ejecutas una consulta de búsqueda con una API de operación de larga duración (LRO), recibes un ID de operación. Puedes usar este ID para supervisar el estado de la operación y obtener los resultados página por página.

Requisitos previos

Para usar las APIs de operaciones de larga duración, la principal que realiza la llamada requiere permisos específicos de Identity and Access Management (IAM).

Para realizar las siguientes acciones, debes tener los permisos de IAM correspondientes:

  • Inicia una búsqueda: chronicle.searchSessions.search
  • Enumera los resultados: chronicle.searchedResults.list en el recurso SearchSession.

Asegúrate de que la principal que realiza la llamada tenga un rol que otorgue estos permisos, por ejemplo, el rol de visualizador de la API de Chronicle, editor de la API de Chronicle o administrador de la API de Chronicle.

Ejecuta una búsqueda con las APIs de LRO

Sigue estos pasos para ejecutar una búsqueda con las APIs de LRO:

  1. Inicia la búsqueda.
  2. Supervisa la operación.
  3. Recupera los resultados.

Envía una solicitud POST al método personalizado search en la instancia de Google SecOps.

  • Extremo: POST /{$api_version}/projects/{project}/locations/{location}/instances/{instance}:search
  • Método: Search
  • Cuerpo de la solicitud: SearchRequest

En el siguiente ejemplo, se muestra un 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"
}

La solicitud requiere los siguientes parámetros clave:

  • query: Es la cadena de consulta de búsqueda.
  • time_range: Es el intervalo de tiempo de la búsqueda.
  • dialect: Especifica el dialecto del idioma como YL2.
    • El dialecto SQL no es compatible con la recuperación asíncrona de resultados de LRO con ListSearchedResults (searchedResults.list).
    • El dialecto RAW_LOG se encuentra en versión preliminar y podría devolver un error 501 UNIMPLEMENTED si no está habilitado para tu instancia.
  • result_limit: Opcional Es la cantidad máxima de filas que se materializarán. El valor predeterminado es 10000 y el valor máximo es 1000000.
  • simulated_data_visibility (o simulatedDataVisibility en JSON): Es opcional. Controla si los resultados de la búsqueda incluyen eventos simulados. Establécelo en SIMULATED_DATA_INCLUDED para incluir eventos simulados en los resultados de la búsqueda. Si no se especifica, este parámetro se establece de forma predeterminada en SIMULATED_DATA_EXCLUDED, lo que excluye los eventos simulados.

Esta llamada devuelve un objeto google.longrunning.Operation.

En el siguiente ejemplo, se muestra una respuesta de operación correcta:

{
  "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"
  }
}

El campo state: RUNNING indica que la búsqueda está en curso.

Supervisa la operación

Sondea el estado de la LRO con el método GetOperation estándar del servicio google.longrunning.Operations. Usa el valor name de la respuesta anterior.

  • Extremo: GET /{$api_version}/projects/{project}/locations/{location}/instances/{instance}/operations/{operationID}

Sigue sondeando hasta que el campo done de la respuesta GetOperation devuelva true.

  • Si la operación se realiza correctamente, el campo metadata.state devuelve SUCCEEDED y el campo de respuesta contiene el recurso SearchSession creado.
  • Si la operación falla, el campo done devuelve true y el campo de error contiene los detalles de la falla relacionada.

En el siguiente ejemplo, se muestra una respuesta correcta de GetOperation:

{
  "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
    }
  }
}

El formato del nombre del recurso SearchSession es projects/{project}/locations/{location}/instances/{instance}/searchSessions/{search_session}.

La respuesta correcta contiene los siguientes campos clave:

  • done: Cuando se establece en true, la operación se completa.
  • state: Cuando se establece en SUCCEEDED, la búsqueda finalizó correctamente.
  • response.name: Es el nombre del recurso de SearchSession. Usa este valor como la propiedad superior en el siguiente paso.
  • response.metadata.resultRowCount: Indica la cantidad total de filas encontradas.
  • response.metadata.moreDataAvailable: Indica que la cantidad de resultados disponibles supera el límite de devolución definido.

Enumera las operaciones de LRO

Para enumerar las operaciones de LRO, usa el método ListOperations del servicio google.longrunning.Operations. Usa el valor name de la respuesta anterior.

  • Extremo: GET /{$api_version}/projects/{project}/locations/{location}/instances/{instance}

Para enumerar las operaciones de LRO de búsqueda de las últimas 24 horas, especifica el filtro name:"operations/s-lro-", incluido el guion final.

En el siguiente ejemplo, se muestra una solicitud ListOperations correcta:

google.longrunning.ListOperationsRequest {
  name: "projects/PROJECT_NUMBER/locations/LOCATION/instances/INSTANCE_ID"
  filter: "name:\"operations/s-lro-\""
  page_size: 100
}

En el siguiente ejemplo, se muestra una respuesta correcta de ListOperations:

{
  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"
    }
  }
}

Recupera los resultados

Después de que el estado de la operación devuelva SUCCEEDED, usa el método ListSearchedResults() para recuperar los resultados de la búsqueda.

  • Extremo: GET /{$api_version}/{parent=projects/*/locations/*/instances/*/searchSessions/*}/searchedResults
  • Método: ListSearchedResults
  • Parámetros de solicitud: ListSearchedResultsRequest

En el siguiente ejemplo, se muestra un ListSearchedResultsRequest que recupera tres resultados y omite los primeros cinco:

// GET
/v1alpha/projects/PROJECT_NUMBER/locations/LOCATION/instances/INSTANCE_ID/searchSessions/SEARCH_SESSION_ID/searchedResults?page_size=3&skip=5

La solicitud admite los siguientes parámetros de consulta:

  • page_size: Es la cantidad máxima de resultados que se mostrarán por página. El valor predeterminado es 100 y el valor máximo es 10000.
  • page_token: Es el token de un ListSearchedResultsResponse anterior que se usa para recuperar la página siguiente.
  • order_by (o orderBy en JSON): Es opcional. Es el campo que se usa para ordenar los resultados. Cuando omites order_by, los resultados de los eventos de UDM se ordenan por udm.metadata.event_timestamp en orden descendente de forma predeterminada, lo que devuelve primero los eventos más recientes. Cuando especificas una ruta de campo en order_by sin un sufijo de dirección, como udm.principal.hostname, los resultados se ordenan de forma ascendente de forma predeterminada. No agregues asc, ya que el sufijo asc no es compatible y devuelve un error 400 INVALID_ARGUMENT. Para ordenar los resultados de forma descendente, agrega el sufijo desc a la ruta de acceso del campo, como udm.metadata.event_timestamp desc. No se admite la ordenación por varias columnas.

    • UDM events (eventRecord): Usa rutas de acceso completamente calificadas dentro del campo udm, como udm.metadata.event_timestamp desc o udm.principal.hostname. También se admiten nombres de columnas como hostname, user, process name y event type.

      El orden predeterminado es udm.metadata.event_timestamp en orden descendente, que devuelve primero los eventos más recientes.

    • Entities / ECG (entityContextRecord): Usa rutas de acceso dentro del campo entity, como graph.entity.ip o graph.entity.ip desc.

    • data tables (dataTableRecord): Usa el formato %<table_alias>.<column_name>. Por ejemplo, %dt.user desc.

      El valor predeterminado es la primera columna de la tabla de datos.

    • Detections (DetectionRecord): Usa la palabra clave detection seguida de la ruta de acceso, por ejemplo, detection.id.

    • Uniones: Para los eventos y las entidades, usa la variable de marcador de posición que los define. Para todas las demás fuentes, el formato sigue siendo el mismo.

      Por ejemplo:

      • ECG (unión de UDM y ECG): Entidad: $e1.graph.entity.hostname
      • UDM (todas las uniones con UDM): $e1.principal.ip
      • Tabla de datos (unión de tabla de datos y UDM): %<table_alias>.<column_name>

      También se admiten alias predefinidos, como hostname, user, process name y event type. Para estos, usa el formato $e1.hostname.at.

  • skip: Opcional Es la cantidad de resultados que se omitirán. No uses este parámetro con page_token.

    • La ordenación predeterminada (udm.metadata.event_timestamp) no es única en los eventos que comparten la misma marca de tiempo. Además, el orden de los resultados de la búsqueda se establece en la primera llamada a ListSearchedResults (searchedResults.list).
    • Cuando pagines con skip, en especial en solicitudes paralelas, especifica un campo de orden único, como udm.metadata.id, en el parámetro order_by. Como alternativa, recupera la primera página antes de enviar solicitudes skip paralelas para que el orden de clasificación ya esté establecido.

En el siguiente ejemplo, se muestra una respuesta correcta de ListSearchedResultsResponse:

{
"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 recuperar la página de resultados siguiente, usa el valor nextPageToken que se muestra en el parámetro de consulta page_token de tu próxima solicitud ListSearchedResults. El campo resultRow contiene los datos reales.

Sigue llamando a ListSearchedResults con el valor next_page_token de cada respuesta. Cuando next_page_token devuelve un valor vacío, significa que se recuperaron todos los resultados.

¿Qué sigue?

Para obtener más información sobre los métodos, los campos de solicitud y respuesta, y los tipos, consulta la siguiente documentación de referencia de la API:

¿Necesitas más ayuda? Obtén respuestas de miembros de la comunidad y profesionales de Google SecOps.