XMCyberDashboard

Return the specific data for the XM Cyber Dashboard.

python · XM Cyber

Source

import demistomock as demisto  # noqa: F401
from CommonServerPython import *  # noqa: F401

"""XMCyberDashboard Script for Cortex XSOAR
This is a dashboard-widget script built
for the "XM Cyber Dashboard" dashboard.
"""

from typing import Any
import traceback


""" CONSTANTS """

SECURITY_SCORE_RT = "security_score"
COMPROMISING_EXPOSURE_RT = "compromising_exposure"
CRITICAL_ASSETS_RT = "critical_assets"
CHOKE_POINTS_RT = "choke_points"
RETURN_TYPES = [
    SECURITY_SCORE_RT,
    COMPROMISING_EXPOSURE_RT,
    CRITICAL_ASSETS_RT,
    CHOKE_POINTS_RT,
]
SCORE_TO_COLOR = {
    "A": "00ff91",  # Green
    "B": "ffd600",  # Gold
    "C": "ff5f1d",  # Orange
    "D": "ff6691",  # Lollipop
    "F": "99002b",  # Deep Paprika
}


""" COMMAND FUNCTION """


def widget_data_generator(args: Dict[str, Any]) -> str | dict:
    """Generate widget data for XM Cyber Dashboard.

    Args:
        args (Dict[str, Any]): Dictionary containing the function arguments.
            - return_type (str): Type of data to return. Valid values are:
                - "security_score": Returns security score information
                - "choke_points": Returns choke points data
                - "critical_assets": Returns critical assets data
                - "compromising_exposure": Returns compromising exposures data
            Defaults to "security_score" if not provided.

    Returns:
        str | dict:
            - For "security_score": Returns a markdown formatted string
            - For other types: Returns a dictionary with 'total' and 'data' keys

    Raises:
        DemistoException: If return_type is not one of the valid types, or if no
                         XM Cyber CEM integration instance is configured.

    """
    return_type = args.get("return_type", "security_score").strip()

    if return_type not in RETURN_TYPES:
        raise DemistoException(f"Invalid argument provided for 'return_type' with value: '{return_type}'")

    command_results = demisto.executeCommand("xmcyber-get-dashboard-data", {})
    command_output = json.loads(json.dumps(command_results))

    combined_data = {}
    if command_output:
        combined_data = command_output[0].get("Contents", {})
        if not combined_data:
            raise DemistoException("No data found in the response. Please check the 'XM Cyber CEM' integration instance.")
        if not isinstance(combined_data, dict):
            raise DemistoException(
                "Invalid data format in the response. Expected a dictionary, but got "
                f"{type(combined_data)} with value: {combined_data}. Please check the 'XM Cyber CEM' integration instance."
            )
    else:
        raise DemistoException(
            "No XM Cyber CEM integration instance found. Please configure an instance of the 'XM Cyber CEM' integration."
        )

    if return_type == SECURITY_SCORE_RT:
        security_score_response: dict = combined_data.get("SecurityScore", {})
        grade = security_score_response.get("grade", "")
        score = security_score_response.get("score", 0)
        trend = security_score_response.get("trend", 0)
        trend_emoji = "📈" if trend > 0 else ("📉" if trend < 0 else "➡️")
        if trend > 0:
            trend = f"+{trend}"
        return (
            f"## <-:-> Security Score\n\n# <-:-> {{{{color:#{SCORE_TO_COLOR.get(grade, '')}}}}}(**{grade}**)\n\n"
            f"### <-:-> **{score}**\n\n"
            f"#### <-:-> **{trend}** {trend_emoji} From last month"
        )

    if return_type == CHOKE_POINTS_RT:
        choke_points: list = combined_data.get("ChokePoints", [])
        return {
            "total": len(choke_points),
            "data": [
                {
                    "Name": choke_point.get("name", ""),
                    "Severity": choke_point.get("severity", ""),
                    "Severity Score": choke_point.get("severityScore", ""),
                }
                for choke_point in choke_points
            ],
        }

    if return_type == CRITICAL_ASSETS_RT:
        critical_assets: list = combined_data.get("CriticalAssets", [])
        return {
            "total": len(critical_assets),
            "data": [
                {
                    "Name": critical_asset.get("name", ""),
                    "Severity": critical_asset.get("severity", ""),
                    "Severity Score": critical_asset.get("severityScore", ""),
                }
                for critical_asset in critical_assets
            ],
        }

    if return_type == COMPROMISING_EXPOSURE_RT:
        compromising_exposures: list = combined_data.get("CompromisingExposures", [])
        return {
            "total": len(compromising_exposures),
            "data": [
                {
                    "Name": compromising_exposure.get("name", ""),
                    "Complexity": compromising_exposure.get("complexity", ""),
                    "Severity": compromising_exposure.get("severity", ""),
                    "Choke Points": compromising_exposure.get("chokePoints", ""),
                    "Compromised Entities": compromising_exposure.get("entities", ""),
                    "Critical Assets": compromising_exposure.get("criticalAssets", ""),
                    "Critical Assets at Risk": compromising_exposure.get("criticalAssetsAtRisk", ""),
                    "Total Assets": compromising_exposure.get("totalAssets", ""),
                }
                for compromising_exposure in compromising_exposures
            ],
        }

    raise DemistoException(f"Invalid argument provided for 'return_type' with value: '{return_type}'")


""" MAIN FUNCTION """


def main():
    """Main execution function for XMCyberDashboard script.

    Raises:
        Exception: Any exception raised during execution is caught, logged via demisto.error,
                  and returned as an error message via return_error.
    """
    try:
        return_results(widget_data_generator(demisto.args()))
    except Exception as ex:
        demisto.error(traceback.format_exc())  # print the traceback
        return_error(f"Failed to load data using 'XMCyberDashboard' automation script. Error: {str(ex)}")


""" ENTRY POINT """


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

README

Return the specific data for the XM Cyber Dashboard.

Script Data


Name Description
Script Type python3
Cortex XSOAR Version 6.10.0

Inputs


Argument Name Description
return_type Select the return type to have specific output context for widget. Possible values are: security_score, compromising_exposure, critical_assets, choke_points.

Outputs


There are no outputs for this script.