SetIndicatorGridField
This script updates an indicator's grid field in Cortex XSOAR with provided row data. You can input the rows directly or extract them from the context.
python · Common Scripts
Source
import demistomock as demisto # noqa: F401 from CommonServerPython import * # noqa: F401 def parse_rows(rows: str) -> list[list[str]]: """ Parse the rows input as a string and convert it into a list of lists. Args: rows (str): A string representation of a list of lists. Returns: list[list[str]]: A list of lists representing the rows. Raises: Exception: If the format is invalid or parsing fails. """ if not (rows.startswith("[") and rows.endswith("]")): raise ValueError("Invalid format: rows should be a list of lists e.g., [[1,2],[3,4]]") rows = rows.replace("], [", "],[") rows = rows.strip("[]") row_list_strs = rows.split("],[") row_list: list[list[str]] = [] for row_str in row_list_strs: row_str = row_str.strip("[]") row = row_str.split(",") processed_row = [element.strip().strip('"').strip("'") for element in row] row_list.append(processed_row) return row_list def get_existing_grid_records(indicator_value: str, grid_field: str) -> list[dict[str, str | None]]: """ Retrieve the existing grid field records from the indicator. Args: indicator_value (str): The value of the indicator. grid_field (str): The name of the grid field. Returns: list[dict[str, str | None]]: The existing grid field records. Raises: Exception: If the indicator or grid field is not found or if any errors occur. """ search_result = demisto.executeCommand("findIndicators", {"value": indicator_value}) if isError(search_result): return_error(f"Failed to find indicator {indicator_value}. Error: {get_error(search_result)}") indicators = search_result[0]["Contents"] if not indicators: return_error(f"No indicator found with value {indicator_value}.") indicator = indicators[0] existing_grid_records = indicator.get("CustomFields", {}).get(grid_field, []) if not isinstance(existing_grid_records, list): existing_grid_records = [] return existing_grid_records def main() -> None: """ Main function to update an indicator's grid field with provided row data. The data can either be provided as a dictionary or as a list of lists. Headers for the table must be provided using the 'headers' argument. Keys for the extraction from context dictionaries can be provided using the 'keys_from_context' argument. When the 'append' argument is set to True, the new content is appended to the existing grid content. Raises: Exception: If required arguments are not provided, or if any validations fail. """ raw_input_data = demisto.args().get("input", {}) headers: list[str] = demisto.args().get("headers", "").split(",") indicator_value: str = demisto.args().get("indicator", "") grid_field: str = demisto.args().get("grid_field", "") keys_from_context: str = demisto.args().get("keys_from_context", "") append: bool = demisto.args().get("append", "false").lower() == "true" if not raw_input_data: return_error('You must provide the "input" argument.') # Check if the input data is a dict or list of dicts if isinstance(raw_input_data, dict): raw_input_data = [raw_input_data] # Convert single dictionary to list of dictionaries if isinstance(raw_input_data, list) and all(isinstance(item, dict) for item in raw_input_data): # Process dictionary input if keys_from_context: keys = keys_from_context.split(",") rows: list[list[str]] = [[row.get(key, "") for key in keys[: len(headers)]] for row in raw_input_data] demisto.debug(f"{rows}") else: # Ensure input dictionary keys match headers for row in raw_input_data: if set(row.keys()) != set(headers): return_error("Input dictionary keys must match headers when context keys are not provided.") rows = [[row.get(header, "") for header in headers] for row in raw_input_data] demisto.debug("Changed the data into list format") else: # Process as list of lists string demisto.debug(f"Trying to parse rows - {raw_input_data}") try: rows = parse_rows(str(raw_input_data)) if not isinstance(rows, list) or not all(isinstance(row, list) for row in rows): return_error("Rows must be a list of lists.") except Exception as e: return_error( f"Invalid format for rows input. Expected format: [[1,2],[3,4]] or a valid dictionary structure. Error: {e!s}" ) # Validate that headers are a list of strings if not all(isinstance(header, str) for header in headers): return_error("All headers must be strings.") # Validate rows length matches headers length for row in rows: if len(row) != len(headers): return_error("Each row must have the same number of elements as there are headers.") # Prepare the new rows data in the format expected by the grid field new_grid_records: list[dict[str, str | None]] = [] for row in rows: # Handle empty cells by setting them to None or an empty string record = {header: (value if value != "" else None) for header, value in zip(headers, row)} new_grid_records.append(record) if append: # Append new records to existing ones grid_records = get_existing_grid_records(indicator_value, grid_field) + new_grid_records else: # Overwrite the grid field with new records grid_records = new_grid_records # Update the indicator with the grid field using its value set_indicator_result = demisto.executeCommand("setIndicator", {"value": indicator_value, grid_field: grid_records}) if isError(set_indicator_result): if get_error(set_indicator_result) == "setIndicator must contain at least one field to set (7)": return_error(f"Indicator {indicator_value} has no grid field called {grid_field}.") else: return_error(f"Failed to set grid field for indicator {indicator_value}. Error: {get_error(set_indicator_result)}") else: demisto.results(f"Successfully updated indicator {indicator_value} grid field {grid_field}.") if __name__ in ["__main__", "__builtin__", "builtins"]: main()
README
This script updates an indicator’s grid field in Cortex XSOAR with provided row data. You can input the rows directly or extract them from the context.
Script Data
| Name | Description |
|---|---|
| Script Type | python3 |
Inputs
| Argument Name | Description |
|---|---|
| indicator | The value of the indicator to be updated. |
| grid_field | The name of the grid field you want to update. |
| headers | A comma-separated string listing the column headers for the grid. |
| input | Either a JSON or list of lists. This argument is mandatory. |
| keys_from_context | A comma-separated string listing the keys to extract values from the provided dictionaries in the input. The extracted values will be mapped to the headers in the order provided. |
| append | When set to True, appends the new content to the existing grid content instead of overwriting it. |
Outputs
There are no outputs for this script.