Palo Alto Networks Device Security
Use the Palo Alto Networks Device Security integration to fetch alerts and vulnerabilities, retrieve device details, and resolve security incidents (previously Zingbox).
Network Security · Device Security by Palo Alto Networks
Details
| ID | Palo Alto Networks Device Security |
|---|---|
| Provider | Palo Alto Networks |
| Category | Network Security |
| From Version | 6.10.0 |
| Docker Image | demisto/fastapi:0.125.0.10158186 |
| Supported Modules | Agentix XSIAM |
README
Use the Palo Alto Networks Device Security integration to fetch alerts and vulnerabilities, retrieve device details, and resolve security incidents (previously Zingbox).
Prerequisites
Before configuring the integration, ensure that you have:
- Access to a Strata Cloud Manager (SCM) tenant.
- A valid Tenant Service Group (TSG) ID.
- An OAuth Client ID and Client Secret for a service account with the required permissions.
- A custom role assigned to the service account with the following permissions:
- Devices: Read
- Alerts: Read, Write
- Vulnerabilities: Read, Write
Configure Palo Alto Networks Device Security in Cortex
| Parameter | Description | Required |
|---|---|---|
| TSG ID | True | |
| Client ID | True | |
| Client Secret | True | |
| Trust any certificate (not secure) | False | |
| Use system proxy settings | False | |
| First fetch time | The format must be <number> <time unit>, for example, 12 hours, 7 days, or 2 seconds. | False |
| Maximum number of incidents per fetch | The maximum number of incidents is 100. | False |
| Fetch Device Security Alerts | When selected, the integration fetches Device Security alerts from the Device Security Portal. | False |
| Fetch Device Security Vulnerabilities | When selected, the integration fetches Device Security vulnerabilities from the Device Security Portal. | False |
| Fetch incidents | False | |
| Incidents Fetch Interval | False | |
| The timeout for querying APIs | False | |
| Incident type | False |
Commands
You can execute these commands from the 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.
device-security-get-device
Retrieves a single device’s details using its MAC address.
Base Command
device-security-get-device
Input
| Argument Name | Description | Required |
|---|---|---|
| id | Retrieves the device UID (mac address). | Required |
Context Output
| Path | Type | Description |
|---|---|---|
| PaloAltoNetworksDeviceSecurity.Device | Object | The device details. |
| PaloAltoNetworksDeviceSecurity.Device.hostname | String | The hostname of the device. |
| PaloAltoNetworksDeviceSecurity.Device.ip_address | String | The IP address of the device. |
| PaloAltoNetworksDeviceSecurity.Device.profile_type | String | The device profile type: Non_IoT vs IoT. |
| PaloAltoNetworksDeviceSecurity.Device.profile_vertical | String | The device profile vertical. |
| PaloAltoNetworksDeviceSecurity.Device.category | String | The device category. |
| PaloAltoNetworksDeviceSecurity.Device.profile | String | The device profile. |
| PaloAltoNetworksDeviceSecurity.Device.last_activity | Date | The last activity timestamp of the device. |
| PaloAltoNetworksDeviceSecurity.Device.long_description | String | The long description of the device. |
| PaloAltoNetworksDeviceSecurity.Device.vlan | Number | The device VLAN ID. |
| PaloAltoNetworksDeviceSecurity.Device.site_name | String | The name of the site where the device is located. |
| PaloAltoNetworksDeviceSecurity.Device.risk_score | Number | The device risk score. |
| PaloAltoNetworksDeviceSecurity.Device.risk_level | String | The device risk level: Low, Medium, High, Critical. |
| PaloAltoNetworksDeviceSecurity.Device.subnet | String | The device subnet. |
| PaloAltoNetworksDeviceSecurity.Device.first_seen_date | Date | The first seen date of the device. |
| PaloAltoNetworksDeviceSecurity.Device.confidence_score | Number | The device confidence score. |
| PaloAltoNetworksDeviceSecurity.Device.deviceid | String | The device ID. |
| PaloAltoNetworksDeviceSecurity.Device.location | String | The device location. |
| PaloAltoNetworksDeviceSecurity.Device.vendor | String | The device vendor. |
| PaloAltoNetworksDeviceSecurity.Device.model | String | The device model. |
| PaloAltoNetworksDeviceSecurity.Device.description | String | The device description. |
| PaloAltoNetworksDeviceSecurity.Device.asset_tag | String | The device asset tag (e.g. a sticky label at the bottom of the device). |
| PaloAltoNetworksDeviceSecurity.Device.os_group | String | The device OS group. |
| PaloAltoNetworksDeviceSecurity.Device.Serial_Number | String | The device serial number. |
| PaloAltoNetworksDeviceSecurity.Device.DHCP | String | Whether the device uses DHCP configuration. Can be “Yes” or “No”. |
| PaloAltoNetworksDeviceSecurity.Device.wire_or_wireless | String | Whether the device is wired or wireless. |
| PaloAltoNetworksDeviceSecurity.Device.department | String | The device department. |
| PaloAltoNetworksDeviceSecurity.Device.Switch_Port | Number | The port of the switch this device is connected to. |
| PaloAltoNetworksDeviceSecurity.Device.Switch_Name | String | The name of the switch this device is connected to. |
| PaloAltoNetworksDeviceSecurity.Device.Switch_IP | String | The IP of the switch this device is connected to. |
| PaloAltoNetworksDeviceSecurity.Device.Access_Point_IP | String | The IP of the access point this device is connected to. |
| PaloAltoNetworksDeviceSecurity.Device.Access_Point_Name | String | The name of the access point this device is connected to. |
| PaloAltoNetworksDeviceSecurity.Device.SSID | String | The SSID of the wireless network this device is connected to. |
| PaloAltoNetworksDeviceSecurity.Device.MAC | String | The device MAC address. |
| PaloAltoNetworksDeviceSecurity.Device.display_tags | String | The user tags of the device. |
| PaloAltoNetworksDeviceSecurity.Device.mac_address | String | The device MAC address. |
Command Example
!device-security-get-device id="00:50:56:bf:32:95"
Context Example
{
"PaloAltoNetworksDeviceSecurity.Device": {
"AD_Domain": null,
"wire_or_wireless": null,
"NAC_profile_source": null,
"cmms_end_of_service": null,
"cmms_mission_critical": null,
"Windows_Installed_Software_Version": null,
"internet_access": "Yes",
"mdm_lost_mode_capable": null,
"risk_score": 30,
"cmms_warranty_date": null,
"CMMS_State": null,
"confidence_score_factors": {
"0": {
"name": "Network Behaviors",
"ts": "2026.07.09"
},
"1": {
"name": "Application Behaviors",
"ts": "2026.07.09"
},
"2": {
"name": "Device Attributes",
"ts": "2026.07.09"
}
},
"first_seen_date": "2026-07-02T19:50:02.000Z",
"site_name": "Test Google Map",
"Applications": "",
"vlan": "1",
"childrenDeviceids": null,
"endpoint_protection": "not_protected",
"NetworkLocation": null,
"os_group": null,
"SCCM_Model": null,
"endpoint_protection_vendor": null,
"iccid": null,
"Has_Children": "No",
"number_of_critical_alerts": 0,
"cmms_device_purchase_price": null,
"Windows_GUID": null,
"Windows_Installed_Patches_Source": null,
"os_end_of_support": null,
"Encryption_Cipher": null,
"dnac_location": null,
"Authentication_Method": null,
"SMB": null,
"vendor": "VMware, Inc.",
"os_ver": null,
"mdm_model_identifier": null,
"customAttributes": [
{
"test_jnolan": "testing-adding-device-id"
}
],
"firmwareVer": null,
"profile": "VMware",
"WIFI_Auth_Timestamp": null,
"NAC_Auth_State": null,
"SCCM_Domain": null,
"model": null,
"cmms_equipment_number": null,
"cmms_id": null,
"CMMS_Source": null,
"Total_Scan_Time(min)": "",
"asset_tag": null,
"EAP_Method": null,
"number_of_warning_alerts": 0,
"profile_vertical": "Traditional IT",
"SCCM_Site": null,
"Synced_With_Third-Party": null,
"Disk_Encryption_Status": null,
"Switch_Port": null,
"mdm_supervised": null,
"CMMS_Category": null,
"External_Inventory_Sync_Field": null,
"SCCM_Vendor": null,
"in_use": "",
"Disk_Encryption_Status_Source": null,
"MAC": "00:50:56:bf:32:95",
"SCCM_Serial_Number": null,
"profile_type": "Non_IoT",
"AET": null,
"display_meid": null,
"PHI": "No",
"deviceid": "00:50:56:bf:32:95",
"Access_Point_IP": null,
"cmms_end_of_life": null,
"Network_Segments": "28",
"mdm_vendor": null,
"DHCP": null,
"Status": "Offline",
"AD_Username": null,
"Switch_IP": null,
"department": null,
"hostname": "apt1",
"cmms_device_replacement_cost": null,
"confidence_score_status": "existing",
"risk_level": "Low",
"Serial_Number": null,
"Windows_Installed_Patches": null,
"Access_Point_Name": null,
"Windows_GUID_Source": null,
"location": null,
"NAC_Auth_Info": null,
"number_of_info_alerts": 0,
"Switch_Name": null,
"display_tags": null,
"cmms_owner_id": null,
"mdm_managed": null,
"display_ssid": null,
"cmms_next_service": null,
"Case_Studies": "",
"last_activity": "2026-07-08T23:35:04.707Z",
"Images": "",
"config_source": null,
"is_server": null,
"Tags": "",
"long_description": "",
"parent_mac": null,
"allTags": [],
"NAC_profile": null,
"Time_Synced_With_Third-Party": null,
"Tag": [],
"source": "",
"Source": "Monitored",
"mdm_device_id": null,
"cmms_last_service": null,
"ip_address": "10.0.2.184",
"cmms_secondary_mac_and_ip_addresses": null,
"description": null,
"mdm_lock_status": null,
"confidence_score": 70,
"mdm_firmware_version": null,
"number_of_caution_alerts": 0,
"subnet": "10.0.0.0/12",
"services": null,
"category": "Virtual Machine",
"WIFI_Auth_Status": null,
"os/firmware_version": null
}
}
Human Readable Output
Device Security Device
AD_Domain AD_Username AET Access_Point_IP Access_Point_Name Applications Authentication_Method CMMS_Category CMMS_Source CMMS_State DHCP EAP_Method Encryption_Cipher External_Inventory_Sync_Field MAC NAC_Auth_Info NAC_Auth_State NAC_profile NAC_profile_source NetworkLocation SMB SSID Serial_Number Source Switch_IP Switch_Name Switch_Port Synced_With_Third-Party Time_Synced_With_Third-Party WIFI_Auth_Status WIFI_Auth_Timestamp asset_tag category confidence_score department description deviceid display_tags endpoint_protection endpoint_protection_vendor first_seen_date hostname in_use ip_address is_server last_activity location long_description mac_address model number_of_caution_alerts number_of_critical_alerts number_of_info_alerts number_of_warning_alerts os/firmware_version os_combined os_group parent_mac profile profile_type profile_vertical risk_level risk_score services site_name source subnet vendor vlan wire_or_wireless 00:50:56:bf:32:95 Monitored Virtual Machine 70 00:50:56:bf:32:95 not_protected 2026-07-02T19:50:02.000Z apt1 10.0.2.184 2026-07-08T23:35:04.707Z 00:50:56:bf:32:95 0 0 0 0 VMware Non_IoT Traditional IT Low 30 Test Google Map 10.0.0.0/12 VMware, Inc. 1
device-security-get-device-by-ip
Returns a single device’s details using its IP address.
Base Command
device-security-get-device-by-ip
Input
| Argument Name | Description | Required |
|---|---|---|
| ip | The device IP address. | Required |
Context Output
| Path | Type | Description |
|---|---|---|
| PaloAltoNetworksDeviceSecurity.Device | Object | The device details. |
| PaloAltoNetworksDeviceSecurity.Device.hostname | String | The hostname of the device. |
| PaloAltoNetworksDeviceSecurity.Device.ip_address | String | The IP address of the device. |
| PaloAltoNetworksDeviceSecurity.Device.profile_type | String | The device profile type: Non_IoT vs IoT. |
| PaloAltoNetworksDeviceSecurity.Device.profile_vertical | String | The device profile vertical. |
| PaloAltoNetworksDeviceSecurity.Device.category | String | The device category. |
| PaloAltoNetworksDeviceSecurity.Device.profile | String | The device profile. |
| PaloAltoNetworksDeviceSecurity.Device.last_activity | Date | The last activity timestamp of the device. |
| PaloAltoNetworksDeviceSecurity.Device.long_description | String | The long description of the device. |
| PaloAltoNetworksDeviceSecurity.Device.vlan | Number | The device VLAN ID. |
| PaloAltoNetworksDeviceSecurity.Device.site_name | String | The name of the site where the device is located. |
| PaloAltoNetworksDeviceSecurity.Device.risk_score | Number | The device risk score. |
| PaloAltoNetworksDeviceSecurity.Device.risk_level | String | The device risk level: Low, Medium, High, Critical. |
| PaloAltoNetworksDeviceSecurity.Device.subnet | String | The device subnet. |
| PaloAltoNetworksDeviceSecurity.Device.first_seen_date | Date | The first seen date of the device. |
| PaloAltoNetworksDeviceSecurity.Device.confidence_score | Number | The device confidence score. |
| PaloAltoNetworksDeviceSecurity.Device.deviceid | String | The device ID. |
| PaloAltoNetworksDeviceSecurity.Device.location | String | The device location. |
| PaloAltoNetworksDeviceSecurity.Device.vendor | String | The device vendor. |
| PaloAltoNetworksDeviceSecurity.Device.model | String | The device model. |
| PaloAltoNetworksDeviceSecurity.Device.description | String | The device description. |
| PaloAltoNetworksDeviceSecurity.Device.asset_tag | String | The device asset tag (e.g. a sticky label at the bottom of the device). |
| PaloAltoNetworksDeviceSecurity.Device.os_group | String | The device OS group. |
| PaloAltoNetworksDeviceSecurity.Device.Serial_Number | String | The device serial number. |
| PaloAltoNetworksDeviceSecurity.Device.DHCP | String | Whether the device uses DHCP configuration. Can be “Yes” or “No”. |
| PaloAltoNetworksDeviceSecurity.Device.wire_or_wireless | String | Whether the device is wired or wireless. |
| PaloAltoNetworksDeviceSecurity.Device.department | String | The device department. |
| PaloAltoNetworksDeviceSecurity.Device.Switch_Port | Number | The port of the switch this device is connected to. |
| PaloAltoNetworksDeviceSecurity.Device.Switch_Name | String | The name of the switch this device is connected to. |
| PaloAltoNetworksDeviceSecurity.Device.Switch_IP | String | The IP of the switch this device is connected to. |
| PaloAltoNetworksDeviceSecurity.Device.Access_Point_IP | String | The IP of the access point this device is connected to. |
| PaloAltoNetworksDeviceSecurity.Device.Access_Point_Name | String | The name of the access point this device is connected to. |
| PaloAltoNetworksDeviceSecurity.Device.SSID | String | The SSID of the wireless network this device is connected to. |
| PaloAltoNetworksDeviceSecurity.Device.MAC | String | The device MAC address. |
| PaloAltoNetworksDeviceSecurity.Device.display_tags | String | The user tags of the device. |
| PaloAltoNetworksDeviceSecurity.Device.mac_address | String | The device MAC address. |
Command Example
!device-security-get-device-by-ip ip="10.0.2.184"
Context Example
{
"PaloAltoNetworksDeviceSecurity.Device": [
{
"risk_score": 30,
"first_seen_date": "2026-07-02T19:50:02.000Z",
"site_name": "Test Google Map",
"Applications": "",
"vlan": "1",
"endpoint_protection": "not_protected",
"mac_address": "00:50:56:bf:32:95",
"number_of_critical_alerts": 1,
"vendor": "VMware, Inc.",
"profile": "VMware",
"number_of_warning_alerts": 2,
"profile_vertical": "Traditional IT",
"zone": null,
"in_use": "",
"segmentId": "28",
"MAC": "00:50:56:bf:32:95",
"profile_type": "Non_IoT",
"attr": {
"panwIoTFname_39Cd0UDM8": "",
"panwIoTFname_f_nfikiK3T_source": "ruleBased",
"panwIoTFname_1001": "unknown",
"panwIoTFname_1002": "2",
"panwIoTFname_6_G_6PYPEg_source": "config",
"panwIoTFname_1003": "",
"panwIoTFname_pVeqQm9URJ": "defaultValueEdit7",
"panwIoTFname_vLo9iTCUkB_source": "config",
"panwIoTFname_1004": "testbbbb",
"panwIoTFname_1005": "Unmanaged",
"panwIoTFname_VhpPXcTuF": "mohamed-test-value",
"panwIoTFname_jUXXLtTC7_source": "config",
"panwIoTFname_J-gAZNlwze": "test",
"panwIoTFname_J-gAZNlwze_source": "config",
"panwIoTFname_jUXXLtTC7": "katherine-test-value",
"panwIoTFname_VhpPXcTuF_source": "config",
"panwIoTFname_1005_source": "config",
"panwIoTFname_1004_source": "config",
"panwIoTFname_6_G_6PYPEg": "ff",
"panwIoTFname_vLo9iTCUkB": "abc",
"panwIoTFname_pVeqQm9URJ_source": "config",
"panwIoTFname_1003_source": "config",
"panwIoTFname_1002_source": "config",
"panwIoTFname_1001_source": "config",
"panwIoTFname_f_nfikiK3T": "testing-adding-device-id",
"panwIoTFname_39Cd0UDM8_source": "config"
},
"deviceid": "00:50:56:bf:32:95",
"hostname": "apt1",
"risk_level": "Low",
"number_of_info_alerts": 1,
"last_activity": "2026-07-08T23:35:04.707Z",
"allTags": [],
"source": "",
"ip_address": "10.0.2.184",
"ext_network_date": "2026-07-05T02:22:12.000Z",
"confidence_score": 70,
"number_of_caution_alerts": 0,
"subnet": "10.0.0.0/12",
"category": "Virtual Machine"
}
]
}
Human Readable Output
Device Security Devices
AD_Domain AD_Username AET Access_Point_IP Access_Point_Name Applications Authentication_Method CMMS_Category CMMS_Source CMMS_State DHCP EAP_Method Encryption_Cipher External_Inventory_Sync_Field MAC NAC_Auth_Info NAC_Auth_State NAC_profile NAC_profile_source NetworkLocation SMB SSID Serial_Number Source Switch_IP Switch_Name Switch_Port Synced_With_Third-Party Time_Synced_With_Third-Party WIFI_Auth_Status WIFI_Auth_Timestamp asset_tag category confidence_score department description deviceid display_tags endpoint_protection endpoint_protection_vendor first_seen_date hostname in_use ip_address is_server last_activity location long_description mac_address model number_of_caution_alerts number_of_critical_alerts number_of_info_alerts number_of_warning_alerts os/firmware_version os_combined os_group parent_mac profile profile_type profile_vertical risk_level risk_score services site_name source subnet vendor vlan wire_or_wireless 00:50:56:bf:32:95 Virtual Machine 70 00:50:56:bf:32:95 not_protected 2026-07-02T19:50:02.000Z apt1 10.0.2.184 2026-07-08T23:35:04.707Z 00:50:56:bf:32:95 0 1 1 2 VMware Non_IoT Traditional IT Low 30 Test Google Map 10.0.0.0/12 VMware, Inc. 1
device-security-list-devices
Retrieves a list of devices.
Base Command
device-security-list-devices
Input
| Argument Name | Description | Required |
|---|---|---|
| offset | The offset in the pagination. | Optional |
| limit | The maximum size of the list of the devices. | Optional |
Context Output
| Path | Type | Description |
|---|---|---|
| PaloAltoNetworksDeviceSecurity.DeviceList | List | The list of devices. |
Command Example
!device-security-list-devices offset=0 limit=2
Context Example
{
"PaloAltoNetworksDeviceSecurity.DeviceList":
[{
"firewall": [
{
"applianceid": "012501003437",
"date": "2026-07-03T06:43:01.523Z"
}
],
"display_vlan": null,
"carm_sources_seen_array": [
"iot.bg_connect",
"iot.bg_profiler",
"iot.auto_tag",
"iot.offline_profile",
"iot.ai_confidence_score_breakdown",
"data_quality_metrics"
],
"display_profile_confidence_level": "70_Medium",
"siteid": "43",
"ml_risk_score": 0,
"WireWireless": "wireless",
"ip": "10.47.115.129",
"vendor": "Apple Inc.",
"display_protos": "ssh,ssl,web-browsing",
"last_network_activity": "2026-07-03T06:43:01.523Z",
"profile": "Apple Device",
"firstseen": "2026-07-02T19:46:29.000Z",
"ouiVendor": "Apple, Inc.",
"name": "88:66:5a:1e:a0:3c",
"profile_vertical": "Traditional IT",
"epp_safety": "not_protected",
"MAC_sources_seen_array": [
"iot.hipmatch"
],
"zone": null,
"segmentId": "28",
"MAC": "88:66:5a:1e:a0:3c",
"display_apps": "",
"profile_type": "Non_IoT",
"carm_first_source": "iot.bg_connect",
"attr": {
"panwIoTFname_39Cd0UDM8": "",
"panwIoTFname_f_nfikiK3T_source": "ruleBased",
"panwIoTFname_1001": "Level 4",
"panwIoTFname_1002": "2",
"panwIoTFname_6_G_6PYPEg_source": "config",
"panwIoTFname_1003": "",
"panwIoTFname_pVeqQm9URJ": "defaultValueEdit7",
"panwIoTFname_vLo9iTCUkB_source": "config",
"panwIoTFname_1004": "testbbbb",
"panwIoTFname_1005": "Unmanaged",
"panwIoTFname_VhpPXcTuF": "mohamed-test-value",
"panwIoTFname_jUXXLtTC7_source": "config",
"panwIoTFname_J-gAZNlwze": "test",
"panwIoTFname_J-gAZNlwze_source": "config",
"panwIoTFname_jUXXLtTC7": "katherine-test-value",
"panwIoTFname_VhpPXcTuF_source": "config",
"panwIoTFname_1005_source": "config",
"panwIoTFname_1004_source": "config",
"panwIoTFname_6_G_6PYPEg": "ff",
"panwIoTFname_vLo9iTCUkB": "abc",
"panwIoTFname_pVeqQm9URJ_source": "config",
"panwIoTFname_1003_source": "config",
"panwIoTFname_1002_source": "config",
"panwIoTFname_1001_source": "ruleBased",
"panwIoTFname_f_nfikiK3T": "testing-adding-device-id",
"panwIoTFname_39Cd0UDM8_source": "config"
},
"ml_risk_level": "Low",
"countries": "No",
"subnets": "10.0.0.0/10",
"adv_name": {
"734f1597-dc3a-4be6-bc43-820861090bbf": "Documentation-demo",
"fce32059-a030-4cbe-912b-0e67b39a03af": "Onboarding Device"
},
"foreignAccess": "",
"tags": {
"panwIoTTname_1": "In Scope",
"panwIoTTname_1_source": "ruleBased",
"panwIoTTname_xvLLFTDKR": "test",
"panwIoTTname_xvLLFTDKR_source": "ruleBased"
},
"_id": "6a46c0152dd53a90ec54b3c8",
"source": "",
"id": "88:66:5a:1e:a0:3c",
"ext_network_date": "",
"display_vlan_description": null,
"display_profile_confidence": 70,
"category": "generic",
"latest_device_time": "2026-07-08T07:40:03.462Z"
}]
}
Human Readable Output
Device Security Devices
AD_Domain AD_Username AET Access_Point_IP Access_Point_Name Applications Authentication_Method CMMS_Category CMMS_Source CMMS_State DHCP EAP_Method Encryption_Cipher External_Inventory_Sync_Field MAC NAC_Auth_Info NAC_Auth_State NAC_profile NAC_profile_source NetworkLocation SMB SSID Serial_Number Source Switch_IP Switch_Name Switch_Port Synced_With_Third-Party Time_Synced_With_Third-Party WIFI_Auth_Status WIFI_Auth_Timestamp asset_tag category confidence_score department description deviceid display_tags endpoint_protection endpoint_protection_vendor first_seen_date hostname in_use ip_address is_server last_activity location long_description mac_address model number_of_caution_alerts number_of_critical_alerts number_of_info_alerts number_of_warning_alerts os/firmware_version os_combined os_group parent_mac profile profile_type profile_vertical risk_level risk_score services site_name source subnet vendor vlan wire_or_wireless 88:66:5a:1e:a0:3c generic 70 88:66:5a:1e:a0:3c not_protected 2026-07-02T19:46:29.000Z 88:66:5a:1e:a0:3c 10.47.115.129 2026-07-08T07:40:03.462Z 88:66:5a:1e:a0:3c Apple Device Non_IoT Traditional IT Low 0 10.0.0.0/10 Apple Inc. wireless
device-security-list-alerts
Retrieves a list of device security alerts.
Base Command
device-security-list-alerts
Input
| Argument Name | Description | Required |
|---|---|---|
| start_time | The start time in the format of ISO 8601 in UTC, e.g. 2018-11-06T08:56:41Z. | Optional |
| offset | The offset in the pagination. | Optional |
| limit | The maximum size of the list of the alerts. | Optional |
Context Output
| Path | Type | Description |
|---|---|---|
| PaloAltoNetworksDeviceSecurity.Alerts | List | The list of alerts. |
Command Example
!device-security-list-alerts offset=0 limit=2
Context Example
{
"PaloAltoNetworksDeviceSecurity.Alerts": [
{
"msg": {
"alertType": "action_center",
"id": "JL6JM9RIa",
"status": "publish"
},
"display_profile_confidence_level": "90_High",
"siteid": "43",
"tenantid": "",
"severityNumber": 3,
"profile": "Super Micro Computer",
"name": "Action Center Alert",
"date": "2026-07-09T06:30:03.843Z",
"url": "https://iot45-64662843-csp-sls-09.iot.paloaltonetworks.com/guardian/alert/alert?id=JL6JM9RIa",
"serviceLevel": "",
"deviceid": "3c:ec:ef:fa:e6:3e",
"siteName": "Test Google Map",
"hostname": "ubuntu-server",
"internal_hostname": "ubuntu-server",
"trafficRestricted": true,
"primaryDevice": null,
"resolved": "no",
"reason_history": [],
"display_severity": "high",
"type": "policy_alert",
"id": "6a4f3feb7bb95b150609ad41",
"description": "aaaa",
"severity": "medium",
"zb_ticketid": "alert-JL6JM9RIa",
"category": "IT Server"
}
]
}
Human Readable Output
Device Security Alerts
category date description deviceid hostname id inspectorid internal_hostname msg name profile reason_history resolved serviceLevel severity severityNumber siteid tenantid type zb_ticketid IT Server 2026-07-09T06:30:03.843Z aaaa 3c:ec:ef:fa:e6:3e ubuntu-server 6a4f3feb7bb95b150609ad41 ubuntu-server alertType: action_center; id: JL6JM9RIa; status: publish Action Center Alert Super Micro Computer [] no medium 3 43 policy_alert alert-JL6JM9RIa
device-security-list-vulns
Retrieves a list of device security vulnerabilities.
Base Command
device-security-list-vulns
Input
| Argument Name | Description | Required |
|---|---|---|
| start_time | The start time in ISO 8601 UTC format, for example 2018-11-06T08:56:41Z. | Optional |
| offset | The offset in the pagination. | Optional |
| limit | The maximum size of the list of the vulnerabilities. | Optional |
Context Output
| Path | Type | Description |
|---|---|---|
| PaloAltoNetworksDeviceSecurity.Vulns | List | The list of vulnerabilities. |
Command Example
!device-security-list-vulns offset=0 limit=2
Context Example
{
"PaloAltoNetworksDeviceSecurity.Vulns": [
{
"deviceid": "00:15:5d:94:1c:01",
"cvss_score": 7.8,
"detected_date": [
"2023-10-11T19:15:09.000Z"
],
"device_last_activity": "2026-06-15T05:50:44.677Z",
"ics_cert": null,
"is_sbom": false,
"severity": "Medium",
"source": "trend_micro_vision_one",
"status": "Confirmed",
"zb_ticketid": "vuln-3e396a5f",
"ticketState": "new",
"ticketAssignees": null,
"reason_history": [
{
"evidence_type": "last_detected",
"timestamp": "2023-10-11T19:15:09.000Z",
"evidence": {}
},
{
"evidence_type": "first_detected",
"timestamp": "2023-10-11T19:15:09.000Z",
"evidence": {}
}
],
"remediate_workorder": null,
"remediate_checkbox": null,
"remediate_instruction": null,
"last_detected_date": "2023-10-11T19:15:09.000Z",
"vulnerability_name": "CVE-2023-31096",
"asset_criticality": "Medium",
"name": "DESKTOP-A51IU1U",
"ip": "172.30.72.200",
"profile": "PC-Windows",
"profile_vertical": "Traditional IT",
"display_profile_category": "Personal Computer",
"vendor": "Microsoft Corporation",
"model": null,
"os": "Windows",
"osCombined": "Windows",
"siteid": "43",
"asset_tag": null,
"sn": "4758-5248-5193-6935-8922-7043-79",
"date": "2026-06-15T05:50:44.677Z",
"risk_score": 0,
"risk_level": "Low",
"trafficRestricted": null,
"subnets": "172.16.0.0/12",
"display_profile_confidence_level": "70_Medium",
"display_profile_confidence": 75,
"siteName": "Test Google Map",
"allTags": []
}
]
}
Human Readable Output
Device Security Vulnerabilities
asset_tag date detected_date deviceid display_profile_category ip model name os osCombined profile profile_vertical reason_history remediate_checkbox remediate_instruction remediate_workorder risk_level risk_score siteName siteid sn ticketAssignees ticketState vendor vulnerability_name zb_ticketid 2026-06-15T05:50:44.677Z 2023-10-11T19:15:09.000Z 00:15:5d:94:1c:01 Personal Computer 172.30.72.200 DESKTOP-A51IU1U Windows Windows PC-Windows Traditional IT evidence_type: last_detected; timestamp: 2023-10-11T19:15:09.000Z; evidence: {}; evidence_type: first_detected; timestamp: 2023-10-11T19:15:09.000Z; evidence: {} Low 0 Test Google Map 43 4758-5248-5193-6935-8922-7043-79 new Microsoft Corporation CVE-2023-31096 vuln-3e396a5f
device-security-resolve-alert
Resolves a device security alert.
Base Command
device-security-resolve-alert
Input
| Argument Name | Description | Required |
|---|---|---|
| id | The alert ID. | Required |
| reason | The alert resolution reason. | Optional |
| reason_type | The alert resolution reason type (No Action Needed, Issue Mitigated). Possible values are: No Action Needed, Issue Mitigated. | Optional |
Context Output
There is no context output for this command.
Command Example
!device-security-resolve-alert id="5e73ecb3eff46f80a7cdc57a" reason="test" reason_type="No Action Needed"
Context Example
There is no context example for this command because it does not return context output.
Human Readable Output
Alert 5e73ecb3eff46f80a7cdc57a was resolved successfully
device-security-resolve-vuln
Resolves a device security vulnerability.
Base Command
device-security-resolve-vuln
Input
| Argument Name | Description | Required |
|---|---|---|
| id | The vulnerability ID. | Required |
| full_name | The vulnerability full name. | Required |
| reason | The vulnerability resolution reason. | Optional |
Context Output
There is no context output for this command.
Command Example
!device-security-resolve-vuln id="vuln-b12d4f0a" full_name="CVE-2019-10960" reason="test"
Context Example
There is no context example for this command because it does not return context output.
Human Readable Output
Vulnerability vuln-b12d4f0a was resolved successfully
Configuration parameters
tsg_id— TSG ID (required)client_id— Client ID (required)client_secret— Client Secret (required)insecure— Trust any certificate (not secure)proxy— Use system proxy settingsfirst_fetch— First fetch timemax_fetch— Maximum number of incidents per fetchfetch_alerts— Fetch Device Security Alertsfetch_vulns— Fetch Device Security VulnerabilitiesisFetch— Fetch incidentsincidentFetchInterval— Incidents Fetch Intervalapi_timeout— The timeout for querying APIsincidentType— Incident type
Commands (7)
-
device-security-get-deviceRetrieves a single device's details using its MAC address.
-
device-security-get-device-by-ipReturns a single device's details using its IP address.
-
device-security-list-alertsRetrieves a list of device security alerts.
-
device-security-list-devicesRetrieves a list of devices.
-
device-security-list-vulnsRetrieves a list of device security vulnerabilities.
-
device-security-resolve-alertResolves a device security alert.
-
device-security-resolve-vulnResolves a device security vulnerability.
import json import time import base64 from datetime import UTC, datetime import demistomock as demisto # noqa: F401 import urllib3 from CommonServerPython import * # noqa: F401 from CommonServerUserPython import * # noqa: E402 lgtm [py/polluting-import] from ContentClientApiModule import * # IMPORTS # Disable insecure warnings urllib3.disable_warnings() # CONSTANTS # api list size limit PAGELENGTH = 100 SEEN_IDS_LIMIT = 1000 SEEN_IDS_TRIM_COUNT = 750 class Client(ContentClient): """Client class to interact with the service API This Client implements API calls, and does not contain any XSOAR logic. Should only do requests and return data. """ def __init__( self, base_url: str, first_fetch: str = "-1", max_fetch: int = 10, api_timeout: int = 60, verify: bool = True, proxy: bool = False, ok_codes: tuple = (), headers: dict | None = None, ) -> None: super().__init__(base_url, verify=verify, proxy=proxy, ok_codes=ok_codes, headers=headers) self.api_timeout = api_timeout self.first_fetch = first_fetch self.max_fetch = min(max_fetch, PAGELENGTH) def _http_request(self, **kwargs) -> Any: # type: ignore[override] try: params = kwargs.get("params", {}) headers = kwargs.get("headers") if headers is None: headers = dict(self._headers) if self._headers else {} else: headers = dict(headers) headers.setdefault("User-Agent", "/") kwargs["params"] = params kwargs["headers"] = headers return super()._http_request(**kwargs) except DemistoException as error: error_message = str(error) if "[404]" in error_message: raise DemistoException(f"{error_message}\nResource or endpoint not found.") elif "[403]" in error_message: raise DemistoException( f"{error_message}\nValidate your TSG ID and ensure the Client ID/Client Secret have the required permissions." ) elif "[401]" in error_message: raise DemistoException( f"{error_message}\nUnauthorized request. Validate Client ID and Client Secret, " "and ensure the generated token is valid." ) elif "[429]" in error_message: raise DemistoException( f"{error_message}\nRate limit exceeded. Retry the request later or lower the request frequency." ) elif "[500]" in error_message: raise DemistoException(f"{error_message}\nService temporary error. Retry the request in a few minutes.") else: raise error def get_device(self, device_id: str) -> dict: """ Get a device from Device Security portal by device ID """ return self._http_request(method="GET", url_suffix="/device", params={"deviceid": device_id}, timeout=self.api_timeout) def get_device_by_ip(self, ip: str) -> dict: """ Get a device from Device Security portal by ip """ return self._http_request(method="GET", url_suffix="/device/ip", params={"ip": ip}, timeout=self.api_timeout) def list_alerts(self, stime: str = "-1", offset: int = 0, pagelength: int = 100, sortdirection: str = "asc") -> list[dict]: """ returns alerts inventory list """ data = self._http_request( method="GET", url_suffix="/alert/list", params={ "offset": offset, "pagelength": pagelength, "stime": stime, "type": "policy_alert", "resolved": "no", "sortfield": "date", "sortdirection": sortdirection, }, timeout=self.api_timeout, ) return data["items"] def list_vulns(self, stime: str = "-1", offset: int = 0, pagelength: int = 100) -> list[dict]: """ returns vulnerability instances """ data = self._http_request( method="GET", url_suffix="/vulnerability/list", params={ "offset": offset, "pagelength": pagelength, "stime": stime, "type": "vulnerability", "status": "Confirmed", "groupby": "device", }, timeout=self.api_timeout, ) return data["items"] def list_devices(self, offset: int, pagelength: int) -> list[dict]: """ returns a list of devices """ data = self._http_request( method="GET", full_url=f"{self._base_url.replace('/v1', '/v2')}/device/list", params={ "offset": offset, "pagelength": pagelength, "stime": datetime.fromtimestamp(int(time.time()) - 2592000, tz=UTC).strftime("%Y-%m-%dT%H:%M:%S.%fZ"), "sortdirection": "asc", }, timeout=self.api_timeout, ) return data["devices"] def resolve_alert(self, alert_id: str, reason: str, reason_type: str = "No Action Needed") -> dict: """ Resolve a Device Security alert """ return self._http_request( method="PUT", url_suffix="/alert/update", params={"id": alert_id}, json_data={"resolved": "yes", "reason": reason, "reason_type": [reason_type]}, timeout=self.api_timeout, ) def resolve_vuln(self, vuln_id: str, full_name: str, reason: str) -> dict: """ Resolve a Device Security vulnerability """ return self._http_request( method="PUT", url_suffix="/vulnerability/update", json_data={"action": "mitigate", "full_name": full_name, "reason": reason, "ticketIdList": [vuln_id]}, timeout=self.api_timeout, ) def get_scm_access_token( token_base_url: str, tsg_id: str, client_id: str, client_secret: str, verify_certificate: bool = True, proxy: bool = False ) -> str: try: integration_context = get_integration_context() access_token = integration_context.get("scm_access_token") expires_on = integration_context.get("scm_expires_on") if access_token and expires_on: try: expires_on_dt = datetime.fromisoformat(expires_on.replace("Z", "+00:00")) if expires_on_dt.tzinfo is None: expires_on_dt = expires_on_dt.replace(tzinfo=UTC) if expires_on_dt > datetime.now(tz=UTC): return access_token except ValueError: demisto.debug(f"Failed to parse cached scm_expires_on timestamp: {expires_on}. Requesting a new token.") auth = base64.b64encode(f"{client_id}:{client_secret}".encode()).decode() client = BaseClient( token_base_url, verify=verify_certificate, proxy=proxy, ok_codes=(200, 201, 202, 204), headers={"Authorization": f"Basic {auth}"}, ) token_data = client._http_request( method="POST", url_suffix="/oauth2/access_token", data={ "grant_type": "client_credentials", "scope": f"tsg_id:{tsg_id}", }, ) access_token = token_data.get("access_token") expires_in = token_data.get("expires_in", 0) set_integration_context( { "scm_access_token": access_token, "scm_expires_on": (datetime.now(tz=UTC) + timedelta(seconds=int(expires_in))).isoformat(), } ) return access_token except Exception as e: raise Exception(f"Failed to generate or validate SCM access token: {str(e)}") def get_scm_ui_base_url() -> str: """Return SCM UI base URL.""" return "https://stratacloudmanager.paloaltonetworks.com" def get_scm_alert_url(alert_id: str) -> str: """Build the SCM alert details URL. Args: alert_id (str): Alert identifier. Returns: str: Full alert details URL. """ return f"{get_scm_ui_base_url()}/insights/iot-security/alerts/security-alerts/alert-detail?id={alert_id}" def get_scm_vuln_url(vuln: dict) -> str: """Build the SCM vulnerability details URL. Args: vuln (dict): Vulnerability object. Returns: str: Full vulnerability details URL. """ vulnerability_name = vuln.get("vulnerability_name", "").replace(" ", "%20") device_id = vuln.get("deviceid", "") return ( f"{get_scm_ui_base_url()}" f"/insights/iot-security/assets/assets/overview/{device_id}" f"?vulnerabilityname={vulnerability_name}" ) def trim_seen_ids(seen_ids: list[str]) -> list[str]: if len(seen_ids) > SEEN_IDS_LIMIT: return seen_ids[SEEN_IDS_TRIM_COUNT:] return seen_ids def test_module(client: Client, is_fetch: bool, fetch_alerts: bool, fetch_vulns: bool) -> str: """ Returning 'ok' indicates that the integration works like it is supposed to. Connection to the service is successful. Args: client (Client): client to use is_fetch (bool): Whether to fetch incidents fetch_alerts (bool): Whether to fetch alerts fetch_vulns (bool): Whether to fetch vulnerabilities Returns: 'ok' if test passed, anything else will fail the test. """ if is_fetch: fetch_incidents( client, last_run=demisto.getLastRun(), fetch_alerts=fetch_alerts, fetch_vulns=fetch_vulns, is_test=True, ) else: client.list_devices(0, 1) return "ok" def device_security_get_device(client: Client, args: dict) -> CommandResults: """ Returns a Device Security device Args: client (Client): Device Security client. args (dict): all command arguments. Returns: device CommandResults """ device_id = args.get("id", "") if not device_id: return_error("id argument is required.") device_id = str(device_id) result = client.get_device(device_id) if not result: return CommandResults(readable_output="### No device found") readable_output = tableToMarkdown("Device Security Device", result, removeNull=True) return CommandResults( readable_output=readable_output, outputs_prefix="PaloAltoNetworksDeviceSecurity.Device", outputs_key_field="deviceid", outputs=result, ) def device_security_get_device_by_ip(client: Client, args: dict) -> CommandResults: """ Returns a Device Security device Args: client (Client): Device Security client. args (dict): all command arguments. Returns: device CommandResults """ device_ip = args.get("ip", "") if not device_ip: return_error("ip argument is required.") device_ip = str(device_ip) result = client.get_device_by_ip(device_ip) devices = result.get("devices", []) if not devices: return CommandResults(readable_output="### No devices found") readable_output = tableToMarkdown("Device Security Devices", devices, removeNull=True) return CommandResults( readable_output=readable_output, outputs_prefix="PaloAltoNetworksDeviceSecurity.Device", outputs_key_field="devices", outputs=devices, ) def device_security_list_devices(client: Client, args: dict) -> CommandResults: """ Returns a list of Device Security devices Args: client (Client): Device Security client. args (dict): all command arguments. Returns: List of devices CommandResults """ try: offset = int(args.get("offset", "0")) if offset < 0: return_error("Offset must be a non-negative integer.") pagelength = int(args.get("limit", client.max_fetch)) if pagelength <= 0: return_error("Limit must be a positive integer.") except ValueError: return_error("Offset and limit must be integers.") result = client.list_devices(offset, pagelength) if not result: return CommandResults(readable_output="### No devices found") readable_output = tableToMarkdown("Device Security Devices", result, removeNull=True) return CommandResults( readable_output=readable_output, outputs_prefix="PaloAltoNetworksDeviceSecurity.DeviceList", outputs_key_field="deviceid", outputs=result, ) def device_security_list_alerts(client: Client, args: dict) -> CommandResults: """ Returns a list of Device Security alerts (max: 100) Args: client (Client): Device Security client. args (dict): all command arguments. Returns: List of alerts CommandResults """ try: start_time = arg_to_datetime( arg=args.get("start_time"), arg_name="start_time", required=False, is_utc=True, ) stime = start_time.strftime("%Y-%m-%dT%H:%M:%SZ") if start_time else "-1" offset = int(args.get("offset", "0")) if offset < 0: return_error("Offset must be a non-negative integer.") pagelength = min(int(args.get("limit", client.max_fetch)), PAGELENGTH) if pagelength <= 0: return_error("Limit must be a positive integer.") except ValueError: return_error("Offset and limit must be integers.") result = client.list_alerts(stime, offset, pagelength, "desc") if not result: return CommandResults(readable_output="### No alerts found") readable_output = tableToMarkdown("Device Security Alerts", result, removeNull=True) return CommandResults( readable_output=readable_output, outputs_prefix="PaloAltoNetworksDeviceSecurity.Alerts", outputs_key_field="id", outputs=result, ) def device_security_list_vulns(client: Client, args: dict) -> CommandResults: """ Returns a list of Device Security vulnerabilities (max: 100) Args: client (Client): Device Security client. args (dict): all command arguments. Returns: List of vulnerabilities CommandResults """ try: start_time = arg_to_datetime( arg=args.get("start_time"), arg_name="start_time", required=False, is_utc=True, ) stime = start_time.strftime("%Y-%m-%dT%H:%M:%SZ") if start_time else "-1" offset = int(args.get("offset", "0")) if offset < 0: return_error("Offset must be a non-negative integer.") pagelength = min(int(args.get("limit", client.max_fetch)), PAGELENGTH) if pagelength <= 0: return_error("Limit must be a positive integer.") except ValueError: return_error("Offset and limit must be integers.") result = client.list_vulns(stime, offset, pagelength) if not result: return CommandResults(readable_output="### No vulnerabilities found") readable_output = tableToMarkdown("Device Security Vulnerabilities", result, removeNull=True) return CommandResults( readable_output=readable_output, outputs_prefix="PaloAltoNetworksDeviceSecurity.Vulns", outputs_key_field="zb_ticketid", outputs=result, ) def device_security_resolve_alert(client: Client, args: dict) -> CommandResults: """ Resolve a Device Security alert Args: client (Client): Device Security client. args (dict): all command arguments. Returns: None in CommandResults """ alert_id = args.get("id", "") if not alert_id: return_error("id argument is required.") alert_id = str(alert_id) reason = str(args.get("reason", "Resolved by XSOAR")) reason_type = str(args.get("reason_type", "No Action Needed")) client.resolve_alert(alert_id, reason, reason_type) return CommandResults(readable_output=f"Alert {alert_id} was resolved successfully") def device_security_resolve_vuln(client: Client, args: dict) -> CommandResults: """ Resolve a Device Security vulnerability Args: client (Client): Device Security client. args (dict): all command arguments. Returns: None in CommandResults """ vuln_id = args.get("id", "") if not vuln_id: return_error("id argument is required.") vuln_id = str(vuln_id) full_name = args.get("full_name", "") if not full_name: return_error("full_name argument is required.") full_name = str(full_name) reason = str(args.get("reason", "Resolved by XSOAR")) client.resolve_vuln(vuln_id, full_name, reason) return CommandResults(readable_output=f"Vulnerability {vuln_id} was resolved successfully") def normalize_detected_date(detected_date: str | list | None) -> str | None: if isinstance(detected_date, str) or detected_date is None: return detected_date if detected_date: first_detected_date = detected_date[0] return first_detected_date if isinstance(first_detected_date, str) else None return None def format_fetch_start_time(fetch_time: str) -> str: if fetch_time == "-1": return fetch_time fetch_time_dt = arg_to_datetime(fetch_time, arg_name="Fetch start time", is_utc=True, required=True) if fetch_time_dt is None: raise ValueError(f"Could not parse fetch time: {fetch_time}") return fetch_time_dt.strftime("%Y-%m-%dT%H:%M:%SZ") def fetch_alert_incidents( client: Client, last_alerts_fetch: str | None, last_alerts_seen_ids: list[str] | None, max_fetch: int ) -> tuple[list[dict], str | None, list[str]]: stime = last_alerts_fetch or format_fetch_start_time(client.first_fetch) seen_ids = set(last_alerts_seen_ids or []) incidents: list[dict] = [] new_last_fetch = last_alerts_fetch new_seen_ids: list[str] = list(seen_ids) # preserve previously seen IDs offset = 0 while len(incidents) < max_fetch: alerts = client.list_alerts(stime, offset=offset, pagelength=max_fetch) demisto.debug(f"[Fetch]- Number of incidents - alerts before filtering: {len(alerts)}") if not alerts: break for alert in alerts: alert_date = alert.get("date") alert_id = alert.get("zb_ticketid", "").replace("alert-", "") if not alert_date or not alert_id: continue if alert_date == last_alerts_fetch and alert_id in seen_ids: continue if len(incidents) >= max_fetch: break device_security_incident_url = get_scm_alert_url(alert_id) alert_raw_json = { **alert, "rawType": "Device Security Alert", "devicesecurityincidenturl": device_security_incident_url, } incidents.append( { "name": alert.get("name", ""), "rawType": "Device Security Alert", "occurred": alert_date, "rawJSON": json.dumps(alert_raw_json), "details": alert.get("description", ""), "CustomFields": {"devicesecurityincidenturl": device_security_incident_url}, } ) if new_last_fetch is None or alert_date > new_last_fetch: new_last_fetch = alert_date new_seen_ids = [alert_id] elif alert_date == new_last_fetch and alert_id not in new_seen_ids: new_seen_ids.append(alert_id) if len(alerts) < max_fetch or len(incidents) >= max_fetch: break offset += max_fetch return incidents, new_last_fetch, trim_seen_ids(new_seen_ids) def fetch_vulnerability_incidents( client: Client, last_vulns_fetch: str | None, last_vulns_seen_ids: list[str] | None, max_fetch: int ) -> tuple[list[dict], str | None, list[str]]: stime = last_vulns_fetch or format_fetch_start_time(client.first_fetch) seen_ids = set(last_vulns_seen_ids or []) incidents: list[dict] = [] new_last_fetch = last_vulns_fetch new_seen_ids: list[str] = list(seen_ids) # preserve previously seen IDs offset = 0 while len(incidents) < max_fetch: vulns = client.list_vulns(stime, offset=offset, pagelength=max_fetch) if not vulns: break for vuln in vulns: detected_date = normalize_detected_date(vuln.get("detected_date")) vuln_id = vuln.get("zb_ticketid", "") if not detected_date or not vuln_id: continue if detected_date == last_vulns_fetch and vuln_id in seen_ids: continue if len(incidents) >= max_fetch: break device_security_incident_url = get_scm_vuln_url(vuln) vuln_raw_json = { **vuln, "rawType": "Device Security Vulnerability", "devicesecurityincidenturl": device_security_incident_url, } incidents.append( { "name": vuln.get("name", ""), "rawType": "Device Security Vulnerability", "occurred": detected_date, "rawJSON": json.dumps(vuln_raw_json), "details": ( f'Device {vuln.get("name", "")} at IP {vuln.get("ip", "")}: ' f'{vuln.get("vulnerability_name", "")}' ), "CustomFields": {"devicesecurityincidenturl": device_security_incident_url}, } ) if new_last_fetch is None or detected_date > new_last_fetch: new_last_fetch = detected_date new_seen_ids = [vuln_id] elif detected_date == new_last_fetch and vuln_id not in new_seen_ids: new_seen_ids.append(vuln_id) if len(vulns) < max_fetch or len(incidents) >= max_fetch: break offset += max_fetch return incidents, new_last_fetch, trim_seen_ids(new_seen_ids) def fetch_incidents( client: Client, last_run: dict, fetch_alerts: bool, fetch_vulns: bool, is_test: bool = False ) -> tuple[dict | None, list[dict] | None]: """ This function will execute each interval (default is 1 minute). Args: client (Client): Device Security client last_run: last_run dict containing the timestamps of the latest incident we fetched from previous fetch Returns: next_run: This will be last_run in the next fetch-incidents incidents: Incidents that will be created in Demisto """ demisto.debug("[Fetch] PaloAltoNetworks_DeviceSecurity - Start fetching") demisto.debug(f"[Fetch] PaloAltoNetworks_DeviceSecurity - Last run: {json.dumps(last_run)}") # Get the last fetch time, if exists last_alerts_fetch = last_run.get("last_alerts_fetch") last_alerts_seen_ids = last_run.get("last_alerts_seen_ids", []) last_vulns_fetch = last_run.get("last_vulns_fetch") last_vulns_seen_ids = last_run.get("last_vulns_seen_ids", []) max_fetch = client.max_fetch incidents = [] if fetch_alerts: alert_incidents, last_alerts_fetch, last_alerts_seen_ids = fetch_alert_incidents( client, last_alerts_fetch, last_alerts_seen_ids, max_fetch ) incidents.extend(alert_incidents) if fetch_vulns: vuln_incidents, last_vulns_fetch, last_vulns_seen_ids = fetch_vulnerability_incidents( client, last_vulns_fetch, last_vulns_seen_ids, max_fetch ) incidents.extend(vuln_incidents) next_run = { "last_alerts_fetch": last_alerts_fetch, "last_alerts_seen_ids": last_alerts_seen_ids, "last_vulns_fetch": last_vulns_fetch, "last_vulns_seen_ids": last_vulns_seen_ids, } demisto.debug( f"[Fetch] PaloAltoNetworks_DeviceSecurity - Number of incidents (alerts and vulnerability) " f"after filtering : {len(incidents)}" ) demisto.debug(f"[Fetch] PaloAltoNetworks_DeviceSecurity - Next run after incidents fetching: {json.dumps(next_run)}") if is_test: return None, None return next_run, incidents def parse_positive_int(value: Any, field_name: str) -> int: try: parsed_value = int(value) except (ValueError, TypeError) as e: raise ValueError(f"{field_name} needs to be an integer") from e if parsed_value <= 0: raise ValueError(f"{field_name} needs to be a positive integer") return parsed_value def main(): """ PARSE AND VALIDATE INTEGRATION PARAMS """ command = demisto.command() try: params = demisto.params() args = demisto.args() is_fetch = argToBoolean(params.get("isFetch", False)) tsg_id = params.get("tsg_id") client_id = params.get("client_id") client_secret = params.get("client_secret") verify_certificate = not argToBoolean(params.get("insecure", False)) proxy = argToBoolean(params.get("proxy", False)) fetch_alerts = argToBoolean(params.get("fetch_alerts", True)) fetch_vulns = argToBoolean(params.get("fetch_vulns", True)) api_timeout = parse_positive_int(params.get("api_timeout", "60"), "API timeout") max_fetch = parse_positive_int(params.get("max_fetch", "10"), "Maximum number of incidents per fetch") first_fetch = "-1" try: first_fetch_dt = arg_to_datetime( arg=params.get("first_fetch"), arg_name="First fetch time", is_utc=True, required=False, ) except ValueError as e: raise ValueError(f"First fetch time is in a wrong format. Error: {e!s}") from e if first_fetch_dt: first_fetch = first_fetch_dt.strftime("%Y-%m-%dT%H:%M:%SZ") token_base_url = "https://auth.apps.paloaltonetworks.com" base_url = "https://api.strata.paloaltonetworks.com/iot/pub/v1" access_token = get_scm_access_token( token_base_url, tsg_id, client_id, client_secret, verify_certificate, proxy, ) headers = {"Authorization": f"Bearer {access_token}"} client = Client( base_url=base_url, api_timeout=api_timeout, first_fetch=first_fetch, max_fetch=max_fetch, verify=verify_certificate, proxy=proxy, ok_codes=(200,), headers=headers, ) demisto.info(f"Command being called is {command}") if command == "test-module": # This is the call made when pressing the integration Test button. return_results(test_module(client, is_fetch, fetch_alerts, fetch_vulns)) elif command == "fetch-incidents": # Set and define the fetch incidents command to run after activated via integration settings. next_run, incidents = fetch_incidents( client=client, last_run=demisto.getLastRun(), fetch_alerts=fetch_alerts, fetch_vulns=fetch_vulns, ) if next_run is not None: demisto.setLastRun(next_run) if incidents is not None: demisto.incidents(incidents) elif command == "device-security-get-device": return_results(device_security_get_device(client, args)) elif command == "device-security-get-device-by-ip": return_results(device_security_get_device_by_ip(client, args)) elif command == "device-security-list-devices": return_results(device_security_list_devices(client, args)) elif command == "device-security-list-alerts": return_results(device_security_list_alerts(client, args)) elif command == "device-security-list-vulns": return_results(device_security_list_vulns(client, args)) elif command == "device-security-resolve-alert": return_results(device_security_resolve_alert(client, args)) elif command == "device-security-resolve-vuln": return_results(device_security_resolve_vuln(client, args)) else: raise NotImplementedError(f'Command "{command}" is not implemented.') except Exception as e: return_error(f"Failed to execute {command} command. Error: {e!s}") if __name__ in ("__main__", "__builtin__", "builtins"): main()