GetIncidentsApiModule
Common code that is appended into scripts which require searching incidents.
python · ApiModules
Source
from CommonServerPython import * from datetime import datetime DEFAULT_LIMIT = 500 DEFAULT_PAGE_SIZE = 100 DEFAULT_TIME_FIELD = "created" def build_query_parameter( custom_query: str | None, incident_types: list[str], time_field: str, from_date: str | None, to_date: str | None, non_empty_fields: list[str], ) -> str: """Builds the query parameter string from given arguments. Args: custom_query (str | None): A custom query. incident_types (list[str] | None): Incident types to retrieve. time_field (str): The relevant time field to search by. from_date (str | None): The start date for the incidents query. to_date (str | None): The end date for the incidents query. non_empty_fields (list[str]): Required non-empty incident fields. Raises: Exception: If no query parts were added. Returns: str: The query string built from the given arguments. """ query_parts = [] if custom_query: query_parts.append(custom_query) if incident_types: types = [x if "*" in x else f'"{x}"' for x in incident_types] query_parts.append(f"type:({' '.join(types)})") if from_date and time_field: query_parts.append(f'{time_field}:>="{from_date}"') if to_date and time_field: query_parts.append(f'{time_field}:<"{to_date}"') if non_empty_fields: query_parts.append(" and ".join(f"{x}:*" for x in non_empty_fields)) if not query_parts: raise DemistoException("Incidents query is empty - please fill at least one argument") return " and ".join(f"({x})" for x in query_parts) def format_incident(inc: dict, fields_to_populate: list[str], include_context: bool) -> dict: """Flattens custom fields with incident data and filters by fields_to_populate Args: inc (dict): An incident. fields_to_populate (list[str]): List of fields to populate. include_context (bool): Whether or not to enrich the incident with its context data. Returns: dict: The formatted incident. """ custom_fields = inc.pop("CustomFields", {}) inc.update(custom_fields or {}) if fields_to_populate: inc = {k: v for k, v in inc.items() if k.lower() in {val.lower() for val in fields_to_populate}} if any(f.lower() == "customfields" for f in fields_to_populate): inc["CustomFields"] = custom_fields if include_context: inc["context"] = execute_command("getContext", {"id": inc["id"]}, extract_contents=True) return inc def get_incidents_with_pagination( query: str, from_date: str | None, to_date: str | None, fields_to_populate: list[str], include_context: bool, limit: int, page_size: int, sort: str, ) -> list[dict]: """Performs paginated getIncidents requests until limit is reached or no more results. Each incident in the response is formatted before returned. Args: query (str): The incidents query string. from_date (str | None): The fromdate argument for the incidents query. to_date (str | None): The todate argument for the incidents query. fields_to_populate (list[str]): The fields to populate for each incident. include_context (bool): Whether or not to enrich the returned incidents with their the context data. limit (int): Maximum number of incidents to return. page_size (int): Number of incidents to retrieve per page. sort (str): Sort order for incidents. Returns: list[dict]: The requested incidents. """ incidents: list = [] page = -1 populate_fields = ",".join(f.split(".")[0] for f in fields_to_populate) demisto.debug(f"Running getIncidents with {query=}") while len(incidents) < limit: page += 1 page_results = ( execute_command( "getIncidents", args={ "query": query, "fromdate": from_date, "todate": to_date, "page": page, "populateFields": populate_fields, "size": page_size, "sort": sort, }, extract_contents=True, fail_on_error=True, ).get("data") or [] ) incidents += page_results if len(page_results) < page_size: break return [format_incident(inc, fields_to_populate, include_context) for inc in incidents[:limit]] def prepare_fields_list(fields_list: list[str] | None) -> list[str]: """Removes `incident.` prefix from the fields list and returns a list of unique values. Args: fields_list (list[str] | None): The current state of the fields list, as provided by the user. Returns: list[str]: The prepared fields list. """ return list({field.removeprefix("incident.") for field in fields_list if field}) if fields_list else [] def get_incidents( custom_query: str | None = None, incident_types: list[str] | None = None, populate_fields: list[str] | None = None, non_empty_fields: list[str] | None = None, time_field: str = DEFAULT_TIME_FIELD, from_date: datetime | None = None, # type: ignore[name-defined] to_date: datetime | None = None, # type: ignore[name-defined] include_context: bool = False, limit: int = DEFAULT_LIMIT, page_size: int = DEFAULT_PAGE_SIZE, ) -> list[dict]: """Performs a deeper formatting on the search arguments and runs paginated incidents search. Args: custom_query (str | None, optional): A custom query. Defaults to None. incident_types (list[str] | None, optional): Incident types to retrieve. Defaults to None. populate_fields (list[str] | None, optional): Incident fields to populate. Defaults to None. non_empty_fields (list[str] | None, optional): Required non-empty incident fields. Defaults to None. from_date (datetime | None, optional): The start date of the timeframe. Defaults to None. to_date (datetime | None, optional): The end date of the timeframe. Defaults to None. time_field (str, optional): The relevant time field to search by. Defaults to "created". include_context (bool, optional): Whether or not to enrich the returned incidents with their the context data. Defaults to False. limit (int, optional): The search limit. Defaults to 500. page_size (int, optional): Maximal page size. Defaults to 100. Returns: list[dict]: The requested incidents. """ non_empty_fields = prepare_fields_list(non_empty_fields) if populate_fields := prepare_fields_list(populate_fields): populate_fields.extend(non_empty_fields + ["id"]) populate_fields = list(set(populate_fields)) query = build_query_parameter( custom_query, incident_types or [], time_field, from_date.isoformat() if from_date and time_field != "created" else None, to_date.isoformat() if to_date and time_field != "created" else None, non_empty_fields, ) return get_incidents_with_pagination( query, from_date.astimezone().isoformat() if from_date and time_field == "created" else None, to_date.astimezone().isoformat() if to_date and time_field == "created" else None, populate_fields, include_context, limit, page_size=min(limit, page_size), sort=f"{time_field}.desc", ) def get_incidents_by_query(args: dict) -> list[dict]: """Performs an initial parsing of args and calls the get_incidents method. Args: args (dict): the GetIncidentsByQuery arguments. Returns: list[dict]: The requested incidents. """ query = args.get("query") incident_types = argToList(args.get("incidentTypes"), transform=str.strip) populate_fields = args.get("populateFields") if populate_fields is not None: populate_fields = populate_fields.replace("|", ",") populate_fields = argToList(populate_fields, transform=str.strip) non_empty_fields = argToList(args.get("NonEmptyFields"), transform=str.strip) time_field = args.get("timeField") or DEFAULT_TIME_FIELD from_date = arg_to_datetime(args.get("fromDate")) to_date = arg_to_datetime(args.get("toDate")) include_context = argToBoolean(args.get("includeContext") or False) limit = arg_to_number(args.get("limit")) or DEFAULT_LIMIT page_size = arg_to_number(args.get("pageSize")) or DEFAULT_PAGE_SIZE return get_incidents( query, incident_types, populate_fields, non_empty_fields, time_field, from_date, to_date, include_context, limit, page_size, )
README
Common code that is appended into scripts which require searching incidents.
Script Data
| Name | Description |
|---|---|
| Script Type | python3 |
| Tags | infra, server |
| Cortex XSOAR Version | 5.0.0 |
Inputs
There are no inputs for this script.
Outputs
There are no outputs for this script.