XCloudAdditionalAlertInformationWidget

This script retrieves additional original alert information from the context.

Type
python
Pack
CloudIncidentResponse

Source

from CommonServerPython import *  # noqa: F401

""" CONSTANTS """

# The `getRawAlerts` command is only available from this server version onwards.
# On older servers we fall back to the legacy `core-get-cloud-original-alerts` command.
MIN_SERVER_VERSION_FOR_RAW_ALERTS = "8.16.0"

""" COMMAND FUNCTION """


def get_additonal_info() -> List[Dict]:
    alerts = demisto.context().get("Core", {}).get("OriginalAlert")
    if not alerts:
        # No original alert in context (e.g. the issue has no cloud-analytics original
        # alert, or retrieval returned nothing). Return an empty result so the widget
        # renders a friendly message instead of surfacing an error banner.
        return []
    if not isinstance(alerts, list):
        alerts = [alerts]

    results = []
    for alert in alerts:
        # Alerts with no XDR cloud-analytics event are returned without an "event" key
        # (both getRawAlerts and the legacy core-get-cloud-original-alerts omit it in that
        # case - see filter_general_fields "No XDR cloud analytics event"). Default to an
        # empty dict so the per-field .get() calls below degrade gracefully instead of
        # raising 'NoneType' object has no attribute 'get'.
        alert_event = alert.get("event") or {}
        res = {
            "Alert Full Description": alert.get("alert_full_description"),
            "Detection Module": alert.get("detection_modules"),
            "Vendor": alert_event.get("vendor"),
            "Provider": alert_event.get("cloud_provider"),
            "Log Name": alert_event.get("log_name"),
            "Event Type": demisto.get(alert_event, "raw_log.eventType"),
            "Caller IP": alert_event.get("caller_ip"),
            "Caller IP Geo Location": alert_event.get("caller_ip_geolocation"),
            "Resource Type": alert_event.get("resource_type"),
            "Identity Name": alert_event.get("identity_name"),
            "Operation Name": alert_event.get("operation_name"),
            "Operation Status": alert_event.get("operation_status"),
            "User Agent": alert_event.get("user_agent"),
        }
        results.append(res)
    indicators = [res.get("Caller IP") for res in results]
    indicators_callable = indicators_value_to_clickable(indicators)
    for res in results:
        res["Caller IP"] = indicators_callable.get(res.get("Caller IP"))
    return results


def verify_list_type(original_alert_data):
    if not isinstance(original_alert_data, list) or not original_alert_data:
        return None
    entry_context = original_alert_data[0].get("EntryContext") or {}
    # Match the `Core.OriginalAlert` prefix so we are resilient to the exact DT selector form.
    original_alert_key = next(
        (key for key in entry_context if key.startswith("Core.OriginalAlert")),
        None,
    )
    if not original_alert_key:
        return None
    res = {"OriginalAlert": entry_context.pop(original_alert_key)}
    if isinstance(res["OriginalAlert"], list):
        res["OriginalAlert"] = res["OriginalAlert"][0]
    return res


""" MAIN FUNCTION """


def main():  # pragma: no cover
    try:
        alert_context = demisto.investigation()
        core_alert_context = demisto.context().get("Core", {})
        if not core_alert_context.get("OriginalAlert"):
            if is_demisto_version_ge(MIN_SERVER_VERSION_FOR_RAW_ALERTS):
                original_alert_data = demisto.executeCommand("getRawAlerts", {"issue_ids": alert_context.get("id")})
            else:
                original_alert_data = demisto.executeCommand(
                    "core-get-cloud-original-alerts", {"alert_ids": alert_context.get("id")}
                )
            if isError(original_alert_data):
                raise DemistoException(f"Failed to retrieve original alerts: {get_error(original_alert_data)}")
            if original_alert_data:
                res = verify_list_type(original_alert_data)
                if res:
                    demisto.executeCommand("SetByIncidentId", {"key": "Core", "value": res, "id": alert_context.get("id")})
        results = get_additonal_info()
        if not results:
            # Nothing to show (no cloud-analytics original alert for this issue).
            return_results(CommandResults(readable_output="No additional alert information available."))
            return
        command_results = CommandResults(
            readable_output=tableToMarkdown("Original Alert Additional Information", results, headers=list(results[0].keys()))
        )
        return_results(command_results)
    except Exception as ex:
        return_error(f"Failed to execute AdditionalAlertInformationWidget. Error: {ex!s}")


""" ENTRY POINT """

if __name__ in ("__main__", "__builtin__", "builtins"):
    main()

README

This script retrieves additional original alert information from the context.

Script Data


Name Description
Script Type python3
Tags dynamic-section
Cortex XSOAR Version 6.10.0

Dependencies


This script uses the following commands and scripts.

Inputs


There are no inputs for this script.

Outputs


There are no outputs for this script.