비동기 Search API
Google Security Operations의 검색 플랫폼을 사용하면 최대 100만 개의 결과가 포함된 대규모 결과 집합을 반환하는 장기 실행 쿼리에 비동기 API를 사용할 수 있습니다. 이러한 API를 사용하면 애플리케이션을 차단하지 않고 통합 데이터 모델 (UDM) 이벤트, 감지, 데이터 테이블, 항목 컨텍스트 그래프 (ECG)를 포함한 데이터 소스에서 검색을 시작할 수 있습니다. 장기 실행 작업 (LRO) API를 사용하여 검색어를 실행하면 작업 ID가 수신됩니다. 이 ID를 사용하여 작업 상태를 모니터링하고 페이지별로 결과를 가져올 수 있습니다.
기본 요건
장기 실행 작업 API를 사용하려면 호출 주 구성원에게 특정 Identity and Access Management (IAM) 권한이 필요합니다.
다음 작업을 수행하려면 해당 IAM 권한이 있어야 합니다.
- 검색 시작:
chronicle.searchSessions.search - 결과 나열:
SearchSession리소스에 대한chronicle.searchedResults.list권한
호출 주 구성원에게 이러한 권한을 부여하는 역할(예: Chronicle API 뷰어, Chronicle API 편집자 또는 Chronicle API 관리자 역할)이 있는지 확인합니다.
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로 지정합니다.ListSearchedResults(searchedResults.list)를 사용하는 비동기 LRO 결과 검색에는SQL언어가 지원되지 않습니다.RAW_LOG언어는 프리뷰 버전이며 인스턴스에 사용 설정되지 않은 경우501 UNIMPLEMENTED오류가 반환될 수 있습니다.
result_limit: 선택사항. 구체화할 최대 행 수입니다. 기본값은10000이고 최댓값은1000000입니다.simulated_data_visibility(또는 JSON의simulatedDataVisibility): 선택사항입니다. 검색 결과에 시뮬레이션된 이벤트가 포함되는지 여부를 제어합니다. 검색 결과에 시뮬레이션된 이벤트를 포함하려면SIMULATED_DATA_INCLUDED로 설정합니다. 지정하지 않으면 이 매개변수의 기본값은SIMULATED_DATA_EXCLUDED이며, 시뮬레이션된 이벤트는 제외됩니다.
이 호출은 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/s-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
다음 예시에서는 결과 3개를 검색하고 처음 5개를 건너뛰는 ListSearchedResultsRequest를 보여줍니다.
// GET
/v1alpha/projects/PROJECT_NUMBER/locations/LOCATION/instances/INSTANCE_ID/searchSessions/SEARCH_SESSION_ID/searchedResults?page_size=3&skip=5
요청은 다음 쿼리 매개변수를 지원합니다.
page_size: 페이지당 반환할 최대 결과 수입니다. 기본값은 100이고 최댓값은 10, 000입니다.page_token: 다음 페이지를 검색하는 데 사용되는 이전ListSearchedResultsResponse의 토큰입니다.order_by(또는 JSON의orderBy): 선택사항입니다. 결과를 정렬하는 데 사용되는 필드입니다.order_by를 생략하면 UDM 이벤트 결과가 기본적으로udm.metadata.event_timestamp를 기준으로 내림차순으로 정렬되어 가장 최근 이벤트가 먼저 반환됩니다.udm.principal.hostname와 같이 방향 서픽스 없이order_by에 필드 경로를 지정하면 결과가 기본적으로 오름차순으로 정렬됩니다.asc서픽스는 지원되지 않으며400 INVALID_ARGUMENT오류를 반환하므로asc를 추가하지 마세요. 결과를 내림차순으로 정렬하려면 필드 경로에desc접미사를 추가합니다(예:udm.metadata.event_timestamp desc). 다중 열 정렬은 지원되지 않습니다.UDM events (eventRecord):udm필드 내에서 정규화된 경로를 사용합니다(예:udm.metadata.event_timestamp desc또는udm.principal.hostname).hostname,user,process name,event type과 같은 열 이름도 지원됩니다.기본 정렬 순서는
udm.metadata.event_timestamp내림차순이며, 이 경우 가장 최근 이벤트가 먼저 반환됩니다.Entities / ECG (entityContextRecord):graph.entity.ip또는graph.entity.ip desc와 같은entity필드 내의 경로를 사용합니다.data tables (dataTableRecord):%<table_alias>.<column_name>형식을 사용합니다. 예를 들면%dt.user desc입니다.기본값은 첫 번째 데이터 표 열입니다.
Detections (DetectionRecord): 키워드detection뒤에 경로를 사용합니다(예:detection.id).조인: 이벤트 및 항목의 경우 이를 정의하는 자리표시자 변수를 사용합니다. 다른 모든 소스의 경우 형식은 동일하게 유지됩니다.
예를 들면 다음과 같습니다.
- ECG (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형식을 사용합니다.- ECG (UDM-ECG 조인): 항목:
skip: 선택사항. 건너뛸 결과 수입니다. 이 파라미터를page_token과 함께 사용하지 마세요.- 기본 정렬 (
udm.metadata.event_timestamp)은 동일한 타임스탬프를 공유하는 이벤트에서 고유하지 않습니다. 또한 검색 결과의 정렬 순서는 첫 번째ListSearchedResults(searchedResults.list) 호출에서 설정됩니다. skip를 사용하여 페이지를 매길 때, 특히 동시 요청에서 페이지를 매길 때는order_by매개변수에udm.metadata.id와 같은 고유한 정렬 필드를 지정합니다. 또는 정렬 순서가 이미 설정되도록 병렬skip요청을 보내기 전에 첫 번째 페이지를 가져옵니다.
- 기본 정렬 (
다음 예시는 성공적인 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"
}
결과의 다음 페이지를 가져오려면 다음 ListSearchedResults 요청의 page_token 쿼리 매개변수에 반환된 nextPageToken 값을 사용합니다.
resultRow 필드에는 실제 데이터가 포함됩니다.
각 응답의 next_page_token 값을 사용하여 ListSearchedResults를 계속 호출합니다. next_page_token가 비어 있으면 모든 결과가 검색된 것입니다.
다음 단계
메서드, 요청 및 응답 필드, 유형에 대한 자세한 내용은 다음 API 참고 문서를 참조하세요.
도움이 더 필요하신가요? 커뮤니티 회원 및 Google SecOps 전문가에게 문의하여 답변을 받으세요.