SendPANWIoTDevicesToCiscoISE

This script takes (as a required argument) custom attributes from PANW IoT cloud and creates or updates endpoints in ISE with the input custom attributes. 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 · IoT 3rd Party Integrations by Palo Alto Networks (Deprecated)

Source

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

PANW_IOT_INSTANCE = demisto.args().get("panw_iot_3rd_party_instance")
CISCO_ISE_ACTIVE_INSTANCE = demisto.args().get("active_ise_instance")
GET_EP_ID_CMD = "cisco-ise-get-endpoint-id-by-name"


def send_status_to_panw_iot_cloud(status, msg):
    """
    Reports status details back to PANW IoT Cloud.
    param status: Status (error, disabled, success) to be send to PANW IoT cloud.
    param msg: Debug message to be send to PANW IoT cloud.
    """
    resp = demisto.executeCommand(
        "panw-iot-3rd-party-report-status-to-panw",
        {
            "status": status,
            "message": msg,
            "integration_name": "ise",
            "playbook_name": "PANW IoT 3rd Party Cisco ISE Integration - Bulk Export to Cisco ISE",
            "asset_type": "device",
            "timestamp": int(round(time.time() * 1000)),
            "using": PANW_IOT_INSTANCE,
        },
    )

    if isError(resp[0]):
        err_msg = f'Error, failed to send status to PANW IoT Cloud - {resp[0].get("Contents")}'
        raise Exception(err_msg)


def extract_ise_api_error(err_msg):
    """
    Extract any connection error or error code if possible,
    Otherwise just return the original error
    """
    err_msg = err_msg.split("-")[0]
    if err_msg.startswith("Error in API call to Cisco"):
        start = err_msg.find("[") + 1
        end = err_msg.find("]")
        return err_msg[start:end]
    elif err_msg.startswith("Connection Error. Verify"):
        return "Connection Error"
    else:
        return err_msg


def update_existing_endpoint(mac, attr_map, ep_id, active_instance):
    """
    Update an existing endpoint with the given custom attributes.
    Param mac: mac address of the endpoint that needs to be updated.
    Param attr_map: a map containing various ise custom attributes.
    Param ep_id: ID for endpoint that needs to be updated.
    Param active_instance: The primary/active ISE instance.
    """
    attribute_names = ""
    attribute_values = ""
    for key in attr_map:
        attribute_names += key + ","
        attribute_values += str(attr_map[key]) + ","
    attribute_names = attribute_names[:-1]
    attribute_values = attribute_values[:-1]

    resp = demisto.executeCommand(
        "cisco-ise-update-endpoint-custom-attribute",
        {
            "id": ep_id,
            "macAddress": mac,
            "attributeName": attribute_names,
            "attributeValue": attribute_values,
            "using": active_instance,
        },
    )
    if isError(resp[0]):
        err_msg = f'Error, failed to update custom attributes for endpoint {id} - {resp[0].get("Contents")}'
        raise Exception(err_msg)


def create_new_ep(mac, attr_map, active_instance):
    """
    Create a new endpoint with the given params
    Param mac: mac address of the endpoint that needs to be created.
    Param attr_map: a map containing various ise custom attributes.
    Param active_instance: The primary/active ISE instance.
    """
    resp = demisto.executeCommand(
        "cisco-ise-create-endpoint", {"mac_address": mac, "attributes_map": attr_map, "using": active_instance}
    )
    if isError(resp[0]):
        err_msg = f'Failed to create new Endpoint {mac} - {resp[0].get("Contents")}'
        raise Exception(err_msg)


def create_or_update_ep(mac, attr_map):
    """
    Check if an enpoint exists in ISE, if not create one with the custom attributes
    otherwise update it. If at any point the connection goes down or we get a 401 -
    unautherized access we will attempt to get the new active instance.
    Params mac: Mac adress of the endpoint.
    attr_map: Custom attributes for the endpoint.
    """

    global CISCO_ISE_ACTIVE_INSTANCE
    global GET_EP_ID_CMD

    cmd_mac_syntax_map = {"cisco-ise-get-endpoint-id-by-name": "mac_address", "cisco-ise-get-endpoint-id": "macAddress"}

    # Check if this mac address (endpoint) is present in ISE by attempting to get its ID
    resp = demisto.executeCommand(GET_EP_ID_CMD, {cmd_mac_syntax_map[GET_EP_ID_CMD]: mac, "using": CISCO_ISE_ACTIVE_INSTANCE})

    if isError(resp[0]):
        err_msg = extract_ise_api_error(resp[0].get("Contents"))

        # 404 Not Found or empty results, we need to create a new EP
        if err_msg == "404" or err_msg == "list index out of range":
            create_new_ep(mac, attr_map, CISCO_ISE_ACTIVE_INSTANCE)

        # 405 - Method not allowed means we need to switch to an old filter based API
        elif err_msg == "405":
            GET_EP_ID_CMD = "cisco-ise-get-endpoint-id"

        else:
            raise Exception(resp[0].get("Contents"))
    else:
        ep_id = resp[0]["EntryContext"]["Endpoint(val.ID === obj.ID)"]["ID"]
        update_existing_endpoint(mac, attr_map, ep_id, CISCO_ISE_ACTIVE_INSTANCE)


def send_panw_iot_devices_to_send_to_cisco_ise(device_list):
    """
    For given device lists consisting of custom attributes, create or update
    endpoints in Cisco ISE.
    Param device_list: a list of devices and their custom attributes.
    """
    count = 0
    for device in device_list:
        mac = device["mac"]
        attr_map = device["zb_attributes"]
        create_or_update_ep(mac, attr_map)
        count += 1

    return f"Successfully exported {count} devices to Cisco ISE"


def main():
    device_list = demisto.args().get("device_maps")
    status_msg = None
    try:
        status_msg = send_panw_iot_devices_to_send_to_cisco_ise(device_list)
    except Exception as ex:
        send_status_to_panw_iot_cloud("error", str(ex))
        return_error(str(ex))

    send_status_to_panw_iot_cloud("success", status_msg)
    return_results(
        CommandResults(readable_output=status_msg, outputs_prefix="PaloAltoIoTIntegrationBase.Status", outputs=status_msg)
    )


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

README

This script takes PANW IoT cloud devices as input and exports them as endpoints with custom attributes in Cisco ISE.

Permissions


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 PANW IoT 3rd Party Integration, Cisco ISE
Cortex XSOAR Version 6.0.0

Used In


This script is used in the following playbooks and scripts.

  • Incremental Export to SIEM - PANW IoT 3rd Party Integration

Dependencies


This script uses the following commands and scripts.

  • cisco-ise-get-endpoint-id
  • cisco-ise-get-endpoint-id-by-name
  • cisco-ise-create-endpoint
  • cisco-ise-update-endpoint-custom-attribute

Inputs


Argument Name Description
device_maps List of device maps from PANW IoT cloud.
active_ise_instance Name of the Active Cisco ISE instance.
panw_iot_3rd_party_instance Name of the configured PANW Iot 3rd Party instance.

Outputs


Path Description Type
PaloAltoIoTIntegrationBase.Status Total count of devices updated or created on ISE unknown