1515"""UDM search functionality for Chronicle."""
1616
1717from datetime import datetime
18- from typing import Any
18+ from typing import Any , TYPE_CHECKING
1919
20- import requests
20+ from secops .chronicle .models import APIVersion
21+ from secops .chronicle .utils .request_utils import (
22+ chronicle_request ,
23+ )
2124
22- from secops .exceptions import APIError
25+ if TYPE_CHECKING :
26+ from secops .chronicle .client import ChronicleClient
2327
2428
2529def search_udm (
26- client ,
30+ client : "ChronicleClient" ,
2731 query : str ,
2832 start_time : datetime ,
2933 end_time : datetime ,
@@ -32,7 +36,8 @@ def search_udm(
3236 max_attempts : int = 30 ,
3337 timeout : int = 30 ,
3438 debug : bool = False ,
35- ) -> dict [str , Any ]:
39+ as_list : bool = False ,
40+ ) -> dict [str , Any ] | list [dict [str , Any ]]:
3641 """Perform a UDM search query using the Chronicle V1alpha API.
3742
3843 Args:
@@ -46,23 +51,19 @@ def search_udm(
4651 for backwards compatibility)
4752 timeout: Timeout in seconds for each API request (default: 30)
4853 debug: Print debug information during execution
54+ as_list: Whether to return results as a list or dictionary
4955
5056 Returns:
51- Dict containing the search results with events
57+ If as_list is True: List of Events.
58+ If as_list is False: Dict with event list, total number of event and
59+ flag to check if more data is available.
5260
5361 Raises:
5462 APIError: If the API request fails
5563 """
56-
5764 # Unused parameters, kept for backward compatibility
5865 _ = (case_insensitive , max_attempts )
5966
60- # Format the instance ID for the API call
61- instance = client .instance_id
62-
63- # Endpoint for UDM search
64- url = f"{ client .base_url } /{ instance } :udmSearch"
65-
6667 # Format times for the API
6768 start_time_str = start_time .strftime ("%Y-%m-%dT%H:%M:%S.%fZ" )
6869 end_time_str = end_time .strftime ("%Y-%m-%dT%H:%M:%S.%fZ" )
@@ -79,40 +80,21 @@ def search_udm(
7980 print (f"Executing UDM search: { query } " )
8081 print (f"Time range: { start_time_str } to { end_time_str } " )
8182
82- try :
83- response = client .session .get (url , params = params , timeout = timeout )
84-
85- if response .status_code != 200 :
86- error_msg = (
87- f"Error executing search: Status { response .status_code } , "
88- f"Response: { response .text } "
89- )
90- if debug :
91- print (f"Error: { error_msg } " )
92- raise APIError (error_msg )
93-
94- # Parse the response
95- response_data = response .json ()
96-
97- # Extract events and metadata
98- events = response_data .get ("events" , [])
99- more_data_available = response_data .get ("moreDataAvailable" , False )
100-
101- if debug :
102- print (f"Found { len (events )} events" )
103- print (f"More data available: { more_data_available } " )
104-
105- # Build the result structure to match the expected format
106- result = {
107- "events" : events ,
108- "total_events" : len (events ),
109- "more_data_available" : more_data_available ,
110- }
111-
112- return result
113-
114- except requests .exceptions .RequestException as e :
115- error_msg = f"Request failed: { str (e )} "
116- if debug :
117- print (f"Error: { error_msg } " )
118- raise APIError (error_msg ) from e
83+ result = chronicle_request (
84+ client ,
85+ method = "GET" ,
86+ endpoint_path = ":udmSearch" ,
87+ api_version = APIVersion .V1ALPHA ,
88+ params = params ,
89+ timeout = timeout ,
90+ )
91+
92+ if as_list :
93+ return result .get ("events" , [])
94+
95+ events = result .get ("events" , [])
96+ return {
97+ "events" : events ,
98+ "total_events" : len (events ),
99+ "more_data_available" : result .get ("moreDataAvailable" , False ),
100+ }
0 commit comments