iot-security-get-raci

IoT RACI model script.

python · IoT by Palo Alto Networks

Details

IDiot-security-get-raci
Languagepython
From Version5.0.0
Docker Imagedemisto/python3:3.12.13.10116658
Tagsiot

README

IoT RACI model script

Script Data


Name Description
Script Type python3
Tags iot
Cortex XSOAR Version 5.5.0

This script is using the device and incident attributes to evaluate the Responsible (R) and Informed (I) parties in the RACI model.

A list variable needs to be created with a fixed format JSON. You can create a new XSOAR list variable under Settings > Advanced > Lists.

By default, the name of the list variable is IOT_CONFIG.

There are three main sections in the JSON: devices, alerts, and groups.

“devices” is a list of devices mapping to the owners based on the device_id, which is a concatenation of the device’s category, profile, vendor and model delimited by “ ”.
  • device_id: a regular expression to match
  • owner: a group name, which is also defined in the “groups” section

“alerts” is a list of conditions to map a combination of IoT incident type and incident names to the RACI model.

  • iot_raw_type: either “IoT Alert” or “IoT Vulnerability”
  • name_regex: a list of regular expressions trying to match with the alert/vulnerability names
  • raci: a section to define the RACI model for the match. If the value is “IOT_OWNER”, we look up the underlying group using the mapping in “devices” section.

“groups” is all the groups found in the “devices” and “alerts” section.

  • email: the email of the group, this is used when setting the incident owner in XSOAR or sending an email through the email integration
  • snow: it has three fields, table, fields and custom_fields. Those are the fields when you use the official ServiceNow integration when you create a ServiceNow ticket.

Here is the template of the JSON:

{
    "devices": [
        {
            "device_id": "Audio Streaming|Profusion.*",
            "owner": "IT_AUDIO_VIDEO"
        },
        {
            "device_id": "Camera|Avigilon Camera.*",
            "owner": "PHYSICAL_SECURITY"
        }
    ],
    "alerts": [
        {
            "iot_raw_type": "IoT Alert",
            "name_regex": [
                "DOUBLEPULSAR.+",
                "ECLIPSEDWING.+",
                "ETERNALBLUE.+"
            ],
            "raci": {
                "r": "SOC",
                "i": ["IOT_OWNER"]
            }
        },
        {
            "iot_raw_type": "IoT Vulnerability",
            "raci": {
                "r": "IOT_OWNER",
                "i": ["INFOSEC", "SOC"]
            }
        }
    ],
    "groups": {
        "DEFAULT": {
            "email": "default@example.com"
        },
        "SOC": {
            "email": "soc@example.com"
        },
        "INFOSEC": {
            "email": "infosec@example.com"
        },
        "IT_AUDIO_VIDEO": {
            "email": "av@example.com",
            "snow": {
                "table": "incident",
                "fields": {
                    "assignment_group": "98dae8874fd67348bf547fe24210c7a0"
                },
                "custom_fields": {
                    "u_custom_field1": "IT",
                    "u_category": "05b9e5371b3b08905f28fc43cd4bcbe2"
                }
            }
        },
        "PHYSICAL_SECURITY": {
            "email": "security@example.com"
        }
    }
}

Used In


This script is used in the following playbooks and scripts.

  • PANW IoT Incident Handling with ServiceNow

Inputs


Argument Name Description
alert_name The name of the IoT alert.
raw_type The raw type of the incident.
category The device category.
profile The device profile.
vendor The device vendor.
model The device model.
iot_config_list_name The variable name for IOT_CONFIG.

Outputs


Path Description Type
PaloAltoNetworksIoT.RACI The RACI model of the IoT incident unknown
PaloAltoNetworksIoT.RACI.r The responsible in the RACI model string
PaloAltoNetworksIoT.RACI.r_email The email of responsible in the RACI model string
PaloAltoNetworksIoT.RACI.i The informed in the RACI model string
PaloAltoNetworksIoT.RACI.i_email The emails of informed in the RACI model delimited by comma string
PaloAltoNetworksIoT.RACI.owner The IoT owner of the device string
PaloAltoNetworksIoT.RACI.r_snow The ServiceNow information of the incident responsible string
PaloAltoNetworksIoT.RACI.r_snow.fields The fields of the ServiceNow ticket string
PaloAltoNetworksIoT.RACI.r_snow.custom_fields The custom fields of the ServiceNow ticket string
PaloAltoNetworksIoT.RACI.r_snow.table The table of the ServiceNow ticket string
import iot_get_raci
from iot_get_raci import get_raci

_CONFIG = {
    "devices": [
        {"device_id": "Audio Streaming|Profusion Media Player.*", "owner": "IT_AUDIO_VIDEO"},
        {"device_id": "Camera|Avigilon Camera.*", "owner": "WPR_SECURITY"},
        {"device_id": "category|profile|vendor|model", "owner": "IT_AUDIO_VIDEO"},
    ],
    "alerts": [
        {
            "iot_raw_type": "IoT Alert",
            "name_regex": [
                "DOUBLEPULSAR.+",
                "ETERNALBLUE.+",
                "ETERNALROMANCE.+",
                "Excessive domain lookup failures with DGA usage",
                ".+flagged Internet host detected",
                "NETBIOS SMB ADMIN.+",
                "NotPetya.+",
                "PII transmission anomaly",
                "Remote access.+Windows Security Account Manager.+",
                "SamSam Testmanware SMB.+",
                "Win.Ransomware.+",
            ],
            "raci": {"r": "SOC", "i": ["IOT_OWNER"]},
        },
        {
            "iot_raw_type": "IoT Alert",
            "name_regex": [
                "Excessive .+ server port range detected",
                ".+ external SMB port connections",
                "Inbound .+ connections from Internet",
                "Uncontrolled Internet access",
            ],
            "raci": {"r": "INFOSEC", "i": ["IOT_OWNER", "SOC"]},
        },
        {"iot_raw_type": "IoT Vulnerability", "raci": {"r": "IOT_OWNER", "i": ["INFOSEC", "SOC"]}},
    ],
    "groups": {
        "DEFAULT": {"email": "default@example.com"},
        "INFOSEC": {"email": "infosec@example.com"},
        "IT_AUDIO_VIDEO": {
            "email": "itav@example.com",
            "snow": {
                "table": "incident",
                "fields": {"assignment_group": "itav_group_snow_id"},
                "custom_fields": {"u_resolver_department": "IT", "u_category_5": "iot_category_snow_id"},
            },
        },
        "SOC": {"email": "soc@example.com"},
        "WPR_SECURITY": {"email": "wpr_security@example.com"},
    },
}

_CONFIG_WITHOUT_DEFAULT = {
    "devices": [{"device_id": "Audio Streaming|Profusion Media Player.*", "owner": "IT_AUDIO_VIDEO"}],
    "alerts": [{"iot_raw_type": "IoT Vulnerability", "raci": {"r": "IOT_OWNER", "i": ["INFOSEC", "SOC"]}}],
    "groups": {},
}

_CONFIG_WITH_DEFAULT = {
    "devices": [{"device_id": "Audio Streaming|Profusion Media Player.*", "owner": "IT_AUDIO_VIDEO"}],
    "alerts": [{"iot_raw_type": "IoT Vulnerability", "raci": {"r": "IOT_OWNER", "i": ["INFOSEC", "SOC"]}}],
    "groups": {"DEFAULT": {"email": "default@example.com"}},
}


def test_iot_get_raci_normal(monkeypatch):
    """
    Scenario: getting the raci result in a normal case

    Given
    - A device with an IoT alert named "DOUBLEPULSAR Backdoor traffic"

    When
    - Calculating the RACI model result

    Then
    - Ensure the correct RACI model is calculated
    """
    monkeypatch.setattr(iot_get_raci, "get_iot_config", lambda x: _CONFIG)

    outputs = get_raci(
        {
            "alert_name": "DOUBLEPULSAR Backdoor traffic",
            "raw_type": "IoT Alert",
            "category": "Audio Streaming",
            "profile": "Profusion Media Player",
        }
    ).outputs
    assert outputs == {
        "owner": "IT_AUDIO_VIDEO",
        "r": "SOC",
        "r_email": "soc@example.com",
        "r_snow": None,
        "i": "IT_AUDIO_VIDEO",
        "i_email": "itav@example.com",
    }


def test_iot_get_raci_no_default_email(monkeypatch):
    """
    Scenario: checking the responsiblie email is None if a default email is missing in IOT_CONFIG

    Given
    - A device with an IoT Vulnerability

    When
    - Calculating the RACI model result

    Then
    - Ensure the r_email is None even though r is not None
    """
    monkeypatch.setattr(iot_get_raci, "get_iot_config", lambda x: _CONFIG_WITHOUT_DEFAULT)

    outputs = get_raci(
        {"alert_name": "", "raw_type": "IoT Vulnerability", "category": "Audio Streaming", "profile": "Profusion Media Player"}
    ).outputs
    assert outputs == {
        "owner": "IT_AUDIO_VIDEO",
        "r": "IT_AUDIO_VIDEO",
        "r_email": None,
        "r_snow": None,
        "i": "INFOSEC, SOC",
        "i_email": None,
    }


def test_iot_get_raci_default_email(monkeypatch):
    """
    Scenario: checking the responsiblie email is the default one specified in IOT_CONFIG

    Given
    - A device with an IoT Vulnerability

    When
    - Calculating the RACI model result

    Then
    - Ensure the r_email is the default email in IOT_CONFIG
    """
    monkeypatch.setattr(iot_get_raci, "get_iot_config", lambda x: _CONFIG_WITH_DEFAULT)

    outputs = get_raci(
        {"alert_name": "", "raw_type": "IoT Vulnerability", "category": "Audio Streaming", "profile": "Profusion Media Player"}
    ).outputs
    assert outputs == {
        "owner": "IT_AUDIO_VIDEO",
        "r": "IT_AUDIO_VIDEO",
        "r_email": "default@example.com",
        "r_snow": None,
        "i": "INFOSEC, SOC",
        "i_email": "default@example.com, default@example.com",
    }


def test_iot_get_raci_no_name_regex(monkeypatch):
    """
    Scenario: checking the IOT_CONFIG is working without the name regex in the "alerts" section of the JSON

    Given
    - A device with an IoT Vulnerability

    When
    - Calculating the RACI model result

    Then
    - Ensure the r is correct
    """
    monkeypatch.setattr(iot_get_raci, "get_iot_config", lambda x: _CONFIG)

    outputs = get_raci({"alert_name": "FooBar", "raw_type": "IoT Vulnerability", "category": "Foo"}).outputs
    assert outputs == {
        "owner": None,
        "r": None,
        "r_email": None,
        "r_snow": None,
        "i": "INFOSEC, SOC",
        "i_email": "infosec@example.com, soc@example.com",
    }

    outputs = get_raci(
        {"alert_name": "FooBar", "raw_type": "IoT Vulnerability", "category": "Camera", "profile": "Avigilon Camera"}
    ).outputs
    assert outputs == {
        "owner": "WPR_SECURITY",
        "r": "WPR_SECURITY",
        "r_email": "wpr_security@example.com",
        "r_snow": None,
        "i": "INFOSEC, SOC",
        "i_email": "infosec@example.com, soc@example.com",
    }


def test_iot_snow(monkeypatch):
    """
    Scenario: checking the ServiceNow config is returned from the IOT_CONFIG

    Given
    - A device with an IoT Vulnerability

    When
    - Calculating the RACI model result

    Then
    - Ensure the r_snow is returned
    """
    monkeypatch.setattr(iot_get_raci, "get_iot_config", lambda x: _CONFIG)
    outputs = get_raci(
        {
            "alert_name": "FooBar",
            "raw_type": "IoT Vulnerability",
            "category": "Audio Streaming",
            "profile": "Profusion Media Player",
        }
    ).outputs
    assert outputs == {
        "owner": "IT_AUDIO_VIDEO",
        "r": "IT_AUDIO_VIDEO",
        "r_email": "itav@example.com",
        "r_snow": {
            "custom_fields": "u_resolver_department=IT;u_category_5=iot_category_snow_id",
            "fields": "assignment_group=itav_group_snow_id",
            "table": "incident",
        },
        "i": "INFOSEC, SOC",
        "i_email": "infosec@example.com, soc@example.com",
    }


def test_iot_get_raci_no_raci(monkeypatch):
    """
    Scenario: checking the case of missing the group defined in IOT_CONFIG

    Given
    - A device with an owner WPR_SECURITY, and its email is not listed

    When
    - Calculating the RACI model result

    Then
    - Ensure the code is still returning the raci
    """
    monkeypatch.setattr(iot_get_raci, "get_iot_config", lambda x: _CONFIG)
    outputs = get_raci(
        {"alert_name": "FooBar", "raw_type": "IoT Alert", "category": "Camera", "profile": "Avigilon Camera"}
    ).outputs
    assert outputs == {"owner": "WPR_SECURITY", "r": None, "r_email": None, "r_snow": None, "i": None, "i_email": None}