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 muestran grandes conjuntos de resultados de hasta 1 millón de resultados. Estas APIs te permiten iniciar búsquedas en fuentes de datos, incluidos eventos del Modelo de datos unificado (UDM), detecciones, 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 operación de larga duración, la entidad de seguridad 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:

  • Iniciar una búsqueda: chronicle.searchSessions.search
  • Mostrar lista de resultados: chronicle.searchedResults.list en el recurso SearchSession

Asegúrate de que la entidad de seguridad 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: La cadena de consulta de búsqueda.
  • time_range: El intervalo de tiempo para la búsqueda.
  • dialect: Especifica el dialecto del lenguaje como YL2.
  • 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.

Esta llamada muestra un objeto google.longrunning.Operation.

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

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

Continúa sondeando hasta que el campo done en la respuesta GetOperation muestre true.

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

En el siguiente ejemplo, se muestra una respuesta GetOperation exitosa:

{
  "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 exitosa 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: 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.

Mostrar lista de operaciones de LRO

Para mostrar una lista de 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 mostrar una lista de todas las operaciones de LRO de las últimas 24 horas, agrega el filtro name: "operations/s-lro".

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

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

En el siguiente ejemplo, se muestra una respuesta ListOperations exitosa:

{
  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

Una vez que el estado de la operación muestre 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 muestran 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: Opcional. El campo se usa para ordenar los resultados.

    • UDM events (eventRecord): Usa rutas de acceso dentro del campo udm, por ejemplo, udm.metadata.timestamp desc o udm.principal.hostname asc. También se admiten nombres de columnas que incluyen hostname, user, process name y event type.

      El valor predeterminado es udm.metadata.event_timestamp.

    • Entities / ECG (entityContextRecord): Usa rutas de acceso dentro del campo entity, por ejemplo, graph.entity.ip asc.

    • 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 eventos y 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-ECG): Entidad: $e1.graph.entity.hostname
      • UDM (todas las uniones con UDM): $e1.principal.ip
      • Tabla de datos (unión de UDM-tabla de datos): %<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 lo uses si usas page_token.

En el siguiente ejemplo, se muestra una respuesta ListSearchedResultsResponse exitosa:

{
"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 siguiente página de resultados, 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.

Continúa llamando a ListSearchedResults con el valor next_page_token de cada respuesta. Cuando next_page_token muestra un valor vacío, 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.