GetCampaignIncidentsInfo

Get the campaign incidents information as a MD table. This automation runs using the default Limited User role, unless you explicitly change the permissions. For more information, see the section about permissions here: - For Cortex XSOAR 6 see https://docs-cortex.paloaltonetworks.com/r/Cortex-XSOAR/6.x/Cortex-XSOAR-Playbook-Design-Guide/Automations - For Cortex XSOAR 8 Cloud see https://docs-cortex.paloaltonetworks.com/r/Cortex-XSOAR/8/Cortex-XSOAR-Cloud-Documentation/Create-a-script - For Cortex XSOAR 8.7 On-prem see https://docs-cortex.paloaltonetworks.com/r/Cortex-XSOAR/8.7/Cortex-XSOAR-On-prem-Documentation/Create-a-script

python · Phishing Campaign

Source

import copy

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

DEFAULT_HEADERS = ["id", "name", "added_manually_to_campaign", "emailfrom", "recipients", "severity", "status", "created"]
KEYS_FETCHED_BY_QUERY = ["status", "severity"]
NO_CAMPAIGN_INCIDENTS_MSG = "There is no Campaign Incidents in the Context"
LINKABLE_ID_FORMAT = "[{incident_id}](#/Details/{incident_id})"
STATUS_DICT = {
    0: "Pending",
    1: "Active",
    2: "Closed",
    3: "Archive",
}
DEFAULT_CUSTOM_FIELDS = {
    "campaignclosenotes": "Notes explaining why the incident was closed",
    "campaignemailsubject": "Campaign detected",
    "campaignemailbody": "Fill here message for the recipients",
    "selectcampaignincidents": ["All"],
}
SEVERITIES = {4: "Critical", 3: "High", 2: "Medium", 1: "Low", 0.5: "Info", 0: "Unknown"}


def update_incident_with_required_keys(incidents: list, required_keys: list):
    """
    Update the given incident dict (from context) with values retrieved by GetIncidentsByQuery command

    :type incidents: ``list``
    :param incidents: campaign incidents from the context

    :type required_keys: ``list``
    :param required_keys: keys need to be updated

    """

    # If an incident is deleted, remove it from the list to avoid a key error
    incidents = [
        incident
        for incident in incidents
        if demisto.executeCommand("GetIncidentsByQuery", {"query": f"id:({incident['id']})"})[0].get("Contents") != "[]"
    ]

    ids = [str(incident["id"]) for incident in incidents]
    res = demisto.executeCommand("GetIncidentsByQuery", {"query": f"id:({' '.join(ids)})"})
    if isError(res):
        return_error(f"Error occurred while trying to get incidents by query: {get_error(res)}")

    incidents_from_query = json.loads(res[0]["Contents"])
    id_to_updated_incident_map = {incident["id"]: incident for incident in incidents_from_query}
    for incident in incidents:
        updated_incident = id_to_updated_incident_map[incident["id"]]
        for key in required_keys:
            incident[key] = updated_incident.get(key)

    return incidents


def convert_incident_to_hr(incident) -> dict:
    """
    Get the value from incident dict and convert it in some cases e.g. make id linkable etc.
    Note: this script change the original incident

    :type incident: ``dict``
    :param incident: the incident to get the value from

    :rtype: ``dict``
    :return Converted incident
    """
    converted_incident = copy.deepcopy(incident)

    for key in converted_incident:
        if key == "status":
            converted_incident[key] = STATUS_DICT.get(converted_incident.get(key))

        if key == "id":
            converted_incident[key] = LINKABLE_ID_FORMAT.format(incident_id=converted_incident.get(key))

        if key == "severity":
            converted_incident[key] = SEVERITIES.get(converted_incident.get(key), "None")

        if key == "similarity":
            if str(converted_incident[key])[0] == "1":
                converted_incident[key] = "1"

            elif len(str(converted_incident[key])) > 4:
                converted_incident[key] = str(round(converted_incident[key], 3))
                converted_incident[key] = (
                    converted_incident[key][:-1] if len(converted_incident[key]) > 4 else converted_incident[key]
                )

            else:
                converted_incident[key] = str(converted_incident[key])

        converted_incident[key] = converted_incident.get(key.replace("_", ""))
    converted_incident["added_manually_to_campaign"] = incident.get("added_manually_to_campaign", False)

    return converted_incident


def get_campaign_incidents_from_context():
    return demisto.get(demisto.context(), "EmailCampaign.incidents")


def get_incidents_info_md(incidents: list, fields_to_display: list | None = None) -> str | None:
    """
    Get the campaign incidents relevant info in MD table

    :type incidents: ``list``
    :param incidents: the campaign incidents to collect the info from
    :type fields_to_display: ``list``
    :param fields_to_display: list of result headers

    :rtype: ``str``
    :return the MD table str

    """

    if incidents:
        headers = fields_to_display or DEFAULT_HEADERS
        converted_incidents = [convert_incident_to_hr(incident) for incident in incidents]

        return tableToMarkdown(
            name="",
            t=converted_incidents,
            headerTransform=string_to_table_header,
            headers=headers,
            removeNull=True,
        )

    return None


def update_empty_fields():
    """
    Update the campaign dynamic section empty field with default values in order for them to appear in the page
    """
    incident = demisto.incidents()[0]
    custom_fields = incident.get("customFields", {})

    for field in DEFAULT_CUSTOM_FIELDS:
        if not custom_fields.get(field):
            custom_fields[field] = DEFAULT_CUSTOM_FIELDS[field]
    demisto.executeCommand("setIncident", {"id": incident["id"], "customFields": custom_fields})


def main():
    try:
        incidents = get_campaign_incidents_from_context()
        fields_to_display = demisto.get(demisto.context(), "EmailCampaign.fieldsToDisplay")
        if incidents:
            incidents = update_incident_with_required_keys(incidents, KEYS_FETCHED_BY_QUERY)
            update_empty_fields()
            readable_output = get_incidents_info_md(incidents, fields_to_display)
        else:
            readable_output = NO_CAMPAIGN_INCIDENTS_MSG

        return_results(CommandResults(readable_output=readable_output, raw_response=readable_output))
    except Exception as err:
        return_error(str(err))


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

README

Creates a channel in Slack v2 or in Microsoft Teams. If both Slack v2 and Microsoft Teams are available,
it creates the channel in both Slack v2 and Microsoft Teams.

This automation runs using the default Limited User role, unless you explicitly change the permissions.
For more information, see the section about permissions here: For Cortex XSOAR 6, see the https://docs-cortex.paloaltonetworks.com/r/Cortex-XSOAR/6.x/Cortex-XSOAR-Playbook-Design-Guide/Automations for Cortex XSOAR 8 Cloud, see the https://docs-cortex.paloaltonetworks.com/r/Cortex-XSOAR/8/Cortex-XSOAR-Cloud-Documentation/Create-a-script for Cortex XSOAR 8 On-prem, see the https://docs-cortex.paloaltonetworks.com/r/Cortex-XSOAR/8.7/Cortex-XSOAR-On-prem-Documentation/Create-a-script.

Script Data


Name Description
Script Type python3
Tags field-display, dynamic-section
Cortex XSOAR Version 5.0.0

Inputs


There are no inputs for this script.

Outputs


There are no outputs for this script.