异步搜索 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 运行搜索:
发起搜索
向 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.name:SearchSession的资源名称。在下一步中,将此值用作父属性。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 desc或udm.principal.hostname asc。还支持包含hostname、user、process name和event 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>
此外,还支持预定义的别名,例如
hostname、user、process name和event type。对于这些,请使用$e1.hostname.at格式。- 心电图(UDM-ECG 联接):实体:
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 参考文档: