异步搜索 API

支持的平台:

借助 Google Security Operations 中的搜索平台,您可以针对长时间运行的查询使用异步 API,这些查询会返回最多 100 万条结果的大型结果集。借助这些 API,您可以跨数据源(包括统一数据模型 [UDM] 事件、检测、数据表和实体上下文图 [ECG])发起搜索,而不会阻塞应用。当您使用长时间运行的操作 (LRO) API 运行搜索查询时,会收到一个操作 ID。您可以使用此 ID 监控操作状态,并逐页获取结果。

前提条件

如需使用长时间运行的操作 API,调用方正文需要拥有特定的 Identity and Access Management (IAM) 权限。

如需执行以下操作,您必须拥有相应的 IAM 权限:

  • 发起搜索:chronicle.searchSessions.search
  • 列出结果:SearchSession 资源上的 chronicle.searchedResults.list

确保调用方主账号拥有授予这些权限的角色,例如 Chronicle API Viewer、Chronicle API Editor 或 Chronicle API Admin 角色。

使用 LRO API 运行搜索

请按以下步骤使用 LRO API 运行搜索:

  1. 发起搜索
  2. 监控操作
  3. 获取结果

向 Google SecOps 实例上的 search 自定义方法发送 POST 请求。

  • 端点POST /{$api_version}/projects/{project}/locations/{location}/instances/{instance}:search
  • 方法Search
  • 请求正文SearchRequest

以下示例展示了一个 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"
}

相应请求需要以下关键参数:

  • query:搜索查询字符串。
  • time_range:搜索的时间间隔。
  • dialect:将语言方言指定为 YL2
  • result_limit:可选。要具体化的最大行数。默认值为 10000,最大值为 1000000

此调用会返回一个 google.longrunning.Operation 对象。

以下示例展示了成功操作响应:

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

state: RUNNING 字段表示搜索正在进行中。

监控操作

使用 google.longrunning.Operations 服务中的标准 GetOperation 方法轮询 LRO 的状态。使用上一个响应中的 name 值。

  • 端点GET /{$api_version}/projects/{project}/locations/{location}/instances/{instance}/operations/{operationID}

继续轮询,直到 GetOperation 响应中的 done 字段返回 true

  • 如果操作成功,metadata.state 字段将返回 SUCCEEDED,并且响应字段包含已创建的 SearchSession 资源。
  • 如果操作失败,done 字段会返回 true,并且错误字段会包含相关的失败详细信息。

以下示例展示了成功的 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
    }
  }
}

SearchSession 资源名称格式为 projects/{project}/locations/{location}/instances/{instance}/searchSessions/{search_session}

成功响应包含以下关键字段:

  • done:设置为 true 时,表示操作已完成。
  • state:如果设置为 SUCCEEDED,则表示搜索已成功完成。
  • response.nameSearchSession 的资源名称。在下一步中,将此值用作父属性。
  • response.metadata.resultRowCount:表示找到的行总数。
  • response.metadata.moreDataAvailable:表示可用结果的数量超过了定义的返回限制。

列出 LRO 操作

如需列出 LRO 操作,请使用 google.longrunning.Operations 服务中的 ListOperations 方法。使用上一个响应中的 name 值。

  • 端点GET /{$api_version}/projects/{project}/locations/{location}/instances/{instance}

如需列出过去 24 小时内的所有 LRO 操作,请添加过滤条件 name: "operations/s-lro"

以下示例展示了成功的 ListOperations 请求:

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

以下示例展示了成功的 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"
    }
  }
}

提取结果

当操作状态返回 SUCCEEDED 后,使用 ListSearchedResults() 方法检索搜索结果。

  • 端点GET /{$api_version}/{parent=projects/*/locations/*/instances/*/searchSessions/*}/searchedResults
  • 方法ListSearchedResults
  • 请求参数ListSearchedResultsRequest

以下示例展示了一个 ListSearchedResultsRequest,该 ListSearchedResultsRequest 会检索 3 个结果并跳过前 5 个结果:

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

该请求支持以下查询参数:

  • page_size:每页返回的结果数上限。默认值为 100,最大值为 10000。
  • page_token:之前 ListSearchedResultsResponse 中的令牌,用于检索下一页。
  • order_by:可选。该字段用于对结果进行排序。

    • UDM events (eventRecord):使用 udm 字段中的路径,例如 udm.metadata.timestamp descudm.principal.hostname asc。还支持包含 hostnameuserprocess nameevent type 的列名称。

      默认值为 udm.metadata.event_timestamp

    • Entities / ECG (entityContextRecord):使用 entity 字段中的路径,例如 graph.entity.ip asc

    • data tables (dataTableRecord):使用 %<table_alias>.<column_name> 格式。 例如 %dt.user desc

      默认值为第一个数据表列。

    • Detections (DetectionRecord):使用关键字 detection,后跟路径,例如 detection.id

    • 联接:对于事件和实体,请使用定义它们的占位符变量。对于所有其他来源,格式保持不变。

      例如:

      • 心电图(UDM-ECG 联接):实体:$e1.graph.entity.hostname
      • UDM(与 UDM 的所有联接):$e1.principal.ip
      • 数据表(UDM-数据表联接):%<table_alias>.<column_name>

      此外,还支持预定义的别名,例如 hostnameuserprocess nameevent type。对于这些,请使用 $e1.hostname.at 格式。

    • skip:可选。要跳过的结果数。如果使用 page_token,请勿使用。

以下示例展示了成功的 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
/searchSessions/SEARCH_SESSION_ID/searchedResults/RESULT_ID", "resultRow": {
"eventRecord": {
//... Similar UDM event structure...
}
}
},
{
""name": "projects/PROJECT_NUMBER/locations/
LOCATION/instances/INSTANCE_ID
/searchSessions/SEARCH_SESSION_ID/searchedResults/RESULT_ID", "resultRow": {
"eventRecord": {
//... Similar UDM event structure...
}
}
}
],
"totalSize": 10000,
"columnNames": [],
"columnSchema": {},
"nextPageToken": "CAKYASAB"
}

如需提取下一页结果,请在下一个 ListSearchedResults 请求的 page_token 查询参数中使用返回的 nextPageToken 值。resultRow 字段包含实际数据。

继续使用每个响应中的 next_page_token 值调用 ListSearchedResults。当 next_page_token 返回空值时,表示已检索到所有结果。

后续步骤

如需详细了解方法、请求和响应字段以及类型,请参阅以下 API 参考文档:

需要更多帮助?获得社区成员和 Google SecOps 专业人士的解答。