PrismaCloud v2
Prisma Cloud secures infrastructure, workloads and applications, across the entire cloud-native technology stack.
Network Security · Prisma Cloud by Palo Alto Networks
Details
| ID | PrismaCloud v2 |
|---|---|
| Provider | Palo Alto Networks |
| Category | Network Security |
| From Version | 6.5.0 |
| Docker Image | demisto/python3:3.12.13.10116658 |
| Supported Modules | Agentix XSIAM EDR Cortex Cloud Cloud Runtime Security |
README
Prisma Cloud secures infrastructure, workloads and applications, across the entire cloud-native technology stack.
This integration was integrated and tested with version 23.2.1 of PrismaCloud
Some changes have been made that might affect your existing content.
If you are upgrading from a previous version of this integration, see Breaking Changes.
Configure Prisma Cloud v2 in Cortex
| Parameter | Description | Required |
|---|---|---|
| Server URL | Prisma Cloud service tenant admin console URL. The URL for the Prisma Cloud service varies depending on the cluster on which your tenant is deployed. For more information see: https://pan.dev/prisma-cloud/api/cspm/api-urls/. | True |
| Username / Access Key ID | True | |
| Password / Access Key Secret | True | |
| Use system proxy settings | False | |
| Trust any certificate (not secure) | False | |
| Incident type | False | |
| Maximum number of incidents to fetch | Maximum is limited to 200. | False |
| First fetch time interval | Date or relative timestamp to start fetching incidents from, in the format of <number> <time unit>. For example, 2 minutes, 12 hours, 6 days, 2 weeks, 3 months, 1 year, ISO timestamp. Default is 3 days. | False |
| Advanced: Time in minutes to look back when fetching incidents | Use this parameter to determine how far back to look in the search for incidents that were created before the last run time and did not match the query when they were created. When choosing to increase this value, duplicate incidents might occur at increase time. | False |
| Fetch only incidents matching these filters | Comma-separated list of filter name and value, in the following format: filtername1=filtervalue1,filtername2=filtervalue2,etc. Names and possible values for filters can be found by running the “prisma-cloud-alert-filter-list” command. | False |
| Fetch incidents | ||
| Incident Mirroring Direction | Choose the direction to mirror the incident: Incoming (from Prisma Cloud to Cortex XSOAR), Outgoing (from Cortex XSOAR to Prisma Cloud), or Incoming and Outgoing (from/to Cortex XSOAR and Prisma Cloud). Cortex XSOAR only parameter. | False |
| Close Mirrored XSOAR Incident | When selected, closing and re-opening the Prisma Cloud alert is mirrored in Cortex XSOAR. Cortex XSOAR only parameter. | False |
| Close Mirrored Prisma Cloud Alert | When selected, closing and re-opening the Cortex XSOAR incident is mirrored in Prisma Cloud. | False |
| Output results of V1 commands to the context data in the old format | False |
Incident Mirroring
You can enable incident mirroring between Cortex XSOAR incidents and Prisma Cloud alerts (available from Cortex XSOAR version 6.0.0).
To setup the mirroring follow these instructions:
- Navigate to Settings > Integrations > Servers & Services.
- Search for Prisma Cloud v2 and select your integration instance.
- Enable Fetches incidents.
- Optional: You can go to the Fetch only incidents matching these filters parameter and select the query to fetch the alerts from Prisma Cloud.
- In the Incident Mirroring Direction parameter, select in which direction the incidents should be mirrored:
- Incoming - Changes in Prisma Cloud Alerts (
status,dismissalNote,reason) will be reflected in Cortex XSOAR incidents. - Outgoing - Changes in Cortex XSOAR incidents will be reflected in Prisma Cloud alerts (
status,reason). - Incoming And Outgoing - Changes in Cortex XSOAR incidents and in Prisma Cloud alerts will be reflected in both directions.
- None - Turns off incident mirroring.
- Incoming - Changes in Prisma Cloud Alerts (
- Optional: Check the Close Mirrored XSOAR Incident integration parameter to close or reopen the Cortex XSOAR incident when the corresponding alert is closed or re-opened in Prisma Cloud.
- Optional: Check the Close Mirrored Prisma Cloud Alert integration parameter to close or reopen the Prisma Cloud alert when the corresponding Cortex XSOAR incident is closed or re-opened.
Newly fetched incidents will be mirrored in the chosen direction. However, this selection does not affect existing incidents.
Important Notes
- To ensure the mirroring works as expected, an incoming mapper is required, to map the expected fields in Cortex XSOAR (you can use the default mapper - Prisma Cloud - Incoming Mapper).
- When mirroring in incidents from Prisma Cloud to Cortex XSOAR:
- When enabling the Close Mirrored XSOAR Incident integration parameter, the field in Prisma Cloud that determines whether the incident was closed or re-opend is the
statusfield.
- When enabling the Close Mirrored XSOAR Incident integration parameter, the field in Prisma Cloud that determines whether the incident was closed or re-opend is the
- When mirroring out incidents from Cortex XSOAR to Prisma Cloud:
- When enabling the Close Mirrored Prisma Cloud Alert integration parameter, the corresponding alert in Prisma Cloud will be closed with a Dismissed status for every reason chosen in the Cortex XSOAR incident (possible reasons are:
False Positive,Duplicate,OtherandResolved). The Reason field of the Prisma Cloud alert will include the original reason selected in Cortex XSOAR and the close notes. - When re-opening a Cortex XSOAR incident with a
ResolvedPrisma Cloud status, the incident will be re-opened, but the alert in Prisma Cloud will remain Resolved due to API limitations.
- When enabling the Close Mirrored Prisma Cloud Alert integration parameter, the corresponding alert in Prisma Cloud will be closed with a Dismissed status for every reason chosen in the Cortex XSOAR incident (possible reasons are:
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.
prisma-cloud-alert-dismiss
Dismiss or snooze the alerts matching the given filter. Either policy IDs or alert IDs must be provided. When no absolute time nor relative time arguments are provided, the default time range is all times. For snoozing, provide “snooze_unit” and “snooze_value” arguments.
Base Command
prisma-cloud-alert-dismiss
Input
| Argument Name | Description | Required |
|---|---|---|
| alert_ids | Comma-separated list of alert IDs to be dismissed. | Optional |
| policy_ids | Comma-separated list of policy IDs. | Optional |
| snooze_value | The amount of time for snoozing alert. Both snooze value and unit must be specified if snoozing. | Optional |
| snooze_unit | The time unit for snoozing alert. Both snooze value and unit must be specified if snoozing. Possible values are: hour, day, week, month, year. | Optional |
| dismissal_note | Reason for dismissal. | Required |
| time_range_date_from | Start time for the search. Time is interpreted as UTC. Values can be in either ISO date format, relative time, or epoch timestamp. For example: “2019-10-21T23:45:00 GMT+3” (ISO date format), “3 days” (relative time), 1579039377301 (epoch time). | Optional |
| time_range_date_to | End time for the search. Time is interpreted as UTC. Values can be in either ISO date format, relative time, or epoch timestamp. For example: “2019-10-21T23:45:00 GMT+3” (ISO date format), “3 days” (relative time), 1579039377301 (epoch time). | Optional |
| time_range_unit | The search time unit. The “login” and “epoch” options are only available if “time_range_value” is not provided. Possible values are: hour, day, week, month, year, login, epoch. | Optional |
| time_range_value | The amount of “time_range_unit” to go back in time. For example, 3 days, 5 weeks, etc. | Optional |
| filters | Comma-separated list of filter name and value, in the following format: filtername1=filtervalue1,filtername2=filtervalue2,etc. Names and possible values for filters can be found by running the “prisma-cloud-alert-filter-list” command. | Optional |
Context Output
There is no context output for this command.
Command example
!prisma-cloud-alert-dismiss dismissal_note="from XSOAR" alert_ids=P-464811 snooze_unit=hour snooze_value=1
Human Readable Output
Alerts snoozed successfully
Snooze note: from XSOAR.
Command example
!prisma-cloud-alert-dismiss dismissal_note="from XSOAR" alert_ids=P-469663 time_range_unit=month
Human Readable Output
Alerts dismissed successfully
Dismissal note: from XSOAR.
prisma-cloud-alert-get-details
Gets the details of an alert based on the alert ID.
Base Command
prisma-cloud-alert-get-details
Input
| Argument Name | Description | Required |
|---|---|---|
| alert_id | The alert ID. | Required |
| detailed | Whether to retrieve the entire / trimmed alert model. Possible values are: true, false. Default is true. | Optional |
Context Output
| Path | Type | Description |
|---|---|---|
| PrismaCloud.Alert.id | String | The alert ID. |
| PrismaCloud.Alert.status | String | The alert status. |
| PrismaCloud.Alert.reason | String | The alert reason. |
| PrismaCloud.Alert.alertTime | Date | The time of the alert. |
| PrismaCloud.Alert.firstSeen | Date | The time the alert was first seen. |
| PrismaCloud.Alert.lastSeen | Date | The time the alert was last seen. |
| PrismaCloud.Alert.eventOccurred | Date | The time the event occurred. |
| PrismaCloud.Alert.alertRules | String | Names of the alert rules that triggered this alert. |
| PrismaCloud.Alert.resource.resourceApiName | String | The resource API name. |
| PrismaCloud.Alert.resource.id | String | The resource ID. |
| PrismaCloud.Alert.resource.account | String | The resource account. |
| PrismaCloud.Alert.resource.accountId | String | The resource account ID. |
| PrismaCloud.Alert.resource.resourceType | String | The resource type. |
| PrismaCloud.Alert.policy.policyId | String | The policy ID. |
| PrismaCloud.Alert.policy.name | String | The policy name. |
| PrismaCloud.Alert.policy.policyType | String | The type of policy. |
| PrismaCloud.Alert.policy.severity | String | The policy severity. |
| PrismaCloud.Alert.policy.recommendation | String | The policy recommendation. |
| PrismaCloud.Alert.policy.remediation.description | String | The policy remediation description. |
| PrismaCloud.Alert.policy.remediation.cliScriptTemplate | String | The policy remediation CLI script template. |
| PrismaCloud.Alert.policy.description | String | The policy description. |
| PrismaCloud.Alert.policy.labels | Unknown | The policy labels. |
| PrismaCloud.Alert.resource.cloudType | String | The resource cloud type. |
| PrismaCloud.Alert.resource.rrn | String | The restricted resource name. |
| PrismaCloud.Alert.resource.regionId | String | The resource region ID. |
| PrismaCloud.Alert.resource.url | String | The resource URL. |
| PrismaCloud.Alert.policy.remediable | Boolean | Whether the policy is remediable. |
| PrismaCloud.Alert.policy.systemDefault | Boolean | Whether the policy is the system default. |
| PrismaCloud.Alert.policy.deleted | Boolean | Whether the policy was deleted. |
Command example
!prisma-cloud-alert-get-details alert_id=P-465020
Context Example
{
"PrismaCloud": {
"Alert": {
"alertRules": [
{
"alertRuleNotificationConfig": [],
"allowAutoRemediate": false,
"enabled": true,
"name": "test",
"notifyOnDismissed": false,
"notifyOnOpen": true,
"notifyOnResolved": false,
"notifyOnSnoozed": false,
"policyScanConfigId": "policy-scan-config-id3",
"scanAll": true,
"target": {
"accountGroups": [],
"excludedAccounts": [],
"regions": [],
"tags": []
}
},
{
"alertRuleNotificationConfig": [],
"allowAutoRemediate": false,
"enabled": true,
"name": "Default Alert Rule",
"notifyOnDismissed": false,
"notifyOnOpen": true,
"notifyOnResolved": false,
"notifyOnSnoozed": false,
"policyScanConfigId": "policy-scan-config-id2",
"scanAll": false,
"target": {
"accountGroups": [],
"excludedAccounts": [],
"regions": [],
"tags": []
}
}
],
"alertTime": "2023-01-25T19:18:22Z",
"dismissalNote": "from XSOAR",
"dismissalUntilTs": -1,
"dismissedBy": "name@company.com",
"firstSeen": "2023-01-25T19:18:22Z",
"history": [
{
"modifiedBy": "name@company.com",
"modifiedOn": 1674987271011,
"reason": "NEW_ALERT",
"status": "open"
}
],
"id": "P-465020",
"lastSeen": "2023-01-29T10:14:31Z",
"metadata": {
"saveSearchId": "save-search-id1"
},
"networkAnomaly": false,
"policy": {
"complianceMetadata": [
{
"complianceId": "compliance-id1",
"customAssigned": false,
"policyId": "a11b2cc3-1111-2222-33aa-a1b23ccc4dd5",
"requirementId": "DSI",
"requirementName": "Data Security & Information Lifecycle Management",
"requirementViewOrder": 5,
"sectionDescription": "Data Inventory / Flows.",
"sectionId": "DSI-02",
"sectionLabel": "CSA CCM",
"sectionViewOrder": 25,
"standardDescription": "Cloud Security Alliance: Cloud Controls Matrix Version 3.0.1",
"standardName": "CSA CCM v3.0.1",
"systemDefault": true
},
{
"complianceId": "compliance-id2",
"customAssigned": false,
"policyId": "a11b2cc3-1111-2222-33aa-a1b23ccc4dd5",
"requirementId": "IAM",
"requirementName": "Identity & Access Management",
"requirementViewOrder": 10,
"sectionDescription": "Third Party Access.",
"sectionId": "IAM-07",
"sectionLabel": "CSA CCM",
"sectionViewOrder": 72,
"standardDescription": "Cloud Security Alliance: Cloud Controls Matrix Version 3.0.1",
"standardName": "CSA CCM v3.0.1",
"systemDefault": true
}
],
"deleted": false,
"description": "This policy identifies GCP VPC Network subnets have disabled Private Google access. Private Google access enables virtual machine instances on a subnet to reach Google APIs and services using an internal IP address rather than an external IP address. Internal (private) IP addresses are internal to Google Cloud Platform and are not routable or reachable over the Internet. You can use Private Google access to allow VMs without Internet access to reach Google APIs, services, and properties that are accessible over HTTP/HTTPS.",
"findingTypes": [],
"labels": [
"Policy Status Review"
],
"lastModifiedBy": "example@gmail.com",
"lastModifiedOn": 1664515792712,
"name": "GCP VPC Network subnets have Private Google access disabled",
"policyId": "a11b2cc3-1111-2222-33aa-a1b23ccc4dd5",
"policyType": "config",
"recommendation": "1. Login to GCP Portal\n2. Go to VPC network (Left Panel)\n3. Select VPC networks\n2. Click on the name of a reported subnet, The 'Subnet details' page will be displayed\n3. Click on 'EDIT' button\n4. Set 'Private Google access' to 'On'\n5. Click on Save",
"remediable": true,
"remediation": {
"cliScriptTemplate": "gcloud compute networks subnets update ${resourceName} --project=${account} --region ${region} --enable-private-ip-google-access",
"description": "This CLI command requires 'compute.networkAdmin' permission. Successful execution will enable GCP VPC Network subnets 'Private Google access'.",
"impact": "enables private-ip-google-access in GCP VPC Network subnets"
},
"severity": "medium",
"systemDefault": true
},
"reason": "USER_DISMISSED",
"resource": {
"account": "mail1@gmail.com",
"accountId": "panw-prisma-cloud",
"additionalInfo": {},
"cloudAccountGroups": [
"Default Account Group"
],
"cloudAccountOwners": [
"mail1@gmail.com"
],
"cloudServiceName": "Google VPC",
"cloudType": "gcp",
"data": {
"creationTimestamp": "2023-01-25T08:52:45.111-08:00",
"fingerprint": "a-fingerprint=",
"gatewayAddress": "1.1.1.1",
"id": "1111111111111111111",
"ipCidrRange": "1.1.1.1/20",
"kind": "compute#subnetwork",
"name": "boombox-network",
"network": "https://some-url",
"privateIpGoogleAccess": false,
"purpose": "PRIVATE",
"region": "https://some-url",
"selfLink": "https://some-url/subnetworks/boombox-network",
"stackType": "IPV4_ONLY"
},
"id": "1111111111111111111",
"internalResourceId": "11111111",
"name": "boombox-network",
"region": "GCP Belgium",
"regionId": "europe-west1",
"resourceApiName": "gcloud-compute-networks-subnets-list",
"resourceConfigJsonAvailable": true,
"resourceDetailsAvailable": true,
"resourceTs": 1676633361033,
"resourceType": "SUBNET",
"rrn": "rrn::name:place:111:a1b2:a%3Ajj55-2023-01-29-09-25",
"unifiedAssetId": "unified-asset-id1"
},
"saveSearchId": "save-search-id3",
"status": "dismissed"
}
}
}
Human Readable Output
Alert P-465020 Details
Alert ID Reason Status Alert Time First Seen Last Seen Policy ID Policy Type Is Policy System Default Is Policy Remediable Policy Name Policy Recommendation Policy Description Policy Severity Policy Remediation Description Policy Remediation CLI Script Policy Labels Resource Type Resource Account Resource Cloud Type Resource RRN Resource ID Resource Account ID Resource Region ID Resource Api Name P-465020 USER_DISMISSED dismissed 2023-01-25T19:18:22Z 2023-01-25T19:18:22Z 2023-01-29T10:14:31Z a11b2cc3-1111-2222-33aa-a1b23ccc4dd5 config true true GCP VPC Network subnets have Private Google access disabled 1. Login to GCP Portal
2. Go to VPC network (Left Panel)
3. Select VPC networks
2. Click on the name of a reported subnet, The ‘Subnet details’ page will be displayed
3. Click on ‘EDIT’ button
4. Set ‘Private Google access’ to ‘On’
5. Click on SaveThis policy identifies GCP VPC Network subnets have disabled Private Google access. Private Google access enables virtual machine instances on a subnet to reach Google APIs and services using an internal IP address rather than an external IP address. Internal (private) IP addresses are internal to Google Cloud Platform and are not routable or reachable over the Internet. You can use Private Google access to allow VMs without Internet access to reach Google APIs, services, and properties that are accessible over HTTP/HTTPS. medium This CLI command requires ‘compute.networkAdmin’ permission. Successful execution will enable GCP VPC Network subnets ‘Private Google access’. gcloud compute networks subnets update ${resourceName} –project=${account} –region ${region} –enable-private-ip-google-access Policy Status Review SUBNET mail1@gmail.com gcp rrn::name:place:111:a1b2:a%3Ajj55-2023-01-29-09-25 1111111111111111111 panw-prisma-cloud europe-west1 gcloud-compute-networks-subnets-list
prisma-cloud-alert-filter-list
List the acceptable filters and values for alerts.
Base Command
prisma-cloud-alert-filter-list
Input
There are no input arguments for this command.
Context Output
| Path | Type | Description |
|---|---|---|
| PrismaCloud.AlertFilters.filterName | String | The filter name. |
| PrismaCloud.AlertFilters.options | String | The filter value options. |
| PrismaCloud.AlertFilters.staticFilter | Unknown | Whether the filter is static. |
Command example
#### Context Example
```json
{
"PrismaCloud": {
"AlertFilters": [
{
"filterName": "policy.name",
"options": [
"GCP Kubernetes Engine Clusters have Master authorized networks disabled"
],
"staticFilter": false
},
{
"filterName": "policy.type",
"options": [
"anomaly",
"audit_event",
"config",
"data",
"iam",
"network",
"workload_incident",
"workload_vulnerability"
],
"staticFilter": true
},
{
"filterName": "policy.label",
"options": [],
"staticFilter": false
},
{
"filterName": "policy.severity",
"options": [
"critical",
"high",
"medium",
"low",
"informational"
],
"staticFilter": true
},
{
"filterName": "policy.complianceStandard",
"options": [],
"staticFilter": false
},
{
"filterName": "policy.complianceRequirement",
"options": [],
"staticFilter": false
},
{
"filterName": "policy.complianceSection",
"options": [],
"staticFilter": false
},
{
"filterName": "cloud.account",
"options": [],
"staticFilter": false
},
{
"filterName": "account.group",
"options": [],
"staticFilter": false
},
{
"filterName": "cloud.region",
"options": [],
"staticFilter": false
},
{
"filterName": "alertRule.name",
"options": [],
"staticFilter": false
},
{
"filterName": "resource.id",
"options": [],
"staticFilter": false
},
{
"filterName": "resource.name",
"options": [],
"staticFilter": false
},
{
"filterName": "resource.type",
"options": [],
"staticFilter": false
},
{
"filterName": "resource.group",
"options": [],
"staticFilter": false
},
{
"filterName": "cloud.service",
"options": [],
"staticFilter": false
},
{
"filterName": "cloud.accountId",
"options": [],
"staticFilter": false
},
{
"filterName": "object.exposure",
"options": [
"private",
"public",
"conditional"
],
"staticFilter": true
},
{
"filterName": "malware",
"options": [
"true"
],
"staticFilter": true
},
{
"filterName": "object.classification",
"options": [],
"staticFilter": false
},
{
"filterName": "object.identifier",
"options": [],
"staticFilter": false
},
{
"filterName": "timeRange.type",
"options": [
"ALERT_STATUS_UPDATED",
"ALERT_UPDATED",
"ALERT_OPENED"
],
"staticFilter": true
},
{
"filterName": "vulnerability.severity",
"options": [
"all",
"high",
"critical",
"low",
"medium"
],
"staticFilter": true
},
{
"filterName": "buildtime.resourceName",
"options": [],
"staticFilter": false
},
{
"filterName": "git.filename",
"options": [],
"staticFilter": false
},
{
"filterName": "git.provider",
"options": [
"github",
"gitlab",
"bitbucket",
"perforce"
],
"staticFilter": false
},
{
"filterName": "git.repository",
"options": [],
"staticFilter": false
},
{
"filterName": "iac.framework",
"options": [
"ttt",
"CloudFormation"
],
"staticFilter": false
},
{
"filterName": "asset.class",
"options": [],
"staticFilter": false
},
{
"filterName": "alert.id",
"options": [],
"staticFilter": false
},
{
"filterName": "policy.subtype",
"options": [
"audit",
"build",
"data_classification",
"dns",
"identity",
"malware",
"network",
"network_config",
"network_event",
"permissions",
"run",
"run_and_build",
"ueba"
],
"staticFilter": true
},
{
"filterName": "alert.status",
"options": [
"dismissed",
"snoozed",
"open",
"resolved"
],
"staticFilter": true
},
{
"filterName": "cloud.type",
"options": [
"alibaba_cloud",
"aws",
"azure",
"gcp",
"oci"
],
"staticFilter": true
},
{
"filterName": "policy.remediable",
"options": [
"true",
"false"
],
"staticFilter": true
}
]
}
}
Human Readable Output
Filter Options
Filter Name Options Static Filter policy.name GCP Kubernetes Engine Clusters have Master authorized networks disabled false policy.type anomaly,
audit_event,
config,
data,
iam,
network,
workload_incident,
workload_vulnerabilitytrue policy.label false policy.severity critical,
high,
medium,
low,
informationaltrue policy.complianceStandard false policy.complianceRequirement false policy.complianceSection false cloud.account false account.group false cloud.region false alertRule.name false resource.id false resource.name false resource.type false resource.group false cloud.service false cloud.accountId false object.exposure private,
public,
conditionaltrue malware true true object.classification false object.identifier false timeRange.type ALERT_STATUS_UPDATED,
ALERT_UPDATED,
ALERT_OPENEDtrue vulnerability.severity all,
high,
critical,
low,
mediumtrue buildtime.resourceName false git.filename false git.provider github,
gitlab,
bitbucket,
perforcefalse git.repository false iac.framework ttt,
CloudFormationfalse asset.class false alert.id false policy.subtype audit,
build,
data_classification,
dns,
identity,
malware,
network,
network_config,
network_event,
permissions,
run,
run_and_build,
uebatrue alert.status dismissed,
snoozed,
open,
resolvedtrue cloud.type alibaba_cloud,
aws,
azure,
gcp,
ocitrue policy.remediable true,
falsetrue
prisma-cloud-remediation-command-list
Generates and returns a list of remediation commands for the specified alerts and policies. Data returned for a successful call include fully constructed commands for remediation. Either a policy ID or alert IDs must be provided. The returned information can be retrieved in the UI by clicking the “Remediate” button under the “Actions” column for supported alerts. When no absolute time nor relative time arguments are provided, the default time range is all times.
Base Command
prisma-cloud-remediation-command-list
Input
| Argument Name | Description | Required |
|---|---|---|
| alert_ids | Comma-seperated list of alert IDs for which to get remediation details. Provided alert IDs must be associated with the same policy. If a policy is specified, all the alerts specified must belong to that policy. | Optional |
| policy_id | Policy ID for which to get remediation details. | Optional |
| time_range_date_from | Start time for the search. Time is interpreted as UTC. Values can be in either ISO date format, relative time, or epoch timestamp. For example: “2019-10-21T23:45:00 GMT+3” (ISO date format), “3 days” (relative time), 1579039377301 (epoch time). | Optional |
| time_range_date_to | End time for the search. Time is interpreted as UTC. Values can be in either ISO date format, relative time, or epoch timestamp. For example: “2019-10-21T23:45:00 GMT+3” (ISO date format), “3 days” (relative time), 1579039377301 (epoch time). | Optional |
| time_range_unit | The search time unit. The “login” and “epoch” options are only available if “time_range_value” is not provided. Possible values are: hour, day, week, month, year, login, epoch. | Optional |
| time_range_value | The amount of “time_range_unit” to go back in time. For example, 3 days, 5 weeks, etc. | Optional |
| limit | Maximum number of entries to return. Default is 50. | Optional |
| all_results | Whether to retrieve all results. The “limit” argument will be ignored. Possible values are: true, false. | Optional |
Context Output
| Path | Type | Description |
|---|---|---|
| PrismaCloud.AlertRemediation.description | String | Description of CLI remediation instructions. |
| PrismaCloud.AlertRemediation.scriptImpact | String | Impact of CLI remediation instructions. |
| PrismaCloud.AlertRemediation.alertId | String | The ID of the alert to which the remediation details apply. |
| PrismaCloud.AlertRemediation.CLIScript | String | The exact CLI command string. |
Command example
!prisma-cloud-remediation-command-list policy_id=a11b2cc3-1111-2222-33aa-a1b23ccc4dd5 limit=2
Context Example
{
"PrismaCloud": {
"Alert": {
"Remediation": [
{
"CLIScript": "aws rds modify-db-instance --db-instance-identifier aaaaaaaaaaaaaa --region us-east-1 --deletion-protection",
"alertId": "P-351515",
"description": "This CLI command requires 'rds:ModifyDBInstance' permission. Successful execution will enable deletion protection for the reported AWS RDS instance.",
"scriptImpact": null
},
{
"CLIScript": "aws rds modify-db-instance --db-instance-identifier bbbbbbbbbbbbbbb --region us-east-1 --deletion-protection",
"alertId": "P-351323",
"description": "This CLI command requires 'rds:ModifyDBInstance' permission. Successful execution will enable deletion protection for the reported AWS RDS instance.",
"scriptImpact": null
}
]
}
}
}
Human Readable Output
Showing 2 of 3 results:
Remediation Command List
CLI Script Alert Id Description aws rds modify-db-instance –db-instance-identifier aaaaaaaaaaaaaa –region us-east-1 –deletion-protection P-351515 This CLI command requires ‘rds:ModifyDBInstance’ permission. Successful execution will enable deletion protection for the reported AWS RDS instance. aws rds modify-db-instance –db-instance-identifier bbbbbbbbbbbbbbb –region us-east-1 –deletion-protection P-351323 This CLI command requires ‘rds:ModifyDBInstance’ permission. Successful execution will enable deletion protection for the reported AWS RDS instance.
prisma-cloud-alert-remediate
Remediates the alert with the specified ID, if that alert is associated with a remediable policy. In order to check what remediation would run, use the “prisma-cloud-remediation-command-list” command first.
Base Command
prisma-cloud-alert-remediate
Input
| Argument Name | Description | Required |
|---|---|---|
| alert_id | The alert ID. | Required |
Context Output
| Path | Type | Description |
|---|---|---|
| PrismaCloud.AlertRemediation.alertId | String | The ID of the alert to which the remediation apply. |
| PrismaCloud.AlertRemediation.successful | Boolean | Whether the remediation was successful. |
| PrismaCloud.AlertRemediation.failureReason | String | The failure reason for the remediation. |
| PrismaCloud.AlertRemediation.errorValue | String | The error value for the remediation. |
Command example
!prisma-cloud-alert-remediate alert_id=P-488074
Context Example
{
"PrismaCloud": {
"AlertRemediation": {
"alertId": "P-488074",
"successful": true
}
}
}
Human Readable Output
Alert P-488074 remediated successfully.
prisma-cloud-alert-reopen
Re-open the alerts matching the given filter. Either policy IDs or alert IDs must be provided. When no absolute time nor relative time arguments are provided, the default time range is all times.
Base Command
prisma-cloud-alert-reopen
Input
| Argument Name | Description | Required |
|---|---|---|
| alert_ids | Comma-separated list of alert IDs to be reopened. | Optional |
| policy_ids | Comma-separated list of policy IDs. | Optional |
| time_range_date_from | Start time for the search. Time is interpreted as UTC. Values can be in either ISO date format, relative time, or epoch timestamp. For example: “2019-10-21T23:45:00 GMT+3” (ISO date format), “3 days” (relative time), 1579039377301 (epoch time). | Optional |
| time_range_date_to | End time for the search. Time is interpreted as UTC. Values can be in either ISO date format, relative time, or epoch timestamp. For example: “2019-10-21T23:45:00 GMT+3” (ISO date format), “3 days” (relative time), 1579039377301 (epoch time). | Optional |
| time_range_unit | The search time unit. The “login” and “epoch” options are only available if “time_range_value” is not provided. Possible values are: hour, day, week, month, year, login, epoch. | Optional |
| time_range_value | The amount of “time_range_unit” to go back in time. For example, 3 days, 5 weeks, etc. | Optional |
| filters | Comma-separated list of filter name and value, in the following format: filtername1=filtervalue1,filtername2=filtervalue2,etc. Names and possible values for filters can be found by running the “prisma-cloud-alert-filter-list” command. | Optional |
Context Output
There is no context output for this command.
Command example
!prisma-cloud-alert-reopen alert_ids=P-469663
Human Readable Output
Alerts re-opened successfully
prisma-cloud-alert-search
Search alerts on the Prisma Cloud platform. When no absolute time nor relative time arguments are provided, the search will show alerts from the last 7 days.
Base Command
prisma-cloud-alert-search
Input
| Argument Name | Description | Required |
|---|---|---|
| time_range_date_from | Start time for the search. Time is interpreted as UTC. Values can be in either ISO date format, relative time, or epoch timestamp. For example: “2019-10-21T23:45:00 GMT+3” (ISO date format), “3 days” (relative time), 1579039377301 (epoch time). | Optional |
| time_range_date_to | End time for the search. Time is interpreted as UTC. Values can be in either ISO date format, relative time, or epoch timestamp. For example: “2019-10-21T23:45:00 GMT+3” (ISO date format), “3 days” (relative time), 1579039377301 (epoch time). | Optional |
| time_range_unit | The search time unit. The “login” and “epoch” options are only available if “time_range_value” is not provided. Possible values are: hour, day, week, month, year, login, epoch. | Optional |
| time_range_value | The amount of “time_range_unit” to go back in time. For example, 3 days, 5 weeks, etc. | Optional |
| filters | Comma-separated list of filter name and value, in the following format: filtername1=filtervalue1,filtername2=filtervalue2,etc. Names and possible values for filters can be found by running the “prisma-cloud-alert-filter-list” command. | Optional |
| detailed | Whether to retrieve the entire / trimmed alert model. Possible values are: true, false. Default is true. | Optional |
| limit | Maximum number of entries to return. Default is 50. | Optional |
| next_token | Token of the next page to retrive. When provided, other arguments are ignored. | Optional |
| sort_field | The field to sort the results by. Possible values are: alertTime,firstSeen,lastSeen,lastUpdated. | Optional |
| sort_direction | The direction to sort the results by. Sort field must be specified if sorting. Possible values are: asc, desc. Default is asc. | Optional |
Context Output
| Path | Type | Description |
|---|---|---|
| PrismaCloud.AlertPageToken.nextPageToken | String | Next page token. |
| PrismaCloud.Alert.id | String | The ID of the returned alert. |
| PrismaCloud.Alert.status | String | The status of the returned alert. |
| PrismaCloud.Alert.reason | String | The reason of the returned alert. |
| PrismaCloud.Alert.lastSeen | String | The time the returned alert was last seen. |
| PrismaCloud.Alert.firstSeen | String | The time the returned alert was first seen. |
| PrismaCloud.Alert.lastUpdated | String | The time the returned alert was last updated. |
| PrismaCloud.Alert.alertTime | String | The time of the returned alert. |
| PrismaCloud.Alert.policy.policyId | String | The policy ID of the returned alert. |
| PrismaCloud.Alert.policy.name | String | The policy name of the returned alert. |
| PrismaCloud.Alert.policy.policyType | String | The policy type of the returned alert. |
| PrismaCloud.Alert.policy.severity | String | The policy severity of the returned alert. |
| PrismaCloud.Alert.policy.remediable | Boolean | Whether the policy is remediable. |
| PrismaCloud.Alert.policy.description | String | The policy description of the returned alert. |
| PrismaCloud.Alert.policy.recommendation | String | The policy recommendation of the returned alert. |
| PrismaCloud.Alert.policy.remediation.description | String | The policy remediation description of the returned alert. |
| PrismaCloud.Alert.policy.remediation.cliScriptTemplate | String | The policy CLI script template description of the returned alert. |
| PrismaCloud.Alert.policy.systemDefault | Boolean | Whether the policy is the system default. |
| PrismaCloud.Alert.policy.deleted | Boolean | Whether the policy was deleted. |
| PrismaCloud.Alert.resource.resourceType | String | The resource type of the returned alert. |
| PrismaCloud.Alert.resource.name | String | The resource name of the returned alert. |
| PrismaCloud.Alert.resource.account | String | The resource account of the returned alert. |
| PrismaCloud.Alert.resource.cloudType | String | The resource cloud type of the returned alert. |
| PrismaCloud.Alert.resource.rrn | String | The restricted resource name of the returned alert. |
Command example
!prisma-cloud-alert-search filters=alert.status=open,policy.remediable=true,cloud.type=gcp,policy.type=config limit=2
Context Example
{
"PrismaCloud": {
"Alert": [
{
"alertRules": [],
"alertTime": "2023-02-17T12:57:46Z",
"firstSeen": "2023-02-17T12:57:46Z",
"history": [],
"id": "P-487678",
"lastSeen": "2023-02-17T12:57:46Z",
"lastUpdated": "2023-02-19T13:27:29Z",
"metadata": {
"saveSearchId": "save-search-id2"
},
"policy": {
"complianceMetadata": [
{
"complianceId": "compliance-id1",
"customAssigned": false,
"policyId": "policy-id2",
"requirementId": "DSI",
"requirementName": "Data Security & Information Lifecycle Management",
"requirementViewOrder": 5,
"sectionDescription": "Data Inventory / Flows.",
"sectionId": "DSI-02",
"sectionLabel": "CSA CCM",
"sectionViewOrder": 25,
"standardDescription": "Cloud Security Alliance: Cloud Controls Matrix Version 3.0.1",
"standardName": "CSA CCM v3.0.1",
"systemDefault": true
},
{
"complianceId": "compliance-id2",
"customAssigned": false,
"policyId": "policy-id4",
"requirementId": "IAM",
"requirementName": "Identity & Access Management",
"requirementViewOrder": 10,
"sectionDescription": "Third Party Access.",
"sectionId": "IAM-07",
"sectionLabel": "CSA CCM",
"sectionViewOrder": 72,
"standardDescription": "Cloud Security Alliance: Cloud Controls Matrix Version 3.0.1",
"standardName": "CSA CCM v3.0.1",
"systemDefault": true
}
],
"deleted": false,
"description": "This policy identifies GCP Firewall rule allowing all traffic on read-only port (12346) which exposes GKE clusters. In GKE, Kubelet exposes a read-only port 12346 which shows the configurations of all pods on the cluster at the /pods API endpoint. GKE itself does not expose this port to the Internet as the default project firewall configuration blocks external access. However, it is possible to inadvertently expose this port publicly on GKE clusters by creating a Google Compute Engine VPC firewall for GKE nodes that allows traffic from all source ranges on all the ports. This configuration publicly exposes all pod configurations, which might contain sensitive information.",
"findingTypes": [],
"labels": [],
"lastModifiedBy": "example@gmail.com",
"lastModifiedOn": 1649907869989,
"name": "GCP Firewall rule exposes GKE clusters by allowing all traffic on read-only port (12346)",
"policyId": "policy-id5",
"policyType": "config",
"recommendation": "As port 12345 exposes sensitive information of GKE pod configuration it is recommended to disable this firewall rule. \nOtherwise, remove the overly permissive source IPs following below steps,\n\n1. Login to GCP Console\n2. Navigate to 'VPC Network'(Left Panel)\n3. Go to the 'Firewall' section (Left Panel)\n4. Click on the reported Firewall rule\n5. Click on 'EDIT'\n6. Modify Source IP ranges to specific IP\n7. Click on 'SAVE'.",
"remediable": true,
"remediation": {
"cliScriptTemplate": "gcloud compute --project=${account} firewall-rules update ${resourceName} --disabled",
"description": "This CLI command requires 'compute.firewalls.update' and 'compute.networks.updatePolicy' permission. Successful execution will disable this firewall rule blocking internet traffic to port 12346.",
"impact": "Disable GCP Firewall rule which allows all traffic on read-only port (12345)"
},
"severity": "medium",
"systemDefault": true
},
"policyId": "policy-id7",
"reason": "NEW_ALERT",
"resource": {
"account": "Google Cloud Account",
"accountId": "AAAAAAA",
"additionalInfo": {},
"cloudAccountGroups": [
"Default Account Group"
],
"cloudAccountOwners": [
"mail1@gmail.com",
"example@gmail.com"
],
"cloudServiceName": "Google VPC",
"cloudType": "gcp",
"data": {
"allowed": [
{
"IPProtocol": "all"
}
],
"creationTimestamp": "2022-09-19T21:28:10.104-07:00",
"description": "",
"direction": "INGRESS",
"disabled": false,
"id": "666666666666666666",
"kind": "compute#firewall",
"logConfig": {
"enable": false
},
"name": "k8s",
"network": "https://some-url",
"priority": 1000,
"selfLink": "https://some-url",
"sourceRanges": [
"0.0.0.0/0"
]
},
"id": "3333333333333333333",
"name": "k8s",
"region": "global",
"regionId": "global",
"resourceApiName": "gcloud-compute-firewall-rules-list",
"resourceConfigJsonAvailable": true,
"resourceDetailsAvailable": true,
"resourceTs": 1676633555070,
"resourceType": "SECURITY_GROUP",
"rrn": "rrn::name:place:111:a1b2:a%3Ajj55-2023-01-29-09-25",
"unifiedAssetId": "unifiedassetid2"
},
"saveSearchId": "save-search-id5",
"status": "open"
},
{
"alertRules": [],
"alertTime": "2023-02-17T12:57:46Z",
"firstSeen": "2023-02-17T12:57:46Z",
"history": [],
"id": "P-487768",
"lastSeen": "2023-02-17T12:57:46Z",
"lastUpdated": "2023-02-19T13:27:29Z",
"metadata": {
"saveSearchId": "save-search-id5"
},
"policy": {
"complianceMetadata": [
{
"complianceId": "compliance-id5",
"customAssigned": false,
"policyId": "policy-id-4",
"requirementId": "Section 404",
"requirementName": "Management Assessment",
"requirementViewOrder": 3,
"sectionDescription": "(b) Evaluation and Reporting.",
"sectionId": "Section 404.B",
"sectionLabel": "Section 404.B",
"sectionViewOrder": 9,
"standardDescription": "Management",
"standardName": "Management",
"systemDefault": true
}
],
"deleted": false,
"description": "This policy identifies GCP Firewall rule allowing all traffic on port 12345 which allows GKE full node access. The port 12345 on the kubelet is used by the kube-apiserver (running on hosts labelled as Orchestration Plane) for exec and logs. As per security best practice, port 12345 should not be exposed to the public.",
"findingTypes": [],
"labels": [],
"lastModifiedBy": "example@gmail.com",
"lastModifiedOn": 1652328910000,
"name": "GCP Firewall rule exposes GKE clusters by allowing all traffic on port 12345",
"policyId": "policy-id5",
"policyType": "config",
"recommendation": "As port 12345 exposes sensitive information of GKE pod configuration it is recommended to disable this firewall rule. \nOtherwise, remove the overly permissive source IPs following the below steps,\n\n1. Login to GCP Console\n2. Navigate to 'VPC Network'(Left Panel)\n3. Go to the 'Firewall' section (Left Panel)\n4. Click on the reported Firewall rule\n5. Click on 'EDIT'\n6. Modify Source IP ranges to specific IP\n7. Click on 'SAVE'.",
"remediable": true,
"remediation": {
"cliScriptTemplate": "gcloud compute --project=${account} firewall-rules update ${resourceName} --disabled",
"description": "This CLI command requires 'compute.firewalls.update' and 'compute.networks.updatePolicy' permission. Successful execution will disable this firewall rule blocking internet traffic to port 12345.",
"impact": "disable GCP Firewall rule that allows all traffic on port 12345"
},
"severity": "medium",
"systemDefault": true
},
"policyId": "policy-id-2",
"reason": "NEW_ALERT",
"resource": {
"account": "Google Cloud Account",
"accountId": "AAAAAAA",
"additionalInfo": {},
"cloudAccountGroups": [
"AAAAAAA",
"Default Account Group"
],
"cloudAccountOwners": [
"mail1@gmail.com",
"example@gmail.com"
],
"cloudServiceName": "Google VPC",
"cloudType": "gcp",
"data": {
"allowed": [
{
"IPProtocol": "all"
}
],
"creationTimestamp": "2022-09-19T21:28:10.104-07:00",
"description": "",
"direction": "INGRESS",
"disabled": false,
"id": "7777777777777777777",
"kind": "compute#firewall",
"logConfig": {
"enable": false
},
"name": "k8s",
"network": "https://some-url/global/networks/default",
"priority": 1000,
"selfLink": "https://some-url/global/firewalls/k8s",
"sourceRanges": [
"0.0.0.0/0"
]
},
"id": "7777777777777777777",
"name": "k8s",
"region": "global",
"regionId": "global",
"resourceApiName": "gcloud-compute-firewall-rules-list",
"resourceConfigJsonAvailable": true,
"resourceDetailsAvailable": true,
"resourceTs": 1676633555070,
"resourceType": "SECURITY_GROUP",
"rrn": "rrn::name:place:111:a1b2:a%3Ajj55-2023-01-29-09-25",
"unifiedAssetId": "unifiedassetid6"
},
"saveSearchId": "save-search-id6",
"status": "open"
}
],
"AlertPageToken": {
"nextPageToken": "token"
}
}
}
Human Readable Output
Showing 2 of 25 results:
Alerts Details
Alert ID Reason Status Alert Time First Seen Last Seen Last Updated Policy ID Policy Type Is Policy System Default Is Policy Remediable Policy Name Is Policy Deleted Policy Recommendation Policy Description Policy Severity Policy Remediation Description Policy Remediation CLI Script Resource Type Resource Name Resource Account Resource Cloud Type Resource RRN P-487678 NEW_ALERT open 2023-02-17T12:57:46Z 2023-02-17T12:57:46Z 2023-02-17T12:57:46Z 2023-02-19T13:27:29Z policy-id7 config true true GCP Firewall rule exposes GKE clusters by allowing all traffic on read-only port (12346) false As port 12346 exposes sensitive information of GKE pod configuration it is recommended to disable this firewall rule.
Otherwise, remove the overly permissive source IPs following below steps,
1. Login to GCP Console
2. Navigate to ‘VPC Network’(Left Panel)
3. Go to the ‘Firewall’ section (Left Panel)
4. Click on the reported Firewall rule
5. Click on ‘EDIT’
6. Modify Source IP ranges to specific IP
7. Click on ‘SAVE’.This policy identifies GCP Firewall rule allowing all traffic on read-only port (12346) which exposes GKE clusters. In GKE, Kubelet exposes a read-only port 12346 which shows the configurations of all pods on the cluster at the /pods API endpoint. GKE itself does not expose this port to the Internet as the default project firewall configuration blocks external access. However, it is possible to inadvertently expose this port publicly on GKE clusters by creating a Google Compute Engine VPC firewall for GKE nodes that allows traffic from all source ranges on all the ports. This configuration publicly exposes all pod configurations, which might contain sensitive information. medium This CLI command requires ‘compute.firewalls.update’ and ‘compute.networks.updatePolicy’ permission. Successful execution will disable this firewall rule blocking internet traffic to port 12346. gcloud compute –project=${account} firewall-rules update ${resourceName} –disabled SECURITY_GROUP k8s Google Cloud Account gcp rrn::name:place:111:a1b2:a%3Ajj55-2023-01-29-09-25 P-487768 NEW_ALERT open 2023-02-17T12:57:46Z 2023-02-17T12:57:46Z 2023-02-17T12:57:46Z 2023-02-19T13:27:29Z policy-id-2 config true true GCP Firewall rule exposes GKE clusters by allowing all traffic on port 12345 false As port 12345 exposes sensitive information of GKE pod configuration it is recommended to disable this firewall rule.
Otherwise, remove the overly permissive source IPs following the below steps,
1. Login to GCP Console
2. Navigate to ‘VPC Network’(Left Panel)
3. Go to the ‘Firewall’ section (Left Panel)
4. Click on the reported Firewall rule
5. Click on ‘EDIT’
6. Modify Source IP ranges to specific IP
7. Click on ‘SAVE’.This policy identifies GCP Firewall rule allowing all traffic on port 12345 which allows GKE full node access. The port 12345 on the kubelet is used by the kube-apiserver (running on hosts labelled as Orchestration Plane) for exec and logs. As per security best practice, port 12345 should not be exposed to the public. medium This CLI command requires ‘compute.firewalls.update’ and ‘compute.networks.updatePolicy’ permission. Successful execution will disable this firewall rule blocking internet traffic to port 12345. gcloud compute –project=${account} firewall-rules update ${resourceName} –disabled SECURITY_GROUP k8s Google Cloud Account gcp rrn::name:place:111:a1b2:a%3Ajj55-2023-01-29-09-25 Next Page Token
token
prisma-cloud-config-search
Search configuration inventory on the Prisma Cloud platform using RQL language. Use this command for all queries that start with “config”. When no absolute time nor relative time arguments are provided, the default time range is all times.
Base Command
prisma-cloud-config-search
Input
| Argument Name | Description | Required |
|---|---|---|
| time_range_date_from | Start time for the search. Time is interpreted as UTC. Values can be in either ISO date format, relative time, or epoch timestamp. For example: “2019-10-21T23:45:00 GMT+3” (ISO date format), “3 days” (relative time), 1579039377301 (epoch time). | Optional |
| time_range_date_to | End time for the search. Time is interpreted as UTC. Values can be in either ISO date format, relative time, or epoch timestamp. For example: “2019-10-21T23:45:00 GMT+3” (ISO date format), “3 days” (relative time), 1579039377301 (epoch time). | Optional |
| time_range_unit | The search time unit. The “login” and “epoch” options are only available if “time_range_value” is not provided. Possible values are: hour, day, week, month, year, login, epoch. | Optional |
| time_range_value | The amount of “time_range_unit” to go back in time. For example, 3 days, 5 weeks, etc. | Optional |
| query | Query to run in Prisma Cloud config API using RQL language. For more information see: https://docs.paloaltonetworks.com/prisma/prisma-cloud/prisma-cloud-rql-reference/rql-reference/config-query. | Required |
| limit | Maximum number of entries to return. Default is 50. | Optional |
| search_id | Search ID. Can be used to rerun the same search. | Optional |
| sort_direction | The direction to sort the results by. Both sort direction and field must be specified if sorting. Possible values are: asc, desc. Default is desc. | Optional |
| sort_field | The field to sort the results by. Both sort direction and field must be specified if sorting. Possible values are: id, time, apiName, customerId, insertTs, json, cloudAccount, cloudRegion, stateId. Default is insertTs. | Optional |
| heuristic_search | Enable heuristic search optimization for faster results. Default is true. | Optional |
Context Output
| Path | Type | Description |
|---|---|---|
| PrismaCloud.Config.accountId | String | Cloud account ID. |
| PrismaCloud.Config.accountName | String | Cloud account name. |
| PrismaCloud.Config.allowDrillDown | Boolean | Whether to allow drill down. |
| PrismaCloud.Config.cloudType | String | Cloud type. |
| PrismaCloud.Config.deleted | Boolean | Whether the asset was deleted. |
| PrismaCloud.Config.hasExtFindingRiskFactors | Boolean | Whether the configuration has external finding risk factors. |
| PrismaCloud.Config.hasExternalFinding | Boolean | Whether the configuration has an external finding. |
| PrismaCloud.Config.hasExternalIntegration | Boolean | Whether the configuration has an external integration. |
| PrismaCloud.Config.hasNetwork | Boolean | Whether the configuration has a network. |
| PrismaCloud.Config.id | String | Prisma Cloud configuration ID. |
| PrismaCloud.Config.assetId | String | Prisma Cloud asset ID. |
| PrismaCloud.Config.data | Unknown | Prisma Cloud asset specific data. |
| PrismaCloud.Config.insertTs | Date | Insert timestamp. |
| PrismaCloud.Config.createdTs | Date | Created timestamp. |
| PrismaCloud.Config.name | String | Asset name. |
| PrismaCloud.Config.regionId | String | Cloud region ID. |
| PrismaCloud.Config.regionName | String | Cloud region name. |
| PrismaCloud.Config.resourceType | String | Cloud resource type. |
| PrismaCloud.Config.rrn | String | Cloud restricted resource name. |
| PrismaCloud.Config.service | String | Cloud service. |
| PrismaCloud.Config.stateId | String | State ID. |
Command example
!prisma-cloud-config-search query="config from cloud.resource where cloud.region = 'AWS Ohio' " limit=1
Context Example
{
"PrismaCloud": {
"Config": {
"accountId": "888888888888",
"accountName": "labs",
"allowDrillDown": true,
"assetId": "assetid1",
"cloudType": "aws",
"createdTs": "2023-02-17T11:07:40Z",
"data": {
"status": {
"isLogging": true,
"latestCloudWatchLogsDeliveryTime": "2023-02-19T13:27:38.122Z",
"latestDeliveryAttemptSucceeded": "2023-02-19T13:28:24Z",
"latestDeliveryAttemptTime": "2023-02-19T13:28:24Z",
"latestDeliveryTime": "2023-02-19T13:28:24.465Z",
"latestDigestDeliveryTime": "2023-02-19T12:40:04.109Z",
"latestNotificationAttemptSucceeded": "2023-02-19T13:28:24Z",
"latestNotificationAttemptTime": "2023-02-19T13:28:24Z",
"latestNotificationTime": "2023-02-19T13:28:24.461Z",
"logging": true,
"startLoggingTime": "2022-05-25T10:51:34.851Z",
"timeLoggingStarted": "2022-05-25T10:51:34Z",
"timeLoggingStopped": ""
},
"trail": "control"
},
"deleted": false,
"hasExtFindingRiskFactors": false,
"hasExternalFinding": false,
"hasExternalIntegration": false,
"hasNetwork": false,
"id": "arn:aws:trail:us-west-1:888888888888:trail/control",
"insertTs": "2023-02-19T13:29:28Z",
"name": "trail-status",
"regionId": "us-east-1",
"regionName": "AWS Ohio",
"resourceConfigJsonAvailable": true,
"resourceType": "Cloud Trail Status",
"rrn": "rrn::name:place:111:a1b2:a%3Ajj55-2023-01-29-09-25",
"service": "AWS CloudTrail",
"stateId": "stateid3"
}
}
}
Human Readable Output
Showing 1 of 2925 results:
Configuration Details
Name Id Cloud Type Service Account Name Region Name Deleted Account Id Asset Id Created Ts Insert Ts Region Id Resource Type Rrn control-trail-status arn:aws:trail:us-west-1:888888888888:trail/control aws AWS CloudTrail labs AWS Ohio false 888888888888 assetid1 2023-02-17T11:07:40Z 2023-02-19T13:29:28Z us-east-2 Cloud Trail Status rrn::name:place:111:a1b2:a%3Ajj55-2023-01-29-09-25
prisma-cloud-event-search
Search events inventory on the Prisma Cloud platform using RQL language. Use this command for all queries that start with “event”. When no absolute time nor relative time arguments are provided, the default time range is all times.
Base Command
prisma-cloud-event-search
Input
| Argument Name | Description | Required |
|---|---|---|
| time_range_date_from | Start time for the search. Time is interpreted as UTC. Values can be in either ISO date format, relative time, or epoch timestamp. For example: “2019-10-21T23:45:00 GMT+3” (ISO date format), “3 days” (relative time), 1579039377301 (epoch time). | Optional |
| time_range_date_to | End time for the search. Time is interpreted as UTC. Values can be in either ISO date format, relative time, or epoch timestamp. For example: “2019-10-21T23:45:00 GMT+3” (ISO date format), “3 days” (relative time), 1579039377301 (epoch time). | Optional |
| time_range_unit | The search time unit. The “login” and “epoch” options are only available if “time_range_value” is not provided. Possible values are: hour, day, week, month, year, login, epoch. | Optional |
| time_range_value | The amount of “time_range_unit” to go back in time. For example, 3 days, 5 weeks, etc. | Optional |
| query | Query to run in Prisma Cloud event API using RQL language. For more information see: https://docs.paloaltonetworks.com/prisma/prisma-cloud/prisma-cloud-rql-reference/rql-reference/event-query. | Required |
| limit | Maximum number of entries to return. Default is 50. | Optional |
| sort_field | The field to sort the results by. Possible values are: cloudService, operation, cloudAccount, cloudRegion, id, time, crud, user. | Optional |
| sort_direction | The direction to sort the results by. Sort field must be specified if sorting. Possible values are: asc, desc. Default is asc. | Optional |
Context Output
| Path | Type | Description |
|---|---|---|
| PrismaCloud.Event.subject | String | Cloud event subject. |
| PrismaCloud.Event.accountName | String | Cloud event account name. |
| PrismaCloud.Event.name | String | Cloud event name. |
| PrismaCloud.Event.source | String | Cloud event source. |
| PrismaCloud.Event.ip | String | Cloud event IP address. |
| PrismaCloud.Event.eventTs | Date | Cloud event timestamp. |
| PrismaCloud.Event.countryName | String | Cloud event country name. |
| PrismaCloud.Event.stateName | String | Cloud event state name. |
| PrismaCloud.Event.cityName | String | Cloud event city name. |
| PrismaCloud.Event.location | String | Cloud event location. |
| PrismaCloud.Event.account | String | Cloud event account. |
| PrismaCloud.Event.regionId | Number | Cloud event region ID. |
| PrismaCloud.Event.type | String | Cloud event type. |
| PrismaCloud.Event.id | Number | Cloud event ID. |
| PrismaCloud.Event.role | String | Cloud event role. |
| PrismaCloud.Event.accessKeyUsed | Boolean | Whether the cloud event access key is used. |
| PrismaCloud.Event.success | Boolean | Whether the cloud event is successful. |
| PrismaCloud.Event.internal | Boolean | Whether the cloud event is internal. |
| PrismaCloud.Event.cityId | Number | Cloud event city ID. |
| PrismaCloud.Event.cityLatitude | Number | Cloud event city latitude. |
| PrismaCloud.Event.cityLongitude | Number | Cloud event city longitude. |
| PrismaCloud.Event.countryId | Number | Cloud event country ID. |
| PrismaCloud.Event.dynamicData | String | Cloud event dynamic data. |
| PrismaCloud.Event.stateId | Number | Cloud event state ID. |
Command example
!prisma-cloud-event-search query="event from cloud.audit_logs where cloud.type = 'aws'" limit=2
Context Example
{
"PrismaCloud": {
"Event": [
{
"accessKeyUsed": false,
"account": "111111111111",
"accountName": "AAAAAAA",
"cityId": -3,
"cityLatitude": -1,
"cityLongitude": -1,
"cityName": "Internal",
"countryId": -3,
"countryName": "Internal",
"dynamicData": {},
"eventTs": "2022-10-17T00:00:26Z",
"id": 222222222,
"internal": false,
"location": "Internal",
"name": "StartBuild",
"notPersisted": false,
"regionId": 2,
"regionName": "AWS Ohio",
"role": "CloudWatchEventRule",
"source": "codebuild",
"stateId": -3,
"stateName": "Internal",
"subject": "Subject3",
"success": true,
"type": "CREATE"
},
{
"accessKeyUsed": false,
"account": "111111111111",
"accountName": "AAAAAAA",
"cityId": 4509177,
"cityLatitude": -1,
"cityLongitude": -1,
"cityName": "Columbus",
"countryId": 6251111,
"countryName": "United States of America",
"dynamicData": {},
"eventTs": "2022-10-17T00:03:07Z",
"id": 333333333,
"internal": false,
"ip": "1.1.1.1",
"location": "Columbus, Ohio, United States of America",
"name": "CreateReportGroup",
"notPersisted": false,
"regionId": 2,
"regionName": "AWS Ohio",
"role": "aws-codebuild-samples",
"source": "codebuild",
"stateId": 6666666,
"stateName": "Ohio",
"subject": "Subject6",
"success": false,
"type": "CREATE"
}
]
}
}
Human Readable Output
Showing 2 of 39018 results:
Event Details
Subject Account Name Name Source Ip Event Ts Country Name State Name City Name Location Account Region Id Type Id Role Access Key Used Success Internal Subject3 AAAAAAA StartBuild codebuild 2022-10-17T00:00:26Z Internal Internal Internal Internal 111111111111 2 CREATE 222222222 CloudWatchEventRule false true false Subject6 AAAAAAA CreateReportGroup codebuild 1.1.1.1 2022-10-17T00:03:07Z United States of America Ohio Columbus Columbus, Ohio, United States of America 111111111111 2 CREATE 333333333 aws-codebuild-samples false false false
prisma-cloud-network-search
Search networks inventory on the Prisma Cloud platform using RQL language. Use this command for all queries that start with “networks”. When no absolute time nor relative time arguments are provided, the default time range is all times. In order to limit the results returning, use “limit search records to” at the end of the RQL query, followed by a value from one of these options: 1, 10, 100, 1000, and 10,000.
Base Command
prisma-cloud-network-search
Input
| Argument Name | Description | Required |
|---|---|---|
| time_range_date_from | Start time for the search. Time is interpreted as UTC. Values can be in either ISO date format, relative time, or epoch timestamp. For example: “2019-10-21T23:45:00 GMT+3” (ISO date format), “3 days” (relative time), 1579039377301 (epoch time). | Optional |
| time_range_date_to | End time for the search. Time is interpreted as UTC. Values can be in either ISO date format, relative time, or epoch timestamp. For example: “2019-10-21T23:45:00 GMT+3” (ISO date format), “3 days” (relative time), 1579039377301 (epoch time). | Optional |
| time_range_unit | The search time unit. The “login” and “epoch” options are only available if “time_range_value” is not provided. Possible values are: hour, day, week, month, year, login, epoch. | Optional |
| time_range_value | The amount of “time_range_unit” to go back in time. For example, 3 days, 5 weeks, etc. | Optional |
| query | Query to run in Prisma Cloud network API using RQL language. For more information see: https://docs.paloaltonetworks.com/prisma/prisma-cloud/prisma-cloud-rql-reference/rql-reference/network-query. | Required |
| cloud_type | The cloud in which the network should be searched. Possible values are: aws, azure, gcp, alibaba_cloud, oci. | Optional |
| search_id | Search ID. Can be used to rerun the same search. | Optional |
Context Output
| Path | Type | Description |
|---|---|---|
| PrismaCloud.Network.Node.id | Number | Cloud network node ID. |
| PrismaCloud.Network.Node.name | String | Cloud network node name. |
| PrismaCloud.Network.Node.ipAddr | String | Cloud network node IP address. |
| PrismaCloud.Network.Node.grouped | Boolean | Whether the cloud network node is grouped. |
| PrismaCloud.Network.Node.suspicious | Boolean | Whether the cloud network node is suspicious. |
| PrismaCloud.Network.Node.vulnerable | Boolean | Whether the cloud network node is vulnerable. |
| PrismaCloud.Network.Node.metadata | Unknown | Cloud network node metadata. |
| PrismaCloud.Network.Connection.from | Number | Cloud network connection from node ID. |
| PrismaCloud.Network.Connection.to | Number | Cloud network connection to node ID. |
| PrismaCloud.Network.Connection.label | String | Cloud network connection label. |
| PrismaCloud.Network.Connection.suspicious | Boolean | Whether the cloud network node is suspicious. |
| PrismaCloud.Network.Connection.metadata | Unknown | Cloud network connection metadata. |
Command example
!prisma-cloud-network-search query="network from vpc.flow_record where cloud.account = 'AWS Prod' AND source.publicnetwork IN ( 'Suspicious IPs' ) AND bytes > 0 "
Context Example
{
"PrismaCloud": {
"Network": {
"Connection": [
{
"from": -963693921,
"label": "Web & 1 more",
"metadata": {
"account_id": [
"888888888888"
],
"asset_role": [
"Suspicious IPs"
],
"bytes_accepted": 598088,
"bytes_attempted": 360,
"bytes_rejected": 0,
"cloud_type": [
"aws"
],
"connection_overview_table": [
{
"accepted": "yes",
"port": "Web (80)",
"traffic_volume": 565611
},
{
"accepted": "yes",
"port": "SSH (22)",
"traffic_volume": 32477
},
{
"accepted": "no",
"port": "Web (80)",
"traffic_volume": 360
}
],
"countries": [
"N/A"
],
"flow_class": [
"Web (80)",
"SSH (22)"
],
"from_ip_addresses": [
"0.0.0.0"
],
"isps": [
"N/A"
],
"region_id": [
"N/A"
],
"states": [
"N/A"
],
"suspicious_ips": [
"35.180.1.1",
"172.31.34.235"
],
"to_ip_addresses": [
"35.180.1.1",
"10.0.2.5"
]
},
"suspicious": true,
"to": -1695489264
}
],
"Node": [
{
"grouped": false,
"iconId": "web_server",
"id": -1695489264,
"ipAddr": "10.0.2.5",
"metadata": {
"account_id": [
"888888888888"
],
"account_name": [
"AWS Prod"
],
"asset_role": [
"VM Instance",
"SSH",
"Web Server"
],
"cloud_type": [
"aws"
],
"compliance_count": 0,
"guard_duty_host_count": 4,
"guard_duty_iam_count": 0,
"host_vulnerability_count": 0,
"initial": true,
"inspector_rba_count": 0,
"inspector_sbp_count": 0,
"instance_id": [
"i-0d"
],
"ip_addresses": [
"10.0.2.5"
],
"net_iface_id": [
"eni-08"
],
"redlock_alert_count": 10,
"region_id": [
"us-west-1"
],
"region_name": [
"AWS California"
],
"resource_id": [
"i-00"
],
"rrn": "rrn::name:place:111:a1b2:a%3Ajj55-2023-01-29-09-25",
"secgroup_ids": [
"sg-0a"
],
"security_groups": [
{
"id": "sg-0a",
"name": "WebServersg"
}
],
"serverless_vulnerability_count": 0,
"tags": [
{
"name": "aws:cloudformation:stack-name",
"values": [
"aaa"
]
},
{
"name": "aws:cloudformation:stack-id",
"values": [
"arn:aws:trail:us-west-1:888888888888:trail/control"
]
},
{
"name": "aws:cloudformation:logical-id",
"values": [
"WebServerInstance"
]
},
{
"name": "Name",
"values": [
"PANW-WebServer"
]
}
],
"vpc_id": [
"vpc-07"
],
"vpc_name": [
{
"id": "vpc-07",
"name": "VPC-aaa"
}
]
},
"name": "PANW-WebServer",
"suspicious": false,
"vulnerable": true
},
{
"grouped": true,
"iconId": "suspicious",
"id": -963693921,
"ipAddr": "0.0.0.0",
"metadata": {
"account_id": [
"888888888888"
],
"account_name": [
"N/A"
],
"asset_role": [
"Suspicious IPs"
],
"bytes_accepted": 1368976,
"bytes_attempted": 2428,
"bytes_rejected": 0,
"cloud_type": [
"aws"
],
"compliance_count": 0,
"countries": [
"N/A"
],
"guard_duty_host_count": 0,
"guard_duty_iam_count": 0,
"host_vulnerability_count": 0,
"inspector_rba_count": 0,
"inspector_sbp_count": 0,
"instance_id": [
"N/A"
],
"ip_addresses": [
"N/A"
],
"isps": [
"N/A"
],
"launched_on": [
"N/A"
],
"net_iface_id": [
"N/A"
],
"redlock_alert_count": 0,
"region_id": [
"N/A"
],
"region_name": [
"N/A"
],
"resource_id": [
"N/A"
],
"secgroup_ids": [
"N/A"
],
"secgroup_names": [
"N/A"
],
"security_groups": [
"N/A"
],
"serverless_vulnerability_count": 0,
"specificIps": [
"172.31.34.235",
"1.1.1.1"
],
"states": [
"N/A"
],
"tags": [
"N/A"
],
"vpc_name": [
"N/A"
]
},
"name": "Suspicious IPs",
"suspicious": false,
"vulnerable": false
}
]
}
}
}
Human Readable Output
Network Details
Nodes
Id Name Ip Addr Grouped Suspicious Vulnerable -1695489264 PANW-WebServer 10.0.2.5 false false true -963693921 Suspicious IPs 0.0.0.0 true false false Connections
From To Label Suspicious -963693921 -1695489264 Web & 1 more true
prisma-cloud-error-file-list
Deprecated, use the prisma-cloud-code-issues-list command instead.
prisma-cloud-trigger-scan
Trigger asynchronous scan of all resources to refresh the current state at Prisma Cloud Code Security. In order to use this command, the “Code Security” module needs to be enabled and accessible in the Prisma Cloud UI.
Base Command
prisma-cloud-trigger-scan
Input
There are no input arguments for this command.
Context Output
There is no context output for this command.
Command example
#### Human Readable Output
>### Trigger Scan Results
>
>|Is Executed|Message|
>|---|---|
>| false | Executing a new scan has failed - a scheduled scan is already in progress. |
### prisma-cloud-resource-get
***
Get resource details.
#### Base Command
`prisma-cloud-resource-get`
#### Input
| **Argument Name** | **Description** | **Required** |
| --- | --- | --- |
| rrn | Restricted Resource Name of the resource to get details about. Can be retrieved by running a command that has that RRN. | Required |
#### Context Output
| **Path** | **Type** | **Description** |
| --- | --- | --- |
| PrismaCloud.Resource.rrn | String | Prisma Cloud restricted resource name. |
| PrismaCloud.Resource.id | String | Prisma Cloud resource ID. |
| PrismaCloud.Resource.name | String | Resource name. |
| PrismaCloud.Resource.url | String | Resource URL. |
| PrismaCloud.Resource.accountId | String | Cloud account ID. |
| PrismaCloud.Resource.accountName | String | Cloud account name. |
| PrismaCloud.Resource.cloudType | String | Cloud type. |
| PrismaCloud.Resource.regionId | String | Cloud region ID. |
| PrismaCloud.Resource.regionName | String | Cloud region Name. |
| PrismaCloud.Resource.service | String | Cloud service. |
| PrismaCloud.Resource.resourceType | String | Cloud resource type. |
| PrismaCloud.Resource.insertTs | Date | Insert timestamp. |
| PrismaCloud.Resource.deleted | Boolean | Whether the resource was deleted. |
| PrismaCloud.Resource.vpcId | String | VPC ID. |
| PrismaCloud.Resource.vpcName | String | VPC name. |
| PrismaCloud.Resource.tags | Unknown | Prisma Cloud resource tags. |
| PrismaCloud.Resource.riskGrade | String | Risk grade. |
| PrismaCloud.Resource.hasNetwork | Boolean | Whether the resource has a network. |
| PrismaCloud.Resource.hasExternalFinding | Boolean | Whether the resource has an external finding. |
| PrismaCloud.Resource.hasExternalIntegration | Boolean | Whether the resource has an external integration. |
| PrismaCloud.Resource.allowDrillDown | Boolean | Whether to allow drill down. |
| PrismaCloud.Resource.hasExtFindingRiskFactors | Boolean | Whether the resource has external finding risk factors. |
| PrismaCloud.Resource.data | Unknown | Prisma Cloud resource specific data. |
#### Command example
```!prisma-cloud-resource-get rrn=rrn::name:place:111:a1b2:a%3Ajj55-2023-01-29-09-25```
#### Context Example
```json
{
"PrismaCloud": {
"Resource": {
"accountId": "111111111111",
"accountName": "AAAAAAA",
"allowDrillDown": true,
"cloudType": "aws",
"data": {
"attributes": [
{
"attributeName": "restore",
"attributeValues": []
}
],
"snapshot": {
"allocatedStorage": 20,
"availabilityZone": "us-east-1a",
"dbiResourceId": "db-S",
"dbinstanceIdentifier": "aaaaaaaaaaaaaa",
"dbsnapshotArn": "arn:aws:trail:us-west-1:888888888888:trail/control",
"dbsnapshotIdentifier": "rds:aaaaaaaaaaaaaa-2023-01-29-09-25",
"encrypted": false,
"engine": "postgres",
"engineVersion": "13.7",
"iamdatabaseAuthenticationEnabled": false,
"instanceCreateTime": "2022-07-22T18:35:54.809Z",
"licenseModel": "postgresql-license",
"masterUsername": "master",
"optionGroupName": "default:postgres-13",
"originalSnapshotCreateTime": "2023-01-29T09:25:08.698Z",
"percentProgress": 100,
"port": 5432,
"processorFeatures": [],
"snapshotCreateTime": "2023-01-29T09:25:08.698Z",
"snapshotTarget": "region",
"snapshotType": "automated",
"status": "available",
"storageThroughput": 0,
"storageType": "standard",
"tagList": [],
"vpcId": "vpc-0f"
},
"tags": []
},
"deleted": true,
"hasExtFindingRiskFactors": false,
"hasExternalFinding": false,
"hasExternalIntegration": false,
"hasNetwork": false,
"id": "rds:aaaaaaaaaaaaaa-2023-01-29-09-25",
"insertTs": "2023-01-29T09:35:27Z",
"name": "rds:aaaaaaaaaaaaaa-2023-01-29-09-25",
"regionId": "us-east-1",
"regionName": "AWS Virginia",
"resourceConfigJsonAvailable": false,
"resourceType": "Managed Database Snapshot",
"riskGrade": "A",
"rrn": "rrn::name:place:111:a1b2:a%3Ajj55-2023-01-29-09-25",
"service": "Amazon RDS",
"tags": {
"": ""
},
"url": "https://some-url?region=us-east-1#db-snapshots:id=rds:aaaaaaaaaaaaaa-2023-01-29-09-25",
"vpcId": "vpc-0f",
"vpcName": "ServerlessVPC"
}
}
}
Human Readable Output
Resource Details
Rrn Id Name Url Account Id Account Name Cloud Type Region Id Region Name Service Resource Type Insert Ts Deleted Vpc Id Vpc Name Tags Risk Grade Has Network Has External Finding Has External Integration Allow Drill Down Has Ext Finding Risk Factors rrn::name:place:111:a1b2:a%3Ajj55-2023-01-29-09-25 rds:aaaaaaaaaaaaaa-2023-01-29-09-25 rds:aaaaaaaaaaaaaa-2023-01-29-09-25 https://some_url?region=us-east-1#db-snapshots:id=rds:aaaaaaaaaaaaaa-2023-01-29-09-25 111111111111 AAAAAAA aws us-east-1 AWS Virginia Amazon RDS Managed Database Snapshot 2023-01-29T09:35:27Z true vpc-0f ServerlessVPC : A false false false true false
prisma-cloud-resource-list
Returns all the resource lists. Maps to the Resource Lists under Settings > Resource Lists in the Console UI.
Base Command
prisma-cloud-resource-list
Input
| Argument Name | Description | Required |
|---|---|---|
| list_type | The resource list type. | Optional |
| limit | Maximum number of entries to return. Default is 50. | Optional |
| all_results | Whether to retrieve all results. The “limit” argument will be ignored. Possible values are: true, false. | Optional |
Context Output
| Path | Type | Description |
|---|---|---|
| PrismaCloud.ResourceList.id | String | Prisma Cloud resource list ID. |
| PrismaCloud.ResourceList.name | String | Resource list name. |
| PrismaCloud.ResourceList.resourceListType | String | Resource list type. |
| PrismaCloud.ResourceList.description | String | Resource list description. |
| PrismaCloud.ResourceList.lastModifiedBy | String | Resource list last modified user. |
| PrismaCloud.ResourceList.lastModifiedTs | Date | Resource list last modified time. |
| PrismaCloud.ResourceList.members | Unknown | Resource list members. |
Command example
!prisma-cloud-resource-list limit=3
Context Example
{
"PrismaCloud": {
"ResourceList": [
{
"description": null,
"id": "aa11bb22",
"lastModifiedBy": "admin@paloaltonetworks.com",
"lastModifiedTs": "2021-09-20T16:23:15Z",
"members": [
{
"demo": "lab"
},
{
"dev": "prisma"
},
{
"env": "lab"
}
],
"name": "First",
"resourceListType": "TAG"
},
{
"description": null,
"id": "aa22bb11",
"lastModifiedBy": "admin2@paloaltonetworks.com",
"lastModifiedTs": "2023-03-10T04:54:34Z",
"members": [
{
}
],
"name": "other",
"resourceListType": "COMPUTE_ACCESS_GROUP"
},
{
"description": null,
"id": "a3b4",
"lastModifiedBy": "test@paloaltonetworks.com",
"lastModifiedTs": "2023-07-10T22:27:55Z",
"members": [
{
"labels": [
"*"
],
"namespaces": [
"*"
]
}
],
"name": "panw",
"resourceListType": "COMPUTE_ACCESS_GROUP"
}
]
}
}
Human Readable Output
Showing 3 of 6 results:
Resources Details
Name Id Type Last Modified By First aa11bb22 TAG admin@paloaltonetworks.com other aa22bb11 COMPUTE_ACCESS_GROUP admin2@paloaltonetworks.com panw a3b4 COMPUTE_ACCESS_GROUP test@paloaltonetworks.com
prisma-cloud-user-roles-list
Retrieves user roles. Maps to Settings > Access Control > Roles in the Console UI.
Base Command
prisma-cloud-user-roles-list
Input
| Argument Name | Description | Required |
|---|---|---|
| role_id | The role id to get details of. | Optional |
| limit | Maximum number of entries to return. Default is 50. | Optional |
| all_results | Whether to retrieve all results. The “limit” argument will be ignored. Possible values are: true, false. | Optional |
Context Output
| Path | Type | Description |
|---|---|---|
| PrismaCloud.UserRoles.id | String | Prisma Cloud user roles ID. |
| PrismaCloud.UserRoles.name | String | User roles name. |
| PrismaCloud.UserRoles.resourceListIds | Unknown | User roles resource list IDs. |
| PrismaCloud.UserRoles.description | String | User roles description. |
| PrismaCloud.UserRoles.lastModifiedBy | String | User roles last modified user. |
| PrismaCloud.UserRoles.lastModifiedTs | Date | User roles last modified time. |
| PrismaCloud.UserRoles.associatedUsers | Unknown | User roles associated users. |
| PrismaCloud.UserRoles.restrictDismissalAccess | Boolean | Whether dismissal access is restricted for the user role. |
| PrismaCloud.UserRoles.roleType | String | User roles role type. |
| PrismaCloud.UserRoles.additionalAttributes | Unknown | User roles additional attributes. |
| PrismaCloud.UserRoles.codeRepositoryIds | Unknown | User roles code repository IDs. |
| PrismaCloud.UserRoles.accountGroupIds | Unknown | User roles account group IDs. |
| PrismaCloud.UserRoles.resourceLists | Unknown | User roles resource lists. |
| PrismaCloud.UserRoles.permissionGroup | Unknown | User roles permission group. |
| PrismaCloud.UserRoles.codeRepositories | Unknown | User roles code repositories. |
| PrismaCloud.UserRoles.accountGroups | Unknown | User roles account groups. |
Command example
!prisma-cloud-user-roles-list limit=3
Context Example
{
"PrismaCloud": {
"UserRoles": [
{
"accountGroupIds": [],
"accountGroups": [],
"additionalAttributes": {
"hasDefenderPermissions": false,
"onlyAllowCIAccess": false,
"onlyAllowComputeAccess": false,
"onlyAllowReadAccess": false
},
"associatedUsers": [
"lab",
"demo"
],
"codeRepositories": [],
"codeRepositoryIds": [],
"description": "",
"id": "a2b2",
"lastModifiedBy": "test@paloaltonetworks.com",
"lastModifiedTs": "2023-08-02T17:47:07Z",
"name": "dev-test",
"permissionGroup": null,
"resourceListIds": [],
"resourceLists": [],
"restrictDismissalAccess": true,
"roleType": "Developer"
},
{
"accountGroupIds": [],
"accountGroups": [],
"additionalAttributes": {
"hasDefenderPermissions": false,
"onlyAllowCIAccess": false,
"onlyAllowComputeAccess": false,
"onlyAllowReadAccess": false
},
"associatedUsers": [
"test"
],
"codeRepositories": [],
"codeRepositoryIds": [],
"description": "",
"id": "a3b3",
"lastModifiedBy": "admin@paloaltonetworks.com",
"lastModifiedTs": "2023-07-21T15:27:04Z",
"name": "Custom Read Only",
"permissionGroup": null,
"resourceListIds": [],
"resourceLists": [],
"restrictDismissalAccess": false,
"roleType": "Custom Read Only"
},
{
"accountGroupIds": [
"aaa111",
"bbb222"
],
"accountGroups": [
{
"id": "aaa111",
"name": "group1"
},
{
"id": "bbb222",
"name": "group2"
}
],
"additionalAttributes": {
"hasDefenderPermissions": false,
"onlyAllowCIAccess": false,
"onlyAllowComputeAccess": false,
"onlyAllowReadAccess": true
},
"associatedUsers": [
"user1",
"user2"
],
"codeRepositories": [
{
"id": "a3c3",
"name": "demo"
}
],
"codeRepositoryIds": [
"a3c3"
],
"description": "",
"id": "a4b4",
"lastModifiedBy": "test@paloaltonetworks.com",
"lastModifiedTs": "2023-07-18T19:27:59Z",
"name": "Read Only",
"permissionGroup": null,
"resourceListIds": [],
"resourceLists": [],
"restrictDismissalAccess": true,
"roleType": "Account Group Read Only"
}
]
}
}
Human Readable Output
Showing 3 of 14 results:
User Roles Details
Name Id Role Type dev-test a2b2 Developer Custom Read Only a3b3 Custom Read Only Read Only a4b4 Account Group Read Only
prisma-cloud-users-list
Lists all users and service accounts for your tenant. Maps to Settings > Access Control > Users in the Console UI.
Base Command
prisma-cloud-users-list
Input
| Argument Name | Description | Required |
|---|---|---|
| limit | Maximum number of entries to return. Default is 50. | Optional |
| all_results | Whether to retrieve all results. The “limit” argument will be ignored. Possible values are: true, false. | Optional |
| usernames | Usernames to return only users associated with. | Optional |
Context Output
| Path | Type | Description |
|---|---|---|
| PrismaCloud.Users.email | String | Prisma Cloud user email. |
| PrismaCloud.Users.firstName | String | User first name. |
| PrismaCloud.Users.lastName | String | User last name. |
| PrismaCloud.Users.timeZone | String | User time zone. |
| PrismaCloud.Users.enabled | Boolean | User enabled. |
| PrismaCloud.Users.lastModifiedBy | String | User last modified user. |
| PrismaCloud.Users.lastModifiedTs | Date | User last modified time. |
| PrismaCloud.Users.lastLoginTs | Date | User last login time. |
| PrismaCloud.Users.displayName | String | User display name. |
| PrismaCloud.Users.ssoBypassAllowed | Boolean | Whether SSO bypass is allowed for the user role. |
| PrismaCloud.Users.accessKeysAllowed | Boolean | Whether access keys are allowed for the user role. |
| PrismaCloud.Users.defaultRoleId | String | User default role ID. |
| PrismaCloud.Users.roleIds | Unknown | User role IDs. |
| PrismaCloud.Users.roles | Unknown | User roles. |
| PrismaCloud.Users.username | String | User username. |
| PrismaCloud.Users.type | String | User type. |
| PrismaCloud.Users.enableKeyExpiration | Boolean | Whether key expiration is enabled for the user role. |
| PrismaCloud.Users.accessKeysCount | Number | User access keys count. |
Command example
!prisma-cloud-users-list limit=2
Context Example
{
"PrismaCloud": {
"Users": [
{
"accessKeysAllowed": false,
"accessKeysCount": 0,
"defaultRoleId": "a4b4",
"displayName": "User Test",
"email": "test@paloaltonetworks.com",
"enableKeyExpiration": false,
"enabled": true,
"firstName": "User",
"lastLoginTs": "1969-12-31T23:59:59Z",
"lastModifiedBy": "admin@paloaltonetworks.com",
"lastModifiedTs": "2020-01-21T22:35:36Z",
"lastName": "Test",
"roleIds": [
"a4b4"
],
"roles": [
{
"id": "a4b4",
"name": "Read Only",
"onlyAllowCIAccess": false,
"onlyAllowComputeAccess": false,
"onlyAllowReadAccess": true,
"type": "Account Group Read Only"
}
],
"roles names": [
"Read Only"
],
"ssoBypassAllowed": false,
"timeZone": "America/New_York",
"type": "USER_ACCOUNT",
"username": "test@paloaltonetworks.com"
},
{
"accessKeysAllowed": false,
"accessKeysCount": 0,
"defaultRoleId": "a4b4",
"displayName": "User Other",
"email": "other@paloaltonetworks.com",
"enableKeyExpiration": false,
"enabled": true,
"firstName": "User",
"lastLoginTs": "2023-08-29T14:04:17Z",
"lastModifiedBy": "USER-ADD",
"lastModifiedTs": "2023-08-29T13:45:06Z",
"lastName": "Other",
"roleIds": [
"a4b4"
],
"roles": [
{
"id": "a4b4",
"name": "Read Only",
"onlyAllowCIAccess": false,
"onlyAllowComputeAccess": false,
"onlyAllowReadAccess": true,
"type": "Account Group Read Only"
}
],
"roles names": [
"Read Only"
],
"ssoBypassAllowed": false,
"timeZone": "America/New_York",
"type": "USER_ACCOUNT",
"username": "other@paloaltonetworks.com"
}
]
}
}
Human Readable Output
Showing 2 of 200 results:
Users Details
Display Name Enabled Username Type Roles Names User Test test@paloaltonetworks.com true test@paloaltonetworks.com USER_ACCOUNT Read Only User Other other@paloaltonetworks.com true other@paloaltonetworks.com USER_ACCOUNT Read Only
prisma-cloud-account-list
List accounts.
Base Command
prisma-cloud-account-list
Input
| Argument Name | Description | Required |
|---|---|---|
| exclude_account_group_details | Whether to exclude account group details. Possible values are: true, false. Default is false. | Optional |
| limit | Maximum number of entries to return. Default is 50. | Optional |
| all_results | Whether to retrieve all results. The “limit” argument will be ignored. Possible values are: true, false. | Optional |
Context Output
| Path | Type | Description |
|---|---|---|
| PrismaCloud.Account.name | String | Account name. |
| PrismaCloud.Account.cloudType | String | Account cloud type. |
| PrismaCloud.Account.accountType | String | Account type. |
| PrismaCloud.Account.enabled | Boolean | Whether the account is enabled. |
| PrismaCloud.Account.lastModifiedTs | Date | Account last modified time. |
| PrismaCloud.Account.storageScanEnabled | Boolean | Whether account storage scan is enabled. |
| PrismaCloud.Account.protectionMode | String | Account protection mode. |
| PrismaCloud.Account.ingestionMode | Number | Account ingestion mode. |
| PrismaCloud.Account.deploymentType | String | Account deployment type. |
| PrismaCloud.Account.groupIds | Unknown | Account group IDs. |
| PrismaCloud.Account.groups | Unknown | Account groups. |
| PrismaCloud.Account.status | String | Account status. |
| PrismaCloud.Account.numberOfChildAccounts | Number | The number of child accounts. |
| PrismaCloud.Account.accountId | String | Account ID. |
| PrismaCloud.Account.addedOn | Date | Account added on time. |
Command example
!prisma-cloud-account-list limit=1
Context Example
{
"PrismaCloud": {
"Account": [
{
"accountId": "777777777777",
"accountType": "organization",
"addedOn": "2022-10-06T04:06:41Z",
"cloudAccountOwner": "mail1@gmail.com",
"cloudAccountOwnerCount": 1,
"cloudType": "aws",
"deploymentType": "aws",
"enabled": true,
"groupIds": [
"group2"
],
"groups": [
{
"id": "group2",
"name": "Adi"
}
],
"ingestionMode": 7,
"lastModifiedBy": "example@example.com",
"lastModifiedTs": "2022-10-06T12:48:42Z",
"name": "aws-Adi-train",
"numberOfChildAccounts": 4,
"protectionMode": "MONITOR_AND_PROTECT",
"status": "warning",
"storageScanEnabled": false
}
]
}
}
Human Readable Output
Showing 1 of 19 results:
Accounts Details
Account Id Name Cloud Type Account Type Enabled Added On Last Modified Ts Last Modified By Storage Scan Enabled Protection Mode Ingestion Mode Deployment Type Status 777777777777 aws-Adi-train aws organization true 2022-10-06T04:06:41Z 2022-10-06T12:48:42Z example@example.com false MONITOR_AND_PROTECT 7 aws warning
prisma-cloud-account-status-get
Get the statuses of the provided accounts.
Base Command
prisma-cloud-account-status-get
Input
| Argument Name | Description | Required |
|---|---|---|
| account_ids | A comma-separated list of accound IDs. To get account IDs, run the “prisma-cloud-account-list” command. | Required |
Context Output
| Path | Type | Description |
|---|---|---|
| PrismaCloud.Account.accountId | String | Account ID. |
| PrismaCloud.Account.name | String | Account name. |
| PrismaCloud.Account.status | String | Account status. |
| PrismaCloud.Account.message | String | Account message. |
| PrismaCloud.Account.remediation | String | Account remediation action. |
Command example
!prisma-cloud-account-status-get account_ids=111111111111
Context Example
{
"PrismaCloud": {
"Account": {
"accountId": "111111111111",
"message": "",
"name": "Config",
"remediation": "",
"status": "ok",
"subComponents": []
}
}
}
Human Readable Output
Accounts Status Details
Account Id Name Status 111111111111 Config ok
prisma-cloud-account-owner-list
Get the owners of the provided accounts.
Base Command
prisma-cloud-account-owner-list
Input
| Argument Name | Description | Required |
|---|---|---|
| account_ids | A comma-separated list of account IDs. To get account IDs, run the “prisma-cloud-account-list” command. | Required |
Context Output
| Path | Type | Description |
|---|---|---|
| PrismaCloud.Account.accountId | String | Account ID. |
| PrismaCloud.Account.emails | Unknown | Account owner emails. |
Command example
!prisma-cloud-account-owner-list account_ids=888888888888888888888888888888888888,111111111111
Context Example
{
"PrismaCloud": {
"Account": [
{
"accountId": "888888888888888888888888888888888888",
"emails": [
"name@company.com"
]
},
{
"accountId": "111111111111",
"emails": []
}
]
}
}
Human Readable Output
Accounts Owner Details
Account Id Emails 888888888888888888888888888888888888 name@company.com 111111111111
prisma-cloud-host-finding-list
Get resource host finding list.
Base Command
prisma-cloud-host-finding-list
Input
| Argument Name | Description | Required |
|---|---|---|
| rrn | Restricted Resource Name of the resource to get host finding of. Can be retrieved by running a command that has that RRN. | Required |
| finding_types | Comma separated list of finding types to look for. Available options are: guard_duty_host, guard_duty_iam, inspector_sbp, compliance_cis, host_vulnerability_cve. When left empty, will return all options. | Optional |
| risk_factors | Comma separated list of risk factors to look for. Available options are: CRITICAL_SEVERITY, HIGH_SEVERITY, MEDIUM_SEVERITY, HAS_FIX, REMOTE_EXECUTION, DOS, RECENT_VULNERABILITY, EXPLOIT_EXISTS, ATTACK_COMPLEXITY_LOW, ATTACK_VECTOR_NETWORK, REACHABLE_FROM_THE_INTERNET, LISTENING_PORTS, CONTAINER_IS_RUNNING_AS_ROOT, NO_MANDATORY_SECURITY_PROFILE_APPLIED, RUNNING_AS_PRIVILEGED_CONTAINER, PACKAGE_IN_USE. When left empty, will return all options. | Optional |
| limit | Maximum number of entries to return. Default is 50. | Optional |
| all_results | Whether to retrieve all results. The “limit” argument will be ignored. Possible values are: true, false. | Optional |
Context Output
| Path | Type | Description |
|---|---|---|
| PrismaCloud.HostFinding.accountId | String | Host finding account ID. |
| PrismaCloud.HostFinding.regionId | String | Host finding region ID. |
| PrismaCloud.HostFinding.findingId | String | Host finding ID. |
| PrismaCloud.HostFinding.type | String | Host finding type. |
| PrismaCloud.HostFinding.source | String | Host finding source. |
| PrismaCloud.HostFinding.severity | String | Host finding severity. |
| PrismaCloud.HostFinding.status | String | Host finding status. |
| PrismaCloud.HostFinding.createdOn | Date | The date on which the host finding was created. |
| PrismaCloud.HostFinding.updatedOn | Date | The date on which the host finding was updated. |
| PrismaCloud.HostFinding.normalizedNames | Unknown | Host finding normalized names. |
| PrismaCloud.HostFinding.scanId | String | Host finding scan ID. |
| PrismaCloud.HostFinding.resourceCloudId | String | Host finding resource cloud ID. |
| PrismaCloud.HostFinding.sourceData.accountId | String | Host finding source data account ID. |
| PrismaCloud.HostFinding.sourceData.arn | String | Host finding source data ARN. |
| PrismaCloud.HostFinding.title | String | Host finding title. |
| PrismaCloud.HostFinding.description | String | Host finding description. |
| PrismaCloud.HostFinding.resourceUrl | String | Host finding resource URL. |
| PrismaCloud.HostFinding.rlUpdatedOn | Date | The date on which the RL was updated. |
| PrismaCloud.HostFinding.externalFindingId | String | External finding ID. |
| PrismaCloud.HostFinding.sourceData | Unknown | Host finding source data. |
| PrismaCloud.HostFinding.score | String | Host finding score. |
| PrismaCloud.HostFinding.count | Number | The number of host findings. |
Command example
!prisma-cloud-host-finding-list rrn=rrn::name:place:111:a1b2:a%3Ajj55-2023-01-29-09-25 finding_types=guard_duty_host,guard_duty_iam limit=2
Context Example
{
"PrismaCloud": {
"HostFinding": {
"accountId": "555555555555",
"count": "5",
"createdOn": "2023-01-03T16:13:25Z",
"description": "35.180.1.1 is performing SSH brute force attacks against i-44444444444444444. Brute force attacks are used to gain unauthorized access to your instance by guessing the SSH password.",
"externalFindingId": 999999,
"findingId": "findingid3",
"normalizedNames": [
"UnauthorizedAccess:EC2/SSHBruteForce"
],
"regionId": "us-east-1",
"resourceCloudId": "i-44444444444444444",
"resourceUrl": "https://some-url?#/findings?search=id%3D66666666666666666666666666666666",
"rlUpdatedOn": "2023-02-16T16:27:26Z",
"scanId": "scan-id-5",
"score": "N/A",
"severity": "low",
"source": "guardduty",
"sourceData": {
"accountId": "555555555555",
"arn": "arn:aws:trail:us-west-1:888888888888:trail/control",
"createdAt": "2023-01-03T16:13:25.421Z",
"description": "35.180.1.1 is performing SSH brute force attacks against i-44444444444444444. Brute force attacks are used to gain unauthorized access to your instance by guessing the SSH password.",
"id": "66666666666666666666666666666666",
"partition": "aws",
"region": "us-east-1",
"resource": {
"instanceDetails": {
"availabilityZone": "us-east-1a",
"iamInstanceProfile": {
"arn": "arn:aws:trail:us-west-1:888888888888:trail/control",
"id": "A2"
},
"imageDescription": "Amazon Linux AMI 2.0.20222202 x86_64 ECS HVM GP2",
"imageId": "ami-2",
"instanceId": "i-44444444444444444",
"instanceState": "running",
"instanceType": "t2.xlarge",
"launchTime": "2022-12-13T01:29:18.000Z",
"networkInterfaces": [
{
"ipv6Addresses": [],
"networkInterfaceId": "eni-1",
"privateDnsName": "ip-1-1-1-1.ec2.internal",
"privateIpAddress": "1.1.1.1",
"privateIpAddresses": [
{
"privateDnsName": "ip-1-1-1-1.ec2.internal",
"privateIpAddress": "1.1.1.1"
}
],
"publicDnsName": "ec2-5.compute-1.amazonaws.com",
"publicIp": "1.1.1.1",
"sgs": [
{
"groupId": "sg-000",
"groupName": "security-group"
}
],
"subnetId": "subnet-0",
"vpcId": "vpc-01"
}
],
"productCodes": [],
"tags": [
{
"key": "aws:autoscaling:groupName",
"value": "pc-infra-autoscaling"
}
]
},
"resourceType": "Instance"
},
"schemaVersion": "2.0",
"service": {
"action": {
"actionType": "NETWORK_CONNECTION",
"networkConnectionAction": {
"blocked": false,
"connectionDirection": "INBOUND",
"localIpDetails": {
"ipAddressV4": "1.1.1.1"
},
"localPortDetails": {
"port": 22,
"portName": "SSH"
},
"protocol": "TCP",
"remoteIpDetails": {
"city": {
"cityName": "George Town"
},
"country": {
"countryName": "Malaysia"
},
"geoLocation": {
"lat": 5.4244,
"lon": 100.333
},
"ipAddressV4": "35.180.1.1",
"organization": {
"asn": "9999",
"asnOrg": "TIME",
"isp": "TIME",
"org": "TIME"
}
},
"remotePortDetails": {
"port": 33333,
"portName": "Unknown"
}
}
},
"additionalInfo": {
"type": "default",
"value": "{}"
},
"archived": false,
"count": 5,
"detectorId": "scan-id-5",
"eventFirstSeen": "2023-01-03T15:56:55.000Z",
"eventLastSeen": "2023-02-16T15:53:32.000Z",
"resourceRole": "TARGET",
"serviceName": "guardduty"
},
"severity": 2,
"title": "35.180.1.1 is performing SSH brute force attacks against i-44444444444444444.",
"type": "UnauthorizedAccess:EC2/SSHBruteForce",
"updatedAt": "2023-02-16T16:01:36.608Z"
},
"status": "open",
"title": "35.180.1.1 is performing SSH brute force attacks against i-44444444444444444.",
"type": "guard_duty_host",
"updatedOn": "2023-02-16T16:01:36Z"
}
}
}
Human Readable Output
Showing 1 of 1 results:
Host Finding Details
Account Id Region Id Finding Id Type Source Severity Status Created On Updated On Normalized Names Scan Id Resource Cloud Id Source Data Account ID ARN Title Description Resource Url 555555555555 us-east-1 66666666666666666666666666666666 guard_duty_host guardduty low open 2023-01-03T16:13:25Z 2023-02-16T16:01:36Z UnauthorizedAccess:EC2/SSHBruteForce scan-id-5 i-44444444444444444 555555555555 arn:aws:trail:us-west-1:888888888888:trail/control 35.180.1.1 is performing SSH brute force attacks against i-44444444444444444. 35.180.1.1 is performing SSH brute force attacks against i-44444444444444444. Brute force attacks are used to gain unauthorized access to your instance by guessing the SSH password. https://some_url?#/findings?search=id%3D66666666666666666666666666666666
prisma-cloud-permission-list
Get permission list. You must provide either “query” or “next_token”.
Base Command
prisma-cloud-permission-list
Input
| Argument Name | Description | Required |
|---|---|---|
| user_id | User ID to look for. Must be provided with the “query” argument. | Optional |
| query | IAM query to run in Prisma Cloud config API using RQL language. For more information see: https://docs.paloaltonetworks.com/prisma/prisma-cloud/prisma-cloud-rql-reference/rql-reference/iam-query. | Optional |
| limit | Maximum number of entries to return. Default is 50. | Optional |
| next_token | Token of the next page to retrive. | Optional |
Context Output
| Path | Type | Description |
|---|---|---|
| PrismaCloud.PermissionPageToken.nextPageToken | String | Next page token. |
| PrismaCloud.Permission.id | String | Permission ID. |
| PrismaCloud.Permission.sourceCloudType | String | Permission source cloud type. |
| PrismaCloud.Permission.sourceCloudAccount | String | Permission source cloud account. |
| PrismaCloud.Permission.sourceResourceId | String | Permission source resource ID. |
| PrismaCloud.Permission.destCloudType | String | Permission destination cloud type. |
| PrismaCloud.Permission.destCloudServiceName | String | Permission destination cloud service name. |
| PrismaCloud.Permission.destResourceType | String | Permission destination resource type. |
| PrismaCloud.Permission.effectiveActionName | String | Permission effective action name. |
| PrismaCloud.Permission.grantedByCloudType | String | Permission granted by cloud type. |
| PrismaCloud.Permission.grantedByCloudPolicyId | String | Permission granted by cloud policy ID. |
| PrismaCloud.Permission.grantedByCloudPolicyName | String | Permission granted by cloud policy name. |
| PrismaCloud.Permission.grantedByCloudPolicyType | String | Permission granted by cloud policy type. |
| PrismaCloud.Permission.grantedByCloudPolicyRrn | String | Permission granted by cloud policy restricted resource name. |
| PrismaCloud.Permission.grantedByCloudEntityId | String | Permission granted by cloud entity ID. |
| PrismaCloud.Permission.grantedByCloudEntityName | String | Permission granted by cloud entity name. |
| PrismaCloud.Permission.grantedByCloudEntityRrn | String | Permission granted by cloud entity restricted resource name. |
| PrismaCloud.Permission.sourcePublic | Boolean | Whether the permission source is public. |
| PrismaCloud.Permission.sourceCloudRegion | String | Permission source cloud region. |
| PrismaCloud.Permission.sourceCloudServiceName | String | Permission source cloud service name. |
| PrismaCloud.Permission.sourceResourceName | String | Permission source resource name. |
| PrismaCloud.Permission.sourceResourceType | String | Permission source resource type. |
| PrismaCloud.Permission.sourceIdpService | String | Permission source IDP service. |
| PrismaCloud.Permission.sourceIdpDomain | String | Permission source IDP domain. |
| PrismaCloud.Permission.sourceIdpEmail | String | Permission source IDP email. |
| PrismaCloud.Permission.sourceIdpUsername | String | Permission source IDP username. |
| PrismaCloud.Permission.sourceIdpGroup | String | Permission source IDP group. |
| PrismaCloud.Permission.sourceIdpRrn | String | Permission source IDP restricted resource name. |
| PrismaCloud.Permission.sourceCloudResourceRrn | String | Permission source cloud resource restricted resource name. |
| PrismaCloud.Permission.destCloudAccount | String | Permission destination cloud account. |
| PrismaCloud.Permission.destCloudRegion | String | Permission destination cloud region. |
| PrismaCloud.Permission.destResourceName | String | Permission destination resource name. |
| PrismaCloud.Permission.destResourceId | String | Permission destination resource ID. |
| PrismaCloud.Permission.destCloudResourceRrn | String | Permission destination cloud resource restricted resource name. |
| PrismaCloud.Permission.grantedByCloudEntityType | String | Permission granted by cloud entity type. |
| PrismaCloud.Permission.accessedResourcesCount | String | Permission accessed resources count. |
| PrismaCloud.Permission.lastAccessDate | String | Permission last access date. |
| PrismaCloud.Permission.lastAccessStatus | String | Permission last access status. |
| PrismaCloud.Permission.isWildCardDestCloudResourceName | Boolean | Whether the destination cloud resource name is a wildcard. |
| PrismaCloud.Permission.exceptions | Unknown | Permission exceptions. |
| PrismaCloud.Permission.grantedByLevelType | String | Permission granted by level type. |
| PrismaCloud.Permission.grantedByLevelId | String | Permission granted by level ID. |
| PrismaCloud.Permission.grantedByLevelName | String | Permission granted by level name. |
| PrismaCloud.Permission.grantedByLevelRrn | String | Permission granted by level restricted resource name. |
Command example
!prisma-cloud-permission-list query="config from iam where source.cloud.service.name = 'EC2'" limit=2
Context Example
{
"PrismaCloud": {
"Permission": [
{
"accessedResourcesCount": null,
"destCloudAccount": "AWS-JLo",
"destCloudRegion": "*",
"destCloudResourceRrn": null,
"destCloudServiceName": "ec2",
"destCloudType": "AWS",
"destResourceId": "*",
"destResourceName": "*",
"destResourceType": "instance",
"effectiveActionName": "ssm:UpdateInstanceInformation",
"exceptions": [
{
"messageCode": "CLOUD_EVENT_NOT_SUPPORTED"
},
{
"messageCode": "AWS_ROOT_ACCOUNT_IS_NOT_ONBOARDED"
}
],
"grantedByCloudEntityId": "arn:aws:trail:us-west-1:888888888888:trail/control",
"grantedByCloudEntityName": "service-role/AWSCloud9SSMAccessRole",
"grantedByCloudEntityRrn": "rrn::name:place:111:a1b2:a%3Ajj55-2023-01-29-09-25",
"grantedByCloudEntityType": "role",
"grantedByCloudPolicyId": "arn:aws:arn:aws:trail:us-west-1:888888888888:trail/control",
"grantedByCloudPolicyName": "AWSCloud9SSMInstanceProfile",
"grantedByCloudPolicyRrn": "rrn::name:place:111:a1b2:a%3Ajj55-2023-01-29-09-25",
"grantedByCloudPolicyType": "AWS Managed Policy",
"grantedByCloudType": "AWS",
"grantedByLevelId": null,
"grantedByLevelName": null,
"grantedByLevelRrn": null,
"grantedByLevelType": "",
"id": "jjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjj",
"isWildCardDestCloudResourceName": true,
"lastAccessDate": null,
"lastAccessStatus": "NOT_AVAILABLE",
"sourceCloudAccount": "AWS-JLo",
"sourceCloudRegion": "AWS Oregon",
"sourceCloudResourceRrn": "rrn::name:place:111:a1b2:a%3Ajj55-2023-01-29-09-25",
"sourceCloudServiceName": "ec2",
"sourceCloudType": "AWS",
"sourceIdpDomain": null,
"sourceIdpEmail": null,
"sourceIdpGroup": null,
"sourceIdpRrn": null,
"sourceIdpService": null,
"sourceIdpUsername": null,
"sourcePublic": false,
"sourceResourceId": "arn:aws:trail:us-west-1:888888888888:trail/control",
"sourceResourceName": "i-33333333333333333",
"sourceResourceType": "instance"
},
{
"accessedResourcesCount": null,
"destCloudAccount": "AWS-JLo",
"destCloudRegion": "*",
"destCloudResourceRrn": null,
"destCloudServiceName": "ssm",
"destCloudType": "AWS",
"destResourceId": "*",
"destResourceName": "*",
"destResourceType": "managed-instance",
"effectiveActionName": "ssm:UpdateInstanceInformation",
"exceptions": [
{
"messageCode": "CLOUD_EVENT_NOT_SUPPORTED"
},
{
"messageCode": "AWS_ROOT_ACCOUNT_IS_NOT_ONBOARDED"
}
],
"grantedByCloudEntityId": "arn:aws:arn:aws:trail:us-west-1:888888888888:trail/control",
"grantedByCloudEntityName": "service-role/AWSCloud9SSMAccessRole",
"grantedByCloudEntityRrn": "rrn::name:place:111:a1b2:a%3Ajj55-2023-01-29-09-25",
"grantedByCloudEntityType": "role",
"grantedByCloudPolicyId": "arn:aws:trail:us-west-1:888888888888:trail/control",
"grantedByCloudPolicyName": "AWSCloud9SSMInstanceProfile",
"grantedByCloudPolicyRrn": "rrn::name:place:111:a1b2:a%3Ajj55-2023-01-29-09-25",
"grantedByCloudPolicyType": "AWS Managed Policy",
"grantedByCloudType": "AWS",
"grantedByLevelId": null,
"grantedByLevelName": null,
"grantedByLevelRrn": null,
"grantedByLevelType": "",
"id": "kkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkk",
"isWildCardDestCloudResourceName": true,
"lastAccessDate": null,
"lastAccessStatus": "NOT_AVAILABLE",
"sourceCloudAccount": "AWS-JLo",
"sourceCloudRegion": "AWS Oregon",
"sourceCloudResourceRrn": "rrn::name:place:111:a1b2:a%3Ajj55-2023-01-29-09-25",
"sourceCloudServiceName": "ec2",
"sourceCloudType": "AWS",
"sourceIdpDomain": null,
"sourceIdpEmail": null,
"sourceIdpGroup": null,
"sourceIdpRrn": null,
"sourceIdpService": null,
"sourceIdpUsername": null,
"sourcePublic": false,
"sourceResourceId": "arn:aws:trail:us-west-1:888888888888:trail/control",
"sourceResourceName": "i-33333333333333333",
"sourceResourceType": "instance"
}
],
"PermissionPageToken": {
"nextPageToken": "token2"
}
}
}
Human Readable Output
Showing 2 of 20261 results:
Permissions Details
Id Source Cloud Type Source Cloud Account Source Resource Id Destination Cloud Type Destination Cloud Service Name Destination Resource Type Effective Action Name Granted By Cloud Type Granted By Cloud Policy Id Granted By Cloud Policy Name Granted By Cloud Policy Type Granted By Cloud Policy Rrn Granted By Cloud Entity Id Granted By Cloud Entity Name Granted By Cloud Entity Rrn jjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjj AWS AWS-JLo arn:aws:trail:us-west-1:888888888888:trail/control AWS ec2 instance ssm:UpdateInstanceInformation AWS arn:aws:trail:us-west-1:888888888888:trail/control AWSCloud9SSMInstanceProfile AWS Managed Policy rrn::name:place:111:a1b2:a%3Ajj55-2023-01-29-09-25 arn:aws:iam::555555555555:role/service-role/AWSCloud9SSMAccessRole service-role/AWSCloud9SSMAccessRole rrn::name:place:111:a1b2:a%3Ajj55-2023-01-29-09-25 kkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkk AWS AWS-JLo arn:aws:trail:us-west-1:888888888888:trail/control AWS ssm managed-instance ssm:UpdateInstanceInformation AWS arn:aws:trail:us-west-1:888888888888:trail/control AWSCloud9SSMInstanceProfile AWS Managed Policy rrn::name:place:111:a1b2:a%3Ajj55-2023-01-29-09-25 arn:aws:iam::555555555555:role/service-role/AWSCloud9SSMAccessRole service-role/AWSCloud9SSMAccessRole rrn::name:place:111:a1b2:a%3Ajj55-2023-01-29-09-25 Next Page Token
token2
Access Keys
Access keys are a secure way to enable programmatic access to the Prisma Cloud API. By default, only the System Admin has API access and can enable API access for other administrators. If you have API access, you can create up to two access keys.
A service account is a special Prisma Cloud identity used to access Prisma Cloud programmatically via API.
To create a service account, see Add Service Accounts On Prisma Cloud
Base Command
prisma-cloud-access-key-create
Input
| Argument Name | Description | Required |
|---|---|---|
| name | Access key name. | Required |
| expires-on | Timestamp in milliseconds when access key expires. Default:0. | Optional |
Context Output
| Path | Type | Description |
|---|---|---|
| PrismaCloud.AccessKeys.id | String | Access key ID. |
| PrismaCloud.AccessKeys.secretKey | String | Access key secret. |
Command example
!prisma-cloud-access-key-create name=MyNewKey
Context Example
{
"PrismaCloud": {
"AccessKeys": [
{
"Id": "Id",
"Secret Key": "Secret Key"
}
]
}
}
prisma-cloud-access-keys-list
Input
| Argument Name | Description | Required |
|---|---|---|
| access-key | Returns the metadata of the access key that has the specified ID. | Optional |
| limit | Maximum number of entries to return. | Optional |
Context Output
| Path | Type | Description |
|---|---|---|
| PrismaCloud.AccessKeys.id | String | Access key ID. |
| PrismaCloud.AccessKeys.name | String | The name of the access key. |
| PrismaCloud.AccessKeys.createdBy | String | The user who created the access key. |
| PrismaCloud.AccessKeys.createdTs | String | Time access key was created. |
| PrismaCloud.AccessKeys.expiresOn | String | The time the access key expires. |
| PrismaCloud.AccessKeys.lastUsedTime | String | The last time the access key was used. |
| PrismaCloud.AccessKeys.status | String | Access key status. |
| PrismaCloud.AccessKeys.role.id | String | User role ID. |
| PrismaCloud.AccessKeys.role.name | String | User role name. |
| PrismaCloud.AccessKeys.roleType | String | User role permission type. |
| PrismaCloud.AccessKeys.username | String | Access key user name. |
Command example
!prisma-cloud-access-keys-list limit=2
Context Example
{
"PrismaCloud": {
"AccessKeys": [
{
"id": "string",
"name": "string",
"createdBy": "string",
"createdTs": "number",
"lastUsedTime": "number",
"status": "string",
"expiresOn": "number",
"role": {
"id": "string",
"name": "string"
},
"roleType": "string",
"username": "string"
},
{
"id": "string",
"name": "string",
"createdBy": "string",
"createdTs": "number",
"lastUsedTime": "number",
"status": "string",
"expiresOn": "number",
"role": {
"id": "string",
"name": "string"
},
"roleType": "string",
"username": "string"
}
]
}
}
prisma-cloud-access-key-disable
Input
| Argument Name | Description | Required |
|---|---|---|
| access-key | Access key ID. | Required |
Command example
!prisma-cloud-access-key-disable access-key=id
Human Readable Output
Access key mockmock-mock-mock-mock-mockmockmock was disabled successfully
prisma-cloud-access-key-enable
Input
| Argument Name | Description | Required |
|---|---|---|
| access-key | Access key ID. | Required |
Command example
!prisma-cloud-access-key-enable access-key=id
Human Readable Output
Access key mockmock-mock-mock-mock-mockmockmock was enabled successfully
prisma-cloud-access-key-delete
Input
| Argument Name | Description | Required |
|---|---|---|
| access-key | Access key ID. | Required |
Command example
!prisma-cloud-access-key-delete access-key=id
Human Readable Output
Access key mockmock-mock-mock-mock-mockmockmock was successfully deleted successfully
Breaking changes from the previous version of this integration - Prisma Cloud v2
The following sections list the changes in this version.
Commands
The following commands were deprecated in this version because they are not supported by the API anymore
- redlock-list-scans
- redlock-get-scan-status**
- redlock-get-scan-results
The following commands were replaced in this version
- redlock-dismiss-alerts - this command is replaced by prisma-cloud-alert-dismiss.
- redlock-get-alert-details - this command is replaced by prisma-cloud-alert-get-details.
- redlock-get-remediation-details - this command is replaced by prisma-cloud-remediation-command-list.
- redlock-get-rql-response - this command is replaced by prisma-cloud-config-search.
- redlock-list-alert-filters - this command is replaced by prisma-cloud-alert-filter-list.
- redlock-reopen-alerts - this command is replaced by prisma-cloud-alert-reopen.
- redlock-search-alerts - this command is replaced by prisma-cloud-alert-search.
- redlock-search-config - this command is replaced by prisma-cloud-config-search.
- redlock-search-event - this command is replaced by prisma-cloud-event-search.
- redlock-search-network - this command is replaced by prisma-cloud-network-search.
Additional Considerations for this version
- “Risk detail” was removed from all commands because it is not supported by the API anymore.
- Commands from the previous version were kept in order to make to transition from v1 to v2 easy for existing playbooks. We encourage to use the new version of each command.
prisma-cloud-code-issues-list
Retrieves the code errors detected by Application Security during periodic scans.
Base Command
prisma-cloud-code-issues-list
Input
| Argument Name | Description | Required |
|---|---|---|
| git_users | Comma-separated list of names of Git users. | Optional |
| branch | A branch name. | Optional |
| code_categories | Comma-separated list of code issue categories. Is also available as a search criteria (search_scopes). Possible values are: IacMisconfiguration, IacExternalModule, ImageReferencerVul, ImageReferencerLicenses, Vulnerabilities, Licenses, Secrets. | Optional |
| iac_categories | Comma-separated list of categories related to Infrastructure-as-Code (IaC) issues. Possible values are: IAM, Monitoring, Networking, Kubernetes, General, Storage, Public, Drift, Compute. | Optional |
| iac_labels | Comma-separated list of labels associated with Infrastructure-as-Code (IaC). Possible values are: CustomPolicy, HasFix. | Optional |
| file_types | Comma-separated list of file types. Possible values are: yml, yaml, json, template, py, js, properties, pem, php, xml, ts, env, Dockerfile, java, rb, sum, mod, cs, txt, bicep, hcl, gradle, kts, lock, config, csproj, dependencies. | Optional |
| fixable_only | Whether to retrieve only fixable issues. Recommended to use this argument with another argument code_categories ,for example. Possible values are: true, false. | Optional |
| repositories | Comma-separated list of repository names. | Optional |
| secrets_risk_factors | Comma-separated list of risk factors related to secrets. Possible values are: PublicRepository, PrivateRepository, User, Privileged, Valid, Invalid, Unknown, FoundInHistory. | Optional |
| search_scopes | Comma-separated list of specific areas or categories within which to search. When specifying search_scopes, search_term argument is required. Possible values are: IacMisconfiguration, IacExternalModule, ImageReferencerVul, ImageReferencerLicenses, Vulnerabilities, Licenses, Secrets. |
Optional |
| severities | Comma-separated list of the criticality of issues. Possible values are: INFO, LOW, MEDIUM, HIGH, CRITICAL. | Optional |
| vulnerability_risk_factors | Comma-separated list of risk factors for vulnerabilities. Possible values are: AttackComplexity, AttackVector, DoS, HasFix, RemoteExecution, ExploitInTheWild, ExploitPOC, IsUsed. | Optional |
| search_term | A keyword or phrase used to narrow down results within specific scopes (like a particular vulnerability). It’s needed if you are filtering results by search_scopes. | Optional |
| iac_tags | An infrastructure-as-code (IaC) resource. Relevant only to- IacMisconfiguration,Vulnerabilities. | Optional |
| license_type | Comma-separated list of license types. | Optional |
| check_status | Status of checks. Possible values are: Error, Passed, Suppressed, FixPendin. | Optional |
| limit | The limit of issues to retrieve. Default is 50. | Optional |
Context Output
| Path | Type | Description |
|---|---|---|
| PrismaCloud.CodeIssue.modifiedOn | String | The date and time when the code issue was last modified. |
| PrismaCloud.CodeIssue.isPublic | String | Indicates whether the repository or resource is publicly accessible (true/false). |
| PrismaCloud.CodeIssue.fileType | String | The type of file where the issue was detected (e.g., `.js`, `.py`). |
| PrismaCloud.CodeIssue.secretCommitRemove | String | The commit identifier where a secret was removed. |
| PrismaCloud.CodeIssue.secretCommitAdd | String | The commit identifier where a secret was added. |
| PrismaCloud.CodeIssue.gitUser | String | The username of the person who made the commit associated with the code issue. |
| PrismaCloud.CodeIssue.codePath | String | The path to the code file where the issue was detected. |
| PrismaCloud.CodeIssue.codeCategory | String | The category or classification of the detected issue (e.g., security, compliance). |
| PrismaCloud.CodeIssue.author | String | The original author of the code where the issue was detected. |
| PrismaCloud.CodeIssue.repositoryUuid | String | The unique identifier of the repository where the issue was found. |
| PrismaCloud.CodeIssue.path | String | The path in the repository where the issue was detected. |
| PrismaCloud.CodeIssue.repositorySource | String | The source of the repository (e.g., GitHub, Bitbucket). |
| PrismaCloud.CodeIssue.firstDetected | String | The date and time when the code issue was first detected. |
| PrismaCloud.CodeIssue.codeIssueLine | String | The line number in the code where the issue was detected. |
| PrismaCloud.CodeIssue.labels | String | Labels associated with the code issue for classification or categorization. |
| PrismaCloud.CodeIssue.labels.label | String | A specific label related to the code issue. |
| PrismaCloud.CodeIssue.labels.metadata.imageName | String | The name of the image associated with the label metadata. |
| PrismaCloud.CodeIssue.policy | String | The policy that was violated by the detected issue. |
| PrismaCloud.CodeIssue.repository | String | The name of the repository where the issue was found. |
| PrismaCloud.CodeIssue.resourceName | String | The name of the resource associated with the code issue. |
| PrismaCloud.CodeIssue.resourceScanType | String | The type of scan that detected the issue (e.g., static analysis, secret detection). |
| PrismaCloud.CodeIssue.resourceUuid | String | The unique identifier of the resource associated with the code issue. |
| PrismaCloud.CodeIssue.severity | String | The severity level of the detected issue (e.g., High, Medium, Low). |
| PrismaCloud.CodeIssue.violationId | String | The unique identifier for the policy violation related to the code issue. |
| PrismaCloud.CodeIssue.causePackageId | String | The ID of the package that caused the issue. |
| PrismaCloud.CodeIssue.causePackageName | String | The name of the package that caused the issue. |
| PrismaCloud.CodeIssue.cveUuid | String | The unique identifier of the Common Vulnerabilities and Exposures (CVE) related to the issue. |
| PrismaCloud.CodeIssue.cvss | String | The Common Vulnerability Scoring System (CVSS) score for the detected issue. |
| PrismaCloud.CodeIssue.fixVersion | String | The version of the code or package that contains the fix for the issue. |
| PrismaCloud.CodeIssue.pr | String | The pull request (PR) associated with resolving the code issue. |
| PrismaCloud.CodeIssue.resourceId | String | The identifier of the resource related to the code issue. |
| PrismaCloud.CodeIssue.riskFactors | String | Risk factors associated with the code issue, such as high-impact areas or sensitive data. |
| PrismaCloud.CodeIssue.isIndirectPackage | String | Indicates whether the issue is from an indirect package (true/false). |
prisma-cloud-asset-alerts-get
Returns detailed information for the asset alerts with the given ID.
Base Command
prisma-cloud-asset-alerts-get
Input
| Argument Name | Description | Required |
|---|---|---|
| asset_id | Unified asset ID or RRN (Restricted Resource Name). | Required |
| finding_type | External finding types. Possible values are: COMPLIANCE_CIS, GUARD_DUTY_HOST, GUARD_DUTY_IAM, INSPECTOR_RBA, INSPECTOR_SBP, NETWORK_REACHABILITY, AZURE_SECURITY_CENTER_ALERTS, UNCLASSIFIED, COMMAND_AND_CONTROL, CREDENTIAL_ACCESS, CROSS_ACCOUNT_TRUST, DATA_EXFILTRATION, DEFENSE_EVASION, DISCOVERY, HIGH_PRIVILEGED_ROLE, INITIAL_ACCESS, INTERNET_EXPOSURE, KEYS_AND_SECRETS, LATERAL_MOVEMENT, MALWARE, MFA, MISCONFIGURATION, NETWORK_ANOMALY, PRIVILEGE_ESCALATION, RECONNAISSANCE, RESOURCE_HIJACKING, SSH_BRUTE_FORCE, UNAUTHORIZED_ACCESS, UNENCRYPTED_DATA, UNUSED_PRIVILEGES, USER_ANOMALY, WEAK_PASSWORD, SENSITIVE_DATA_EXPOSURE, INJECTIONS, VULNERABILITY_SCANNING, SHELLSHOCK, KNOWN_BOTS, UNKNOWN_BOTS, VIRTUAL_PATCHES, WEB_ATTACK, BOT_ACTIVITY, WEB_SCRAPING, CUSTOM, VULNERABILITY, HOST_VULNERABILITY_CVE, CONTAINER_IMAGE_VULNERABILITY_CVE, VIRTUAL_IMAGE_VULNERABILITY_CVE, SERVERLESS_VULNERABILITY, PACKAGE_VULNERABILITY. | Optional |
| risk_factors | Comma-separated list of external finding risk factors. Possible values are: CRITICAL_SEVERITY, HIGH_SEVERITY, MEDIUM_SEVERITY, HAS_FIX, REMOTE_EXECUTION, DOS, RECENT_VULNERABILITY, EXPLOIT_EXISTS, ATTACK_COMPLEXITY_LOW, ATTACK_VECTOR_NETWORK, REACHABLE_FROM_THE_INTERNET, LISTENING_PORTS, CONTAINER_IS_RUNNING_AS_ROOT, NO_MANDATORY_SECURITY_PROFILE_APPLIED, RUNNING_AS_PRIVILEGED_CONTAINER, PACKAGE_IN_USE, DOS_LOW, DOS_HIGH, EXPLOIT_EXISTS_IN_THE_WILD, EXPLOIT_EXISTS_POC, SENSITIVE_INFORMATION, ROOT_MOUNT, RUNTIME_SOCKET, HOST_ACCESS. | Optional |
| timeline_item_id | Timeline item ID. | Optional |
| alert_ids | Comma-separated list of alert IDs. | Optional |
| limit | Limit number of records. | Optional |
| permission_type | Permissions type. | Optional |
| page_token | Next page token. | Optional |
| prisma_cloud_findings_only | Filter Hyperion findings. Possible values are: true, false. | Optional |
| vulnerability_info_type_id | CVE ID, package ID, or layer ID. The value needs to be fetched from one of the group by API calls. | Optional |
| vulnerability_info_type | Supported vulnerability types. Possible values are: CVE, PACKAGE, LAYER. | Optional |
Context Output
| Path | Type | Description |
|---|---|---|
| PrismaCloud.AssetAlerts.problem.title | String | The title of the problem. |
| PrismaCloud.AssetAlerts.problem.status.statusCode | Number | The status code of the problem. |
| PrismaCloud.AssetAlerts.problem.status.reasonPhrase | String | The reason for the problem. |
| PrismaCloud.AssetAlerts.problem.detail | String | The details of the problem. |
| PrismaCloud.AssetAlerts.problem.instance | String | The instance of the problem. |
| PrismaCloud.AssetAlerts.problem.type | String | The type of the problem. |
| PrismaCloud.AssetAlerts.problem.parameters | Unknown | The parameters of the problem. |
| PrismaCloud.AssetAlerts.id | String | The ID of the asset alert. |
| PrismaCloud.AssetAlerts.severity | String | The severity of the asset alert. |
| PrismaCloud.AssetAlerts.policyId | String | The policy ID of the asset alert. |
| PrismaCloud.AssetAlerts.isHyperionPolicy | Boolean | The hyperion policy of the asset alert. |
| PrismaCloud.AssetAlerts.policyType | String | The policy type of the asset alert. |
| PrismaCloud.AssetAlerts.policyName | String | The policy name of the asset alert. |
| PrismaCloud.AssetAlerts.policyDescription | String | The policy description of the asset alert. |
| PrismaCloud.AssetAlerts.alertTime | Number | The alert time of the asset alert. |
prisma-cloud-asset-network-get
Returns detailed information for the asset network with the given ID.
Base Command
prisma-cloud-asset-network-get
Input
| Argument Name | Description | Required |
|---|---|---|
| asset_id | Unified asset ID or RRN (Restricted Resource Name). | Required |
| finding_type | External finding types. Possible values are: COMPLIANCE_CIS, GUARD_DUTY_HOST, GUARD_DUTY_IAM, INSPECTOR_RBA, INSPECTOR_SBP, NETWORK_REACHABILITY, AZURE_SECURITY_CENTER_ALERTS, UNCLASSIFIED, COMMAND_AND_CONTROL, CREDENTIAL_ACCESS, CROSS_ACCOUNT_TRUST, DATA_EXFILTRATION, DEFENSE_EVASION, DISCOVERY, HIGH_PRIVILEGED_ROLE, INITIAL_ACCESS, INTERNET_EXPOSURE, KEYS_AND_SECRETS, LATERAL_MOVEMENT, MALWARE, MFA, MISCONFIGURATION, NETWORK_ANOMALY, PRIVILEGE_ESCALATION, RECONNAISSANCE, RESOURCE_HIJACKING, SSH_BRUTE_FORCE, UNAUTHORIZED_ACCESS, UNENCRYPTED_DATA, UNUSED_PRIVILEGES, USER_ANOMALY, WEAK_PASSWORD, SENSITIVE_DATA_EXPOSURE, INJECTIONS, VULNERABILITY_SCANNING, SHELLSHOCK, KNOWN_BOTS, UNKNOWN_BOTS, VIRTUAL_PATCHES, WEB_ATTACK, BOT_ACTIVITY, WEB_SCRAPING, CUSTOM, VULNERABILITY, HOST_VULNERABILITY_CVE, CONTAINER_IMAGE_VULNERABILITY_CVE, VIRTUAL_IMAGE_VULNERABILITY_CVE, SERVERLESS_VULNERABILITY, PACKAGE_VULNERABILITY. | Optional |
| risk_factors | Comma-separated list of external finding risk factors. Possible values are: CRITICAL_SEVERITY, HIGH_SEVERITY, MEDIUM_SEVERITY, HAS_FIX, REMOTE_EXECUTION, DOS, RECENT_VULNERABILITY, EXPLOIT_EXISTS, ATTACK_COMPLEXITY_LOW, ATTACK_VECTOR_NETWORK, REACHABLE_FROM_THE_INTERNET, LISTENING_PORTS, CONTAINER_IS_RUNNING_AS_ROOT, NO_MANDATORY_SECURITY_PROFILE_APPLIED, RUNNING_AS_PRIVILEGED_CONTAINER, PACKAGE_IN_USE, DOS_LOW, DOS_HIGH, EXPLOIT_EXISTS_IN_THE_WILD, EXPLOIT_EXISTS_POC, SENSITIVE_INFORMATION, ROOT_MOUNT, RUNTIME_SOCKET, HOST_ACCESS. | Optional |
| timeline_item_id | Timeline item ID. | Optional |
| alert_ids | Comma-separated list of alert IDs. | Optional |
| limit | Limit number of records. | Optional |
| permission_type | Permissions type. | Optional |
| page_token | Next page token. | Optional |
| prisma_cloud_findings_only | Filter Hyperion findings. Possible values are: true, false. | Optional |
| vulnerability_info_type_id | CVE ID, package ID, or layer ID. The value needs to be fetched from one of the group by API calls. | Optional |
| vulnerability_info_type | Supported vulnerability types. Possible values are: CVE, PACKAGE, LAYER. | Optional |
Context Output
| Path | Type | Description |
|---|---|---|
| PrismaCloud.AssetNetwork.problem.title | String | The title of the problem. |
| PrismaCloud.AssetNetwork.problem.status.statusCode | Number | The status code of the problem. |
| PrismaCloud.AssetNetwork.problem.status.reasonPhrase | String | The reason for the problem. |
| PrismaCloud.AssetNetwork.problem.detail | String | The details of the problem. |
| PrismaCloud.AssetNetwork.problem.instance | String | The instance of the problem. |
| PrismaCloud.AssetNetwork.problem.type | String | The type of the problem. |
| PrismaCloud.AssetNetwork.problem.parameters | Unknown | The parameters of the problem. |
| PrismaCloud.AssetNetwork.id | Number | The ID of the asset network. |
| PrismaCloud.AssetNetwork.access | String | The access of the asset network. |
| PrismaCloud.AssetNetwork.direction | String | The direction of the asset network. |
| PrismaCloud.AssetNetwork.ips | String | The IPS of the asset network. |
| PrismaCloud.AssetNetwork.ports | String | The ports of the asset network. |
| PrismaCloud.AssetNetwork.protocol | String | The protocol of the asset network. |
| PrismaCloud.AssetNetwork.priority | Number | The priority of the asset network. |
prisma-cloud-asset-vulnerabilities-get
Returns detailed information for the asset vulnerabilities with the given ID.
Base Command
prisma-cloud-asset-vulnerabilities-get
Input
| Argument Name | Description | Required |
|---|---|---|
| asset_id | Unified asset ID or RRN (Restricted Resource Name). | Required |
| finding_type | External finding types. Possible values are: COMPLIANCE_CIS, GUARD_DUTY_HOST, GUARD_DUTY_IAM, INSPECTOR_RBA, INSPECTOR_SBP, NETWORK_REACHABILITY, AZURE_SECURITY_CENTER_ALERTS, UNCLASSIFIED, COMMAND_AND_CONTROL, CREDENTIAL_ACCESS, CROSS_ACCOUNT_TRUST, DATA_EXFILTRATION, DEFENSE_EVASION, DISCOVERY, HIGH_PRIVILEGED_ROLE, INITIAL_ACCESS, INTERNET_EXPOSURE, KEYS_AND_SECRETS, LATERAL_MOVEMENT, MALWARE, MFA, MISCONFIGURATION, NETWORK_ANOMALY, PRIVILEGE_ESCALATION, RECONNAISSANCE, RESOURCE_HIJACKING, SSH_BRUTE_FORCE, UNAUTHORIZED_ACCESS, UNENCRYPTED_DATA, UNUSED_PRIVILEGES, USER_ANOMALY, WEAK_PASSWORD, SENSITIVE_DATA_EXPOSURE, INJECTIONS, VULNERABILITY_SCANNING, SHELLSHOCK, KNOWN_BOTS, UNKNOWN_BOTS, VIRTUAL_PATCHES, WEB_ATTACK, BOT_ACTIVITY, WEB_SCRAPING, CUSTOM, VULNERABILITY, HOST_VULNERABILITY_CVE, CONTAINER_IMAGE_VULNERABILITY_CVE, VIRTUAL_IMAGE_VULNERABILITY_CVE, SERVERLESS_VULNERABILITY, PACKAGE_VULNERABILITY. | Optional |
| risk_factors | Comma-separated list of external finding risk factors. Possible values are: CRITICAL_SEVERITY, HIGH_SEVERITY, MEDIUM_SEVERITY, HAS_FIX, REMOTE_EXECUTION, DOS, RECENT_VULNERABILITY, EXPLOIT_EXISTS, ATTACK_COMPLEXITY_LOW, ATTACK_VECTOR_NETWORK, REACHABLE_FROM_THE_INTERNET, LISTENING_PORTS, CONTAINER_IS_RUNNING_AS_ROOT, NO_MANDATORY_SECURITY_PROFILE_APPLIED, RUNNING_AS_PRIVILEGED_CONTAINER, PACKAGE_IN_USE, DOS_LOW, DOS_HIGH, EXPLOIT_EXISTS_IN_THE_WILD, EXPLOIT_EXISTS_POC, SENSITIVE_INFORMATION, ROOT_MOUNT, RUNTIME_SOCKET, HOST_ACCESS. | Optional |
| timeline_item_id | Timeline item ID. | Optional |
| alert_ids | Comma-separated list of alert IDs. | Optional |
| limit | Limit number of records. | Optional |
| permission_type | Permissions type. | Optional |
| page_token | Next page token. | Optional |
| prisma_cloud_findings_only | Filter Hyperion findings. Possible values are: true, false. | Optional |
| vulnerability_info_type_id | CVE ID, package ID, or layer ID. The value needs to be fetched from one of the group by API calls. | Optional |
| vulnerability_info_type | Supported vulnerability types. Possible values are: CVE, PACKAGE, LAYER. | Optional |
Context Output
| Path | Type | Description |
|---|---|---|
| PrismaCloud.AssetVulnerabilities.problem.title | String | The title of the problem. |
| PrismaCloud.AssetVulnerabilities.problem.status.statusCode | Number | The status code of the problem. |
| PrismaCloud.AssetVulnerabilities.problem.status.reasonPhrase | String | The reason for the problem. |
| PrismaCloud.AssetVulnerabilities.problem.detail | String | The details of the problem. |
| PrismaCloud.AssetVulnerabilities.problem.instance | String | The instance of the problem. |
| PrismaCloud.AssetVulnerabilities.problem.type | String | The type of the problem. |
| PrismaCloud.AssetVulnerabilities.problem.parameters | Unknown | The parameters of the problem. |
| PrismaCloud.AssetVulnerabilities.accountId | String | The account ID of the asset vulnerability. |
| PrismaCloud.AssetVulnerabilities.count | String | The count of asset vulnerabilities. |
| PrismaCloud.AssetVulnerabilities.createdOn | Number | The created on of the asset vulnerability. |
| PrismaCloud.AssetVulnerabilities.customerId | Number | The customer ID of the asset vulnerability. |
| PrismaCloud.AssetVulnerabilities.cveId | String | The CVE ID of the asset vulnerability. |
| PrismaCloud.AssetVulnerabilities.description | String | The description of the asset vulnerability. |
| PrismaCloud.AssetVulnerabilities.externalId | Number | The external ID of the asset vulnerability. |
| PrismaCloud.AssetVulnerabilities.id | String | The ID of the asset vulnerability. |
| PrismaCloud.AssetVulnerabilities.normalizedName | String | The normalized name of the asset vulnerability. |
| PrismaCloud.AssetVulnerabilities.normalizedNames | String | The normalized names of the asset vulnerability. |
| PrismaCloud.AssetVulnerabilities.nvdUrl | String | The nvd URL of the asset vulnerability. |
| PrismaCloud.AssetVulnerabilities.link | String | The link of the asset vulnerability. |
| PrismaCloud.AssetVulnerabilities.rawData | String | The raw data of the asset vulnerability. |
| PrismaCloud.AssetVulnerabilities.regionId | String | The region ID of the asset vulnerability. |
| PrismaCloud.AssetVulnerabilities.resourceCloudId | String | The resource cloud ID of the asset vulnerability. |
| PrismaCloud.AssetVulnerabilities.resourceId | Number | The resource ID of the asset vulnerability. |
| PrismaCloud.AssetVulnerabilities.resourceUrl | String | The resource URL of the asset vulnerability. |
| PrismaCloud.AssetVulnerabilities.riskFactors | String | The risk factors of the asset vulnerability. |
| PrismaCloud.AssetVulnerabilities.rlUpdatedOn | Number | The rl updated on of the asset vulnerability. |
| PrismaCloud.AssetVulnerabilities.scanId | String | The scan ID of the asset vulnerability. |
| PrismaCloud.AssetVulnerabilities.score | String | The score of the asset vulnerability. |
| PrismaCloud.AssetVulnerabilities.severity | String | The severity of the asset vulnerability. |
| PrismaCloud.AssetVulnerabilities.source | String | The source of the asset vulnerability. |
| PrismaCloud.AssetVulnerabilities.sourceData | Unknown | The source data of the asset vulnerability. |
| PrismaCloud.AssetVulnerabilities.status | String | The status of the asset vulnerability. |
| PrismaCloud.AssetVulnerabilities.title | String | The title of the asset vulnerability. |
| PrismaCloud.AssetVulnerabilities.type | String | The type of the asset vulnerability. |
| PrismaCloud.AssetVulnerabilities.packageName | String | The package name of the asset vulnerability. |
| PrismaCloud.AssetVulnerabilities.updatedOn | Number | The updated on of the asset vulnerability. |
prisma-cloud-asset-get
Returns detailed information for the asset with the given ID.
Base Command
prisma-cloud-asset-get
Input
| Argument Name | Description | Required |
|---|---|---|
| asset_id | Unified Asset ID or RRN (Restricted Resource Name). | Required |
| finding_type | External finding types. Possible values are: COMPLIANCE_CIS, GUARD_DUTY_HOST, GUARD_DUTY_IAM, INSPECTOR_RBA, INSPECTOR_SBP, NETWORK_REACHABILITY, AZURE_SECURITY_CENTER_ALERTS, UNCLASSIFIED, COMMAND_AND_CONTROL, CREDENTIAL_ACCESS, CROSS_ACCOUNT_TRUST, DATA_EXFILTRATION, DEFENSE_EVASION, DISCOVERY, HIGH_PRIVILEGED_ROLE, INITIAL_ACCESS, INTERNET_EXPOSURE, KEYS_AND_SECRETS, LATERAL_MOVEMENT, MALWARE, MFA, MISCONFIGURATION, NETWORK_ANOMALY, PRIVILEGE_ESCALATION, RECONNAISSANCE, RESOURCE_HIJACKING, SSH_BRUTE_FORCE, UNAUTHORIZED_ACCESS, UNENCRYPTED_DATA, UNUSED_PRIVILEGES, USER_ANOMALY, WEAK_PASSWORD, SENSITIVE_DATA_EXPOSURE, INJECTIONS, VULNERABILITY_SCANNING, SHELLSHOCK, KNOWN_BOTS, UNKNOWN_BOTS, VIRTUAL_PATCHES, WEB_ATTACK, BOT_ACTIVITY, WEB_SCRAPING, CUSTOM, VULNERABILITY, HOST_VULNERABILITY_CVE, CONTAINER_IMAGE_VULNERABILITY_CVE, VIRTUAL_IMAGE_VULNERABILITY_CVE, SERVERLESS_VULNERABILITY, PACKAGE_VULNERABILITY. | Optional |
| risk_factors | Comma-separated list of external finding risk factors. Possible values are: CRITICAL_SEVERITY, HIGH_SEVERITY, MEDIUM_SEVERITY, HAS_FIX, REMOTE_EXECUTION, DOS, RECENT_VULNERABILITY, EXPLOIT_EXISTS, ATTACK_COMPLEXITY_LOW, ATTACK_VECTOR_NETWORK, REACHABLE_FROM_THE_INTERNET, LISTENING_PORTS, CONTAINER_IS_RUNNING_AS_ROOT, NO_MANDATORY_SECURITY_PROFILE_APPLIED, RUNNING_AS_PRIVILEGED_CONTAINER, PACKAGE_IN_USE, DOS_LOW, DOS_HIGH, EXPLOIT_EXISTS_IN_THE_WILD, EXPLOIT_EXISTS_POC, SENSITIVE_INFORMATION, ROOT_MOUNT, RUNTIME_SOCKET, HOST_ACCESS. | Optional |
| timeline_item_id | Timeline item ID. | Optional |
| alert_ids | Comma-separated list of alert IDs. | Optional |
| limit | Limit number of records. | Optional |
| permission_type | Permissions type. | Optional |
| page_token | Next page token. | Optional |
| prisma_cloud_findings_only | Filter Hyperion findings. Possible values are: true, false. | Optional |
| vulnerability_info_type_id | CVE ID, Package ID, or Layer ID. The value needs to be fetched from one of the groups by API calls. | Optional |
| vulnerability_info_type | Supported vulnerability types. Possible values are: CVE, PACKAGE, LAYER. | Optional |
Context Output
| Path | Type | Description |
|---|---|---|
| PrismaCloud.Asset.problem.title | String | The title of the problem. |
| PrismaCloud.Asset.problem.status.statusCode | Number | The status code of the problem. |
| PrismaCloud.Asset.problem.status.reasonPhrase | String | The reason for the problem. |
| PrismaCloud.Asset.problem.detail | String | The details of the problem. |
| PrismaCloud.Asset.problem.instance | String | The instance of the problem. |
| PrismaCloud.Asset.problem.type | String | The type of the problem. |
| PrismaCloud.Asset.problem.parameters | Unknown | The parameters of the problem. |
| PrismaCloud.Asset.id | String | The ID of the asset. |
| PrismaCloud.Asset.prismaId | String | The Prisma ID of the asset. |
| PrismaCloud.Asset.appName | String | The app name of the asset. |
| PrismaCloud.Asset.externalAssetId | String | The external asset ID of the asset. |
| PrismaCloud.Asset.assetTypeId | Number | The asset type ID of the asset. |
| PrismaCloud.Asset.cloudType | String | The cloud type of the asset. |
| PrismaCloud.Asset.createdTs | Number | The creation timestamp of the asset. |
| PrismaCloud.Asset.insertTs | Number | The insertion timestamp of the asset. |
| PrismaCloud.Asset.data | Unknown | The data of the asset. |
| PrismaCloud.Asset.dynamicData | Unknown | The dynamic data of the asset. |
| PrismaCloud.Asset.riskGrade | String | The risk grade of the asset. |
| PrismaCloud.Asset.stateId | String | The state ID of the asset. |
| PrismaCloud.Asset.name | String | The name of the asset. |
| PrismaCloud.Asset.regionId | String | The region ID of the asset. |
| PrismaCloud.Asset.regionName | String | The region name of the asset. |
| PrismaCloud.Asset.altAssetId | String | The alternative asset ID of the asset. |
| PrismaCloud.Asset.url | String | The URL of the asset. |
| PrismaCloud.Asset.vpcId | String | The VPC ID of the asset. |
| PrismaCloud.Asset.vpcExternalAssetId | String | The VPC external asset ID of the asset. |
| PrismaCloud.Asset.vpcName | String | The VPC name of the asset. |
| PrismaCloud.Asset.tags | Unknown | The tags of the asset. |
| PrismaCloud.Asset.relationshipCounts | Number | The relationship counts of the asset. |
| PrismaCloud.Asset.vulnerabilityCounts | Unknown | The vulnerability counts of the asset. |
| PrismaCloud.Asset.accountName | String | The account name of the asset. |
| PrismaCloud.Asset.assetType | String | The account type of the asset. |
| PrismaCloud.Asset.serviceName | String | The service name of the asset. |
| PrismaCloud.Asset.resourceType | String | The resource type of the asset. |
| PrismaCloud.Asset.deleted | Boolean | The deletion state of the asset. |
| PrismaCloud.Asset.assetClassId | String | The asset class ID of the asset. |
| PrismaCloud.Asset.assetClass | String | The asset class of the asset. |
| PrismaCloud.Asset.attributes | Unknown | The attributes of the asset. |
| PrismaCloud.Asset.alertsCount.severity | String | The severity of the alerts of the asset. |
| PrismaCloud.Asset.alertsCount.count | Number | The alert count of the asset. |
| PrismaCloud.Asset.ipAddresses | String | The IP addresses of the asset. |
| PrismaCloud.Asset.trueInternetExposure | String | The internet exposure state of the asset. |
| PrismaCloud.Asset.dataSecurity | Unknown | The data security of the asset. |
prisma-cloud-asset-generic-get
Returns detailed information for the asset with the given ID.
Base Command
prisma-cloud-asset-generic-get
Input
| Argument Name | Description | Required |
|---|---|---|
| asset_id | Unified asset ID or RRN (Restricted Resource Name). | Required |
| type | Asset domain service query type. Possible values are: external_finding, asset, asset_lite, alerts, alerts_counts, alert_summary, finding_summary, attack_path, attack_path_summary, raw_config, network, timeline, external_integration, asset_data_indicators, relationships, findings, vulnerabilities, permissions, package_info, labels, vulnerability_aggregates, process_info, vulnerabilities_group_by_type, asset_cwp_vulns, app_contexts, attributes, data_security, data_security_summary. Default is asset. | Required |
| finding_type | External finding types. Possible values are: COMPLIANCE_CIS, GUARD_DUTY_HOST, GUARD_DUTY_IAM, INSPECTOR_RBA, INSPECTOR_SBP, NETWORK_REACHABILITY, AZURE_SECURITY_CENTER_ALERTS, UNCLASSIFIED, COMMAND_AND_CONTROL, CREDENTIAL_ACCESS, CROSS_ACCOUNT_TRUST, DATA_EXFILTRATION, DEFENSE_EVASION, DISCOVERY, HIGH_PRIVILEGED_ROLE, INITIAL_ACCESS, INTERNET_EXPOSURE, KEYS_AND_SECRETS, LATERAL_MOVEMENT, MALWARE, MFA, MISCONFIGURATION, NETWORK_ANOMALY, PRIVILEGE_ESCALATION, RECONNAISSANCE, RESOURCE_HIJACKING, SSH_BRUTE_FORCE, UNAUTHORIZED_ACCESS, UNENCRYPTED_DATA, UNUSED_PRIVILEGES, USER_ANOMALY, WEAK_PASSWORD, SENSITIVE_DATA_EXPOSURE, INJECTIONS, VULNERABILITY_SCANNING, SHELLSHOCK, KNOWN_BOTS, UNKNOWN_BOTS, VIRTUAL_PATCHES, WEB_ATTACK, BOT_ACTIVITY, WEB_SCRAPING, CUSTOM, VULNERABILITY, HOST_VULNERABILITY_CVE, CONTAINER_IMAGE_VULNERABILITY_CVE, VIRTUAL_IMAGE_VULNERABILITY_CVE, SERVERLESS_VULNERABILITY, PACKAGE_VULNERABILITY. | Optional |
| risk_factors | Comma-separated list of external finding risk factors. Possible values are: CRITICAL_SEVERITY, HIGH_SEVERITY, MEDIUM_SEVERITY, HAS_FIX, REMOTE_EXECUTION, DOS, RECENT_VULNERABILITY, EXPLOIT_EXISTS, ATTACK_COMPLEXITY_LOW, ATTACK_VECTOR_NETWORK, REACHABLE_FROM_THE_INTERNET, LISTENING_PORTS, CONTAINER_IS_RUNNING_AS_ROOT, NO_MANDATORY_SECURITY_PROFILE_APPLIED, RUNNING_AS_PRIVILEGED_CONTAINER, PACKAGE_IN_USE, DOS_LOW, DOS_HIGH, EXPLOIT_EXISTS_IN_THE_WILD, EXPLOIT_EXISTS_POC, SENSITIVE_INFORMATION, ROOT_MOUNT, RUNTIME_SOCKET, HOST_ACCESS. | Optional |
| timeline_item_id | Timeline item ID. | Optional |
| alert_ids | Comma-separated list of alert IDs. | Optional |
| limit | Limit number of records. | Optional |
| permission_type | Permissions type. | Optional |
| page_token | Next page token. | Optional |
| prisma_cloud_findings_only | Filter Hyperion findings. Possible values are: true, false. | Optional |
| vulnerability_info_type_id | CVE ID, package ID, or layer ID. The value needs to be fetched from one of the group by API calls. | Optional |
| vulnerability_info_type | Supported vulnerability types. Possible values are: CVE, PACKAGE, LAYER. | Optional |
Context Output
There is no context output for this command.
prisma-cloud-asset-findings-get
Returns detailed information for the asset findings with the given ID.
Base Command
prisma-cloud-asset-findings-get
Input
| Argument Name | Description | Required |
|---|---|---|
| asset_id | Unified asset ID or RRN (Restricted Resource Name). | Required |
| finding_type | External finding types. Possible values are: COMPLIANCE_CIS, GUARD_DUTY_HOST, GUARD_DUTY_IAM, INSPECTOR_RBA, INSPECTOR_SBP, NETWORK_REACHABILITY, AZURE_SECURITY_CENTER_ALERTS, UNCLASSIFIED, COMMAND_AND_CONTROL, CREDENTIAL_ACCESS, CROSS_ACCOUNT_TRUST, DATA_EXFILTRATION, DEFENSE_EVASION, DISCOVERY, HIGH_PRIVILEGED_ROLE, INITIAL_ACCESS, INTERNET_EXPOSURE, KEYS_AND_SECRETS, LATERAL_MOVEMENT, MALWARE, MFA, MISCONFIGURATION, NETWORK_ANOMALY, PRIVILEGE_ESCALATION, RECONNAISSANCE, RESOURCE_HIJACKING, SSH_BRUTE_FORCE, UNAUTHORIZED_ACCESS, UNENCRYPTED_DATA, UNUSED_PRIVILEGES, USER_ANOMALY, WEAK_PASSWORD, SENSITIVE_DATA_EXPOSURE, INJECTIONS, VULNERABILITY_SCANNING, SHELLSHOCK, KNOWN_BOTS, UNKNOWN_BOTS, VIRTUAL_PATCHES, WEB_ATTACK, BOT_ACTIVITY, WEB_SCRAPING, CUSTOM, VULNERABILITY, HOST_VULNERABILITY_CVE, CONTAINER_IMAGE_VULNERABILITY_CVE, VIRTUAL_IMAGE_VULNERABILITY_CVE, SERVERLESS_VULNERABILITY, PACKAGE_VULNERABILITY. | Optional |
| risk_factors | Comma-separated list of external finding risk factors. Possible values are: CRITICAL_SEVERITY, HIGH_SEVERITY, MEDIUM_SEVERITY, HAS_FIX, REMOTE_EXECUTION, DOS, RECENT_VULNERABILITY, EXPLOIT_EXISTS, ATTACK_COMPLEXITY_LOW, ATTACK_VECTOR_NETWORK, REACHABLE_FROM_THE_INTERNET, LISTENING_PORTS, CONTAINER_IS_RUNNING_AS_ROOT, NO_MANDATORY_SECURITY_PROFILE_APPLIED, RUNNING_AS_PRIVILEGED_CONTAINER, PACKAGE_IN_USE, DOS_LOW, DOS_HIGH, EXPLOIT_EXISTS_IN_THE_WILD, EXPLOIT_EXISTS_POC, SENSITIVE_INFORMATION, ROOT_MOUNT, RUNTIME_SOCKET, HOST_ACCESS. | Optional |
| timeline_item_id | Timeline item ID. | Optional |
| alert_ids | Comma-separated list of alert IDs. | Optional |
| limit | Limit number of records. | Optional |
| permission_type | Permissions type. | Optional |
| page_token | Next page token. | Optional |
| prisma_cloud_findings_only | Filter Hyperion findings. Possible values are: true, false. | Optional |
| vulnerability_info_type_id | CVE ID, package ID, or layer ID. The value needs to be fetched from one of the group by API calls. | Optional |
| vulnerability_info_type | Supported vulnerability types. Possible values are: CVE, PACKAGE, LAYER. | Optional |
Context Output
| Path | Type | Description |
|---|---|---|
| PrismaCloud.AssetFindings.problem.title | String | The title of the problem. |
| PrismaCloud.AssetFindings.problem.status.statusCode | Number | The status code of the problem. |
| PrismaCloud.AssetFindings.problem.status.reasonPhrase | String | The reason for the problem. |
| PrismaCloud.AssetFindings.problem.detail | String | The details of the problem. |
| PrismaCloud.AssetFindings.problem.instance | String | The instance of the problem. |
| PrismaCloud.AssetFindings.problem.type | String | The type of the problem. |
| PrismaCloud.AssetFindings.problem.parameters | Unknown | The parameters of the problem. |
| PrismaCloud.AssetFindings.accountId | String | The account ID of the asset findings. |
| PrismaCloud.AssetFindings.count | String | The count of asset findings. |
| PrismaCloud.AssetFindings.createdOn | Number | The created on of the asset findings. |
| PrismaCloud.AssetFindings.customerId | Number | The customer ID of the asset findings. |
| PrismaCloud.AssetFindings.cveId | String | The CVE ID of the asset findings. |
| PrismaCloud.AssetFindings.description | String | The description of the asset findings. |
| PrismaCloud.AssetFindings.externalId | Number | The external ID of the asset findings. |
| PrismaCloud.AssetFindings.id | String | The ID of the asset findings. |
| PrismaCloud.AssetFindings.normalizedName | String | The normalized name of the asset findings. |
| PrismaCloud.AssetFindings.normalizedNames | String | The normalized names of the asset findings. |
| PrismaCloud.AssetFindings.nvdUrl | String | The nvd URL of the asset findings. |
| PrismaCloud.AssetFindings.link | String | The link of the asset findings. |
| PrismaCloud.AssetFindings.rawData | String | The raw data of the asset findings. |
| PrismaCloud.AssetFindings.regionId | String | The region ID of the asset findings. |
| PrismaCloud.AssetFindings.resourceCloudId | String | The resource cloud ID of the asset findings. |
| PrismaCloud.AssetFindings.resourceId | Number | The resource ID of the asset findings. |
| PrismaCloud.AssetFindings.resourceUrl | String | The resource URL of the asset findings. |
| PrismaCloud.AssetFindings.riskFactors | String | The risk factors of the asset findings. |
| PrismaCloud.AssetFindings.rlUpdatedOn | Number | The rl updated on of the asset findings. |
| PrismaCloud.AssetFindings.scanId | String | The scan ID of the asset findings. |
| PrismaCloud.AssetFindings.score | String | The score of the asset findings. |
| PrismaCloud.AssetFindings.severity | String | The severity of the asset findings. |
| PrismaCloud.AssetFindings.source | String | The source of the asset findings. |
| PrismaCloud.AssetFindings.sourceData | Unknown | The source data of the asset findings. |
| PrismaCloud.AssetFindings.status | String | The status of the asset findings. |
| PrismaCloud.AssetFindings.title | String | The title of the asset findings. |
| PrismaCloud.AssetFindings.type | String | The type of the asset findings. |
| PrismaCloud.AssetFindings.packageName | String | The package name of the asset findings. |
| PrismaCloud.AssetFindings.updatedOn | Number | The updated on of the asset findings. |
prisma-cloud-asset-relationships-get
Returns detailed information for the asset relationships with the given ID.
Base Command
prisma-cloud-asset-relationships-get
Input
| Argument Name | Description | Required |
|---|---|---|
| asset_id | Unified asset ID or RRN (Restricted Resource Name). | Required |
| finding_type | External finding types. Possible values are: COMPLIANCE_CIS, GUARD_DUTY_HOST, GUARD_DUTY_IAM, INSPECTOR_RBA, INSPECTOR_SBP, NETWORK_REACHABILITY, AZURE_SECURITY_CENTER_ALERTS, UNCLASSIFIED, COMMAND_AND_CONTROL, CREDENTIAL_ACCESS, CROSS_ACCOUNT_TRUST, DATA_EXFILTRATION, DEFENSE_EVASION, DISCOVERY, HIGH_PRIVILEGED_ROLE, INITIAL_ACCESS, INTERNET_EXPOSURE, KEYS_AND_SECRETS, LATERAL_MOVEMENT, MALWARE, MFA, MISCONFIGURATION, NETWORK_ANOMALY, PRIVILEGE_ESCALATION, RECONNAISSANCE, RESOURCE_HIJACKING, SSH_BRUTE_FORCE, UNAUTHORIZED_ACCESS, UNENCRYPTED_DATA, UNUSED_PRIVILEGES, USER_ANOMALY, WEAK_PASSWORD, SENSITIVE_DATA_EXPOSURE, INJECTIONS, VULNERABILITY_SCANNING, SHELLSHOCK, KNOWN_BOTS, UNKNOWN_BOTS, VIRTUAL_PATCHES, WEB_ATTACK, BOT_ACTIVITY, WEB_SCRAPING, CUSTOM, VULNERABILITY, HOST_VULNERABILITY_CVE, CONTAINER_IMAGE_VULNERABILITY_CVE, VIRTUAL_IMAGE_VULNERABILITY_CVE, SERVERLESS_VULNERABILITY, PACKAGE_VULNERABILITY. | Optional |
| risk_factors | Comma-separated list of external finding risk factors. Possible values are: CRITICAL_SEVERITY, HIGH_SEVERITY, MEDIUM_SEVERITY, HAS_FIX, REMOTE_EXECUTION, DOS, RECENT_VULNERABILITY, EXPLOIT_EXISTS, ATTACK_COMPLEXITY_LOW, ATTACK_VECTOR_NETWORK, REACHABLE_FROM_THE_INTERNET, LISTENING_PORTS, CONTAINER_IS_RUNNING_AS_ROOT, NO_MANDATORY_SECURITY_PROFILE_APPLIED, RUNNING_AS_PRIVILEGED_CONTAINER, PACKAGE_IN_USE, DOS_LOW, DOS_HIGH, EXPLOIT_EXISTS_IN_THE_WILD, EXPLOIT_EXISTS_POC, SENSITIVE_INFORMATION, ROOT_MOUNT, RUNTIME_SOCKET, HOST_ACCESS. | Optional |
| timeline_item_id | Timeline item ID. | Optional |
| alert_ids | Comma-separated list of alert IDs. | Optional |
| limit | Limit number of records. | Optional |
| permission_type | Permissions type. | Optional |
| page_token | Next page token. | Optional |
| prisma_cloud_findings_only | Filter Hyperion findings. Possible values are: true, false. | Optional |
| vulnerability_info_type_id | CVE ID, package ID, or layer ID. The value needs to be fetched from one of the group by API calls. | Optional |
| vulnerability_info_type | Supported vulnerability types. Possible values are: CVE, PACKAGE, LAYER. | Optional |
Context Output
| Path | Type | Description |
|---|---|---|
| PrismaCloud.AssetRelationships.assetId | String | The asset ID of the asset relationship. |
| PrismaCloud.AssetRelationships.relationshipType | String | The relationship type of the asset relationship. |
| PrismaCloud.AssetRelationships.assetTypeId | Number | The asset type ID of the asset relationship. |
| PrismaCloud.AssetRelationships.assetType | String | The asset type of the asset relationship. |
| PrismaCloud.AssetRelationships.assetName | String | The asset name of the asset relationship. |
| PrismaCloud.AssetRelationships.externalAssetId | String | The external asset ID of the asset relationship. |
| PrismaCloud.AssetRelationships.cloudId | String | The cloud ID of the asset relationship. |
| PrismaCloud.AssetRelationships.cloudName | String | The cloud name of the asset relationship. |
| PrismaCloud.AssetRelationships.pseudoAsset | Boolean | The pseudo asset of the asset relationship. |
| PrismaCloud.AssetRelationships.region | String | The region of the asset relationship. |
| PrismaCloud.AssetRelationships.cloudAccountId | String | The cloud account ID of the asset relationship. |
| PrismaCloud.AssetRelationships.assetClassId | String | The asset class ID of the asset relationship. |
| PrismaCloud.AssetRelationships.assetClass | String | The asset class of the asset relationship. |
| PrismaCloud.AssetRelationships.alertsCount.severity | String | The severity of the alerts of the asset relationship. |
| PrismaCloud.AssetRelationships.alertsCount.count | Number | The number of alerts of the asset relationships. |
| PrismaCloud.AssetRelationships.alertCountBySeverity.severity | String | The severity of the alerts of the asset relationship. |
| PrismaCloud.AssetRelationships.alertCountBySeverity.count | Number | The number of alerts by severity of the asset relationship. |
| PrismaCloud.AssetRelationships.vulnerabilityCounts | Unknown | The number of vulnerabilities of the asset relationship. |
| PrismaCloud.AssetRelationships.problem.title | String | The title of the problem. |
| PrismaCloud.AssetRelationships.problem.status.statusCode | Number | The status code of the problem. |
| PrismaCloud.AssetRelationships.problem.status.reasonPhrase | String | The reason for the problem. |
| PrismaCloud.AssetRelationships.problem.detail | String | The details of the problem. |
| PrismaCloud.AssetRelationships.problem.instance | String | The instance of the problem. |
| PrismaCloud.AssetRelationships.problem.type | String | The type of the problem. |
| PrismaCloud.AssetRelationships.problem.parameters | Unknown | The parameters of the problem. |
Configuration parameters
url— Server URL (required)credentials— Username / Access Key ID (required)proxy— Use system proxy settingsinsecure— Trust any certificate (not secure)incidentType— Incident typeincidentFetchInterval— Incidents Fetch Intervalmax_fetch— Maximum number of incidents to fetchfirst_fetch— First fetch time intervallook_back— Advanced: Time in minutes to look back when fetching incidentsfilters— Fetch only incidents matching these filtersisFetch— Fetch incidentsmirror_direction— Incident Mirroring Directionclose_incident— Close Mirrored XSOAR Incidentclose_alert— Close Mirrored Prisma Cloud Alertoutput_old_format— Output results of V1 commands to the context data in the old format
Commands (47)
-
get-modified-remote-dataGet the list of incidents that were modified since the last update time. This method is used for debugging purposes. The get-modified-remote-data command is used as part of the Mirroring feature that was introduced in Cortex XSOAR version 6.1.
-
get-remote-dataGet remote data from a remote incident. This method does not update the current incident, and should be used for debugging purposes only.
-
prisma-cloud-access-key-createAdds a new access key for the current user. If you have API access, you can create up to two access keys.
-
prisma-cloud-access-key-deleteDeletes the access key that has the specified ID.
-
prisma-cloud-access-key-disableDeactivates the access key that has the specified ID.
-
prisma-cloud-access-key-enableActivates the access key that has the specified ID. You cannot activate an expired access key.
-
prisma-cloud-access-keys-listReturns all access keys for your tenant if you have a Prisma Cloud System Admin role. Returns just your access keys if you don't have this role.
-
prisma-cloud-account-listList accounts.
-
prisma-cloud-account-owner-listGet the owners of the provided accounts.
-
prisma-cloud-account-status-getGet the statuses of the provided accounts.
-
prisma-cloud-alert-dismissDismiss or snooze the alerts matching the given filter. Either policy IDs or alert IDs must be provided. When no absolute time nor relative time arguments are provided, the default time range is all times. For snoozing, provide "snooze_unit" and "snooze_value" arguments.
-
prisma-cloud-alert-filter-listList the acceptable filters and values for alerts.
-
prisma-cloud-alert-get-detailsGets the details of an alert based on the alert ID.
-
prisma-cloud-alert-remediateRemediates the alert with the specified ID, if that alert is associated with a remediable policy. In order to check what remediation would run, use the "prisma-cloud-remediation-command-list" command first.
-
prisma-cloud-alert-reopenRe-open the alerts matching the given filter. Either policy IDs or alert IDs must be provided. When no absolute time nor relative time arguments are provided, the default time range is all times.
-
prisma-cloud-alert-searchSearch alerts on the Prisma Cloud platform. When no absolute time nor relative time arguments are provided, the search will show alerts from the last 7 days.
-
prisma-cloud-asset-alerts-getReturns detailed information for the asset alerts with the given ID.
-
prisma-cloud-asset-findings-getReturns detailed information for the asset findings with the given ID.
-
prisma-cloud-asset-generic-getReturns detailed information for the asset with the given ID.
-
prisma-cloud-asset-getReturns detailed information for the asset with the given ID.
-
prisma-cloud-asset-network-getReturns detailed information for the asset network with the given ID.
-
prisma-cloud-asset-relationships-getReturns detailed information for the asset relationships with the given ID.
-
prisma-cloud-asset-vulnerabilities-getReturns detailed information for the asset vulnerabilities with the given ID.
-
prisma-cloud-code-issues-listRetrieves the code errors detected by Application Security during periodic scans. At least one filtering argument is required, excluding `search_scopes`, `search_term`, and `limit`. For example, `fixable_only` or 'branch`.
-
prisma-cloud-config-searchSearch configuration inventory on the Prisma Cloud platform using RQL language. Use this command for all queries that start with "config". When no absolute time nor relative time arguments are provided, the default time range is all times.
-
prisma-cloud-error-file-listDeprecatedThis command is deprecated. Use prisma-cloud-code-issues-list instead.
-
prisma-cloud-event-searchSearch events inventory on the Prisma Cloud platform using RQL language. Use this command for all queries that start with "event". When no absolute time nor relative time arguments are provided, the default time range is all times. In order to reduce the returned data, set the "include_resource_json" argument to "false".
-
prisma-cloud-host-finding-listGet resource host finding list.
-
prisma-cloud-network-searchSearch networks inventory on the Prisma Cloud platform using RQL language. Use this command for all queries that start with "networks". When no absolute time nor relative time arguments are provided, the default time range is all times. In order to limit the results returning, use "limit search records to" at the end of the RQL query, followed by a value from one of these options: 1, 10, 100, 1000, and 10,000.
-
prisma-cloud-permission-listGet permission list. You must provide either "query" or "next_token".
-
prisma-cloud-remediation-command-listGenerates and returns a list of remediation commands for the specified alerts and policies. Data returned for a successful call include fully constructed commands for remediation. Either a policy ID or alert IDs must be provided. The returned information can be retrieved in the UI by clicking the "Remediate" button under the "Actions" column for supported alerts. When no absolute time nor relative time arguments are provided, the default time range is all times.
-
prisma-cloud-resource-getGet resource details.
-
prisma-cloud-resource-listReturns all the resource lists. Maps to the Resource Lists under Settings > Resource Lists in the Console UI.
-
prisma-cloud-trigger-scanTrigger asynchronous scan of all resources to refresh the current state at Prisma Cloud Code Security. In order to use this command, the "Code Security" module needs to be enabled and accessible in the Prisma Cloud UI.
-
prisma-cloud-user-roles-listRetrieves user roles. Maps to Settings > Access Control > Roles in the Console UI.
-
prisma-cloud-users-listLists all users and service accounts for your tenant. Maps to Settings > Access Control > Users in the Console UI.
-
redlock-dismiss-alertsDeprecatedDismiss the alerts matching the given filter. Must provide either policy IDs or alert IDs.
-
redlock-get-alert-detailsDeprecatedGets the details of an alert based on the alert ID.
-
redlock-get-remediation-detailsDeprecatedGets remediation details for the given alert.
-
redlock-get-rql-responseDeprecatedReturns the results of an RQL config query.
-
redlock-list-alert-filtersDeprecatedList the acceptable filters and values for alerts.
-
redlock-reopen-alertsDeprecatedRe-open the alerts matching the given filter. Must provide either policy IDs or alert IDs.
-
redlock-search-alertsDeprecatedSearch alerts on the Prisma Cloud platform. If no time-range arguments are given, the search will filter only alerts from the last 7 days.
-
redlock-search-configDeprecatedSearch the configuration inventory on the Prisma Cloud platform using RQL language.
-
redlock-search-eventDeprecatedSearch events on the Prisma Cloud platform using RQL language.
-
redlock-search-networkDeprecatedSearch networks on the Prisma Cloud platform using RQL language.
-
update-remote-systemUpdates the remote incident with local incident changes. This method is only used for debugging purposes and will not update the current incident.
import json from copy import deepcopy import demistomock as demisto # noqa: F401 from CommonServerPython import * # noqa: F401 """ CONSTANTS """ HEADERS = {"Content-Type": "application/json; charset=UTF-8", "Accept": "application/json; charset=UTF-8"} REQUEST_CSPM_AUTH_HEADER = "x-redlock-auth" # Prisma Cloud Security Posture Management REQUEST_CCS_AUTH_HEADER = "authorization" # Prisma Cloud Code Security RESPONSE_STATUS_HEADER = "x-redlock-status" DATE_FORMAT = "%Y-%m-%dT%H:%M:%SZ" # ISO8601 format with UTC, default in XSOAR RELATIVE_TIME_UNIT_OPTIONS = ( "hour", "day", "week", "month", "year", ) TO_NOW_TIME_UNIT_OPTIONS = ( "day", "week", "month", "year", "epoch", # account on-boarding "login", # last login ) TIME_FILTER_BASE_CASE = {"type": "to_now", "value": "epoch"} ALERT_SEARCH_BASE_TIME_FILTER = {"type": "relative", "value": {"amount": 7, "unit": "day"}} ERROR_TOO_MANY_ARGS = ( 'Too many arguments provided. You cannot specify absolute times ("time_range_date_from", ' '"time_range_date_to") with relative times ("time_range_unit", "time_range_value").' ) ERROR_NOT_ENOUGH_ARGS = ( 'Not enough arguments provided. You cannot specify "time_range_date_from" without ' '"time_range_date_to", or "time_range_value" without "time_range_unit".' ) ERROR_RELATIVE_TIME_UNIT = f'Time unit for relative time must be one of the following: {", ".join(RELATIVE_TIME_UNIT_OPTIONS)}.' ERROR_TO_NOW_TIME_UNIT = f'Time unit for to_now time must be one of the following: {", ".join(TO_NOW_TIME_UNIT_OPTIONS)}' MAX_INCIDENTS_TO_FETCH = 200 FETCH_DEFAULT_TIME = "3 days" FETCH_LOOK_BACK_TIME = 20 MIRROR_DIRECTION_MAPPING = { "None": None, "Incoming": "In", "Outgoing": "Out", "Incoming And Outgoing": "Both", } INCIDENT_INCOMING_MIRROR_ARGS = ["status", "dismissalNote", "reason", "policy.name"] INCIDENT_INCOMING_MIRROR_CLOSING_STATUSES = ["dismissed", "resolved", "snoozed"] INCIDENT_INCOMING_MIRROR_REOPENING_STATUS = "open" INCIDENT_OUTGOING_MIRROR_DISMISSAL_NOTE = "Closed by XSOAR" PAGE_NUMBER_DEFAULT_VALUE = 1 PAGE_SIZE_DEFAULT_VALUE = 50 PAGE_SIZE_MAX_VALUE = 10000 DEFAULT_LIMIT = "50" PRISMA_TO_XSOAR_SEVERITY = { "critical": IncidentSeverity.CRITICAL, "high": IncidentSeverity.HIGH, "medium": IncidentSeverity.MEDIUM, "low": IncidentSeverity.LOW, "informational": IncidentSeverity.INFO, } FINDING_TYPES_OPTIONS = ["guard_duty_host", "guard_duty_iam", "inspector_sbp", "compliance_cis", "host_vulnerability_cve"] RISK_FACTORS_OPTIONS = [ "CRITICAL_SEVERITY", "HIGH_SEVERITY", "MEDIUM_SEVERITY", "HAS_FIX", "REMOTE_EXECUTION", "DOS", "RECENT_VULNERABILITY", "EXPLOIT_EXISTS", "ATTACK_COMPLEXITY_LOW", "ATTACK_VECTOR_NETWORK", "REACHABLE_FROM_THE_INTERNET", "LISTENING_PORTS", "CONTAINER_IS_RUNNING_AS_ROOT", "NO_MANDATORY_SECURITY_PROFILE_APPLIED", "RUNNING_AS_PRIVILEGED_CONTAINER", "PACKAGE_IN_USE", ] CATEGORIES_OPTIONS = [ "IAM", "Compute", "Monitoring", "Networking", "Kubernetes", "General", "Storage", "Secrets", "Public", "Vulnerabilities", "Drift", "BuildIntegrity", "Licenses", ] FILE_TYPES_OPTIONS = [ "tf", "json", "yml", "yaml", "template", ".checkov.baseline", "hcl", "Dockerfile", "package.json", "package-lock.json", "bower.json", "pom.xml", "build.gradle", "build.gradle.kts", "gradle.properties", "gradle-wrapper.properties", "go.sum", "go.mod", "requirements.txt", "METADATA", "bicep", "Pipfile.lock", "Pipfile", "yarn.lock", "Gemfile", "Gemfile.lock", "gemspec", "env", "settings.py", "main.py", "application.py", "config.py", "app.js", "config.js", "dev.js", "db.properties", "application.properties", "private.pem", "privatekey.pem", "index.php", "config.php", "config.xml", "strings.xml", "app.module.ts", "environment.ts", "tpl", "tfvars", "unknown", ] SEARCH_OPTIONS_OPTIONS = ["path", "code"] SEARCH_TITLE_OPTIONS = ["title", "constructive_title", "descriptive_title"] SEVERITIES_OPTIONS = ["CRITICAL", "HIGH", "MEDIUM", "LOW", "INFO"] SOURCE_TYPES_OPTIONS = [ "Github", "Bitbucket", "Gitlab", "AzureRepos", "cli", "AWS", "Azure", "GCP", "Docker", "githubEnterprise", "gitlabEnterprise", "bitbucketEnterprise", "terraformCloud", "githubActions", "circleci", "codebuild", "jenkins", "tfcRunTasks", "admissionController", "terraformEnterprise", ] STATUSES_OPTIONS = ["Errors", "Suppressed", "Passed", "Fixed"] TIME_FIELDS = [ "firstSeen", "lastSeen", "alertTime", "eventOccurred", "lastUpdated", "insertTs", "createdTs", "lastModifiedTs", "addedOn", "eventTs", "createdOn", "updatedOn", "rlUpdatedOn", "lastLoginTs", ] LICENSE_TYPES = [ "OSI_APACHE", "OSI_ARTISTIC", "OSI_BSD", "OSI_EFL", "OSI_FDL", "OSI_LGPL", "OSI_ZPL", "CC-BY-SA-2.1-JP", "GPL-2.0-or-later", "AMDPLPA", "CC-BY-SA-3.0-DE", "ECL-2.0", "EPICS", "eCos-2.0", "GPL-3.0-with-GCC-exception", "KiCad-libraries-exception", "GFDL-1.3-invariants-or-later", "APSL-1.1", "MIT", "CC-BY-NC-ND-3.0-DE", "GPL-3.0", "CC-BY-SA-1.0", "ADSL", "MIT-CMU", "Linux-man-pages-copyleft", "diffmark", "GPL-2.0", "HPND", "OSL-1.0", "ClArtistic", "IJG", "IPL-1.0", "NCGL-UK-2.0", "CC-BY-2.5", "LGPL-3.0-or-later", "LiLiQ-Rplus-1.1", "CC0-1.0", "Glide", "ImageMagick", "CECILL-1.1", "AGPL-3.0-only", "eGenix", "ANTLR-PD", "CC-BY-NC-SA-4.0", "CECILL-C", "GFDL-1.3-no-invariants-only", "SHL-0.5", "MIT-Modern-Variant", "CC-BY-3.0-NL", "MIT-feh", "SMLNJ", "CC-BY-ND-2.0", "HaskellReport", "AGPL-1.0", "BitTorrent-1.0", "CDL-1.0", "SISSL", "CC-BY-SA-3.0", "C-UDA-1.0", "YPL-1.1", "AGPL-1.0-or-later", "NLOD-2.0", "Unlicense", "D-FSL-1.0", "Linux-OpenIB", "GPL-1.0-only", "libtiff", "Plexus", "BSD-1-Clause", "MPL-2.0", "Intel-ACPI", "Barr", "OGL-Canada-2.0", "ANTLR-PD-fallback", "Zed", "MIT-open-group", "LGPL-2.1-or-later", "mpich2", "Motosoto", "OGDL-Taiwan-1.0", "PDDL-1.0", "GFDL-1.3-invariants-only", "EUPL-1.1", "EUPL-1.0", "Entessa", "CC-BY-NC-ND-2.0", "W3C", "GFDL-1.2-no-invariants-or-later", "Saxpath", "GFDL-1.3-only", "FreeImage", "CNRI-Python", "Apache-1.0", "OLDAP-1.4", "JSON", "GPL-3.0-or-later", "DSDP", "MPL-2.0-no-copyleft-exception", "Condor-1.1", "Imlib2", "iMatix", "OLDAP-2.6", "Rdisc", "LiLiQ-P-1.1", "xpp", "FDK-AAC", "CC-BY-NC-3.0", "Jam", "GFDL-1.3-no-invariants-or-later", "GFDL-1.3-or-later", "ICU", "LGPL-2.1", "AFL-2.1", "JasPer-2.0", "SSPL-1.0", "CC-BY-SA-2.0", "BSD-3-Clause-Clear", "OSL-2.0", "CC-BY-SA-4.0", "SISSL-1.2", "ODC-By-1.0", "ZPL-2.1", "QPL-1.0", "LGPL-2.0-only", "CC-BY-SA-2.5", "Zimbra-1.3", "MTLL", "Eurosym", "NPL-1.0", "blessing", "GFDL-1.3", "GPL-1.0+", "GFDL-1.1-no-invariants-only", "CC-BY-NC-ND-3.0", "Xerox", "Unicode-TOU", "Aladdin", "CC-BY-NC-SA-2.5", "Artistic-1.0", "BSL-1.0", "CC-BY-ND-2.5", "NetCDF", "MulanPSL-2.0", "UCL-1.0", "PostgreSQL", "GFDL-1.1-only", "RHeCos-1.1", "Sendmail-8.23", "psfrag", "SNIA", "EPL-2.0", "0BSD", "MPL-1.0", "GFDL-1.1-or-later", "XFree86-1.1", "WTFPL", "CDLA-Sharing-1.0", "CAL-1.0", "CERN-OHL-S-2.0", "CC-BY-NC-SA-3.0-DE", "CC-BY-NC-1.0", "Artistic-2.0", "BUSL-1.1", "EUPL-1.2", "GPL-2.0-with-font-exception", "LGPL-2.0+", "AGPL-1.0-only", "SGI-B-1.0", "W3C-20150513", "Adobe-2006", "xinetd", "BSD-3-Clause-No-Military-License", "DRL-1.0", "LGPL-2.0", "MirOS", "PolyForm-Small-Business-1.0.0", "CDLA-Permissive-2.0", "LiLiQ-R-1.1", "Vim", "curl", "OLDAP-2.2.2", "CATOSL-1.1", "CC-BY-ND-4.0", "CC-BY-NC-SA-2.0-UK", "APSL-1.0", "GPL-2.0-with-classpath-exception", "OLDAP-2.0.1", "NIST-PD-fallback", "Glulxe", "NPL-1.1", "CC-BY-NC-ND-1.0", "CC-BY-NC-2.5", "Parity-6.0.0", "CC-BY-NC-SA-3.0-IGO", "CPAL-1.0", "CC-BY-2.5-AU", "SWL", "LAL-1.2", "NRL", "OGL-UK-3.0", "MS-RL", "OSL-2.1", "LPL-1.0", "OSET-PL-2.1", "OFL-1.0-no-RFN", "OML", "Arphic-1999", "BSD-2-Clause", "MulanPSL-1.0", "EPL-1.0", "BSD-4-Clause-Shortened", "Elastic-2.0", "NLPL", "LPPL-1.2", "SchemeReport", "Multics", "Net-SNMP", "SHL-0.51", "MIT-advertising", "GPL-3.0-with-autoconf-exception", "MS-PL", "wxWindows", "ZPL-1.1", "ISC", "CC-BY-NC-SA-3.0", "GPL-2.0-only", "Giftware", "CPL-1.0", "EUDatagrid", "SGI-B-1.1", "CC-BY-1.0", "bzip2-1.0.5", "libselinux-1.0", "SMPPL", "Latex2e", "Watcom-1.0", "VSL-1.0", "CC-BY-NC-SA-1.0", "FreeBSD-DOC", "Nunit", "LPPL-1.0", "OLDAP-2.4", "TAPR-OHL-1.0", "OLDAP-2.3", "CECILL-2.0", "LPPL-1.3a", "Qhull", "CNRI-Python-GPL-Compatible", "Frameworx-1.0", "CDLA-Permissive-1.0", "X11-distribute-modifications-variant", "EFL-1.0", "DOC", "GFDL-1.2-or-later", "BSD-3-Clause-No-Nuclear-License", "LPPL-1.1", "CC-BY-3.0-US", "TOSL", "Spencer-99", "copyleft-next-0.3.1", "FSFAP", "CC-BY-NC-ND-4.0", "OLDAP-2.8", "Bahyph", "Newsletr", "CC-BY-NC-4.0", "OFL-1.1", "TU-Berlin-2.0", "GFDL-1.2-invariants-or-later", "BSD-2-Clause-NetBSD", "Crossword", "YPL-1.0", "GPL-2.0-with-bison-exception", "NIST-PD", "IPA", "GFDL-1.1-invariants-or-later", "CC-BY-NC-ND-3.0-IGO", "BSD-Source-Code", "BitTorrent-1.1", "AFL-3.0", "Zend-2.0", "GFDL-1.1", "HPND-sell-variant", "Abstyles", "Interbase-1.0", "MakeIndex", "EFL-2.0", "LPL-1.02", "OLDAP-2.2", "LGPL-3.0-only", "LPPL-1.3c", "libpng-2.0", "Hippocratic-2.1", "BSD-3-Clause-No-Nuclear-License-2014", "AAL", "NOSL", "CC-BY-3.0-AT", "HTMLTIDY", "GPL-1.0-or-later", "RPL-1.5", "BSD-4-Clause-UC", "Wsuipa", "Cube", "SCEA", "IBM-pibs", "Borceux", "CC-BY-ND-3.0-DE", "CC-BY-NC-SA-2.0-FR", "Afmparse", "CUA-OPL-1.0", "CC-BY-SA-3.0-AT", "LGPL-2.1+", "OLDAP-2.7", "GLWTPL", "CC-BY-NC-SA-2.0", "OCCT-PL", "CNRI-Jython", "Leptonica", "OFL-1.0-RFN", "OpenSSL", "RSA-MD", "TORQUE-1.1", "X11", "BSD-Protection", "JPNIC", "App-s2p", "GFDL-1.2-only", "CPOL-1.02", "CC-BY-ND-3.0", "GPL-1.0", "Zlib", "Python-2.0", "OLDAP-1.3", "Mup", "LGPLLR", "CC-BY-4.0", "OCLC-2.0", "OGTSL", "DL-DE-BY-2.0", "OFL-1.0", "GFDL-1.2-invariants-only", "Sendmail", "CC-BY-NC-3.0-DE", "VOSTROM", "Beerware", "FSFULLR", "Fair", "BSD-2-Clause-FreeBSD", "Community-Spec-1.0", "SSH-short", "FSFUL", "GFDL-1.1-no-invariants-or-later", "CrystalStacker", "GFDL-1.1-invariants-only", "Ruby", "BSD-3-Clause-Open-MPI", "Baekmuk", "Libpng", "GD", "OLDAP-2.1", "Sleepycat", "CERN-OHL-P-2.0", "GFDL-1.2", "CC-BY-2.0", "SPL-1.0", "OLDAP-1.2", "etalab-2.0", "TMate", "NCSA", "NBPL-1.0", "Intel", "GPL-3.0-only", "APSL-2.0", "GPL-2.0-with-autoconf-exception", "TU-Berlin-1.0", "Noweb", "SSH-OpenSSH", "BSD-3-Clause-Attribution", "PSF-2.0", "psutils", "CERN-OHL-1.2", "SimPL-2.0", "OLDAP-2.2.1", "SGI-B-2.0", "GPL-2.0+", "COIL-1.0", "Naumen", "CC-BY-ND-1.0", "Unicode-DFS-2016", "AFL-1.2", "OSL-3.0", "OFL-1.1-RFN", "SAX-PD", "Xnet", "AML", "Apache-1.1", "NAIST-2003", "NGPL", "ZPL-2.0", "OFL-1.1-no-RFN", "APSL-1.2", "MPL-1.1", "BlueOak-1.0.0", "Unicode-DFS-2015", "PHP-3.01", "GL2PS", "NTP-0", "BSD-4-Clause", "TCL", "RSCPL", "MIT-enna", "CERN-OHL-1.1", "OSL-1.1", "BSD-3-Clause-LBNL", "Bitstream-Vera", "Adobe-Glyph", "MITNFA", "CC-BY-3.0-DE", "CECILL-1.0", "SugarCRM-1.1.3", "CAL-1.0-Combined-Work-Exception", "BSD-3-Clause", "Info-ZIP", "LGPL-3.0+", "Zimbra-1.4", "zlib-acknowledgement", "Spencer-94", "MIT-0", "AGPL-3.0", "CC-PDDC", "CC-BY-NC-2.0", "mplus", "ODbL-1.0", "RPSL-1.0", "APAFML", "OGL-UK-1.0", "CDDL-1.1", "bzip2-1.0.6", "LGPL-2.1-only", "OGC-1.0", "BSD-3-Clause-No-Nuclear-Warranty", "ErlPL-1.1", "ECL-1.0", "CERN-OHL-W-2.0", "OGL-UK-2.0", "O-UDA-1.0", "NTP", "NASA-1.3", "copyleft-next-0.3.0", "TCP-wrappers", "Apache-2.0", "CC-BY-3.0", "CECILL-B", "Nokia", "GPL-3.0+", "GPL-2.0-with-GCC-exception", "OPL-1.0", "OPUBL-1.0", "UPL-1.0", "AFL-2.0", "LGPL-2.0-or-later", "CECILL-2.1", "gnuplot", "Caldera", "PolyForm-Noncommercial-1.0.0", "OLDAP-2.0", "CDDL-1.0", "APL-1.0", "dvipdfm", "XSkat", "Spencer-86", "NLOD-1.0", "W3C-19980720", "BSD-2-Clause-Patent", "AMPAS", "AGPL-3.0-or-later", "RPL-1.1", "Parity-7.0.0", "OLDAP-1.1", "AFL-1.1", "Artistic-1.0-cl8", "FTL", "Dotseqn", "CC-BY-NC-ND-2.5", "GFDL-1.2-no-invariants-only", "PHP-3.0", "CC-BY-SA-2.0-UK", "BSD-3-Clause-Modification", "LAL-1.3", "gSOAP-1.3b", "StandardML-NJ", "NPOSL-3.0", "LGPL-3.0", "Artistic-1.0-Perl", "OLDAP-2.5", "BSD-2-Clause-Views", ] MAX_LIMIT_FOR_CODE_ISSUES = 1000 INT_DEFAULT_LIMIT = 50 DEFAULT_PAGE = 0 """ CLIENT CLASS """ class Client(BaseClient): def __init__( self, server_url: str, verify: bool, proxy: bool, headers: Dict[str, str], username: str, password: str, mirror_direction: str | None, close_incident: bool, close_alert: bool, is_test_module: bool, ): super().__init__(base_url=server_url, verify=verify, proxy=proxy, headers=headers) self.mirror_direction = mirror_direction self.close_incident = close_incident self.close_alert = close_alert self.retries = 0 if is_test_module else 2 self.timeout = 15 if is_test_module else self.timeout self.generate_auth_token(username, password) def generate_auth_token(self, username: str, password: str) -> None: """ Logins and generates a JSON Web Token (JWT) for authorization. The token is valid for 10 minutes. """ data = {"username": username, "password": password} demisto.debug("Sending request to get the auth token") response = self._http_request("POST", "login", json_data=data, retries=self.retries, timeout=self.timeout) try: token = response.get("token") if not token: raise DemistoException(f'Could not retrieve token from server: {response.get("message")}', res=response) except ValueError as exception: raise DemistoException("Could not parse API response.", exception=exception) from exception demisto.debug("Successfully got the auth token") self._headers[REQUEST_CSPM_AUTH_HEADER] = token def code_issues_list_request(self, body): return self._http_request("POST", "/code/api/v2/code-issues/branch_scan", json_data=body) def alert_filter_list_request(self): return self._http_request("GET", "filter/alert/suggest") def alert_search_request( self, time_range: Dict[str, Any], filters: List[str], limit: Optional[int] = None, detailed: Optional[str] = None, page_token: Optional[str] = None, sort_by: Optional[List[str]] = None, ): params = assign_params(detailed=detailed) data = remove_empty_values( { "limit": limit, "filters": handle_filters(filters), "timeRange": time_range, "sortBy": sort_by, "pageToken": page_token, } ) demisto.info(f"Executing Prisma Cloud alert search with payload: {data}") return self._http_request("POST", "v2/alert", params=params, json_data=data, retries=self.retries) def alert_get_details_request(self, alert_id: str, detailed: Optional[str] = None): params = assign_params(detailed=detailed) response = self._http_request("GET", f"alert/{alert_id}", params=params) self._concatenate_url(response, "resource.url") return response def _concatenate_url(self, response: Dict[str, Any], url_field: str = "url") -> None: """ Concatenates a url suffix with the base url for the places where only a suffix is returned, so urls we display will be clickable and lead to a real place. Updates the dict given. """ split_url_field = url_field.split(".") if len(split_url_field) > 1: self._concatenate_url(response.get(split_url_field[0], {}), ".".join(split_url_field[1:])) elif url_field in response: url = urljoin(self._base_url, response[url_field]).replace("https://api", "https://app") response[url_field] = url def alert_dismiss_request( self, dismissal_note: str, time_range: Dict[str, Any], alert_ids: Optional[List[str]] = None, policy_ids: Optional[List[str]] = None, dismissal_time_range: Optional[Dict[str, Any]] = None, filters: Optional[List[str]] = None, ): data = remove_empty_values( { "alerts": alert_ids, "policies": policy_ids, "dismissalNote": dismissal_note, "dismissalTimeRange": dismissal_time_range, "filter": { "timeRange": time_range, "filters": handle_filters(filters), }, } ) self._http_request("POST", "alert/dismiss", json_data=data, resp_type="response") def alert_reopen_request( self, time_range: Dict[str, Any], alert_ids: Optional[List[str]] = None, policy_ids: Optional[List[str]] = None, filters: Optional[List[str]] = None, ): data = remove_empty_values( { "alerts": alert_ids, "policies": policy_ids, "dismissalTimeRange": time_range, "filter": { "timeRange": time_range, "filters": handle_filters(filters), }, } ) self._http_request("POST", "alert/reopen", json_data=data, resp_type="response") def remediation_command_list_request( self, time_range: Dict[str, Any], alert_ids: Optional[List[str]] = None, policy_id: Optional[str] = None ): data = remove_empty_values( { "alerts": alert_ids, "filter": {"timeRange": time_range}, # all other filters are ignored by API "policies": [policy_id], } ) return self._http_request("POST", "alert/remediation", json_data=data) def alert_remediate_request(self, alert_id: str): self._http_request("PATCH", f"alert/remediation/{alert_id}", resp_type="response") def config_search_request( self, time_range: Dict[str, Any], query: str, limit: Optional[int] = None, search_id: Optional[str] = None, sort_direction: Optional[str] = None, sort_field: Optional[str] = None, include_resource_json: Optional[str] = "true", heuristic_search: Optional[str] = "true", ): total_items = [] page_count = 1 data = remove_empty_values( { "id": search_id, "limit": limit, "query": query, "sort": [{"direction": sort_direction, "field": sort_field}], "timeRange": time_range, "withResourceJson": include_resource_json, "heuristicSearch": heuristic_search, } ) first_page_response = self._http_request("POST", "search/config", json_data=data) first_page_data = first_page_response.get("data", {}) items = first_page_data.get("items", []) total_items.extend(items) demisto.debug(f"POST search/config - {len(items)} items were fetched from page {page_count}") page_limit = limit - len(items) if limit is not None else 0 next_page_token = first_page_data.get("nextPageToken") while next_page_token and page_limit: data["pageToken"] = next_page_token data["limit"] = page_limit page_count += 1 response = self._http_request("POST", "search/config/page", json_data=data) items = response.get("items", []) demisto.debug(f"POST search/config/page - {len(items)} items were fetched from page {page_count}") page_limit -= len(items) total_items.extend(items) next_page_token = response.get("nextPageToken", "") return total_items def event_search_request( self, time_range: Dict[str, Any], query: str, limit: Optional[int] = None, sort_by: Optional[List[Dict[str, str]]] = None ): data = remove_empty_values( { "limit": limit, "query": query, "timeRange": time_range, "sort": sort_by, } ) return self._http_request("POST", "search/event", json_data=data) def network_search_request( self, query: str, time_range: Dict[str, Any], search_id: Optional[str] = None, cloud_type: Optional[str] = None ): data = remove_empty_values( { "cloudType": cloud_type, "id": search_id, "query": query, "timeRange": time_range, } ) return self._http_request("POST", "search", json_data=data) def resource_get_request(self, rrn: str): data = remove_empty_values({"rrn": rrn}) return self._http_request("POST", "resource", json_data=data) def resource_list_request(self, list_type: Optional[str]): params = assign_params(listType=list_type) return self._http_request("GET", "v1/resource_list", params=params) def user_roles_list_request(self, role_id: str): return self._http_request("GET", f"user/role/{role_id}") def all_user_roles_list_request(self): return self._http_request("GET", "user/role") def users_list_request(self): return self._http_request("GET", "v3/user") def account_list_request(self, exclude_account_group_details: str): data = remove_empty_values({"excludeAccountGroupDetails": exclude_account_group_details}) return self._http_request("GET", "cloud", json_data=data) def account_status_get_request(self, account_id: str): return self._http_request("GET", f"account/{account_id}/config/status") def account_owner_list_request(self, account_id: str): return self._http_request("GET", f"cloud/{account_id}/owners") def host_finding_list_request( self, rrn: str, finding_types: Optional[List[str]] = None, risk_factors: Optional[List[str]] = None ): data = remove_empty_values({"rrn": rrn, "findingType": finding_types, "riskFactors": risk_factors}) return self._http_request("POST", "resource/external_finding", json_data=data) def permission_list_request(self, query: str, limit: int, user_id: Optional[str] = None): data = remove_empty_values({"id": user_id, "limit": limit, "query": query}) return self._http_request("POST", "api/v1/permission", json_data=data) def permission_list_next_page_request(self, next_token: str, limit: int): data = remove_empty_values({"limit": limit, "pageToken": next_token}) return self._http_request("POST", "api/v1/permission/page", json_data=data) # Prisma Cloud Code Security module requests def trigger_scan_request(self): headers = self._headers headers[REQUEST_CCS_AUTH_HEADER] = headers.pop(REQUEST_CSPM_AUTH_HEADER) return self._http_request("POST", "code/api/v1/scans/integrations", headers=headers) def error_file_list_request( self, repository: str, source_types: List[str], cicd_run_id: Optional[float] = None, authors: Optional[List[str]] = None, branch: Optional[str] = None, categories: Optional[List[str]] = None, code_status: Optional[str] = None, file_types: Optional[List[str]] = None, repository_id: Optional[str] = None, search_options: Optional[List[str]] = None, search_text: Optional[str] = None, search_title: Optional[str] = None, severities: Optional[List[str]] = None, tags: Optional[List[str]] = None, statuses: Optional[List[str]] = None, ): data = remove_empty_values( { "CICDRunId": cicd_run_id, "authors": authors, "branch": branch, "categories": categories, "codeStatus": [code_status], "fileTypes": file_types, "repository": repository, "repositoryId": repository_id, "severities": severities, "sourceTypes": source_types, "tags": handle_tags(tags), "types": statuses, } ) if search_title: data["search"] = {"options": search_options, "text": search_text, "title": search_title} elif search_options or search_text: data["search"] = {"options": search_options, "text": search_text} headers = self._headers headers[REQUEST_CCS_AUTH_HEADER] = headers.pop(REQUEST_CSPM_AUTH_HEADER) return self._http_request("POST", "code/api/v1/errors/files", json_data=data, headers=headers) def access_key_creation(self, args: Dict[str, Any]) -> Dict[str, Any]: """ Create an access key using the provided arguments. Args: - args (Dict[str, Any]): A dictionary containing the required parameters for key creation. - name (str): required - expires-on (str): optional Returns: - Dict[str, Any]: A dictionary containing the response from the API request to create the access key. """ payload = {"name": args.get("name")} if args.get("expires-on"): dateparser_datetime_object = dateparser.parse(args.get("expires-on", ""), settings={"PREFER_DATES_FROM": "future"}) if isinstance(dateparser_datetime_object, datetime): payload["expiresOn"] = dateparser_datetime_object.strftime("%s") + "000" # API require milliseconds timestamp return self._http_request(method="POST", url_suffix="/access_keys", data=json.dumps(payload)) def get_access_key_by_id(self, args: Dict[str, Any]) -> Dict[str, Any]: return self._http_request(method="GET", url_suffix=f"/access_keys/{args.get('access-key')}") def get_access_keys_list(self) -> List[Dict[str, Any]]: return self._http_request(method="GET", url_suffix="/access_keys") def patch_access_key_disable(self, access_key: str) -> Dict[str, Any]: return self._http_request(method="PATCH", url_suffix=f"/access_keys/{access_key}/status/false", resp_type="content") def patch_access_key_enable(self, access_key: str) -> Dict[str, Any]: return self._http_request(method="PATCH", url_suffix=f"/access_keys/{access_key}/status/true", resp_type="content") def access_key_deletion(self, access_key: str) -> Dict[str, Any]: return self._http_request(method="DELETE", url_suffix=f"/access_keys/{access_key}", resp_type="content") def get_asset_by_id(self, params: Dict[str, Any]) -> Dict[str, Any]: return self._http_request(method="POST", url_suffix="/uai/v1/asset", json_data=params) """ HELPER FUNCTIONS """ def format_url(url: str) -> str: """ Formats the URL from the regular one (with 'app') to the API one (with 'api'), in order to support providing both options. """ return urljoin(url.replace("https://app", "https://api"), "") def extract_nested_values(readable_response: dict, nested_headers: Dict[str, str]) -> None: """ Extracts nested fields from readable_response according to nested_headers keys, and names them according to nested_headers values. Updates readable_response in place. """ for nested_name, new_name in nested_headers.items(): nested_name_parts = nested_name.split(".") nested_value = readable_response for index, part in enumerate(nested_name_parts): nested_value = nested_value.get(part) # type: ignore[assignment] if index == (len(nested_name_parts) - 1): readable_response[new_name] = nested_value elif not nested_value: break def change_timestamp_to_datestring_in_dict(readable_response: dict) -> None: """ Changes the values of the time fields in the given response from epoch timestamp to human readable date format. """ for field in TIME_FIELDS: if epoch_value := readable_response.get(field): # a value of -1 means that it never happened, so we leave the field empty readable_response[field] = timestamp_to_datestring(epoch_value, DATE_FORMAT) if epoch_value != -1 else None def convert_date_to_unix(date_str: str) -> int: """ Convert the given string to milliseconds since epoch. """ if not (date := dateparser.parse(date_str, settings={"TIMEZONE": "UTC"})): raise DemistoException(f'The date "{date_str}" given is not valid.') return int(date.timestamp() * 1000) def handle_time_filter( base_case: Optional[Dict[str, Any]] = None, unit_value: Optional[str] = None, amount_value: Optional[int] = None, time_from: Optional[str] = None, time_to: Optional[str] = None, ) -> Dict[str, Any]: """ Create the relevant time filter to be sent in the POST request body, under "timeRange". This doesn't deal with the way the time range should be sent in the GET request parameters. """ if (time_from or time_to) and (unit_value or amount_value): raise DemistoException(ERROR_TOO_MANY_ARGS) elif (time_from and not time_to) or (amount_value and not unit_value): raise DemistoException(ERROR_NOT_ENOUGH_ARGS) if unit_value: if amount_value: # amount is only for relative time - defines a window of time from a given point of time in the past until now if unit_value not in RELATIVE_TIME_UNIT_OPTIONS: raise DemistoException(ERROR_RELATIVE_TIME_UNIT) return {"type": "relative", "value": {"amount": arg_to_number(amount_value), "unit": unit_value}} else: # using to_now time - represents a window of time from the start of the time unit given until now if unit_value not in TO_NOW_TIME_UNIT_OPTIONS: raise DemistoException(ERROR_TO_NOW_TIME_UNIT) return {"type": "to_now", "value": unit_value} elif time_to: # using absolute time if time_from: return { "type": "absolute", "value": {"startTime": convert_date_to_unix(time_from), "endTime": convert_date_to_unix(time_to)}, } else: # alert dismissal requires only an end time in the future return {"type": "absolute", "value": {"endTime": convert_date_to_unix(time_to)}} return base_case or TIME_FILTER_BASE_CASE def handle_filters(filters: Optional[List[str]]) -> List[Dict[str, Any]]: """ Creates the list of filters in the format that the request expects. The filters are given from the user as a comma-separated list, in the format of filtername=filtervalue. """ filters_to_send = [] for filter_ in filters or []: split_filter = filter_.split("=") if len(split_filter) != 2 or not split_filter[0] or not split_filter[1]: raise DemistoException( 'Filters should be in the format of "filtername1=filtervalue1,filtername2=filtervalue2". ' f'The filter "{filter_}" doesn\'t meet this requirement.' ) filters_to_send.append({"name": split_filter[0], "operator": "=", "value": split_filter[1]}) return filters_to_send def handle_tags(tags: Optional[List[str]]) -> List[Dict[str, Any]]: """ Creates the list of tags in the format that the request expects. The tags are given from the user as a comma-separated list, in the format of tagkey=tagvalue. """ tags_to_send = [] if tags: for tag in tags: split_tag = tag.split("=") if len(split_tag) != 2 or not split_tag[0] or not split_tag[1]: raise DemistoException( 'Tags should be in the format of "tagkey1=tagvalue1,tagkey2=tagvalue2". ' f'The tag "{tag}" doesn\'t meet this requirement.' ) tags_to_send.append({"key": split_tag[0], "value": split_tag[1]}) return tags_to_send def validate_array_arg(array_arg: List[str], arg_name: str, arg_options: List[str]) -> None: """ Validates that all comma-separated provided arg values are in the available options. """ if not set(array_arg).issubset(arg_options): raise DemistoException(f'{arg_name} values are unexpected, must be of the following: {", ".join(arg_options)}.') def error_file_list_command_args_validation( source_types: List[str], categories: List[str], statuses: List[str], file_types: List[str], search_options: List[str], severities: List[str], ) -> None: """ Validates values for all multi-select args in 'prisma-cloud-error-file-list' command. """ validate_array_arg(categories, "Categories", CATEGORIES_OPTIONS) validate_array_arg(file_types, "File types", FILE_TYPES_OPTIONS) validate_array_arg(search_options, "Search options", SEARCH_OPTIONS_OPTIONS) validate_array_arg(severities, "Severities", SEVERITIES_OPTIONS) validate_array_arg(source_types, "Source types", SOURCE_TYPES_OPTIONS) validate_array_arg(statuses, "Statuses", STATUSES_OPTIONS) def remove_empty_values(value_to_reduce: Union[Dict[str, Any], List, Any]): """ Removes empty values from given dict or list and from the nested dicts and lists in it. """ if isinstance(value_to_reduce, dict): reduced_dict = {} for key, value in value_to_reduce.items(): if reduced_nested_value := remove_empty_values(value): reduced_dict[key] = reduced_nested_value return reduced_dict elif isinstance(value_to_reduce, list): reduced_list = [] for item in value_to_reduce: if reduced_nested_value := remove_empty_values(item): reduced_list.append(reduced_nested_value) return reduced_list return value_to_reduce def get_response_status_header(response: requests.Response) -> str: """ The status of the error raised from Prisma Cloud appears in the response header. This function returns the status header from the response got from Prisma Cloud. """ if hasattr(response, "headers"): return response.headers.get(RESPONSE_STATUS_HEADER, "") return "" def calculate_offset(page_size: int, page_number: int) -> tuple[int, int]: """ Prisma Cloud receives offset and limit arguments. To follow our convention, we receive page_size and page_number arguments and calculate the offset from them. The offset is the start point from which to retrieve values, zero based. It starts at 0. NOTICE: Currently the offset argument is not working in the API, so this is not used until further update by Prisma Cloud. :param page_size: The number of results to show in one page. :param page_number: The page number to show, starts at 1. """ if page_size > PAGE_SIZE_MAX_VALUE: raise DemistoException(f'Maximum "page_size" value is {PAGE_SIZE_MAX_VALUE} (got {page_size}).') return page_size, page_size * (page_number - 1) def extract_namespace(response_items: List[Dict[str, Any]]): """ Extract namespaces from resource list items. """ for item in response_items: for member in item.get("members", []): # members is a list of dict or strs if isinstance(member, str | int): continue if item_namespace := member.get("namespaces", []): item["namespaces"] = item_namespace break def remove_additional_resource_fields(items): if items: for current_item in list(items): data = current_item.get("data", {}) disks = data.get("disks", []) for current_disk in disks: if "shieldedInstanceInitialState" in current_disk: del current_disk["shieldedInstanceInitialState"] metadata = data.get("metadata", {}) metadata_items = metadata.get("items", []) for current_metadata_item in list(metadata_items): if "key" in current_metadata_item and current_metadata_item["key"] == "configure-sh": metadata_items.remove(current_metadata_item) """ FETCH AND MIRRORING HELPER FUNCTIONS """ def translate_severity(alert: Dict[str, Any]) -> float: """ Translate alert severity to XSOAR """ severity = alert.get("policy", {}).get("severity") return PRISMA_TO_XSOAR_SEVERITY.get(severity, IncidentSeverity.UNKNOWN) def expire_stored_ids(fetched_ids: Dict[str, int], updated_last_run_time: int, look_back: int) -> Dict[str, int]: """ Expires stored ids when their alert time will not be fetched in the next fetch. Args: fetched_ids: Dict from fetched ids to the epoch alert time from Prisma Cloud. updated_last_run_time: epoch time for next fetch look_back: minutes to add to the next fetch time Returns: The dict of fetched ids that their time is after the next fetch time. """ if not fetched_ids: return {} cleaned_cache = {} next_fetch_epoch = add_look_back(updated_last_run_time, look_back * 3) # in case look_back needs to be increased # to avoid duplicate incidents, make sure that when increasing this value, to increase it up to a multiplier of 3 each time for fetched_id, alert_time in fetched_ids.items(): if alert_time >= next_fetch_epoch: # keep if it is later cleaned_cache[fetched_id] = alert_time return cleaned_cache def calculate_fetch_time_range( now: int, first_fetch: str, look_back: int = 0, last_run_time: Optional[int] = None ) -> Dict[str, Any]: if last_run_time: last_run_time = add_look_back(int(last_run_time), look_back) else: # first fetch last_run_time = convert_date_to_unix(first_fetch) return {"type": "absolute", "value": {"startTime": last_run_time, "endTime": now}} def add_look_back(last_run_epoch_time: int, look_back_minutes: int) -> int: look_back_epoch = look_back_minutes * 60 * 1000 return last_run_epoch_time - look_back_epoch def fetch_request( client: Client, fetched_ids: Dict[str, int], filters: List[str], limit: int, now: int, time_range: Dict[str, Any] ) -> tuple[List[Dict[str, Any]], Dict[str, int], int]: response = client.alert_search_request( time_range=time_range, filters=filters, detailed="true", sort_by=["alertTime:asc"], # adding sort by 'id:asc' doesn't work limit=limit + len(fetched_ids), ) response_items = response.get("items", []) demisto.debug(f"Finished request, got {len(response_items)} items") updated_last_run_time_epoch = response_items[-1].get("alertTime") if response_items else now incidents = filter_alerts(client, fetched_ids, response_items, limit) # there is a 'nextPageToken' value even if we already got all the results while len(incidents) < limit and response.get("nextPageToken") and response.get("items"): # only page_token is being used, also sending other arguments because it is not stated clearly in the # API documentation response = client.alert_search_request( time_range=time_range, filters=filters, detailed="true", sort_by=["alertTime:asc"], limit=limit + len(fetched_ids), page_token=response.get("nextPageToken"), ) response_items = response.get("items", []) demisto.debug(f"Finished request, got {len(response_items)} items.") updated_last_run_time_epoch = response_items[-1].get("alertTime") if response_items else updated_last_run_time_epoch incidents.extend(filter_alerts(client, fetched_ids, response_items, limit, len(incidents))) return incidents, fetched_ids, updated_last_run_time_epoch def filter_alerts( client: Client, fetched_ids: Dict[str, int], response_items: List[Dict[str, Any]], limit: int, num_of_prev_incidents: int = 0 ) -> List[Dict[str, Any]]: incidents = [] for alert in response_items: alert_id = alert.get("id") if alert_id in fetched_ids: demisto.debug(f"Alert {alert_id} already fetched. Skipping.") # Update alert time if changed (Prisma Cloud may update alert time for the same alert we already fetched, # potentially causing us to re-fetch it). if fetched_ids[alert_id] != alert["alertTime"]: fetched_ids[alert_id] = alert["alertTime"] demisto.debug(f"Overwriting alert time in lookback for alert {alert_id} to be {alert['alertTime']}") continue demisto.debug(f'Processing new fetched alert {alert.get("id")}.') add_mirroring_fields(client, alert) incidents.append(alert_to_incident_context(alert)) fetched_ids[str(alert["id"])] = int(alert["alertTime"]) if len(incidents) + num_of_prev_incidents >= limit: break return incidents def add_mirroring_fields(client: Client, alert: Dict): """ Updates the given Prisma Cloud fetched alert to hold the needed mirroring fields. Args: client: Demisto client. alert: The Prisma Cloud fetched alert. """ alert["mirror_direction"] = client.mirror_direction alert["mirror_instance"] = demisto.integrationInstance() def alert_to_incident_context(alert: Dict[str, Any]) -> Dict[str, Any]: incident_context = { "name": alert.get("policy", {}).get("name", "No policy") + " - " + alert.get("id"), "occurred": timestamp_to_datestring(alert.get("alertTime"), DATE_FORMAT), "severity": translate_severity(alert), "rawJSON": json.dumps(alert), } demisto.debug( f'New PrismaCloud incident is: name: {incident_context["name"]}, occurred: ' f'{incident_context["occurred"]}, severity: {incident_context["severity"]}.' ) return incident_context def get_remote_alert_data(client: Client, remote_alert_id: str) -> tuple[Dict, Dict]: """ Called every time get-remote-data command runs on an alert. Gets the details of the relevant alert entity from the remote system (Prisma Cloud). Takes from the entity only the relevant incoming mirroring fields, and returns the updated_object for the incident selected to mirror in. Args: client: Demisto client. remote_alert_id: The id of the mirrored Prisma Cloud alert. Returns: The raw alert's details, and a dictionary contains only the mirrored fields and their values. """ alert_details = client.alert_get_details_request(alert_id=remote_alert_id, detailed="true") updated_object: Dict[str, Any] = {} for field in INCIDENT_INCOMING_MIRROR_ARGS: mirrored_field_value = demisto.get(alert_details, field, "") if "." in field: # field is nested (currently it is only the policy.name field) # policy.name field was added to the mirrored fields cause this is the field that is used in the default classifier to # classify incident types. Without it, all mirrored alerts will be changed to the default incident type which is # 'Prisma Cloud'. split_field = field.split(".") updated_object[split_field[0]] = {split_field[1]: mirrored_field_value} else: updated_object[field] = mirrored_field_value return alert_details, updated_object def close_incident_in_xsoar(remote_alert_id: str, mirrored_status: str, mirrored_dismissal_note: str) -> Dict: """ Closes an XSOAR incident. Args: remote_alert_id: The id of the mirrored Prisma Cloud alert to be closed. mirrored_status: The status of the mirrored Prisma alert. mirrored_dismissal_note: The dismissal note of the mirrored Prisma alert. Returns: An entry object with relevant data for closing an XSOAR incident. """ demisto.debug(f"Prisma Alert {remote_alert_id} was closed. Closing the mirrored incident in XSOAR") if mirrored_status == "resolved" and mirrored_dismissal_note == "": mirrored_dismissal_note = "resolved" closing_time = datetime.now() parsed_closing_time = closing_time.strftime(DATE_FORMAT) entry = { "Type": EntryType.NOTE, "Contents": { "dbotIncidentClose": True, "rawCloseReason": mirrored_status, "closeReason": f"Alert was {mirrored_status} on Prisma Cloud.", "closeNotes": mirrored_dismissal_note, "closed": parsed_closing_time, }, "ContentsFormat": EntryFormat.JSON, } return entry def reopen_incident_in_xsoar(remote_alert_id: str): """ Reopens an XSOAR incident. Args: remote_alert_id: The id of the mirrored Prisma Cloud alert to be reopened. Returns: An entry object with relevant data for reopening an XSOAR incident. """ demisto.debug(f"Prisma Alert {remote_alert_id} was reopened. Reopening the incident on XSOAR.") entry = {"Type": EntryType.NOTE, "Contents": {"dbotIncidentReopen": True}, "ContentsFormat": EntryFormat.JSON} return entry def set_xsoar_incident_entries(updated_object: Dict[str, Any], remote_alert_id: str) -> Dict | None: """ Extracts the status of the mirrored Prisma alert, and close/reopen the matched XSOAR incident in accordance. Args: updated_object: A dictionary contains the mirrored relevant fields. remote_alert_id: The id of the mirrored Prisma Cloud alert. Returns: An entry object with relevant data for closing or reopening an XSOAR incident. """ mirrored_status = updated_object.get("status") if mirrored_status in set(INCIDENT_INCOMING_MIRROR_CLOSING_STATUSES): # closing incident mirrored_dismissal_note = updated_object.get("dismissalNote", "") entry = close_incident_in_xsoar(remote_alert_id, mirrored_status, mirrored_dismissal_note) return entry elif mirrored_status == INCIDENT_INCOMING_MIRROR_REOPENING_STATUS: # re-opening incident entry = reopen_incident_in_xsoar(remote_alert_id) return entry return None def close_alert_in_prisma_cloud(client: Client, ids: List[str], delta: Dict[str, Any]): """ Close (Dismiss) an alert in Prisma Cloud. Args: client: Demisto client. ids: The IDs of the alerts to be dismissed. delta: A dictionary of fields that changed from the last update - containing only the changed fields. Returns: None. """ close_notes = delta.get("closeNotes") close_reason = delta.get("closeReason") dismissal_note = f"{INCIDENT_OUTGOING_MIRROR_DISMISSAL_NOTE} - Closing Reason: {close_reason}, Closing Notes: {close_notes}." time_filter = handle_time_filter(base_case=TIME_FILTER_BASE_CASE) client.alert_dismiss_request(dismissal_note=dismissal_note, time_range=time_filter, alert_ids=ids) def reopen_alert_in_prisma_cloud(client: Client, ids: List[str]): """ Re-open an alert in Prisma Cloud. Args: client: Demisto client. ids: The IDs of the alerts to be re-opened. Returns: None. """ time_filter = handle_time_filter(base_case=TIME_FILTER_BASE_CASE) client.alert_reopen_request(time_range=time_filter, alert_ids=ids) def whether_to_close_in_prisma_cloud(user_selection: bool, delta: Dict[str, Any]) -> bool: """ Closing in the remote system should happen only when both: 1. The user asked for it. 2. One of the closing fields appears in the delta. The second condition is mandatory so we will not send a closing request at all of the mirroring requests that happen after closing an incident (in case where the incident is updated so there is a delta, but it is not the status that was changed). Args: user_selection: True if the user wants to mirror out closing of an incident ('close_alert' integration parameter), otherwise - False. delta: A dictionary of fields that changed from the last update - containing only the changed fields. Returns: True - if closing the prisma alert is needed, False - otherwise. """ closing_fields = {"closeReason", "closingUserId", "closeNotes"} return user_selection and any(field in delta for field in closing_fields) def whether_to_reopen_in_prisma_cloud(user_selection: bool, delta: Dict[str, Any]) -> bool: """ Re-opening in the remote system should happen only when both: 1. The user asked for it. 2. The delta contains the 'closingUserId' field. The second condition is mandatory so we will not send a re-opening request in case where the incident is updated so there is a delta, but it is not the status that was changed. Args: user_selection: True if the user wants to mirror out re-opening of an incident ('close_alert' integration parameter), otherwise - False. delta: A dictionary of fields that changed from the last update - containing only the changed fields. Returns: True - if re-opening the prisma alert is needed, False - otherwise. """ return user_selection and "closingUserId" in delta def update_remote_alert(client: Client, delta: Dict[str, Any], inc_status: IncidentStatus, incident_id: str): """ Updates the remote prisma alert according to the changes of the mirrored xsaor incident. The possible updates are closing or re-opening the alert. When closing an incident in XSOAR the possible reasons are: False Positive, Duplicate, Other and Resolved. As a result, the remote Prisma alert will be closed with a 'Dismissed' status, and the reason and close notes will be added to the 'Reason' field of the remote alert. * It is not possible to close an incident as 'Resolved' in XSOAR and mark it as 'Resolved' in Prisma, it will be closed with a 'dismissed' status even if the selected reason is 'Resolved'. Args: client: Demisto client. delta: A dictionary of fields that changed from the last update - containing only the changed fields. inc_status: The status of the incident. incident_id: Contains the value of the dbotMirrorId field, which represents the ID of the alert in prisma. Returns: None. """ # XSOAR incident was closed - closing the mirrored prisma alert if inc_status == IncidentStatus.DONE and whether_to_close_in_prisma_cloud(client.close_alert, delta): demisto.debug(f"Closing incident with remote ID {incident_id} in remote system.") close_alert_in_prisma_cloud(client, [incident_id], delta) demisto.debug(f"Remote Incident: {incident_id} was updated successfully.") # XSOAR incident was re-opened - re-opening the mirrored prisma alert elif inc_status == IncidentStatus.ACTIVE and whether_to_reopen_in_prisma_cloud(client.close_alert, delta): demisto.debug(f"Reopening incident with remote ID {incident_id} in remote system.") reopen_alert_in_prisma_cloud(client, [incident_id]) demisto.debug(f"Remote Incident: {incident_id} was updated successfully.") else: demisto.debug(f"Skipping the update of remote incident {incident_id} as it has not closed or re-opened in XSOAR.") """ V1 DEPRECATED COMMAND FUNCTIONS to support backwards compatibility """ RISK_GRADE_NOT_SUPPORTED_MSG = ( 'In the new API version of Prisma Cloud, "risk-grade" argument is not supported ' "and therefore removed from the available command arguments." ) def get_v1_filters(args: Dict[str, Any]) -> List[str]: """ Transform V1 arguments to V2 filters list. """ filters = [] args_name_to_filter_name = { "alert-status": "alert.status", "policy-name": "policy.name", "policy-label": "policy.label", "policy-compliance-standard": "policy.complianceStandard", "cloud-account": "cloud.account", "cloud-account-id": "cloud.accountId", "cloud-region": "cloud.region", "alert-rule-name": "alertRule.name", "resource-id": "resource.id", "resource-name": "resource.name", "resource-type": "resource.type", "alert-id": "alert.id", "cloud-type": "cloud.type", "policy-type": "policy.type", "policy-severity": "policy.severity", } for arg_name, filter_name in args_name_to_filter_name.items(): if arg_value := args.get(arg_name): filters.append(f"{filter_name}={arg_value}") return filters def alert_to_v1_context(alert: Any, args: Dict[str, Any]) -> Dict[str, Any]: """ This was copied from V1 and should not be maintained. Transform a single alert to context struct. """ ec = { "ID": alert.get("id"), "Status": alert.get("status"), "AlertTime": alert.get("alertTime"), "Policy": { "ID": demisto.get(alert, "policy.policyId"), "Name": demisto.get(alert, "policy.name"), "Type": demisto.get(alert, "policy.policyType"), "Severity": demisto.get(alert, "policy.severity"), "Remediable": demisto.get(alert, "policy.remediable"), }, "Resource": { "ID": demisto.get(alert, "resource.id"), "Name": demisto.get(alert, "resource.name"), "Account": demisto.get(alert, "resource.account"), "AccountID": demisto.get(alert, "resource.accountId"), }, } if "resource_keys" in args: # if resource_keys argument was given, include those items from resource.data extra_keys = demisto.getArg("resource_keys") resource_data = {} keys = extra_keys.split(",") for key in keys: resource_data[key] = demisto.get(alert, f"resource.data.{key}") ec["Resource"]["Data"] = resource_data if alert.get("alertRules"): ec["AlertRules"] = [alert_rule.get("name") for alert_rule in alert.get("alertRules")] return ec def format_v1_response(response: Any) -> Any: """ This was copied from V1 and should not be maintained. """ if response and isinstance(response, dict): response = {pascalToSpace(key).replace(" ", ""): format_v1_response(value) for key, value in response.items()} elif response and isinstance(response, list): response = [format_v1_response(item) for item in response] return response def alert_search_v1_command( client: Client, args: Dict[str, Any], return_v1_output: bool ) -> Union[CommandResults, List[Union[CommandResults, str]], Dict]: """ This command is for supporting backwards compatibility, to make transition to V2 easier for users with custom playbooks. """ new_args = { "time_range_unit": args.get("time-range-unit"), "time_range_value": args.get("time-range-value"), "time_range_date_from": args.get("time-range-date-from"), "time_range_date_to": args.get("time-range-date-to"), "filters": get_v1_filters(args), "limit": args.get("limit", DEFAULT_LIMIT), "detailed": "true", } command_results = alert_search_command(client, new_args) if return_v1_output: response = command_results.raw_response context_path = "Redlock.Alert(val.ID === obj.ID)" context: dict = {context_path: []} for alert in response: # type: ignore[attr-defined] context[context_path].append(alert_to_v1_context(alert, args)) context["Redlock.Metadata.CountOfAlerts"] = len(response) # type: ignore[arg-type] command_results = command_results.to_context() command_results["EntryContext"].update(context) # type: ignore[index] if args.get("risk-grade"): return [RISK_GRADE_NOT_SUPPORTED_MSG, command_results] return command_results def alert_get_details_v1_command(client: Client, args: Dict[str, Any], return_v1_output: bool) -> Union[CommandResults, Dict]: """ This command is for supporting backwards compatibility, to make transition to V2 easier for users with custom playbooks. """ new_args = {"alert_id": args.get("alert-id")} command_results = alert_get_details_command(client, new_args) if return_v1_output: response = command_results.raw_response command_results = command_results.to_context() command_results["EntryContext"].update( # type: ignore[index] {"Redlock.Alert(val.ID === obj.ID)": alert_to_v1_context(response, args)} ) return command_results def alert_dismiss_v1_command( client: Client, args: Dict[str, Any], return_v1_output: bool ) -> Union[CommandResults, List[Union[CommandResults, str]], Dict]: """ This command is for supporting backwards compatibility, to make transition to V2 easier for users with custom playbooks. """ new_args = { "alert_ids": args.get("alert-id"), "policy_ids": args.get("policy-id"), "dismissal_note": args.get("dismissal-note"), "snooze_value": args.get("snooze-value"), "snooze_unit": args.get("snooze-unit"), "time_range_unit": args.get("time-range-unit"), "time_range_value": args.get("time-range-value"), "time_range_date_from": args.get("time-range-date-from"), "time_range_date_to": args.get("time-range-date-to"), "filters": get_v1_filters(args), } command_results = alert_dismiss_command(client, new_args) if return_v1_output and args.get("alert-id"): command_results = command_results.to_context() command_results["EntryContext"].update({"Redlock.DismissedAlert.ID": args.get("alert-id")}) # type: ignore[index] if args.get("risk-grade"): return [RISK_GRADE_NOT_SUPPORTED_MSG, command_results] return command_results def alert_reopen_v1_command( client: Client, args: Dict[str, Any], return_v1_output: bool ) -> Union[CommandResults, List[Union[CommandResults, str]], Dict]: """ This command is for supporting backwards compatibility, to make transition to V2 easier for users with custom playbooks. """ new_args = { "alert_ids": args.get("alert-id"), "policy_ids": args.get("policy-id"), "time_range_unit": args.get("time-range-unit"), "time_range_value": args.get("time-range-value"), "time_range_date_from": args.get("time-range-date-from"), "time_range_date_to": args.get("time-range-date-to"), "filters": get_v1_filters(args), } command_results = alert_reopen_command(client, new_args) if return_v1_output and args.get("alert-id"): command_results = command_results.to_context() command_results["EntryContext"].update({"Redlock.ReopenedAlert.ID": args.get("alert-id")}) # type: ignore[index] if args.get("risk-grade"): return [RISK_GRADE_NOT_SUPPORTED_MSG, command_results] return command_results def remediation_command_list_v1_command( client: Client, args: Dict[str, Any], return_v1_output: bool ) -> Union[CommandResults, Dict]: """ This command is for supporting backwards compatibility, to make transition to V2 easier for users with custom playbooks. """ new_args = {"alert_ids": args.get("alert-id"), "all_results": "true"} command_results = remediation_command_list_command(client, new_args) if return_v1_output: response = command_results.raw_response context = [] for alert in response: # type: ignore[attr-defined] details = { "ID": alert.get("alertId"), "Remediation": {"CLI": alert.get("CLIScript"), "Description": alert.get("description")}, } context.append(details) command_results = command_results.to_context() command_results["EntryContext"].update({"Redlock.Alert(val.ID == obj.ID)": context}) # type: ignore[index] return command_results def rql_config_search_v1_command(client: Client, args: Dict[str, Any], return_v1_output: bool) -> Union[CommandResults, Dict]: """ This command is for supporting backwards compatibility, to make transition to V2 easier for users with custom playbooks. """ query = f'{args.get("rql")} limit search records to {args.get("limit", "1")}' new_args = { "query": query, "limit": args.get("limit", "1"), } command_results = config_search_command(client, new_args) if return_v1_output: rql_data = {"Query": query, "Response": format_v1_response(command_results.raw_response)} command_results = command_results.to_context() command_results["EntryContext"].update({"Redlock.RQL(val.Query === obj.Query)": rql_data}) # type: ignore[index] return command_results def config_search_v1_command(client: Client, args: Dict[str, Any], return_v1_output: bool) -> Union[CommandResults, Dict]: """ This command is for supporting backwards compatibility, to make transition to V2 easier for users with custom playbooks. """ new_args = { "query": args.get("query"), "limit": args.get("limit", "100"), "time_range_unit": args.get("time-range-unit"), "time_range_value": args.get("time-range-value"), "time_range_date_from": args.get("time-range-date-from"), "time_range_date_to": args.get("time-range-date-to"), } command_results = config_search_command(client, new_args) if return_v1_output: response = command_results.raw_response command_results = command_results.to_context() command_results["EntryContext"].update({"Redlock.Asset(val.id == obj.id)": response}) # type: ignore[index] return command_results def event_search_v1_command(client: Client, args: Dict[str, Any], return_v1_output: bool) -> Union[CommandResults, Dict]: """ This command is for supporting backwards compatibility, to make transition to V2 easier for users with custom playbooks. """ new_args = { "query": args.get("query"), "limit": args.get("limit", "100"), "time_range_unit": args.get("time-range-unit"), "time_range_value": args.get("time-range-value"), "time_range_date_from": args.get("time-range-date-from"), "time_range_date_to": args.get("time-range-date-to"), } command_results = event_search_command(client, new_args) if return_v1_output: response = command_results.raw_response command_results = command_results.to_context() command_results["EntryContext"].update({"Redlock.Event(val.id == obj.id)": response}) # type: ignore[index] return command_results def network_search_v1_command(client: Client, args: Dict[str, Any], return_v1_output: bool) -> Union[CommandResults, Dict]: """ This command is for supporting backwards compatibility, to make transition to V2 easier for users with custom playbooks. """ new_args = { "query": args.get("query"), "cloud_type": args.get("cloud-type"), "time_range_unit": args.get("time-range-unit"), "time_range_value": args.get("time-range-value"), "time_range_date_from": args.get("time-range-date-from"), "time_range_date_to": args.get("time-range-date-to"), } command_results = network_search_command(client, new_args) if return_v1_output: response = command_results.raw_response command_results = command_results.to_context() command_results["EntryContext"].update( # type: ignore[index] { "Redlock.Network.Node(val.id == obj.id)": response.get("nodes", []), # type: ignore[attr-defined] "Redlock.Network.Connection(val.id == obj.from)": response.get("connections", []), # type: ignore[attr-defined] } ) return command_results def alert_filter_list_v1_command(client: Client, args: Dict[str, Any], return_v1_output: bool) -> Union[CommandResults, Dict]: """ This command is for supporting backwards compatibility, to make transition to V2 easier for users with custom playbooks. """ return alert_filter_list_command(client) """ COMMAND FUNCTIONS """ def alert_filter_list_command(client: Client) -> CommandResults: response = client.alert_filter_list_request() readable_response = [ {"filterName": filter_name, "options": filter_values.get("options"), "staticFilter": filter_values.get("staticFilter")} for filter_name, filter_values in response.items() ] command_results = CommandResults( outputs_prefix="PrismaCloud.AlertFilters", outputs_key_field="filterName", readable_output=tableToMarkdown("Filter Options:", readable_response, removeNull=True, headerTransform=pascalToSpace), outputs=readable_response, raw_response=readable_response, ) return command_results def alert_search_command(client: Client, args: Dict[str, Any]) -> CommandResults: filters = argToList(args.get("filters")) detailed = args.get("detailed", "true") limit = arg_to_number(args.get("limit", DEFAULT_LIMIT)) next_token = args.get("next_token") time_filter = handle_time_filter( base_case=ALERT_SEARCH_BASE_TIME_FILTER, unit_value=args.get("time_range_unit"), amount_value=arg_to_number(args.get("time_range_value")), time_from=args.get("time_range_date_from"), time_to=args.get("time_range_date_to"), ) sort_by = [f'{sort_field}:{args.get("sort_direction")}'] if (sort_field := args.get("sort_field")) else None response = client.alert_search_request(time_filter, filters, limit, detailed, next_token, sort_by) response_items = response.get("items", []) next_page_token = response.get("nextPageToken") for response_item in response_items: change_timestamp_to_datestring_in_dict(response_item) readable_responses = deepcopy(response_items) nested_headers = { "id": "Alert ID", "policy.policyId": "Policy ID", "policy.policyType": "Policy Type", "policy.systemDefault": "Is Policy System Default", "policy.remediable": "Is Policy Remediable", "policy.name": "Policy Name", "policy.deleted": "Is Policy Deleted", "policy.recommendation": "Policy Recommendation", "policy.description": "Policy Description", "policy.severity": "Policy Severity", "policy.remediation.description": "Policy Remediation Description", "policy.remediation.cliScriptTemplate": "Policy Remediation CLI Script", "resource.resourceType": "Resource Type", "resource.name": "Resource Name", "resource.account": "Resource Account", "resource.cloudType": "Resource Cloud Type", "resource.rrn": "Resource RRN", } for readable_response in readable_responses: extract_nested_values(readable_response, nested_headers) headers = ["Alert ID", "reason", "status", "alertTime", "firstSeen", "lastSeen", "lastUpdated"] + list( nested_headers.values() )[1:] output = { "PrismaCloud.AlertPageToken(val.nextPageToken)": {"nextPageToken": next_page_token}, # values are overridden "PrismaCloud.Alert(val.id && val.id == obj.id)": response_items, # values are appended to list based on id } command_results = CommandResults( readable_output=f'Showing {len(readable_responses)} of {response.get("totalRows", 0)} results:\n' + tableToMarkdown("Alerts Details:", readable_responses, headers=headers, removeNull=True, headerTransform=pascalToSpace) + f"### Next Page Token:\n{next_page_token}", outputs=output, raw_response=response_items, ) return command_results def alert_get_details_command(client: Client, args: Dict[str, Any]) -> CommandResults: alert_id = args.get("alert_id") detailed = args.get("detailed", "true") response = client.alert_get_details_request(str(alert_id), detailed) change_timestamp_to_datestring_in_dict(response) readable_response = deepcopy(response) nested_headers = { "id": "Alert ID", "policy.policyId": "Policy ID", "policy.policyType": "Policy Type", "policy.systemDefault": "Is Policy System Default", "policy.remediable": "Is Policy Remediable", "policy.name": "Policy Name", "policy.recommendation": "Policy Recommendation", "policy.description": "Policy Description", "policy.severity": "Policy Severity", "policy.remediation.description": "Policy Remediation Description", "policy.remediation.cliScriptTemplate": "Policy Remediation CLI Script", "policy.labels": "Policy Labels", "resource.resourceType": "Resource Type", "resource.account": "Resource Account", "resource.cloudType": "Resource Cloud Type", "resource.rrn": "Resource RRN", "resource.id": "Resource ID", "resource.accountId": "Resource Account ID", "resource.regionId": "Resource Region ID", "resource.resourceApiName": "Resource Api Name", "resource.url": "Resource Url", } headers = ["Alert ID", "reason", "status", "alertTime", "firstSeen", "lastSeen", "lastUpdated", "eventOccurred"] + list( nested_headers.values() )[1:] extract_nested_values(readable_response, nested_headers) command_results = CommandResults( outputs_prefix="PrismaCloud.Alert", outputs_key_field="id", readable_output=tableToMarkdown( f"Alert {alert_id} Details:", readable_response, headers=headers, removeNull=True, url_keys=["Resource Url"], headerTransform=pascalToSpace, ), outputs=response, raw_response=response, ) return command_results def alert_dismiss_command(client: Client, args: Dict[str, Any]) -> CommandResults: alert_ids = argToList(args.get("alert_ids")) policy_ids = argToList(args.get("policy_ids")) if not alert_ids and not policy_ids: raise DemistoException('You must provide either "alert_ids" or "policy_ids" for dismissing alerts.') dismissal_note = args.get("dismissal_note") filters = argToList(args.get("filters")) snooze_value = arg_to_number(args.get("snooze_value")) snooze_unit = args.get("snooze_unit") dismissal_time_filter = ( handle_time_filter(unit_value=snooze_unit, amount_value=snooze_value) if snooze_value and snooze_unit else None ) time_filter = handle_time_filter( base_case=dismissal_time_filter or TIME_FILTER_BASE_CASE, unit_value=args.get("time_range_unit"), amount_value=arg_to_number(args.get("time_range_value")), time_from=args.get("time_range_date_from"), time_to=args.get("time_range_date_to"), ) client.alert_dismiss_request(str(dismissal_note), time_filter, alert_ids, policy_ids, dismissal_time_filter, filters) command_results = CommandResults( readable_output=( f"### Alerts snoozed successfully.\nSnooze note: {dismissal_note}." if dismissal_time_filter else f"### Alerts dismissed successfully.\nDismissal note: {dismissal_note}." ) ) return command_results def alert_reopen_command(client: Client, args: Dict[str, Any]) -> CommandResults: alert_ids = argToList(args.get("alert_ids")) policy_ids = argToList(args.get("policy_ids")) if not alert_ids and not policy_ids: raise DemistoException('You must provide either "alert_ids" or "policy_ids" for re-opening alerts.') filters = argToList(args.get("filters")) time_filter = handle_time_filter( base_case=TIME_FILTER_BASE_CASE, unit_value=args.get("time_range_unit"), amount_value=arg_to_number(args.get("time_range_value")), time_from=args.get("time_range_date_from"), time_to=args.get("time_range_date_to"), ) client.alert_reopen_request(time_filter, alert_ids, policy_ids, filters) command_results = CommandResults(readable_output="### Alerts re-opened successfully.") return command_results def remediation_command_list_command(client: Client, args: Dict[str, Any]) -> CommandResults: alert_ids = argToList(args.get("alert_ids")) policy_id = args.get("policy_id") if not alert_ids and not policy_id: raise DemistoException('You must provide either "alert_ids" or "policy_id".') limit = arg_to_number(args.get("limit", DEFAULT_LIMIT)) all_results = argToBoolean(args.get("all_results", "false")) time_filter = handle_time_filter( base_case=TIME_FILTER_BASE_CASE, unit_value=args.get("time_range_unit"), amount_value=arg_to_number(args.get("time_range_value")), time_from=args.get("time_range_date_from"), time_to=args.get("time_range_date_to"), ) try: response = client.remediation_command_list_request(time_filter, alert_ids, policy_id) description = response.get("cliDescription") script_impact = response.get("scriptImpact") readable_response = [ {"description": description, "scriptImpact": script_impact, "alertId": alert_id, "CLIScript": cli_script} for alert_id, cli_script in response.get("alertIdVsCliScript", {}).items() ] total_response_amount = len(readable_response) if not all_results and limit and readable_response: demisto.debug(f"Returning results only up to limit={limit}, from {len(readable_response)} results returned.") readable_response = readable_response[:limit] except DemistoException as de: if not (hasattr(de, "res") and hasattr(de.res, "status_code")): raise if de.res.status_code == 400: return CommandResults( readable_output="Policy type disallowed using this remediation api. Cannot remediate multiple policy alerts." ) return CommandResults( readable_output=f'Remediation unavailable{" for the time given" if time_filter != TIME_FILTER_BASE_CASE else ""}.' ) command_results = CommandResults( outputs_prefix="PrismaCloud.AlertRemediation", outputs_key_field="alertId", readable_output=f"Showing {len(readable_response)} of {total_response_amount} results:\n" + tableToMarkdown("Remediation Command List:", readable_response, removeNull=True, headerTransform=pascalToSpace), outputs=readable_response, raw_response=readable_response, ) return command_results def alert_remediate_command(client: Client, args: Dict[str, Any]) -> CommandResults: alert_id = args.get("alert_id") try: client.alert_remediate_request(str(alert_id)) readable_response = {"alertId": alert_id, "successful": True} # context output that states the remediation was successful readable_output = f"Alert {alert_id} remediated successfully." except DemistoException as de: if not (hasattr(de, "res") and hasattr(de.res, "status_code")): raise status = json.loads(get_response_status_header(de.res)) status = status if isinstance(status, dict) else status[0] error_value = status.get("subject", "") failure_reason = str(status.get("i18nKey", "")).replace("_", " ") readable_response = {"alertId": alert_id, "successful": False, "failureReason": failure_reason, "errorValue": error_value} readable_output = tableToMarkdown( f"Remediation Failed For Alert {alert_id}:", readable_response, removeNull=True, headerTransform=pascalToSpace ) if de.res.status_code == 406: return_error( message=f"Remediation Failed For Alert {alert_id}.\n" f"Failure reason: {failure_reason}.\nError value: {error_value}", error=de, outputs={"PrismaCloud.AlertRemediation(val.alertId === obj.alertId)": readable_response}, ) command_results = CommandResults( outputs_prefix="PrismaCloud.AlertRemediation", outputs_key_field="alertId", readable_output=readable_output, outputs=readable_response, raw_response=readable_response, ) return command_results def config_search_command(client: Client, args: Dict[str, Any]) -> CommandResults: query = args.get("query") heuristic_search = args.get("heuristic_search", "true") limit = arg_to_number(args.get("limit", DEFAULT_LIMIT)) time_filter = handle_time_filter( base_case=TIME_FILTER_BASE_CASE, unit_value=args.get("time_range_unit"), amount_value=arg_to_number(args.get("time_range_value")), time_from=args.get("time_range_date_from"), time_to=args.get("time_range_date_to"), ) search_id = args.get("search_id") sort_direction = args.get("sort_direction", "desc") sort_field = args.get("sort_field", "insertTs") if any([sort_direction, sort_field]) and not all([sort_direction, sort_field]): raise DemistoException("Both sort direction and field must be specified if sorting.") include_resource_json = args.get("include_resource_json", "true") include_additional_resource_fields = argToBoolean(args.get("include_additional_resource_fields", "false")) demisto.debug( f"Searching for config with the following params: {query=}, {limit=}, {time_filter=}, {include_resource_json=}," f" {include_additional_resource_fields=}, {heuristic_search=}" ) response_items = client.config_search_request( time_filter, str(query), limit, search_id, sort_direction, sort_field, include_resource_json, heuristic_search ) if not include_additional_resource_fields: remove_additional_resource_fields(response_items) for response_item in response_items: change_timestamp_to_datestring_in_dict(response_item) headers = [ "name", "id", "cloudType", "service", "accountName", "regionName", "deleted", "accountId", "assetId", "createdTs", "insertTs", "regionId", "resourceType", "rrn", ] command_results = CommandResults( outputs_prefix="PrismaCloud.Config", outputs_key_field="assetId", readable_output=f"Showing {len(response_items)} results:\n" + tableToMarkdown( "Configuration Details:", response_items, headers=headers, removeNull=True, headerTransform=pascalToSpace ), outputs=response_items, raw_response=response_items, ) return command_results def event_search_command(client: Client, args: Dict[str, Any]) -> CommandResults: query = args.get("query") limit = arg_to_number(args.get("limit", DEFAULT_LIMIT)) time_filter = handle_time_filter( base_case=TIME_FILTER_BASE_CASE, unit_value=args.get("time_range_unit"), amount_value=arg_to_number(args.get("time_range_value")), time_from=args.get("time_range_date_from"), time_to=args.get("time_range_date_to"), ) sort_by = ( [ { "field": sort_field, "direction": args.get("sort_direction"), } ] if (sort_field := args.get("sort_field")) else None ) response = client.event_search_request(time_filter, str(query), limit, sort_by) response_items = response.get("data", {}).get("items", []) for response_item in response_items: change_timestamp_to_datestring_in_dict(response_item) headers = [ "subject", "accountName", "name", "source", "ip", "eventTs", "countryName", "stateName", "cityName", "location", "account", "regionId", "type", "id", "role", "accessKeyUsed", "success", "internal", ] command_results = CommandResults( outputs_prefix="PrismaCloud.Event", outputs_key_field="id", readable_output=f'Showing {len(response_items)} of {response.get("data", {}).get("totalRows", 0)} results:\n' + tableToMarkdown("Event Details:", response_items, headers=headers, removeNull=True, headerTransform=pascalToSpace), outputs=response_items, raw_response=response_items, ) return command_results def network_search_command(client: Client, args: Dict[str, Any]) -> CommandResults: query = args.get("query") search_id = args.get("search_id") cloud_type = args.get("cloud_type") time_filter = handle_time_filter( base_case=TIME_FILTER_BASE_CASE, unit_value=args.get("time_range_unit"), amount_value=arg_to_number(args.get("time_range_value")), time_from=args.get("time_range_date_from"), time_to=args.get("time_range_date_to"), ) response = client.network_search_request(str(query), time_filter, search_id, cloud_type) response_items = response.get("data", {}) nodes = response_items.get("nodes", []) connections = response_items.get("connections", []) output = { "PrismaCloud.Network.Node(val.id && val.id == obj.id)": nodes, # values are appended to list based on id "PrismaCloud.Network.Connection(val.from && val.from == obj.from && val.to && val.to == obj.to)": connections, # values are appended to list based on 'from' and 'to' keys } command_results = CommandResults( readable_output="## Network Details\n" + tableToMarkdown( "Nodes:", nodes, headers=["id", "name", "ipAddr", "grouped", "suspicious", "vulnerable"], removeNull=True, headerTransform=pascalToSpace, ) + tableToMarkdown( "Connections:", connections, headers=["from", "to", "label", "suspicious"], removeNull=True, headerTransform=pascalToSpace, ), outputs=output, raw_response=response_items, ) return command_results def trigger_scan_command(client: Client) -> CommandResults: response = client.trigger_scan_request() command_results = CommandResults( readable_output=tableToMarkdown("Trigger Scan Results:", response, removeNull=False, headerTransform=pascalToSpace), ) return command_results def error_file_list_command(client: Client, args: Dict[str, Any]) -> CommandResults: cicd_run_id = args.get("cicd_run_id") if cicd_run_id: arg_to_number(cicd_run_id) # for input validation or readable errors cicd_run_id = float(cicd_run_id) authors = argToList(args.get("authors")) branch = args.get("branch") categories = argToList(args.get("categories")) code_status = args.get("code_status") file_types = argToList(args.get("file_types")) repository = args.get("repository") repository_id = args.get("repository_id") search_options = argToList(args.get("search_options")) search_text = args.get("search_text", "") search_title = args.get("search_title") severities = argToList(args.get("severities")) source_types = argToList(args.get("source_types")) tags = argToList(args.get("tags")) statuses = argToList(args.get("statuses")) limit = arg_to_number(args.get("limit", DEFAULT_LIMIT)) all_results = argToBoolean(args.get("all_results", "false")) error_file_list_command_args_validation(source_types, categories, statuses, file_types, search_options, severities) response = client.error_file_list_request( repository=str(repository), source_types=source_types, cicd_run_id=cicd_run_id, authors=authors, branch=branch, categories=categories, code_status=code_status, file_types=file_types, repository_id=repository_id, search_options=search_options, search_text=search_text, search_title=search_title, severities=severities, tags=tags, statuses=statuses, ) response_items = response.get("data", []) total_response_amount = len(response_items) if not all_results and limit and response_items: demisto.debug(f"Returning results only up to {limit=}, from {len(response_items)} results returned.") response_items = response_items[:limit] headers = ["filePath", "suppressedErrorsCount", "passedCount", "openErrorsCount", "errorsCount", "fixedCount", "type"] command_results = CommandResults( outputs_prefix="PrismaCloud.ErrorFile", outputs_key_field="filePath", readable_output=f"Showing {len(response_items)} of {total_response_amount} results:\n" + tableToMarkdown( "Files Error Details:", response_items, headers=headers, removeNull=True, url_keys=["url"], headerTransform=pascalToSpace, ), outputs=response_items, raw_response=response_items, ) return command_results def resource_get_command(client: Client, args: Dict[str, Any]) -> CommandResults: rrn = args.get("rrn") response = client.resource_get_request(str(rrn)) change_timestamp_to_datestring_in_dict(response) headers = [ "rrn", "id", "name", "url", "accountId", "accountName", "cloudType", "regionId", "regionName", "service", "resourceType", "insertTs", "deleted", "vpcId", "vpcName", "tags", "riskGrade", "hasNetwork", "hasExternalFinding", "hasExternalIntegration", "allowDrillDown", "hasExtFindingRiskFactors", ] command_results = CommandResults( outputs_prefix="PrismaCloud.Resource", outputs_key_field="rrn", readable_output=tableToMarkdown( "Resource Details:", response, headers=headers, removeNull=True, url_keys=["url"], headerTransform=pascalToSpace ), outputs=response, raw_response=response, ) return command_results def resource_list_command(client: Client, args: Dict[str, Any]) -> CommandResults: list_type = args.get("list_type") namespace = args.get("namespace") limit = arg_to_number(args.get("limit", DEFAULT_LIMIT)) all_results = argToBoolean(args.get("all_results", "false")) response_items = client.resource_list_request(list_type) extract_namespace(response_items) if namespace and response_items: response_items = [item for item in response_items if namespace in item.get("namespaces", [])] total_response_amount = len(response_items) if not all_results and limit and response_items: demisto.debug(f"Returning results only up to {limit=}, from {len(response_items)} results returned.") response_items = response_items[:limit] for response_item in response_items: change_timestamp_to_datestring_in_dict(response_item) headers = ["name", "id", "resourceListType", "description", "lastModifiedBy"] command_results = CommandResults( outputs_prefix="PrismaCloud.ResourceList", outputs_key_field="id", readable_output=f"Showing {len(response_items)} of {total_response_amount} results:\n" + tableToMarkdown("Resources Details:", response_items, headers=headers, removeNull=True, headerTransform=pascalToSpace), outputs=response_items, raw_response=response_items, ) return command_results def user_roles_list_command(client: Client, args: Dict[str, Any]) -> CommandResults: role_id = args.get("role_id") resource_list_name = args.get("resource_list_name") limit = arg_to_number(args.get("limit", DEFAULT_LIMIT)) all_results = argToBoolean(args.get("all_results", "false")) if role_id: response_items = client.user_roles_list_request(str(role_id)) response_items = [response_items] if response_items else [] else: response_items = client.all_user_roles_list_request() # reduce response to hold only items that are associated with resource_list_name if resource_list_name and response_items: response_items = [ item for item in response_items if resource_list_name in [resource.get("name") for resource in item.get("resourceLists", [])] ] total_response_amount = len(response_items) if not all_results and limit and response_items: demisto.debug(f"Returning results only up to {limit=}, from {len(response_items)} results returned.") response_items = response_items[:limit] for response_item in response_items: change_timestamp_to_datestring_in_dict(response_item) headers = ["name", "id", "roleType", "description"] command_results = CommandResults( outputs_prefix="PrismaCloud.UserRoles", outputs_key_field="id", readable_output=f"Showing {len(response_items)} of {total_response_amount} results:\n" + tableToMarkdown("User Roles Details:", response_items, headers=headers, removeNull=True, headerTransform=pascalToSpace), outputs=response_items, raw_response=response_items, ) return command_results def users_list_command(client: Client, args: Dict[str, Any]) -> CommandResults: usernames = argToList(args.get("usernames")) limit = arg_to_number(args.get("limit", DEFAULT_LIMIT)) all_results = argToBoolean(args.get("all_results", "false")) response_items = client.users_list_request() # reduce response to hold only items that are associated with the provided usernames if usernames and response_items: response_items = [item for item in response_items if item.get("username") in usernames] total_response_amount = len(response_items) if not all_results and limit and response_items: demisto.debug(f"Returning results only up to {limit=}, from {len(response_items)} results returned.") response_items = response_items[:limit] for response_item in response_items: change_timestamp_to_datestring_in_dict(response_item) roles = [] for role in response_item.get("roles", []): roles.append(role.get("name")) response_item["roles names"] = roles headers = ["displayName", "email", "enabled", "username", "type", "roles names"] command_results = CommandResults( outputs_prefix="PrismaCloud.Users", outputs_key_field="username", readable_output=f"Showing {len(response_items)} of {total_response_amount} results:\n" + tableToMarkdown("Users Details:", response_items, headers=headers, removeNull=True, headerTransform=pascalToSpace), outputs=response_items, raw_response=response_items, ) return command_results def account_list_command(client: Client, args: Dict[str, Any]) -> CommandResults: exclude_account_group_details = args.get("exclude_account_group_details", "false") limit = arg_to_number(args.get("limit", DEFAULT_LIMIT)) all_results = argToBoolean(args.get("all_results", "false")) response = client.account_list_request(exclude_account_group_details) total_response_amount = len(response) if not all_results and limit and response: demisto.debug(f"Returning results only up to {limit=}, from {len(response)} results returned.") response = response[:limit] for response_item in response: change_timestamp_to_datestring_in_dict(response_item) headers = [ "accountId", "name", "cloudType", "accountType", "enabled", "addedOn", "lastModifiedTs", "lastModifiedBy", "storageScanEnabled", "protectionMode", "ingestionMode", "deploymentType", "status", ] command_results = CommandResults( outputs_prefix="PrismaCloud.Account", outputs_key_field="accountId", readable_output=f"Showing {len(response)} of {total_response_amount} results:\n" + tableToMarkdown("Accounts Details:", response, headers=headers, removeNull=True, headerTransform=pascalToSpace), outputs=response, raw_response=response, ) return command_results def account_status_get_command(client: Client, args: Dict[str, Any]) -> CommandResults: account_ids = argToList(args.get("account_ids")) responses = [] for account_id in account_ids: if response := client.account_status_get_request(account_id): response[0]["accountId"] = account_id responses.append(response[0]) headers = ["accountId", "name", "status", "message", "remediation"] command_results = CommandResults( outputs_prefix="PrismaCloud.Account", outputs_key_field="accountId", readable_output=tableToMarkdown( "Accounts Status Details:", responses, headers=headers, removeNull=True, headerTransform=pascalToSpace ), outputs=responses, raw_response=responses, ) return command_results def account_owner_list_command(client: Client, args: Dict[str, Any]) -> CommandResults: account_ids = argToList(args.get("account_ids")) responses = [] for account_id in account_ids: response = client.account_owner_list_request(account_id) responses.append({"accountId": account_id, "emails": response}) command_results = CommandResults( outputs_prefix="PrismaCloud.Account", outputs_key_field="accountId", readable_output=tableToMarkdown("Accounts Owner Details:", responses, removeNull=True, headerTransform=pascalToSpace), outputs=responses, raw_response=responses, ) return command_results def host_finding_list_command(client: Client, args: Dict[str, Any]) -> CommandResults: rrn = args.get("rrn") limit = arg_to_number(args.get("limit", DEFAULT_LIMIT)) all_results = argToBoolean(args.get("all_results", "false")) finding_types = argToList(args.get("finding_types")) finding_types = [finding_type.lower() for finding_type in finding_types] validate_array_arg(finding_types, "Finding types", FINDING_TYPES_OPTIONS) risk_factors = argToList(args.get("risk_factors")) risk_factors = [risk_factor.upper() for risk_factor in risk_factors] validate_array_arg(risk_factors, "Risk factors", RISK_FACTORS_OPTIONS) response = client.host_finding_list_request(str(rrn), finding_types, risk_factors) total_response_amount = len(response) if not all_results and limit and response: demisto.debug(f"Returning results only up to {limit=}, from {len(response)} results returned.") response = response[:limit] for response_item in response: change_timestamp_to_datestring_in_dict(response_item) readable_responses = deepcopy(response) nested_headers = { "sourceData.accountId": "Source Data Account ID", "sourceData.arn": "ARN", } headers = [ "accountId", "regionId", "findingId", "type", "source", "severity", "status", "createdOn", "updatedOn", "normalizedNames", "scanId", "resourceCloudId", "Source Data Account ID", "ARN", "title", "description", "resourceUrl", ] for readable_response in readable_responses: extract_nested_values(readable_response, nested_headers) command_results = CommandResults( outputs_prefix="PrismaCloud.HostFinding", outputs_key_field="findingId", readable_output=f"Showing {len(readable_responses)} of {total_response_amount} results:\n" + tableToMarkdown( "Host Finding Details:", readable_responses, headers=headers, removeNull=True, url_keys=["resourceUrl"], headerTransform=pascalToSpace, ), outputs=response, raw_response=response, ) return command_results def permission_list_command(client: Client, args: Dict[str, Any]) -> CommandResults: user_id = args.get("user_id") query = args.get("query") limit = arg_to_number(args.get("limit", DEFAULT_LIMIT)) next_token = args.get("next_token") if not query and not next_token: raise DemistoException('You must provide either "query" or "next_token" for getting permission list.') if next_token and (user_id or query): raise DemistoException('You can\'t provide "next_token" with "user_id" or "query".') if query: response = client.permission_list_request(query, limit, user_id) # type: ignore[arg-type] response = response.get("data", {}) else: response = client.permission_list_next_page_request(str(next_token), limit) # type: ignore[arg-type] response_items = response.get("items", []) next_page_token = response.get("nextPageToken") readable_responses = deepcopy(response_items) nested_headers = { "destCloudType": "destinationCloudType", "destCloudServiceName": "destinationCloudServiceName", "destResourceType": "destinationResourceType", } for readable_response in readable_responses: extract_nested_values(readable_response, nested_headers) headers = [ "id", "sourceCloudType", "sourceCloudAccount", "sourceResourceId", "destinationCloudType", "destinationCloudServiceName", "destinationResourceType", "effectiveActionName", "grantedByCloudType", "grantedByCloudPolicyId", "grantedByCloudPolicyName", "grantedByCloudPolicyType", "grantedByCloudPolicyRrn", "grantedByCloudEntityId", "grantedByCloudEntityName", "grantedByCloudEntityRrn", ] output = { "PrismaCloud.PermissionPageToken(val.nextPageToken)": {"nextPageToken": next_page_token}, # values are overridden "PrismaCloud.Permission(val.id && val.id == obj.id)": response_items, # values are appended to list based on id } command_results = CommandResults( readable_output=f'Showing {len(readable_responses)} of {response.get("totalRows", 0)} results:\n' + tableToMarkdown( "Permissions Details:", readable_responses, headers=headers, removeNull=True, headerTransform=pascalToSpace ) + f"### Next Page Token:\n{next_page_token}", outputs=output, raw_response=response_items, ) return command_results def fetch_incidents( client: Client, last_run: Dict[str, Any], params: Dict[str, Any] ) -> tuple[List[Dict[str, Any]], Dict[str, int], int]: """ Retrieve new incidents periodically based on pre-defined instance parameters """ last_run_time = last_run.get("time") now = convert_date_to_unix("now") first_fetch = params.get("first_fetch", FETCH_DEFAULT_TIME) look_back = arg_to_number(params.get("look_back", FETCH_LOOK_BACK_TIME)) or FETCH_LOOK_BACK_TIME time_range = calculate_fetch_time_range(now, first_fetch, look_back, last_run_time) fetched_ids = last_run.get("fetched_ids", {}) limit = arg_to_number(params.get("max_fetch", MAX_INCIDENTS_TO_FETCH)) or MAX_INCIDENTS_TO_FETCH filters = argToList(params.get("filters")) incidents, fetched_ids, updated_last_run_time = fetch_request(client, fetched_ids, filters, limit, now, time_range) updated_last_run_time = max(convert_date_to_unix(first_fetch), updated_last_run_time) demisto.debug(f"Fetched {len(incidents)} incidents, {updated_last_run_time=}") ids_to_insert = expire_stored_ids(fetched_ids, updated_last_run_time, look_back) return incidents, ids_to_insert, updated_last_run_time def access_key_create_command(client: Client, args: Dict[str, Any]) -> CommandResults: """ Perform an API request to create an access key using the provided client. Args: - client (Client): An instance of the client used to make the API request. - args (Dict[str, Any]): A dictionary containing any additional arguments required for the API request. Returns: - CommandResults: An object containing the raw response and table representation of the access key. """ access_key = client.access_key_creation(args) markdown_table = tableToMarkdown( "PrismaCloud Access Key Creation", access_key, headers=["id", "secretKey"], headerTransform=pascalToSpace ) return CommandResults( outputs_prefix="PrismaCloud.AccessKeys", outputs_key_field="id", outputs=access_key, raw_response=access_key, readable_output=markdown_table, ) def get_access_keys_command(client: Client, args: Dict[str, Any]) -> CommandResults: """ Get information about specific access key or a list of all access keys. Args: - client (Client): An instance of the client used to make the API request. - args (Dict[str, Any]): A dictionary that may contain access-key ID argument for specific access-key Returns: - CommandResults: An object containing the response and table representation of the access key(s). """ return get_access_key_by_id(client, args) if args.get("access-key") else get_access_keys_list(client, args) def get_access_key_by_id(client: Client, args: Dict[str, Any]) -> CommandResults: """ Get specific information about an access key using the provided client. Args: - client (Client): An instance of the client used to make the API request. - args (Dict[str, Any]): A dictionary containing access-key ID arguments required for the API request. Returns: - CommandResults: An object containing the raw response and table representation of the access key information. """ access_key = client.get_access_key_by_id(args) if access_key.get("expiresOn"): access_key["expiresOn"] = timestamp_to_datestring(access_key.get("expiresOn"), DATE_FORMAT) markdown_table = tableToMarkdown( "PrismaCloud Access Key", access_key, headers=["id", "name", "expiresOn"], headerTransform=pascalToSpace ) return CommandResults( outputs_prefix="PrismaCloud.AccessKeys", outputs_key_field="id", outputs=access_key, raw_response=access_key, readable_output=markdown_table, ) def get_access_keys_list(client: Client, args: Dict[str, Any]) -> CommandResults: """ Get a list of access keys using the provided client. Args: - client (Client): An instance of the client used to make the API request. - args (Dict[str, Any]): A dictionary containing any additional arguments required for the API request, including an optional 'limit' to restrict the number of access keys returned. Returns: - CommandResults: An object containing the raw response and table representation of the access key list. """ access_keys = client.get_access_keys_list() limit = int(args.get("limit", DEFAULT_LIMIT)) limited_access_keys_list = access_keys[:limit] for access_key in limited_access_keys_list: access_key["createdTs"] = timestamp_to_datestring(access_key.get("createdTs"), DATE_FORMAT) access_key["lastUsedTime"] = timestamp_to_datestring(access_key.get("lastUsedTime"), DATE_FORMAT) access_key["expiresOn"] = ( timestamp_to_datestring(access_key.get("expiresOn"), DATE_FORMAT) if access_key.get("expiresOn") != 0 else "" ) access_key["roleId"] = access_key.get("role", {}).get("id", "") access_key["roleName"] = access_key.get("role", {}).get("name", "") markdown_table = tableToMarkdown( "PrismaCloud Access Keys", limited_access_keys_list, headers=[ "id", "name", "createdBy", "createdTs", "lastUsedTime", "status", "expiresOn", "roleId", "roleName", "roleType", "username", ], headerTransform=pascalToSpace, ) return CommandResults( outputs_prefix="PrismaCloud.AccessKeys", outputs_key_field="id", outputs=access_keys, raw_response=access_keys, readable_output=markdown_table, ) def access_key_disable_command(client: Client, args: Dict[str, Any]) -> CommandResults: """ Disable an access key using the provided client. Args: - client (Client): An instance of the client used to make the API request. - args (Dict[str, Any]): A dictionary containing the 'access-key' ID for disabling the access key. Returns: - CommandResults: An object containing the readable output to announce that the access key has been disabled. """ access_key = args.get("access-key", "") client.patch_access_key_disable(access_key) return CommandResults( readable_output=f"Access key {access_key} was disabled successfully", ) def access_key_enable_command(client: Client, args: Dict[str, Any]) -> CommandResults: """ Enable an access key using the provided client. Args: - client (Client): An instance of the client used to make the API request. - args (Dict[str, Any]): A dictionary containing the 'access-key' ID for enabling the access key. Returns: - CommandResults: An object containing the readable output to announce that the access key has been enabled. """ access_key = args.get("access-key", "") client.patch_access_key_enable(access_key) return CommandResults( readable_output=f"Access key {access_key} was enabled successfully", ) def access_key_delete_command(client: Client, args: Dict[str, Any]) -> CommandResults: """ Delete an access key using the provided client. Args: - client (Client): An instance of the client used to make the API request. - args (Dict[str, Any]): A dictionary containing the 'access-key' ID for deleting the access key. Returns: - CommandResults: An object containing the readable output to announce that the access key has been deleted. """ access_key = args.get("access-key", "") client.access_key_deletion(access_key) return CommandResults( readable_output=f"Access key {access_key} was successfully deleted successfully", ) """ MIRRORING COMMANDS """ def get_modified_remote_data_command( client: Client, args: Dict[str, str], params: Dict[str, Any] ) -> GetModifiedRemoteDataResponse: """ Gets the modified remote alerts IDs. Args: client: Demisto client. args: last_update: The last time we retrieved modified incidents. params: Demisto params. Returns: GetModifiedRemoteDataResponse object, which contains a list of the retrieved alerts IDs. """ remote_args = GetModifiedRemoteDataArgs(args) last_update = remote_args.last_update parsed_date = dateparser.parse(last_update, settings={"TIMEZONE": "UTC"}) # convert to utc format if not parsed_date: raise DemistoException(f"could not parse {last_update}") last_update_timestamp = parsed_date.strftime(DATE_FORMAT) demisto.debug(f"Remote arguments last_update in UTC is {last_update_timestamp}") detailed = "false" sort_by = ["alertTime:asc"] time_filter = handle_time_filter(time_from=last_update, time_to="now") filters = argToList(params.get("filters")) # According to the PM of prisma cloud the following filter provide us with all the alerts that their status has been changed. # It is not yet documented in the Prisma Cloud API reference - for more info see this issue: # https://jira-hq.paloaltonetworks.local/browse/CIAC-5504. filters.append("timeRange.type=ALERT_STATUS_UPDATED") # Removes any status-related filter to retrieve all the relevant statuses (open, resolved, dismissed and snoozed) for status_filter in ["alert.status=open", "alert.status=dismissed", "alert.status=snoozed", "alert.status=resolved"]: if status_filter in set(filters): filters.remove(status_filter) response = client.alert_search_request(time_range=time_filter, filters=filters, detailed=detailed, sort_by=sort_by) response_items = response.get("items", []) modified_records_ids = [str(item.get("id")) for item in response_items] demisto.debug(f"Detected {len(modified_records_ids)} modified alerts in Prisma Cloud") return GetModifiedRemoteDataResponse(modified_records_ids) def get_remote_data_command(client: Client, args: Dict[str, Any]) -> GetRemoteDataResponse: """ Returns an updated remote alert. Args: client: Demisto client. args: id: alert id to retrieve. lastUpdate: when was the last time we retrieved data. Returns: GetRemoteDataResponse object, which contains the alert data to update. """ remote_args = GetRemoteDataArgs(args) remote_alert_id = remote_args.remote_incident_id entries = [] try: demisto.debug( f"Performing get-remote-data command with incident id: {remote_alert_id} " f"and last_update: {remote_args.last_update}" ) mirrored_data, updated_object = get_remote_alert_data(client, remote_alert_id) if updated_object and client.close_incident: demisto.debug(f"Update incident {remote_alert_id} with fields: {updated_object}") entry = set_xsoar_incident_entries(updated_object, remote_alert_id) if entry: entries.append(entry) if not updated_object: demisto.debug(f"No delta was found for incident id: {remote_alert_id}.") return GetRemoteDataResponse(mirrored_object=updated_object, entries=entries) except Exception as e: demisto.debug(f"Error in Prisma Cloud v2 incoming mirror for incident: {remote_alert_id}\nError message: {e!s}") if not mirrored_data: mirrored_data = {"id": remote_alert_id} mirrored_data["in_mirror_error"] = str(e) return GetRemoteDataResponse(mirrored_object=mirrored_data, entries=[]) def update_remote_system_command(client: Client, args: Dict[str, Any]) -> str: """ Mirrors out local changes (closing or reopening of an xsoar incident) to the remote system (Prisma Cloud). To determine a closing of an XSOAR incident that should be mirrored to Prisma we check that: 1. parsed_args.incident_changed = True (meaning the incident has changed). 2. Incident status is Done (=2). 3. The delta contains at least one of the following fields: 'closeReason', 'closingUserId', 'closeNotes'. To determine a re-opening of an XSOAR incident that should be mirrored to Prisma we check that: 1. parsed_args.incident_changed = True (meaning the incident has changed). 2. Incident status is Active (=1). 3. The delta contains the 'closingUserId'. These conditions should be sufficient. In any other case, the change in XSOAR won't be mirrored to the remote system. Args: client: Demisto client. args: A dictionary containing the data regarding a modified incident, including: data, entries, incident_changed, remote_incident_id, inc_status and delta. Returns: The remote incident id that was modified. """ parsed_args = UpdateRemoteSystemArgs(args) delta = parsed_args.delta remote_incident_id = parsed_args.remote_incident_id try: if parsed_args.incident_changed: incident_status = parsed_args.inc_status demisto.debug( f"Performing update_remote_system command with incident id {remote_incident_id}, incident status" f" {incident_status} and delta {delta}." ) update_remote_alert(client, delta, incident_status, remote_incident_id) else: demisto.debug(f"Skipping the update of remote incident {remote_incident_id} as it has not changed.") except Exception as e: demisto.error(f"Error in Prisma Cloud V2 outgoing mirror for incident {remote_incident_id}. Error message: {e!s}") return remote_incident_id def validate_code_issues_list_args(args): license_type = args.get("license_type") args.get("term") search_scopes = args.get("search_scopes") search_term = args.get("search_term") page = args.get("page") page_size = arg_to_number(args.get("page_size")) if (page and not page_size) or (page_size and not page): raise DemistoException("Please provide both `page` and `page_size` arguments.") if page_size and page_size > MAX_LIMIT_FOR_CODE_ISSUES: raise DemistoException("`Page_size` argument can't be more than 1000.") if license_type and license_type not in LICENSE_TYPES: raise DemistoException( "Invalid license type. For the list of valid license types go to- https://pan.dev/prisma-cloud/api/code/get-periodic-findings/#request" ) if search_scopes and not search_term: raise DemistoException("The `search_term` argument is required when specifying `search_scopes`.") # Create a copy of the dictionary excluding `limit`, `scopes`, and `term` filtered_args = { key: value for key, value in args.items() if key not in ["limit", "search_scopes", "search_term", "page", "page_size"] } # Ensure there is at least one valid filtering argument if not filtered_args: raise DemistoException( "At least one filtering argument is required, excluding `search_scopes`, `search_term`, and `limit`. For example, \ `fixable_only` or 'branch`" ) def get_labels(labels) -> Optional[List]: """ Converts the labels from a code issue into a list of strings, handling both string lists and lists of label dictionaries """ if labels: res = [] for label in labels: if isinstance(label, str): res.append(label) else: res.append(label.get("label")) return res return None def code_issues_list_request_body( fixable_only: Optional[bool] = None, search_scopes: Optional[List[str]] = [], search_term: Optional[str] = None, branch: Optional[str] = None, check_status: Optional[str] = None, git_users: Optional[List[str]] = [], iac_categories: Optional[List[str]] = [], iac_labels: Optional[List[str]] = [], file_types: Optional[List[str]] = [], repositories: Optional[List[str]] = [], secrets_risk_factors: Optional[List[str]] = [], severities: Optional[List[str]] = [], vulnerability_risk_factors: Optional[List[str]] = [], iac_tags: Optional[List[str]] = [], license_type: Optional[List[str]] = [], code_categories: Optional[List[str]] = [], limit: Optional[float] = 50, offset: Optional[float] = 0, ): return assign_params( filters=assign_params( branch=branch, checkStatus=check_status, codeCategories=code_categories, fileTypes=file_types, fixableOnly=fixable_only, gitUsers=git_users, iacCategories=iac_categories, iacLabels=iac_labels, iacTags=iac_tags, licenseType=license_type, repositories=repositories, secretsRiskFactors=secrets_risk_factors, severities=severities, vulnerabilityRiskFactors=vulnerability_risk_factors, ), search=assign_params(scopes=search_scopes, term=search_term), limit=limit, offset=offset, ) def code_issues_list_command(client, args): validate_code_issues_list_args(args) fixable_only = argToBoolean(args.get("fixable_only", False)) search_scopes = argToList(args.get("search_scopes")) search_term = args.get("search_term") branch = args.get("branch") check_status = args.get("check_status") git_users = argToList(args.get("git_users")) iac_categories = argToList(args.get("iac_categories")) iac_labels = argToList(args.get("iac_labels")) file_types = argToList(args.get("file_types")) repositories = argToList(args.get("repositories")) secrets_risk_factors = argToList(args.get("secrets_risk_factors")) severities = argToList(args.get("severities")) vulnerability_risk_factors = argToList(args.get("vulnerability_risk_factors")) iac_tags = argToList(args.get("iac_tags")) license_type = argToList(args.get("license_type")) code_categories = argToList(args.get("code_categories")) limit = arg_to_number(args.get("limit")) or INT_DEFAULT_LIMIT page = arg_to_number(args.get("page")) or DEFAULT_PAGE page_size = arg_to_number(args.get("page_size")) limit_for_request = min(limit, MAX_LIMIT_FOR_CODE_ISSUES) # pagination if page_size: limit_for_request = page_size offset = page * page_size limit = page_size else: offset = 0 has_next = True res_issues: List[Dict] = [] issues_for_readable_output = [] while len(res_issues) < limit and has_next: body = code_issues_list_request_body( fixable_only=fixable_only, search_scopes=search_scopes, search_term=search_term, branch=branch, check_status=check_status, git_users=git_users, iac_categories=iac_categories, iac_labels=iac_labels, file_types=file_types, repositories=repositories, secrets_risk_factors=secrets_risk_factors, severities=severities, vulnerability_risk_factors=vulnerability_risk_factors, iac_tags=iac_tags, license_type=license_type, code_categories=code_categories, limit=limit_for_request, offset=offset, ) response = client.code_issues_list_request(body) res_issues.extend(response["data"]) for issue in response["data"]: issues_for_readable_output.append( { "Repository": issue.get("repository"), "First Detected": issue["firstDetected"], "Policy": issue["policy"], "Severity": issue["severity"], "Labels": get_labels(issue.get("labels")), "Repository Source": issue.get("repositorySource"), } ) has_next = response["hasNext"] offset = len(res_issues) res_issues = res_issues[0:limit] issues_for_readable_output = issues_for_readable_output[0:limit] headers = ["Repository", "First Detected", "Policy", "Severity", "Labels", "Repository Source"] readable_output = tableToMarkdown("Issues list:", issues_for_readable_output, headers, removeNull=True) return CommandResults( outputs_prefix="PrismaCloud.CodeIssue", outputs=res_issues, readable_output=readable_output, raw_response=res_issues ) def get_asset_command(client: Client, args: Dict[str, Any]) -> CommandResults: """ Retrieve information about an asset using the provided client. Args: - client (Client): An instance of the client used to make the API request. - args (Dict[str, Any]): A dictionary containing the 'asset-id' ID for retrieving the asset information. Returns: - CommandResults: An object containing the information about the asset. """ asset_id = args.get("asset_id") finding_type = args.get("finding_type") risk_factors = argToList(args.get("risk_factors")) timeline_item_id = args.get("timeline_item_id") alert_ids = argToList(args.get("alert_ids")) limit = arg_to_number(args.get("limit")) or INT_DEFAULT_LIMIT permission_type = args.get("permission_type") page_token = args.get("page_token") findings_only = argToBoolean(args.get("prisma_cloud_findings_only", False)) vulnerability_info_type_id = args.get("vulnerability_info_type_id") vulnerability_info_type = args.get("vulnerability_info_type") data = assign_params( assetId=asset_id, type="asset", findingType=finding_type, riskFactors=risk_factors, timelineItemId=timeline_item_id, alertIds=alert_ids, limit=limit, permissionType=permission_type, pageToken=page_token, prismaCloudFindingsOnly=findings_only, vulnerabilityInfoTypeId=vulnerability_info_type_id, vulnerabilityInfoType=vulnerability_info_type, ) response = client.get_asset_by_id(data) outputs = response.get("data", {}).get("asset", {}) return CommandResults( outputs_prefix="PrismaCloud.Asset", outputs_key_field="id", outputs=outputs, readable_output=tableToMarkdown( "Asset", outputs, headerTransform=pascalToSpace, sort_headers=False, ), raw_response=response, ) def get_asset_generic_command(client: Client, args: Dict[str, Any]) -> Dict[str, Any]: """ Retrieve specific information about an asset using the provided client. Args: - client (Client): An instance of the client used to make the API request. - args (Dict[str, Any]): A dictionary containing the 'asset-id' ID for retrieving the asset information. Returns: - Dict[str, Any]: A dictionary containing the specific information about the asset. """ asset_id = args.get("asset_id") asset_type = args.get("type") finding_type = args.get("finding_type") risk_factors = argToList(args.get("risk_factors")) timeline_item_id = args.get("timeline_item_id") alert_ids = argToList(args.get("alert_ids")) limit = arg_to_number(args.get("limit")) or INT_DEFAULT_LIMIT permission_type = args.get("permission_type") page_token = args.get("page_token") findings_only = argToBoolean(args.get("prisma_cloud_findings_only", False)) vulnerability_info_type_id = args.get("vulnerability_info_type_id") vulnerability_info_type = args.get("vulnerability_info_type") data = assign_params( assetId=asset_id, type=asset_type, findingType=finding_type, riskFactors=risk_factors, timelineItemId=timeline_item_id, alertIds=alert_ids, limit=limit, permissionType=permission_type, pageToken=page_token, prismaCloudFindingsOnly=findings_only, vulnerabilityInfoTypeId=vulnerability_info_type_id, vulnerabilityInfoType=vulnerability_info_type, ) response = client.get_asset_by_id(data) return response def get_asset_findings_command(client: Client, args: Dict[str, Any]) -> CommandResults: """ Retrieve information about an asset findings using the provided client. Args: - client (Client): An instance of the client used to make the API request. - args (Dict[str, Any]): A dictionary containing the 'asset-id' ID for retrieving the asset information. Returns: - CommandResults: An object containing the information about the asset findings. """ asset_id = args.get("asset_id") finding_type = args.get("finding_type") risk_factors = argToList(args.get("risk_factors")) timeline_item_id = args.get("timeline_item_id") alert_ids = argToList(args.get("alert_ids")) limit = arg_to_number(args.get("limit")) or INT_DEFAULT_LIMIT permission_type = args.get("permission_type") page_token = args.get("page_token") findings_only = argToBoolean(args.get("prisma_cloud_findings_only", False)) vulnerability_info_type_id = args.get("vulnerability_info_type_id") vulnerability_info_type = args.get("vulnerability_info_type") data = assign_params( assetId=asset_id, type="findings", findingType=finding_type, riskFactors=risk_factors, timelineItemId=timeline_item_id, alertIds=alert_ids, limit=limit, permissionType=permission_type, pageToken=page_token, prismaCloudFindingsOnly=findings_only, vulnerabilityInfoTypeId=vulnerability_info_type_id, vulnerabilityInfoType=vulnerability_info_type, ) response = client.get_asset_by_id(data) outputs = response.get("data", {}).get("asset", {}).get("findings") return CommandResults( outputs_prefix="PrismaCloud.AssetFindings", outputs_key_field="id", outputs=outputs, readable_output=tableToMarkdown( "Asset Findings", outputs, headerTransform=pascalToSpace, sort_headers=False, ), raw_response=response, ) def get_asset_vulnerabilities_command(client: Client, args: Dict[str, Any]) -> CommandResults: """ Retrieve information about an asset vulnerabilities using the provided client. Args: - client (Client): An instance of the client used to make the API request. - args (Dict[str, Any]): A dictionary containing the 'asset-id' ID for retrieving the asset information. Returns: - CommandResults: An object containing the information about the asset vulnerabilities. """ asset_id = args.get("asset_id") finding_type = args.get("finding_type") risk_factors = argToList(args.get("risk_factors")) timeline_item_id = args.get("timeline_item_id") alert_ids = argToList(args.get("alert_ids")) limit = arg_to_number(args.get("limit")) or INT_DEFAULT_LIMIT permission_type = args.get("permission_type") page_token = args.get("page_token") findings_only = argToBoolean(args.get("prisma_cloud_findings_only", False)) vulnerability_info_type_id = args.get("vulnerability_info_type_id") vulnerability_info_type = args.get("vulnerability_info_type") data = assign_params( assetId=asset_id, type="vulnerabilities", findingType=finding_type, riskFactors=risk_factors, timelineItemId=timeline_item_id, alertIds=alert_ids, limit=limit, permissionType=permission_type, pageToken=page_token, prismaCloudFindingsOnly=findings_only, vulnerabilityInfoTypeId=vulnerability_info_type_id, vulnerabilityInfoType=vulnerability_info_type, ) response = client.get_asset_by_id(data) outputs = response.get("data", {}).get("asset", {}).get("vulnerabilities") return CommandResults( outputs_prefix="PrismaCloud.AssetVulnerabilities", outputs_key_field="id", outputs=outputs, readable_output=tableToMarkdown( "Asset Vulnerabilities", outputs, headerTransform=pascalToSpace, sort_headers=False, ), raw_response=response, ) def get_asset_alerts_command(client: Client, args: Dict[str, Any]) -> CommandResults: """ Retrieve information about an asset alerts using the provided client. Args: - client (Client): An instance of the client used to make the API request. - args (Dict[str, Any]): A dictionary containing the 'asset-id' ID for retrieving the asset information. Returns: - CommandResults: An object containing the information about the asset alerts. """ asset_id = args.get("asset_id") finding_type = args.get("finding_type") risk_factors = argToList(args.get("risk_factors")) timeline_item_id = args.get("timeline_item_id") alert_ids = argToList(args.get("alert_ids")) limit = arg_to_number(args.get("limit")) or INT_DEFAULT_LIMIT permission_type = args.get("permission_type") page_token = args.get("page_token") findings_only = argToBoolean(args.get("prisma_cloud_findings_only", False)) vulnerability_info_type_id = args.get("vulnerability_info_type_id") vulnerability_info_type = args.get("vulnerability_info_type") data = assign_params( assetId=asset_id, type="alerts", findingType=finding_type, riskFactors=risk_factors, timelineItemId=timeline_item_id, alertIds=alert_ids, limit=limit, permissionType=permission_type, pageToken=page_token, prismaCloudFindingsOnly=findings_only, vulnerabilityInfoTypeId=vulnerability_info_type_id, vulnerabilityInfoType=vulnerability_info_type, ) response = client.get_asset_by_id(data) outputs = response.get("data", {}).get("asset", {}).get("alerts") return CommandResults( outputs_prefix="PrismaCloud.AssetAlerts", outputs_key_field="id", outputs=outputs, readable_output=tableToMarkdown( "Asset Alerts", outputs, headerTransform=pascalToSpace, sort_headers=False, ), raw_response=response, ) def get_asset_relationships_command(client: Client, args: Dict[str, Any]) -> CommandResults: """ Retrieve information about an asset relationships using the provided client. Args: - client (Client): An instance of the client used to make the API request. - args (Dict[str, Any]): A dictionary containing the 'asset-id' ID for retrieving the asset information. Returns: - CommandResults: An object containing the information about the asset relationships. """ asset_id = args.get("asset_id") finding_type = args.get("finding_type") risk_factors = argToList(args.get("risk_factors")) timeline_item_id = args.get("timeline_item_id") alert_ids = argToList(args.get("alert_ids")) limit = arg_to_number(args.get("limit")) or INT_DEFAULT_LIMIT permission_type = args.get("permission_type") page_token = args.get("page_token") findings_only = argToBoolean(args.get("prisma_cloud_findings_only", False)) vulnerability_info_type_id = args.get("vulnerability_info_type_id") vulnerability_info_type = args.get("vulnerability_info_type") data = assign_params( assetId=asset_id, type="relationships", findingType=finding_type, riskFactors=risk_factors, timelineItemId=timeline_item_id, alertIds=alert_ids, limit=limit, permissionType=permission_type, pageToken=page_token, prismaCloudFindingsOnly=findings_only, vulnerabilityInfoTypeId=vulnerability_info_type_id, vulnerabilityInfoType=vulnerability_info_type, ) response = client.get_asset_by_id(data) outputs = response.get("data", {}).get("asset", {}).get("relationships") return CommandResults( outputs_prefix="PrismaCloud.AssetRelationships", outputs_key_field="id", outputs=outputs, readable_output=tableToMarkdown( "Asset Relationships", outputs, headerTransform=pascalToSpace, sort_headers=False, ), raw_response=response, ) def get_asset_network_command(client: Client, args: Dict[str, Any]) -> CommandResults: """ Retrieve information about an asset network using the provided client. Args: - client (Client): An instance of the client used to make the API request. - args (Dict[str, Any]): A dictionary containing the 'asset-id' ID for retrieving the asset information. Returns: - CommandResults: An object containing the information about the asset network. """ asset_id = args.get("asset_id") finding_type = args.get("finding_type") risk_factors = argToList(args.get("risk_factors")) timeline_item_id = args.get("timeline_item_id") alert_ids = argToList(args.get("alert_ids")) limit = arg_to_number(args.get("limit")) or INT_DEFAULT_LIMIT permission_type = args.get("permission_type") page_token = args.get("page_token") findings_only = argToBoolean(args.get("prisma_cloud_findings_only", False)) vulnerability_info_type_id = args.get("vulnerability_info_type_id") vulnerability_info_type = args.get("vulnerability_info_type") data = assign_params( assetId=asset_id, type="network", findingType=finding_type, riskFactors=risk_factors, timelineItemId=timeline_item_id, alertIds=alert_ids, limit=limit, permissionType=permission_type, pageToken=page_token, prismaCloudFindingsOnly=findings_only, vulnerabilityInfoTypeId=vulnerability_info_type_id, vulnerabilityInfoType=vulnerability_info_type, ) response = client.get_asset_by_id(data) outputs = response.get("data", {}).get("asset", {}).get("network") return CommandResults( outputs_prefix="PrismaCloud.AssetNetwork", outputs_key_field="id", outputs=outputs, readable_output=tableToMarkdown( "Asset Network", outputs, headerTransform=pascalToSpace, sort_headers=False, ), raw_response=response, ) """ TEST MODULE """ def test_module(client: Client, params: Dict[str, Any]) -> str: if params.get("isFetch"): max_fetch = arg_to_number(params.get("max_fetch"), arg_name="Maximum number of incidents to fetch") if max_fetch and (max_fetch > MAX_INCIDENTS_TO_FETCH or max_fetch <= 0): return f"Maximum number of incidents to fetch must be between 1 and {MAX_INCIDENTS_TO_FETCH} ({max_fetch} provided)." filters = argToList(params.get("filters")) # check the filters format handle_filters(filters) # raises if invalid, otherwise we don't use the value # check the filters names filters_available_names = client.alert_filter_list_request().keys() for filter_ in filters: filter_name = filter_.split("=")[0] if filter_name not in filters_available_names: return ( f'Filter "{filter_name}" is not one of the available filters. ' f'The available filters names can be found by running "prisma-cloud-alert-filter-list" command.' ) look_back = arg_to_number(params.get("look_back"), arg_name="Time in minutes to look back when fetching incidents") if look_back and look_back < 0: return "Time in minutes to look back when fetching incidents must be a positive value, greater than or equal to zero." time_range = calculate_fetch_time_range( now=convert_date_to_unix("now"), first_fetch=params.get("first_fetch", FETCH_DEFAULT_TIME) ) alerts = client.alert_search_request( time_range=time_range, filters=filters, detailed="true", limit=max_fetch, sort_by=["alertTime:asc"] ).get("items", []) if not alerts: return ( "The connection succeeded, but no alerts were found for the provided filters and first fetch time. " "To pass the test, increase the first fetch time to a time when there were alerts at." ) # Authorization is done in client.generate_auth_token return "ok" """ MAIN FUNCTION """ def main() -> None: params: Dict[str, Any] = demisto.params() args: Dict[str, Any] = demisto.args() url = format_url(str(params.get("url"))) verify_certificate: bool = not params.get("insecure", False) proxy = params.get("proxy", False) username = params.get("credentials", {}).get("identifier") password = params.get("credentials", {}).get("password") mirror_direction = MIRROR_DIRECTION_MAPPING.get(params.get("mirror_direction", "None")) close_incident = argToBoolean(params.get("close_incident", False)) close_alert = argToBoolean(params.get("close_alert", False)) return_v1_output = params.get("output_old_format", False) command = demisto.command() demisto.debug(f"Command being called is {command}") is_test_module: bool = command == "test-module" try: client: Client = Client( url, verify_certificate, proxy, headers=HEADERS, username=username, password=password, mirror_direction=mirror_direction, close_incident=close_incident, close_alert=close_alert, is_test_module=is_test_module, ) commands_without_args = { "prisma-cloud-alert-filter-list": alert_filter_list_command, "prisma-cloud-trigger-scan": trigger_scan_command, } commands_with_args = { "prisma-cloud-alert-search": alert_search_command, "prisma-cloud-alert-get-details": alert_get_details_command, "prisma-cloud-alert-dismiss": alert_dismiss_command, "prisma-cloud-alert-reopen": alert_reopen_command, "prisma-cloud-remediation-command-list": remediation_command_list_command, "prisma-cloud-alert-remediate": alert_remediate_command, "prisma-cloud-config-search": config_search_command, "prisma-cloud-event-search": event_search_command, "prisma-cloud-network-search": network_search_command, "prisma-cloud-error-file-list": error_file_list_command, "prisma-cloud-resource-get": resource_get_command, "prisma-cloud-resource-list": resource_list_command, "prisma-cloud-user-roles-list": user_roles_list_command, "prisma-cloud-users-list": users_list_command, "prisma-cloud-account-list": account_list_command, "prisma-cloud-account-status-get": account_status_get_command, "prisma-cloud-account-owner-list": account_owner_list_command, "prisma-cloud-host-finding-list": host_finding_list_command, "prisma-cloud-permission-list": permission_list_command, "get-remote-data": get_remote_data_command, "update-remote-system": update_remote_system_command, "prisma-cloud-access-key-create": access_key_create_command, "prisma-cloud-access-keys-list": get_access_keys_command, "prisma-cloud-access-key-disable": access_key_disable_command, "prisma-cloud-access-key-enable": access_key_enable_command, "prisma-cloud-access-key-delete": access_key_delete_command, "prisma-cloud-asset-get": get_asset_command, "prisma-cloud-asset-generic-get": get_asset_generic_command, "prisma-cloud-asset-findings-get": get_asset_findings_command, "prisma-cloud-asset-alerts-get": get_asset_alerts_command, "prisma-cloud-asset-vulnerabilities-get": get_asset_vulnerabilities_command, "prisma-cloud-asset-relationships-get": get_asset_relationships_command, "prisma-cloud-asset-network-get": get_asset_network_command, } commands_v1 = { "redlock-search-alerts": alert_search_v1_command, "redlock-get-alert-details": alert_get_details_v1_command, "redlock-dismiss-alerts": alert_dismiss_v1_command, "redlock-reopen-alerts": alert_reopen_v1_command, "redlock-get-remediation-details": remediation_command_list_v1_command, "redlock-get-rql-response": rql_config_search_v1_command, "redlock-search-config": config_search_v1_command, "redlock-search-event": event_search_v1_command, "redlock-search-network": network_search_v1_command, "redlock-list-alert-filters": alert_filter_list_v1_command, } if command in commands_without_args: return_results(commands_without_args[command](client)) elif command in commands_with_args: return_results(commands_with_args[command](client, args)) elif command in commands_v1: return_results(commands_v1[command](client, args, return_v1_output)) elif command == "test-module": return_results(test_module(client, params)) elif command == "fetch-incidents": last_run = demisto.getLastRun() incidents, fetched_ids, last_run_time = fetch_incidents(client, last_run, params) demisto.incidents(incidents) demisto.setLastRun({"fetched_ids": fetched_ids, "time": last_run_time}) elif command == "get-modified-remote-data": return_results(get_modified_remote_data_command(client, args, params)) elif command == "prisma-cloud-code-issues-list": return_results(code_issues_list_command(client, args)) else: raise NotImplementedError(f"{command} command is not implemented.") except Exception as e: error_msg = str(e) if hasattr(e, "res"): error_msg += get_response_status_header(e.res) # type: ignore[attr-defined] if hasattr(e.res, "status_code") and e.res.status_code == 401: # type: ignore[attr-defined] error_msg = ( "Authentication failed. " "Check that the Server URL parameter is correct and validate your credentials.\n" + error_msg ) return_error(error_msg, error=e) """ ENTRY POINT """ if __name__ in ("__main__", "builtin", "builtins"): main()