MobileIronCLOUD

MobileIron Cloud Integration.

Endpoint · MobileIron-UEM

Details

IDMobileIronCLOUD
ProviderIvanti
CategoryEndpoint
From Version6.0.0
Docker Imagedemisto/python3:3.12.13.10116658
Supported ModulesAgentix XSIAM

README

MobileIron CLOUD Integration

MobileIron Cloud - Getting Started

  1. Log in to the MobileIron Cloud Admin console.
  2. Open the users section.
  3. Click the create user button and select the option to create a new API user. It is recommended to create a new user for the Cortex XSOAR integration specifically and not reuse
    an existing one.
  4. Fill in all the required details (i.e., use core-api-user as the username) and make sure you enter a strong password.
  5. When setting up the Cortex XSOAR integration, use the auto-generated email address as the username and the password you
    defined as the MobileIron tenant credentials.
  6. Click the Test button and ensure the connection can be established.

Refer to the API documentation at the MobileIron community for more details on setting up the API user.

MobileIron Cloud - Spaces

If you are dividing the devices into different spaces, it is important to make sure the integration
points to the correct Partition ID (Device Space ID).

You should leave this value blank if you are not using spaces or if you want the integration to automatically resolve the
default space ID.

Setting up pre-processing rules

If you are using the fetch incidents option, we recommend to set-up a pre-processing rule in order
to filter out any duplicates that might show up as part of the command.

  • In the Cortex XSOAR admin go to Settings -> Integrations -> Pre-Processing Rules
  • In Step 1 add a rule for Type equals MobileIron Cloud Device Incident.
  • In Step 2 select Drop and Update.
  • In Step 3 select Link to oldest incident created within the last 15 days and check the checkbox next to
    Search closed incidents .
  • Add an AND statement and enter MobileIron Device ID of existing incident is identical to the one of the incoming incident.
  • Save the rule.

Here is an example image of the rule

Pre-Processing Rules Example

Configure MobileIronCLOUD on Cortex XSOAR

  1. Navigate to Settings > Integrations > Servers & Services.
  2. Search for MobileIronCLOUD.
  3. Click Add instance to create and configure a new integration instance.

    Parameter Description Required
    url Server URL (i.e., https://eu1.mobileiron.com ) True
    credentials User Name True
    incidentType Incident type False
    partition_id Partition ID (leave empty to resolve default) False
    insecure Trust any certificate (not secure) False
    proxy Use system proxy settings False
    fetch_interval Fetch Interval (in minutes) True
    max_fetch Maximum number of incidents per fetch False
    isFetch Fetch incidents False
  4. Click Test to validate the URLs, token, and connection.

Commands

You can execute these commands from the Cortex XSOAR CLI, as part of an automation, or in a playbook.
After you successfully execute a command, a DBot message appears in the War Room with the command details.

mobileiron-cloud-get-devices-data


Gets all the devices based on a particular filter query. The command might execute multiple API calls depending on the amount of devices that would be returned.

Base Command

mobileiron-cloud-get-devices-data

Input

Argument Name Description Required
query Filter query for fetching the device data. Default is registrationState=ACTIVE. Optional
max_fetch The maximum number of items returned in the list. Optional

Context Output

Path Type Description
MobileIronCloud.Device.id Number ID of the device that is fetched.
MobileIronCloud.Device.guid String GUID of the device that is fetched.
MobileIronCloud.Device.deviceModel String Model of the device that is fetched.
MobileIronCloud.Device.deviceName String Name of the device that is fetched.
MobileIronCloud.Device.platformType String Platform type of the device that is fetched.
MobileIronCloud.Device.platformVersion String Platform version of the device that is fetched.
MobileIronCloud.Device.osBuildVersion String Operating system build version of the device that is fetched.
MobileIronCloud.Device.lastCheckin Date Last check in time of the device that is fetched.
MobileIronCloud.Device.registrationState String Registration state of the device that is fetched.
MobileIronCloud.Device.displayName String Display name of the device that is fetched.
MobileIronCloud.Device.firstName String First name of the device that is fetched.
MobileIronCloud.Device.lastName String Last name of the device that is fetched.
MobileIronCloud.Device.uid String UID of the device that is fetched.
MobileIronCloud.Device.emailAddress String Email address of the device that is fetched.
MobileIronCloud.Device.manufacturer String Manufacturer of the device that is fetched.
MobileIronCloud.Device.imei Unknown International Mobile Equipment Identity (IMEI) of the device that is fetched.
MobileIronCloud.Device.imei2 Unknown International Mobile Equipment Identity 2 (IME2) of the device that is fetched.
MobileIronCloud.Device.imsi String International Mobile Subscriber Identity (IMSI) of the device that is fetched.
MobileIronCloud.Device.wifiMacAddress String WiFi MAC address of the device that is fetched.
MobileIronCloud.Device.serialNumber Unknown Serial number of the device that is fetched.
MobileIronCloud.Device.altSerialNumber Unknown Alternative serial number of the device that is fetched.
MobileIronCloud.Device.ownershipType String Ownership type of the device that is fetched.
MobileIronCloud.Device.complianceState Boolean Compliance state of the device that is fetched.
MobileIronCloud.Device.roaming Boolean Roaming status of the device that is fetched.
MobileIronCloud.Device.supervised Unknown Device supervised.
MobileIronCloud.Device.udid String UDID of the device that is fetched.
MobileIronCloud.Device.policyViolationCount Number Policy violation count of the device that is fetched.
MobileIronCloud.Device.lastRegistrationTime Date Last registration time of the device that is fetched.
MobileIronCloud.Device.quarantined Boolean Whether the device is quarantined.
MobileIronCloud.Device.jailbroken Boolean Whether the device is jailbroken.

Command Example


#### Context Example

```json
{
  "MobileIronCloud": {
    "Device": [
      {
        "id": 123,
        "guid": "",
        "deviceModel": "VirtualBox",
        "deviceName": "DESKTOP-B76IV6U",
        "platformType": "WINDOWS_PHONE",
        "platformVersion": "10.0",
        "osBuildVersion": "",
        "lastCheckin": 1596026443798,
        "registrationState": "ACTIVE",
        "displayName": "Windows User",
        "firstName": "Windows",
        "lastName": "User",
        "uid": "userid",
        "emailAddress": "email",
        "manufacturer": "GmbH",
        "imei": null,
        "imei2": null,
        "imsi": "Not Present",
        "wifiMacAddress": "",
        "serialNumber": null,
        "altSerialNumber": null,
        "ownershipType": "UNKNOWN",
        "complianceState": false,
        "roaming": false,
        "supervised": null,
        "udid": "UIDVALUE",
        "clientLastCheckin": null,
        "prettyModel": "VirtualBox",
        "policyViolationCount": 1,
        "lastRegistrationTime": 1596022502880,
        "quarantined": false,
        "jailbroken": false,
        "windowsDeviceType": "WINDOWS_DESKTOP",
        "entityName": "DESKTOP-B76IV6U"
      }
    ]
  }
}

mobileiron-cloud-get-device-by-mac


Gets a single device matching the provided mac address.

Base Command

mobileiron-cloud-get-device-by-mac

Input

Argument Name Description Required
device_mac THe MAC address of the device to fetch. Required

Context Output

Path Type Description
MobileIronCloud.Device.id Number The ID of the device that is fetched.
MobileIronCloud.Device.guid String GUID of the device that is fetched.
MobileIronCloud.Device.deviceModel String Model of the device that is fetched.
MobileIronCloud.Device.deviceName String Name of the device that is fetched.
MobileIronCloud.Device.platformType String Platform type of the device that is fetched.
MobileIronCloud.Device.platformVersion String Platform version of the device that is fetched.
MobileIronCloud.Device.osBuildVersion String Operating system build version of the device that is fetched.
MobileIronCloud.Device.lastCheckin Date Last check in time of the device that is fetched.
MobileIronCloud.Device.registrationState String Registration state of the device that is fetched.
MobileIronCloud.Device.displayName String Display name of the device that is fetched.
MobileIronCloud.Device.firstName String First name of the device that is fetched.
MobileIronCloud.Device.lastName String Last name of the device that is fetched.
MobileIronCloud.Device.uid String UID of the device that is fetched.
MobileIronCloud.Device.emailAddress String Email address of the device that is fetched.
MobileIronCloud.Device.manufacturer String Manufacturer of the device that is fetched.
MobileIronCloud.Device.imei Unknown International Mobile Equipment Identity (IMEI) of the device that is fetched.
MobileIronCloud.Device.imei2 Unknown International Mobile Equipment Identity 2 (IME2) of the device that is fetched.
MobileIronCloud.Device.imsi String International mobile subscriber identity (IMSI) of the device that is fetched.
MobileIronCloud.Device.wifiMacAddress String WiFi MAC address of the device that is fetched.
MobileIronCloud.Device.serialNumber Unknown Serial number of the device that is fetched.
MobileIronCloud.Device.altSerialNumber Unknown Alternative serial number of the device that is fetched.
MobileIronCloud.Device.ownershipType String Ownership type of the device that is fetched.
MobileIronCloud.Device.complianceState Boolean Compliance state of the device that is fetched.
MobileIronCloud.Device.roaming Boolean Roaming status of the device that is fetched.
MobileIronCloud.Device.supervised Unknown Device Supervised
MobileIronCloud.Device.udid String Device UDID of the device that is fetched.
MobileIronCloud.Device.policyViolationCount Number Policy violation count of the device that is fetched.
MobileIronCloud.Device.lastRegistrationTime Date Last registration time of the device that is fetched.
MobileIronCloud.Device.quarantined Boolean Whether the device is quarantined.
MobileIronCloud.Device.jailbroken Boolean Whether the device is jailbroken.

Command Example

!mobileiron-cloud-get-device-by-mac device_mac=MAC_HERE

Context Example

{
  "MobileIronCloud": {
    "Device": {
      "id": 123,
      "guid": "",
      "deviceModel": "VirtualBox",
      "deviceName": "DESKTOP-B76IV6U",
      "platformType": "WINDOWS_PHONE",
      "platformVersion": "10.0",
      "osBuildVersion": "",
      "lastCheckin": 1596026443798,
      "registrationState": "ACTIVE",
      "displayName": "Windows User",
      "firstName": "Windows",
      "lastName": "User",
      "uid": "userid",
      "emailAddress": "email",
      "manufacturer": "GmbH",
      "imei": null,
      "imei2": null,
      "imsi": "Not Present",
      "wifiMacAddress": "",
      "serialNumber": null,
      "altSerialNumber": null,
      "ownershipType": "UNKNOWN",
      "complianceState": false,
      "roaming": false,
      "supervised": null,
      "udid": "UIDVALUE",
      "clientLastCheckin": null,
      "prettyModel": "VirtualBox",
      "policyViolationCount": 1,
      "lastRegistrationTime": 1596022502880,
      "quarantined": false,
      "jailbroken": false,
      "windowsDeviceType": "WINDOWS_DESKTOP",
      "entityName": "DESKTOP-B76IV6U"
    }
  }
}

mobileiron-cloud-get-device-by-serial


Gets a single device matching the provided value for the device serial number.

Base Command

mobileiron-cloud-get-device-by-serial

Input

Argument Name Description Required
device_serial Serial number of the device to fetch. Optional

Context Output

Path Type Description
MobileIronCloud.Device.id Number The ID of the device that is fetched.
MobileIronCloud.Device.guid String GUID of the device that is fetched.
MobileIronCloud.Device.deviceModel String Model of the device that is fetched.
MobileIronCloud.Device.deviceName String Name of the device that is fetched.
MobileIronCloud.Device.platformType String Platform type of the device that is fetched.
MobileIronCloud.Device.platformVersion String Platform version of the device that is fetched.
MobileIronCloud.Device.osBuildVersion String Operating system build version of the device that is fetched.
MobileIronCloud.Device.lastCheckin Date Last check in time of the device that is fetched.
MobileIronCloud.Device.registrationState String Registration state of the device that is fetched.
MobileIronCloud.Device.displayName String Display name of the device that is fetched.
MobileIronCloud.Device.firstName String First name of the device that is fetched.
MobileIronCloud.Device.lastName String Last name of the device that is fetched.
MobileIronCloud.Device.uid String UID of the device that is fetched.
MobileIronCloud.Device.emailAddress String Email address of the device that is fetched.
MobileIronCloud.Device.manufacturer String Manufacturer of the device that is fetched.
MobileIronCloud.Device.imei Unknown International Mobile Equipment Identity (IMEI) of the device that is fetched.
MobileIronCloud.Device.imei2 Unknown International Mobile Equipment Identity 2 (IME2) of the device that is fetched.
MobileIronCloud.Device.imsi String International mobile subscriber identity (IMSI) of the device that is fetched.
MobileIronCloud.Device.wifiMacAddress String WiFi MAC address of the device that is fetched.
MobileIronCloud.Device.serialNumber Unknown Serial number of the device that is fetched.
MobileIronCloud.Device.altSerialNumber Unknown Alternative serial number of the device that is fetched.
MobileIronCloud.Device.ownershipType String Ownership type of the device that is fetched.
MobileIronCloud.Device.complianceState Boolean Compliance state of the device that is fetched.
MobileIronCloud.Device.roaming Boolean Roaming status of the device that is fetched.
MobileIronCloud.Device.supervised Unknown Device Supervised
MobileIronCloud.Device.udid String Device UDID of the device that is fetched.
MobileIronCloud.Device.policyViolationCount Number Policy violation count of the device that is fetched.
MobileIronCloud.Device.lastRegistrationTime Date Last registration time of the device that is fetched.
MobileIronCloud.Device.quarantined Boolean Whether the device is quarantined.
MobileIronCloud.Device.jailbroken Boolean Whether the device is jailbroken.

Command Example

!mobileiron-cloud-get-device-by-serial device_serial=SERIAL_HERE

Context Example

{
  "MobileIronCloud": {
    "Device": {
      "id": 123,
      "guid": "",
      "deviceModel": "VirtualBox",
      "deviceName": "DESKTOP-B76IV6U",
      "platformType": "WINDOWS_PHONE",
      "platformVersion": "10.0",
      "osBuildVersion": "",
      "lastCheckin": 1596026443798,
      "registrationState": "ACTIVE",
      "displayName": "Windows User",
      "firstName": "Windows",
      "lastName": "User",
      "uid": "userid",
      "emailAddress": "email",
      "manufacturer": "GmbH",
      "imei": null,
      "imei2": null,
      "imsi": "Not Present",
      "wifiMacAddress": "",
      "serialNumber": null,
      "altSerialNumber": null,
      "ownershipType": "UNKNOWN",
      "complianceState": false,
      "roaming": false,
      "supervised": null,
      "udid": "UIDVALUE",
      "clientLastCheckin": null,
      "prettyModel": "VirtualBox",
      "policyViolationCount": 1,
      "lastRegistrationTime": 1596022502880,
      "quarantined": false,
      "jailbroken": false,
      "windowsDeviceType": "WINDOWS_DESKTOP",
      "entityName": "DESKTOP-B76IV6U"
    }
  }
}

mobileiron-cloud-unlock-device


Sends an unlock action to the device.

Base Command

mobileiron-cloud-unlock-device

Input

Argument Name Description Required
device_id The ID of the MobileIron device to fetch. Optional

Command Example

!mobileiron-cloud-unlock-device device_id=1100646

Human Readable Output

Action was performed successfully

mobileiron-cloud-retire-device


Sends a retire action to the device.

Base Command

mobileiron-cloud-retire-device

Input

Argument Name Description Required
device_id The ID of the MobileIron device to fetch. Optional

Human Readable Output

Action was performed successfully

mobileiron-cloud-wipe-device


Sends a wipe action to the device. This is a potentially destructive action as it will completely wipe the device.

Base Command

mobileiron-cloud-wipe-device

Input

Argument Name Description Required
device_id The ID of the MobileIron device to fetch. Optional

Human Readable Output

Action was performed successfully

mobileiron-cloud-force-check-in


Forces a check in to the particular device based on the device ID.

Base Command

mobileiron-cloud-force-check-in

Input

Argument Name Description Required
device_id The ID of the MobileIron device to fetch. Optional

Human Readable Output

Action was performed successfully

mobileiron-cloud-send-message


Sends a message to the device.

Base Command

mobileiron-cloud-send-message

Input

Argument Name Description Required
device_id The ID of the MobileIron device to fetch. Optional
message_type The type of notification to send. Possible values are: email, push. Default is push. Required
subject The subject of the email. (Only used if an email should be sent). Optional
message The message to be sent. Required

Human Readable Output

Action was performed successfully

mobileiron-cloud-get-device-by-id


Returns the data for a particular device based on the device ID.

Base Command

mobileiron-cloud-get-device-by-id

Input

Argument Name Description Required
device_id The ID of the MobileIron device to fetch. Required

Context Output

Path Type Description
MobileIronCloud.Device.id Number The ID of the device that is fetched.
MobileIronCloud.Device.guid String GUID of the device that is fetched.
MobileIronCloud.Device.deviceModel String Model of the device that is fetched.
MobileIronCloud.Device.deviceName String Name of the device that is fetched.
MobileIronCloud.Device.platformType String Platform type of the device that is fetched.
MobileIronCloud.Device.platformVersion String Platform version of the device that is fetched.
MobileIronCloud.Device.osBuildVersion String Operating system build version of the device that is fetched.
MobileIronCloud.Device.lastCheckin Date Last check in time of the device that is fetched.
MobileIronCloud.Device.registrationState String Registration state of the device that is fetched.
MobileIronCloud.Device.displayName String Display name of the device that is fetched.
MobileIronCloud.Device.firstName String First name of the device that is fetched.
MobileIronCloud.Device.lastName String Last name of the device that is fetched.
MobileIronCloud.Device.uid String UID of the device that is fetched.
MobileIronCloud.Device.emailAddress String Email address of the device that is fetched.
MobileIronCloud.Device.manufacturer String Manufacturer of the device that is fetched.
MobileIronCloud.Device.imei Unknown International Mobile Equipment Identity (IMEI) of the device that is fetched.
MobileIronCloud.Device.imei2 Unknown International Mobile Equipment Identity 2 (IME2) of the device that is fetched.
MobileIronCloud.Device.imsi String International mobile subscriber identity (IMSI) of the device that is fetched.
MobileIronCloud.Device.wifiMacAddress String WiFi MAC address of the device that is fetched.
MobileIronCloud.Device.serialNumber Unknown Serial number of the device that is fetched.
MobileIronCloud.Device.altSerialNumber Unknown Alternative serial number of the device that is fetched.
MobileIronCloud.Device.ownershipType String Ownership type of the device that is fetched.
MobileIronCloud.Device.complianceState Boolean Compliance state of the device that is fetched.
MobileIronCloud.Device.roaming Boolean Roaming status of the device that is fetched.
MobileIronCloud.Device.supervised Unknown Device Supervised
MobileIronCloud.Device.udid String Device UDID of the device that is fetched.
MobileIronCloud.Device.policyViolationCount Number Policy violation count of the device that is fetched.
MobileIronCloud.Device.lastRegistrationTime Date Last registration time of the device that is fetched.
MobileIronCloud.Device.quarantined Boolean Whether the device is quarantined.
MobileIronCloud.Device.jailbroken Boolean Whether the device is jailbroken.

Command Example

!mobileiron-cloud-get-device-by-id device_id=1100646

Context Example

{
  "MobileIronCloud": {
    "Device": {
      "id": 123,
      "guid": "",
      "deviceModel": "VirtualBox",
      "deviceName": "DESKTOP-B76IV6U",
      "platformType": "WINDOWS_PHONE",
      "platformVersion": "10.0",
      "osBuildVersion": "",
      "lastCheckin": 1596026443798,
      "registrationState": "ACTIVE",
      "displayName": "Windows User",
      "firstName": "Windows",
      "lastName": "User",
      "uid": "userid",
      "emailAddress": "email",
      "manufacturer": "GmbH",
      "imei": null,
      "imei2": null,
      "imsi": "Not Present",
      "wifiMacAddress": "",
      "serialNumber": null,
      "altSerialNumber": null,
      "ownershipType": "UNKNOWN",
      "complianceState": false,
      "roaming": false,
      "supervised": null,
      "udid": "UIDVALUE",
      "clientLastCheckin": null,
      "prettyModel": "VirtualBox",
      "policyViolationCount": 1,
      "lastRegistrationTime": 1596022502880,
      "quarantined": false,
      "jailbroken": false,
      "windowsDeviceType": "WINDOWS_DESKTOP",
      "entityName": "DESKTOP-B76IV6U"
    }
  }
}

Configuration parameters

  • isFetch — Fetch incidents
  • incidentType — Incident type
  • incidentFetchInterval — Incidents Fetch Interval
  • url — Server URL (i.e., https://eu1.mobileiron.com ) (required)
  • credentials — User Name (required)
  • partition_id — Partition ID (leave empty to resolve default)
  • max_fetch — Maximum number of incidents per fetch
  • insecure — Trust any certificate (not secure)
  • proxy — Use system proxy settings

Commands (9)

  • mobileiron-cloud-force-check-in

    Forces a check in to the particular device based on the device ID.

  • mobileiron-cloud-get-device-by-id

    Returns the data for a particular device based on the device id.

  • mobileiron-cloud-get-device-by-mac

    Gets a single device matching the provided MAC address.

  • mobileiron-cloud-get-device-by-serial

    Gets a single device matching the provided value for the device serial number.

  • mobileiron-cloud-get-devices-data

    Gets all the devices based on a particular filter query. The command might execute multiple API calls depending on the amount of devices that are returned.

  • mobileiron-cloud-retire-device

    Sends a retire action to the device.

  • mobileiron-cloud-send-message

    Sends a message to the device.

  • mobileiron-cloud-unlock-device

    Sends an unlock action to the device.

  • mobileiron-cloud-wipe-device

    Sends a wipe action to the device. This is a potentially destructive action as it will completely wipe the device.

from typing import Any

import urllib3

# Disable insecure warnings
from CommonServerPython import *

urllib3.disable_warnings()

"""CONSTANTS"""

FETCH_INCIDENTS_QUERY = "registrationState=ACTIVE and (quarantined=true or jailbroken=true or complianceState=false)"

SEVERITY_LOW = 1
SEVERITY_MEDIUM = 2
SEVERITY_HIGH = 3
SEVERITY_CRITICAL = 4


class MobileIronCloudClient(BaseClient):
    """
    MobileIronCloudClient class to interact with the MobileIron Cloud Service API
    """

    def get_device_by_id(self, device_id: str, partition_id: str = None) -> dict[str, Any]:
        """
        Gets a single device by id
        """
        response = self._http_request(
            method="GET", url_suffix=f"/api/v1/device/{device_id}", params={"dmPartitionId": partition_id}
        )
        return response["result"]

    def get_device_data_page(self, start: int = 0, rows: int = 50, query: str = None, partition_id: str = None) -> dict:
        """
        Gets all the pages of device data from MobileIron Cloud
        """
        return self._http_request(
            method="GET",
            url_suffix="/api/v1/device",
            params={"dmPartitionId": partition_id, "fq": query, "rows": rows, "start": start},
        )

    def get_devices_data(self, partition_id: str, query: str = None, max_fetch: int = None) -> list[Any]:
        """
        Gets the Devices Data from MobileIron Cloud

        :type query: ``str``
        :param query: Conditions in the CLoud API Call

        :type partition_id: ``str``
        :param partition_id: Space ID, usually the global space id is sufficient

        :type max_fetch: ``int``
        :param max_fetch: Cap on how many devices should be fetched from the API

        :return: list containing all device info as returned from the API
        :rtype: ``List``
        """

        if not partition_id:
            raise ValueError("partition_id not specified")

        has_more = True
        results = []
        rows = 50
        start = 0
        while has_more:
            response = self.get_device_data_page(rows=rows, start=start, query=query, partition_id=partition_id)
            total_count = response["result"]["totalCount"]
            start += rows
            results += response["result"]["searchResults"]
            has_more = len(results) < total_count
            if max_fetch and len(results) >= max_fetch:
                return results[:max_fetch]

        return results

    def execute_device_action(self, action: str, device_id: str) -> dict[str, Any]:
        """Execute actions to MobileIron Cloud based on the conditions.

        :type action: ``str``
        :param action: Action String based on the action to be performed over MobileIron Cloud.
        :type device_id: ``str``
        :param device_id: DeviceID on which the actions should be performed.

        :return: dict containing the results as returned from the API
        :rtype: ``Dict[str, Any]``
        """
        if not device_id:
            raise ValueError("device_id not specified")

        data = {"ids": device_id}
        return self._http_request(method="PUT", url_suffix=f"/api/v1/device/{action}", data=data)

    def send_message(
        self, device_id: str, partition_id: str, message: str, message_type: str = None, subject: str = None
    ) -> dict[str, Any]:
        """Send an email or/and a push message to the user of the specific device

        :type message_type: ``str``
        :param message_type: only options email or push are allowed

        :type subject: ``str``
        :param subject: Subject of the email message.

        :type message: ``str``
        :param message: Message to the user. In the case of email, this is the body,
        in case of push this is the complete message

        :type partition_id: ``str``
        :param partition_id: Partition ID of the tenant that contains the device.

        :type device_id: ``str``
        :param device_id: DeviceID on which the actions should be performed.

        :return: dict containing the results as returned from the API
        :rtype: ``Dict[str, Any]``
        """
        if not message:
            raise ValueError("message not specified")

        if message_type not in ["email", "push"]:
            raise ValueError("message_type not valid, choose between 'email' or 'push'")

        if not partition_id:
            raise ValueError("partition_id not specified")

        should_send_mail = message_type == "email"
        data = {
            "sendPushNotification": not should_send_mail,
            "sendEmail": should_send_mail,
            "emailSubject": subject,
            "pushNotificationMessage": message.replace(" ", "+"),
            "emailBody": message,
            "dmPartitionId": partition_id,
            "deviceIds": device_id,
        }
        return self._http_request(method="PUT", url_suffix="/api/v1/device/message", data=data)

    def get_tenant_partitions(self):
        """
        An API call used to fetch all the partitions within the tenant.
        Usually of importance is the defaultPartition.

        :return: response containing a list of partition information
        """

        response = self._http_request(method="GET", url_suffix="/api/v1/tenant/partition/device")
        return response["result"]["searchResults"]


"""HELPER FUNCTIONS"""


def validate_action_response(response):
    if response["errors"] or response["result"] != 1:
        raise ValueError(f"Failed to perform the action on the device. Got: {response}")


def get_partition_id(client) -> str:
    params = demisto.params()
    id_from_params = params.get("partition_id")
    if id_from_params:
        return id_from_params

    integration_context = demisto.getIntegrationContext()

    credentials = params.get("credentials")
    username = credentials.get("identifier")
    if integration_context and integration_context.get("for_user") == username:
        return integration_context.get("default_partition_id")

    spaces = client.get_tenant_partitions()
    space = next(item for item in spaces if item["defaultPartition"])
    api_partition_id = str(space["id"])

    demisto.setIntegrationContext({"for_user": username, "default_partition_id": api_partition_id})

    return api_partition_id


def resolve_device_incident_severity(device: dict[str, Any]) -> tuple[str, int]:
    """
    Function to find the device severity based on device properties

    :type device: ``Dict[str, Any]``
    :param device:
        a dictionary containing all the device properties

    :return:
        an int value marking the incident severity determined from the device properties

    :rtype: ``int``

    """

    if device.get("jailbroken"):
        return "Jailbroken device", SEVERITY_CRITICAL
    if not device.get("complianceState"):
        message = compose_non_compliance_message(device)
        return message, SEVERITY_HIGH
    if device.get("quarantined"):
        return "Quarantined device", SEVERITY_LOW

    raise ValueError("Unable to determine severity. The device does not contain any fields which indicate an issue")


def compose_non_compliance_message(device):
    base_message = "Non Compliant Device"
    list_of_policies = device["violatedPolicies"]
    if list_of_policies:
        message = ", ".join(list_of_policies)
        return f"{base_message} - {message}"
    return base_message


"""COMMAND FUNCTIONS"""


def execute_device_action_command(client: MobileIronCloudClient, action: str) -> str:
    """
    Runs the specified device action against the mobileiron API for a particular device

    :type client: ``MobileIronCloudClient``
    :param client: MobileIron client to use

    :type action: ``str``
    :param action: Action String based on the action to be performed over MobileIron Cloud.
    Following actions are allowed:
    - retire
    - unlock
    - wipe
    - forceCheckin

    :return:
        A ``CommandResults`` compatible to return ``return_results()``,
        that contains a Post action result
        A Dict of entries also compatible to ``return_results()``

    :rtype: ``CommandResults``
    """

    device_id = demisto.args().get("device_id")
    response = client.execute_device_action(action=action, device_id=device_id)

    validate_action_response(response)

    return "Action was performed successfully"


def execute_send_message_command(client: MobileIronCloudClient) -> str:
    """mobileiron-send-message command: Returns results for a MobileIron PostAction

    :type client: ``MobileIronCloudClient``
    :param client: MobileIron client to use

    :return:
        A ``CommandResults`` compatible to return ``return_results()``,
        that contains a Post action result
        A Dict of entries also compatible to ``return_results()``

    :rtype: ``CommandResults``
    """
    args = demisto.args()
    message_type = args.get("message_type")
    device_id = args.get("device_id")
    partition_id = get_partition_id(client)
    message = args.get("message")
    subject = args.get("subject")

    response = client.send_message(
        device_id=device_id, partition_id=partition_id, message=message, message_type=message_type, subject=subject
    )
    validate_action_response(response)

    return "Message was sent successfully"


def execute_test_module_command(client: MobileIronCloudClient):
    """This definition is for test command to get Ping response from Cloud"""

    response = client.get_tenant_partitions()
    if response:  # noqa: RET503
        return "ok"


def execute_get_device_by_id_command(client: MobileIronCloudClient) -> CommandResults:
    device_id = demisto.args().get("device_id")
    partition_id = get_partition_id(client)
    device = client.get_device_by_id(device_id=device_id, partition_id=partition_id)
    return CommandResults(outputs_prefix="MobileIronCloud.Device", outputs_key_field="id", outputs=device)


def execute_get_devices_data_command(client: MobileIronCloudClient) -> CommandResults:
    """Returns a list of all devices from mobileiron system

    :type client: ``MobileIronCloudClient``
    :param client: MobileIron UEM client to use

    :return:
        A ``CommandResults`` object that is then passed to ``return_results``,
        that contains the device data

    :rtype: ``CommandResults``
    """
    args = demisto.args()
    query = args.get("query")
    max_fetch = args.get("max_fetch")
    max_fetch = int(max_fetch) if max_fetch else None
    partition_id = get_partition_id(client)
    devices = client.get_devices_data(partition_id=partition_id, query=query, max_fetch=max_fetch)
    return CommandResults(outputs_prefix="MobileIronCloud.Device", outputs_key_field="id", outputs=devices)


def execute_get_device_by_field_command(client: MobileIronCloudClient, field_name: str, field_value: str) -> CommandResults:
    """Returns a single device based on the property name matching the provided value

    :type client: ``MobileIronCloudClient``
    :param client: MobileIron UEM client to use

    :type field_name: ``str``
    :param field_name: name of the field to query for

    :type field_value: ``str``
    :param field_value: value of the field to query for

    :return:
        A ``CommandResults`` object that is then passed to ``return_results``,
        that contains the device data

    :rtype: ``CommandResults``
    """
    query = f"{field_name}={field_value}"
    partition_id = get_partition_id(client)
    devices = client.get_devices_data(partition_id=partition_id, query=query)
    device = next(iter(devices), None)
    return CommandResults(outputs_prefix="MobileIronCloud.Device", outputs_key_field="id", outputs=device)


def fetch_incidents(client: MobileIronCloudClient, partition_id: str, incident_type: str, max_fetch: int) -> list[dict[str, Any]]:
    """This function returns incidents after analyzing the response data

    This function has to implement the logic of making sure that incidents are
    fetched based on analyzing the response data.

    :type partition_id: ``str``
    :param partition_id: Partition ID of the tenant that contains the device.

    :type incident_type: ``str``
    :param incident_type: Incident Type to create, configured in the instance settings

    :type max_fetch: ``int``
    :param max_fetch: Cap on how many devices should be fetched from the API

    :type client: ``MobileIronCloudClient``
    :param client: MobileIron client to use

    :return:
        incidents are returned in the form of dict
    """

    incidents = []
    devices = client.get_devices_data(partition_id=partition_id, query=FETCH_INCIDENTS_QUERY, max_fetch=max_fetch)
    for device in devices:
        # Rename keys for device attributes
        message, severity = resolve_device_incident_severity(device)
        incident_name = f"MobileIron Device Alert - {message}"

        incident = {"name": incident_name, "rawJSON": json.dumps(device), "type": incident_type, "severity": severity}

        incidents.append(incident)

    return incidents


def execute_fetch_incidents_command(client):
    params = demisto.params()
    max_fetch = min(int(params.get("max_fetch")), 200)

    partition_id = get_partition_id(client)
    incident_type = params.get("incidentType")
    incidents = fetch_incidents(client=client, partition_id=partition_id, incident_type=incident_type, max_fetch=max_fetch)
    demisto.incidents(incidents)


"""MAIN FUNCTION"""


def main():
    params = demisto.params()
    args = demisto.args()
    credentials = params.get("credentials")
    username = credentials.get("identifier")
    password = credentials.get("password")
    base_url = params.get("url")

    verify_certificate = not params.get("insecure", False)
    proxy = params.get("proxy", False)
    try:
        client = MobileIronCloudClient(base_url=base_url, verify=verify_certificate, auth=(username, password), proxy=proxy)
        command_methods = {
            "test-module": lambda: execute_test_module_command(client),
            "fetch-incidents": lambda: execute_fetch_incidents_command(client),
            "mobileiron-cloud-get-devices-data": lambda: execute_get_devices_data_command(client),
            "mobileiron-cloud-get-device-by-mac": lambda: execute_get_device_by_field_command(
                client, field_name="wifiMacAddress", field_value=args.get("device_mac")
            ),
            "mobileiron-cloud-get-device-by-serial": lambda: execute_get_device_by_field_command(
                client, field_name="serialNumber", field_value=args.get("device_serial")
            ),
            "mobileiron-cloud-get-device-by-id": lambda: execute_get_device_by_id_command(client),
            "mobileiron-cloud-unlock-device": lambda: execute_device_action_command(client, "unlock"),
            "mobileiron-cloud-retire-device": lambda: execute_device_action_command(client, "retire"),
            "mobileiron-cloud-wipe-device": lambda: execute_device_action_command(client, "wipe"),
            "mobileiron-cloud-force-check-in": lambda: execute_device_action_command(client, "forceCheckin"),
            "mobileiron-cloud-send-message": lambda: execute_send_message_command(client),
        }
        command_method = command_methods.get(demisto.command())
        if not command_method:
            raise DemistoException(f"command not recognised - {demisto.command()}")

        result = command_method()
        if result:
            return_results(result)

    except Exception as e:
        demisto.error(traceback.format_exc())  # print the traceback
        return_error(f"Failed to execute {demisto.command()} command.\nError:\n{e!s}")


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