Panorama
Manage Palo Alto Networks Firewall and Panorama. Use this pack to manage Prisma Access through Panorama. For more information, see the Panorama documentation.
Network Security · PAN-OS by Palo Alto Networks
Details
| ID | Panorama |
|---|---|
| Provider | Palo Alto Networks |
| Category | Network Security |
| From Version | 5.0.0 |
| Docker Image | demisto/pan-os-python:1.0.0.10133006 |
| Supported Modules | Agentix Cloud Runtime Security Cloud Posture Security XSIAM EDR Cortex Cloud |
README
This integration supports both Palo Alto Networks Panorama and Palo Alto Networks Firewall. You can create separate instances of each integration, and they are not necessarily related or dependent on one another.
This integration enables you to manage the Palo Alto Networks Firewall and Panorama. For more information see the PAN-OS documentation.
This integration was integrated and tested with versions 8.xx, 9.xx, 10.xx and 11.xx of Palo Alto Firewall and Palo Alto Panorama.
Use Cases
- Create custom security rules in Palo Alto Networks PAN-OS.
- Create and update address objects, address-groups, custom URL categories, and URL filtering objects.
- Use the URL Filtering category information from Palo Alto Networks to enrich URLs by checking the use_url_filtering parameter. A valid license for the Firewall is required.
- Get URL Filtering category information from Palo Alto. Request Change is a known Palo Alto limitation.
- Add URL filtering objects including overrides to Palo Alto Panorama and Firewall.
- Commit a configuration to Palo Alto Firewall and to Panorama, and push a configuration from Panorama to Pre-Defined Device-Groups of Firewalls.
-
Block IP addresses using registered IP tags from PAN-OS without committing the PAN-OS instance. First you have to create a registered IP tag, DAG, and security rule, and commit the instance. You can then register additional IP addresses to the tag without committing the instance.
-
Create a registered IP tag and add the necessary IP addresses by running the pan-os-register-ip-tag command.
-
Create a dynamic address group (DAG), by running the pan-os-create-address-group command. Specify values for the following arguments: type=”dynamic”, match={ tagname }.
-
Create a security rule using the DAG created in the previous step, by running the pan-os-create-rule command.
-
Commit the PAN-OS instance by running the PanoramaCommitConfiguration playbook.
-
You can now register IP addresses to, or unregister IP addresses from the IP tag by running the pan-os-register-ip-tag command, or pan-os-unregister-ip-tag command, respectively, without committing the PAN-OS instance.
-
- Create a predefined security profiles with the best practices by Palo Alto Networks.
- Get security profiles best practices as defined by Palo Alto Networks. For more information about Palo Alto Networks best practices, visit Palo Alto Networks best practices.
- Apply security profiles to specific rule.
- Set default categories to block in the URL filtering profile.
-
Enforce WildFire best practice.
-
Set file upload to the maximum size.
-
Set WildFire Update Schedule to download and install updates every minute.
-
All file types are forwarded.
-
Known Limitations
- Maximum commit queue length is 3. Running numerous Panorama commands simultaneously might cause errors.
- After running
panorama-create-commands and the object is not committed, thepanorama-editcommands orpanorama-getcommands might not run correctly. - URL Filtering
request changeof a URL is not available via the API. Instead, you need to use the https://urlfiltering.paloaltonetworks.com website. - If you do not specify a vsys (Firewall instances) or a device group (Panorama instances), you will only be able to execute the following commands.
- The target argument is supported only in operational type commands. Meaning, you cannot use it with commit, logs, or PCAP commands.
- Creating or updating the encryption master key of Palo Alto Networks Firewall or Panorama invalidates the current API key and requires obtaining a new one. All subsequent commands will raise an “Invalid Credential” error until a new API key is obtained and the integration instance is updated accordingly.
Fetch Incidents
The Panorama integration now supports fetch incidents.
The incidents are fetched according to a number of different optional log type queries. The log types are: Traffic, Threat, URL, Data, Correlation, System, Wildfire, Decryption.
Max incidents per fetch
- The max incidents per fetch parameter specifies the maximum number of incidents to fetch per Log Type Query.
- Important note: Cortex XSOAR standard setup is not designed to handle many hundreds of new incidents every minute. Therefore, it is strongly recommended to narrow your query by log type, severity, or other criteria to ensure that each fetch cycle retrieves no more than 200 incidents at a time.
Log Type
The queries that will be included during the fetch are decided according to the “Log Type” parameter (Multiple select dropdown).
- Selecting “All” will use all the log type queries in the fetch.
- To choose a specific set of queries, select their log types from the dropdown (make sure “All” option is unselected).
Log Type Query
- Each log type has its own query field in the instance configuration.
- Note that the default query values has some example text in it, make sure to enter a valid query.
- Note: In case of multiple devices, for the sake of speed it is recommended to narrow the query to a specific device.
For example: “and (device_name eq dummy_device)”.
Log Type Query Examples
| Log Type | Query Example |
|---|---|
| Traffic | (addr.src in {source}) and (addr.dst in {destination}) and (action eq {action}) |
| Threat | (severity geq high) |
| URL | ((action eq block-override) or (action eq block-url)) and (severity geq high) |
| Data | ((action eq alert) or (action eq wildfire-upload-success) or (action eq forward)) and (severity geq high) |
| Correlation | (hostid eq {host_id}) and (match_time in {last_x_time}) and (objectname eq {object_name}) and (severity geq ‘{severity}’) and (src in {source_address}) |
| System | (subtype eq {sub_type}) and (severity geq {severity}) |
| Wildfire Submission | ((action eq wildfire-upload-fail) or (action eq wildfire-upload-skip) or (action eq sinkhole)) |
| Decryption | (app eq {application}) and (policy_name geq {policy_name}) and ((src in {source}) or (dst in {destination})) |
Classifiers and Mappers
This integration supports a default Classifier (Panorama Classifier) and Mapper (Panorama Mapper) that handles incidents returned from the API.
Configure Panorama on Cortex XSOAR
- Navigate to Settings > Integrations > Instances.
- Search for Panorama.
- Click Add instance to create and configure a new integration instance.
| Parameter | Description | Required | |
|---|---|---|---|
| server | Server URL (e.g., https://192.168.0.1) | True | |
| port | Port (e.g 443) | False | |
| key | API Key | True | |
| device_group | Device group - Panorama instances only (write shared for Shared location) | False | |
| vsys | Vsys - Firewall instances only | False | |
| template | Template - Panorama instances only | False | ** |
| use_url_filtering | Use URL Filtering for auto enrichment | False | |
| additional_suspicious | URL Filtering Additional suspicious categories. CSV list of categories that will be considered suspicious. | False | |
| additional_malicious | URL Filtering Additional malicious categories. CSV list of categories that will be considered malicious. | False | |
| insecure | Trust any certificate (not secure) | False | |
| First fetch timestamp | First fetch time interval | False | |
| Max incidents per fetch | Max incidents per fetch for each selected Log Type Query | False | |
| Log Type | Log Types incidents to fetch | False | ** |
| Log type max number of pull attempts | The maximum number of attempts to try and pull results for each log type. Each attempt takes around 1 second. Increasing this value is useful in case there are many logs to pull from a given log type.Note: When increasing this number, in case fetching more than 4 logs types together, it is recommended to split different log types for different integration instance | False | |
| Traffic Log Type Query | Traffic Query for fetch incidents | False | |
| Threat Log Type Query | Threat Query for fetch incidents | False | |
| URL Log Type Query | URL Query for fetch incidents | False | |
| Data Log Type Query | Data Query for fetch incidents | False | |
| Correlation Log Type Query | Correlation Query for fetch incidents | False | |
| System Log Type Query | System Query for fetch incidents | False | |
| Wildfire Submission Log Type Query | Wildfire Submission Query for fetch incidents | False | |
| Decryption Log Type Query | Decryption Query for fetch incidents | False | |
| Incidents Fetch Interval | Time interval between incident fetches | False |
- Click Test to validate the URLs, token, and connection.
Debugging in Panorama
In order to ease the process of understanding what parameters are required to be used in the !pan-os command, it is highly recommended to use the debugging mode in Panorama to get the correct structure of a request.
Debugging Methods:
Several Examples of !pan-os for a configuration type commands:
1) Create a new address object named test123 for the test device-group.
Given the following debug-log from PAN-OS Web UI Debug after creating an address through the Panorama UI:
`
1.1.1.1`
The equivalent !pan-os command is:
`
!pan-os action=set xpath=/config/devices/entry[@name=’localhost.localdomain’]/device-group/entry[@name=’test’]/address/entry[@name=’test123’] type=config element=1.1.1.1
`
| Argument | Description |
|---|---|
| action | Create/add an object. In this case we want to create a new address object, so we will use set - the Panorama debug log shows us its a ‘set’ action. |
| xpath | /config/devices/entry[@name=’localhost.localdomain’]/device-group/entry[@name=’test’]/address/entry[@name=’test123’] - simply the location of the new object. |
| type | This is a configuration type command, therefore use config. |
| element | The object properties (similar to an API body request). |
2) Modify an existing address group object named test12345 under the test device group to use a different address object.
Given the following debug-log from PAN-OS Web UI Debug after editing an address group through the Panorama UI to use a different address object:
`
test123`
The equivalent !pan-os command is:
`
!pan-os action=edit xpath=/config/devices/entry[@name=’localhost.localdomain’]/device-group/entry[@name=’test’]/address-group/entry[@name=’test12345’] type=config element=test123
`
| Argument | Description |
|---|---|
| action | Edit an object, in this case we want to edit an entry in an existing address group object, so we will use edit - the panorama debug log shows us its an ‘edit’ action. |
| xpath | /config/devices/entry[@name=’localhost.localdomain’]/device-group/entry[@name=’test’]/address-group/entry[@name=’test12345’ - simply the location of the object. |
| type | This is a configuration type command, therefore use config. |
| element | The object properties (similar to an API body request). |
3) Get a specific security pre-rule called test1.
Using the API browser, we can easily find the xpath for the security pre-rule object, therefore the pan-os command will be:
`
!pan-os xpath=/config/devices/entry[@name=’localhost.localdomain’]/device-group/entry[@name=’test’]/pre-rulebase/security/rules/entry[@name=’test1’], action=get type=config
`
| Argument | Description |
|---|---|
| action | Get an object, in this case we want to get an object, so we will use ‘get’ as an action. |
| xpath | By using the API browser, we can find every object’s xpath easily. |
| type | This is a configuration type command, therefore use config. |
Several examples of !pan-os for an operational type command:
1) Show system information - Can be viewed by using the API browser to get the structure of the request.

The equivalent !pan-os command is:
`
!pan-os type=op cmd=
`
2) Show information about all the jobs - Can be viewed by using the API browser to get the structure of the request.

The equivalent !pan-os command is:
`
!pan-os type=op cmd=
`
Commands
You can execute these commands from the Cortex XSOAR CLI, as part of an automation, or in a playbook.
After you successfully execute a command, a DBot message appears in the War Room with the command details.
NOTE: The “create” commands function as UPSERT (UPDATE and INSERT), overriding existing data with new data if it already exists.
- Run any command supported in the Panorama API: pan-os
- Get pre-defined threats list from a Firewall or Panorama and stores as a JSON file in the context: panorama-get-predefined-threats-list
- Commit a configuration: panorama-commit
- Pushes rules from PAN-OS to the configured device group: panorama-push-to-device-group
- Returns a list of addresses: panorama-list-addresses
- Returns address details for the supplied address name: panorama-get-address
- Creates an address object: panorama-create-address
- Delete an address object: panorama-delete-address
- Returns a list of address groups: panorama-list-address-groups
- Get details for the specified address group: panorama-get-address-group
- Creates a static or dynamic address group: panorama-create-address-group
- Sets a vulnerability signature to block mode: panorama-block-vulnerability
- Deletes an address group: panorama-delete-address-group
- Edits a static or dynamic address group: panorama-edit-address-group
- Returns a list of addresses: panorama-list-services
- Returns service details for the supplied service name: panorama-get-service
- Creates a service: panorama-create-service
- Deletes a service: panorama-delete-service
- Returns a list of service groups: panorama-list-service-groups
- Returns details for the specified service group: panorama-get-service-group
- Creates a service group: panorama-create-service-group
- Deletes a service group: panorama-delete-service-group
- Edit a service group: panorama-edit-service-group
- Returns information for a custom URL category: panorama-get-custom-url-category
- Creates a custom URL category: panorama-create-custom-url-category
- Deletes a custom URL category: panorama-delete-custom-url-category
- Adds or removes sites to and from a custom URL category: panorama-edit-custom-url-category
- Gets a URL category from URL Filtering: panorama-get-url-category
- Gets a URL information: url
- Returns a URL category from URL Filtering in the cloud: panorama-get-url-category-from-cloud
- Returns a URL category from URL Filtering on the host: panorama-get-url-category-from-host
- Returns information for a URL filtering rule: panorama-get-url-filter
- Creates a URL filtering rule: panorama-create-url-filter
- Edit a URL filtering rule: panorama-edit-url-filter
- Deletes a URL filtering rule: panorama-delete-url-filter
- Returns a list of external dynamic lists: panorama-list-edls
- Returns information for an external dynamic list: panorama-get-edl
- Creates an external dynamic list: panorama-create-edl
- Modifies an element of an external dynamic list: panorama-edit-edl
- Deletes an external dynamic list: panorama-delete-edl
- Refreshes the specified external dynamic list: panorama-refresh-edl
- Creates a policy rule: panorama-create-rule
- Creates a custom block policy rule: panorama-custom-block-rule
- Changes the location of a policy rule: panorama-move-rule
- Edits a policy rule: panorama-edit-rule
- Deletes a policy rule: panorama-delete-rule
- Returns a list of applications: panorama-list-applications
- Returns commit status for a configuration: panorama-commit-status
- Returns the push status for a configuration: panorama-push-status
- Returns information for a Panorama PCAP file: panorama-get-pcap
- Returns a list of all PCAP files by PCAP type: panorama-list-pcaps
- Registers IP addresses to a tag: panorama-register-ip-tag
- Unregisters IP addresses from a tag: panorama-unregister-ip-tag
- Registers Users to a tag: panorama-register-user-tag
- Unregisters Users from a tag: panorama-unregister-user-tag
- Deprecated. Queries traffic logs: panorama-query-traffic-logs
- Deprecated. Checks the query status of traffic logs: panorama-check-traffic-logs-status
- Deprecated. Retrieves traffic log query data by job id: panorama-get-traffic-logs
- Returns a list of predefined Security Rules: panorama-list-rules
- Query logs in Panorama: panorama-query-logs
- Checks the status of a logs query: panorama-check-logs-status
- Retrieves the data of a logs query: panorama-get-logs
- Checks whether a session matches the specified security policy: panorama-security-policy-match
- Lists the static routes of a virtual router: panorama-list-static-routes
- Returns the specified static route of a virtual router: panorama-get-static-route
- Adds a static route: panorama-add-static-route
- Deletes a static route: panorama-delete-static-route
- Show firewall device software version: panorama-show-device-version
- Downloads the latest content update: panorama-download-latest-content-update
- Checks the download status of a content update: panorama-content-update-download-status
- Installs the latest content update: panorama-install-latest-content-update
- Gets the installation status of the content update: panorama-content-update-install-status
- Checks the PAN-OS software version from the repository: panorama-check-latest-panos-software
- Downloads the target PAN-OS software version to install on the target device: panorama-download-panos-version
- Gets the download status of the target PAN-OS software: panorama-download-panos-status
- Installs the target PAN-OS version on the specified target device: panorama-install-panos-version
- Gets the installation status of the PAN-OS software: panorama-install-panos-status
- Reboots the Firewall device: panorama-device-reboot
- Gets location information for an IP address: panorama-show-location-ip
- Gets information about available PAN-OS licenses and their statuses: panorama-get-licenses
- Gets information for the specified security profile: panorama-get-security-profiles
- Apply a security profile to specific rules or rules with a specific tag: panorama-apply-security-profile
- Removes a security profile to specific rules or rules with a specific tag
- Get SSL decryption rules: panorama-get-ssl-decryption-rules
- Retrieves the Wildfire configuration: panorama-get-wildfire-configuration
- Set default categories to block in the URL filtering profile: panorama-url-filtering-block-default-categories
- Get anti-spyware best practices: panorama-get-anti-spyware-best-practice
- Get file-blocking best practices: panorama-get-file-blocking-best-practice
- Get anti-virus best practices: panorama-get-antivirus-best-practice
- Get vulnerability-protection best practices: panorama-get-vulnerability-protection-best-practice
- View WildFire best practices: panorama-get-wildfire-best-practice
- View URL Filtering best practices: panorama-get-url-filtering-best-practice
- Enforces wildfire best practices to upload files to the maximum size, forwards all file types, and updates the schedule: panorama-enforce-wildfire-best-practice
- Creates an antivirus best practice profile: panorama-create-antivirus-best-practice-profile
- Creates an Anti-Spyware best practice profile: panorama-create-anti-spyware-best-practice-profile
- Creates a vulnerability protection best practice profile: panorama-create-vulnerability-best-practice-profile
- Creates a URL filtering best practice profile: panorama-create-url-filtering-best-practice-profile
- Creates a file blocking best practice profile: panorama-create-file-blocking-best-practice-profile
- Creates a WildFire analysis best practice profile: panorama-create-wildfire-best-practice-profile
- Shows the user ID interface configuration.
- Shows the zones configuration.
- Retrieves list of user-ID agents configured in the system.
- Gets global counter information from all the PAN-OS firewalls in the topology.
- Retrieves all BGP peer information from the PAN-OS firewalls in the topology.
- Check the devices for software that is available to be installed.
- Get the HA state and associated details from the given device and any other details.
- Get all the jobs from the devices in the environment, or a single job when ID is specified.
- Download The provided software version onto the device.
- Download the running configuration
- Download the merged configuration
- Create Nat-rule
- Create PBF-rule
pan-os
Run any command supported in the API.
Base Command
pan-os
Input
| Argument Name | Description | Required |
|---|---|---|
| action | Action to be taken, such as show, get, set, edit, delete, rename, clone, move, override, multi-move, multi-clone, or complete. Documentation - https://docs.paloaltonetworks.com/pan-os/9-1/pan-os-panorama-api/pan-os-xml-api-request-types/configuration-api | Optional |
| category | Category parameter. For example, when exporting a configuration file, use “category=configuration”. | Optional |
| cmd | Specifies the XML structure that defines the command. Used for operation commands (op type command). Can be retrieved from the PAN-OS web UI debugger or enabling debugging via the CLI using debug cli on. |
Optional |
| command | Run a command. For example, command =<show><arp><entry name=’all’/></arp></show> | Optional |
| dst | Specifies a destination. | Optional |
| element | Used to define a new value for an object. Should be an XML object, for example, test. | Optional |
| to | End time (used only when cloning an object). | Optional |
| from | Start time (used only when cloning an object). | Optional |
| key | Sets a key value. | Optional |
| log-type | Retrieves log types. For example, log-type=threat for threat logs. | Optional |
| where | Specifies the type of a move operation (for example, where=after, where=before, where=top, where=bottom). | Optional |
| period | Time period. For example, period=last-24-hrs | Optional |
| xpath | xpath location. xpath defines the location of the object. For example, xpath=/config/predefined/application/entry[@name=’hotmail’]. Documentation - https://docs.paloaltonetworks.com/pan-os/9-1/pan-os-panorama-api/about-the-pan-os-xml-api/structure-of-a-pan-os-xml-api-request/xml-and-xpath. | Optional |
| pcap-id | PCAP ID included in the threat log. | Optional |
| serialno | Specifies the device serial number. | Optional |
| reporttype | Chooses the report type, such as dynamic, predefined or custom. | Optional |
| reportname | Report name. | Optional |
| type | Request type (e.g. export, import, log, config). Possible values are: keygen, config, commit, op, report, log, import, export, user-id, version. default is config. | Optional |
| search-time | The time that the PCAP was received on the firewall. Used for threat PCAPs. | Optional |
| target | Serial number of the firewall on which to run the command. Use only for a Panorama instance. | Optional |
| job-id | Job ID. | Optional |
| query | Query string. | Optional |
| vsys | The name of the virtual system to be configured. If no vsys is mentioned, this command will not use the vsys parameter. | Optional |
| newname | The object’s new name, used when action=rename. If no value is provided, the name defaults to ‘newname’. | Optional |
Context Output
There is no context output for this command.
Command Example
!pan-os xpath=“/config/devices/entry[@name=‘localhost.localdomain’]/template/entry[@name=‘test’]/config/devices/entry[@name=‘localhost.localdomain’]/network/profiles/zone-protection-profile/entry[@name=‘test’]/scan-white-list/entry[@name=‘test’]/ipv4" type=config action=edit element=“<ipv4>1.1.1.1</ipv4>”
Human Readable Output
Command was executed successfully.
pan-os-get-predefined-threats-list
Gets the pre-defined threats list from a Firewall or Panorama and stores as a JSON file in the context.
Base Command
pan-os-get-predefined-threats-list
Input
| Argument Name | Description | Required |
|---|---|---|
| target | The firewall managed by Panorama from which to retrieve the predefined threats. | Optional |
Context Output
| Path | Type | Description |
|---|---|---|
| File.Size | number | File size. |
| File.Name | string | File name. |
| File.Type | string | File type. |
| File.Info | string | File info. |
| File.Extension | string | File extension. |
| File.EntryID | string | File entryID. |
| File.MD5 | string | MD5 hash of the file. |
| File.SHA1 | string | SHA1 hash of the file. |
| File.SHA256 | string | SHA256 hash of the file. |
| File.SHA512 | string | SHA512 hash of the file. |
| File.SSDeep | string | SSDeep hash of the file. |
Command Example
### pan-os-commit
***
Commits a configuration to the Palo Alto firewall or Panorama, validates if a commit was successful if using polling="true", otherwise does not validate if the commit was successful. Committing to Panorama does not push the configuration to the firewalls. To push the configuration, run the panorama-push-to-device-group command.
#### Base Command
`pan-os-commit`
#### Input
| **Argument Name** | **Description** | **Required** |
| --- | --- | --- |
| device-group | Panorama only. Limits the commit scope to the specified device group(s), so only pending changes for those device groups are committed. If omitted, all pending changes are committed. | Optional |
| template | Panorama only. Limits the commit scope to the specified template(s), so only pending changes for those templates are committed. If omitted, all pending changes are committed. | Optional |
| description | The commit description. | Optional |
| admin_name | The administrator name. To commit admin-level changes on a firewall, include the administrator name in the request. | Optional |
| force_commit | Forces a commit. Possible values are: true, false. | Optional |
| exclude_device_network_configuration | Performs a partial commit while excluding device and network configuration. Possible values are: true, false. | Optional |
| exclude_shared_objects | Performs a partial commit while excluding shared objects. Possible values are: true, false. | Optional |
| polling | Whether to use polling. Possible values are: true, false. Default is false. | Optional |
| commit_job_id | commit job ID to use in polling commands. (automatically filled by polling). | Optional |
| timeout | The timeout (in seconds) when polling. Default is 120. | Optional |
| interval_in_seconds | The interval (in seconds) when polling. Default is 10. | Optional |
| hide_polling_output | whether to hide the polling result (automatically filled by polling). | Optional |
#### Context Output
| **Path** | **Type** | **Description** |
| --- | --- | --- |
| Panorama.Commit.JobID | Number | The job ID to commit. |
| Panorama.Commit.Status | String | The commit status. |
| Panorama.Commit.Description | String | The commit description from the the command input. |
| Panorama.Commit.Scope | String | Whether the commit is partial. |
| Panorama.Commit.Details | String | The summary of the targeted device group and templates. |
#### Command example with polling
```!pan-os-commit description=test polling=true interval_in_seconds=5 timeout=60```
#### Human Readable Output
>Waiting for commit "test" with job ID 12345 to finish...
>
>### Commit Status
>
>|JobID|Status| Description
>|---|---|---|
>| 12345 | Success | test
#### Context Example
```json
{
"Panorama": {
"Commit": {
"JobID": "12345",
"Status": "Success",
"Description": "test",
"Scope": "Full",
"Details": "Full commit"
}
}
}
Command example without polling
!pan-os-commit description=test
Human Readable Output
Commit Status
JobID Status Description 12345 Pending test
Context Example
{
"Panorama": {
"Commit": {
"JobID": "12345",
"Status": "Pending",
"Description": "test",
"Scope": "Full",
"Details": "Full commit"
}
}
}
pan-os-push-to-device-group
Pushes rules from PAN-OS to the configured device group. In order to push the configuration to Prisma Access managed tenants (single or multi tenancy), use the device group argument with the device group which is associated with the tenant ID. Validates if a push has been successful if polling=”true”.
Base Command
pan-os-push-to-device-group
Input
| Argument Name | Description | Required |
|---|---|---|
| device-group | The device group to which to push (Panorama instances). | Optional |
| validate-only | Pre policy validation. Possible values are: true, false. Default is false. | Optional |
| include-template | Whether to include template changes. Possible values are: true, false. Default is true. | Optional |
| description | The push description. | Optional |
| serial_number | The serial number for a virtual system commit. If provided, the commit will be a virtual system commit. | Optional |
| polling | Whether to use polling. Possible values are: true, false. Default is false. | Optional |
| timeout | The timeout (in seconds) when polling. Default is 120. | Optional |
| interval_in_seconds | The interval (in seconds) when polling. Default is 10. | Optional |
Context Output
| Path | Type | Description |
|---|---|---|
| Panorama.Push.DeviceGroup | String | The device group in which the policies were pushed. |
| Panorama.Push.JobID | Number | The job ID of the policies that were pushed. |
| Panorama.Push.Status | String | The push status. |
| Panorama.Push.Warnings | String | The push warnings. |
| Panorama.Push.Errors | String | The push errors. |
| Panorama.Push.Details | String | The job ID details. |
Command example with polling=true
!pan-os-push-to-device-group description=test polling=true interval_in_seconds=5 timeout=60
Context Example
{
"Panorama": {
"Push": {
"Details": [
"commit succeeded with warnings",
"commit succeeded with warnings"
],
"Errors": ,
"JobID": "31377",
"Status": "Completed",
"Warnings": [
"Interface loopback.645 has no zone configuration.",
"External Dynamic List test_pb_domain_edl_DONT_DEL is configured with no certificate profile. Please select a certificate profile for performing server certificate validation.",
"External Dynamic List Cortex XSOAR Remediation - IP EDL-ip-edl-object is configured with no certificate profile. Please select a certificate profile for performing server certificate validation.",
"External Dynamic List Cortex XSOAR Remediation - URL EDL-url-edl-object is configured with no certificate profile. Please select a certificate profile for performing server certificate validation.",
"External Dynamic List Cortex XSOAR Remediation - URL EDL tamarcat3-url-edl-object is configured with no certificate profile. Please select a certificate profile for performing server certificate validation.",
"External Dynamic List Cortex XSOAR Remediation - IP EDL tamarcat3-ip-edl-object is configured with no certificate profile. Please select a certificate profile for performing server certificate validation.",
"External Dynamic List minemeld is configured with no certificate profile. Please select a certificate profile for performing server certificate validation.",
"External Dynamic List edl-webinar-malicious-urls-OLD is configured with no certificate profile. Please select a certificate profile for performing server certificate validation.",
"External Dynamic List edl-webinar-malicious-ips is configured with no certificate profile. Please select a certificate profile for performing server certificate validation.",
"External Dynamic List edl-webinar-malicious-domains is configured with no certificate profile. Please select a certificate profile for performing server certificate validation.",
"Warning: No valid Antivirus content package exists",
"(Module: device)"
]
}
}
}
Human Readable Output
Waiting for Job-ID 31374 to finish push changes to device-group Lab-Devices..
Push to Device Group status
JobID Status Details Errors Warnings 31377 Completed commit succeeded with warnings,
commit succeeded with warningsInterface loopback.645 has no zone configuration.,
External Dynamic List test_pb_domain_edl_DONT_DEL is configured with no certificate profile. Please select a certificate profile for performing server certificate validation.,
External Dynamic List Cortex XSOAR Remediation - IP EDL-ip-edl-object is configured with no certificate profile. Please select a certificate profile for performing server certificate validation.,
External Dynamic List Cortex XSOAR Remediation - URL EDL-url-edl-object is configured with no certificate profile. Please select a certificate profile for performing server certificate validation.,
External Dynamic List Cortex XSOAR Remediation - URL EDL tamarcat3-url-edl-object is configured with no certificate profile. Please select a certificate profile for performing server certificate validation.,
External Dynamic List Cortex XSOAR Remediation - IP EDL tamarcat3-ip-edl-object is configured with no certificate profile. Please select a certificate profile for performing server certificate validation.,
External Dynamic List minemeld is configured with no certificate profile. Please select a certificate profile for performing server certificate validation.,
External Dynamic List edl-webinar-malicious-urls-OLD is configured with no certificate profile. Please select a certificate profile for performing server certificate validation.,
External Dynamic List edl-webinar-malicious-ips is configured with no certificate profile. Please select a certificate profile for performing server certificate validation.,
External Dynamic List edl-webinar-malicious-domains is configured with no certificate profile. Please select a certificate profile for performing server certificate validation.,
Warning: No valid Antivirus content package exists,
(Module: device)
Command example with polling=false
!pan-os-push-to-device-group description=test polling=false
Human Readable Output
Push to Device Group status
JobID Status Description 113198 Pending test
Context Example
{
"Panorama": {
"Push": {
"JobID": "113198",
"Status": "Pending",
"Description": "test",
"DeviceGroup": "device group name"
}
}
}
pan-os-list-addresses
Returns a list of addresses.
Base Command
pan-os-list-addresses
Input
| Argument Name | Description | Required |
|---|---|---|
| device-group | The device group for which to return addresses (Panorama instances). | Optional |
| tag | Tag for which to filter the list of addresses. | Optional |
Context Output
| Path | Type | Description |
|---|---|---|
| Panorama.Addresses.Name | string | Address name. |
| Panorama.Addresses.Description | string | Address description. |
| Panorama.Addresses.FQDN | string | Address FQDN. |
| Panorama.Addresses.IP_Netmask | string | Address IP Netmask. |
| Panorama.Addresses.IP_Range | string | Address IP range. |
| Panorama.Addresses.DeviceGroup | String | Address device group. |
| Panorama.Addresses.Tags | String | Address tags. |
Command Example
#### Context Example
```json
{
"Panorama": {
"Addresses": [
{
"IP_Netmask": "10.10.10.1/24",
"Name": "Demisto address"
},
{
"Description": "a",
"IP_Netmask": "1.1.1.1",
"Name": "test1"
}
]
}
}
Human Readable Output
Addresses
Name IP_Netmask IP_Range FQDN Demisto address 10.10.10.1/24 test1 1.1.1.1
pan-os-get-address
Returns address details for the supplied address name.
Base Command
pan-os-get-address
Input
| Argument Name | Description | Required |
|---|---|---|
| name | Address name. | Required |
| device-group | The device group for which to return addresses (Panorama instances). | Optional |
Context Output
| Path | Type | Description |
|---|---|---|
| Panorama.Addresses.Name | string | Address name. |
| Panorama.Addresses.Description | string | Address description. |
| Panorama.Addresses.FQDN | string | Address FQDN. |
| Panorama.Addresses.IP_Netmask | string | Address IP Netmask. |
| Panorama.Addresses.IP_Range | string | Address IP range. |
| Panorama.Addresses.DeviceGroup | String | Device group for the address (Panorama instances). |
| Panorama.Addresses.Tags | String | Address tags. |
Command Example
!pan-os-get-address name="Demisto address"
Context Example
{
"Panorama": {
"Addresses": {
"IP_Netmask": "10.10.10.1/24",
"Name": "Demisto address"
}
}
}
Human Readable Output
Address
Name IP_Netmask Demisto address 10.10.10.1/24
pan-os-create-address
Creates an address object.
Base Command
pan-os-create-address
Input
| Argument Name | Description | Required |
|---|---|---|
| name | New address name. | Required |
| description | New address description. | Optional |
| fqdn | FQDN of the new address. | Optional |
| ip_netmask | IP Netmask of the new address. For example, 10.10.10.10/24 | Optional |
| ip_range | IP range of the new address IP. For example, 10.10.10.0-10.10.10.255 | Optional |
| ip_wildcard | The IP wildcard of the new address. For example, 10.20.1.0/0.0.248.255 | Optional |
| device-group | The device group for which to return addresses (Panorama instances). | Optional |
| tag | The tag for the new address. | Optional |
| create_tag | Whether to create the tag if it does not exist. | Optional |
Context Output
| Path | Type | Description |
|---|---|---|
| Panorama.Addresses.Name | string | Address name. |
| Panorama.Addresses.Description | string | Address description. |
| Panorama.Addresses.FQDN | string | Address FQDN. |
| Panorama.Addresses.IP_Netmask | string | Address IP Netmask. |
| Panorama.Addresses.IP_Range | string | Address IP range. |
| Panorama.Addresses.DeviceGroup | String | Device group for the address (Panorama instances). |
| Panorama.Addresses.Tags | String | Address tags. |
Command Example
!pan-os-create-address name="address_test_pb" description="just a desc" ip_range="10.10.10.9-10.10.10.10"
Context Example
{
"Panorama": {
"Addresses": {
"Description": "just a desc",
"IP_Range": "10.10.10.9-10.10.10.10",
"Name": "address_test_pb"
}
}
}
Human Readable Output
Address was created successfully.
pan-os-delete-address
Delete an address object
Base Command
pan-os-delete-address
Input
| Argument Name | Description | Required |
|---|---|---|
| name | Name of the address to delete. | Required |
| device-group | The device group for which to return addresses (Panorama instances). | Optional |
Context Output
| Path | Type | Description |
|---|---|---|
| Panorama.Addresses.Name | string | Address name that was deleted. |
| Panorama.Addresses.DeviceGroup | String | Device group for the address (Panorama instances). |
Command Example
!pan-os-delete-address name="address_test_pb"
Context Example
{
"Panorama": {
"Addresses": {
"Name": "address_test_pb"
}
}
}
Human Readable Output
Address was deleted successfully.
pan-os-list-address-groups
Returns a list of address groups.
Base Command
pan-os-list-address-groups
Input
| Argument Name | Description | Required |
|---|---|---|
| device-group | The device group for which to return addresses (Panorama instances). | Optional |
| tag | Tag for which to filter the Address groups. | Optional |
Context Output
| Path | Type | Description |
|---|---|---|
| Panorama.AddressGroups.Name | string | Address group name. |
| Panorama.AddressGroups.Type | string | Address group type. |
| Panorama.AddressGroups.Match | string | Dynamic Address group match. |
| Panorama.AddressGroups.Description | string | Address group description. |
| Panorama.AddressGroups.Addresses | String | Static Address group addresses. |
| Panorama.AddressGroups.DeviceGroup | String | Device group for the address group (Panorama instances). |
| Panorama.AddressGroups.Tags | String | Address group tags. |
Command Example
#### Context Example
```json
{
"Panorama": {
"AddressGroups": [
{
"Match": "2.2.2.2",
"Name": "a_g_1",
"Type": "dynamic"
},
{
"Addresses": [
"Demisto address",
"test3",
"test_demo3"
],
"Name": "Demisto group",
"Type": "static"
},
{
"Description": "jajja",
"Match": "4.4.4.4",
"Name": "dynamic2",
"Type": "dynamic"
},
{
"Addresses": [
"test4",
"test2"
],
"Name": "static2",
"Type": "static"
}
]
}
}
Human Readable Output
Address groups
Name Type Addresses Match Description Tags a_g_1 dynamic 2.2.2.2 Demisto group static Demisto address,
test3,
test_demo3dynamic2 dynamic 4.4.4.4 jajja static2 static test4,
test2
pan-os-get-address-group
Get details for the specified address group
Base Command
pan-os-get-address-group
Input
| Argument Name | Description | Required |
|---|---|---|
| name | Address group name. | Required |
| device-group | The device group for which to return addresses (Panorama instances). | Optional |
Context Output
| Path | Type | Description |
|---|---|---|
| Panorama.AddressGroups.Name | string | Address group name. |
| Panorama.AddressGroups.Type | string | Address group type. |
| Panorama.AddressGroups.Match | string | Dynamic Address group match. |
| Panorama.AddressGroups.Description | string | Address group description. |
| Panorama.AddressGroups.Addresses | string | Static Address group addresses. |
| Panorama.AddressGroups.DeviceGroup | String | Device group for the address group (Panorama instances). |
| Panorama.AddressGroups.Tags | String | Address group tags. |
Command Example
!pan-os-get-address-group name=suspicious_address_group
Human Readable Output
Address groups
Name Type Addresses Match Description suspicious_address_group dynamic 1.1.1.1 this ip is very bad
pan-os-create-address-group
Creates a static or dynamic address group.
Base Command
pan-os-create-address-group
Input
| Argument Name | Description | Required |
|---|---|---|
| name | Address group name. | Required |
| type | Address group type. | Required |
| match | Dynamic Address group match. e.g: “1.1.1.1 or 2.2.2.2” | Optional |
| addresses | Static address group list of addresses. | Optional |
| description | Address group description. | Optional |
| device-group | The device group for which to return addresses (Panorama instances). | Optional |
| tags | The tags for the Address group. | Optional |
Context Output
| Path | Type | Description |
|---|---|---|
| Panorama.AddressGroups.Name | string | Address group name. |
| Panorama.AddressGroups.Type | string | Address group type. |
| Panorama.AddressGroups.Match | string | Dynamic Address group match. |
| Panorama.AddressGroups.Addresses | string | Static Address group list of addresses. |
| Panorama.AddressGroups.Description | string | Address group description. |
| Panorama.AddressGroups.DeviceGroup | String | Device group for the address group (Panorama instances). |
| Panorama.AddressGroups.Tags | String | Address group tags. |
Command Example
!pan-os-create-address-group name=suspicious_address_group type=dynamic match=1.1.1.1 description="this ip is very bad"
Context Example
{
"Panorama": {
"AddressGroups": {
"Description": "this ip is very bad",
"Match": "1.1.1.1",
"Name": "suspicious_address_group",
"Type": "dynamic"
}
}
}
Human Readable Output
Address group was created successfully.
pan-os-block-vulnerability
Sets a vulnerability signature to block mode.
Base Command
pan-os-block-vulnerability
Input
| Argument Name | Description | Required |
|---|---|---|
| drop_mode | Type of session rejection. Possible values are: “drop”, “alert”, “block-ip”, “reset-both”, “reset-client”, and “reset-server”.’ Default is “drop”. | Optional |
| vulnerability_profile | Name of vulnerability profile. | Required |
| threat_id | Numerical threat ID. | Required |
Context Output
| Path | Type | Description |
|---|---|---|
| Panorama.Vulnerability.ID | string | ID of vulnerability that has been blocked/overridden. |
| Panorama.Vulnerability.NewAction | string | New action for the vulnerability. |
Command Example
!pan-os-block-vulnerability threat_id=18250 vulnerability_profile=name
Human Readable Output
Threat with ID 18250 overridden.
pan-os-delete-address-group
Deletes an address group.
Base Command
pan-os-delete-address-group
Input
| Argument Name | Description | Required |
|---|---|---|
| name | Name of address group to delete. | Required |
| device-group | The device group for which to return addresses (Panorama instances). | Optional |
Context Output
| Path | Type | Description |
|---|---|---|
| Panorama.AddressGroups.Name | string | Name of address group that was deleted. |
| Panorama.AddressGroups.DeviceGroup | String | Device group for the address group (Panorama instances). |
Command Example
!pan-os-delete-address-group name="dynamic_address_group_test_pb3"
Human Readable Output
Address group was deleted successfully
pan-os-edit-address-group
Edits a static or dynamic address group.
Base Command
pan-os-edit-address-group
Input
| Argument Name | Description | Required |
|---|---|---|
| name | Name of the address group to edit. | Required |
| type | Address group type. | Required |
| match | Address group new match. For example, ‘1.1.1.1 and 2.2.2.2’. | Optional |
| element_to_add | Element to add to the list of the static address group. Only existing Address objects can be added. | Optional |
| element_to_remove | Element to remove from the list of the static address group. Only existing Address objects can be removed. | Optional |
| description | Address group new description. | Optional |
| tags | The tag of the Address group to edit. | Optional |
| device-group | The device group in which the address group belongs to. | Optional |
Context Output
| Path | Type | Description |
|---|---|---|
| Panorama.AddressGroups.Name | string | Address group name. |
| Panorama.AddressGroups.Type | string | Address group type. |
| Panorama.AddressGroups.Filter | string | Dynamic Address group match. |
| Panorama.AddressGroups.Description | string | Address group description. |
| Panorama.AddressGroups.Addresses | string | Static Address group addresses. |
| Panorama.AddressGroups.DeviceGroup | String | Device group for the address group (Panorama instances). |
| Panorama.AddressGroups.Tags | String | Address group tags. |
pan-os-list-services
Returns a list of addresses.
Base Command
pan-os-list-services
Input
| Argument Name | Description | Required |
|---|---|---|
| device-group | The device group for which to return addresses (Panorama instances). | Optional |
| tag | Tag for which to filter the Services. | Optional |
Context Output
| Path | Type | Description |
|---|---|---|
| Panorama.Services.Name | string | Service name. |
| Panorama.Services.Protocol | string | Service protocol. |
| Panorama.Services.Description | string | Service description. |
| Panorama.Services.DestinationPort | string | Service destination port. |
| Panorama.Services.SourcePort | string | Service source port. |
| Panorama.Services.DeviceGroup | string | Device group in which the service was configured (Panorama instances). |
| Panorama.Services.Tags | String | Service tags. |
Command Example
#### Context Example
```json
{
"Panorama": {
"Services": [
{
"Description": "rgfg",
"DestinationPort": "55",
"Name": "demisto_service1",
"Protocol": "tcp",
"SourcePort": "567-569"
},
{
"Description": "mojo",
"DestinationPort": "55",
"Name": "demi_service_test_pb",
"Protocol": "sctp",
"SourcePort": "60"
},
]
}
}
Human Readable Output
Services
Name Protocol SourcePort DestinationPort Description demisto_service1 tcp 567-569 55 rgfg demi_service_test_pb sctp 60 55 mojo
pan-os-get-service
Returns service details for the supplied service name.
Base Command
pan-os-get-service
Input
| Argument Name | Description | Required |
|---|---|---|
| name | Service name. | Required |
| device-group | The device group for which to return addresses (Panorama instances). | Optional |
Context Output
| Path | Type | Description |
|---|---|---|
| Panorama.Services.Name | string | Service name. |
| Panorama.Services.Protocol | string | Service protocol. |
| Panorama.Services.Description | string | Service description. |
| Panorama.Services.DestinationPort | string | Service destination port. |
| Panorama.Services.SourcePort | string | Service source port. |
| Panorama.Services.DeviceGroup | string | Device group for the service (Panorama instances). |
| Panorama.Service.Tags | String | Service tags. |
Command Example
!pan-os-get-service name=demisto_service1
Human Readable Output
Address
Name Protocol SourcePort DestinationPort Description demisto_service1 tcp 567-569 55 rgfg
pan-os-create-service
Creates a service.
Base Command
pan-os-create-service
Input
| Argument Name | Description | Required |
|---|---|---|
| name | The name for the new service. | Required |
| protocol | The protocol for the new service. Possible values are: tcp, udp, sctp. | Required |
| destination_port | The destination port for the new service. | Required |
| source_port | The source port for the new service. | Optional |
| description | The description for the new service. | Optional |
| device-group | The device group for which to return addresses (Panorama instances). | Optional |
| tags | The tags for the new service. | Optional |
Context Output
| Path | Type | Description |
|---|---|---|
| Panorama.Services.Name | string | The service name. |
| Panorama.Services.Protocol | string | The service protocol. |
| Panorama.Services.Description | string | The service description. |
| Panorama.Services.DestinationPort | string | The service destination port. |
| Panorama.Services.SourcePort | string | The service source port. |
| Panorama.Services.DeviceGroup | string | The device group for the service (Panorama instances). |
| Panorama.Services.Tags | String | The service tags. |
Command Example
!pan-os-create-service name=guy_ser3 protocol=udp destination_port=36 description=bfds
Context Example
{
"Panorama": {
"Services": {
"Description": "bfds",
"DestinationPort": "36",
"Name": "guy_ser3",
"Protocol": "udp"
}
}
}
Human Readable Output
Service was created successfully.
pan-os-delete-service
Deletes a service.
Base Command
pan-os-delete-service
Input
| Argument Name | Description | Required |
|---|---|---|
| name | Name of the service to delete. | Required |
| device-group | The device group for which to return addresses (Panorama instances). | Optional |
Context Output
| Path | Type | Description |
|---|---|---|
| Panorama.Services.Name | string | Name of the deleted service. |
| Panorama.Services.DeviceGroup | string | Device group for the service (Panorama instances). |
Command Example
!pan-os-delete-service name=guy_ser3
Context Example
{
"Panorama": {
"Services": {
"Name": "guy_ser3"
}
}
}
Human Readable Output
Service was deleted successfully.
pan-os-list-service-groups
Returns a list of service groups.
Base Command
pan-os-list-service-groups
Input
| Argument Name | Description | Required |
|---|---|---|
| device-group | The device group for which to return addresses (Panorama instances). | Optional |
| tag | Tags for which to filter the Service groups. | Optional |
Context Output
| Path | Type | Description |
|---|---|---|
| Panorama.ServiceGroups.Name | string | Service group name. |
| Panorama.ServiceGroups.Services | string | Service group related services. |
| Panorama.ServiceGroups.DeviceGroup | string | Device group for the service group (Panorama instances). |
| Panorama.ServiceGroups.Tags | String | Service group tags. |
Command Example
#### Context Example
```json
{
"Panorama": {
"ServiceGroups": [
{
"Name": "demisto_default_service_groups",
"Services": [
"service-http",
"service-https"
]
},
{
"Name": "demisto_test_pb_service_group",
"Services": "serice_tcp_test_pb"
}
]
}
}
Human Readable Output
Service groups
Name Services demisto_default_service_groups service-http,
service-httpsdemisto_test_pb_service_group service_tcp_test_pb
pan-os-get-service-group
Returns details for the specified service group.
Base Command
pan-os-get-service-group
Input
| Argument Name | Description | Required |
|---|---|---|
| name | Service group name. | Required |
| device-group | The device group for which to return addresses (Panorama instances). | Optional |
Context Output
| Path | Type | Description |
|---|---|---|
| Panorama.ServiceGroups.Name | string | Service group name. |
| Panorama.ServiceGroups.Services | string | Service group related services. |
| Panorama.ServiceGroups.DeviceGroup | string | Device group for the service group (Panorama instances). |
| Panorama.ServiceGroups.Tags | String | Service group tags. |
Command Example
!pan-os-get-service-group name=ser_group6
Context Example
{
"Panorama": {
"ServiceGroups": {
"Name": "ser_group6",
"Services": [
"serice_tcp_test_pb",
"demi_service_test_pb"
]
}
}
}
Human Readable Output
Service group
Name Services ser_group6 serice_tcp_test_pb,
demi_service_test_pb
pan-os-create-service-group
Creates a service group.
Base Command
pan-os-create-service-group
Input
| Argument Name | Description | Required |
|---|---|---|
| name | Service group name. | Required |
| services | Service group related services. | Required |
| device-group | The device group for which to return addresses (Panorama instances). | Optional |
| tags | Tags for which to filter Service groups. | Optional |
Context Output
| Path | Type | Description |
|---|---|---|
| Panorama.ServiceGroups.Name | string | Service group name. |
| Panorama.ServiceGroups.Services | string | Service group related services. |
| Panorama.ServiceGroups.DeviceGroup | string | Device group for the service group (Panorama instances). |
| Panorama.ServiceGroups.Tags | String | Service group tags. |
Command Example
!pan-os-create-service-group name=lalush_sg4 services=`["demisto_service1","demi_service_test_pb"]
pan-os-delete-service-group
Deletes a service group.
Base Command
pan-os-delete-service-group
Input
| Argument Name | Description | Required |
|---|---|---|
| name | Name of the service group to delete. | Required |
| device-group | The device group for which to return addresses (Panorama instances). | Optional |
Context Output
| Path | Type | Description |
|---|---|---|
| Panorama.ServiceGroups.Name | string | Name of the deleted service group. |
| Panorama.ServiceGroups.DeviceGroup | string | Device group for the service group (Panorama instances). |
Command Example
!pan-os-delete-service-group name=lalush_sg4
pan-os-edit-service-group
Edit a service group.
Base Command
pan-os-edit-service-group
Input
| Argument Name | Description | Required |
|---|---|---|
| name | Name of the service group to edit. | Required |
| services_to_add | Services to add to the service group. Only existing Services objects can be added. | Optional |
| services_to_remove | Services to remove from the service group. Only existing Services objects can be removed. | Optional |
| tags | Tag of the Service group to edit. | Optional |
| device-group | The device group in which the service group belongs to. | Optional |
Context Output
| Path | Type | Description |
|---|---|---|
| Panorama.ServiceGroups.Name | string | Service group name. |
| Panorama.ServiceGroups.Services | string | Service group related services. |
| Panorama.ServiceGroups.DeviceGroup | string | Device group for the service group (Panorama instances). |
| Panorama.ServiceGroups.Tags | String | Service group tags. |
Command Example
!pan-os-edit-service-group name=lalush_sg4 services_to_remove=`["serice_udp_test_pb","demisto_service1"]
Human Readable Output
Service group was edited successfully
pan-os-get-custom-url-category
Returns information for a custom URL category.
Base Command
pan-os-get-custom-url-category
Input
| Argument Name | Description | Required |
|---|---|---|
| name | Custom URL category name. | Required |
| device-group | The device group for which to return addresses for the custom URL category (Panorama instances). | Optional |
Context Output
| Path | Type | Description |
|---|---|---|
| Panorama.CustomURLCategory.Name | String | The category name of the custom URL. |
| Panorama.CustomURLCategory.Description | String | The category description of the custom URL. |
| Panorama.CustomURLCategory.Sites | String | The list of sites of the custom URL category. |
| Panorama.CustomURLCategory.DeviceGroup | String | The device group for the custom URL Category (Panorama instances). |
| Panorama.CustomURLCategory.Categories | String | The list of categories of the custom URL category. |
| Panorama.CustomURLCategory.Type | String | The category type of the custom URL. |
Command Example
!pan-os-get-custom-url-category name=my_personal_url_category
Human Readable Output
Custom URL Category
Name Sites Description my_personal_url_category thepill.com,
abortion.comjust a desc
pan-os-create-custom-url-category
Creates a custom URL category.
Base Command
pan-os-create-custom-url-category
Input
| Argument Name | Description | Required |
|---|---|---|
| name | The name of the custom URL category to create. | Required |
| description | Description of the custom URL category to create. | Optional |
| sites | List of sites for the custom URL category. | Optional |
| device-group | The device group for which to return addresses for the custom URL category (Panorama instances). | Optional |
| type | The category type of the URL. Relevant from PAN-OS v9.x. | Optional |
| categories | The list of categories. Relevant from PAN-OS v9.x. | Optional |
Context Output
| Path | Type | Description |
|---|---|---|
| Panorama.CustomURLCategory.Name | String | Custom URL category name. |
| Panorama.CustomURLCategory.Description | String | Custom URL category description. |
| Panorama.CustomURLCategory.Sites | String | Custom URL category list of sites. |
| Panorama.CustomURLCategory.DeviceGroup | String | Device group for the Custom URL Category (Panorama instances). |
| Panorama.CustomURLCategory.Sites | String | Custom URL category list of categories. |
| Panorama.CustomURLCategory.Type | String | Custom URL category type. |
Command Example
!pan-os-create-custom-url-category name=suspicious_address_group sites=["thepill.com","abortion.com"] description=momo
Context Example
{
"Panorama": {
"CustomURLCategory": {
"Description": "momo",
"Name": "suspicious_address_group",
"Sites": [
"thepill.com",
"abortion.com"
]
}
}
}
Human Readable Output
Created Custom URL Category
Name Sites Description suspicious_address_group thepill.com,
abortion.commomo
pan-os-delete-custom-url-category
Deletes a custom URL category.
Base Command
pan-os-delete-custom-url-category
Input
| Argument Name | Description | Required |
|---|---|---|
| name | Name of the custom URL category to delete. | Optional |
| device-group | The device group for which to return addresses (Panorama instances). | Optional |
Context Output
| Path | Type | Description |
|---|---|---|
| Panorama.CustomURLCategory.Name | string | Name of the custom URL category to delete. |
| Panorama.CustomURLCategory.DeviceGroup | string | Device group for the Custom URL Category (Panorama instances). |
Command Example
!pan-os-delete-custom-url-category name=suspicious_address_group
Context Example
{
"Panorama": {
"CustomURLCategory": {
"Name": "suspicious_address_group"
}
}
}
Human Readable Output
Custom URL category was deleted successfully.
pan-os-edit-custom-url-category
Adds or removes sites to and from a custom URL category.
Base Command
pan-os-edit-custom-url-category
Input
| Argument Name | Description | Required |
|---|---|---|
| name | Name of the custom URL category to add or remove sites. | Required |
| sites | A comma separated list of sites to add to the custom URL category. | Optional |
| action | Adds or removes sites or categories. Possible values are: add, remove | Required |
| categories | A comma separated list of categories to add to the custom URL category. | Optional |
| device-group | The device group in which the URL category belongs to. | Optional |
Context Output
| Path | Type | Description |
|---|---|---|
| Panorama.CustomURLCategory.Name | string | Custom URL category name. |
| Panorama.CustomURLCategory.Description | string | Custom URL category description. |
| Panorama.CustomURLCategory.Sites | string | Custom URL category list of sites. |
| Panorama.CustomURLCategory.DeviceGroup | string | Device group for the Custom URL Category (Panorama instances). |
pan-os-get-url-category
Gets a URL category from URL Filtering. This command is only available on Firewall devices.
Base Command
pan-os-get-url-category
Input
| Argument Name | Description | Required |
|---|---|---|
| url | URL to check. | Optional |
| target | Serial number of the firewall on which to run the command. Use only for a Panorama instance | Optional |
Context Output
| Path | Type | Description |
|---|---|---|
| Panorama.URLFilter.URL | string | URL. |
| Panorama.URLFilter.Category | string | URL category. |
| DBotScore.Vendor | String | The vendor used to calculate the score. |
| DBotScore.Score | Number | The actual score. |
| DBotScore.Type | String | The indicator type. |
| DBotScore.Indicator | String | The indicator that was tested. |
| URL.Data | String | The URL address. |
| URL.Category | String | The URL Category. |
Command Example
!pan-os-get-url-category url="poker.com"
Context Example
{
"DBotScore": {
"Indicator": "poker.com",
"Score": 1,
"Type": "url",
"Vendor": "PAN-OS"
},
"Panorama": {
"URLFilter": {
"Category": "gambling",
"URL": [
"poker.com"
]
}
},
"URL": {
"Category": "gambling",
"Data": "poker.com"
}
}
Human Readable Output
URL Filtering
URL Category poker.com gambling
url
Gets a URL category from URL Filtering. This command is only available on Firewall devices.
Base Command
url
Input
| Argument Name | Description | Required |
|---|---|---|
| url | URL to check. | Optional |
Context Output
| Path | Type | Description |
|---|---|---|
| Panorama.URLFilter.URL | string | URL. |
| Panorama.URLFilter.Category | string | The URL category. |
| DBotScore.Vendor | String | The vendor used to calculate the score. |
| DBotScore.Score | Number | The actual score. |
| DBotScore.Type | String | The indicator type. |
| DBotScore.Indicator | String | The indicator that was tested. |
| URL.Data | String | The URL address. |
| URL.Category | String | The URL category. |
pan-os-get-url-category-from-cloud
Returns a URL category from URL filtering. This command is only available on Firewall devices.
Base Command
pan-os-get-url-category-from-cloud
Input
| Argument Name | Description | Required |
|---|---|---|
| url | URL to check. | Required |
Context Output
| Path | Type | Description |
|---|---|---|
| Panorama.URLFilter.URL | string | The URL. |
| Panorama.URLFilter.Category | string | URL category. |
Command Example
!pan-os-get-url-category-from-cloud url=google.com
Human Readable Output
URL Filtering from cloud
URL Category google.com search-engines
pan-os-get-url-category-from-host
Returns a URL category from URL Filtering.
Base Command
pan-os-get-url-category-from-host
Input
| Argument Name | Description | Required |
|---|---|---|
| url | URL to check. | Required |
Context Output
| Path | Type | Description |
|---|---|---|
| Panorama.URLFilter.URL | string | The URL. |
| Panorama.URLFilter.Category | string | The URL category. |
Command Example
!pan-os-get-url-category-from-host url=google.com
Human Readable Output
URL Filtering from host
URL Category google.com search-engines
pan-os-get-url-filter
Returns information for a URL filtering rule.
Base Command
pan-os-get-url-filter
Input
| Argument Name | Description | Required |
|---|---|---|
| name | URL Filter name. | Required |
| device-group | The device group for which to return addresses for the URL Filter (Panorama instances). | Optional |
Context Output
| Path | Type | Description |
|---|---|---|
| Panorama.URLFilter.Name | string | URL Filter name. |
| Panorama.URLFilter.Category.Name | string | URL Filter category name. |
| Panorama.URLFilter.Category.Action | string | Action for the URL category. |
| Panorama.URLFilter.OverrideBlockList | string | URL Filter override block list. |
| Panorama.URLFilter.OverrideAllowList | string | URL Filter override allow list. |
| Panorama.URLFilter.Description | string | URL Filter description. |
| Panorama.URLFilter.DeviceGroup | string | Device group for the URL Filter (Panorama instances). |
Command Example
!pan-os-get-url-filter name=demisto_default_url_filter
Human Readable Output
URL Filter
Name Category OverrideAllowList Description demisto_default_url_filter {‘Action’: ‘block’, ‘Name’: u’abortion’},
{‘Action’: ‘block’, ‘Name’: u’abuse-drugs’}888.com,
777.comgres
pan-os-create-url-filter
Creates a URL filtering rule.
Base Command
pan-os-create-url-filter
Input
| Argument Name | Description | Required |
|---|---|---|
| name | Name of the URL filter to create. | Required |
| url_category | URL categories. | Required |
| action | Action for the URL categories. Can be “allow”, “block”, “alert”, “continue”, or “override”. | Required |
| override_allow_list | CSV list of URLs to exclude from the allow list. | Optional |
| override_block_list | CSV list of URLs to exclude from the blocked list. | Optional |
| description | URL Filter description. | Optional |
| device-group | The device group for which to return addresses for the URL Filter (Panorama instances). | Optional |
Context Output
| Path | Type | Description |
|---|---|---|
| Panorama.URLFilter.Name | string | URL Filter name. |
| Panorama.URLFilter.Category.Name | string | URL Filter category name. |
| Panorama.URLFilter.Category.Action | string | Action for the URL category. |
| Panorama.URLFilter.OverrideBlockList | string | URL Filter override allow list. |
| Panorama.URLFilter.OverrideBlockList | string | URL Filter override blocked list. |
| Panorama.URLFilter.Description | string | URL Filter description. |
| Panorama.URLFilter.DeviceGroup | string | Device group for the URL Filter (Panorama instances). |
Command Example
!pan-os-create-url-filter action=block name=gambling_url url_category=gambling
Context Example
{
"Panorama": {
"URLFilter": {
"Category": [
{
"Action": "block",
"Name": "gambling"
}
],
"Name": "gambling_url"
}
}
}
Human Readable Output
URL Filter was created successfully.
pan-os-edit-url-filter
Edit a URL filtering rule.
Base Command
pan-os-edit-url-filter
Input
| Argument Name | Description | Required |
|---|---|---|
| name | Name of the URL filter to edit. | Required |
| element_to_change | Element to change. | Required |
| element_value | Element value. Limited to one value. | Required |
| add_remove_element | Add or remove an element from the Allow List or Block List fields. Default is to ‘add’ the element_value to the list. | Optional |
| device-group | The device group in which the URL-filter belongs to. | Optional |
Context Output
| Path | Type | Description |
|---|---|---|
| Panorama.URLFilter.Name | string | URL Filter name. |
| Panorama.URLFilter.Description | string | URL Filter description. |
| Panorama.URLFilter.Category.Name | string | URL Filter category. |
| Panorama.URLFilter.Action | string | Action for the URL category. |
| Panorama.URLFilter.OverrideAllowList | string | Allow Overrides for the URL category. |
| Panorama.URLFilter.OverrideBlockList | string | Block Overrides for the URL category. |
| Panorama.URLFilter.DeviceGroup | string | Device group for the URL Filter (Panorama instances). |
Command Example
!pan-os-edit-url-filter name=demisto_default_url_filter element_to_change=override_allow_list element_value="poker.com" add_remove_element=add
Human Readable Output
URL Filter was edited successfully
pan-os-delete-url-filter
Deletes a URL filtering rule.
Base Command
pan-os-delete-url-filter
Input
| Argument Name | Description | Required |
|---|---|---|
| name | Name of the URL filter rule to delete. | Required |
| device-group | The device group for which to return addresses for the URL filter (Panorama instances) | Optional |
Context Output
| Path | Type | Description |
|---|---|---|
| Panorama.URLFilter.Name | string | URL filter rule name. |
| Panorama.URLFilter.DeviceGroup | string | Device group for the URL Filter (Panorama instances). |
Command Example
!pan-os-delete-url-filter name=gambling_url
Context Example
{
"Panorama": {
"URLFilter": {
"Name": "gambling_url"
}
}
}
Human Readable Output
URL Filter was deleted successfully.
pan-os-list-edls
Returns a list of external dynamic lists.
Base Command
pan-os-list-edls
Input
| Argument Name | Description | Required |
|---|---|---|
| device-group | The device group for which to return addresses for the EDL (Panorama instances). | Optional |
Context Output
| Path | Type | Description |
|---|---|---|
| Panorama.EDL.Name | string | Name of the EDL. |
| Panorama.EDL.Type | string | The type of EDL. |
| Panorama.EDL.URL | string | URL in which the EDL is stored. |
| Panorama.EDL.Description | string | Description of the EDL. |
| Panorama.EDL.CertificateProfile | string | EDL certificate profile. |
| Panorama.EDL.Recurring | string | Time interval that the EDL was pulled and updated. |
| Panorama.EDL.DeviceGroup | string | Device group for the EDL (Panorama instances). |
Command Example
#### Context Example
```json
{
"Panorama": {
"EDL": [
{
"Description": "6u4ju7",
"Name": "blabla3",
"Recurring": "hourly",
"Type": "url",
"URL": "lolo"
},
{
"Description": "ip",
"Name": "bad_ip_edl_demisot_web_server",
"Recurring": "five-minute",
"Type": "ip",
"URL": "http://192.168.1.15/files/very_bad_ip2.txt"
}
]
}
}
Human Readable Output
External Dynamic Lists
Name Type URL Recurring Description blabla3 url lolo hourly 6u4ju7 bad_ip_edl_demisot_web_server ip http://192.168.1.15/files/very_bad_ip2.txt five-minute ip
pan-os-get-edl
Returns information for an external dynamic list
Base Command
pan-os-get-edl
Input
| Argument Name | Description | Required |
|---|---|---|
| name | Name of the EDL. | Required |
| device-group | The device group for which to return addresses for the EDL (Panorama instances). | Optional |
Context Output
| Path | Type | Description |
|---|---|---|
| Panorama.EDL.Name | string | Name of the EDL. |
| Panorama.EDL.Type | string | The type of EDL. |
| Panorama.EDL.URL | string | URL in which the EDL is stored. |
| Panorama.EDL.Description | string | Description of the EDL. |
| Panorama.EDL.CertificateProfile | string | EDL certificate profile. |
| Panorama.EDL.Recurring | string | Time interval that the EDL was pulled and updated. |
| Panorama.EDL.DeviceGroup | string | Device group for the EDL (Panorama instances). |
Command Example
!pan-os-get-edl name=test_pb_domain_edl_DONT_DEL
Context Example
{
"Panorama": {
"EDL": {
"Description": "new description3",
"Name": "test_pb_domain_edl_DONT_DEL",
"Recurring": "hourly",
"Type": "url",
"URL": "https://test_pb_task.not.real"
}
}
}
Human Readable Output
External Dynamic List
Name Type URL Recurring Description test_pb_domain_edl_DONT_DEL url https://test_pb_task.not.real hourly new description3
pan-os-create-edl
Creates an external dynamic list.
Base Command
pan-os-create-edl
Input
| Argument Name | Description | Required |
|---|---|---|
| name | Name of the EDL. | Required |
| url | URL from which to pull the EDL. | Required |
| type | The type of EDL. | Required |
| recurring | Time interval for pulling and updating the EDL. | Required |
| certificate_profile | Certificate Profile name for the URL that was previously uploaded. to PAN OS. | Optional |
| description | Description of the EDL. | Optional |
| device-group | The device group for which to return addresses for the EDL (Panorama instances). | Optional |
Context Output
| Path | Type | Description |
|---|---|---|
| Panorama.EDL.Name | string | Name of theEDL. |
| Panorama.EDL.Type | string | Type of the EDL. |
| Panorama.EDL.URL | string | URL in which the EDL is stored. |
| Panorama.EDL.Description | string | Description of the EDL. |
| Panorama.EDL.CertificateProfile | string | EDL certificate profile. |
| Panorama.EDL.Recurring | string | Time interval that the EDL was pulled and updated. |
| Panorama.EDL.DeviceGroup | string | Device group for the EDL (Panorama instances). |
Command Example
!pan-os-create-edl name=new_EDL recurring="five-minute" type=url url="gmail.com"
Context Example
{
"Panorama": {
"EDL": {
"Name": "new_EDL",
"Recurring": "five-minute",
"Type": "url",
"URL": "gmail.com"
}
}
}
Human Readable Output
External Dynamic List was created successfully.
pan-os-edit-edl
Modifies an element of an external dynamic list.
Base Command
pan-os-edit-edl
Input
| Argument Name | Description | Required |
|---|---|---|
| name | Name of the external dynamic list to edit. | Required |
| element_to_change | The element to change (“url”, “recurring”, “certificate_profile”, “description”). | Required |
| element_value | The element value. | Required |
| device-group | The device group in which the EDL belongs to. | Optional |
Context Output
| Path | Type | Description |
|---|---|---|
| Panorama.EDL.Name | string | Name of the EDL. |
| Panorama.EDL.URL | string | URL where the EDL is stored. |
| Panorama.EDL.Description | string | Description of the EDL. |
| Panorama.EDL.CertificateProfile | string | EDL certificate profile. |
| Panorama.EDL.Recurring | string | Time interval that the EDL was pulled and updated. |
| Panorama.EDL.DeviceGroup | string | Device group for the EDL (Panorama instances). |
Command Example
!pan-os-edit-edl name=test_pb_domain_edl_DONT_DEL element_to_change=description element_value="new description3"
Context Example
{
"Panorama": {
"EDL": {
"Description": "new description3",
"Name": "test_pb_domain_edl_DONT_DEL"
}
}
}
Human Readable Output
External Dynamic List was edited successfully
pan-os-delete-edl
Deletes an external dynamic list.
Base Command
pan-os-delete-edl
Input
| Argument Name | Description | Required |
|---|---|---|
| name | Name of the EDL to delete. | Required |
| device-group | The device group for which to return addresses for the EDL (Panorama instances). | Optional |
Context Output
| Path | Type | Description |
|---|---|---|
| Panorama.EDL.Name | string | Name of the EDL that was deleted. |
| Panorama.EDL.DeviceGroup | string | Device group for the EDL (Panorama instances). |
Command Example
!pan-os-delete-edl name=new_EDL
Context Example
{
"Panorama": {
"EDL": {
"Name": "new_EDL"
}
}
}
Human Readable Output
External Dynamic List was deleted successfully
pan-os-refresh-edl
Refreshes the specified external dynamic list.
Base Command
pan-os-refresh-edl
Input
| Argument Name | Description | Required |
|---|---|---|
| name | Name of the EDL | Required |
| device-group | The device group for which to return addresses for the EDL (Panorama instances). | Optional |
| edl_type | The type of the EDL. Required when refreshing an EDL object which is configured on Panorama. | Optional |
| location | The location of the EDL. Required when refreshing an EDL object which is configured on Panorama. | Optional |
| vsys | The Vsys of the EDL. Required when refreshing an EDL object which is configured on Panorama. | Optional |
Context Output
There is no context output for this command.
Command Example
!pan-os-refresh-edl name=test_pb_domain_edl_DONT_DEL
Human Readable Output
Refreshed External Dynamic List successfully
pan-os-create-rule
Creates a policy rule.
Base Command
pan-os-create-rule
Input
| Argument Name | Description | Required |
|---|---|---|
| rulename | Name of the rule to create. | Optional |
| description | Description of the rule to create. | Optional |
| action | Action for the rule. Can be “allow”, “deny”, or “drop”. | Required |
| source | A comma-separated list of address object names, address group object names, or EDL object names. | Optional |
| destination | A comma-separated list of address object names, address group object names, or EDL object names. | Optional |
| source_zone | A comma-separated list of source zones. | Optional |
| destination_zone | A comma-separated list of destination zones. | Optional |
| negate_source | Whether to negate the source (address, address group). Can be “Yes” or “No”. | Optional |
| negate_destination | Whether to negate the destination (address, address group). Can be “Yes” or “No”. | Optional |
| service | A comma-separated list of service object names for the rule. | Optional |
| disable | Whether to disable the rule. Can be “Yes” or “No” (default is “No”). | Optional |
| application | A comma-separated list of application object names for the rule. | Optional |
| source_user | A comma-separated list of source users for the rule to create. | Optional |
| pre_post | Pre rule or Post rule (Panorama instances). | Optional |
| target | Specifies a target firewall for the rule (Panorama instances). | Optional |
| log_forwarding | Log forwarding profile. | Optional |
| device-group | The device group for which to return addresses for the rule (Panorama instances). | Optional |
| tags | Rule tags to create. | Optional |
| category | A comma-separated list of URL categories. | Optional |
| profile_setting | A profile setting group. | Optional |
| where | Where to move the rule. Can be “before”, “after”, “top”, or “bottom”. If you specify “before” or “after”, you need to supply the “dst” argument. | Optional |
| dst | Destination rule relative to the rule that you are moving. This field is only relevant if you specify “before” or “after” in the “where” argument. | Optional |
| audit_comment | An audit comment for the rule. | Optional |
Context Output
| Path | Type | Description |
|---|---|---|
| Panorama.SecurityRule.Name | string | Rule name. |
| Panorama.SecurityRule.Description | string | Rule description. |
| Panorama.SecurityRule.Action | string | Action for the rule. |
| Panorama.SecurityRule.Source | string | Source address. |
| Panorama.SecurityRule.Destination | string | Destination address. |
| Panorama.SecurityRule.NegateSource | boolean | Whether the source is negated (address, address group). |
| Panorama.SecurityRule.NegateDestination | boolean | Whether the destination negated (address, address group). |
| Panorama.SecurityRule.Service | string | Service for the rule. |
| Panorama.SecurityRule.Disabled | string | Whether the rule is disabled. |
| Panorama.SecurityRule.Application | string | Application for the rule. |
| Panorama.SecurityRule.Target | string | Target firewall (Panorama instances). |
| Panorama.SecurityRule.LogForwarding | string | Log forwarding profile (Panorama instances). |
| Panorama.SecurityRule.DeviceGroup | string | Device group for the rule (Panorama instances). |
| Panorama.SecurityRules.Tags | String | Rule tags. |
| Panorama.SecurityRules.ProfileSetting | String | Profile setting group. |
Command Example
!pan-os-create-rule rulename="block_bad_application" description="do not play at work" action="deny" application="fortnite"
Context Example
{
"Panorama": {
"SecurityRule": {
"Action": "deny",
"Application": "fortnite",
"Description": "do not play at work",
"Disabled": "No",
"Name": "block_bad_application",
"SourceUser": "any"
}
}
}
Human Readable Output
Rule configured successfully.
pan-os-custom-block-rule
Creates a custom block policy rule.
Base Command
pan-os-custom-block-rule
Input
| Argument Name | Description | Required |
|---|---|---|
| rulename | The name of the custom block policy rule to create. | Optional |
| object_type | The object type to block in the policy rule. Possible values are: ip, address-group, application, url-category, edl. | Required |
| object_value | A comma-separated list of object values for the object_type argument. | Required |
| direction | The direction to block. This argument is not applicable for the “custom-url-category” object_type. Possible values are: to, from, both. Default is both. | Optional |
| pre_post | The pre-rule or post-rule (Panorama instances). Possible values are: pre-rulebase, post-rulebase. | Optional |
| target | Specifies a target firewall for the rule (Panorama instances). | Optional |
| log_forwarding | The log forwarding profile. | Optional |
| device-group | The device group for which to return addresses for the rule (Panorama instances). | Optional |
| tags | The tags to use for the custom block policy rule. | Optional |
| where | Where to move the rule. If you specify “before” or “after”, you need to supply the “dst” argument. Possible values are: before, after, top, bottom. Default is bottom. | Optional |
| dst | The destination rule relative to the rule that you are moving. This field is only relevant if you specify “before” or “after” in the “where” argument. | Optional |
Context Output
| Path | Type | Description |
|---|---|---|
| Panorama.SecurityRule.Name | string | The rule name. |
| Panorama.SecurityRule.Object | string | The blocked object. |
| Panorama.SecurityRule.Direction | string | The direction blocked. |
| Panorama.SecurityRule.Target | string | The target firewall (Panorama instances). |
| Panorama.SecurityRule.LogForwarding | string | The log forwarding profile (Panorama instances). |
| Panorama.SecurityRule.DeviceGroup | string | The device group for the rule (Panorama instances). |
| Panorama.SecurityRule.Tags | String | The rule tags. |
| Panorama.SecurityRules.ProfileSetting | String | The profile setting group. |
Command Example
!pan-os-custom-block-rule object_type=application object_value=fortnite
Context Example
{
"Panorama": {
"SecurityRule": {
"Application": [
"fortnite"
],
"Direction": "both",
"Disabled": false,
"Name": "demisto-9c9ed15a"
}
}
}
Human Readable Output
Object was blocked successfully.
pan-os-move-rule
Changes the location of a policy rule.
Base Command
pan-os-move-rule
Input
| Argument Name | Description | Required |
|---|---|---|
| rulename | Name of the rule to move. | Required |
| where | Where to move the rule. Can be “before”, “after”, “top”, or “bottom”. If you specify “before” or “after”, you need to supply the “dst” argument. | Required |
| dst | Destination rule relative to the rule that you are moving. This field is only relevant if you specify “before” or “after” in the “where” argument. | Optional |
| pre_post | Rule location. Mandatory for Panorama instances. | Optional |
| device-group | The device group for which to return addresses for the rule (Panorama instances). | Optional |
Context Output
| Path | Type | Description |
|---|---|---|
| Panorama.SecurityRule.Name | string | Rule name. |
| Panorama.SecurityRule.DeviceGroup | string | Device group for the rule (Panorama instances). |
Command Example
!pan-os-move-rule rulename="test_rule3" where="bottom"
Human Readable Output
Rule test_rule3 moved successfully
pan-os-edit-rule
Edits a policy rule.
Base Command
pan-os-edit-rule
Input
| Argument Name | Description | Required |
|---|---|---|
| rulename | Name of the rule to edit. | Required |
| element_to_change | Parameter in the security rule to change. Can be ‘source’, ‘destination’, ‘application’, ‘action’, ‘category’, ‘description’, ‘disabled’, ‘target’, ‘log-forwarding’, ‘tag’, ‘source-user’, ‘service’, ‘profile-setting’ or ‘audit-comment’. | Required |
| element_value | The new value for the parameter. | Required |
| pre_post | Pre-rule or post-rule (Panorama instances). | Optional |
| behaviour | Whether to replace, add, or remove the element_value from the current rule object value. | Optional |
| device-group | The device group in which the rule belongs to. | Optional |
Context Output
| Path | Type | Description |
|---|---|---|
| Panorama.SecurityRule.Name | string | Rule name. |
| Panorama.SecurityRule.Description | string | Rule description. |
| Panorama.SecurityRule.Action | string | Action for the rule. |
| Panorama.SecurityRule.Source | string | Source address. |
| Panorama.SecurityRule.Destination | string | Destination address. |
| Panorama.SecurityRule.NegateSource | boolean | Whether the source is negated (address, address group). |
| Panorama.SecurityRule.NegateDestination | boolean | Whether the destination is negated (address, address group). |
| Panorama.SecurityRule.Service | string | Service for the rule. |
| Panorama.SecurityRule.Disabled | string | Whether the rule is disabled. |
| Panorama.SecurityRule.Application | string | Application for the rule. |
| Panorama.SecurityRule.Target | string | Target firewall (Panorama instances). |
| Panorama.SecurityRule.DeviceGroup | string | Device group for the rule (Panorama instances). |
| Panorama.SecurityRule.Category | string | The category of the rule. |
| Panorama.SecurityRule.LogForwarding | string | The log forwarding of the rule. |
| Panorama.SecurityRule.ProfileSetting | string | The profile setting of the rule. |
| Panorama.SecurityRule.SourceUser | string | The source user of the rule. |
| Panorama.SecurityRule.AuditComment | string | The audit comment of the rule. |
| Panorama.SecurityRule.Tags | String | Tags for the rule. |
| Panorama.SecurityRules.ProfileSetting | String | Profile setting group. |
Command Example
!pan-os-edit-rule rulename="block_bad_application" element_to_change=action element_value=drop
Context Example
{
"Panorama": {
"SecurityRule": {
"Action": "drop",
"Name": "block_bad_application"
}
}
}
Human Readable Output
Rule edited successfully.
pan-os-delete-rule
Deletes a policy rule.
Base Command
pan-os-delete-rule
Input
| Argument Name | Description | Required |
|---|---|---|
| rulename | The name of the rule to delete. | Required |
| pre_post | The pre-rule or post-rule (Panorama instances). Possible values are: pre-rulebase, post-rulebase. | Optional |
| device-group | The device group where the rule is configured (Panorama instances). | Optional |
| target | Serial number of the firewall on which to run the command. Use only for a Panorama instance. | Optional |
| rulebase | The rulebase from which to delete the rule. Possible values are: security, application-override, authentication, decryption, nat, pbf. Default is security. | Required |
| vsys | The Firewall VSYS to delete the rule from. Use for deleting local rules from a firewall via Panorama or to specify a different VSYS than set in Integration parameters. Default is vsys1. | Optional |
Context Output
| Path | Type | Description |
|---|---|---|
| Panorama.SecurityRule.Name | string | The rule name. |
| Panorama.SecurityRule.DeviceGroup | string | The device group for the rule (Panorama instances). |
| Panorama.NAT.Name | string | The rule name. |
| Panorama.NAT.DeviceGroup | string | The device group for the rule (Panorama instances). |
| Panorama.SSLRule.Name | string | The rule name. |
| Panorama.SSLRule.DeviceGroup | string | The device group for the rule (Panorama instances). |
| Panorama.PBF.Name | string | The rule name. |
| Panorama.PBF.DeviceGroup | string | The device group for the rule (Panorama instances). |
| Panorama.AuthRule.Name | string | The rule name. |
| Panorama.AuthRule.DeviceGroup | string | The device group for the rule (Panorama instances). |
| Panorama.AppOverride.Name | string | The rule name. |
| Panorama.AppOverride.DeviceGroup | string | The device group for the rule (Panorama instances). |
| Panorama.CleanedUpRules.Category | string | The category of the rule that was cleaned up (Local or Panorama). |
| Panorama.CleanedUpRules.AppliedAction | string | The applied cleanup action (Disabled or Deleted). |
| Panorama.CleanedUpRules.DeviceGroup | string | The device group where the rule was cleaned up from (Panorama instances). |
| Panorama.CleanedUpRules.PrePost | string | The location where the rule was cleaned up from (Panorama instances). |
| Panorama.CleanedUpRules.RuleName | string | The name of the rule. |
| Panorama.CleanedUpRules.Rulebase | string | The rulebase where the rule was cleaned up from (e.g. ‘security’, ‘nat’). |
| Panorama.CleanedUpRules.Target | string | The target firewall serial number, if provided. |
| Panorama.CleanedUpRules.Vsys | string | The VSYS where the rule was cleaned up from. |
pan-os-list-applications
Returns a list of applications.
Base Command
pan-os-list-applications
Input
| Argument Name | Description | Required |
|---|---|---|
| predefined | Whether to list predefined applications. Possible values are: true, false. Default is false. | Optional |
| device-group | The device group for which to return applications. | Optional |
| name_match | When specified, the results returned in the list are limited to applications whose names match the specified string. | Optional |
| name_contain | When specified, the results returned in the list are limited to applications whose names contain the specified string. | Optional |
| risk | The application risk (1 to 5). Possible values are: 1, 2, 3, 4, 5. | Optional |
| category | The application category. Possible values are: collaboration, business-systems, networking, media. | Optional |
| sub_category | The application sub-category. | Optional |
| technology | The application technology. Possible values are: browser-based, client-server, network-protocol, peer-to-peer. | Optional |
| characteristics | A comma-separated list of characteristics. Possible values are: ‘virus-ident’, ‘evasive-behavior’, ‘file-type-ident’, ‘consume-big-bandwidth’, ‘used-by-malware’, ‘able-to-transfer-file’, ‘has-known-vulnerability’, ‘tunnel-other-application’, ‘prone-to-misuse’, ‘pervasive-use’, ‘file-forward’, ‘is-saas’. | Optional |
| limit | The maximum number of rules to retrieve. Will be used by default if page argument was not provided. Default is 50. | Optional |
| page_size | The page size of the applications to return. Default is 50. | Optional |
| page | The page at which to start listing applications. Must be a positive number. | Optional |
Context Output
| Path | Type | Description |
|---|---|---|
| Panorama.Applications.Name | string | The application name. |
| Panorama.Applications.Id | number | The application ID. |
| Panorama.Applications.Category | string | The application category. |
| Panorama.Applications.SubCategory | string | The application sub-category. |
| Panorama.Applications.Technology | string | The application technology. |
| Panorama.Applications.Risk | number | The application risk (1 to 5). |
| Panorama.Applications.Description | string | The application description. |
| Panorama.Applications.Characteristics | string | The application characteristics. |
Command Example
#### Context Example
```json
{
"Panorama": {
"Applications": {
"Description": "lala",
"Id": null,
"Name": "demisto_fw_app3",
"Risk": "1",
"SubCategory": "ip-protocol",
"Technology": "peer-to-peer"
}
}
}
Human Readable Output
Applications
Id Name Risk Category SubCategory Technology Description demisto_fw_app3 1 ip-protocol peer-to-peer lala
pan-os-push-status
Returns the push status for a configuration.
Base Command
pan-os-push-status
Input
| Argument Name | Description | Required |
|---|---|---|
| job_id | The job ID to check. | Required |
Context Output
| Path | Type | Description |
|---|---|---|
| Panorama.Push.DeviceGroup | string | The device group to which the policies were pushed. |
| Panorama.Push.JobID | number | The job ID of the configuration to be pushed. |
| Panorama.Push.Status | string | The push status. |
| Panorama.Push.Details | string | The job ID details. |
| Panorama.Push.Warnings | String | The job ID warnings |
Command example
!pan-os-push-status job_id=31377
Context Example
{
"Panorama": {
"Push": {
"Details": [
"commit succeeded with warnings",
"commit succeeded with warnings"
],
"Errors": [],
"JobID": "31377",
"Status": "Completed",
"Warnings": [
"Interface loopback.645 has no zone configuration.",
"External Dynamic List test_pb_domain_edl_DONT_DEL is configured with no certificate profile. Please select a certificate profile for performing server certificate validation.",
"External Dynamic List Cortex XSOAR Remediation - IP EDL-ip-edl-object is configured with no certificate profile. Please select a certificate profile for performing server certificate validation.",
"External Dynamic List Cortex XSOAR Remediation - URL EDL-url-edl-object is configured with no certificate profile. Please select a certificate profile for performing server certificate validation.",
"External Dynamic List Cortex XSOAR Remediation - URL EDL tamarcat3-url-edl-object is configured with no certificate profile. Please select a certificate profile for performing server certificate validation.",
"External Dynamic List Cortex XSOAR Remediation - IP EDL tamarcat3-ip-edl-object is configured with no certificate profile. Please select a certificate profile for performing server certificate validation.",
"External Dynamic List minemeld is configured with no certificate profile. Please select a certificate profile for performing server certificate validation.",
"External Dynamic List edl-webinar-malicious-urls-OLD is configured with no certificate profile. Please select a certificate profile for performing server certificate validation.",
"External Dynamic List edl-webinar-malicious-ips is configured with no certificate profile. Please select a certificate profile for performing server certificate validation.",
"External Dynamic List edl-webinar-malicious-domains is configured with no certificate profile. Please select a certificate profile for performing server certificate validation.",
"Warning: No valid Antivirus content package exists",
"(Module: device)"
]
}
}
}
Human Readable Output
Push to Device Group status
JobID Status Details Errors Warnings 31377 Completed commit succeeded with warnings,
commit succeeded with warningsInterface loopback.645 has no zone configuration.,
External Dynamic List test_pb_domain_edl_DONT_DEL is configured with no certificate profile. Please select a certificate profile for performing server certificate validation.,
External Dynamic List Cortex XSOAR Remediation - IP EDL-ip-edl-object is configured with no certificate profile. Please select a certificate profile for performing server certificate validation.,
External Dynamic List Cortex XSOAR Remediation - URL EDL-url-edl-object is configured with no certificate profile. Please select a certificate profile for performing server certificate validation.,
External Dynamic List Cortex XSOAR Remediation - URL EDL tamarcat3-url-edl-object is configured with no certificate profile. Please select a certificate profile for performing server certificate validation.,
External Dynamic List Cortex XSOAR Remediation - IP EDL tamarcat3-ip-edl-object is configured with no certificate profile. Please select a certificate profile for performing server certificate validation.,
External Dynamic List minemeld is configured with no certificate profile. Please select a certificate profile for performing server certificate validation.,
External Dynamic List edl-webinar-malicious-urls-OLD is configured with no certificate profile. Please select a certificate profile for performing server certificate validation.,
External Dynamic List edl-webinar-malicious-ips is configured with no certificate profile. Please select a certificate profile for performing server certificate validation.,
External Dynamic List edl-webinar-malicious-domains is configured with no certificate profile. Please select a certificate profile for performing server certificate validation.,
Warning: No valid Antivirus content package exists,
(Module: device)
pan-os-get-pcap
Returns information for a Panorama PCAP file. The recommended maximum file size is 5 MB. If the limit is exceeded, you might need to SSH the firewall and run the scp export command to export the PCAP file. For more information, see the Palo Alto Networks documentation.
When trying to retrieve threat-PCAPs of a firewall through a panorama instance, be sure to forward the log containing the threat PCAP file from the firewall to the panorama instance.
For more information follow instructions from here.
Base Command
pan-os-get-pcap
PCAPs api docs
You can find information about required/optional arguments for each pcap type here:




Input
| Argument Name | Description | Required |
|---|---|---|
| pcapType | Type of Packet Capture. | Required |
| serialNumber | The serial number of the firewall to download the PCAP from. | Optional |
| from | The file name for the PCAP type (‘dlp-pcap’, ‘filter-pcap’, or ‘application-pcap’). Required for ‘filter-pcap’. | Optional |
| localName | The new name for the PCAP file after downloading. If this argument is not specified, the file name is the PCAP file name set in the firewall. | Optional |
| serialNo | Serial number for the request. For further information, see the Panorama XML API Documentation. | Optional |
| searchTime | The Search time for the request. For example: “2019/12/26 00:00:00”, “2020/01/10”. For more information, see the Panorama XML API documentation. Required for “threat-pcap”. | Optional |
| pcapID | The ID of the PCAP for the request. For further information, see the Panorama XML API Documentation. Required for ‘threat-pcap’. | Optional |
| password | Password for Panorama, needed for the ‘dlp-pcap’ PCAP type only. | Optional |
| deviceName | The Device Name on which the PCAP is stored. For further information, see the Panorama XML API Documentation. Required for ‘threat-pcap’ in pan-os firewalls < 9.0.7 versions. | Optional |
| sessionID | The Session ID of the PCAP. For further information, see the Panorama XML API Documentation. Required for ‘threat-pcap’ in pan-os firewalls < 9.0.7 versions. | Optional |
Context Output
| Path | Type | Description |
|---|---|---|
| File.Size | number | File size. |
| File.Name | string | File name. |
| File.Type | string | File type. |
| File.Info | string | File info. |
| File.Extension | string | File extension. |
| File.EntryID | string | FIle entryID. |
| File.MD5 | string | MD5 hash of the file. |
| File.SHA1 | string | SHA1 hash of the file. |
| File.SHA256 | string | SHA256 hash of the file. |
| File.SHA512 | string | SHA512 hash of the file. |
| File.SSDeep | string | SSDeep hash of the file. |
Command Example
!pan-os-get-pcap pcapType="filter-pcap" from=pcap_test
pan-os-list-pcaps
Returns a list of all PCAP files by PCAP type. Not available for threat PCAPs.
Base Command
pan-os-list-pcaps
Input
| Argument Name | Description | Required |
|---|---|---|
| pcapType | Type of Packet Capture. | Required |
| serialNumber | The serial number of the firewall to download the PCAP from. | Optional |
| password | Password for Panorama. Relevant for the ‘dlp-pcap’ PCAP type. | Optional |
Context Output
There is no context output for this command.
Command Example
!pan-os-list-pcaps pcapType=“filter-pcap”
Human Readable Output
List of Pcaps
Pcap name pcam_name
pan-os-register-ip-tag
Registers IP addresses to a tag.
Base Command
pan-os-register-ip-tag
Input
| Argument Name | Description | Required |
|---|---|---|
| tag | Tag for which to register IP addresses. | Required |
| IPs | IP addresses to register. | Required |
| persistent | Whether the IP addresses remain registered to the tag after the device reboots (‘true’:persistent, ‘false’:non-persistent). Default is ‘true’. | Optional |
Context Output
| Path | Type | Description |
|---|---|---|
| Panorama.DynamicTags.Tag | string | Name of the tag. |
| Panorama.DynamicTags.IPs | string | Registered IP addresses. |
Command Example
!pan-os-register-ip-tag tag=tag02 IPs=[“10.0.0.13”,“10.0.0.14”]
Human Readable Output
Registered ip-tag successfully
pan-os-unregister-ip-tag
Unregisters IP addresses from a tag.
Base Command
pan-os-unregister-ip-tag
Input
| Argument Name | Description | Required |
|---|---|---|
| tag | Tag for which to unregister IP addresses. | Required |
| IPs | IP addresses to unregister. | Required |
Context Output
There is no context output for this command.
Command Example
!pan-os-unregister-ip-tag tag=tag02 IPs=["10.0.0.13","10.0.0.14"]
Human Readable Output
Unregistered ip-tag successfully
pan-os-register-user-tag
Registers users to a tag. This command is only available for PAN-OS version 9.x and above.
Base Command
pan-os-register-user-tag
Input
| Argument Name | Description | Required |
|---|---|---|
| tag | Tag for which to register users. | Required |
| Users | A comma-separated list of users to register. | Required |
Context Output
| Path | Type | Description |
|---|---|---|
| Panorama.DynamicTags.Tag | string | Name of the tag. |
| Panorama.DynamicTags.Users | string | List of registered users. |
Command Example
!pan-os-register-user-tag tag-tag02 Users=Username
Human Readable Output
Registered user-tag successfully
pan-os-unregister-user-tag
Unregisters users from a tag. This command is only available for PAN-OS version 9.x and above.
Base Command
pan-os-unregister-user-tag
Input
| Argument Name | Description | Required |
|---|---|---|
| tag | Tag from which to unregister Users. | Required |
| Users | A comma-separated list of users to unregister. | Required |
Context Output
There is no context output for this command.
Command Example
!pan-os-unregister-user-tag tag-tag02 Users=Username
Human Readable Output
Unregistered user-tag successfully
pan-os-query-traffic-logs
Deprecated. Queries traffic logs.
Base Command
pan-os-query-traffic-logs
Input
| Argument Name | Description | Required |
|---|---|---|
| query | Specifies the match criteria for the logs. This is similar to the query provided in the web interface under the Monitor tab when viewing the logs. | Optional |
| number_of_logs | The number of logs to retrieve. Default is 100. Maximum is 5,000. | Optional |
| direction | Whether logs are shown oldest first (forward) or newest first (backward). Default is backward. | Optional |
| source | Source address for the query. | Optional |
| destination | Destination address for the query. | Optional |
| receive_time | Date and time after which logs were received, in the format: YYYY/MM/DD HH:MM:SS. | Optional |
| application | Application for the query. | Optional |
| to_port | Destination port for the query. | Optional |
| action | Action for the query. | Optional |
Context Output
| Path | Type | Description |
|---|---|---|
| Panorama.TrafficLogs.JobID | number | Job ID of the traffic logs query. |
| Panorama.TrafficLogs.Status | string | Status of the traffic logs query. |
Command Example
!pan-os-query-traffic-logs query="" number_of_logs="100" direction="backward" source="" destination="" receive_time="" application="" to_port="" action="allow"
Human Readable Output
Query Traffic Logs
JobID Status 1858 Pending
pan-os-check-traffic-logs-status
Deprecated. Checks the query status of traffic logs.
Base Command
pan-os-check-traffic-logs-status
Input
| Argument Name | Description | Required |
|---|---|---|
| job_id | Job ID of the query. | Required |
Context Output
| Path | Type | Description |
|---|---|---|
| Panorama.TrafficLogs.JobID | number | Job ID of the traffic logs query. |
| Panorama.TrafficLogs.Status | string | Status of the traffic logs query. |
Command Example
!pan-os-check-traffic-logs-status job_id="1865"
Human Readable Output
Query Traffic Logs status
JobID Status 1858 Pending
pan-os-get-traffic-logs
Deprecated. Retrieves traffic log query data by job id.
Base Command
pan-os-get-traffic-logs
Input
| Argument Name | Description | Required |
|---|---|---|
| job_id | Job ID of the query. | Required |
Context Output
| Path | Type | Description |
|---|---|---|
| Panorama.TrafficLogs.JobID | number | Job ID of the traffic logs query. |
| Panorama.TrafficLogs.Status | string | Status of the traffic logs query. |
| Panorama.TrafficLogs.Logs.Action | string | Action of the traffic log. |
| Panorama.TrafficLogs.Logs.ActionSource | string | Action source of the traffic log. |
| Panorama.TrafficLogs.Logs.Application | string | Application of the traffic log. |
| Panorama.TrafficLogs.Logs.Bytes | string | The total log bytes. |
| Panorama.TrafficLogs.Logs.BytesReceived | string | The log bytes received. |
| Panorama.TrafficLogs.Logs.BytesSent | string | The log bytes sent. |
| Panorama.TrafficLogs.Logs.Category | string | Category of the traffic log. |
| Panorama.TrafficLogs.Logs.DeviceName | string | Device name of the traffic log. |
| Panorama.TrafficLogs.Logs.Destination | string | Destination of the traffic log. |
| Panorama.TrafficLogs.Logs.DestinationPort | string | Destination port of the traffic log. |
| Panorama.TrafficLogs.Logs.FromZone | string | From zone of the traffic log. |
| Panorama.TrafficLogs.Logs.Protocol | string | Protocol of the traffic log. |
| Panorama.TrafficLogs.Logs.ReceiveTime | string | Receive time of the traffic log. |
| Panorama.TrafficLogs.Logs.Rule | string | Rule of the traffic log. |
| Panorama.TrafficLogs.Logs.SessionEndReason | string | Session end reason of the traffic log. |
| Panorama.TrafficLogs.Logs.Source | string | Source of the traffic log. |
| Panorama.TrafficLogs.Logs.SourcePort | string | Source port of the traffic log. |
| Panorama.TrafficLogs.Logs.StartTime | string | Start time of the traffic log. |
| Panorama.TrafficLogs.Logs.ToZone | string | To zone of the traffic log. |
Command Example
!pan-os-get-traffic-logs job_id="1865"
pan-os-list-rules
Returns a list of predefined Security Rules. (When passing a query, all other arguments are overridden. Make sure the query includes all the filters you want).
Base Command
pan-os-list-rules
Input
| Argument Name | Description | Required |
|---|---|---|
| pre_post | The rules location. Mandatory for Panorama instances. Possible values are: pre-rulebase, post-rulebase. | Optional |
| device-group | The device group for which to return addresses (Panorama instances). | Optional |
| tag | The tag to filter the rules. | Optional |
| tags | A comma-separated list of tags by which to filter the rules. | Optional |
| target | Serial number of the firewall on which to run the command. Use only for a Panorama instance. | Optional |
| rulename | The name of the rule to retrieve. If not mentioned, will retrieve all the rules. | Optional |
| disabled | Whether to retrieve the disabled rules or not. If not mentioned, will retrieve all the rules. Possible values are: yes, no. | Optional |
| action | The action of the rules to retrieve. If not mentioned, will retrieve all the rules. Possible values are: allow, deny, drop. | Optional |
| query | Free query to retrieve rules. If not mentioned, will retrieve all the rules. When passing a query, all other arguments are overridden. | Optional |
Context Output
| Path | Type | Description | ||||
|---|---|---|---|---|---|---|
| Panorama.SecurityRule.Location | String | The location of the security rule. | ||||
| Panorama.SecurityRule.NegateDestination | String | Indicates whether the destination is negated in the security rule. | ||||
| Panorama.SecurityRule.Disabled | String | Indicates whether the security rule is disabled. | ||||
| Panorama.SecurityRule.ICMPUnreachable | String | Specifies the behavior for ICMP unreachable messages. | ||||
| Panorama.SecurityRule.Description | String | The description of the security rule. | ||||
| Panorama.SecurityRule.GroupTag | String | The group tag of the security rule. | ||||
| Panorama.SecurityRule.LogForwardingProfile | String | The log forwarding profile applied to the security rule. | ||||
| Panorama.SecurityRule.NegateSource | String | Indicates whether the source is negated in the security rule. | ||||
| Panorama.SecurityRule.SecurityProfileGroup | String | The security profile group assigned to the security rule. | ||||
| Panorama.SecurityRule.SecurityProfile | Unknown | The security profile settings applied to the security rule. | ||||
| Panorama.SecurityRule.SecurityProfile.url-filtering | String | The security profile setting for url-filtering in the security rule. | ||||
| Panorama.SecurityRule.SecurityProfile.data-filtering | String | The security profile setting for data-filtering in the security rule. | ||||
| Panorama.SecurityRule.SecurityProfile.file-blocking | String | The security profile setting for file-blocking in the security rule. | ||||
| Panorama.SecurityRule.SecurityProfile.virus | String | The security profile setting for viruses in the security rule. | ||||
| Panorama.SecurityRule.SecurityProfile.spyware | String | The security profile setting for spyware in the security rule. | ||||
| Panorama.SecurityRule.SecurityProfile.vulnerability | String | The security profile setting for vulnerability in the security rule. | ||||
| Panorama.SecurityRule.SecurityProfile.wildfire-analysis | String | The security profile setting for wildfire-analysis in the security rule. | Panorama.SecurityRule.Target.devices | String | The devices targeted by the security rule. | |
| Panorama.SecurityRule.Target.negate | String | Indicates whether the target is negated in the security rule. | ||||
| Panorama.SecurityRule.Name | String | The name of the security rule. | ||||
| Panorama.SecurityRule.From | String | The source zone of the security rule. | ||||
| Panorama.SecurityRule.DestinationDevice | String | The destination device of the security rule. | ||||
| Panorama.SecurityRule.Action | String | The action taken by the security rule. | ||||
| Panorama.SecurityRule.SourceDevice | String | The source device of the security rule. | ||||
| Panorama.SecurityRule.Tags | String | The tags associated with the security rule. | ||||
| Panorama.SecurityRule.SourceUser | String | The source user of the security rule. | ||||
| Panorama.SecurityRule.Application | String | The application used in the security rule. | ||||
| Panorama.SecurityRule.Service | String | The service used in the security rule. | ||||
| Panorama.SecurityRule.To | String | The destination zone of the security rule. | ||||
| Panorama.SecurityRule.Source | String | The source address of the security rule. | ||||
| Panorama.SecurityRule.CustomUrlCategory | String | The custom URL category targeted by the security rule. | ||||
| Panorama.SecurityRule.Destination | String | The destination address of the security rule. | ||||
| Panorama.SecurityRule.Options.LogAtSessionStart | String | Indicates whether the session start is logged. | ||||
| Panorama.SecurityRule.Options.LogForwarding | String | Indicates whether log forwarding is enabled for the security rule. | ||||
| Panorama.SecurityRule.Options.Schedule | String | The schedule applied to the security rule. | ||||
| Panorama.SecurityRule.Options.QoSMarking | String | The QoS marking applied to the security rule. | ||||
| Panorama.SecurityRule.Options.DisableServerResponseInspection | String | Specifies whether to disable server response inspection for the security rule. | ||||
| Panorama.SecurityRule.DeviceGroup | String | The device group of the security rule (Panorama instances only). | ||||
| Panorama.SecurityRule.Type | String | Represents the type of the security rule (e.g., pre-rule, post-rule, intra-zone, inter-zone). |
Command Example
!pan-os-list-rules pre_post=“pre-rulebase”
Context Example
{
"Panorama": {
"SecurityRule": [
{
"DeviceGroup": "TestDevice",
"Location": "TestDevice",
"NegateDestination": "",
"Disabled": "no",
"ICMPUnreachable": "",
"Description": "",
"GroupTag": "",
"LogForwardingProfile": "",
"NegateSource": "",
"SecurityProfileGroup": "TestGroup",
"SecurityProfile": {
"url-filtering": "",
"data-filtering": "",
"file-blocking": "",
"vulnerability": "",
"wildfire-analysis": "",
"spyware": "",
"virus": ""
},
"Target": {
"devices": "007051000185487",
"negate": "no"
},
"Name": "block rule",
"Type": "",
"From": [
"TestName",
"TestName2"
],
"DestinationDevice": "any",
"Action": "drop",
"SourceDevice": "any",
"Tags": [
"TestTag1",
"TestTag2",
"TestTag3"
],
"SourceUser": "any",
"Application": [
"cortex-xdr",
"jira",
"zoom"
],
"Service": "application-default",
"To": [
"TestName",
"TestName2"
],
"Source": [
"1.1.1.1",
"8.8.4.4",
"8.8.8.8"
],
"CustomUrlCategory": [
"abortion",
"adult",
"alcohol-and-tobacco",
"hacking"
],
"Destination": [
"1.1.1.1",
"8.8.8.8"
],
"Options": {
"LogAtSessionStart": "",
"LogForwarding": "",
"Schedule": "",
"QoSMarking": "",
"DisableServerResponseInspection": ""
}
},
{
"DeviceGroup": "TestDevice",
"Location": "TestDevice",
"NegateDestination": "",
"Disabled": "",
"ICMPUnreachable": "yes",
"Description": "bbbbbbbbbb",
"GroupTag": "TestGroupTag",
"LogForwardingProfile": "Log forwarding for SA",
"NegateSource": "",
"SecurityProfileGroup": "",
"SecurityProfile": {
"url-filtering": "default",
"spyware": "testing",
"virus": "default",
"data-filtering": "",
"file-blocking": "",
"vulnerability": "",
"wildfire-analysis": ""
},
"Target": {
"devices": [
"007051000185487",
"007051000188986"
],
"negate": "no"
},
"Name": "jl-test-1",
"Type": "intrazone",
"From": "internal",
"DestinationDevice": "bad nam",
"Action": "reset-server",
"SourceDevice": "good name",
"Tags": [
"APIiiiiii",
"test2shared"
],
"SourceUser": "me",
"Application": "8x8",
"Service": [
"new group",
"service-http",
"service-https"
],
"To": "internal",
"Source": "1.1.1.1",
"CustomUrlCategory": [
"alcohol-and-tobacco",
"auctions"
],
"Destination": "my_shared_address_object_test",
"Options": {
"LogAtSessionStart": "yes",
"LogForwarding": "Log forwarding for SA",
"Schedule": "test-schedule",
"QoSMarking": "ip-precedence",
"DisableServerResponseInspection": "yes"
}
}
]
}
}
Human Readable Output
Security Rules
| Name | Location | Tags | Type | Source Zone | Source Address | Source User | Source Device | Destination Zone | Destination Address | Destination Device | Application | Service | Url Category | Action | Profiles | Profile Group | Options | Target |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| block rule | TestDevice | TestTag1, TestTag2, TestTag3 |
TestName, TestName2 |
1.1.1.1, 8.8.4.4, 8.8.8.8 |
any | any | TestName, TestName2 |
1.1.1.1, 8.8.8.8 |
any | cortex-xdr, jira, zoom |
application-default | abortion, adult, alcohol-and-tobacco, hacking |
drop | url-filtering: data-filtering: file-blocking: virus: spyware: vulnerability: wildfire-analysis: |
TestGroup | LogAtSessionStart: LogForwarding: Schedule: QoSMarking: DisableServerResponseInspection: |
devices: 007051000185487 negate: no |
|
| jl-test-1 | TestDevice | APIiiiiii, test2shared |
intrazone | internal | 1.1.1.1 | me | good name | internal | my_shared_address_object_test | bad nam | 8x8 | new group, service-http, service-https |
alcohol-and-tobacco, auctions |
reset-server | url-filtering: default data-filtering: file-blocking: virus: default spyware: testing vulnerability: wildfire-analysis: |
LogAtSessionStart: yes LogForwarding: Log forwarding for SA Schedule: test-schedule QoSMarking: ip-precedence DisableServerResponseInspection: yes |
devices: 007051000185487, 007051000188986 negate: no |
pan-os-query-logs
The query logs in Panorama.
Base Command
pan-os-query-logs
Input
| Argument Name | Description | Required |
|---|---|---|
| log-type | The log type. Can be “threat”, “traffic”, “wildfire”, “url”, or “data”. Possible values are: threat, traffic, wildfire, url, data. | Required |
| query | The query string by which to match criteria for the logs. This is similar to the query provided in the web interface under the Monitor tab when viewing the logs. Do not use the query arguemnt in combination with the following arugments: time-generated, time-generated-after, addr-src, addr-dst, zone-src, zone-dst, action, port-dst, rule, url, filedigest. | Optional |
| time-generated | The time the log was generated from the timestamp and prior to it. For example “2019/08/11 01:10:44”, 3 days ago. |
Optional |
| time-generated-after | The time the log was generated from the timestamp and later then it. For example “2019/08/11 01:10:44”, 3 days ago. |
Optional |
| addr-src | The source address. | Optional |
| addr-dst | The destination address. | Optional |
| ip | The source or destination IP address. | Optional |
| zone-src | The source zone. | Optional |
| zone-dst | The destination source. | Optional |
| action | The rule action. | Optional |
| port-dst | The destination port. | Optional |
| rule | The rule name, for example “Allow all outbound”. | Optional |
| url | The URL, for example “safebrowsing.googleapis.com”. | Optional |
| filedigest | The file hash (for WildFire logs only). | Optional |
| number_of_logs | The maximum number of logs to retrieve. If empty, the default is 100. The maximum is 5,000. Default is 100. | Optional |
| polling | Whether to use polling. Possible values are: true, false. Default is false. | Optional |
| timeout | The timeout (in seconds) when polling. Default is 120. | Optional |
| interval_in_seconds | The interval (in seconds) when polling. Default is 10. | Optional |
| show-detail | Whether to show only after-change-preview, and before-change-preview, or get full data for it. The full data are under the fields after-change-detail, and before-change-detail. Possible values are: yes, no. Default is no. |
Optional |
Context Output
| Path | Type | Description |
| — | — | — |
| Panorama.Monitor.JobID | String | The job ID of the logs query. |
| Panorama.Monitor.Status | String | The status of the logs query. |
| Panorama.Monitor.Message | String | The message of the logs query. |
| Panorama.Monitor.Logs.Action | String | The action taken for the session. Can be “alert”, “allow”, “deny”, “drop”, “drop-all-packets”, “reset-client”, “reset-server”, “reset-both”, or “block-url”. |
| Panorama.Monitor.Logs.Application | String | The application associated with the session. |
| Panorama.Monitor.Logs.Category | String | The URL category of the URL subtype. For WildFire subtype, it is the verdict on the file, and can be either “malicious”, “phishing”, “grayware”, or “benign”. For other subtypes, the value is “any”. |
| Panorama.Monitor.Logs.DeviceName | String | The hostname of the firewall on which the session was logged. |
| Panorama.Monitor.Logs.DestinationAddress | String | The original session destination IP address. |
| Panorama.Monitor.Logs.DestinationUser | String | The username of the user to which the session was destined. |
| Panorama.Monitor.Logs.DestinationCountry | String | The destination country or internal region for private addresses. Maximum length is 32 bytes. |
| Panorama.Monitor.Logs.DestinationPort | String | The destination port utilized by the session. |
| Panorama.Monitor.Logs.FileDigest | String | Only for the WildFire subtype, all other types do not use this field. The filedigest string shows the binary hash of the file sent to be analyzed by the WildFire service. |
| Panorama.Monitor.Logs.FileName | String | File name or file type when the subtype is file.
File name when the subtype is virus.
File name when the subtype is wildfire-virus.
File name when the subtype is wildfire. |
| Panorama.Monitor.Logs.FileType | String | Only for the WildFire subtype, all other types do not use this field.
Specifies the type of file that the firewall forwarded for WildFire analysis. |
| Panorama.Monitor.Logs.FromZone | String | The zone from which the session was sourced. |
| Panorama.Monitor.Logs.URLOrFilename | String | The actual URL when the subtype is url.
The file name or file type when the subtype is file.
The file name when the subtype is virus.
The file name when the subtype is wildfire-virus.
The file name when the subtype is wildfire.
The URL or file name when the subtype is vulnerability (if applicable). |
| Panorama.Monitor.Logs.NATDestinationIP | String | The post-NAT destination IP address if destination NAT was performed. |
| Panorama.Monitor.Logs.NATDestinationPort | String | The post-NAT destination port. |
| Panorama.Monitor.Logs.NATSourceIP | String | The post-NAT source IP address if source NAT was performed. |
| Panorama.Monitor.Logs.NATSourcePort | String | The post-NAT source port. |
| Panorama.Monitor.Logs.PCAPid | String | The packet capture (pcap) ID is a 64 bit unsigned integral denoting
an ID to correlate threat pcap files with extended pcaps taken as a part of
that flow. All threat logs will contain either a pcap_id of 0 (no associated
pcap), or an ID referencing the extended pcap file. |
| Panorama.Monitor.Logs.IPProtocol | String | The IP protocol associated with the session. |
| Panorama.Monitor.Logs.Recipient | String | Only for the WildFire subtype, all other types do not use this field.
Specifies the name of the receiver of an email that WildFire determined to be malicious when analyzing an email link forwarded by the firewall. |
| Panorama.Monitor.Logs.Rule | String | The name of the rule that the session matched. |
| Panorama.Monitor.Logs.RuleID | String | The ID of the rule that the session matched. |
| Panorama.Monitor.Logs.ReceiveTime | String | The time the log was received at the management plane. |
| Panorama.Monitor.Logs.Sender | String | Only for the WildFire subtype; all other types do not use this field.
Specifies the name of the sender of an email that WildFire determined to be malicious when analyzing an email link forwarded by the firewall. |
| Panorama.Monitor.Logs.SessionID | String | An internal numerical identifier applied to each session. |
| Panorama.Monitor.Logs.DeviceSN | String | The serial number of the firewall on which the session was logged. |
| Panorama.Monitor.Logs.Severity | String | The severity associated with the threat. Can be “informational”, “low”,
“medium”, “high”, or “critical”. |
| Panorama.Monitor.Logs.SourceAddress | String | The original session source IP address. |
| Panorama.Monitor.Logs.SourceCountry | String | The source country or internal region for private addresses. Maximum
length is 32 bytes. |
| Panorama.Monitor.Logs.SourceUser | String | The username of the user who initiated the session. |
| Panorama.Monitor.Logs.SourcePort | String | The source port utilized by the session. |
| Panorama.Monitor.Logs.ThreatCategory | String | The threat categories used to classify different types of
threat signatures. |
| Panorama.Monitor.Logs.Name | String | The Palo Alto Networks identifier for the threat. A description
string followed by a 64-bit numerical identifier. |
| Panorama.Monitor.Logs.ID | String | The Palo Alto Networks ID for the threat. |
| Panorama.Monitor.Logs.ToZone | String | The zone to which the session was destined. |
| Panorama.Monitor.Logs.TimeGenerated | String | The time the log was generated on the data plane. |
| Panorama.Monitor.Logs.URLCategoryList | String | A list of the URL filtering categories the firewall used to
enforce the policy. |
| Panorama.Monitor.Logs.Bytes | String | The total log bytes. |
| Panorama.Monitor.Logs.BytesReceived | String | The log bytes received. |
| Panorama.Monitor.Logs.BytesSent | String | The log bytes sent. |
| Panorama.Monitor.Logs.Vsys | String | The VSYS on the firewall that generated the log. |
Command example with polling
!pan-os-query-logs log-type=traffic number_of_logs=1 polling=true show-detail=yes
Context example
{
"Panorama": {
"Monitor": {
"JobID": "1291",
"LogType": "traffic",
"Logs": {
"TimeGenerated": "2019/07/24 08:50:24",
"SourceAddress": "1.1.1.1",
"DestinationAddress": "2.3.4.5",
"Application": "web-browsing",
"Action": "deny",
"Rule": "any - any accept"
},
"Status": "Completed"
}
}
}
Human Readable Output
Fetching traffic logs for job ID 1291…
Query traffic Logs
TimeGenerated SourceAddress DestinationAddress Application Action Rule 2019/07/24 08:50:24 1.1.1.1 2.3.4.5 web-browsing deny any - any accept
Command example without polling
!pan-os-query-logs log-type=traffic number_of_logs=1
Context Example
{
"Panorama": {
"Monitor": {
"JobID": "1283",
"LogType": "traffic",
"Message": "query job enqueued with jobid 1283",
"Status": "Pending"
}
}
}
Human Readable Output
Query Logs
JobID Status 1283 Pending
pan-os-check-logs-status
Checks the status of a logs query.
Base Command
pan-os-check-logs-status
Input
| Argument Name | Description | Required |
|---|---|---|
| job_id | Job ID of the query. | Required |
Context Output
| Path | Type | Description |
|---|---|---|
| Panorama.Monitor.JobID | String | Job ID of the logs query. |
| Panorama.Monitor.Status | String | Status of the logs query. |
Command Example
!pan-os-check-logs-status job_id=657
Human Readable Output
Query Logs Status
JobID Status 657 Completed
pan-os-get-logs
Retrieves the data of a logs query.
Base Command
pan-os-get-logs
Input
| Argument Name | Description | Required |
|---|---|---|
| job_id | Job ID of the query. | Required |
| ignore_auto_extract | Whether to auto-enrich the War Room entry. If “true”, entry is not auto-enriched. If “false”, entry is auto-extracted. Default is “true”. | Optional |
Context Output
| Path | Type | Description |
|---|---|---|
| Panorama.Monitor.Logs.Action | String | Action taken for the session. Can be “alert”, “allow”, “deny”, “drop”, “drop-all-packets”, “reset-client”, “reset-server”, “reset-both”, or “block-url”. |
| Panorama.Monitor.Logs.Application | String | Application associated with the session. |
| Panorama.Monitor.Logs.Category | String | The URL category of the URL subtype. For WildFire subtype, it is the verdict on the file, and can be either “malicious”, “phishing”, “grayware”’, or “benign”. For other subtypes, the value is “any”. |
| Panorama.Monitor.Logs.DeviceName | String | The hostname of the firewall on which the session was logged. |
| Panorama.Monitor.Logs.DestinationAddress | String | Original session destination IP address. |
| Panorama.Monitor.Logs.DestinationUser | String | Username of the user to which the session was destined. |
| Panorama.Monitor.Logs.DestinationCountry | String | Destination country or internal region for private addresses. Maximum length is 32 bytes. |
| Panorama.Monitor.Logs.DestinationPort | String | Destination port utilized by the session. |
| Panorama.Monitor.Logs.FileDigest | String | Only for the WildFire subtype, all other types do not use this field. The file digest string shows the binary hash of the file sent to be analyzed by the WildFire service. |
| Panorama.Monitor.Logs.FileName | String | File name or file type when the subtype is file. File name when the subtype is virus. File name when the subtype is wildfire-virus. File name when the subtype is wildfire. |
| Panorama.Monitor.Logs.FileType | String | Only for the WildFire subtype, all other types do not use this field. Specifies the type of file that the firewall forwarded for WildFire analysis. |
| Panorama.Monitor.Logs.FromZone | String | The zone from which the session was sourced. |
| Panorama.Monitor.Logs.URLOrFilename | String | The actual URL when the subtype is url. File name or file type when the subtype is file. File name when the subtype is virus. File name when the subtype is wildfire-virus. File name when the subtype is wildfire. URL or file name when the subtype is vulnerability (if applicable). |
| Panorama.Monitor.Logs.NATDestinationIP | String | If destination NAT performed, the post-NAT destination IP address. |
| Panorama.Monitor.Logs.NATDestinationPort | String | Post-NAT destination port. |
| Panorama.Monitor.Logs.NATSourceIP | String | If source NAT performed, the post-NAT source IP address. |
| Panorama.Monitor.Logs.NATSourcePort | String | Post-NAT source port. |
| Panorama.Monitor.Logs.PCAPid | String | The packet capture (pcap) ID is a 64 bit unsigned integral denoting an ID to correlate threat pcap files with extended pcaps taken as a part of that flow. All threat logs will contain either a pcap_id of 0 (no associated pcap), or an ID referencing the extended pcap file. |
| Panorama.Monitor.Logs.IPProtocol | String | IP protocol associated with the session. |
| Panorama.Monitor.Logs.Recipient | String | Only for the WildFire subtype, all other types do not use this field. Specifies the name of the receiver of an email that WildFire determined to be malicious when analyzing an email link forwarded by the firewall. |
| Panorama.Monitor.Logs.Rule | String | Name of the rule that the session matched. |
| Panorama.Monitor.Logs.RuleID | String | ID of the rule that the session matched. |
| Panorama.Monitor.Logs.ReceiveTime | String | Time the log was received at the management plane. |
| Panorama.Monitor.Logs.Sender | String | Only for the WildFire subtype; all other types do not use this field. Specifies the name of the sender of an email that WildFire determined to be malicious when analyzing an email link forwarded by the firewall. |
| Panorama.Monitor.Logs.SessionID | String | An internal numerical identifier applied to each session. |
| Panorama.Monitor.Logs.DeviceSN | String | The serial number of the firewall on which the session was logged. |
| Panorama.Monitor.Logs.Severity | String | Severity associated with the threat. Can be “informational”, “low”, “medium”, “high”, or “critical”. |
| Panorama.Monitor.Logs.SourceAddress | String | Original session source IP address. |
| Panorama.Monitor.Logs.SourceCountry | String | Source country or internal region for private addresses. Maximum length is 32 bytes. |
| Panorama.Monitor.Logs.SourceUser | String | Username of the user who initiated the session. |
| Panorama.Monitor.Logs.SourcePort | String | Source port utilized by the session. |
| Panorama.Monitor.Logs.ThreatCategory | String | Describes threat categories used to classify different types of threat signatures. |
| Panorama.Monitor.Logs.Name | String | Palo Alto Networks identifier for the threat. It is a description string followed by a 64-bit numerical identifier. |
| Panorama.Monitor.Logs.ID | String | Palo Alto Networks ID for the threat. |
| Panorama.Monitor.Logs.ToZone | String | The zone to which the session was destined. |
| Panorama.Monitor.Logs.TimeGenerated | String | Time that the log was generated on the dataplane. |
| Panorama.Monitor.Logs.URLCategoryList | String | A list of the URL filtering categories that the firewall used to enforce the policy. |
| Panorama.Monitor.Logs.Bytes | String | Total log bytes. |
| Panorama.Monitor.Logs.BytesReceived | String | Log bytes received. |
| Panorama.Monitor.Logs.BytesSent | String | Log bytes sent. |
| Panorama.Monitor.Logs.Vsys | String | Vsys on the firewall that generated the log. |
Command Example
!pan-os-get-logs job_id=678
Human Readable Output
Query data Logs
TimeGenerated SourceAddress DestinationAddress Application Action Rule 2019/07/24 08:50:24 1.1.1.1 2.3.4.5 web-browsing deny any - any accept
pan-os-security-policy-match
Checks whether a session matches a specified security policy. This command is only available on Firewall instances.
Base Command
pan-os-security-policy-match
Input
| Argument Name | Description | Required |
|---|---|---|
| application | The application name. | Optional |
| category | The category name. | Optional |
| destination | The destination IP address. | Required |
| destination-port | The destination port. | Optional |
| from | The from zone. | Optional |
| to | The to zone. | Optional |
| protocol | The IP protocol value. | Required |
| source | The source IP address. | Required |
| source-user | The source user. | Optional |
| target | Target number of the firewall. Use only on a Panorama instance. | Optional |
Context Output
| Path | Type | Description |
|---|---|---|
| Panorama.SecurityPolicyMatch.Query | String | Query for the session to test. |
| Panorama.SecurityPolicyMatch.Rules.Name | String | The matching rule name. |
| Panorama.SecurityPolicyMatch.Rules.Action | String | The matching rule action. |
| Panorama.SecurityPolicyMatch.Rules.Category | String | The matching rule category. |
| Panorama.SecurityPolicyMatch.Rules.Destination | String | The matching rule destination. |
| Panorama.SecurityPolicyMatch.Rules.From | String | The matching rule from zone. |
| Panorama.SecurityPolicyMatch.Rules.Source | String | The matching rule source. |
| Panorama.SecurityPolicyMatch.Rules.To | String | The matching rule to zone. |
| Panorama.SecurityPolicyMatch.QueryFields.Application | String | The application name. |
| Panorama.SecurityPolicyMatch.QueryFields.Category | String | The category name. |
| Panorama.SecurityPolicyMatch.QueryFields.Destination | String | The destination IP address. |
| Panorama.SecurityPolicyMatch.QueryFields.DestinationPort | Number | The destination port. |
| Panorama.SecurityPolicyMatch.QueryFields.From | String | The from zone. |
| Panorama.SecurityPolicyMatch.QueryFields.To | String | The to zone. |
| Panorama.SecurityPolicyMatch.QueryFields.Protocol | String | The IP protocol value. |
| Panorama.SecurityPolicyMatch.QueryFields.Source | String | The destination IP address. |
| Panorama.SecurityPolicyMatch.QueryFields.SourceUser | String | The source user. |
Command Example
!pan-os-security-policy-match destination=1.2.3.4 protocol=1 source=2.3.4.5
Context Example
{
"Panorama": {
"SecurityPolicyMatch": {
"Query": "<test><security-policy-match><source>2.3.4.5</source><destination>1.2.3.4</destination><protocol>1</protocol></security-policy-match></test>",
"QueryFields": {
"Destination": "1.2.3.4",
"Protocol": "1",
"Source": "2.3.4.5"
},
"Rules": {
"Action": "allow",
"Category": "any",
"Destination": "any",
"From": "any",
"Name": "any - any accept",
"Source": "any",
"To": "any"
}
}
}
}
Human Readable Output
Matching Security Policies
Name Action From To Source Destination any - any accept allow any any any any
pan-os-list-static-routes
Lists the static routes of a virtual router.
Base Command
pan-os-list-static-routes
Input
| Argument Name | Description | Required |
|---|---|---|
| virtual_router | The name of the virtual router for which to list static routes. | Required |
| template | The template to use to run the command. Overrides the template parameter (Panorama instances). | Optional |
| show_uncommitted | Whether to show an uncommitted configuration. Default is “false” | Optional |
Context Output
| Path | Type | Description |
|---|---|---|
| Panorama.StaticRoutes.Name | String | The name of the static route. |
| Panorama.StaticRoutes.BFDProfile | String | The BFD profile of the static route. |
| Panorama.StaticRoutes.Destination | String | The destination of the static route. |
| Panorama.StaticRoutes.Metric | Number | The metric (port) of the static route. |
| Panorama.StaticRoutes.NextHop | String | The next hop of the static route. Can be an IP address, FQDN, or a virtual router. |
| Panorama.StaticRoutes.RouteTable | String | The route table of a static route. |
| Panorama.StaticRoutes.VirtualRouter | String | The virtual router to which the static router belongs. |
| Panorama.StaticRoutes.Template | String | The template in which the static route is defined (Panorama instances only). |
| Panorama.StaticRoutes.Uncommitted | Boolean | Whether the static route is committed. |
Command Example
!pan-os-list-static-routes virtual_router=virtual_router_test_DONT_DELETE
Context Example
{
"Panorama": {
"StaticRoutes": [
{
"BFDprofile": "None",
"Destination": "2.3.4.5/32",
"Metric": 14,
"Name": "static_route_ip",
"NextHop": "3.3.3.3",
"RouteTable": "Unicast",
"VirtualRouter": "virtual_router_test_DONT_DELETE"
},
{
"Destination": "1.1.1.1/32",
"Metric": 1012,
"Name": "test_maya",
"NextHop": "3.3.3.3",
"VirtualRouter": "virtual_router_test_DONT_DELETE"
}
]
}
}
Human Readable Output
Displaying all Static Routes for the Virtual Router: virtual_router_test_DONT_DELETE
Name Destination NextHop RouteTable Metric BFDprofile static_route_ip 2.3.4.5/32 3.3.3.3 Unicast 14 None test_maya 1.1.1.1/32 3.3.3.3 1012
pan-os-get-static-route
Returns the specified static route of a virtual router.
Base Command
pan-os-get-static-route
Input
| Argument Name | Description | Required |
|---|---|---|
| virtual_router | Name of the virtual router for which to display the static route. | Required |
| static_route | Name of the static route to display. | Required |
| template | The template for which to run the command. Overrides the template parameter (Panorama instances). | Optional |
Context Output
| Path | Type | Description |
|---|---|---|
| Panorama.StaticRoutes.Name | String | The name of the static route. |
| Panorama.StaticRoutes.BFDProfile | String | The BFD profile of the static route. |
| Panorama.StaticRoutes.Destination | String | The destination of the static route. |
| Panorama.StaticRoutes.Metric | Number | The metric (port) of the static route. |
| Panorama.StaticRoutes.NextHop | String | The next hop of the static route. Can be an IP address, FQDN, or a virtual router. |
| Panorama.StaticRoutes.RouteTable | String | The route table of the static route. |
| Panorama.StaticRoutes.VirtualRouter | String | The virtual router to which the static router belongs. |
| Panorama.StaticRoutes.Template | String | The template in which the static route is defined (Panorama instances only). |
Command Example
!pan-os-get-static-route static_route=static_route_ip virtual_router=virtual_router_test_DONT_DELETE
Context Example
{
"Panorama": {
"StaticRoutes": {
"BFDprofile": "None",
"Destination": "2.3.4.5/32",
"Metric": 14,
"Name": "static_route_ip",
"NextHop": "3.3.3.3",
"RouteTable": "Unicast",
"VirtualRouter": "virtual_router_test_DONT_DELETE"
}
}
}
Human Readable Output
Static route: static_route_ip
BFDprofile Destination Metric Name NextHop RouteTable VirtualRouter None 2.3.4.5/32 14 static_route_ip 3.3.3.3 Unicast virtual_router_test_DONT_DELETE
pan-os-add-static-route
Adds a static route.
Base Command
pan-os-add-static-route
Input
| Argument Name | Description | Required |
|---|---|---|
| virtual_router | Virtual Router to which the routes will be added. | Required |
| static_route | The name of the static route to add. The argument is limited to a maximum of 31 characters, is case-sensitive, and supports letters, numbers, spaces, hyphens, and underscores. | Required |
| destination | The IP address and network mask in Classless Inter-domain Routing (CIDR) notation: ip_address/mask. For example, 192.168.0.1/24 for IPv4 or 2001:db8::/32 for IPv6). | Required |
| nexthop_type | The type for the nexthop. Can be: “ip-address”, “next-vr”, “fqdn” or “discard”. | Required |
| nexthop_value | The next hop value. | Required |
| metric | The metric port for the static route (1-65535). | Optional |
| interface | The interface name in which to add the static route. | Optional |
| template | The template to use to run the command. Overrides the template parameter (Panorama instances). | Optional |
Context Output
| Path | Type | Description |
|---|---|---|
| Panorama.StaticRoutes.Name | String | The name of the static route. |
| Panorama.StaticRoutes.BFDProfile | String | The BFD profile of the static route. |
| Panorama.StaticRoutes.Destination | String | The destination of the static route. |
| Panorama.StaticRoutes.Metric | Number | The metric (port) of the static route. |
| Panorama.StaticRoutes.NextHop | String | The next hop of the static route. Can be an IP address, FQDN, or a virtual router. |
| Panorama.StaticRoutes.RouteTable | String | The route table of the static route. |
| Panorama.StaticRoutes.VirtualRouter | String | The virtual router to which the static router belongs. |
| Panorama.StaticRoutes.Template | String | The template in which the static route is defined (Panorama instances only). |
Command Example
!pan-os-add-static-route destination=2.3.4.5/32 nexthop_type="ip-address" nexthop_value=3.3.3.3 static_route=my_temp_route virtual_router=virtual_router_test_DONT_DELETE
Context Example
{
"Panorama": {
"StaticRoutes": {
"@code": "20",
"@status": "success",
"msg": "command succeeded"
}
}
}
Human Readable Output
New uncommitted static route my_temp_route configuration added.
pan-os-delete-static-route
Deletes a static route.
Base Command
pan-os-delete-static-route
Input
| Argument Name | Description | Required |
|---|---|---|
| route_name | The name of the static route to delete. | Required |
| virtual_router | The virtual router from which the routes will be deleted. | Required |
| template | The template for to use to run the command. Overrides the template parameter (Panorama instances). | Optional |
Context Output
| Path | Type | Description |
|---|---|---|
| Panorama.StaticRoutes.Name | String | The name of the static route. |
| Panorama.StaticRoutes.BFDProfile | String | The BFD profile of the static route. |
| Panorama.StaticRoutes.Destination | String | The destination of the static route. |
| Panorama.StaticRoutes.Metric | Number | The metric (port) of the static route. |
| Panorama.StaticRoutes.NextHop | String | The next hop of the static route. Can be an IP address, FQDN, or a virtual router. |
| Panorama.StaticRoutes.RouteTable | String | The route table of the static route. |
| Panorama.StaticRoutes.VirtualRouter | String | The virtual router to which the static router belongs. |
| Panorama.StaticRoutes.Template | String | The template in which the static route is defined (Panorama instances only). |
| Panorama.StaticRoutes.Deleted | Boolean | Whether the static route was deleted. |
Command Example
!pan-os-delete-static-route route_name=my_temp_route virtual_router=virtual_router_test_DONT_DELETE
Context Example
{
"Panorama": {
"StaticRoutes": {
"Deleted": true,
"Name": "my_temp_route"
}
}
}
Human Readable Output
The static route: my_temp_route was deleted. Changes are not committed.
pan-os-show-device-version
Show firewall device software version.
Base Command
pan-os-show-device-version
Input
| Argument Name | Description | Required |
|---|---|---|
| target | Serial number of the firewall on which to run the command. Use only for a Panorama instance. | Optional |
Context Output
| Path | Type | Description |
|---|---|---|
| Panorama.Device.Info.Devicename | String | Devicename of the PAN-OS. |
| Panorama.Device.Info.Model | String | Model of the PAN-OS. |
| Panorama.Device.Info.Serial | String | Serial number of the PAN-OS. |
| Panorama.Device.Info.Version | String | Version of the PAN-OS. |
Command Example
#### Context Example
```json
{
"Panorama": {
"Device": {
"Info": {
"Devicename": "PA-VM",
"Model": "PA-VM",
"Serial": "000000000000000",
"Version": "8.1.7"
}
}
}
}
Human Readable Output
Device Version
Devicename Model Serial Version PA-VM PA-VM 000000000000000 8.1.7
pan-os-download-latest-content-update
Downloads the latest app/threat dynamic update.
Base Command
pan-os-download-latest-content-update
Input
| Argument Name | Description | Required |
|---|---|---|
| target | Serial number of the firewall on which to run the command. Use only for a Panorama instance. | Optional |
| polling | When set to false, the function will not use polling and will immediately return the ID of the download job. Possible values are: true, false. | Optional |
| timeout_in_seconds | The polling timeout in seconds. When polling is enabled, the command will keep checking the download status until this timeout is reached. Default is 3600. | Optional |
| interval_in_seconds | The polling interval in seconds. Controls how often the download status is checked. Default is 30. | Optional |
Context Output
| Path | Type | Description |
|---|---|---|
| Panorama.Content.Download.JobID | String | The job ID of the app/threat download. |
| Panorama.Content.Download.Status | String | The app/threat download status. |
| Panorama.Content.Download.Details | String | The download job details. |
pan-os-content-update-download-status
Checks the download status of a content update.
Base Command
pan-os-content-update-download-status
Input
| Argument Name | Description | Required |
|---|---|---|
| target | Serial number of the firewall on which to run the command. Use only for a Panorama instance. | Optional |
| job_id | Job ID to check. | Required |
Context Output
| Path | Type | Description |
|---|---|---|
| Panorama.Content.Download.JobID | String | Job ID to monitor. |
| Panorama.Content.Download.Status | String | Download status. |
| Panorama.Content.Download.Details | String | Job ID details. |
Command Example
!pan-os-content-update-download-status job_id=678
Human Readable Output
Content download status
JobID Status Details 678 Completed download succeeded with warnings
pan-os-install-latest-content-update
Installs the latest app/threat dynamic update.
Base Command
pan-os-install-latest-content-update
Input
| Argument Name | Description | Required |
|---|---|---|
| target | Serial number of the firewall on which to run the command. Use only for a Panorama instance. | Optional |
| polling | When set to false, the function will not use polling and will immediately return the ID of the install job. Possible values are: true, false. | Optional |
| timeout_in_seconds | The polling timeout in seconds. When polling is enabled, the command will keep checking the install status until this timeout is reached. Default is 3600. | Optional |
| interval_in_seconds | The polling interval in seconds. Controls how often the install status is checked. Default is 30. | Optional |
Context Output
| Path | Type | Description |
|---|---|---|
| Panorama.Content.Install.JobID | String | The job ID of the installation. |
| Panorama.Content.Install.Status | String | The installation status. |
| Panorama.Content.Install.Details | String | The install job details. |
pan-os-content-update-install-status
Gets the installation status of the content update.
Base Command
pan-os-content-update-install-status
Input
| Argument Name | Description | Required |
|---|---|---|
| target | Serial number of the firewall on which to run the command. Use only for a Panorama instance. | Optional |
| job_id | Job ID of the content installation. | Required |
Context Output
| Path | Type | Description |
|---|---|---|
| Panorama.Content.Install.JobID | String | Job ID of the content installation. |
| Panorama.Content.Install.Status | String | Content installation status. |
| Panorama.Content.Install.Details | String | Content installation status details. |
Command Example
!pan-os-content-update-install-status job_id=878
Human Readable Output
Content install status
JobID Status Details 878 Completed installation succeeded with warnings
pan-os-check-latest-panos-software
Checks the PAN-OS software version from the repository.
Base Command
pan-os-check-latest-panos-software
Input
| Argument Name | Description | Required |
|---|---|---|
| target | Serial number of the firewall on which to run the command. Use only for a Panorama instance. | Optional |
Context Output
| Path | Type | Description |
|---|---|---|
| Panorama.LatestVersions | unknown | Latest software versions. |
Command Example
### pan-os-download-panos-version
***
Downloads the target PAN-OS software version to install on the target device.
#### Base Command
`pan-os-download-panos-version`
#### Input
| **Argument Name** | **Description** | **Required** |
| --- | --- | --- |
| target | Serial number of the firewall on which to run the command. Use only for a Panorama instance. | Optional |
| target_version | The target version number to install. | Required |
#### Context Output
| **Path** | **Type** | **Description** |
| --- | --- | --- |
| Panorama.PANOS.Download.JobID | Number | Job ID of the PAN-OS download. |
| Panorama.PANOS.Download.Status | String | Status of the PAN-OS download. |
#### Command Example
```!pan-os-download-panos-version target_version=1```
#### Human Readable Output
>### Result
>
>|JobID|Status|
>|---|---|
>| 111 | Pending |
### pan-os-download-panos-status
***
Gets the download status of the target PAN-OS software.
#### Base Command
`pan-os-download-panos-status`
#### Input
| **Argument Name** | **Description** | **Required** |
| --- | --- | --- |
| target | Serial number of the firewall on which to run the command. Use only for a Panorama instance. | Optional |
| job_id | Job ID to check. | Required |
#### Context Output
| **Path** | **Type** | **Description** |
| --- | --- | --- |
| Panorama.PANOS.Download.JobID | String | Job ID of the PAN-OS download. |
| Panorama.PANOS.Download.Status | String | PAN-OS download status. |
| Panorama.PANOS.Download.Details | String | PAN-OS download details. |
#### Command Example
```!pan-os-download-panos-status job_id=999```
#### Human Readable Output
>### PAN-OS download status
>
>|JobID|Status|Details|
>|---|---|---|
>| 999 | Completed | download succeeded with warnings |
### pan-os-install-panos-version
***
Installs the target PAN-OS version on the specified target device.
#### Base Command
`pan-os-install-panos-version`
#### Input
| **Argument Name** | **Description** | **Required** |
| --- |---| --- |
| target | Serial number of the firewall on which to run the command. Use only for a Panorama instance. | Optional |
| target_version | Target PAN-OS version to install. | Required |
#### Context Output
| **Path** | **Type** | **Description** |
| --- | --- | --- |
| Panorama.PANOS.Install.JobID | string | Job ID from the PAN-OS installation. |
| Panorama.PANOS.Install.Status | String | Status of the PAN-OS installation. |
#### Command Example
```!pan-os-install-panos-version target_version=1```
#### Human Readable Output
>### PAN-OS Installation
>
>|JobID|Status|
>|---|---|
>| 111 | Pending |
### pan-os-install-panos-status
***
Gets the installation status of the PAN-OS software.
#### Base Command
`pan-os-install-panos-status`
#### Input
| **Argument Name** | **Description** | **Required** |
| --- | --- | --- |
| target | Serial number of the firewall on which to run the command. Use only for a Panorama instance. | Optional |
| job_id | Job ID to check. | Required |
#### Context Output
| **Path** | **Type** | **Description** |
| --- | --- | --- |
| Panorama.PANOS.Install.JobID | Number | Job ID of the PAN-OS installation. |
| Panorama.PANOS.Install.Status | String | Status of the PAN-OS installation. |
| Panorama.PANOS.Install.Details | String | PAN-OS installation details. |
#### Command Example
```!pan-os-install-panos-status job_id=878```
#### Human Readable Output
>### PAN-OS installation status
>
>|JobID|Status|Details|
>|---|---|---|
>| 878 | Completed | installation succeeded with warnings |
### pan-os-device-reboot
***
Reboots the Firewall device.
#### Base Command
`pan-os-device-reboot`
#### Input
| **Argument Name** | **Description** | **Required** |
| --- | --- | --- |
| target | Serial number of the firewall on which to run the command. Use only for a Panorama instance. | Optional |
#### Context Output
There is no context output for this command.
#### Command Example
```!pan-os-device-reboot```
### pan-os-show-location-ip
***
Gets location information for an IP address.
#### Base Command
`pan-os-show-location-ip`
#### Input
| **Argument Name** | **Description** | **Required** |
| --- | --- | --- |
| ip_address | The IP address from which to return information. | Required |
#### Context Output
| **Path** | **Type** | **Description** |
| --- | --- | --- |
| Panorama.Location.IP.country_code | String | The IP address location country code. |
| Panorama.Location.IP.country_name | String | The IP addres location country name. |
| Panorama.Location.IP.ip_address | String | The IP address. |
| Panorama.Location.IP.Status | String | Whether the IP address was found. |
#### Command Example
```!pan-os-show-location-ip ip_address=8.8.8.8```
#### Context Example
```json
{
"Panorama": {
"Location": {
"IP": {
"country_code": "US",
"country_name": "United States",
"ip_address": "8.8.8.8",
"status": "Found"
}
}
}
}
Human Readable Output
IP 8.8.8.8 location
ip_address country_name country_code 8.8.8.8 United States US
pan-os-get-licenses
Gets information about available PAN-OS licenses and their statuses.
Base Command
pan-os-get-licenses
Input
There are no input arguments for this command.
Context Output
| Path | Type | Description |
|---|---|---|
| Panorama.License.Authcode | String | The authentication code of the license. |
| Panorama.License.Base-license-name | String | The base license name. |
| Panorama.License.Description | String | The description of the license. |
| Panorama.License.Expired | String | Whether the license has expired. |
| Panorama.License.Expires | String | When the license will expire. |
| Panorama.License.Feature | String | The feature of the license. |
| Panorama.License.Issued | String | When the license was issued. |
| Panorama.License.Serial | String | The serial number of the license. |
Command Example
#### Human Readable Output
>|Authcode|Description|Feature|Serial|Expired|Expires|Issued|
>|---|---|---|---|---|---|---|
>| I9805928 | NFR Support | NFR Support | 007DEMISTO1t | no | Never | November 25, 2019 |
### pan-os-get-security-profiles
***
Gets information for the specified security profile.
#### Base Command
`pan-os-get-security-profiles`
#### Input
| **Argument Name** | **Description** | **Required** |
| --- | --- | --- |
| security_profile | The security profile for which to get information. Possible values are: data-filtering, file-blocking, spyware, url-filtering, virus, vulnerability, wildfire-analysis. | Optional |
| device-group | The device group for which to return security profiles. | Optional |
#### Context Output
| **Path** | **Type** | **Description** |
| --- | --- | --- |
| Panorama.Spyware.Name | String | The profile name. |
| Panorama.Spyware.Rules.Action | String | The rule action. |
| Panorama.Spyware.Rules.Category | String | The category for which to apply the rule. |
| Panorama.Spyware.Rules.Name | String | The rule name. |
| Panorama.Spyware.Rules.Packet-capture | String | Whether packet capture is enabled. |
| Panorama.Spyware.Rules.Severity | String | The rule severity. |
| Panorama.Spyware.Rules.Threat-name | String | The threat name to apply for the rule. |
| Panorama.URLFilter.Name | String | The profile name. |
| Panorama.URLFilter.Rules.Category.Action | String | The rule action to apply to the category. |
| Panorama.URLFilter.Rules.Category.Name | String | The category name. |
| Panorama.WildFire.Name | String | The WildFire profile name. |
| Panorama.WildFire.Rules.Analysis | String | The rule analysis. |
| Panorama.WildFire.Rules.Application | String | The application to apply for the rule. |
| Panorama.WildFire.Rules.File-type | String | The file type to apply for the rule. |
| Panorama.WildFire.Rules.Name | String | The rule name. |
| Panorama.Vulnerability.Name | String | The vulnerability profile name. |
| Panorama.Vulnerability.Rules.Vendor-id | String | The vendor ID to apply for the rule. |
| Panorama.Vulnerability.Rules.Packet-capture | String | Whether packet capture is enabled. |
| Panorama.Vulnerability.Rules.Host | String | The rule host. |
| Panorama.Vulnerability.Rules.Name | String | The rule name. |
| Panorama.Vulnerability.Rules.Category | String | The category to apply for the rule. |
| Panorama.Vulnerability.Rules.CVE | String | The CVE to apply for the rule. |
| Panorama.Vulnerability.Rules.Action | String | The rule action. |
| Panorama.Vulnerability.Rules.Severity | String | The rule severity. |
| Panorama.Vulnerability.Rules.Threat-name | String | The threat to apply for the rule. |
| Panorama.Antivirus.Name | String | The antivirus profile name. |
| Panorama.Antivirus.Rules.Action | String | The rule action. |
| Panorama.Antivirus.Rules.Name | String | The rule name. |
| Panorama.Antivirus.Rules.WildFire-action | String | The WildFire action. |
| Panorama.FileBlocking.Name | String | The file blocking profile name. |
| Panorama.FileBlocking.Rules.Action | String | The rule action. |
| Panorama.FileBlocking.Rules.Application | String | The application to apply for the rule. |
| Panorama.FileBlocking.Rules.File-type | String | The file type to apply for the rule. |
| Panorama.FileBlocking.Rules.Name | String | The rule name. |
| Panorama.DataFiltering.Name | String | The data filtering profile name. |
| Panorama.DataFiltering.Rules.Alert-threshold | String | The alert threshold. |
| Panorama.DataFiltering.Rules.Application | String | The application to apply for the rule. |
| Panorama.DataFiltering.Rules.Block-threshold | String | The block threshold. |
| Panorama.DataFiltering.Rules.Data-object | String | The data object. |
| Panorama.DataFiltering.Rules.Direction | String | The rule direction. |
| Panorama.DataFiltering.Rules.File-type | String | The file type to apply for the rule. |
| Panorama.DataFiltering.Rules.Log-severity | String | The log severity. |
| Panorama.DataFiltering.Rules.Name | String | The rule name. |
#### Command Example
```!pan-os-get-security-profiles security_profile=spyware```
#### Human Readable Output
>|Name|Rules|
>|---|---|
>| best-practice | {'Name': 'simple-critical', 'Action': {'reset-both': None}, 'Category': 'any', 'Severity': 'critical', 'Threat-name': 'any', 'Packet-capture': 'disable'},<br/>{'Name': 'simple-high', 'Action': {'reset-both': None}, 'Category': 'any', 'Severity': 'high', 'Threat-name': 'any', 'Packet-capture': 'disable'},<br/>{'Name': 'simple-medium', 'Action': {'reset-both': None}, 'Category': 'any', 'Severity': 'medium', 'Threat-name': 'any', 'Packet-capture': 'disable'},<br/>{'Name': 'simple-informational', 'Action': {'default': None}, 'Category': 'any', 'Severity': 'informational', 'Threat-name': 'any', 'Packet-capture': 'disable'},<br/>{'Name': 'simple-low', 'Action': {'default': None}, 'Category': 'any', 'Severity': 'low', 'Threat-name': 'any', 'Packet-capture': 'disable'} |
### pan-os-apply-security-profile
***
Apply a security profile to specific rules or rules with a specific tag.
#### Base Command
`pan-os-apply-security-profile`
#### Input
| **Argument Name** | **Description** | **Required** |
|-------------------| --- | --- |
| profile_type | Security profile type. Can be 'data-filtering', 'file-blocking', 'spyware', 'url-filtering', 'virus, 'vulnerability', or wildfire-analysis.' | Required |
| rule_name | The rule name to apply. | Required |
| profile_name | The profile name to apply to the rule. | Required |
| pre_post | The location of the rules. Can be 'pre-rulebase' or 'post-rulebase'. Mandatory for Panorama instances. | Optional |
| device-group | The device group for which to apply security profiles. | Optional |
#### Context Output
There is no context output for this command.
#### Command Example
```!pan-os-apply-security-profile profile_name=test profile_type=spyware rule_name=rule1 pre_post="pre-rulebase"```
#### Human Readable Output
>
>The profile spyware = test has been applied to the rule rule1
### pan-os-remove-security-profile
***
Removes a security profile to specific rules or rules with a specific tag.
#### Base Command
`pan-os-remove-security-profile`
#### Input
| **Argument Name** | **Description** | **Required** |
| --- | --- | --- |
| profile_type | The security profile type. Possible values are: data-filtering, file-blocking, spyware, url-filtering, virus, vulnerability, wildfire-analysis. | Required |
| rule_name | The rule name to apply. | Required |
| pre_post | The location of the rules. Mandatory for Panorama instances. Possible values are: pre-rulebase, post-rulebase. | Optional |
| device-group | The device group for which to apply security profiles. | Optional |
#### Human Readable Output
>
>The profile test has been removed from the rule rule1
### pan-os-get-ssl-decryption-rules
***
Get SSL decryption rules.
#### Base Command
`pan-os-get-ssl-decryption-rules`
#### Input
| **Argument Name** | **Description** | **Required** |
| --- | --- | --- |
| pre_post | The location of the rules. Can be 'pre-rulebase' or 'post-rulebase'. Mandatory for Panorama instances. | Optional |
#### Context Output
| **Path** | **Type** | **Description** |
| --- | --- | --- |
| Panorama.SSLRule.From | String | The SSL rule from the source. |
| Panorama.SSLRule.Name | String | The name of the SSL rule. |
| Panorama.SSLRule.Destination | String | The destination of the SSL rule. |
| Panorama.SSLRule.Target | String | The target of the SSL rule. |
| Panorama.SSLRule.Service | String | The SSL rule service. |
| Panorama.SSLRule.Action | String | The SSL rule action. |
| Panorama.SSLRule.Type | String | The SSL rule type. |
| Panorama.SSLRule.Source | String | The source of the SSL rule. |
| Panorama.SSLRule.To | String | The SSL rule to destination. |
| Panorama.SSLRule.UUID | String | The SSL rule UUID. |
| Panorama.SSLRule.Description | String | The SSL rule description. |
| Panorama.SSLRule.Source-user | String | The SSL rule source user. |
| Panorama.SSLRule.Category | String | The SSL rule category. |
#### Command Example
```!pan-os-get-ssl-decryption-rules pre_post="pre-rulebase"```
#### Human Readable Output
>|Name|UUID|Target|Service|Category|Type|From|To|Source|Destenation|Action|Source-user|
>|---|---|---|---|---|---|---|---|---|---|---|---|
>| test | some_uuid | negate: no | any | member: any | ssl-forward-proxy: null | any | any | any | any | no-decrypt | any |
### pan-os-get-wildfire-configuration
***
Retrieves the Wildfire configuration.
#### Base Command
`pan-os-get-wildfire-configuration`
#### Input
| **Argument Name** | **Description** | **Required** |
| --- | --- | --- |
| template | The template name. | Required |
#### Context Output
| **Path** | **Type** | **Description** |
| --- | --- | --- |
| Panorama.WildFire.Name | String | The file type. |
| Panorama.WildFire.Size-limit | String | The file size limit. |
| Panorama.WildFire.recurring | String | The schedule that is recurring. |
#### Command Example
```!pan-os-get-wildfire-configuration template=WildFire```
>### WildFire Configuration
>
> Report Grayware File: yes
>
>|Name|Size-limit|
>|---|---|
>| pe | 10 |
>| apk | 30 |
>### The updated schedule for Wildfire
>
>|recurring|
>|---|
>| every-min: {"action": "download-and-install"} |
### pan-os-url-filtering-block-default-categories
***
Set default categories to block in the URL filtering profile.
#### Base Command
`pan-os-url-filtering-block-default-categories`
#### Input
| **Argument Name** | **Description** | **Required** |
| --- | --- | --- |
| profile_name | The url-filtering profile name. Get the name by running the get-security-profiles command. | Required |
#### Context Output
There is no context output for this command.
#### Command Example
```!pan-os-url-filtering-block-default-categories profile_name=test```
#### Human Readable Output
>The default categories to block has been set successfully to test
### pan-os-get-anti-spyware-best-practice
***
Get anti-spyware best practices.
#### Base Command
`pan-os-get-anti-spyware-best-practice`
#### Input
There are no input arguments for this command.
#### Context Output
| **Path** | **Type** | **Description** |
| --- | --- | --- |
| Panorama.Spyware.BotentDomain.Name | String | The botnet domain name. |
| Panorama.Spyware.BotentDomain.Action | String | The botnet domain action. |
| Panorama.Spyware.BotentDomain.Packet-capture | String | Whether packet capture is enabled. |
| Panorama.Spyware.BotentDomain.Sinkhole.ipv4-address | String | The botnet domain IPv4 address. |
| Panorama.Spyware.BotentDomain.Sinkhole.ipv6-address | String | The Botnet domain IPv6 address. |
| Panorama.Spyware.Rule.Category | String | The rule category. |
| Panorama.Spyware.Rule.Action | String | The rule action. |
| Panorama.Spyware.Rule.Name | String | The rule name. |
| Panorama.Spyware.Rule.Severity | String | The rule severity. |
| Panorama.Spyware.Rule.Threat-name | String | The rule threat name. |
| Panorama.Spyware.BotentDomain.Max_version | String | The botnet domain max version. |
#### Command Example
```!pan-os-get-anti-spyware-best-practice```
#### Human Readable Output
>### Anti Spyware Botnet-Domains Best Practice
>
>|Name|Action|Packet-capture|ipv4-address|ipv6-address|
>|---|---|---|---|---|
>| default-paloalto-dns | sinkhole: null | disable | | |
>| default-paloalto-cloud | allow: null | disable | | |
>| | | | pan-sinkhole-default-ip | ::1 |
>### Anti Spyware Best Practice Rules
>
>|Name|Severity|Action|Category|Threat-name|
>|---|---|---|---|---|
>| simple-critical | critical | reset-both: null | any | any |
>| simple-high | high | reset-both: null | any | any |
### pan-os-get-file-blocking-best-practice
***
Get file-blocking best practices.
#### Base Command
`pan-os-get-file-blocking-best-practice`
#### Input
There are no input arguments for this command.
#### Context Output
| **Path** | **Type** | **Description** |
| --- | --- | --- |
| Panorama.FileBlocking.Rule.Action | String | The rule action. |
| Panorama.FileBlocking.Rule.Application | String | The rule application. |
| Panorama.FileBlocking.Rule.File-type | String | The rule file type. |
| Panorama.FileBlocking.Rule.Name | String | The rule name. |
#### Command Example
```!pan-os-get-file-blocking-best-practice```
#### Human Readable Output
>### File Blocking Profile Best Practice
>
>|Name|Action|File-type|Aplication|
>|---|---|---|---|
>| Block all risky file types | block | 7z,<br/>bat,<br/>cab,<br/>chm,<br/>class,<br/>cpl | any |
>| Block encrypted files | block | encrypted-rar,<br/>encrypted-zip| any |
### pan-os-get-antivirus-best-practice
***
Get anti-virus best practices.
#### Base Command
`pan-os-get-antivirus-best-practice`
#### Input
There are no input arguments for this command.
#### Context Output
| **Path** | **Type** | **Description** |
| --- | --- | --- |
| Panorama.Antivirus.Decoder.Action | String | The rule action. |
| Panorama.Antivirus.Decoder.Name | String | The rule name. |
| Panorama.Antivirus.Decoder.WildFire-action | String | The WildFire action. |
#### Command Example
```!pan-os-get-antivirus-best-practice```
#### Human Readable Output
>### Antivirus Best Practice Profile
>
>|Name|Action|WildFire-action|
>|---|---|---|
>| http | default | default|
>| smtp default | default |
### pan-os-get-vulnerability-protection-best-practice
***
Get vulnerability-protection best practices.
#### Base Command
`pan-os-get-vulnerability-protection-best-practice`
#### Input
There are no input arguments for this command.
#### Context Output
| **Path** | **Type** | **Description** |
| --- | --- | --- |
| Panorama.Vulnerability.Rule.Action | String | The rule action. |
| Panorama.Vulnerability.Rule.CVE | String | The rule CVE. |
| Panorama.Vulnerability.Rule.Category | String | The rule category. |
| Panorama.Vulnerability.Rule.Host | String | The rule host. |
| Panorama.Vulnerability.Rule.Name | String | The rule name. |
| Panorama.Vulnerability.Rule.Severity | String | The rule severity. |
| Panorama.Vulnerability.Rule.Threat-name | String | The threat name. |
| Panorama.Vulnerability.Rule.Vendor-id | String | The vendor ID. |
#### Command Example
```!pan-os-get-vulnerability-protection-best-practice```
#### Human Readable Output
>### vulnerability Protection Best Practice Profile
>
>|Name|Action|Host|Severity|Category|Threat-name|CVE|Vendor-id|
>|---|---|---|---|---|---|---|---|
>| simple-client-critical | reset-both: null | client | critical | any | any | any | any |
>| simple-client-high | reset-both: null | client | high | any | any | any | any |
### pan-os-get-wildfire-best-practice
***
View WildFire best practices.
#### Base Command
`pan-os-get-wildfire-best-practice`
#### Input
There are no input arguments for this command.
#### Context Output
| **Path** | **Type** | **Description** |
| --- | --- | --- |
| Panorama.WildFire.Analysis | String | The WildFire analysis. |
| Panorama.WildFire.Application | String | The WildFire application. |
| Panorama.WildFire.File.File-size | String | The recommended file size. |
| Panorama.WildFire.File.Name | String | The file name. |
| Panorama.WildFire.File-type | String | The WildFire profile file type. |
| Panorama.WildFire.Name | String | The WildFire profile name. |
| Panorama.WildFire.SSLDecrypt | String | The SSL decrypt content. |
| Panorama.WildFire.Schedule.Action | String | The WildFire schedule action. |
| Panorama.WildFire.Schedule.Recurring | String | The WildFire schedule recurring. |
#### Command Example
```!pan-os-get-wildfire-best-practice```
#### Human Readable Output
>### WildFire Best Practice Profile
>
>|Name|Analysis|Aplication|File-type|
>|---|---|---|---|
>| default | public-cloud | any | any |
>### Wildfire Best Practice Schedule
>
>|Action|Recurring|
>|---|---|
>| download-and-install | every-minute |
>### Wildfire SSL Decrypt Settings
>
>|allow-forward-decrypted-content|
>|---|
>| yes |
>### Wildfire System Settings
>
>report-grayware-file: yes
>
>|Name|File-size|
>|---|---|
>| pe | 10 |
>| apk | 30 |
### pan-os-get-url-filtering-best-practice
***
View URL Filtering best practices.
#### Base Command
`pan-os-get-url-filtering-best-practice`
#### Input
There are no input arguments for this command.
#### Context Output
| **Path** | **Type** | **Description** |
| --- | --- | --- |
| Panorama.URLFilter.Category.Action | String | The action to perform on the category. |
| Panorama.URLFilter.Category.Name | String | The category name. |
| Panorama.URLFilter.DeviceGroup | String | The device group name. |
| Panorama.URLFilter.Name | String | The Profile name. |
| Panorama.URLFilter.Header.log-container-page-only | String | The log container page only. |
| Panorama.URLFilter.Header.log-http-hdr-referer | String | The log HTTP header referer. |
| Panorama.URLFilter.Header.log-http-hdr-user | String | The log HTTP header user. |
| Panorama.URLFilter.Header.log-http-hdr-xff | String | The log HTTP header xff. |
#### Command Example
```!pan-os-get-url-filtering-best-practice```
#### Human Readable Output
>### URL Filtering Best Practice Profile Categories
>
>|Category|DeviceGroup|Name|
>|---|---|---|
>| {'Name': 'abortion', 'Action': 'alert'},<br/>{'Name': 'abused-drugs', 'Action': 'alert'} | Demisto sales lab | best-practice |
>### Best Practice Headers
>
>|log-container-page-only|log-http-hdr-referer|log-http-hdr-user|log-http-hdr-xff|
>|---|---|---|---|
>| yes | yes | yes | yes |
### pan-os-enforce-wildfire-best-practice
***
Enforces wildfire best practices to upload files to the maximum size, forwards all file types, and updates the schedule.
#### Base Command
`pan-os-enforce-wildfire-best-practice`
#### Input
| **Argument Name** | **Description** | **Required** |
| --- | --- | --- |
| template | The template name. | Required |
#### Context Output
There is no context output for this command.
#### Command Example
```!pan-os-enforce-wildfire-best-practice template=WildFire```
#### Human Readable Output
>The schedule was updated according to the best practice. Recurring every minute with the action of "download and install" The file upload for all file types is set to the maximum size.
### pan-os-create-antivirus-best-practice-profile
***
Creates an antivirus best practice profile.
#### Base Command
`pan-os-create-antivirus-best-practice-profile`
#### Input
| **Argument Name** | **Description** | **Required** |
| --- | --- | --- |
| profile_name | The name of the profile to create. | Required |
#### Context Output
There is no context output for this command.
#### Command Example
```!pan-os-create-antivirus-best-practice-profile profile_name=test```
#### Human Readable Output
>The profile test was created successfully.
### pan-os-create-anti-spyware-best-practice-profile
***
Creates an Anti-Spyware best practice profile.
#### Base Command
`pan-os-create-anti-spyware-best-practice-profile`
#### Input
| **Argument Name** | **Description** | **Required** |
| --- | --- | --- |
| profile_name | The profile name to create. | Required |
#### Context Output
There is no context output for this command.
#### Command Example
```!pan-os-create-anti-spyware-best-practice-profile profile_name=test```
#### Human Readable Output
>The profile test was created successfully.
### pan-os-create-vulnerability-best-practice-profile
***
Creates a vulnerability protection best practice profile.
#### Base Command
`pan-os-create-vulnerability-best-practice-profile`
#### Input
| **Argument Name** | **Description** | **Required** |
| --- | --- | --- |
| profile_name | The profile name. | Required |
#### Context Output
There is no context output for this command.
#### Command Example
```!pan-os-create-vulnerability-best-practice-profile profile_name=test```
#### Human Readable Output
>The profile test was created successfully.
### pan-os-create-url-filtering-best-practice-profile
***
Creates a URL filtering best practice profile.
#### Base Command
`pan-os-create-url-filtering-best-practice-profile`
#### Input
| **Argument Name** | **Description** | **Required** |
| --- | --- | --- |
| profile_name | The profile name. | Required |
#### Context Output
There is no context output for this command.
#### Command Example
```!pan-os-create-url-filtering-best-practice-profile profile_name=test```
#### Human Readable Output
>The profile test was created successfully.
### pan-os-create-file-blocking-best-practice-profile
***
Creates a file blocking best practice profile.
#### Base Command
`pan-os-create-file-blocking-best-practice-profile`
#### Input
| **Argument Name** | **Description** | **Required** |
| --- | --- | --- |
| profile_name | The name of the profile. | Required |
#### Context Output
There is no context output for this command.
#### Command Example
```!pan-os-create-file-blocking-best-practice-profile profile_name=test```
#### Human Readable Output
>The profile test was created successfully.
### pan-os-create-wildfire-best-practice-profile
***
Creates a WildFire analysis best practice profile.
#### Base Command
`pan-os-create-wildfire-best-practice-profile`
#### Input
| **Argument Name** | **Description** | **Required** |
| --- | --- | --- |
| profile_name | The name of the profile. | Required |
#### Context Output
There is no context output for this command.
#### Command Example
```!pan-os-create-wildfire-best-practice-profile profile_name=test```
#### Human Readable Output
>The profile test was created successfully.
### pan-os-show-user-id-interfaces-config
***
Shows the user ID interface configuration.
#### Base Command
`pan-os-show-user-id-interfaces-config`
#### Input
| **Argument Name** | **Description** | **Required** |
| --- | --- | --- |
| template | The template to use when running the command. Overrides the template parameter (Panorama instances). If not given, will use the integration parameter. | Optional |
| template_stack | The template stack to use when running the command. | Optional |
| vsys | The name of the virtual system to be configured. Will use the configured VSYS parameter if exists. If given a value, will override the VSYS parameter. If neither the VSYS parameter and this argument are entered, will default to 'vsys1'. . | Optional |
#### Context Output
| **Path** | **Type** | **Description** |
| --- | --- | --- |
| Panorama.UserInterfaces.Name | String | The name of the user interface. |
| Panorama.UserInterfaces.Zone | String | The zone to which the interface is connected |
| Panorama.UserInterfaces.EnableUserIdentification | String | Whether user identification is enabled. |
#### Command Example
```!pan-os-show-user-id-interfaces-config```
#### Context Example
```json
{
"Panorama": {
"UserInterfaces": {
"EnableUserIdentification": "no",
"Name": "ethernet1/1",
"Zone": "test_zone"
}
}
}
Human Readable Output
User Interface Configuration
Name Zone EnableUserIdentification ethernet1/1 test_zone no
pan-os-show-zones-config
Shows the zones configuration.
Base Command
pan-os-show-zones-config
Input
| Argument Name | Description | Required |
|---|---|---|
| template | The template to use when running the command. Overrides the template parameter (Panorama instances). If not given, will use the integration parameter. | Optional |
| template_stack | The template stack to use when running the command. | Optional |
| vsys | The name of the virtual system to be configured. Will use the configured VSYS parameter if exists. If given a value, will override the VSYS parameter. If neither the VSYS parameter and this argument are entered, will default to ‘vsys1’. . | Optional |
Context Output
| Path | Type | Description |
|---|---|---|
| Panorama.Zone.Name | String | The name of the zone. |
| Panorama.Zone.Network | String | The network to which the zone connected |
| Panorama.Zone.EnableUserIdentification | String | Whether user identification is enabled. |
| Panorama.Zone.ZoneProtectionProfile | String | The zone protection profile. |
| Panorama.Zone.LogSetting | String | The log setting for the zone |
Command Example
#### Context Example
```json
{
"Panorama": {
"Zone": {
"EnableUserIdentification": "no",
"LogSetting": null,
"Name": "test_zone",
"Network": {
"tap": {
"member": "ethernet1/1"
}
},
"ZoneProtectionProfile": null
}
}
}
Human Readable Output
Zone Configuration
Name Network EnableUserIdentification test_zone tap: {“member”: “ethernet1/1”} no
pan-os-list-configured-user-id-agents
Retrieves list of user-ID agents configured in the system.
Base Command
pan-os-list-configured-user-id-agents
Input
| Argument Name | Description | Required |
|---|---|---|
| template | The template to use when running the command. Overrides the template parameter (Panorama instances). If not given, will use the integration parameter. | Optional |
| template_stack | The template stack to use when running the command. | Optional |
| vsys | The name of the virtual system to be configured. Will use the configured VSYS parameter if exists. If given a value, will override the VSYS parameter. If neither the VSYS parameter and this argument are entered, will default to ‘vsys1’. . | Optional |
Context Output
| Path | Type | Description |
|---|---|---|
| Panorama.UserIDAgents.Name | String | The user-ID Agent name. |
| Panorama.UserIDAgents.Host | String | The user-ID Agent host. |
| Panorama.UserIDAgents.Port | Number | The user-ID Agent port. |
| Panorama.UserIDAgents.LdapProxy | String | Whether LDAP proxy is used in the user-ID agent. |
| Panorama.UserIDAgents.NtlmAuth | String | Whether NLTM authentication is used in the user-ID agent. |
| Panorama.UserIDAgents.EnableHipCollection | String | Whether HIP collection is enabled in the user-ID agent. |
| Panorama.UserIDAgents.IpUserMapping | String | Whether IP user mapping is enabled in the user-ID agent. |
| Panorama.UserIDAgents.SerialNumber | Unknown | The serial number associated with the user-ID agent. |
| Panorama.UserIDAgents.CollectorName | String | The user-ID agent collector name. |
| Panorama.UserIDAgents.Secret | String | The user-ID agent secret. |
| Panorama.UserIDAgents.Disabled | String | Whether the user-ID agent is disbaled. |
Command Example
#### Context Example
```json
{
"Panorama": {
"UserIDAgents": [
{
"CollectorName": "demisto",
"Disabled": "yes",
"EnableHipCollection": null,
"Host": "mine",
"IpUserMapping": null,
"LdapProxy": "yes",
"Name": "testing",
"NtlmAuth": "yes",
"Port": "12",
"Secret": "secret",
"SerialNumber": null
},
{
"CollectorName": null,
"Disabled": null,
"EnableHipCollection": null,
"Host": null,
"IpUserMapping": null,
"LdapProxy": null,
"Name": "withSerial",
"NtlmAuth": null,
"Port": null,
"Secret": null,
"SerialNumber": "panorama"
}
]
}
}
Human Readable Output
User ID Agents
Name SerialNumber Host Port CollectorName LdapProxy NtlmAuth testing mine 12 demisto yes yes withSerial panorama
pan-os-upload-content-update-file
Uploads a content file to Panorama.
Base Command
pan-os-upload-content-update-file
Input
| Argument Name | Description | Required |
|---|---|---|
| entryID | Entry ID of the file to upload. | Required |
| category | The category of the content. Possible values are: wildfire, anti-virus, content. | Required |
Context Output
| Path | Type | Description |
|---|---|---|
| Panorama.Content.Upload.Status | string | Content upload status. |
| Panorama.Content.Upload.Message | string | Content upload message. |
Command Example
pan-os-upload-content-update-file entryID="32@14183" category="content"
Human Readable Output
Results
Status Message Success line: saved
pan-os-install-file-content-update
Installs specific content update file.
Base Command
pan-os-install-file-content-update
Input
| Argument Name | Description | Required |
|---|---|---|
| version_name | Update file name to be installed on PAN-OS. | Required |
| category | The category of the content. Possible values are: wildfire, anti-virus, content. | Required |
| skip_validity_check | Skips file validity check with PAN-OS update server. Use this option for air-gapped networks and only if you trust the content file. Possible values are: yes, no. Default is no. | Required |
Context Output
| Path | Type | Description |
|---|---|---|
| Panorama.Content.Install.JobID | string | JobID of the installation. |
| Panorama.Content.Install.Status | string | Installation status. |
Command Example
pan-os-install-file-content-update version_name="panupv2-all-contents-8322-6317" category="content" skip_validity_check="yes"
Human Readable Output
Results
JobID Status 30 Pending
pan-os-platform-get-arp-tables
Gets all ARP tables from all firewalls in the topology.
Base Command
pan-os-platform-get-arp-tables
Input
| Argument Name | Description | Required |
|---|---|---|
| device_filter_string | String by which to filter the results to only show specific hostnames or serial numbers. | Optional |
| target | Single serial number to target with this command | Optional |
Context Output
| Path | Type | Description |
|---|---|---|
| PANOS.ShowArp.Summary.hostid | String | ID of the PAN-OS host |
| PANOS.ShowArp.Summary.max | String | Maximum number of supported ARP entries. |
| PANOS.ShowArp.Summary.total | String | Total number of current ARP entries. |
| PANOS.ShowArp.Summary.timeout | String | ARP entry timeout. |
| PANOS.ShowArp.Summary.dp | String | Firewall dataplane associated with the entry. |
| PANOS.ShowArp.Result.hostid | String | ID of the PAN-OS host. |
| PANOS.ShowArp.Result.interface | String | Network interface learned ARP entry. |
| PANOS.ShowArp.Result.ip | String | Layer 3 address. |
| PANOS.ShowArp.Result.mac | String | Layer 2 address. |
| PANOS.ShowArp.Result.port | String | Network interface matching entry. |
| PANOS.ShowArp.Result.status | String | ARP entry status. |
| PANOS.ShowArp.Result.ttl | String | Time to live. |
Command example
#### Context Example
```json
{
"PANOS": {
"ShowArp": {
"Result": [
{
"hostid": "0111112222333444",
"interface": "ethernet1/1",
"ip": "192.168.1.1",
"mac": "00:66:4b:da:ce:61",
"port": "ethernet1/1",
"status": " c ",
"ttl": "1799"
},
{
"hostid": "0111112222333444",
"interface": "ethernet1/1",
"ip": "1.1.1.1",
"mac": "00:0c:29:31:bf:8b",
"port": "ethernet1/1",
"status": " c ",
"ttl": "991"
},
{
"hostid": "0111112222333444",
"interface": "ethernet1/1",
"ip": "192.168.1.11",
"mac": "4c:32:75:c2:b2:49",
"port": "ethernet1/1",
"status": " c ",
"ttl": "533"
},
{
"hostid": "0111112222333444",
"interface": "ethernet1/1",
"ip": "192.168.1.12",
"mac": "28:f0:76:79:63:b0",
"port": "ethernet1/1",
"status": " c ",
"ttl": "1721"
},
{
"hostid": "0111112222333444",
"interface": "ethernet1/1",
"ip": "192.168.1.13",
"mac": "a8:60:b6:20:ba:5c",
"port": "ethernet1/1",
"status": " c ",
"ttl": "1723"
},
{
"hostid": "0111112222333444",
"interface": "ethernet1/1",
"ip": "192.168.1.14",
"mac": "20:79:18:93:5a:94",
"port": "ethernet1/1",
"status": " c ",
"ttl": "19"
},
{
"hostid": "0111112222333444",
"interface": "ethernet1/1",
"ip": "192.168.1.15",
"mac": "68:ff:7b:2e:ef:f2",
"port": "ethernet1/1",
"status": " c ",
"ttl": "1396"
},
{
"hostid": "0111112222333444",
"interface": "ethernet1/1",
"ip": "192.168.1.16",
"mac": "00:d8:61:52:b2:ee",
"port": "ethernet1/1",
"status": " c ",
"ttl": "794"
},
{
"hostid": "0111112222333444",
"interface": "ethernet1/2",
"ip": "10.10.0.12",
"mac": "00:0c:29:ba:d7:d2",
"port": "ethernet1/2",
"status": " c ",
"ttl": "1558"
}
],
"Summary": [
{
"dp": "dp0",
"hostid": "0111112222333444",
"max": "1500",
"timeout": "1800",
"total": "9"
}
]
}
}
}
Human Readable Output
PAN-OS ARP Table
dp hostid max timeout total dp0 0111112222333444 1500 1800 9
pan-os-platform-get-route-summary
Pulls all route summary information from the topology.
Base Command
pan-os-platform-get-route-summary
Input
| Argument Name | Description | Required |
|---|---|---|
| device_filter_string | String by which to filter the results to only show specific hostnames or serial numbers. | Optional |
| target | Single serial number to target with this command | Optional |
Context Output
| Path | Type | Description |
|---|---|---|
| PANOS.ShowRouteSummary.Summary.hostid | Number | ID of the PAN-OS host. |
| PANOS.ShowRouteSummary.Summary.total | Number | Total number of routes. |
| PANOS.ShowRouteSummary.Summary.limit | Number | Maximum number of routes for the platform. |
| PANOS.ShowRouteSummary.Summary.active | Number | Active routes in the routing table . |
Command example
#### Context Example
```json
{
"PANOS": {
"ShowRouteSummary": {
"Summary": [
{
"active": 5,
"hostid": "0111112222333444",
"limit": 2500,
"total": 5
}
]
}
}
}
Human Readable Output
PAN-OS Route Summary
active hostid limit total 5 0111112222333444 2500 5
pan-os-platform-get-routes
Pulls all route information from the topology.
Base Command
pan-os-platform-get-routes
Input
| Argument Name | Description | Required |
|---|---|---|
| device_filter_string | String by which to filter the results to only show specific hostnames or serial numbers. | Optional |
| target | Single serial number to target with this command | Optional |
Context Output
| Path | Type | Description |
|---|---|---|
| PANOS.ShowRoute.Summary.hostid | String | ID of the PAN-OS host. |
| PANOS.ShowRoute.Summary.interface | String | Next hop interface. |
| PANOS.ShowRoute.Summary.route_count | Number | Total number of routes seen on the virtual router interface. |
| PANOS.ShowRoute.Result.hostid | String | ID of the PAN-OS host. |
| PANOS.ShowRoute.Result.virtual_router | String | Virtual router this route belongs to. |
| PANOS.ShowRoute.Result.destination | String | Network destination of the route. |
| PANOS.ShowRoute.Result.nexthop | String | Next hop to destination. |
| PANOS.ShowRoute.Result.metric | String | Route metric. |
| PANOS.ShowRoute.Result.flags | String | Route flags. |
| PANOS.ShowRoute.Result.age | Number | Age of the route. |
| PANOS.ShowRoute.Result.interface | String | Next hop interface. |
| PANOS.ShowRoute.Result.route_table | String | The route table this route belongs to. |
Command example
#### Context Example
```json
{
"PANOS": {
"ShowRoute": {
"Result": [
{
"age": null,
"destination": "0.0.0.0/0",
"flags": "A S ",
"hostid": "0111112222333444",
"interface": "ethernet1/1",
"metric": "10",
"nexthop": "192.168.1.1",
"route_table": "unicast",
"virtual_router": "default"
},
{
"age": null,
"destination": "10.10.0.0/24",
"flags": "A C ",
"hostid": "0111112222333444",
"interface": "ethernet1/2",
"metric": "0",
"nexthop": "10.10.0.1",
"route_table": "unicast",
"virtual_router": "default"
},
{
"age": null,
"destination": "10.10.0.1/32",
"flags": "A H ",
"hostid": "0111112222333444",
"interface": null,
"metric": "0",
"nexthop": "0.0.0.0",
"route_table": "unicast",
"virtual_router": "default"
},
{
"age": null,
"destination": "192.168.1.0/24",
"flags": "A C ",
"hostid": "0111112222333444",
"interface": "ethernet1/1",
"metric": "0",
"nexthop": "192.168.1.139",
"route_table": "unicast",
"virtual_router": "default"
},
{
"age": null,
"destination": "192.168.1.139/32",
"flags": "A H ",
"hostid": "0111112222333444",
"interface": null,
"metric": "0",
"nexthop": "0.0.0.0",
"route_table": "unicast",
"virtual_router": "default"
}
],
"Summary": [
{
"hostid": "0111112222333444",
"interface": "ethernet1/1",
"route_count": 2
},
{
"hostid": "0111112222333444",
"interface": "ethernet1/2",
"route_count": 1
},
{
"hostid": "0111112222333444",
"interface": null,
"route_count": 2
}
]
}
}
}
Human Readable Output
PAN-OS Routes
hostid interface route_count 0111112222333444 ethernet1/1 2 0111112222333444 ethernet1/2 1 0111112222333444 2
pan-os-platform-get-system-info
Gets information from all PAN-OS systems in the topology.
Base Command
pan-os-platform-get-system-info
Input
| Argument Name | Description | Required |
|---|---|---|
| device_filter_string | String by which to filter the results to only show specific hostnames or serial numbers. | Optional |
| target | Single serial number to target with this command | Optional |
Context Output
| Path | Type | Description |
|---|---|---|
| PANOS.ShowSystemInfo.Summary.hostid | String | ID of the PAN-OS host. |
| PANOS.ShowSystemInfo.Summary.ip_address | String | Management IP address. |
| PANOS.ShowSystemInfo.Summary.sw_version | String | System software version. |
| PANOS.ShowSystemInfo.Summary.family | String | Platform family. |
| PANOS.ShowSystemInfo.Summary.model | String | Platform model. |
| PANOS.ShowSystemInfo.Summary.uptime | String | Total system uptime. |
| PANOS.ShowSystemInfo.Summary.hostname | String | System hostname. |
| PANOS.ShowSystemInfo.Result.hostid | String | ID of the PAN-OS host. |
| PANOS.ShowSystemInfo.Result.ip_address | String | Management IP address. |
| PANOS.ShowSystemInfo.Result.netmask | String | Management netmask. |
| PANOS.ShowSystemInfo.Result.mac_address | String | Management MAC address. |
| PANOS.ShowSystemInfo.Result.uptime | String | Total system uptime. |
| PANOS.ShowSystemInfo.Result.family | String | Platform family. |
| PANOS.ShowSystemInfo.Result.model | String | Platform model. |
| PANOS.ShowSystemInfo.Result.sw_version | String | System software version. |
| PANOS.ShowSystemInfo.Result.operational_mode | String | Current operational mode. |
| PANOS.ShowSystemInfo.Result.ipv6_address | String | Management IPv6 address. |
| PANOS.ShowSystemInfo.Result.default_gateway | String | Management default gateway. |
| PANOS.ShowSystemInfo.Result.public_ip_address | String | Firewall public IP address. |
| PANOS.ShowSystemInfo.Result.hostname | String | Device hostname. |
| PANOS.ShowSystemInfo.Result.av_version | String | System anti-virus version. |
| PANOS.ShowSystemInfo.Result.av_release_date | String | Release date of the antivirus content, |
| PANOS.ShowSystemInfo.Result.app_version | String | App content version, |
| PANOS.ShowSystemInfo.Result.app_release_date | String | Release date of the application content. |
| PANOS.ShowSystemInfo.Result.threat_version | String | Threat content version. |
| PANOS.ShowSystemInfo.Result.threat_release_date | String | Release date of the threat content. |
| PANOS.ShowSystemInfo.Result.wildfire_version | String | Wildfire content version. |
| PANOS.ShowSystemInfo.Result.wildfire_release_date | String | Wildfire release date. |
| PANOS.ShowSystemInfo.Result.url_filtering_version | String | URL filtering content version. |
| PANOS.ShowSystemInfo.Result.global_protect_client_package_version | String | The GlobalProtect client package version. |
| PANOS.ShowSystemInfo.Result.advanced_routing | string | Advanced routing engine feature. |
| PANOS.ShowSystemInfo.Result.multi_vsys | string | Virtual system feature. |
Command example
#### Context Example
```json
{
"PANOS": {
"ShowSystemInfo": {
"Result": [
{
"app_release_date": "",
"app_version": "8475-7000",
"av_release_date": "",
"av_version": "0",
"default_gateway": "192.168.1.1",
"family": "vm",
"hostid": "0111112222333444",
"hostname": "vm-lab-fw1",
"ip_address": "2.2.2.2",
"ipv6_address": "unknown",
"mac_address": "00:0c:29:eb:35:ad",
"model": "PA-VM",
"netmask": "255.255.255.0",
"operational_mode": "normal",
"public_ip_address": "unknown",
"sw_version": "10.0.5",
"threat_release_date": "",
"threat_version": "8475-7000",
"uptime": "22 days, 0:20:49",
"url_filtering_version": "20220218.20012",
"wildfire_release_date": "",
"wildfire_version": "0",
"global_protect_client_package_version": "0.0.0",
"advanced_routing": "on",
"multi_vsys": "on"
},
{
"app_release_date": "2021/12/06 18:49:44 PST",
"app_version": "8496-7089",
"av_release_date": "",
"av_version": "0",
"default_gateway": "192.168.1.1",
"family": "pc",
"hostid": "1.1.1.1",
"hostname": "Panorama",
"ip_address": "1.1.1.1",
"ipv6_address": "unknown",
"mac_address": "00:0c:29:31:bf:8b",
"model": "Panorama",
"netmask": "255.255.255.0",
"operational_mode": "normal",
"public_ip_address": "unknown",
"sw_version": "10.0.7",
"threat_release_date": "",
"threat_version": "",
"uptime": "3 days, 13:56:06",
"url_filtering_version": "",
"wildfire_release_date": "",
"wildfire_version": "0",
"advanced_routing": "off",
"multi_vsys": "on"
}
],
"Summary": [
{
"family": "vm",
"hostid": "0111112222333444",
"hostname": "vm-lab-fw1",
"ip_address": "2.2.2.2",
"model": "PA-VM",
"sw_version": "10.0.5",
"uptime": "22 days, 0:20:49"
},
{
"family": "pc",
"hostid": "1.1.1.1",
"hostname": "Panorama",
"ip_address": "1.1.1.1",
"model": "Panorama",
"sw_version": "10.0.7",
"uptime": "3 days, 13:56:06"
}
]
}
}
}
Human Readable Output
PAN-OS System Info
family hostid hostname ip_address model sw_version uptime vm 0111112222333444 vm-lab-fw1 2.2.2.2 PA-VM 10.0.5 22 days, 0:20:49 pc 1.1.1.1 Panorama 1.1.1.1 Panorama 10.0.7 3 days, 13:56:06
pan-os-platform-get-device-groups
Gets operational information for all device groups in the Panorama topology, including group names, hierarchy, and associated firewalls. If no filter is provided, the command returns all device groups within the Panorama instance.
Base Command
pan-os-platform-get-device-groups
Input
| Argument Name | Description | Required |
|---|---|---|
| device_filter_string | The Panorama hostname or serial number used to filter device groups. This command is specifically for Panorama and requires an exact match (substrings are not supported). | Optional |
Context Output
| Path | Type | Description |
|---|---|---|
| PANOS.DeviceGroupOp.hostid | String | ID of the PAN-OS host. |
| PANOS.DeviceGroupOp.serial | String | Serial number of the firewall. |
| PANOS.DeviceGroupOp.connected | String | Whether the firewall is currently connected. |
| PANOS.DeviceGroupOp.hostname | String | Firewall hostname. |
| PANOS.DeviceGroupOp.last_commit_all_state_sp | String | State of the last commit. |
| PANOS.DeviceGroupOp.name | String | Device group name. |
pan-os-platform-get-template-stacks
Gets the operational information of the template stacks in the topology.
Base Command
pan-os-platform-get-template-stacks
Input
| Argument Name | Description | Required |
|---|---|---|
| device_filter_string | String by which to filter the results to only show specific hostnames or serial numbers. | Optional |
Context Output
| Path | Type | Description |
|---|---|---|
| PANOS.TemplateStackOp.hostid | String | ID of the PAN-OS host. |
| PANOS.TemplateStackOp.serial | String | Serial number of the firewall. |
| PANOS.TemplateStackOp.connected | String | Whether the firewall is currently connected. |
| PANOS.TemplateStackOp.hostname | String | Firewall hostname. |
| PANOS.TemplateStackOp.last_commit_all_state_tpl | String | State of last commit. |
| PANOS.TemplateStackOp.name | String | Template stack name. |
Command example
#### Context Example
```json
{
"PANOS": {
"TemplateStackOp": [
{
"connected": "yes",
"hostid": "1.1.1.1",
"hostname": "vm-lab-fw1",
"last_commit_all_state_tpl": "commit succeeded with warnings",
"name": "LAB-STACK",
"serial": "0111112222333444"
},
{
"connected": "no",
"hostid": "1.1.1.1",
"hostname": "vm-lab-fw02",
"last_commit_all_state_tpl": "commit succeeded with warnings",
"name": "LAB-STACK",
"serial": "0111112222333455"
}
]
}
}
Human Readable Output
PAN-OS Operational Template Stack status
connected hostid hostname last_commit_all_state_tpl name serial yes 1.1.1.1 vm-lab-fw1 commit succeeded with warnings LAB-STACK 0111112222333444 no 1.1.1.1 vm-lab-fw02 commit succeeded with warnings LAB-STACK 0111112222333455
pan-os-platform-get-global-counters
Gets global counter information from all the PAN-OS firewalls in the topology.
Base Command
pan-os-platform-get-global-counters
Input
| Argument Name | Description | Required |
|---|---|---|
| device_filter_string | String by which to filter the results to only show specific hostnames or serial numbers. | Optional |
| target | Single serial number to target with this command | Optional |
Context Output
| Path | Type | Description |
|---|---|---|
| PANOS.ShowCounters.Summary.hostid | String | Host ID. |
| PANOS.ShowCounters.Summary.name | String | Human readable counter name. |
| PANOS.ShowCounters.Summary.value | Number | Current counter value. |
| PANOS.ShowCounters.Summary.rate | Number | Packets per second rate. |
| PANOS.ShowCounters.Summary.desc | String | Human readable counter description. |
| PANOS.ShowCounters.Result.hostid | String | Host ID. |
| PANOS.ShowCounters.Result.category | String | The counter category. |
| PANOS.ShowCounters.Result.name | String | Human readable counter name. |
| PANOS.ShowCounters.Result.value | Number | Current counter value. |
| PANOS.ShowCounters.Result.rate | Number | Packets per second rate. |
| PANOS.ShowCounters.Result.aspect | String | PAN-OS aspect. |
| PANOS.ShowCounters.Result.desc | String | Human readable counter description. |
| PANOS.ShowCounters.Result.id | String | Counter ID. |
| PANOS.ShowCounters.Result.severity | String | Counter severity. |
Command example
#### Context Example
```json
{
"PANOS": {
"ShowCounters": {
"Result": [
{
"aspect": "pktproc",
"category": "packet",
"desc": "Packets received",
"hostid": "11111111111111",
"id": "17",
"name": "pkt_recv",
"rate": 15,
"severity": "info",
"value": 17981379
"severity": "info",
"value": 2
},
{
"aspect": "pktproc",
"category": "ssl",
"desc": "Number of failures when receiving SSL session cache msg from MP",
"hostid": "11111111111111",
"id": "3185",
"name": "ssl_sess_cache_msg_from_mp_failure",
"rate": 0,
"severity": "info",
"value": 1834071
}
],
"Summary": [
{
"desc": "Packets received",
"hostid": "11111111111111",
"name": "pkt_recv",
"rate": 15,
"value": 17981379
},
]
}
}
}
Human Readable Output
PAN-OS Global Counters
desc hostid name rate value Packets received 11111111111111 pkt_recv 15 17981379 Full Burst Packets received on retry 11111111111111 pkt_recv_retry 0 422240 Packet receive error 11111111111111 pkt_recv_err 0 225 Packets drop due to passive VM in dpdk mode 11111111111111 pkt_recv_flush_passive 0 2351 Packets transmitted 11111111111111 pkt_sent 3 5334628 Packets successfully transmitted to host interface 11111111111111 pkt_sent_host 0 685046 STP BPDU packets received 11111111111111 pkt_stp_rcv 1 1271742 Sessions allocated 11111111111111 session_allocated 0 537466 Sessions freed 11111111111111 session_freed 0 537440 Sessions installed 11111111111111 session_installed 0 449506 Session aging timer modified by unverified RST 11111111111111 session_unverified_rst 0 15579 Session is closing or closed and still receive TCP pkt 11111111111111 session_pkt_in_closed_state 0 3 Session notifications retransmitted to offload processor 11111111111111 session_renotify 0 3 Packets dropped: 802.1q tag not configured 11111111111111 flow_rcv_dot1q_tag_err 0 24 Packets dropped: invalid interface 11111111111111 flow_no_interface 0 24 Packets dropped: IPv6 disabled on interface 11111111111111 flow_ipv6_disabled 1 1505760 Non-SYN TCP packets without session match 11111111111111 flow_tcp_non_syn 0 83 Packets dropped: non-SYN TCP without session match 11111111111111 flow_tcp_non_syn_drop 0 83 Packets dropped: unhandled IP broadcast 11111111111111 flow_fwd_l3_bcast_drop 0 254789 Packets dropped: no route for IP multicast 11111111111111 flow_fwd_l3_mcast_drop 2 2450999 Packets dropped: no ARP 11111111111111 flow_fwd_l3_noarp 0 204 Packet dropped at forwarding: noxmit 11111111111111 flow_fwd_drop_noxmit 0 294 Packets dropped: Packet too short to cover IP header 11111111111111 flow_parse_ip_hdr 0 4 Packets dropped: IPv6 packet truncated 11111111111111 flow_parse_ip6_truncated 0 4 Packets received: IPv6 multicast pkts with flow off 11111111111111 flow_ip6_mcast_off 1 1505760 IP broadcast pkt received 11111111111111 flow_bcast_pkt_rcv 0 255147 DHCP broadcast pkt received 11111111111111 flow_dhcp_bcast_pkt_rcv 0 4 ARP packets received 11111111111111 flow_arp_pkt_rcv 3 4069186 ARP packets transmitted 11111111111111 flow_arp_pkt_xmt 0 87285 ARP requests replied 11111111111111 flow_arp_pkt_replied 0 82094 ARP entry learned 11111111111111 flow_arp_pkt_learned 0 68 Gratuitous ARP packets received 11111111111111 flow_arp_rcv_gratuitous 0 21524 ARP receive error 11111111111111 flow_arp_rcv_err 0 21202 ARP resolution packets transmitted 11111111111111 flow_arp_resolve_xmt 0 2477 ND entry GC 11111111111111 flow_nd_neigh_gc 0 1060 Packets received from control plane 11111111111111 flow_host_pkt_rcv 0 137018 Packets transmitted to control plane 11111111111111 flow_host_pkt_xmt 0 685046 Packets dropped: receive error from control plane 11111111111111 flow_host_rcv_err 0 11 Packets dropped: decapsulation error from control plane 11111111111111 flow_host_decap_err 0 26 Device management session allowed 11111111111111 flow_host_service_allow 0 136965 Device management session denied 11111111111111 flow_host_service_deny 0 38658 Host vardata not sent: rate limit ok 11111111111111 flow_host_vardata_rate_limit_ok 0 3 Packet on VxLAN port without I bit 11111111111111 flow_tci_vxlan_without_vni 0 2 netconfig temporarily unavailable 11111111111111 device_invalid_netconf 0 404 netconfig switched 11111111111111 device_netconf_switch 0 4 tundconfig switched 11111111111111 device_tundconf_switch 0 1 Packets for which IP checksum validation was done in software 11111111111111 flow_ip_cksm_sw_validation 6 8478257 Packets not allowed to egress for pre-negotiation 11111111111111 flow_drop_preneg_egress 0 2 Application identified by simple signature 11111111111111 appid_ident_by_simple_sig 0 92740 Application identified by L4 dport first 11111111111111 appid_ident_by_dport_first 0 174358 The number of packets processed by Application identification 11111111111111 appid_proc 0 177586 The number of unknown applications caused by max. packets reached 11111111111111 appid_unknown_max_pkts 0 9 The number of unknown UDP applications after app engine 11111111111111 appid_unknown_udp 0 271 The number of unknown applications because of no data 11111111111111 appid_unknown_fini_empty 0 97562 The total number of dynamic_ip_port NAT translate called 11111111111111 nat_dynamic_port_xlat 0 242839 The total number of dynamic_ip_port NAT release called 11111111111111 nat_dynamic_port_release 0 242825 The total number of dfa match using software 11111111111111 dfa_sw 1 1096816 tcp reassembly case 1 11111111111111 tcp_case_1 0 1 tcp reassembly case 2 11111111111111 tcp_case_2 0 346 out-of-window packets dropped 11111111111111 tcp_drop_out_of_wnd 0 116 The number of sessions with sml exit in detector i 11111111111111 ctd_sml_exit_detector_i 0 200010 The number of decoder resume requests 11111111111111 ctd_sml_unset_suspend 0 30 Handle reset and url exit 11111111111111 ctd_handle_reset_and_url_exit 0 30 ctd switch decoder 11111111111111 ctd_switch_decoder 0 10 ctd stops to process packet 11111111111111 ctd_stop_proc 0 10 run detector_i 11111111111111 ctd_run_detector_i 0 200020 SML VM opcode exit 11111111111111 ctd_sml_vm_run_impl_opcodeexit 0 199980 Forward to varrcvr error: TCP in establishment when session went away 11111111111111 ctd_fwd_err_tcp_state 0 94652 The total usage of software for pscan 11111111111111 ctd_pscan_sw 1 1170516 appid was changed 11111111111111 ctd_appid_reassign 0 60011 decoder was changed 11111111111111 ctd_decoder_reassign 0 10 session processed by ctd 11111111111111 ctd_process 0 351954 Packets processed by slowpath 11111111111111 ctd_pkt_slowpath 1 1186304 Number of Policy Hit Count periodical update 11111111111111 ctd_hitcount_period_update 0 4237 Number of url logs 11111111111111 log_url_cnt 0 6060 Number of uid request logs 11111111111111 log_uid_req_cnt 0 241849 Number of traffic logs 11111111111111 log_traffic_cnt 0 449480 Time (us) spent on writing packet-diag logs 11111111111111 log_pkt_diag_us 0 16 Number of URL database request 11111111111111 url_db_request 0 1965 Number of URL reply 11111111111111 url_db_reply 9 4419218 The number of packets get dropped because of waiting for url category request 11111111111111 url_request_pkt_drop 0 1771 The session is not waiting for url 11111111111111 url_session_not_in_wait 0 10 The number of HSM up/down events received 11111111111111 ssl_hsm_up_down_event_rcv 0 2 Number of failures when receiving SSL session cache msg from MP 11111111111111 ssl_sess_cache_msg_from_mp_failure 0 1834071
pan-os-platform-get-bgp-peers
Retrieves all BGP peer information from the PAN-OS firewalls in the topology.
Base Command
pan-os-platform-get-bgp-peers
Input
| Argument Name | Description | Required |
|---|---|---|
| device_filter_string | String by which to filter the results to only show specific hostnames or serial numbers. | Optional |
| target | Single serial number to target with this command | Optional |
Context Output
| Path | Type | Description |
|---|---|---|
| PANOS.ShowBGPPeers.Summary.hostid | String | Host ID. |
| PANOS.ShowBGPPeers.Summary.peer | String | Name of the BGP peer. |
| PANOS.ShowBGPPeers.Summary.status | String | Peer connection status. |
| PANOS.ShowBGPPeers.Summary.incoming_accepted | String | Total accepted routes from the peer. |
| PANOS.ShowBGPPeers.Result.hostid | String | Host ID. |
| PANOS.ShowBGPPeers.Result.peer | String | Name of the BGP peer. |
| PANOS.ShowBGPPeers.Result.vr | String | Virtual router in which the peer resides. |
| PANOS.ShowBGPPeers.Result.remote_as | String | Remote AS (Autonomous System) of the peers |
| PANOS.ShowBGPPeers.Result.status | String | Peer connection statuss |
| PANOS.ShowBGPPeers.Result.peer_address | String | IP address and port of the peers |
| PANOS.ShowBGPPeers.Result.local_address | String | Local router address and port of the peer. |
| PANOS.ShowBGPPeers.Result.incoming_total | String | Total incoming routes from the peer. |
| PANOS.ShowBGPPeers.Result.incoming_accepted | String | Total accepted routes from the peer. |
| PANOS.ShowBGPPeers.Result.incoming_rejected | String | Total rejected routes from the peer. |
| PANOS.ShowBGPPeers.Result.policy_rejected | String | Total routes rejected by the peer by policy. |
| PANOS.ShowBGPPeers.Result.outgoing_total | String | Total routes advertised to the peer. |
| PANOS.ShowBGPPeers.Result.outgoing_advertised | String | Number of advertised routes to the peer. |
Command example
#### Context Example
```json
{
"PANOS": {
"ShowBGPPeers": {
"Result": [
{
"hostid": "11111111111111",
"incoming_accepted": 0,
"incoming_rejected": 0,
"incoming_total": 0,
"local_address": "10.10.0.1",
"outgoing_advertised": 0,
"outgoing_total": 0,
"peer": "testlab-server",
"peer_address": "10.10.0.12",
"policy_rejected": 0,
"remote_as": "64511",
"status": "Active",
"vr": "default"
}
],
"Summary": [
{
"hostid": "11111111111111",
"incoming_accepted": 0,
"peer": "testlab-server",
"status": "Active"
}
]
}
}
}
Human Readable Output
PAN-OS BGP Peers
hostid incoming_accepted peer status 11111111111111 0 testlab-server Active
pan-os-platform-get-available-software
Check the devices for software that is available to be installed.
Base Command
pan-os-platform-get-available-software
Input
| Argument Name | Description | Required |
|---|---|---|
| device_filter_string | String by which to filter the results to only show specific hostnames or serial numbers. | Optional |
| target | Single serial number to target with this command | Optional |
Context Output
| Path | Type | Description |
|---|---|---|
| PANOS.SoftwareVersions.Summary.hostid | String | Host ID. |
| PANOS.SoftwareVersions.Summary.version | String | The software version in Major.Minor.Maint format. |
| PANOS.SoftwareVersions.Summary.filename | String | Software version filename. |
| PANOS.SoftwareVersions.Summary.size | String | Size of the software in MB. |
| PANOS.SoftwareVersions.Summary.size_kb | String | Size of the software in KB. |
| PANOS.SoftwareVersions.Summary.release_notes | String | Link to version release notes on PAN knowledge base. |
| PANOS.SoftwareVersions.Summary.downloaded | Boolean | True if the software version is present on the system. |
| PANOS.SoftwareVersions.Summary.current | Boolean | True if this is the currently installed software on the system. |
| PANOS.SoftwareVersions.Summary.latest | Boolean | True if this is the most recently released software for this platform. |
| PANOS.SoftwareVersions.Summary.uploaded | Boolean | True if the software version has been uploaded to the system. |
Command example
#### Context Example
```json
{
"PANOS": {
"SoftwareVersions": {
"Summary": [
{
"current": false,
"downloaded": false,
"filename": "PanOS_vm-10.2.0",
"hostid": "11111111111111",
"latest": true,
"release_notes": "https://www.paloaltonetworks.com/documentation/10-2/pan-os/pan-os-release-notes",
"size": "1010",
"size_kb": "1034657",
"uploaded": false,
"version": "10.2.0"
}
]
}
}
}
Human Readable Output
PAN-OS Available Software Versions
current downloaded filename hostid latest release_notes size size_kb uploaded version false false PanOS_vm-10.2.0 11111111111111 true https://www.paloaltonetworks.com/documentation/10-2/pan-os/pan-os-release-notes 1010 1034657 false 10.2.0 false false PanOS_vm-10.1.5 11111111111111 false https://www.paloaltonetworks.com/documentation/10-1/pan-os/pan-os-release-notes 457 468174 false 10.1.5 false false PanOS_vm-10.1.4-h4 11111111111111 false https://www.paloaltonetworks.com/documentation/10-1/pan-os/pan-os-release-notes 407 416843 false 10.1.4-h4
pan-os-platform-get-ha-state
Get the HA state and associated details from the given device and any other details.
Base Command
pan-os-platform-get-ha-state
Input
| Argument Name | Description | Required |
|---|---|---|
| device_filter_string | String by which to filter the results to only show specific hostnames or serial numbers. | Optional |
| target | Single serial number to target with this command | Optional |
Context Output
| Path | Type | Description |
|---|---|---|
| PANOS.HAState.hostid | String | Host ID. |
| PANOS.HAState.active | Boolean | Whether this is the active firewall in a pair. True if standalone as well. |
| PANOS.HAState.status | String | String HA status. |
| PANOS.HAState.peer | String | HA peer. |
Command example
#### Context Example
```json
{
"PANOS": {
"HAState": [
{
"active": true,
"hostid": "11111111111111",
"peer": "",
"status": "HA Not enabled."
},
{
"active": true,
"hostid": "192.168.1.145",
"peer": "",
"status": "HA Not enabled."
}
]
}
}
Human Readable Output
PAN-OS HA State
active hostid status true 11111111111111 HA Not enabled. true 192.168.1.145 HA Not enabled.
pan-os-platform-get-jobs
Get all the jobs from the devices in the environment, or a single job when ID is specified.
Base Command
pan-os-platform-get-jobs
Input
| Argument Name | Description | Required |
|---|---|---|
| device_filter_string | String by which to filter the results to only show specific hostnames or serial numbers. | Optional |
| target | Single serial number to target with this command | Optional |
| status | Filter to return jobs by status. | Optional |
| job_type | Filter to return jobs by type. | Optional |
| id | Filter by ID. | Optional |
| polling | Whether to poll the job status until it reaches a terminal state (FIN). Only takes effect when a single job “id” is provided. Possible values are: true, false. Default is false. | Optional |
| interval_in_seconds | The interval between poll attempts, in seconds. Default is 30. | Optional |
| timeout_in_seconds | The maximum time to wait for the job to reach a terminal state, in seconds. If the timeout is reached before the job finishes, the command returns the last known result. Default is 3600. | Optional |
Context Output
| Path | Type | Description |
|---|---|---|
| PANOS.JobStatus.hostid | String | Host ID. |
| PANOS.JobStatus.id | Number | ID of job. |
| PANOS.JobStatus.type | String | Job type. |
| PANOS.JobStatus.tfin | String | Time finished. |
| PANOS.JobStatus.status | String | Status of the job. |
| PANOS.JobStatus.result | String | The result of the job. |
| PANOS.JobStatus.user | String | The user who initiated the job. |
| PANOS.JobStatus.tenq | String | The time the job was enqueued into the system. |
| PANOS.JobStatus.stoppable | String | Whether the job can be stopped after it started. |
| PANOS.JobStatus.description | String | The job description. |
| PANOS.JobStatus.positionInQ | String | The position of the job in the current job queue. |
| PANOS.JobStatus.progress | String | The numerical progress of the job. |
| PANOS.JobStatus.warnings | String | The warnings of the job. |
Command example
#### Context Example
```json
{
"PANOS": {
"JobStatus": [
{
"description": null,
"hostid": "11111111111111",
"id": 1,
"positionInQ": "0",
"progress": "01:02:18",
"result": "OK",
"status": "FIN",
"stoppable": "no",
"tenq": "2022/03/30 01:02:04",
"tfin": "01:02:18",
"type": "Downld",
"user": null,
"warnings": null
},
{
"description": null,
"hostid": "22222222222222",
"id": 2,
"positionInQ": "0",
"progress": "100",
"result": "OK",
"status": "FIN",
"stoppable": "no",
"tenq": "2022/03/15 14:16:32",
"tfin": "14:16:33",
"type": "BuildXMLCache",
"user": null,
"warnings": null
}
]
}
}
Human Readable Output
PAN-OS Job Status
hostid id positionInQ progress result status stoppable tenq tfin type user warnings 11111111111111 1 0 100 OK FIN no 2022/03/15 14:17:16 14:18:17 Downld 22222222222222 2 0 01:02:15 OK FIN no 2022/03/16 01:02:04 01:02:15 BuildXMLCache
pan-os-platform-download-software
Download the provided software version onto the device.
Base Command
pan-os-platform-download-software
Input
| Argument Name | Description | Required |
|---|---|---|
| version | The software version to upgrade to, for example, 9.1.2. | Required |
| device_filter_string | String by which to filter the results to only install to sepecific devices or serial numbers. | Optional |
| target | Single serial number to target with this command | Optional |
| sync | If provided, runs the download synchronously. Make sure ‘execution-timeout’ is increased. | Optional |
Context Output
| Path | Type | Description |
|---|---|---|
| PANOS.DownloadStatus.Summary.hostid | String | Host ID. |
| PANOS.DownloadStatus.Summary.started | String | Whether the download process started. |
Command example
!pan-os-platform-download-software version=9.1.0
Context Example
{
"PANOS": {
"DownloadStatus": {
"Summary": [
{
"hostid": "11111111111111",
"started": true
},
{
"hostid": "192.168.1.145",
"started": true
}
]
}
}
}
Human Readable Output
PAN-OS Software Download request Status
hostid started 11111111111111 true 192.168.1.145 true
pan-os-apply-dns-signature-policy
Allows assigning of EDL to the Anti-Spyware profile under “DNS Signature Policies”.
Base Command
pan-os-apply-dns-signature-policy
Input
| Argument Name | Description | Required |
|---|---|---|
| anti_spyware_profile_name | The name of the anti spyware profile. If the profile exists, the command will operate on it, otherwise, if a new name is given, a new Anti-Spyware profile will be created. | Required |
| dns_signature_source | The EDL name to link to the profile. | Required |
| action | Action on the DNS queries. Possible values are: alert, allow, block, sinkhole. | Required |
| packet_capture | Allows capturing packets on match. Select “single-packet” to capture the first packet of the session or “extended-capture” to set between 1-50 packets. Packet capture can be very CPU intensive and can degrade firewall performance. Only use this feature when necessary and make sure you turn it off after you have collected the required packets. Possible values are: disable, single-packet, extended-capture. Default is disable. | Optional |
Context Output
There is no context output for this command.
Human Readable Output
success
pan-os-platform-reboot
Reboot the given device by hostid. Warning: This command has no confirmation and the device
will immediately reboot.
Base Command
pan-os-platform-reboot
Input
| Argument Name | Description | Required |
|---|---|---|
| target | ID of host (serial or hostname) to reboot. | Required |
Context Output
| Path | Type | Description |
|---|---|---|
| PANOS.RestartStatus.Summary.hostid | String | Host ID. |
| PANOS.RestartStatus.Summary.started | String | Whether the system reboot has started. |
Command example
!pan-os-platform-reboot target=11111111111111
Context Example
{
"PANOS": {
"RestartStatus": {
"Summary": [
{
"hostid": "11111111111111",
"started": true
}
]
}
}
}
pan-os-platform-get-system-status
Checks the status of the given device, checking whether it’s up or down and if the operational mode is normal. Supports polling to wait until the device becomes available.
Base Command
pan-os-platform-get-system-status
Input
| Argument Name | Description | Required |
|---|---|---|
| target | ID of host (serial or hostname) to check. | Required |
| polling | Whether to use polling. When set to “true”, the command polls the target device until it becomes available (operational mode “normal”) or the timeout is reached. Possible values are: true, false. Default is false. | Optional |
| interval_in_seconds | The interval (in seconds) between polling attempts. Default is 30. | Optional |
| timeout | The timeout (in seconds) when polling. Default is 1200. | Optional |
Context Output
| Path | Type | Description |
|---|---|---|
| PANOS.SystemStatus.hostid | String | Host ID. |
| PANOS.SystemStatus.up | String | Whether the host device is up or still unavailable. |
Command example
!pan-os-platform-get-system-status target=11111111111111
Context Example
{
"PANOS": {
"SystemStatus": {
"hostid": "11111111111111",
"up": true
}
}
}
pan-os-platform-update-ha-state
Checks the status of the given device, checking whether it’s up or down and the operational mode normal.
Base Command
pan-os-platform-update-ha-state
Input
| Argument Name | Description | Required |
|---|---|---|
| hostid | ID of host (serial or hostname) to update the state. | Required |
| state | New state. | Required |
Context Output
| Path | Type | Description |
|---|---|---|
| PANOS.HAStateUpdate.hostid | String | Host ID. |
| PANOS.HAStateUpdate.state | String | New HA state. |
Command example
!pan-os-platform-update-ha-state hostid=11111111111111 state=functional
Context Example
{
"PANOS": {
"HAStateUpdate": {
"hostid": "11111111111111",
"state": "functional"
}
}
}
pan-os-hygiene-check-log-forwarding
Checks that at least one log forwarding profile is configured according to best practices.
Base Command
pan-os-hygiene-check-log-forwarding
Input
| Argument Name | Description | Required |
|---|---|---|
| device_filter_string | String by which to filter so that only the given device is checked. | Optional |
Context Output
| Path | Type | Description |
|---|---|---|
| PANOS.ConfigurationHygiene.Summary.description | String | The description of the hygiene check. |
| PANOS.ConfigurationHygiene.Summary.issue_code | String | The shorthand code for this hygiene check. |
| PANOS.ConfigurationHygiene.Summary.result | String | Whether the check passed or failed. |
| PANOS.ConfigurationHygiene.Summary.issue_count | String | Total number of matching issues. |
| PANOS.ConfigurationHygiene.Result.hostid | String | Host ID. |
| PANOS.ConfigurationHygiene.Result.container_name | String | The parent container (DG, Template, VSYS) this object belongs to. |
| PANOS.ConfigurationHygiene.Result.issue_code | String | The shorthand code for the issue. |
| PANOS.ConfigurationHygiene.Result.description | String | Human readable description of the issue. |
| PANOS.ConfigurationHygiene.Result.name | String | The affected object name. |
Command example
#### Context Example
```json
{
"PANOS": {
"ConfigurationHygiene": {
"Result": [
{
"container_name": "LAB",
"description": "Log forwarding profile missing log type 'threat'.",
"hostid": "192.168.1.145",
"issue_code": "BP-V-2",
"name": "test_fwd_profile-1"
},
{
"container_name": "LAB",
"description": "Log forwarding profile missing log type 'threat'.",
"hostid": "192.168.1.145",
"issue_code": "BP-V-2",
"name": "test_fwd_profile-1-1"
},
{
"container_name": "shared",
"description": "Log forwarding profile missing log type 'threat'.",
"hostid": "192.168.1.145",
"issue_code": "BP-V-2",
"name": "test_fwd_profile"
}
],
"Summary": [
{
"description": "Fails if there are no valid log forwarding profiles configured.",
"issue_code": "BP-V-1",
"issue_count": 0,
"result": "\u2714\ufe0f"
},
{
"description": "Fails if the configured log forwarding profile has no match list.",
"issue_code": "BP-V-2",
"issue_count": 3,
"result": "\u274c"
},
{
"description": "Fails if enhanced application logging is not configured.",
"issue_code": "BP-V-3",
"issue_count": 0,
"result": "\u2714\ufe0f"
}
]
}
}
}
Human Readable Output
PAN-OS Configuration Hygiene Check
description issue_code issue_count result Fails if there are no valid log forwarding profiles configured. BP-V-1 0 ✔️ Fails if the configured log forwarding profile has no match list. BP-V-2 3 ❌ Fails if enhanced application logging is not configured. BP-V-3 0 ✔️
pan-os-hygiene-check-vulnerability-profiles
Checks the configured vulnerability profiles to ensure at least one meets best practices.
Base Command
pan-os-hygiene-check-vulnerability-profiles
Input
| Argument Name | Description | Required |
|---|---|---|
| device_filter_string | String by which to filter so that only the given device is checked. | Optional |
| minimum_block_severities | Comma-separated list of severities that must be in drop/reset/block-ip mode. Default is critical,high. | Optional |
| minimum_alert_severities | Comma-separated list of severities that must be in alert/default or higher mode. Default is medium,low. | Optional |
Context Output
| Path | Type | Description |
|---|---|---|
| PANOS.ConfigurationHygiene.Summary.description | String | The description of the hygiene check. |
| PANOS.ConfigurationHygiene.Summary.issue_code | String | The shorthand code for this hygiene check. |
| PANOS.ConfigurationHygiene.Summary.result | String | Whether the check passed or failed. |
| PANOS.ConfigurationHygiene.Summary.issue_count | Nunber | Total number of matching issues. |
| PANOS.ConfigurationHygiene.Result.hostid | String | Host ID. |
| PANOS.ConfigurationHygiene.Result.container_name | String | The parent container (DG, Template, VSYS) this object belongs to. |
| PANOS.ConfigurationHygiene.Result.issue_code | String | The shorthand code for the issue. |
| PANOS.ConfigurationHygiene.Result.description | String | Human readable description of the issue. |
| PANOS.ConfigurationHygiene.Result.name | String | The affected object name |
Command example
#### Context Example
```json
{
"PANOS": {
"ConfigurationHygiene": {
"Summary": [
{
"description": "Fails if no vulnerability profile is configured for visibility.",
"issue_code": "BP-V-4",
"issue_count": 0,
"result": "\u2714\ufe0f"
}
]
}
}
}
Human Readable Output
PAN-OS Configuration Hygiene Check
description issue_code issue_count result Fails if no vulnerability profile is configured for visibility. BP-V-4 0 ✔️
pan-os-platform-install-software
Install the given software version onto the device. Download the software first with panorama-download-panos-version.
Base Command
pan-os-platform-install-software
Input
| Argument Name | Description | Required |
|---|---|---|
| version | Software version to upgrade to, for example: 9.1.2. | Required |
| device_filter_string | SString by which to filter to only install to specific devices or serial numbers. | Optional |
| sync | If provided, runs the download synchronously. Make sure ‘execution-timeout’ is increased. | Optional |
| target | Single serial number to target with this command | Optional |
Context Output
| Path | Type | Description |
|---|---|---|
| PANOS.InstallStatus.Summary.hostid | String | Host ID, |
| PANOS.InstallStatus.Summary.started | String | Whether the download process has started. |
Command example
!pan-os-platform-install-software version=9.1.0
Context Example
{
"PANOS": {
"InstallStatus": {
"Summary": [
{
"hostid": "1111111111111",
"started": true
},
{
"hostid": "192.168.1.145",
"started": true
}
]
}
}
}
Human Readable Output
PAN-OS Software Install request Status
hostid started 1111111111111 true 192.168.1.145 true
pan-os-hygiene-check-log-forwarding
Checks that at least one log forwarding profile is configured according to best practices.
Base Command
pan-os-hygiene-check-log-forwarding
Input
| Argument Name | Description | Required |
|---|---|---|
| device_filter_string | String by which to filter so that only the given device is checked. | Optional |
Context Output
| Path | Type | Description |
|---|---|---|
| PANOS.ConfigurationHygiene.Summary.description | String | The description of the hygiene check. |
| PANOS.ConfigurationHygiene.Summary.issue_code | String | The shorthand code for this hygiene check. |
| PANOS.ConfigurationHygiene.Summary.result | String | Whether the check passed or failed. |
| PANOS.ConfigurationHygiene.Summary.issue_count | Number | Total number of matching issues. |
| PANOS.ConfigurationHygiene.Result.hostid | String | Host ID. |
| PANOS.ConfigurationHygiene.Result.container_name | String | The parent container (DG, Template, VSYS) this object belongs to. |
| PANOS.ConfigurationHygiene.Result.issue_code | String | The shorthand code for the issue. |
| PANOS.ConfigurationHygiene.Result.description | String | Human readable description of the issue. |
| PANOS.ConfigurationHygiene.Result.name | String | The affected object name. |
Command example
#### Context Example
```json
{
"PANOS": {
"ConfigurationHygiene": {
"Result": [
{
"container_name": "LAB",
"description": "Log forwarding profile missing log type 'threat'.",
"hostid": "192.168.1.145",
"issue_code": "BP-V-2",
"name": "test_fwd_profile-1"
},
{
"container_name": "LAB",
"description": "Log forwarding profile missing log type 'threat'.",
"hostid": "192.168.1.145",
"issue_code": "BP-V-2",
"name": "test_fwd_profile-1-1"
},
{
"container_name": "shared",
"description": "Log forwarding profile missing log type 'threat'.",
"hostid": "192.168.1.145",
"issue_code": "BP-V-2",
"name": "test_fwd_profile"
}
],
"Summary": [
{
"description": "Fails if there are no valid log forwarding profiles configured.",
"issue_code": "BP-V-1",
"issue_count": 0,
"result": "\u2714\ufe0f"
},
{
"description": "Fails if the configured log forwarding profile has no match list.",
"issue_code": "BP-V-2",
"issue_count": 3,
"result": "\u274c"
},
{
"description": "Fails if enhanced application logging is not configured.",
"issue_code": "BP-V-3",
"issue_count": 0,
"result": "\u2714\ufe0f"
}
]
}
}
}
Human Readable Output
PAN-OS Configuration Hygiene Check
description issue_code issue_count result Fails if there are no valid log forwarding profiles configured. BP-V-1 0 ✔️ Fails if the configured log forwarding profile has no match list. BP-V-2 3 ❌ Fails if enhanced application logging is not configured. BP-V-3 0 ✔️
pan-os-hygiene-check-vulnerability-profiles
Checks the configured vulnerability profiles to ensure at least one meets best practices.
Base Command
pan-os-hygiene-check-vulnerability-profiles
Input
| Argument Name | Description | Required |
|---|---|---|
| device_filter_string | String by which to filter so that only the given device is checked. | Optional |
| minimum_block_severities | Comma-separated list of severities that must be in drop/reset/block-ip mode. Default is critical,high. | Optional |
| minimum_alert_severities | Comma-separated list of severities that must be in alert/default or higher mode. Default is medium,low. | Optional |
Context Output
| Path | Type | Description |
|---|---|---|
| PANOS.ConfigurationHygiene.Summary.description | String | The description of the hygiene check. |
| PANOS.ConfigurationHygiene.Summary.issue_code | String | The shorthand code for this hygiene check. |
| PANOS.ConfigurationHygiene.Summary.result | String | Whether the check passed or failed. |
| PANOS.ConfigurationHygiene.Summary.issue_count | Number | Total number of matching issues. |
| PANOS.ConfigurationHygiene.Result.hostid | String | Host ID. |
| PANOS.ConfigurationHygiene.Result.container_name | String | The parent container (DG, Template, VSYS) this object belongs to. |
| PANOS.ConfigurationHygiene.Result.issue_code | String | The shorthand code for the issue. |
| PANOS.ConfigurationHygiene.Result.description | String | Human readable description of the issue. |
| PANOS.ConfigurationHygiene.Result.name | String | The affected object name. |
Command example
#### Context Example
```json
{
"PANOS": {
"ConfigurationHygiene": {
"Summary": [
{
"description": "Fails if no vulnerability profile is configured for visibility.",
"issue_code": "BP-V-4",
"issue_count": 0,
"result": "\u2714\ufe0f"
}
]
}
}
}
Human Readable Output
PAN-OS Configuration Hygiene Check
description issue_code issue_count result Fails if no vulnerability profile is configured for visibility. BP-V-4 0 ✔️
pan-os-hygiene-check-spyware-profiles
Checks the configured Anti-spyware profiles to ensure at least one meets best practices.
Base Command
pan-os-hygiene-check-spyware-profiles
Input
| Argument Name | Description | Required |
|---|---|---|
| device_filter_string | String to filter to only check given devices. | Optional |
| minimum_block_severities | csv list of severities that must be in drop/reset/block-ip mode. Default is critical,high. | Optional |
| minimum_alert_severities | csv list of severities that must be in alert/default or higher mode. Default is medium,low. | Optional |
Context Output
| Path | Type | Description |
|---|---|---|
| PANOS.ConfigurationHygiene.Summary.description | String | The description of the check |
| PANOS.ConfigurationHygiene.Summary.issue_code | String | The shorthand code for this hygiene check |
| PANOS.ConfigurationHygiene.Summary.result | String | Whether the check passed or failed |
| PANOS.ConfigurationHygiene.Summary.issue_count | String | Total number of matching issues |
| PANOS.ConfigurationHygiene.Result.hostid | String | Host ID. |
| PANOS.ConfigurationHygiene.Result.container_name | String | What parent container (DG, Template, VSYS) this object belongs to. |
| PANOS.ConfigurationHygiene.Result.issue_code | String | The shorthand code for the issue |
| PANOS.ConfigurationHygiene.Result.description | String | Human readable description of issue |
| PANOS.ConfigurationHygiene.Result.name | String | The affected object name |
Command example
#### Context Example
```json
{
"PANOS": {
"ConfigurationHygiene": {
"Summary": [
{
"description": "Fails if no spyware profile is configured for visibility.",
"issue_code": "BP-V-5",
"issue_count": 0,
"result": "\u2714\ufe0f"
}
]
}
}
}
Human Readable Output
PAN-OS Configuration Hygiene Check
description issue_code issue_count result Fails if no spyware profile is configured for visibility. BP-V-5 0 ✔️
pan-os-hygiene-check-url-filtering-profiles
Checks the configured URL Filtering profiles to ensure at least one meets best practices.
Base Command
pan-os-hygiene-check-url-filtering-profiles
Input
| Argument Name | Description | Required |
|---|---|---|
| device_filter_string | String to filter to only check given device. | Optional |
Context Output
| Path | Type | Description |
|---|---|---|
| PANOS.ConfigurationHygiene.Summary.description | String | The description of the check |
| PANOS.ConfigurationHygiene.Summary.issue_code | String | The shorthand code for this hygiene check |
| PANOS.ConfigurationHygiene.Summary.result | String | Whether the check passed or failed |
| PANOS.ConfigurationHygiene.Summary.issue_count | String | Total number of matching issues |
| PANOS.ConfigurationHygiene.Result.hostid | String | Host ID. |
| PANOS.ConfigurationHygiene.Result.container_name | String | What parent container (DG, Template, VSYS) this object belongs to. |
| PANOS.ConfigurationHygiene.Result.issue_code | String | The shorthand code for the issue |
| PANOS.ConfigurationHygiene.Result.description | String | Human readable description of issue |
| PANOS.ConfigurationHygiene.Result.name | String | The affected object name |
Command example
#### Context Example
```json
{
"PANOS": {
"ConfigurationHygiene": {
"Summary": [
{
"description": "Fails if no spyware profile is configured for url-filtering",
"issue_code": "BP-V-6",
"issue_count": 0,
"result": "\u2714\ufe0f"
}
]
}
}
}
Human Readable Output
PAN-OS Configuration Hygiene Check
description issue_code issue_count result Fails if no spyware profile is configured for url-filtering BP-V-6 0 ✔️
pan-os-hygiene-conforming-url-filtering-profiles
Returns a list of existing PANOS URL filtering objects that conform to best practices.
Base Command
pan-os-hygiene-conforming-url-filtering-profiles
Input
| Argument Name | Description | Required |
|---|---|---|
| device_filter_string | String to filter to only check given device. | Optional |
Context Output
| Path | Type | Description |
|---|---|---|
| PANOS.PanosObject.hostid | String | Host ID. |
| PANOS.PanosObject.container_name | String | What parent container (DG, Template, VSYS) this object belongs to. |
| PANOS.PanosObject.name | String | The PAN-OS object name |
| PANOS.PanosObject.object_type | String | The PAN-OS-Python object type |
Command example
#### Context Example
```json
{
"PANOS": {
"PanosObject": [
{
"container_name": "shared",
"hostid": "192.168.1.145",
"name": "Outbound-URL",
"object_type": "URLFilteringProfile"
},
{
"container_name": "shared",
"hostid": "192.168.1.145",
"name": "Exception-URL",
"object_type": "URLFilteringProfile"
}
]
}
}
Human Readable Output
PAN-OS Objects
container_name hostid name object_type shared 192.168.1.145 Outbound-URL URLFilteringProfile shared 192.168.1.145 Exception-URL URLFilteringProfile
pan-os-hygiene-conforming-spyware-profiles
Returns all Anti-spyware profiles that conform to best practices.
Base Command
pan-os-hygiene-conforming-spyware-profiles
Input
| Argument Name | Description | Required |
|---|---|---|
| device_filter_string | String to filter to only check given device. | Optional |
| minimum_block_severities | csv list of severities that must be in drop/reset/block-ip mode. Default is critical,high. | Optional |
| minimum_alert_severities | csv list of severities that must be in alert/default or higher mode. Default is medium,low. | Optional |
Context Output
| Path | Type | Description |
|---|---|---|
| PANOS.PanosObject.hostid | String | Host ID. |
| PANOS.PanosObject.container_name | String | What parent container (DG, Template, VSYS) this object belongs to. |
| PANOS.PanosObject.name | String | The PAN-OS object name |
| PANOS.PanosObject.object_type | String | The PAN-OS-Python object type |
Command example
#### Context Example
```json
{
"PANOS": {
"PanosObject": [
{
"container_name": "shared",
"hostid": "192.168.1.145",
"name": "Outbound-AS",
"object_type": "AntiSpywareProfile"
},
{
"container_name": "shared",
"hostid": "192.168.1.145",
"name": "Inbound-AS",
"object_type": "AntiSpywareProfile"
},
{
"container_name": "shared",
"hostid": "192.168.1.145",
"name": "Internal-AS",
"object_type": "AntiSpywareProfile"
}
]
}
}
Human Readable Output
PAN-OS Objects
container_name hostid name object_type shared 192.168.1.145 Outbound-AS AntiSpywareProfile shared 192.168.1.145 Inbound-AS AntiSpywareProfile shared 192.168.1.145 Internal-AS AntiSpywareProfile
pan-os-hygiene-conforming-vulnerability-profiles
Returns all Vulnerability profiles that conform to best practices.
Base Command
pan-os-hygiene-conforming-vulnerability-profiles
Input
| Argument Name | Description | Required |
|---|---|---|
| device_filter_string | String to filter to only check given device. | Optional |
| minimum_block_severities | csv list of severities that must be in drop/reset/block-ip mode. Default is critical,high. | Optional |
| minimum_alert_severities | csv list of severities that must be in alert/default or higher mode. Default is medium,low. | Optional |
Context Output
| Path | Type | Description |
|---|---|---|
| PANOS.PanosObject.hostid | String | Host ID. |
| PANOS.PanosObject.container_name | String | What parent container (DG, Template, VSYS) this object belongs to. |
| PANOS.PanosObject.name | String | The PAN-OS object name |
| PANOS.PanosObject.object_type | String | The PAN-OS-Python object type |
Command example
#### Context Example
```json
{
"PANOS": {
"PanosObject": [
{
"container_name": "shared",
"hostid": "192.168.1.145",
"name": "Outbound-VP",
"object_type": "VulnerabilityProfile"
},
{
"container_name": "shared",
"hostid": "192.168.1.145",
"name": "Inbound-VP",
"object_type": "VulnerabilityProfile"
},
{
"container_name": "shared",
"hostid": "192.168.1.145",
"name": "Internal-VP",
"object_type": "VulnerabilityProfile"
}
]
}
}
Human Readable Output
PAN-OS Objects
container_name hostid name object_type shared 192.168.1.145 Outbound-VP VulnerabilityProfile shared 192.168.1.145 Inbound-VP VulnerabilityProfile shared 192.168.1.145 Internal-VP VulnerabilityProfile
pan-os-hygiene-check-security-zones
Check configured security zones have correct settings.
Base Command
pan-os-hygiene-check-security-zones
Input
| Argument Name | Description | Required |
|---|---|---|
| device_filter_string | String to filter to only check given device. | Optional |
Context Output
| Path | Type | Description |
|---|---|---|
| PANOS.ConfigurationHygiene.Summary.description | String | The description of the check |
| PANOS.ConfigurationHygiene.Summary.issue_code | String | The shorthand code for this hygiene check |
| PANOS.ConfigurationHygiene.Summary.result | String | Whether the check passed or failed |
| PANOS.ConfigurationHygiene.Summary.issue_count | String | Total number of matching issues |
| PANOS.ConfigurationHygiene.Result.hostid | String | Host ID. |
| PANOS.ConfigurationHygiene.Result.container_name | String | What parent container (DG, Template, VSYS) this object belongs to. |
| PANOS.ConfigurationHygiene.Result.issue_code | String | The shorthand code for the issue |
| PANOS.ConfigurationHygiene.Result.description | String | Human readable description of issue |
| PANOS.ConfigurationHygiene.Result.name | String | The affected object name |
Command example
#### Context Example
```json
{
"PANOS": {
"ConfigurationHygiene": {
"Result": [
{
"container_name": "LAB",
"description": "Security zone has no log forwarding setting.",
"hostid": "192.168.1.145",
"issue_code": "BP-V-7",
"name": "TEST_ZONE"
}
],
"Summary": [
{
"description": "Fails when a security zone has no log forwarding setting.",
"issue_code": "BP-V-7",
"issue_count": 1,
"result": "\u274c"
}
]
}
}
}
Human Readable Output
PAN-OS Configuration Hygiene Check
description issue_code issue_count result Fails when a security zone has no log forwarding setting. BP-V-7 1 ❌
pan-os-hygiene-check-security-rules
Check security rules are configured correctly.
Base Command
pan-os-hygiene-check-security-rules
Input
| Argument Name | Description | Required |
|---|---|---|
| device_filter_string | String to filter to only check given device. | Optional |
Context Output
| Path | Type | Description |
|---|---|---|
| PANOS.ConfigurationHygiene.Summary.description | String | The description of the check |
| PANOS.ConfigurationHygiene.Summary.issue_code | String | The shorthand code for this hygiene check |
| PANOS.ConfigurationHygiene.Summary.result | String | Whether the check passed or failed |
| PANOS.ConfigurationHygiene.Summary.issue_count | String | Total number of matching issues |
| PANOS.ConfigurationHygiene.Result.hostid | String | Host ID. |
| PANOS.ConfigurationHygiene.Result.container_name | String | What parent container (DG, Template, VSYS) this object belongs to. |
| PANOS.ConfigurationHygiene.Result.issue_code | String | The shorthand code for the issue |
| PANOS.ConfigurationHygiene.Result.description | String | Human readable description of issue |
| PANOS.ConfigurationHygiene.Result.name | String | The affected object name |
Command example
#### Context Example
```json
{
"PANOS": {
"ConfigurationHygiene": {
"Result": [
{
"container_name": "shared",
"description": "Security rule is not configured to log at session end.",
"hostid": "192.168.1.145",
"issue_code": "BP-V-8",
"name": "Test-webapp-rule"
},
{
"container_name": "shared",
"description": "Security rule has no log forwarding profile.",
"hostid": "192.168.1.145",
"issue_code": "BP-V-9",
"name": "Test-webapp-rule"
},
{
"container_name": "shared",
"description": "Security rule has no profile group or configured threat profiles.",
"hostid": "192.168.1.145",
"issue_code": "BP-V-10",
"name": "Test-webapp-rule"
}
],
"Summary": [
{
"description": "Fails when a security rule is not configured to log at session end.",
"issue_code": "BP-V-8",
"issue_count": 1,
"result": "\u274c"
},
{
"description": "Fails when a security rule has no log forwarding profile configured.",
"issue_code": "BP-V-9",
"issue_count": 1,
"result": "\u274c"
},
{
"description": "Fails when a security rule has no configured profiles or profile groups.",
"issue_code": "BP-V-10",
"issue_count": 1,
"result": "\u274c"
}
]
}
}
}
Human Readable Output
PAN-OS Configuration Hygiene Check
description issue_code issue_count result Fails when a security rule is not configured to log at session end. BP-V-8 1 ❌ Fails when a security rule has no log forwarding profile configured. BP-V-9 1 ❌ Fails when a security rule has no configured profiles or profile groups. BP-V-10 1 ❌
pan-os-hygiene-fix-log-forwarding
Fix log forwarding issues identified by pan-os-hygiene-check-log-forwarding.
Base Command
pan-os-hygiene-fix-log-forwarding
Input
| Argument Name | Description | Required |
|---|---|---|
| issue | Dictionary of Hygiene issue, from a hygiene check command. Can be a list. | Required |
Context Output
| Path | Type | Description |
|---|---|---|
| PANOS.ConfigurationHygieneFix.hostid | String | Host ID |
| PANOS.ConfigurationHygieneFix.container_name | String | What parent container (DG, Template, VSYS) this object belongs to. |
| PANOS.ConfigurationHygieneFix.issue_code | String | The shorthand code for the issue |
| PANOS.ConfigurationHygieneFix.description | String | Human readable description of issue |
| PANOS.ConfigurationHygieneFix.name | String | The affected object name |
Command example
!pan-os-hygiene-fix-log-forwarding issue=${PANOS.ConfigurationHygiene.Result}
Context Example
{
"PANOS": {
"ConfigurationHygieneFix": [
{
"container_name": "LAB",
"description": "Enabled Enhanced Application Logging.",
"hostid": "192.168.1.145",
"issue_code": "BP-V-2",
"name": "test_fwd_profile-1"
}
]
}
}
pan-os-hygiene-fix-security-zone-log-settings
Fixes security zones that are configured without a valid log forwarding profile.
Base Command
pan-os-hygiene-fix-security-zone-log-settings
Input
| Argument Name | Description | Required |
|---|---|---|
| issue | Dictionary of Hygiene issue, from a hygiene check command. Can be a list. | Required |
| log_forwarding_profile_name | Name of log forwarding profile to set. | Required |
Context Output
| Path | Type | Description |
|---|---|---|
| PANOS.ConfigurationHygieneFix.hostid | String | Host ID |
| PANOS.ConfigurationHygieneFix.container_name | String | What parent container (DG, Template, VSYS) this object belongs to. |
| PANOS.ConfigurationHygieneFix.issue_code | String | The shorthand code for the issue |
| PANOS.ConfigurationHygieneFix.description | String | Human readable description of issue |
| PANOS.ConfigurationHygieneFix.name | String | The affected object name |
Command example
!pan-os-hygiene-fix-security-zone-log-settings issue=${PANOS.ConfigurationHygiene.Result} log_forwarding_profile_name="test-fwd-profile"
Context Example
{
"PANOS": {
"ConfigurationHygieneFix": [
{
"container_name": "LAB",
"description": "Set log forwarding profile test-fwd-profile",
"hostid": "192.168.1.145",
"issue_code": "BP-V-7",
"name": "TEST_ZONE"
}
]
}
}
pan-os-hygiene-fix-security-rule-log-settings
Fixed security rules that have incorrect log settings by adding a log forwarding profile and setting
Base Command
pan-os-hygiene-fix-security-rule-log-settings
Input
| Argument Name | Description | Required |
|---|---|---|
| issue | Dictionary of Hygiene issue, from a hygiene check command. Can be list. | Required |
| log_forwarding_profile_name | Name of log forwarding profile to use as log setting. | Required |
Context Output
| Path | Type | Description |
|---|---|---|
| PANOS.ConfigurationHygieneFix.hostid | String | Host ID |
| PANOS.ConfigurationHygieneFix.container_name | String | What parent container (DG, Template, VSYS) this object belongs to. |
| PANOS.ConfigurationHygieneFix.issue_code | String | The shorthand code for the issue |
| PANOS.ConfigurationHygieneFix.description | String | Human readable description of issue |
| PANOS.ConfigurationHygieneFix.name | String | The affected object name |
Command example
!pan-os-hygiene-fix-security-rule-log-settings issue=${PANOS.ConfigurationHygiene.Result.[0]} log_forwarding_profile_name="test-fwd-profile""
Context Example
{
"PANOS": {
"ConfigurationHygieneFix": [
{
"container_name": "shared",
"description": "Set log forwarding profile to test-fwd-profile-3 andenabled log at session end.",
"hostid": "192.168.1.145",
"issue_code": "BP-V-8",
"name": "Test-webapp-rule"
}
]
}
}
pan-os-hygiene-fix-security-rule-profile-settings
Fixed security rules that have incorrect log settings by adding a log forwarding profile and setting
Base Command
pan-os-hygiene-fix-security-rule-profile-settings
Input
| Argument Name | Description | Required |
|---|---|---|
| issue | Dictionary of Hygiene issue, from a hygiene check command. | Required |
| security_profile_group_name | Name of Security profile group to use as log setting. | Required |
Context Output
| Path | Type | Description |
|---|---|---|
| PANOS.ConfigurationHygieneFix.hostid | String | Host ID |
| PANOS.ConfigurationHygieneFix.container_name | String | What parent container (DG, Template, VSYS) this object belongs to. |
| PANOS.ConfigurationHygieneFix.issue_code | String | The shorthand code for the issue |
| PANOS.ConfigurationHygieneFix.description | String | Human readable description of issue |
| PANOS.ConfigurationHygieneFix.name | String | The affected object name |
Command example
!pan-os-hygiene-fix-security-rule-log-settings issue=${PANOS.ConfigurationHygiene.Result.[0]} log_forwarding_profile_name="test-fwd-profile""
Context Example
{
"PANOS": {
"ConfigurationHygieneFix": [
{
"container_name": "shared",
"description": "Set security profile group Alert-Only",
"hostid": "192.168.1.145",
"issue_code": "BP-V-10",
"name": "Test-webapp-rule"
}
]
}
}
pan-os-config-get-object
Searches and returns a reference for the given object type and name. If no name is provided, all objects of the given type will be returned.
Base Command
pan-os-config-get-object
Input
| Argument Name | Description | Required |
|---|---|---|
| object_type | The type of object to search; see https://pandevice.readthedocs.io/en/latest/module-objects.html. Possible values are: AddressObject, AddressGroup, ServiceGroup, ServiceObject, ApplicationObject, ApplicationGroup, LogForwardingProfile, SecurityProfileGroup. | Required |
| device_filter_string | If provided, only objects from the given device are returned. | Optional |
| object_name | The name of the object reference to return if looking for a specific object. Supports regex if “use_regex” is set. | Optional |
| parent | The parent vsys or device group to search. If not provided, all will be returned. | Optional |
| use_regex | Enables regex matching on object name. | Optional |
Context Output
| Path | Type | Description |
|---|---|---|
| PANOS.PanosObject.hostid | String | Host ID. |
| PANOS.PanosObject.container_name | String | The parent container (DG, Template, VSYS) this object belongs to. |
| PANOS.PanosObject.name | String | The PAN-OS object name. |
| PANOS.PanosObject.object_type | String | The PAN-OS python object type. |
Command example
!pan-os-config-get-object object_type="AddressObject"
Context Example
{
"PANOS": {
"PanosObject": [
{
"container_name": "shared",
"hostid": "192.168.1.145",
"name": "Sinkhole-IPv4",
"object_type": "AddressObject"
},
{
"container_name": "shared",
"hostid": "192.168.1.145",
"name": "Sinkhole-IPv6",
"object_type": "AddressObject"
},
{
"container_name": "shared",
"hostid": "192.168.1.145",
"name": "test-shared",
"object_type": "AddressObject"
}
]
}
}
Human Readable Output
PAN-OS Objects
container_name hostid name object_type shared 192.168.1.145 Sinkhole-IPv4 AddressObject shared 192.168.1.145 Sinkhole-IPv6 AddressObject shared 192.168.1.145 test-shared AddressObject
pan-os-platform-get-device-state
Get the device state from the provided device. Note; This will attempt to connect directly to the provided target to get the device state. If the IP address as reported in “show system info” is unreachable, this command will fail.
Base Command
pan-os-platform-get-device-state
Input
| Argument Name | Description | Required |
|---|---|---|
| target | Serial number of the device from which to fetch the device state. | Required |
| filename | Name of the file for the state file to be saved. Default will use the hostname as the filename. | Optional |
| ip_address | The IP Address of a Panorama managed firewall. Default will use Panorama-supplied IP Address. | Optional |
Context Output
| Path | Type | Description |
|---|---|---|
| InfoFile.Name | String | Filename. |
| InfoFile.EntryID | String | Entry ID. |
| InfoFile.Size | String | Size of the file. |
| InfoFile.Type | String | Type of the file. |
| InfoFile.Info | String | Basic information of the file. |
pan-os-push-to-template
Pushes the given PAN-OS template to the given devices or all devices that belong to the template.
Base Command
pan-os-push-to-template
Input
| Argument Name | Description | Required |
|---|---|---|
| template | The template to push. | Optional |
| validate-only | Whether to validate the policy. Possible values are: true, false. Default is false. | Optional |
| description | The push description. | Optional |
| serial_number | The serial number for a virtual system commit. If provided, the commit will be a virtual system commit. | Optional |
Context Output
| Path | Type | Description |
|---|---|---|
| Panorama.Push.Template | String | The device group in which the policies were pushed. |
| Panorama.Push.JobID | Number | The job ID of the policies that were pushed. |
| Panorama.Push.Status | String | The push status. |
| Panorama.Push.Warnings | String | The push warnings. |
| Panorama.Push.Errors | String | The push errors. |
Command example
!pan-os-push-to-template template=LAB
Context Example
{
"Panorama": {
"Push": {
"JobID": "564",
"Status": "Pending",
"Template": "LAB"
}
}
}
Human Readable Output
Push to Template
JobID Status 564 Pending
pan-os-push-to-template-stack
Pushes the given PAN-OS template-stack to the given devices or all devices that belong to the template stack.
Base Command
pan-os-push-to-template-stack
Input
| Argument Name | Description | Required |
|---|---|---|
| template-stack | The template-stack to push. | Required |
| validate-only | Whether to validate the policy. Possible values are: true, false. Default is false. | Optional |
| description | The push description. | Optional |
| serial_number | The serial number for a virtual system commit. If provided, the commit will be a virtual system commit. | Optional |
Context Output
| Path | Type | Description |
|---|---|---|
| Panorama.Push.TemplateStack | String | The device group in which the policies were pushed. |
| Panorama.Push.JobID | Number | The job ID of the policies that were pushed. |
| Panorama.Push.Status | String | The push status. |
| Panorama.Push.Warnings | String | The push warnings. |
| Panorama.Push.Errors | String | The push errors. |
Command example
!pan-os-push-to-template-stack template-stack=LAB-STACK
Context Example
{
"Panorama": {
"Push": {
"JobID": "565",
"Status": "Pending",
"TemplateStack": "LAB-STACK"
}
}
}
Human Readable Output
Push to Template
JobID Status 565 Pending
pan-os-get-running-config
Pull the running config file
Base Command
pan-os-get-running-config
Input
| Argument Name | Description | Required |
|---|---|---|
| target | The target device. | Optional |
Context Output
There is no context output for this command.
Command example
!pan-os-get-running-config target=00000000000
Context Example
{
"File": {
"EntryID": "3678@268ee30b-69fa-4496-8ab8-51cdeb19c452",
"Info": "text/plain",
"MD5": "da7faf4c6440d87a3e50ef93536ed81a",
"Name": "running_config",
"SHA1": "7910271adc8b3e9de28b804442a11a5160d4adda",
"SHA256": "a4da4cbee7f3e411fbf76f2595d7dfcffce85bd6b3c000dac7a17e58747d1a2b",
"SHA512": "e90d995061b5771f068c07e727ece3b57eeabdac424dabe8f420848e482e2ad18411c030bd4b455f589d8cdae9a1dae942bfef1ebd038104dd975e168cfb7d19",
"SSDeep": "3072:KGH5vDQ4MEa4fM0EYRCmgQKQZyVlxgW0ITUj4MO2jCKH2:ZLMGyQKQZaw2",
"Size": 1284823,
"Type": "ASCII text, with very long lines"
}
}
pan-os-get-merged-config
Pull the merged config file
Base Command
pan-os-get-merged-config
Input
| Argument Name | Description | Required |
|---|---|---|
| target | The serial number of the device. | Optional |
Context Output
There is no context output for this command.
Command example
!pan-os-get-merged-config target=0000000000
Context Example
{
"File": {
"EntryID": "3682@268ee30b-69fa-4496-8ab8-51cdeb19c452",
"Info": "text/plain",
"MD5": "3204cc188e4b4a6616b449441d4d1ad4",
"Name": "merged_config",
"SHA1": "0b058a2ae4b595f80599ef0aeffda640ff386e95",
"SHA256": "7178b16cb30880c93345ff80810af4e1428573a28d1ee354d5c79b03372cc027",
"SHA512": "edf5b851eab40588e4e338071de3c18cc8d198d811ea0759670c0aa4c8028fa3b7870b9554c4b7d85f8429641d7cd6f6217a6b37500e24ad9c60b6cf39b39f3b",
"SSDeep": "3072:OGH5vDQ4MEa4fM0EYRCmgQKQZyVlxDW0ITUj4MO2jCKH2:tLMGyQKQZtw2",
"Size": 1322335,
"Type": "ASCII text, with very long lines"
}
}
pan-os-list-templates
Returns a list of available templates. (Used only in Panorama instances).
Base Command
pan-os-list-templates
Input
| Argument Name | Description | Required |
|---|---|---|
| template_name | The name of the template to retrieve. If not provided then all available templates will be brought. | Optional |
| limit | The maximum number of templates to retrieve. This value will be used by default if page argument was not provided. Default is 50. | Optional |
| page_size | The page size of the templates to return. Default is 50. | Optional |
| page | The page at which to start listing templates. This must be a positive number. | Optional |
Context Output
| Path | Type | Description |
|---|---|---|
| Panorama.Template.Name | String | The name of the template. |
| Panorama.Template.Description | String | The description of the template. |
| Panorama.Template.Variable.Name | String | The variable name of the template. |
| Panorama.Template.Variable.Type | String | The type of the template. |
| Panorama.Template.Variable.Value | String | The value of the variable of the template. |
| Panorama.Template.Variable.Description | String | The description of the variable of the template. |
Command example
!pan-os-list-templates limit=20
Context Example
{
"Panorama": {
"Template": [
{
"Description": null,
"Name": "test-1",
"Variable": []
},
{
"Description": "test description",
"Name": "test-2",
"Variable": [
{
"Description": "variable-1-test",
"Name": "$variable-1",
"Type": "ip-netmask",
"Value": "1.1.1.1"
},
{
"Description": null,
"Name": "$variable-2",
"Type": "fqdn",
"Value": "google.com"
}
]
}
]
}
}
Human Readable Output
Templates
Description Name Variable test-1 test description test-2 $variable-1,
$variable-2
pan-os-list-nat-rules
Returns a list of NAT rules of either a Panorama/firewall instance.
Base Command
pan-os-list-nat-rules
Input
| Argument Name | Description | Required |
|---|---|---|
| name | The name of the NAT rule to retrieve. If not mentioned, will bring all the NAT rules. | Optional |
| device-group | The device group in which the NAT rules are part of. | Optional |
| pre_post | The pre-rule or post-rule (Panorama instances only). Possible values are: pre-rulebase, post-rulebase. | Optional |
| show_uncommitted | Whether to show the un-committed rules or not. Possible values are: true, false. Default is false. | Optional |
| disabled | Whether to retrieve the disabled rules. If not mentioned, will retrieve all the NAT rules. Possible values are: yes, no. | Optional |
| nat_type | The type of the NAT rules to retrieve. If not mentioned, will retrieve all the NAT rules. Possible values are: ipv4, nat64, nptv6. | Optional |
| tags | A comma-separated list of tags of the NAT rules to retrieve. If not mentioned, will retrieve all the NAT rules. | Optional |
| query | Free query to retrieve NAT rule. If not mentioned, will retrieve all the NAT rules. | Optional |
| limit | The maximum number of rules to retrieve. Will be used by default if page argument was not provided. Default is 50. | Optional |
| page_size | The page size of the NAT rules to return. Default is 50. | Optional |
| page | The page at which to start listing NAT rules. Must be a positive number. | Optional |
Context Output
| Path | Type | Description |
|---|---|---|
| Panorama.NAT.Name | String | The name of the rule. |
| Panorama.NAT.Location | String | The device group that the rule is part of. |
| Panorama.NAT.Tags | String | The tags in which the rule is part of. |
| Panorama.NAT.SourceZone | String | The source zone of the rule. |
| Panorama.NAT.DestinationZone | String | The destination zone of the rule. |
| Panorama.NAT.SourceAddress | String | The source address of the rule. |
| Panorama.NAT.DestinationAddress | String | The destination address of the rule. |
| Panorama.NAT.DestinationInterface | String | The destination interface of the rule. |
| Panorama.NAT.Service | String | The service in which the rule has. |
| Panorama.NAT.Description | String | The description of the rule. |
| Panorama.NAT.SourceTranslation | Unknown | The source translation of the rule. |
| Panorama.NAT.DestinationTranslation | Unknown | The destination translation of the rule. |
| Panorama.NAT.DynamicDestinationTranslation | Unknown | The dynamic destination translation of the rule. |
| Panorama.NAT.Disabled | String | Whether the rule is disabled. |
Command example
!pan-os-list-nat-rules pre_post=pre-rulebase show_uncommitted=true
Context Example
{
"Panorama": {
"NAT": [
{
"Description": "Test",
"DestinationAddress": "Test_Bla_Bla",
"DestinationInterface": "any",
"DestinationTranslation": {
"TranslatedAddress": "1.1.1.1/24",
"TranslatedPort": "1234"
},
"DestinationZone": "Admin",
"Disabled": "yes",
"DynamicDestinationTranslation": null,
"Name": "Test",
"Service": "Test_group",
"SourceAddress": "bad-url.com",
"SourceTranslation": {
"StaticIp": {
"TranslatedAddress": "1.2.3.4"
}
},
"SourceZone": "any",
"Tags": null
},
{
"Description": "Desc",
"DestinationAddress": "Test_Bla_Bla",
"DestinationInterface": "any",
"DestinationTranslation": null,
"DestinationZone": "Admin",
"Disabled": "yes",
"DynamicDestinationTranslation": {
"DistributionMethod": "ip-hash",
"TranslatedAddress": "bad-url.com"
},
"Name": "Test",
"Service": "XSOAR_Test",
"SourceAddress": "bad-url.com",
"SourceTranslation": null,
"SourceZone": [
"Admin",
"Bla"
],
"Tags": [
"test",
"tag"
]
}
]
}
}
Human Readable Output
Nat Policy Rules
Name Tags Source Zone Destination Zone Source Address Disabled Destination Address Destination Interface Service Description Test any Admin bad-url.com yes Test_Bla_Bla any Test_group Test Test test,
tagAdmin,
multicastAdmin bad-url.com yes Test_Bla_Bla any XSOAR_Test Desc
pan-os-create-nat-rule
Creates a new NAT rule in a Panorama/firewall instance.
Base Command
pan-os-create-nat-rule
Input
| Argument Name | Description | Required |
|---|---|---|
| rulename | The name of the NAT rule to create. | Required |
| description | The description that the new NAT rule should have. | Optional |
| device-group | The device-group in which the new rule should be created (Panorama instances only). | Optional |
| pre_post | The pre-rule or post-rule (Panorama instances only). Possible values are: pre-rulebase, post-rulebase. | Optional |
| nat_type | The NAT type in which the rule will be created. Possible values are: ipv4, nat64, nptv6. Default is ipv4. | Optional |
| source_zone | A comma-separated list of source zones. Default is any. | Optional |
| destination_zone | A comma-separated list of destination zones. | Optional |
| destination_interface | The page at which to start listing nat-rules, must be a positive number. Default is any. | Optional |
| service | The service in which the rule will be created with. Default is any. | Optional |
| source_address | A comma-separated list of address object names, address group object names, or EDL object names. Default is any. | Optional |
| destination_address | A comma-separated list of address object names, address group object names, or EDL object names. Default is any. | Optional |
| source_translation_type | The source translation type in which the rule will be created. Possible values are: static-ip, dynamic-ip, dynamic-ip-and-port, none. Default is none. | Optional |
| source_translated_address_type | The source translation address type in which the rule will be created. Possible values are: translated-address, interface-address. Default is translated-address. | Optional |
| source_translated_address | A comma-separated list of source translation addresses. If source_translation_type == static_ip, must be a single value. | Optional |
| source_translated_interface | The source translation interface. | Optional |
| destination_translation_type | The destination translation type. Possible values are: static_ip, dynamic_ip, none. Default is none. | Optional |
| destination_translated_address | A comma-separated list of destination translated addresses. | Optional |
| destination_translated_port | The destination translated port. | Optional |
| destination_translation_distribution_method | The destination translation distribution method. Possible values are: round-robin, source-ip-hash, ip-modulo, ip-hash, least-sessions. | Optional |
| negate_destination | Whether to use negate destination. Possible values are: yes, no. | Optional |
| destination_dns_rewrite_direction | The DNS rewrite direction. Possible values are: forward, reverse. | Optional |
| audit_comment | An audit comment for the rule. | Optional |
Context Output
There is no context output for this command.
Command example
!pan-os-create-nat-rule rulename=test pre_post="pre-rulebase" source_translated_address_type="interface-address" source_translated_interface=a2 source_translation_type="dynamic-ip-and-port" destination_translation_type=dynamic_ip destination_translated_address=1.1.1.1
Human Readable Output
Nat rule test was created successfully.
pan-os-delete-nat-rule
Deletes a NAT rule.
Base Command
pan-os-delete-nat-rule
Input
| Argument Name | Description | Required |
|---|---|---|
| rulename | The name of the NAT rule to delete. Can be retrieved from the pan-os-list-nat-rules command. | Optional |
| device-group | The device-group from which the NAT rule should be deleted. Only for a Panorama instance. | Optional |
| pre_post | The pre-rule or post-rule (Panorama instances only). Possible values are: pre-rulebase, post-rulebase. | Optional |
Context Output
There is no context output for this command.
Command example
!pan-os-delete-nat-rule rulename=test pre_post="pre-rulebase"
Human Readable Output
Nat rule test was deleted successfully.
pan-os-edit-nat-rule
Edits a NAT rule.
Base Command
pan-os-edit-nat-rule
Input
| Argument Name | Description | Required |
|---|---|---|
| rulename | The name of the NAT rule to edit. Can be retrieved from the pan-os-list-nat-rules command. | Required |
| device-group | The device-group that the NAT rule is part of. (Panorama instances only). | Optional |
| pre_post | The pre rule or post rule (Panorama instances only). Possible values are: pre-rulebase, post-rulebase. | Optional |
| behavior | The operation to perform on the rule. Possible values are: replace, add, remove. Default is replace. | Optional |
| element_to_change | The element to change. Possible values are: tags, service, nat_type, description, source_zone, destination_zone, source_address, destination_address, destination_interface, negate_destination, source_translation_dynamic_ip_and_port, source_translation_interface, source_translation_dynamic_ip, source_translation_static_ip, destination_translation_port, destination_translation_ip, destination_translation_dynamic_port, destination_translation_dynamic_ip, destination_translation_dynamic_distribution_method, disabled, audit-comment. | Required |
| element_value | The value of the element to change. Can be a list for certain elements. | Required |
Context Output
There is no context output for this command.
Command example
!pan-os-edit-nat-rule rulename=test element_to_change=source_translation_static_ip behavior=replace pre_post="pre-rulebase" element_value=3.3.3.3
Human Readable Output
Nat rule test was edited successfully.
pan-os-list-virtual-routers
Returns a list of virtual routers of either a Panorama/firewall instance.
Base Command
pan-os-list-virtual-routers
Input
| Argument Name | Description | Required |
|---|---|---|
| virtual_router | The name of the virtual router to retrieve. If not mentioned, will bring all the virtual routers. | Optional |
| template | The template that the virtual router is part of. Use only for Panorama instances. | Optional |
| show_uncommitted | Whether to show the un-committed virtual routers or not. Possible values are: true, false. Default is false. | Optional |
| limit | The maximum number of virtual routers to retrieve. Will be used by default if the page argument was not provided. Default is 50. | Optional |
| page_size | The size of virtual-routers to return. Default is 50. | Optional |
| page | The page at which to start listing virtual-routers. Must be a positive number. | Optional |
Context Output
| Path | Type | Description |
|---|---|---|
| Panorama.VirtualRouter.Name | String | The name of the virtual router. |
| Panorama.VirtualRouter.Interface | Unknown | The interface(s) that the virtual router uses. |
| Panorama.VirtualRouter.RIP | Unknown | Information about the RIP of the virtual router. |
| Panorama.VirtualRouter.OSPF | Unknown | Information about the OSPF of the virtual router. |
| Panorama.VirtualRouter.OSPFv3 | Unknown | Information about the OSPFv3 of the virtual router. |
| Panorama.VirtualRouter.BGP | Unknown | Information about the BGP of the virtual router. |
| Panorama.VirtualRouter.RedistributionProfile | Unknown | The redistribution profile(s) that the virtual router uses. |
| Panorama.VirtualRouter.Multicast | Unknown | Information about the multicast of the virtual router. |
| Panorama.VirtualRouter.StaticRoute | Unknown | The static routes(s) that the virtual router uses. |
| Panorama.VirtualRouter.ECMP | Unknown | The ECMP defined for the virtual router. |
Command example
!pan-os-list-virtual-routers show_uncommitted=true
Context Example
{
"Panorama": {
"VirtualRouter": [
{
"BGP": {
"enable": "no",
"routing-options": {
"graceful-restart": {
"enable": "yes"
}
}
},
"Interface": null,
"Multicast": {},
"Name": "virtual-router-1",
"OSPF": {
"enable": "no"
},
"OSPFv3": {
"enable": "no"
},
"RIP": {
"enable": "no"
},
"RedistributionProfile": {},
"StaticRoute": {
"ip": {
"static-route": {
"entry": [
{
"@name": "static_route_ip",
"bfd": {
"profile": "None"
},
"destination": "1.1.1.1",
"metric": "14",
"nexthop": {
"ip-address": "1.1.1.1"
},
"path-monitor": {
"enable": "no",
"failure-condition": "any",
"hold-time": "2"
},
"route-table": {
"unicast": null
}
},
{
"@name": "static_route_ip2",
"bfd": {
"profile": "None"
},
"destination": "1.1.1.1",
"metric": "188",
"nexthop": {
"ip-address": "1.1.1.1"
},
"path-monitor": {
"enable": "no",
"failure-condition": "any",
"hold-time": "2"
},
"route-table": {
"unicast": null
}
},
{
"@name": "static_route_ip3",
"destination": "1.1.1.1/32",
"nexthop": {
"ip-address": "1.1.1.1"
}
}
]
}
}
}
},
{
"BGP": {
"enable": "no",
"routing-options": {
"graceful-restart": {
"enable": "yes"
}
}
},
"Interface": "loopback",
"Multicast": {
"enable": "no",
"rp": {
"local-rp": {
"candidate-rp": {
"interface": "loopback"
}
}
}
},
"Name": "virtual-router-2",
"OSPF": {
"enable": "no"
},
"OSPFv3": {
"enable": "no"
},
"RIP": {
"auth-profile": {
"entry": {
"@name": "213"
}
},
"enable": "no",
"export-rules": {
"entry": {
"@name": "test1"
}
},
"interface": {
"entry": {
"@name": "loopback",
"bfd": {
"profile": "Inherit-vr-global-setting"
},
"default-route": {
"disable": {}
},
"enable": "yes",
"mode": "normal"
}
}
},
"RedistributionProfile": {
"entry": [
{
"@name": "test1",
"action": {
"no-redist": {}
},
"priority": "1"
},
{
"@name": "test-2",
"action": {
"no-redist": {}
},
"priority": "123"
}
]
},
"StaticRoute": {
"ip": {
"static-route": {
"entry": {
"@name": "test",
"bfd": {
"profile": "None"
},
"destination": "1.1.1.1",
"metric": "10",
"nexthop": {
"ip-address": "2.2.2.2"
},
"path-monitor": {
"enable": "no",
"failure-condition": "any",
"hold-time": "2"
},
"route-table": {
"unicast": {}
}
}
}
}
}
}
]
}
}
Human Readable Output
Virtual Routers
BGP Interface Multicast Name OSPF OSPFv3 RIP RedistributionProfile StaticRoute no virtual-router-1 no no no static_route_ip,
static_route_ip2,
static_route_ip3no loopback no virtual-router-2 no no no test1,
test-2test
pan-os-list-redistribution-profiles
Returns a list of redistribution-profiles of a specific virtual-router of either a Panorama/firewall instance.
Base Command
pan-os-list-redistribution-profiles
Input
| Argument Name | Description | Required |
|---|---|---|
| name | Redistribution profile name. | Optional |
| virtual_router | The name of the virtual router that has the redistribution profiles retrieve. Can be retrieved from pan-os-list-virtual-routers. | Required |
| template | The template that the redistribution profiles and virtual-router are part of. Use only for Panorama instances. | Optional |
| limit | The maximum number of redistribution-profiles to retrieve. Default is 50. | Optional |
Context Output
| Path | Type | Description |
|---|---|---|
| Panorama.RedistributionProfile.Name | String | The name of the profile. |
| Panorama.RedistributionProfile.Priority | String | The priority of the profile. |
| Panorama.RedistributionProfile.Action | String | The action of the profile. |
| Panorama.RedistributionProfile.FilterInterface | Unknown | The filter interface(s). |
| Panorama.RedistributionProfile.FilterType | Unknown | The filter type(s). |
| Panorama.RedistributionProfile.FilterDestination | Unknown | The filter destination(s). |
| Panorama.RedistributionProfile.FilterNextHop | Unknown | The filter next hop. |
| Panorama.RedistributionProfile.BGP | Unknown | The BGP of the profile. |
| Panorama.RedistributionProfile.OSPF | Unknown | The OSPF of the profile. |
Command example
!pan-os-list-redistribution-profiles virtual_router=test
Context Example
{
"Panorama": {
"RedistributionProfile": [
{
"Action": "redist",
"BGP": {
"Community": [
"local-as",
"no-export"
],
"ExtendedCommunity": "0x4164ACFCE33404EA"
},
"FilterDestination": "1.1.1.1",
"FilterInterface": "loopback",
"FilterNextHop": "2.2.2.2",
"FilterType": [
"bgp",
"connect",
"ospf",
"rip",
"static"
],
"Name": "test1",
"OSPF": {
"Area": [
"1.1.1.1",
"2.2.2.2"
],
"PathType": [
"ext-1",
"ext-2",
"inter-area",
"intra-area"
],
"Tag": "1"
},
"Priority": "1"
},
{
"Action": "no-redist",
"BGP": null,
"FilterDestination": null,
"FilterInterface": null,
"FilterNextHop": null,
"FilterType": null,
"Name": "test-2",
"OSPF": null,
"Priority": "123"
}
]
}
}
Human Readable Output
Redistribution profiles for virtual router test-guy
Name Priority Action Filter Type Filter Destination Filter Next Hop BGP OSPF test1 1 redist bgp,
connect,
ospf,
rip,
static1.1.1.1 2.2.2.2 Community: local-as,
no-export
ExtendedCommunity: 0x4164ACFCE33404EAPathType: ext-1,
ext-2,
inter-area,
intra-area
Area: 1.1.1.1,
2.2.2.2
Tag: 1test-2 123 no-redist
pan-os-create-redistribution-profile
Creates a new redistribution-profile under a virtual-router for a Panorama/firewall instance.
Base Command
pan-os-create-redistribution-profile
Input
| Argument Name | Description | Required |
|---|---|---|
| name | The name of the of the redistribution profile to create. | Required |
| virtual_router | The virtual router that the redistribution profile will be created on. | Required |
| template | The template that the virtual-router is in. Use only for Panorama instances. | Optional |
| filter_source_type | Comma-separated list of the filter source types. Possible values are: bgp, ospf, rip, static. | Optional |
| destination | A comma-separated list of destination to filter by. | Optional |
| nexthop | A comma-separated list of next-hops to filter by. | Optional |
| interface | A comma-separated list of interfaces to filter by. | Optional |
| priority | The priority of the profile. (1-255). | Required |
| action | The action of the profile. Possible values are: redist, no-redist. | Optional |
| filter_ospf_area | A comma-separated list of areas for the OSPF. | Optional |
| filter_ospf_tag | A comma-separated list of tags for the OSPF. | Optional |
| filter_ospf_path_type | A comma-separated list of path types for the OSPF. Possible values are: ext-1, ext-2, inter-area, intra-area. | Optional |
| filter_bgp_community | A comma-separated list of community filters for the BGP. 32-bit value in decimal or hex or in AS:VAL format where AS and VAL are each in 0 - 65535 range. (Max 10 values). | Optional |
| filter_bgp_extended_community | A comma-separated list of community filters for the BGP. 64-bit value in hex, or in TYPE:AS:VAL, TYPE:IP:VAL format. TYPE is 16-bit, the other two are 16-bit and 32-bit each. (Max 5 values). | Optional |
Context Output
There is no context output for this command.
Command example
!pan-os-create-redistribution-profile name=test virtual_router=virtual-router-1 priority=12 action=redist filter_bgp_extended_community=0x4164ACFCE33404EA filter_source_type=bgp,ospf filter_bgp_community=13,89 filter_ospf_path_type="ext-1" interface=loopback filter_ospf_tag=1.1.1.1,2.2.2.2 filter_ospf_area=1.1.1.1,2.2.2.2 nexthop=1.1.1.1
Human Readable Output
Redistribution profile test was created successfully.
pan-os-edit-redistribution-profile
Edits a redistribution-profile in a virtual-router.
Base Command
pan-os-edit-redistribution-profile
Input
| Argument Name | Description | Required |
|---|---|---|
| name | The name of the redistribution-profile to edit. | Required |
| virtual_router | The name of the virtual-router that the redistribution-profile is part of. | Required |
| template | The template that the virtual-router is in. Only for Panorama instances. | Optional |
| element_to_change | The element to change. Possible values are: filter_type, filter_destination, filter_nexthop, filter_interface, priority, action, filter_ospf_area, filter_ospf_tag, filter_ospf_path_type, filter_bgp_community, filter_bgp_extended_community. | Required |
| element_value | The value of the element to change. Can be a list for all the elements except priority and action. | Required |
| behavior | The operation to perform on the profile. Possible values are: replace, add, remove. Default is replace. | Optional |
Context Output
There is no context output for this command.
Command example
!pan-os-edit-redistribution-profile virtual_router=virtual-router-name name=test element_to_change=filter_type element_value=bgp,ospf
Human Readable Output
Redistribution profile test was edited successfully.
pan-os-delete-redistribution-profile
Deletes a redistribution-profile from a virtual-router.
Base Command
pan-os-delete-redistribution-profile
Input
| Argument Name | Description | Required |
|---|---|---|
| name | The name of the redistribution-profile to delete. | Required |
| virtual_router | The name of the virtual-router that the redistribution-profile is part of. | Required |
| template | The template that the virtual-router is in. Only for panorama instances. | Optional |
Context Output
There is no context output for this command.
Command example
!pan-os-delete-redistribution-profile virtual_router=test1 name=test
Human Readable Output
Redistribution profile test was deleted successfully.
pan-os-list-pbf-rules
Returns a list of pbf-rules of either a Panorama/firewall instance.
Base Command
pan-os-list-pbf-rules
Input
| Argument Name | Description | Required |
|---|---|---|
| rulename | The name of the pbf-rule to retrieve. If not mentioned, will bring all the pbf rules. | Optional |
| device-group | The device-group that the pbf-rules are part of. | Optional |
| pre_post | The pre-rule or post-rule (Panorama instances only). Possible values are: pre-rulebase, post-rulebase. | Optional |
| show_uncommitted | Whether to show the un-committed rules or not. Possible values are: true, false. Default is false. | Optional |
| disabled | Whether to retrieve the disabled rules. If not mentioned, will retrieve all the PBF rules. Possible values are: yes, no. | Optional |
| action | The action of the PBF rules to retrieve. If not mentioned, will retrieve all the PBF rules. Possible values are: discard, forward, no-pbf. | Optional |
| tags | A comma-separated list of tags of the PBF rules to retrieve. If not mentioned, will retrieve all the PBF rules. | Optional |
| query | Free query to retrieve PBF rule. If not mentioned, will retrieve all the PBF rules. | Optional |
| limit | The maximum number of rules to retrieve. Will be used by default if page argument was not provided. Default is 50. | Optional |
| page_size | The size of pbf-rules to return. Default is 50. | Optional |
| page | The page at which to start listing pbf-rules. Must be a positive number. | Optional |
Context Output
| Path | Type | Description |
|---|---|---|
| Panorama.PBF.Name | String | The name of the PBF rule. |
| Panorama.PBF.Description | String | The description of the PBF rule. |
| Panorama.PBF.Tags | Unknown | The tags of the PBF rule. |
| Panorama.PBF.SourceZone | Unknown | The source-zones of the PBF rule. |
| Panorama.PBF.SourceInterface | Unknown | The source-interfaces of the PBF rule. |
| Panorama.PBF.SourceAddress | Unknown | The source-addresses of the PBF rule. |
| Panorama.PBF.SourceUser | Unknown | The source-users of the PBF rule. |
| Panorama.PBF.DestinationAddress | Unknown | The destination-addresses of the PBF rule. |
| Panorama.PBF.EnforceSymmetricReturn | Unknown | The enforce-symmetric-return of the PBF rule. |
| Panorama.PBF.Target | Unknown | The target of the PBF rule. |
| Panorama.PBF.Application | Unknown | The applications of the PBF rule. |
| Panorama.PBF.Service | Unknown | The services of the PBF rule. |
| Panorama.PBF.Disabled | String | Whether the rule is disabled. |
Command example
!pan-os-list-pbf-rules pre_post="pre-rulebase" show_uncommitted=true debug-mode=true
Context Example
{
"Panorama": {
"PBF": [
{
"Action": {
"forward": {
"egress-interface": "Test"
}
},
"Application": "acronis-snapdeploy",
"Description": "Test policy based forwarding rule with a twist",
"DestinationAddress": "bad-url.com",
"Disabled": "no",
"EnforceSymmetricReturn": {
"enabled": "no"
},
"Name": "Test_PBF",
"Service": "service-https",
"SourceAddress": "any",
"SourceInterface": null,
"SourceUser": "any",
"SourceZone": "Test_Zone",
"Tags": "test",
"Target": {
"negate": "no"
}
},
{
"Action": {
"forward": {
"egress-interface": "ethernet1/1"
}
},
"Application": "any",
"Description": "TEst2",
"DestinationAddress": "any",
"Disabled": "no",
"EnforceSymmetricReturn": {
"enabled": "yes",
"nexthop-address-list": {
"entry": [
{
"@name": "1.1.1.1"
},
{
"@name": "2.2.2.2"
}
]
}
},
"Name": "Test_PBF4",
"Service": "any",
"SourceAddress": "any",
"SourceInterface": null,
"SourceUser": "any",
"SourceZone": "internal",
"Tags": null,
"Target": null
}
]
}
}
Human Readable Output
Policy Based Forwarding Rules
Action Description Destination Address Disabled Name Source Address Source User Source Zone Tags forward Test policy based forwarding rule with a twist bad-url.com no Test_PBF any any Test_Zone test forward TEst2 any no Test_PBF4 any any internal
pan-os-create-pbf-rule
Creates a new policy-based-forwarding (PBF) rule in a Panorama/firewall instance.
Base Command
pan-os-create-pbf-rule
Input
| Argument Name | Description | Required |
|---|---|---|
| rulename | The name of the PBF-rule to create. | Required |
| description | The description that the new PBF-rule should have. | Optional |
| device-group | The device-group in which the new rule should be created. Only for Panorama instance. | Optional |
| pre_post | The pre rule or post rule (Panorama instances only). Possible values are: pre-rulebase, post-rulebase. | Optional |
| tags | The tags that the rule will be created with. | Optional |
| source_zone | A comma-separated list of source zones. Default is any. | Optional |
| source_address | A comma-separated list of source addresses. Default is any. | Optional |
| source_user | A comma-separated list of source users. Default is any. | Optional |
| service | The service in which the rule will be created with. Default is any. | Optional |
| destination_address | A comma-separated list of destination addresses. Default is any. | Optional |
| application | A comma-separated list of applications. Default is any. | Optional |
| action | The action that the rule will be created with. Possible values are: forward, discard, no-pbf. | Required |
| egress_interface | The egress interface the rule will be created with. Must be provided if action == forward. | Optional |
| nexthop | The next-hop. Relevant only when action = forward. Possible values are: ip-address, fqdn, none. Default is none. | Optional |
| nexthop_value | The next-hop value when action = forward. Could be an IP address or FQDN. Required when nexthop is not none. | Optional |
| enforce_symmetric_return | Whether to enforce symmetric return. Possible values are: yes, no. Default is no. | Optional |
| negate_source | Whether to negate the source. Possible values are: yes, no. Default is no. | Optional |
| negate_destination | Whether to negate the destination. Possible values are: yes, no. Default is no. | Optional |
| nexthop_address_list | The nexthop addresses list for the symmetric return. | Optional |
| audit_comment | An audit comment for the rule. | Optional |
Context Output
There is no context output for this command.
Command example
!pan-os-create-pbf-rule rulename=test4 pre_post="pre-rulebase" enforce_symmetric_return=yes nexthop_address_list=1.1.1.1,2.2.2.2 action=forward description="this is just a description" egress_interface=a2 nexthop="ip-address" nexthop_value=1.1.1.1 negate_source=yes source_zone=1.1.1.1,2.2.2.2 destination_address=1.1.1.1,2.2.2.2 service=dns,service-https
Human Readable Output
PBF rule test4 was created successfully.
pan-os-edit-pbf-rule
Edits a redistribution-profile in a virtual-router.
Base Command
pan-os-edit-pbf-rule
Input
| Argument Name | Description | Required |
|---|---|---|
| rulename | The name of the PBF rule to edit. Can be retrieved from the pan-os-list-pbf-rules command. | Required |
| device-group | The device-group that the PBF rule is in. | Optional |
| pre_post | The pre-rule or post-rule (Panorama instances only). Possible values are: pre-rulebase, post-rulebase. | Optional |
| element_to_change | The element to change. Possible values are: source_zone, source_address, source_user, service, destination_address, application, negate_source, negate_destination, nexthop_address_list, enforce_symmetric_return, action_forward_egress_interface, action_forward_nexthop_ip, action_forward_nexthop_fqdn, action_forward_discard, action_forward_no_pbf, disabled, audit-comment. | Required |
| element_value | The value of the element to change. Can be a list for some of the elements. When element_to_change == ‘action_forward_egress_interface’, the action of the rule will be changed to ‘forward’ automatically. | Required |
Context Output
There is no context output for this command.
Command example
!pan-os-edit-pbf-rule rulename=test4 element_to_change=nexthop_address_list element_value="1.1.1.1,2.2.2.2" pre_post="pre-rulebase"
Human Readable Output
PBF test4 was edited successfully.
pan-os-delete-pbf-rule
Deletes a PBF rule.
Base Command
pan-os-delete-pbf-rule
Input
| Argument Name | Description | Required |
|---|---|---|
| rulename | The name of the pbf-rule to delete. Can be retrieved from the pan-os-list-pbf-rules command. | Required |
| device-group | The device-group from which the pbf-rule should be deleted. Only for a Panorama instance. | Optional |
| pre_post | The pre-rule or post-rule (Panorama instances only). Possible values are: pre-rulebase, post-rulebase. | Optional |
Context Output
There is no context output for this command.
Command example
!pan-os-delete-pbf-rule rulename=test4 pre_post="pre-rulebase"
Human Readable Output
PBF rule test4 was deleted successfully.
pan-os-list-application-groups
Returns a list of application-groups of either a Panorama/firewall instance.
Base Command
pan-os-list-application-groups
Input
| Argument Name | Description | Required |
|---|---|---|
| name | The name of the application-group to retrieve. If not mentioned, will bring all the application-groups. | Optional |
| device-group | The device-group that the nat-rules are part of. | Optional |
| show_uncommitted | Whether to show the un-committed application-groups or not. Possible values are: true, false. Default is false. | Optional |
| limit | The maximum number of application-groups to retrieve. Will be used by default if page argument was not provided. Default is 50. | Optional |
| page_size | The page size of the application-groups to return. Default is 50. | Optional |
| page | The page at which to start listing application-groups. Must be a positive number. | Optional |
Context Output
| Path | Type | Description |
|---|---|---|
| Panorama.ApplicationGroup.Name | String | The name of the application-group object. |
| Panorama.ApplicationGroup.Applications | Unknown | The list of the applications that the application-group has. |
| Panorama.ApplicationGroup.Members | Number | The number of the application that are part of the application-group |
Command example
!pan-os-list-application-groups show_uncommitted=true
Context Example
{
"Panorama": {
"ApplicationGroup": [
{
"Applications": [
"1c-enterprise"
],
"Members": 1,
"Name": "test"
},
{
"Applications": [
"2ch-base",
"4shared"
],
"Members": 2,
"Name": "test-2"
},
{
"Applications": [
"1c-enterprise",
"4shared"
],
"Members": 2,
"Name": "test-3"
}
]
}
}
Human Readable Output
Application groups
Applications Members Name 1c-enterprise 1 test 2ch-base,
4shared2 test-2 1c-enterprise,
4shared2 test-3
pan-os-create-application-group
Creates a new application group rule in a Panorama/firewall instance.
Base Command
pan-os-create-application-group
Input
| Argument Name | Description | Required |
|---|---|---|
| name | The name for the application-group to be created with. | Required |
| applications | Comma-separated list of applications. Can be retrieved using the command pan-os-list-applications. | Required |
| device-group | The device-group in which the application-group should be created. Only for Panorama instance. | Optional |
Context Output
| Path | Type | Description |
|---|---|---|
| Panorama.ApplicationGroup.Name | String | The name of the application-group object. |
| Panorama.ApplicationGroup.Applications | Unknown | The list of the applications that the application-group has. |
| Panorama.ApplicationGroup.Members | Number | The number of the applications that are part of the application-group. |
Command example
!pan-os-create-application-group name=test-3 applications=1c-enterprise,4shared
Context Example
{
"Panorama": {
"ApplicationGroup": {
"Applications": [
"1c-enterprise",
"4shared"
],
"Members": 2,
"Name": "test-3"
}
}
}
Human Readable Output
application-group test-3 was created successfully.
pan-os-edit-application-group
Edits an application-group.
Base Command
pan-os-edit-application-group
Input
| Argument Name | Description | Required |
|---|---|---|
| name | The name for the application-group to be edit. Can be retrieved from the pan-os-list-application-groups command. | Required |
| applications | Comma-separated list of applications. Can be retrieved using the command pan-os-list-applications. | Required |
| device-group | The device-group in which the application-group should be created. Only for a Panorama instance. | Optional |
| action | The action to perform on the application-group. Possible values are: add, remove. Default is add. | Required |
Context Output
| Path | Type | Description |
|---|---|---|
| Panorama.ApplicationGroup.Name | String | The name of the application-group object. |
| Panorama.ApplicationGroup.Applications | Unknown | The list of the applications that the application-group has. |
| Panorama.ApplicationGroup.Members | Number | The number of the applications that are part of the application-group |
Command example
!pan-os-edit-application-group name=test-3 action=remove applications=4shared
Context Example
{
"Panorama": {
"ApplicationGroup": {
"Applications": [
"1c-enterprise"
],
"Members": 1,
"Name": "test-3"
}
}
}
Human Readable Output
application-group test-3 was edited successfully.
pan-os-delete-application-group
Deletes an application-group
Base Command
pan-os-delete-application-group
Input
| Argument Name | Description | Required |
|---|---|---|
| name | The name of the application-group to delete. Can be retrieved from the pan-os-list-application-groups command. | Required |
| device-group | The device-group in which the application-group is part of. Only for a Panorama instance. | Optional |
Context Output
There is no context output for this command.
Command example
!pan-os-delete-application-group name=test-3
Human Readable Output
application-group test-3 was deleted successfully.
pan-os-list-tag
Returns a list of tags from Panorama.
Base Command
pan-os-list-tag
Input
| Argument Name | Description | Required |
|---|---|---|
| include_shared_tags | Whether to include shared tags in the list. Possible values are: Yes, No. Default is No. | Optional |
| device-group | The device group that the tags are part of. | Optional |
Context Output
| Path | Type | Description |
|---|---|---|
| Panorama.Tag.name | String | The name of the tag. |
| Panorama.Tag.color | String | The color of the tag. |
| Panorama.Tag.comment | String | The comment in the tag. |
| Panorama.Tag.disable-override | String | Whether overriding the tag is disabled. |
| Panorama.Tag.location | String | The tag’s device group location. |
Command example
!pan-os-list-tag include_shared_tags=No
Context Example
{
"Panorama": {
"Tag": [
{
"name": "tag1",
"color": "color13"
},
{
"name": "tag2",
"color": "color39"
},
{
"name": "tag3",
"color": "color39",
"disable-override": "no",
"comments": "text text text"
}
]
}
}
Human Readable Output
Tags
Name Color Comment tag1 color13 tag2 color39 tag3 color39 text text text
pan-os-create-tag
Creates a new tag in Panorama.
Base Command
pan-os-create-tag
Input
| Argument Name | Description | Required |
|---|---|---|
| name | The name for the new tag to be created. | Required |
| device_group | The device group that the tag will be part of. | Optional |
| disable_override | Whether to disable overriding the tag. Possible values are: true, false. Default is false. | Optional |
| is_shared | Whether the tag should be generated in a shared location. Possible values are: true, false. Default is false. | Optional |
| comment | The comment for the tag. | Optional |
Context Output
There is no context output for this command.
Command example
!pan-os-create-tag name="testtag" comment="some comment" is_shared=false
Human Readable Output
The tag with name “testtag” was created successfully.
pan-os-edit-tag
Edits a tag in Panorama.
Base Command
pan-os-edit-tag
Input
| Argument Name | Description | Required |
|---|---|---|
| name | The existing name for the tag to be edited. | Required |
| new_name | The new name for the tag to be replaced with. | Optional |
| device_group | The device group of the tag. | Optional |
| disable_override | Whether to disable overriding the tag. Possible values are: true, false. Default is false. | Optional |
| comment | The comment for the tag. | Optional |
Context Output
There is no context output for this command.
Command example
!pan-os-edit-tag name="testtag" new_name="newtesttag" comment="some comment"
Human Readable Output
The tag with name “testtag” was edited successfully.
pan-os-delete-tag
Deletes a tag from Panorama.
Base Command
pan-os-delete-tag
Input
| Argument Name | Description | Required |
|---|---|---|
| name | The name of the tag to delete. | Required |
Context Output
There is no context output for this command.
Command example
!pan-os-delete-tag name="testtag"
Human Readable Output
The tag with name “testtag” was deleted successfully.
pan-os-list-device-groups
Returns a list of all device groups from Panorama.
Base Command
pan-os-list-device-groups
Input
| Argument Name | Description | Required |
| — | — | — |
Context Output
| Path | Type | Description |
|---|---|---|
| Panorama.DeviceGroupNames | string | The list of device groups. |
pan-os-export-tech-support-file
Exports a tech support file (TSF).
Base Command
pan-os-export-tech-support-file
Input
| Argument Name | Description | Required |
|---|---|---|
| interval_in_seconds | The polling interval (in seconds). Default is 30. | Optional |
| timeout | The polling timeout (in seconds). Default is 1200. | Optional |
Context Output
There is no context output for this command.
Command example
#### Human Readable Output
>Waiting for tech support file export with job ID 101 to finish...
### pan-os-list-security-profile-group
***
Returns a list of security profile groups from Panorama.
#### Base Command
`pan-os-list-security-profile-group`
#### Input
| **Argument Name** | **Description** | **Required** |
| --- | --- | --- |
| group_name | A given group name to return the data for. | Optional |
| device-group | The device group that the security profile groups are part of. | Optional |
#### Context Output
| **Path** | **Type** | **Description** |
| --- | --- | --- |
| Panorama.ProfileGroup.name | String | The name of the group. |
| Panorama.ProfileGroup.location | String | The security profile group's device group location. |
| Panorama.ProfileGroup.virus | String | The antivirus profile. |
| Panorama.ProfileGroup.spyware | String | The anti-spyware profile. |
| Panorama.ProfileGroup.vulnerability | String | The vulnerability protection profile. |
| Panorama.ProfileGroup.url-filtering | String | The URL filtering profile. |
| Panorama.ProfileGroup.file-blocking | String | The file blocking profile. |
| Panorama.ProfileGroup.data-filtering | String | The data filtering profile. |
| Panorama.ProfileGroup.wildfire-analysis | String | The WildFire analysis profile. |
| Panorama.ProfileGroup.disable-override | String | Whether overriding the security profile group is disabled. |
#### Command example
```!pan-os-list-security-profile-group```
#### Context Example
```json
{
"Panorama": {
"ProfileGroups": [
{
"name": "test_security_pg",
"location": "TestDevice",
"virus": "default",
"spyware": "default",
},
{
"name": "test_security_pg_v2",
"file-blocking": "basic file blocking",
"data-filtering": "test data filtering",
"wildfire-analysis": "test wildfire analysis",
"url-filtering": "default",
"location": "TestDevice",
"spyware": "default",
"vulnerability": "vulnerability",
"virus": "default",
}
]
}
}
Human Readable Output
Security Profile Groups
Name Location Antivirus Profile Anti-Spyware Profile Vulnerability Protection Profile URL Filtering Profile File Blocking Profile Data Filtering Profile WildFire Analysis Profile test_security_pg TestDevice default default test_security_pg_v2 TestDevice default default vulnerability default basic file blocking test data filtering test wildfire analysis
pan-os-create-security-profile-group
Creates a new security profile group in Panorama.
Base Command
pan-os-create-security-profile-group
Input
| Argument Name | Description | Required |
|---|---|---|
| group_name | The name of the security profile group. | Required |
| device-group | The device group that the security profile group will be part of. | Optional |
| antivirus_profile | The antivirus profile of the group. You can get the possible values for this argument by running the pan-os-get-security-profile command. | Optional |
| anti_spyware_profile | The anti-spyware profile of the group. You can get the possible values for this argument by running the pan-os-get-security-profile command. | Optional |
| vulnerability_protection_profile | The vulnerability protection profile of the group. You can get the possible values for this argument by running the pan-os-get-security-profile command. | Optional |
| URL_filtering_profile | The URL filtering profile of the group. You can get the possible values for this argument by running the pan-os-get-security-profile command. | Optional |
| file_blocking_profile | The file blocking profile of the group. You can get the possible values for this argument by running the pan-os-get-security-profile command. | Optional |
| data_filtering_profile | The data filtering profile of the group. You can get the possible values for this argument by running the pan-os-get-security-profile command. | Optional |
| wildfire_analysis_profile | The WildFire analysis profile of the group. You can get the possible values for this argument by running the pan-os-get-security-profile command. | Optional |
Context Output
There is no context output for this command.
Command example
!pan-os-create-security-profile-group group_name="test_security_pg" antivirus_profile="default" anti_spyware_profile="default"
Human Readable Output
Successfull created Security Profile Group: “test-spg”
pan-os-edit-security-profile-group
Edits the security profile group in Panorama.
Base Command
pan-os-edit-security-profile-group
Input
| Argument Name | Description | Required |
|---|---|---|
| group_name | The name of the security profile group to edit. | Required |
| profile_to_change | The profile to edit in the group. Possible values are: Antivirus Profile, Anti-Spyware Profile, Vulnerability Protection Profile, URL Filtering Profile, File Blocking Profile, Data Filtering Profile, WildFire Analysis Profile. | Required |
| profile_value | The value to set in the profile. You can get the possible values for this argument by running the pan-os-get-security-profile command. | Required |
| device-group | The device group that the security profile group is part of. | Optional |
Context Output
There is no context output for this command.
Command example
!pan-os-edit-security-profile-group group_name="test-spg" profile_to_change="Antivirus Profile" profile_value="default"
Human Readable Output
Successfull edited Security Profile Group: “test-spg”
pan-os-delete-security-profile-group
Deletes a security profile group from Panorama.
Base Command
pan-os-delete-security-profile-group
Input
| Argument Name | Description | Required |
|---|---|---|
| group_name | The name of the security profile group to delete. | Required |
| device-group | The device group that the security profile group is part of. | Optional |
Context Output
There is no context output for this command.
Command example
!pan-os-delete-security-profile-group group_name="test-spg"
Human Readable Output
Successfull deleted Security Profile Group: “test-spg”
pan-os-get-audit-comment
Gets the audit comment of a rule.
Base Command
pan-os-get-audit-comment
Input
| Argument Name | Description | Required |
|---|---|---|
| rule_name | The rule name to apply. | Required |
| rule_type | The rule type. Possible values are: Security Rule, NAT Rule, PBF Rule. | Required |
| pre_post | The pre-rule or post-rule (Panorama instances only). Possible values are: Pre, Post. | Optional |
| device-group | The device group that the rule is part of. | Optional |
Context Output
| Path | Type | Description |
|---|---|---|
| Panorama.AuditComment.comment | String | The audit comment of the rule. |
| Panorama.AuditComment.rule_name | String | The rule name. |
| Panorama.AuditComment.rule_type | String | The rule type. |
Command example
!pan-os-get-audit-comment rule_name="test" rule_type="Security Rule" pre_post=Post
Context Example
{
"Panorama": {
"AuditComment": [
{
"comment": "some comment",
"rule_name": "test",
"rule_type": "Security Rule"
}
]
}
}
Human Readable Output
Audit Comment for Rule: test
Comment Rule Name Rule Type some comment test Security Rule pan-os-add-profile-exception
Add an exception to a Vulnerability Protection profile or Anti Spyware profile.
Base Command
pan-os-add-profile-exception
Input
| Argument Name | Description | Required |
|---|---|---|
| profile_name | The profile name. | Required |
| threat | The requested threat name/CVE/ID to add. | Required |
| profile_type | The profile type. Possible values are: Vulnerability Protection Profile, Anti Spyware Profile. | Optional |
| action | The action type of the exception. Default value is ‘default’. Possible values are: Alert, Allow, Block IP, Drop, Reset Both, Reset Client, Reset Server. | Optional |
| packet_capture | To configure the firewall to take a packet capture when it detects a threat. Possible values are: Disable, Single Packet, Extended Capture. | Optional |
| exempt_ip | An IP address. Configure an exempt IP address to enforce a threat exception only when the associated session has either a matching source or destination IP address; for all other sessions, the threat is enforced based on the default signature action. | Optional |
| device_group | Device group. This will override any configured device group or vsys. | Optional |
| ip_track_by | Specify whether to Track By and block the IP address using the IP source or the IP source and destination. If action = Block IP , this argument is mandatory. Possible values are: Source, Source And Destination. | Optional |
| ip_duration_sec | Specify the time period (in seconds) after which to trigger the action. If action = Block IP , this argument is mandatory. | Optional |
Command example
!pan-os-add-profile-exception profile_name="test1" threat="10002" action="Drop"
Context Output
There is no context output for this command.
pan-os-list-profile-exception
List the exceptions in a Vulnerability Protection profile or Anti Spyware profile.
Base Command
pan-os-list-profile-exception
Input
| Argument Name | Description | Required |
|---|---|---|
| profile_name | The profile name. | Required |
| profile_type | The profile type. Possible values are: Vulnerability Protection Profile, Anti Spyware Profile. | Optional |
Command example
!pan-os-list-profile-exception profile_name="test1" profile_type="Vulnerability Protection Profile"
Context Output
| Path | Type | Description |
|---|---|---|
| Panorama.Vulnerability.Name | String | The profile name. |
| Panorama.Vulnerability.Exception.name | String | The exception name. |
| Panorama.Vulnerability.Exception.id | String | The exception ID. |
| Panorama.Vulnerability.Exception.CVE | String | The exception CVE if exist. |
| Panorama.Vulnerability.Exception.action | String | The exception action. |
| Panorama.Vulnerability.Exception.exempt-id | String | The exception exempt ID. |
| Panorama.Vulnerability.Exception.packet-capture | String | The exception packet capture. |
| Panorama.Spyware.Name | String | The profile name. |
| Panorama.Spyware.Exception.name | String | The exception name. |
| Panorama.Spyware.Exception.id | String | The exception ID. |
| Panorama.Spyware.Exception.CVE | String | The exception CVE if exist. |
| Panorama.Spyware.Exception.action | String | The exception action. |
| Panorama.Spyware.Exception.exempt-id | String | The exception exempt ID. |
| Panorama.Spyware.Exception.packet-capture | String | The exception packet capture. |
pan-os-delete-profile-exception
Delete an exception to a Vulnerability Protection profile or Anti Spyware profile.
Base Command
pan-os-delete-profile-exception
Input
| Argument Name | Description | Required |
|---|---|---|
| profile_name | The profile name. | Required |
| threat | The requested threat name/CVE/ID to delete. | Required |
| profile_type | The profile type. Possible values are: Vulnerability Protection Profile, Anti Spyware Profile. | Optional |
Command example
!pan-os-delete-profile-exception profile_name="test2" threat="10005" profile_type="Vulnerability Protection Profile"
Context Output
There is no context output for this command.
pan-os-edit-profile-exception
Edit an exception to a Vulnerability Protection profile or Anti Spyware profile.
Base Command
pan-os-edit-profile-exception
Input
| Argument Name | Description | Required |
|---|---|---|
| profile_name | The profile name. | Required |
| threat | The requested threat name/CVE/ID to edit. | Required |
| profile_type | The profile type. Possible values are: Vulnerability Protection Profile, Anti Spyware Profile. | Optional |
| action | The action type of the exception. Default value is ‘default’. Possible values are: Alert, Allow, Block IP, Drop, Reset Both, Reset Client, Reset Server. | Optional |
| packet_capture | To configure the firewall to take a packet capture when it detects a threat. Possible values are: Disable, Single Packet, Extended Capture. | Optional |
| exempt_ip | An IP address. Configure an exempt IP address to enforce a threat exception only when the associated session has either a matching source or destination IP address; for all other sessions, the threat is enforced based on the default signature action. | Optional |
| device_group | Device group. This will override any configured device group or vsys. | Optional |
| ip_track_by | Specify whether to Track By and block the IP address using the IP source or the IP source and destination. If action = Block IP , this argument is mandatory. Possible values are: Source, Source And Destination. | Optional |
| ip_duration_sec | Specify the time period (in seconds) after which to trigger the action. If action = Block IP , this argument is mandatory. | Optional |
Command example
!pan-os-edit-profile-exception profile_name="test1" threat="10002" action="Drop"
Context Output
There is no context output for this command.
pan-os-create-master-key
Create a default master key that encrypts all the private keys and passwords in the configuration.
This command is harmful because it invalidates the current API key and requires re-configuration of the integration instance.
Base Command
pan-os-create-master-key
Input
| Argument Name | Description | Required |
|---|---|---|
| master_key | The encryption master key. Must be exactly 16 characters. | Required |
| lifetime_in_hours | The lifetime of the key in hours. | Required |
| reminder_in_hours | The time to be notified of the key’s expiration in hours. | Required |
Limitations
-
All changes to the configuration of the Palo Alto firewall or Panorama need to be committed before running this command. This can be done using using the pan-os-commit and pan-os-push-status commands.
-
The command invalidates the current API key and requires obtaining a new one using the instructions in the PAN-OS and Panorama API usage guide. All subsequent commands will raise an “Invalid Credential” error until a new API key is obtained and the integration instance is updated accordingly.
Command example
!pan-os-create-master-key master_key="MyFakeMasterKey1" lifetime_in_hours=2160 reminder_in_hours=1992
Context Output
There is no context output for this command.
Human Readable Output
Master key changed successfully. All key material has been re-encrypted with new master key and committed via jobid 1234.
⚠️ The current API key is no longer valid! (by design). Generate a new API key and update it in the integration instance configuration to keep using the integration.
pan-os-update-master-key
Update the default master key that encrypts all the private keys and passwords in the configuration.
This command is harmful because it invalidates the current API key and requires re-configuration of the integration instance.
Base Command
pan-os-update-master-key
Input
| Argument Name | Description | Required |
|---|---|---|
| current_master_key | The current encryption master key. | Required |
| new_master_key | The new encryption master key. Must be exactly 16 characters. | Required |
| lifetime_in_hours | The lifetime of the key in hours. | Required |
| reminder_in_hours | The time to be notified of the key’s expiration in hours. | Required |
Limitations
-
All changes to the configuration of the Palo Alto firewall or Panorama need to be committed before running this command. This can be done using using the pan-os-commit and pan-os-push-status commands.
-
The command invalidates the current API key and requires obtaining a new one using the instructions in the PAN-OS and Panorama API usage guide. All subsequent commands will raise an “Invalid Credential” error until a new API key is obtained and the integration instance is updated accordingly.
Command example
!pan-os-update-master-key current_master_key="MyFakeMasterKey1" new_master_key="MyFakeMasterKey2" lifetime_in_hours=2160 reminder_in_hours=1992
Context Output
There is no context output for this command.
Human Readable Output
Master key changed successfully. All key material has been re-encrypted with new master key and committed via jobid 2468.
⚠️ The current API key is no longer valid! (by design). Generate a new API key and update it in the integration instance configuration to keep using the integration.
pan-os-get-master-key-details
Show the details of the default master key that encrypts all the private keys and passwords in the configuration.
Base Command
pan-os-get-master-key-details
Input
There are no input arguments for this command.
Command example
#### Context Output
| **Path** | **Type** | **Description** |
| --- | --- | --- |
| Panorama.MasterKey.auto-renew-mkey | String | Whether the master key will be automatically renewed on expiry. |
| Panorama.MasterKey.expire-at | String | The date and time when the key is set to expire. |
| Panorama.MasterKey.hours-to-expiry | String | The number of hours remaining before the key expires. |
| Panorama.MasterKey.hours-to-reminder | String | The number of hours remaining before being notified that the key is set to expire. |
| Panorama.MasterKey.minutes-to-expiry | String | The number of minutes remaining before the key expires. |
| Panorama.MasterKey.minutes-to-reminder | String | The number of minutes remaining before being notified that the key is set to expire. |
| Panorama.MasterKey.on-hsm | String | Whether the master key is encrypted using a key stored on a Hardware Security Module (HSM). |
| Panorama.MasterKey.remind-at | String | The date and time when to be notified that the key is set to expire. |
| Panorama.MasterKey.seconds-to-expiry | String | The number of seconds remaining before the key expires. |
| Panorama.MasterKey.seconds-to-reminder | String | The number of seconds remaining before being notified that the key is set to expire. |
#### Context Example
```json
{
"Panorama": {
"MasterKey": {
"auto-renew-mkey": "0",
"expire-at": "2025/02/18 04:26:05",
"hours-to-expiry": "2138",
"hours-to-reminder": "1992",
"minutes-to-expiry": "128288",
"minutes-to-reminder": "119520",
"on-hsm": "no",
"remind-at": "2024/11/27 04:26:05",
"seconds-to-expiry": "7697336",
"seconds-to-reminder": "7171200"
}
}
}
Human Readable Output
Master Key Details
Auto-renew master key Encrypted on HSM Remind at Expire at 0 no 2024/11/27 04:26:05 2025/02/18 04:26:05
pan-os-get-certificate-info
Gathers the name, expiration date, and expiration status of certificates configured locally on a Firewall or pushed from Panorama, as seen under Certificate Management.
Base Command
pan-os-get-certificate-info
Input
| Argument Name | Description | Required |
|---|---|---|
| show_expired_only | Show only expired certificates. | Optional |
Command example
!pan-os-get-certificate-info show_expired_only=true
Context Output
| Path | Type | Description |
|---|---|---|
| Panorama.Certificate.name | String | Name of the certificate. |
| Panorama.Certificate.device | String | Device where this certificate was found. |
| Panorama.Certificate.subject | String | Subject of the certificate. |
| Panorama.Certificate.expiration_date | String | Expiration date of the certificate. |
| Panorama.Certificate.expiration_status | String | Status of certificate - Expired, Expiring in 30 days, Expiring in 60 days, Expiring in 90 days or Valid. |
| Panorama.Certificate.location | String | Where this certificate was configured - Firewall or Panorama. |
| Panorama.Certificate.cert_type | String | Whether this certificate was pushed from Panorama, Local to Firewall, or Predefined on Panorama or a Firewall. |
| Panorama.Certificate.devices_using_certificate | Unknown | List of devices using this certificate if it was pushed from Panorama. |
Context Example
{
"Panorama": {
"Certificate": [
{
"name": "ACME Root CA",
"device": "panorama.test",
"subject": "/CN=acme-root-ca.acme.com",
"expiration_date": "May 9 16:35:16 2026 GMT",
"expiration_status": "Valid",
"location": "Panorama",
"cert_type": "Pushed",
"devices_using_certificate": [
"111111111111111"
]
}
]
}
}
Human Readable Output
Certificates Information
name device subject expiration_date expiration_status location cert_type devices_using_certificate ACME Root CA panorama.test /CN=acme-root-ca.acme.com May 9 16:35:16 2026 GMT Valid Panorama Pushed 111111111111111
pan-os-check-dynamic-updates-status
Checks for the latest available dynamic update versions and returns a list of latest available / currently installed content.
When running from a Panorama instance, the target argument must be specified.
Base Command
pan-os-check-dynamic-updates-status
Input
| Argument Name | Description | Required |
|---|---|---|
| target | Serial number of the firewall on which to run the command. Mandatory for Panorama instances. | Optional |
Context Output
| Path | Type | Description |
|---|---|---|
| Panorama.DynamicUpdates.AntiVirus.CurrentlyInstalled.app-version | String | Version of the dynamic update package. |
| Panorama.DynamicUpdates.AntiVirus.CurrentlyInstalled.current | String | Whether this version is currently active on the device. |
| Panorama.DynamicUpdates.AntiVirus.CurrentlyInstalled.downloaded | String | Whether this version has been downloaded to the device. |
| Panorama.DynamicUpdates.AntiVirus.CurrentlyInstalled.feature-desc | String | Detailed description of features provided. |
| Panorama.DynamicUpdates.AntiVirus.CurrentlyInstalled.features | String | Features provided by this version. |
| Panorama.DynamicUpdates.AntiVirus.CurrentlyInstalled.filename | String | Filename of the dynamic update. |
| Panorama.DynamicUpdates.AntiVirus.CurrentlyInstalled.installing | String | Whether this version is being installed by a running job on the device. |
| Panorama.DynamicUpdates.AntiVirus.CurrentlyInstalled.previous | String | Whether this version was previously active on the system and can be reverted to. |
| Panorama.DynamicUpdates.AntiVirus.CurrentlyInstalled.release-notes | String | Link to release notes about the dynamic update package. |
| Panorama.DynamicUpdates.AntiVirus.CurrentlyInstalled.released-on | Date | Date this version was released. |
| Panorama.DynamicUpdates.AntiVirus.CurrentlyInstalled.sha256 | String | SHA256 hash of the dynamic update package file. |
| Panorama.DynamicUpdates.AntiVirus.CurrentlyInstalled.size | String | Size of the dynamic update package file. |
| Panorama.DynamicUpdates.AntiVirus.CurrentlyInstalled.size-kb | String | Size (in KB) of the dynamic update file. |
| Panorama.DynamicUpdates.AntiVirus.CurrentlyInstalled.update-type | String | Type of update package (Full, Incremental, etc) |
| Panorama.DynamicUpdates.AntiVirus.CurrentlyInstalled.version | String | Version of the dynamic update package. |
| Panorama.DynamicUpdates.AntiVirus.IsUpToDate | Boolean | Whether the latest available AntiVirus package is active on the device. |
| Panorama.DynamicUpdates.AntiVirus.LatestAvailable.app-version | String | Version of the dynamic update package. |
| Panorama.DynamicUpdates.AntiVirus.LatestAvailable.current | String | Whether this version is currently active on the device. |
| Panorama.DynamicUpdates.AntiVirus.LatestAvailable.downloaded | String | Whether this version has been downloaded to the device. |
| Panorama.DynamicUpdates.AntiVirus.LatestAvailable.feature-desc | String | Detailed description of features provided. |
| Panorama.DynamicUpdates.AntiVirus.LatestAvailable.features | String | Features provided by this version. |
| Panorama.DynamicUpdates.AntiVirus.LatestAvailable.filename | String | Filename of the dynamic update. |
| Panorama.DynamicUpdates.AntiVirus.LatestAvailable.installing | String | Whether this version is being installed by a running job on the device. |
| Panorama.DynamicUpdates.AntiVirus.LatestAvailable.previous | String | Whether this version was previously active on the system and can be reverted to. |
| Panorama.DynamicUpdates.AntiVirus.LatestAvailable.release-notes | String | Link to release notes about the dynamic update package. |
| Panorama.DynamicUpdates.AntiVirus.LatestAvailable.released-on | Date | Date this version was released. |
| Panorama.DynamicUpdates.AntiVirus.LatestAvailable.sha256 | String | SHA256 hash of the dynamic update package file. |
| Panorama.DynamicUpdates.AntiVirus.LatestAvailable.size | String | Size of the dynamic update package file. |
| Panorama.DynamicUpdates.AntiVirus.LatestAvailable.size-kb | String | Size (in KB) of the dynamic update file. |
| Panorama.DynamicUpdates.AntiVirus.LatestAvailable.update-type | String | Type of update package (Full, Incremental, etc) |
| Panorama.DynamicUpdates.AntiVirus.LatestAvailable.version | String | Version of the dynamic update package. |
| Panorama.DynamicUpdates.Content.CurrentlyInstalled.app-version | String | Version of the dynamic update package. |
| Panorama.DynamicUpdates.Content.CurrentlyInstalled.current | String | Whether this version is currently active on the device. |
| Panorama.DynamicUpdates.Content.CurrentlyInstalled.downloaded | String | Whether this version has been downloaded to the device. |
| Panorama.DynamicUpdates.Content.CurrentlyInstalled.feature-desc | String | Detailed description of features provided. |
| Panorama.DynamicUpdates.Content.CurrentlyInstalled.features | String | Features provided by this version. |
| Panorama.DynamicUpdates.Content.CurrentlyInstalled.filename | String | Filename of the dynamic update. |
| Panorama.DynamicUpdates.Content.CurrentlyInstalled.installing | String | Whether this version is being installed by a running job on the device. |
| Panorama.DynamicUpdates.Content.CurrentlyInstalled.previous | String | Whether this version was previously active on the system and can be reverted to. |
| Panorama.DynamicUpdates.Content.CurrentlyInstalled.release-notes | String | Link to release notes about the dynamic update package. |
| Panorama.DynamicUpdates.Content.CurrentlyInstalled.released-on | Date | Date this version was released. |
| Panorama.DynamicUpdates.Content.CurrentlyInstalled.sha256 | String | SHA256 hash of the dynamic update package file. |
| Panorama.DynamicUpdates.Content.CurrentlyInstalled.size | String | Size of the dynamic update package file. |
| Panorama.DynamicUpdates.Content.CurrentlyInstalled.size-kb | String | Size (in KB) of the dynamic update file. |
| Panorama.DynamicUpdates.Content.CurrentlyInstalled.update-type | String | Type of update package (Full, Incremental, etc) |
| Panorama.DynamicUpdates.Content.CurrentlyInstalled.version | String | Version of the dynamic update package. |
| Panorama.DynamicUpdates.Content.IsUpToDate | Boolean | Whether the latest available App/Threat package is active on the device. |
| Panorama.DynamicUpdates.Content.LatestAvailable.app-version | String | Version of the dynamic update package. |
| Panorama.DynamicUpdates.Content.LatestAvailable.current | String | Whether this version is currently active on the device. |
| Panorama.DynamicUpdates.Content.LatestAvailable.downloaded | String | Whether this version has been downloaded to the device. |
| Panorama.DynamicUpdates.Content.LatestAvailable.feature-desc | String | Detailed description of features provided. |
| Panorama.DynamicUpdates.Content.LatestAvailable.features | String | Features provided by this version. |
| Panorama.DynamicUpdates.Content.LatestAvailable.filename | String | Filename of the dynamic update. |
| Panorama.DynamicUpdates.Content.LatestAvailable.installing | String | Whether this version is being installed by a running job on the device. |
| Panorama.DynamicUpdates.Content.LatestAvailable.previous | String | Whether this version was previously active on the system and can be reverted to. |
| Panorama.DynamicUpdates.Content.LatestAvailable.release-notes | String | Link to release notes about the dynamic update package. |
| Panorama.DynamicUpdates.Content.LatestAvailable.released-on | Date | Date this version was released. |
| Panorama.DynamicUpdates.Content.LatestAvailable.sha256 | String | SHA256 hash of the dynamic update package file. |
| Panorama.DynamicUpdates.Content.LatestAvailable.size | String | Size of the dynamic update package file. |
| Panorama.DynamicUpdates.Content.LatestAvailable.size-kb | String | Size (in KB) of the dynamic update file. |
| Panorama.DynamicUpdates.Content.LatestAvailable.update-type | String | Type of update package (Full, Incremental, etc) |
| Panorama.DynamicUpdates.Content.LatestAvailable.version | String | Version of the dynamic update package. |
| Panorama.DynamicUpdates.ContentTypesOutOfDate.Count | Number | The total number of active Dynamic Updates that have updates available. |
| Panorama.DynamicUpdates.GP.CurrentlyInstalled.app-version | String | Version of the dynamic update package. |
| Panorama.DynamicUpdates.GP.CurrentlyInstalled.current | String | Whether this version is currently active on the device. |
| Panorama.DynamicUpdates.GP.CurrentlyInstalled.downloaded | String | Whether this version has been downloaded to the device. |
| Panorama.DynamicUpdates.GP.CurrentlyInstalled.feature-desc | String | Detailed description of features provided. |
| Panorama.DynamicUpdates.GP.CurrentlyInstalled.features | String | Features provided by this version. |
| Panorama.DynamicUpdates.GP.CurrentlyInstalled.filename | String | Filename of the dynamic update. |
| Panorama.DynamicUpdates.GP.CurrentlyInstalled.installing | String | Whether this version is being installed by a running job on the device. |
| Panorama.DynamicUpdates.GP.CurrentlyInstalled.previous | String | Whether this version was previously active on the system and can be reverted to. |
| Panorama.DynamicUpdates.GP.CurrentlyInstalled.release-notes | String | Link to release notes about the dynamic update package. |
| Panorama.DynamicUpdates.GP.CurrentlyInstalled.released-on | Date | Date this version was released. |
| Panorama.DynamicUpdates.GP.CurrentlyInstalled.sha256 | String | SHA256 hash of the dynamic update package file. |
| Panorama.DynamicUpdates.GP.CurrentlyInstalled.size | String | Size of the dynamic update package file. |
| Panorama.DynamicUpdates.GP.CurrentlyInstalled.size-kb | String | Size (in KB) of the dynamic update file. |
| Panorama.DynamicUpdates.GP.CurrentlyInstalled.update-type | String | Type of update package (Full, Incremental, etc) |
| Panorama.DynamicUpdates.GP.CurrentlyInstalled.version | String | Version of the dynamic update package. |
| Panorama.DynamicUpdates.GP.IsUpToDate | Boolean | Whether the latest available GP Clientless VPN package is active on the device. |
| Panorama.DynamicUpdates.GP.LatestAvailable.app-version | String | Version of the dynamic update package. |
| Panorama.DynamicUpdates.GP.LatestAvailable.current | String | Whether this version is currently active on the device. |
| Panorama.DynamicUpdates.GP.LatestAvailable.downloaded | String | Whether this version has been downloaded to the device. |
| Panorama.DynamicUpdates.GP.LatestAvailable.feature-desc | String | Detailed description of features provided. |
| Panorama.DynamicUpdates.GP.LatestAvailable.features | String | Features provided by this version. |
| Panorama.DynamicUpdates.GP.LatestAvailable.filename | String | Filename of the dynamic update. |
| Panorama.DynamicUpdates.GP.LatestAvailable.installing | String | Whether this version is being installed by a running job on the device. |
| Panorama.DynamicUpdates.GP.LatestAvailable.previous | String | Whether this version was previously active on the system and can be reverted to. |
| Panorama.DynamicUpdates.GP.LatestAvailable.release-notes | String | Link to release notes about the dynamic update package. |
| Panorama.DynamicUpdates.GP.LatestAvailable.released-on | Date | Date this version was released. |
| Panorama.DynamicUpdates.GP.LatestAvailable.sha256 | String | SHA256 hash of the dynamic update package file. |
| Panorama.DynamicUpdates.GP.LatestAvailable.size | String | Size of the dynamic update package file. |
| Panorama.DynamicUpdates.GP.LatestAvailable.size-kb | String | Size (in KB) of the dynamic update file. |
| Panorama.DynamicUpdates.GP.LatestAvailable.update-type | String | Type of update package (Full, Incremental, etc) |
| Panorama.DynamicUpdates.GP.LatestAvailable.version | String | Version of the dynamic update package. |
| Panorama.DynamicUpdates.WildFire.CurrentlyInstalled.app-version | String | Version of the dynamic update package. |
| Panorama.DynamicUpdates.WildFire.CurrentlyInstalled.current | String | Whether this version is currently active on the device. |
| Panorama.DynamicUpdates.WildFire.CurrentlyInstalled.downloaded | String | Whether this version has been downloaded to the device. |
| Panorama.DynamicUpdates.WildFire.CurrentlyInstalled.feature-desc | String | Detailed description of features provided. |
| Panorama.DynamicUpdates.WildFire.CurrentlyInstalled.features | String | Features provided by this version. |
| Panorama.DynamicUpdates.WildFire.CurrentlyInstalled.filename | String | Filename of the dynamic update. |
| Panorama.DynamicUpdates.WildFire.CurrentlyInstalled.installing | String | Whether this version is being installed by a running job on the device. |
| Panorama.DynamicUpdates.WildFire.CurrentlyInstalled.previous | String | Whether this version was previously active on the system and can be reverted to. |
| Panorama.DynamicUpdates.WildFire.CurrentlyInstalled.release-notes | String | Link to release notes about the dynamic update package. |
| Panorama.DynamicUpdates.WildFire.CurrentlyInstalled.released-on | Date | Date this version was released. |
| Panorama.DynamicUpdates.WildFire.CurrentlyInstalled.sha256 | String | SHA256 hash of the dynamic update package file. |
| Panorama.DynamicUpdates.WildFire.CurrentlyInstalled.size | String | Size of the dynamic update package file. |
| Panorama.DynamicUpdates.WildFire.CurrentlyInstalled.size-kb | String | Size (in KB) of the dynamic update file. |
| Panorama.DynamicUpdates.WildFire.CurrentlyInstalled.update-type | String | Type of update package (Full, Incremental, etc) |
| Panorama.DynamicUpdates.WildFire.CurrentlyInstalled.version | String | Version of the dynamic update package. |
| Panorama.DynamicUpdates.WildFire.IsUpToDate | Boolean | Whether the latest available WildFire package is active on the device. |
| Panorama.DynamicUpdates.WildFire.LatestAvailable.app-version | String | Version of the dynamic update package. |
| Panorama.DynamicUpdates.WildFire.LatestAvailable.current | String | Whether this version is currently active on the device. |
| Panorama.DynamicUpdates.WildFire.LatestAvailable.downloaded | String | Whether this version has been downloaded to the device. |
| Panorama.DynamicUpdates.WildFire.LatestAvailable.feature-desc | String | Detailed description of features provided. |
| Panorama.DynamicUpdates.WildFire.LatestAvailable.features | String | Features provided by this version. |
| Panorama.DynamicUpdates.WildFire.LatestAvailable.filename | String | Filename of the dynamic update. |
| Panorama.DynamicUpdates.WildFire.LatestAvailable.installing | String | Whether this version is being installed by a running job on the device. |
| Panorama.DynamicUpdates.WildFire.LatestAvailable.previous | String | Whether this version was previously active on the system and can be reverted to. |
| Panorama.DynamicUpdates.WildFire.LatestAvailable.release-notes | String | Link to release notes about the dynamic update package. |
| Panorama.DynamicUpdates.WildFire.LatestAvailable.released-on | Date | Date this version was released. |
| Panorama.DynamicUpdates.WildFire.LatestAvailable.sha256 | String | SHA256 hash of the dynamic update package file. |
| Panorama.DynamicUpdates.WildFire.LatestAvailable.size | String | Size of the dynamic update package file. |
| Panorama.DynamicUpdates.WildFire.LatestAvailable.size-kb | String | Size (in KB) of the dynamic update file. |
| Panorama.DynamicUpdates.WildFire.LatestAvailable.update-type | String | Type of update package (Full, Incremental, etc) |
| Panorama.DynamicUpdates.WildFire.LatestAvailable.version | String | Version of the dynamic update package. |
pan-os-download-latest-antivirus-update
Downloads the latest antivirus dynamic update.
Base Command
pan-os-download-latest-antivirus-update
Input
| Argument Name | Description | Required |
|---|---|---|
| target | Serial number of the firewall on which to run the command. Use only for a Panorama instance. | Optional |
| polling | When set to false, the function will not use polling and will immediately return the ID of the download job. Possible values are: true, false. | Optional |
| timeout_in_seconds | The polling timeout in seconds. When polling is enabled, the command will keep checking the download status until this timeout is reached. Default is 3600. | Optional |
| interval_in_seconds | The polling interval in seconds. Controls how often the download status is checked. Default is 30. | Optional |
Context Output
| Path | Type | Description |
|---|---|---|
| Panorama.AntiVirus.Download.JobID | String | The job ID of the antivirus download. |
| Panorama.AntiVirus.Download.Status | String | The antivirus download status. |
| Panorama.AntiVirus.Download.Details | String | The download job details. |
pan-os-download-latest-wildfire-update
Downloads the latest WildFire dynamic update.
Base Command
pan-os-download-latest-wildfire-update
Input
| Argument Name | Description | Required |
|---|---|---|
| target | Serial number of the firewall on which to run the command. Use only for a Panorama instance. | Optional |
| polling | When set to false, the function will not use polling and will immediately return the ID of the download job. Possible values are: true, false. | Optional |
| timeout_in_seconds | The polling timeout in seconds. When polling is enabled, the command will keep checking the download status until this timeout is reached. Default is 3600. | Optional |
| interval_in_seconds | The polling interval in seconds. Controls how often the download status is checked. Default is 30. | Optional |
Context Output
| Path | Type | Description |
|---|---|---|
| Panorama.WildFire.Download.JobID | String | The job ID of the WildFire download. |
| Panorama.WildFire.Download.Status | String | The WildFire download status. |
| Panorama.WildFire.Download.Details | String | The download job details. |
pan-os-download-latest-gp-update
Downloads the latest GlobalProtect Clientless VPN dynamic update.
Base Command
pan-os-download-latest-gp-update
Input
| Argument Name | Description | Required |
|---|---|---|
| target | Serial number of the firewall on which to run the command. Use only for a Panorama instance. | Optional |
| polling | When set to false, the function will not use polling and will immediately return the ID of the download job. Possible values are: true, false. | Optional |
| timeout_in_seconds | The polling timeout in seconds. When polling is enabled, the command will keep checking the download status until this timeout is reached. Default is 3600. | Optional |
| interval_in_seconds | The polling interval in seconds. Controls how often the download status is checked. Default is 30. | Optional |
Context Output
| Path | Type | Description |
|---|---|---|
| Panorama.GP.Download.JobID | String | The job ID of the GlobalProtect Clientless VPN download. |
| Panorama.GP.Download.Status | String | The GlobalProtect Clientless VPN download status. |
| Panorama.GP.Download.Details | String | The download job details. |
pan-os-install-latest-antivirus-update
Installs the latest Antivirus update.
Base Command
pan-os-install-latest-antivirus-update
Input
| Argument Name | Description | Required |
|---|---|---|
| target | Serial number of the firewall on which to run the command. Use only for a Panorama instance. | Optional |
| polling | When set to false, the function will not use polling and will immediately return the ID of the install job. Possible values are: true, false. | Optional |
| timeout_in_seconds | The polling timeout in seconds. When polling is enabled, the command will keep checking the install status until this timeout is reached. Default is 3600. | Optional |
| interval_in_seconds | The polling interval in seconds. Controls how often the install status is checked. Default is 30. | Optional |
Context Output
| Path | Type | Description |
|---|---|---|
| Panorama.AntiVirus.Install.JobID | String | The job ID of the installation. |
| Panorama.AntiVirus.Install.Status | String | The installation status. |
| Panorama.AntiVirus.Install.Details | String | The install job details. |
pan-os-install-latest-wildfire-update
Installs the latest WildFire dynamic update.
Base Command
pan-os-install-latest-wildfire-update
Input
| Argument Name | Description | Required |
|---|---|---|
| target | Serial number of the firewall on which to run the command. Use only for a Panorama instance. | Optional |
| polling | When set to false, the function will not use polling and will immediately return the ID of the install job. Possible values are: true, false. | Optional |
| timeout_in_seconds | The polling timeout in seconds. When polling is enabled, the command will keep checking the install status until this timeout is reached. Default is 3600. | Optional |
| interval_in_seconds | The polling interval in seconds. Controls how often the install status is checked. Default is 30. | Optional |
Context Output
| Path | Type | Description |
|---|---|---|
| Panorama.WildFire.Install.JobID | String | The job ID of the installation. |
| Panorama.WildFire.Install.Status | String | The installation status. |
| Panorama.WildFire.Install.Details | String | The install job details. |
pan-os-install-latest-gp-update
Installs the latest GlobalProtect Clientless VPN dynamic update.
Base Command
pan-os-install-latest-gp-update
Input
| Argument Name | Description | Required |
|---|---|---|
| target | Serial number of the firewall on which to run the command. Use only for a Panorama instance. | Optional |
| polling | When set to false, the function will not use polling and will immediately return the ID of the install job. Possible values are: true, false. | Optional |
| timeout_in_seconds | The polling timeout in seconds. When polling is enabled, the command will keep checking the install status until this timeout is reached. Default is 3600. | Optional |
| interval_in_seconds | The polling interval in seconds. Controls how often the install status is checked. Default is 30. | Optional |
Context Output
| Path | Type | Description |
|---|---|---|
| Panorama.GP.Install.JobID | String | The job ID of the installation. |
| Panorama.GP.Install.Status | String | The installation status. |
| Panorama.GP.Install.Details | String | The install job details. |
pan-os-disable-rule
Disables a policy rule.
Base Command
pan-os-disable-rule
Input
| Argument Name | Description | Required |
|---|---|---|
| rulename | The name of the rule to disable. | Required |
| pre_post | The pre-rule or post-rule (Panorama instances). Possible values are: pre-rulebase, post-rulebase. | Optional |
| device-group | The device group where the rule is configured (Panorama instances). | Optional |
| target | Serial number of the firewall on which to run the command. Use only for a Panorama instance. | Optional |
| rulebase | The rulebase from which to disable the rule. Possible values are: security, application-override, authentication, decryption, nat, pbf. Default is security. | Required |
| vsys | The Firewall VSYS to disable the rule on. Use for disabling local rules on a firewall via Panorama or to specify a different VSYS than set in Integration parameters. Default is vsys1. | Optional |
Context Output
| Path | Type | Description |
|---|---|---|
| Panorama.SecurityRule.Name | string | The rule name. |
| Panorama.SecurityRule.DeviceGroup | string | The device group for the rule (Panorama instances). |
| Panorama.NAT.Name | string | The rule name. |
| Panorama.NAT.DeviceGroup | string | The device group for the rule (Panorama instances). |
| Panorama.SSLRule.Name | string | The rule name. |
| Panorama.SSLRule.DeviceGroup | string | The device group for the rule (Panorama instances). |
| Panorama.PBF.Name | string | The rule name. |
| Panorama.PBF.DeviceGroup | string | The device group for the rule (Panorama instances). |
| Panorama.AuthRule.Name | string | The rule name. |
| Panorama.AuthRule.DeviceGroup | string | The device group for the rule (Panorama instances). |
| Panorama.AppOverride.Name | string | The rule name. |
| Panorama.AppOverride.DeviceGroup | string | The device group for the rule (Panorama instances). |
| Panorama.CleanedUpRules.Category | string | The category of rule that was cleaned up (Local or Panorama). |
| Panorama.CleanedUpRules.AppliedAction | string | The applied cleanup action (Disabled or Deleted). |
| Panorama.CleanedUpRules.DeviceGroup | string | The device group where the rule was cleaned up from (Panorama instances). |
| Panorama.CleanedUpRules.PrePost | string | The location where the rule was cleaned up from (Panorama instances). |
| Panorama.CleanedUpRules.RuleName | string | The name of the rule. |
| Panorama.CleanedUpRules.Rulebase | string | The rulebase where the rule was cleaned up from (e.g. ‘security’, ‘nat’). |
| Panorama.CleanedUpRules.Target | string | The target firewall serial number, if provided. |
| Panorama.CleanedUpRules.Vsys | string | The VSYS where the rule was cleaned up from. |
pan-os-get-rule-hitcounts
Gets rule hit counts from the firewall. When connected to Panorama this command can be run on any firewall managed by it.
Base Command
pan-os-get-rule-hitcounts
Input
| Argument Name | Description | Required |
|---|---|---|
| device_filter_string | The string by which to filter the results to only show specific hostnames or serial numbers. | Optional |
| target | The target number of the firewall. Used only on a Panorama instance. | Optional |
| rulebase | The firewall rulebase to check. Possible values are: application-override, authentication, decryption, dos, nat, network-packet-broker, pbf, qos, sdwan, security, tunnel-inspect. Default is security. | Optional |
| vsys | The firewall VSYS name to check. Returns results for all VSYS if left blank. Default is all. | Optional |
| rules | Comma-separated list of rule names to check. Returns results for all rules if left blank. Default is all. | Optional |
| unused_only | If set to true, only returns rules with a hit count of 0. Possible values are: true, false. Default is false. | Optional |
| no_new_hits_since | Shows rules that have had hits, but not after the date provided (in the format YYYY/MM/DD HH:MM:SS). | Optional |
| pre_post | The pre-rule or post-rule (Panorama instances only). When set, only rules pushed from Panorama at the specified position are returned. Possible values are: pre-rulebase, post-rulebase. | Optional |
Context Output
| Path | Type | Description |
|---|---|---|
| PANOS.RuleHitCount.first_hit_timestamp | Date | Timestamp when the rule was first hit. |
| PANOS.RuleHitCount.from_dg_name | String | Name of the device group the rule is inherited from. |
| PANOS.RuleHitCount.hit_count | Number | Number of hits for the rule. |
| PANOS.RuleHitCount.hostid | String | Serial number of the firewall the entry was fetched from. |
| PANOS.RuleHitCount.instanceName | String | Name of the PAN-OS Integration Instance used to fetch the entry. |
| PANOS.RuleHitCount.instanceType | String | The type of the PAN-OS Integration Instance running the command (panorama or firewall). |
| PANOS.RuleHitCount.is_from_panorama | Boolean | Indicates if the rule was pushed from Panorama (true) or is local to the firewall (false). |
| PANOS.RuleHitCount.last_hit_timestamp | Date | Timestamp when the rule was most recently hit. |
| PANOS.RuleHitCount.last_reset_timestamp | Date | Timestamp when hit count data was last reset. |
| PANOS.RuleHitCount.latest | String | Value of the “latest” property returned by the API. |
| PANOS.RuleHitCount.name | String | Name of the rule. |
| PANOS.RuleHitCount.position | String | Indicates the position of the rule pushed from Panorama (pre_rulebase or post_rulebase). |
| PANOS.RuleHitCount.rule_creation_timestamp | Date | Timestamp when the rule was created. |
| PANOS.RuleHitCount.rule_modification_timestamp | Date | Timestamp when the rule was most recently modified. |
| PANOS.RuleHitCount.rulebase | String | The rulebase of the rule (such as security, nat, and so on). |
| PANOS.RuleHitCount.vsys | String | The name of the firewall VSYS. |
<~PLATFORM>
License Requirements
The following configuration parameters require one of these licenses: Cortex XSIAM or Agentix:
- Fetch incidents
</~PLATFORM>
Configuration parameters
server— Server URL (e.g., https://192.168.0.1) (required)credentials—port— Port (e.g 443)device_group— Device group - Panorama instances only (write shared for Shared location)vsys— Vsys - Firewall instances onlytemplate— Template - Panorama instances onlyuse_url_filtering— Use URL Filtering for auto enrichmentadditional_suspicious— URL Filtering Additional suspicious categories. CSV list of categories that will be considered suspicious.additional_malicious— URL Filtering Additional malicious categories. CSV list of categories that will be considered malicious.insecure— Trust any certificate (not secure)proxy— Use system proxy settingskey— API Key (Deprecated)integrationReliability— Source ReliabilityfeedExpirationPolicy—feedExpirationInterval—isFetch— Fetch incidentsfirst_fetch— First fetch timestamp (<number> <time unit>, e.g., 12 hours, 7 days)max_fetch— Max incidents per fetch (for each selected Log Type Query)log_types— Log Typefetch_job_polling_max_num_attempts— Log type max number of job pulling attemptstraffic_query— Traffic Log Type Querythreat_query— Threat Log Type Queryurl_query— URL Log Type Querydata_query— Data Log Type Querycorrelation_query— Correlation Log Type Querysystem_query— System Log Type Querywildfire_query— Wildfire Submission Log Type Querydecryption_query— Decryption Log Type QueryincidentType— Incident typeincidentFetchInterval— Incidents Fetch Interval
Commands (289)
-
pan-osRuns any command supported in the API.
-
pan-os-add-profile-exceptionAdd an exception to a Vulnerability Protection profile or Anti Spyware profile.
-
pan-os-add-static-routeAdds a static route.
-
pan-os-apply-dns-signature-policyEnables assigning EDL to the anti-spyware profile under "DNS Signature Policies".
-
pan-os-apply-security-profileApplies a security profile to specific rules or rules with a specific tag.
-
pan-os-block-vulnerabilitySets a vulnerability signature to block mode.
-
pan-os-check-dynamic-updates-statusChecks for the latest available dynamic update versions and returns a list of latest available / currently installed content. When running from a Panorama instance, the 'target' argument must be specified.
-
pan-os-check-latest-panos-softwareChecks the PAN-OS software version from the repository.
-
pan-os-check-logs-statusChecks the status of a logs query.
-
pan-os-check-traffic-logs-statusDeprecatedDeprecated. Use the pan-os-check-logs-status command instead.
-
pan-os-commitCommits a configuration to the Palo Alto firewall or Panorama, validates if a commit was successful if using polling="true" otherwise does not validate if the commit was successful. Committing to Panorama does not push the configuration to the firewalls. To push the configuration, run the panorama-push-to-device-group command.
-
pan-os-commit-statusReturns commit status for a configuration.
-
pan-os-config-get-objectSearches and returns a reference for the given object type and name. If no name is provided, all objects of the given type will be returned. Note this ONLY returns the object name and its location in the configuration hierachy, not the entire object.
-
pan-os-content-update-download-statusChecks the download status of an app/threat dynamic update.
-
pan-os-content-update-install-statusGets the installation status of the app/threat dynamic update.
-
pan-os-create-addressCreates an address object.
-
pan-os-create-address-groupCreates a static or dynamic address group.
-
pan-os-create-anti-spyware-best-practice-profileCreates an Anti-Spyware best practice profile.
-
pan-os-create-antivirus-best-practice-profileCreates an antivirus best practice profile.
-
pan-os-create-application-groupCreates a new application group rule in a Panorama/firewall instance.
-
pan-os-create-custom-url-categoryCreates a custom URL category.
-
pan-os-create-edlCreates an external dynamic list.
-
pan-os-create-file-blocking-best-practice-profileCreates a file blocking best practice profile.
-
pan-os-create-master-keyCreate a default master key that encrypts all the private keys and passwords in the configuration. This command is harmful because it invalidates the current API key and requires re-configuration of the integration instance.
-
pan-os-create-nat-ruleCreates a new NAT rule in a Panorama/firewall instance.
-
pan-os-create-pbf-ruleCreates a new policy-based-forwarding (PBF) rule in a Panorama/firewall instance.
-
pan-os-create-redistribution-profileCreates a new redistribution-profile under a virtual-router for a Panorama/firewall instance.
-
pan-os-create-ruleCreates a policy rule.
-
pan-os-create-security-profile-groupCreates a new security profile group in Panorama.
-
pan-os-create-serviceCreates a service.
-
pan-os-create-service-groupCreates a service group.
-
pan-os-create-tagCreates a new tag in Panorama.
-
pan-os-create-url-filterCreates a URL filtering rule.
-
pan-os-create-url-filtering-best-practice-profileCreates a URL filtering best practice profile.
-
pan-os-create-vulnerability-best-practice-profileCreates a vulnerability protection best practice profile.
-
pan-os-create-wildfire-best-practice-profileCreates a WildFire analysis best practice profile.
-
pan-os-custom-block-ruleCreates a custom block policy rule.
-
pan-os-delete-addressDeletes an address object.
-
pan-os-delete-address-groupDeletes an address group.
-
pan-os-delete-application-groupDeletes an application-group.
-
pan-os-delete-custom-url-categoryDeletes a custom URL category.
-
pan-os-delete-edlDeletes an external dynamic list.
-
pan-os-delete-nat-ruleDeletes a NAT rule.
-
pan-os-delete-pbf-ruleDeletes a PBF rule.
-
pan-os-delete-profile-exceptionDelete an exception to a Vulnerability Protection profile or Anti Spyware profile.
-
pan-os-delete-redistribution-profileDeletes a redistribution-profile from a virtual-router.
-
pan-os-delete-ruleDeletes a policy rule.
-
pan-os-delete-security-profile-groupDeletes a security profile group from Panorama.
-
pan-os-delete-serviceDeletes a service.
-
pan-os-delete-service-groupDeletes a service group.
-
pan-os-delete-static-routeDeletes a static route.
-
pan-os-delete-tagDeletes a tag from Panorama.
-
pan-os-delete-url-filterDeletes a URL filtering rule.
-
pan-os-device-rebootReboots the firewall device.
-
pan-os-disable-ruleDisables a policy rule.
-
pan-os-download-latest-antivirus-updateDownloads the latest antivirus dynamic update.
-
pan-os-download-latest-content-updateDownloads the latest app/threat dynamic update.
-
pan-os-download-latest-gp-updateDownloads the latest GlobalProtect Clientless VPN dynamic update.
-
pan-os-download-latest-wildfire-updateDownloads the latest WildFire dynamic update.
-
pan-os-download-panos-statusGets the download status of the target PAN-OS software.
-
pan-os-download-panos-versionDownloads the target PAN-OS software version to install on the target device.
-
pan-os-edit-addressEdits an address object.
-
pan-os-edit-address-groupEdits a static or dynamic address group.
-
pan-os-edit-application-groupEdits an application-group.
-
pan-os-edit-custom-url-categoryAdds or removes sites to and from a custom URL category.
-
pan-os-edit-edlModifies an element of an external dynamic list.
-
pan-os-edit-nat-ruleEdits a NAT rule.
-
pan-os-edit-pbf-ruleEdits a PBF rule.
-
pan-os-edit-profile-exceptionEdit an exception to a Vulnerability Protection profile or Anti Spyware profile.
-
pan-os-edit-redistribution-profileEdits a redistribution-profile in a virtual-router.
-
pan-os-edit-ruleEdits a policy rule.
-
pan-os-edit-security-profile-groupEdits the security profile group in Panorama.
-
pan-os-edit-service-groupEdits a service group.
-
pan-os-edit-tagEdits a tag in Panorama.
-
pan-os-edit-url-filterEdits a URL filtering rule.
-
pan-os-enforce-wildfire-best-practiceEnforces Wildfire best practices to upload files to the maximum size, forwards all file types, and updates the schedule.
-
pan-os-export-tech-support-fileExports a tech support file (TSF).
-
pan-os-get-addressReturns address details for the supplied address name.
-
pan-os-get-address-groupGets details for the specified address group.
-
pan-os-get-anti-spyware-best-practiceGet anti-spyware best practices.
-
pan-os-get-antivirus-best-practiceGets anti-virus best practices.
-
pan-os-get-audit-commentGets the audit comment of a rule.
-
pan-os-get-certificate-infoGathers the name, expiration date, and expiration status of certificates configured locally on a Firewall or pushed from Panorama, as seen under Certificate Management.
-
pan-os-get-custom-url-categoryReturns information for a custom URL category.
-
pan-os-get-edlReturns information for an external dynamic list.
-
pan-os-get-file-blocking-best-practiceGets file-blocking best practices.
-
pan-os-get-licensesGets information about available PAN-OS licenses and their statuses.
-
pan-os-get-logsRetrieves the data of a logs query.
-
pan-os-get-master-key-detailsShow the details of the default master key that encrypts all the private keys and passwords in the configuration.
-
pan-os-get-merged-configPull the merged config file.
-
pan-os-get-pcapReturns a PCAP file. The recommended maximum file size is 5 MB. If the limit is exceeded, you may need to connect to the firewall and run the scp export command in order to export the PCAP file. See the Palo Alto Networks documentation.
-
pan-os-get-predefined-threats-listGets the predefined threats list from a Firewall or Panorama and stores it as a JSON file in the context.
-
pan-os-get-rule-hitcountsGets rule hit counts from the firewall. When connected to Panorama this command can be run on any firewall managed by it.
-
pan-os-get-running-configPull the running config file.
-
pan-os-get-security-profilesGets information for the specified security profile.
-
pan-os-get-serviceReturns service details for the supplied service name.
-
pan-os-get-service-groupReturns details for the specified service group.
-
pan-os-get-ssl-decryption-rulesGets SSL decryption rules.
-
pan-os-get-static-routeReturns the specified static route of a virtual router.
-
pan-os-get-traffic-logsDeprecatedDeprecated. Use the pan-os-get-logs command instead.
-
pan-os-get-url-categoryGets a URL category from URL filtering. This command is only available on firewall devices.
-
pan-os-get-url-category-from-cloudReturns a URL category from URL filtering. This command is only available on firewall devices.
-
pan-os-get-url-category-from-hostReturns a URL category from URL filtering. This command is only available on firewall devices.
-
pan-os-get-url-filterReturns information for a URL filtering rule.
-
pan-os-get-url-filtering-best-practiceViews URL filtering best practices.
-
pan-os-get-vulnerability-protection-best-practiceGets vulnerability-protection best practices.
-
pan-os-get-wildfire-best-practiceViews WildFire best practices.
-
pan-os-get-wildfire-configurationRetrieves the Wildfire configuration.
-
pan-os-hygiene-check-log-forwardingChecks that at least one log forwarding profile is configured according to best practices.
-
pan-os-hygiene-check-security-rulesChecks that security rules are configured correctly.
-
pan-os-hygiene-check-security-zonesChecks that configured security zones have correct settings.
-
pan-os-hygiene-check-spyware-profilesChecks the configured anti-spyware profiles to ensure at least one meets best practices.
-
pan-os-hygiene-check-url-filtering-profilesChecks the configured URL filtering profiles to ensure at least one meets best practices of blocking the following URL categories - abused-drugs, adult, command-and-control, compromised-websites, gambling, grayware, hacking, malware, phishing, questionable, ransomware, scanning-activity, weapons.
-
pan-os-hygiene-check-vulnerability-profilesChecks the configured vulnerability profiles to ensure at least one meets best practices.
-
pan-os-hygiene-conforming-spyware-profilesReturns all anti-spyware profiles that conform to best practices.
-
pan-os-hygiene-conforming-url-filtering-profilesReturns a list of existing PANOS URL filtering objects that conform to best practices.
-
pan-os-hygiene-conforming-vulnerability-profilesReturns all vulnerability profiles that conform to best practices.
-
pan-os-hygiene-fix-log-forwardingFixes log forwarding issues identified by pan-os-hygiene-check-log-forwarding.
-
pan-os-hygiene-fix-security-rule-log-settingsFixes security rules that have incorrect log settings by adding a log forwarding profile and setting.
-
pan-os-hygiene-fix-security-rule-profile-settingsFixes security rules that have incorrect log settings by adding a log forwarding profile and setting.
-
pan-os-hygiene-fix-security-zone-log-settingsFixes security zones that are configured without a valid log forwarding profile.
-
pan-os-install-file-content-updateInstalls a specific content update file.
-
pan-os-install-latest-antivirus-updateInstalls the latest Antivirus update.
-
pan-os-install-latest-content-updateInstalls the latest app/threat dynamic update.
-
pan-os-install-latest-gp-updateInstalls the latest GlobalProtect Clientless VPN dynamic update.
-
pan-os-install-latest-wildfire-updateInstalls the latest WildFire dynamic update.
-
pan-os-install-panos-statusGets the installation status of the PAN-OS software.
-
pan-os-install-panos-versionInstalls the target PAN-OS version on the specified target device.
-
pan-os-list-address-groupsReturns a list of address groups.
-
pan-os-list-addressesReturns a list of addresses.
-
pan-os-list-application-groupsReturns a list of application-groups of either a Panorama/firewall instance.
-
pan-os-list-applicationsReturns a list of applications.
-
pan-os-list-configured-user-id-agentsRetrieves a list of user-ID agents configured in the system.
-
pan-os-list-device-groupsReturns all device groups from Panorama (use only in Panorama instances).
-
pan-os-list-edlsReturns a list of external dynamic lists.
-
pan-os-list-nat-rulesReturns a list of NAT rules of either a Panorama/firewall instance.
-
pan-os-list-pbf-rulesReturns a list of pbf-rules of either a Panorama/firewall instance.
-
pan-os-list-pcapsReturns a list of all PCAP files by PCAP type. Not available for threat PCAPs.
-
pan-os-list-profile-exceptionList the exceptions in a Vulnerability Protection profile or Anti Spyware profile.
-
pan-os-list-redistribution-profilesReturns a list of redistribution-profiles of a specific virtual-router of either a Panorama/firewall instance.
-
pan-os-list-rulesReturns a list of predefined Security Rules. (When passing a query, all other arguments are overridden. Make sure the query includes all the filters you want).
-
pan-os-list-security-profile-groupReturns a list of security profile groups from Panorama.
-
pan-os-list-service-groupsReturns a list of service groups.
-
pan-os-list-servicesReturns a list of addresses.
-
pan-os-list-static-routesLists the static routes of a virtual router.
-
pan-os-list-tagReturns a list of tags from Panorama.
-
pan-os-list-templatesReturns a list of available templates. (To be used only in Panorama instances).
-
pan-os-list-virtual-routersReturns a list of virtual routers of either a Panorama/firewall instance.
-
pan-os-move-ruleChanges the location of a policy rule.
-
pan-os-platform-download-softwareDownloads the provided software version onto the device.
-
pan-os-platform-get-arp-tablesGets all ARP tables from all firewalls in the topology.
-
pan-os-platform-get-available-softwareChecks the devices for software that is available to be installed.
-
pan-os-platform-get-bgp-peersRetrieves all BGP peer information from the PAN-OS firewalls in the topology.
-
pan-os-platform-get-device-groupsGets operational information for all device groups in the Panorama topology, including group names, hierarchy, and associated firewalls. If no filter is provided, the command returns all device groups within the Panorama instance.
-
pan-os-platform-get-device-stateGet the device state from the provided device. Note; This will attempt to connect directly to the provided target to get the device state. If the IP address as reported in "show system info" is unreachable, this command will fail.
-
pan-os-platform-get-global-countersGets global counter information from all the PAN-OS firewalls in the topology.
-
pan-os-platform-get-ha-stateGets the HA state and associated details from the given device and any other details.
-
pan-os-platform-get-jobsGets all the jobs from the devices in the environment, or a single job when the ID is specified. Supports polling when a single job ID is provided.
-
pan-os-platform-get-route-summaryPulls all route summary information from the topology.
-
pan-os-platform-get-routesPulls all route summary information from the topology.
-
pan-os-platform-get-system-infoGets information from all PAN-OS systems in the topology.
-
pan-os-platform-get-system-statusChecks the status of the given device, checking whether it's up or down and if the operational mode is normal. Supports polling to wait until the device becomes available.
-
pan-os-platform-get-template-stacksGets the operational information of the template stacks in the topology.
-
pan-os-platform-install-softwareInstalls the given software version onto the device. Downloads the software first with panorama-download-panos-version.
-
pan-os-platform-rebootReboots the given device by host ID. Warning: This command has no confirmation and the device will immediately reboot. This command can be disruptive.
-
pan-os-platform-update-ha-stateChecks the status of the given device, checking whether it's up or down and if the operational mode is normal.
-
pan-os-push-statusReturns the push status for a configuration.
-
pan-os-push-to-device-groupPushes rules from PAN-OS to the configured device group. In order to push the configuration to Prisma Access managed tenants (single or multi tenancy), use the device group argument with the device group which is associated with the tenant ID. Validates if a push has been successful if polling="true".
-
pan-os-push-to-templatePushes the given PAN-OS template to the given devices or all devices that belong to the template.
-
pan-os-push-to-template-stackPushes the given PAN-OS template-stack to the given devices or all devices that belong to the template stack.
-
pan-os-query-logsThe query logs in Panorama.
-
pan-os-query-traffic-logsDeprecatedDeprecated. Use the pan-os-query-logs command instead.
-
pan-os-refresh-edlRefreshes the specified external dynamic list.
-
pan-os-register-ip-tagRegisters IP addresses to a tag.
-
pan-os-register-user-tagRegisters users to a tag. This command is only available for PAN-OS version 9.x and above.
-
pan-os-remove-security-profileRemoves a security profile to specific rules or rules with a specific tag.
-
pan-os-security-policy-matchChecks whether a session matches a specified security policy. This command is only available on firewall instances.
-
pan-os-show-device-versionShow firewall device software version.
-
pan-os-show-location-ipGets location information for an IP address.
-
pan-os-show-user-id-interfaces-configShows the user ID interface configuration.
-
pan-os-show-zones-configShows the zones configuration.
-
pan-os-unregister-ip-tagUnregisters IP addresses from a tag.
-
pan-os-unregister-user-tagUnregisters users from a tag. This command is only available for PAN-OS version 9.x and higher.
-
pan-os-update-master-keyUpdate the default master key that encrypts all the private keys and passwords in the configuration. This command is harmful because it invalidates the current API key and requires re-configuration of the integration instance.
-
pan-os-upload-content-update-fileUploads a content file to Panorama.
-
pan-os-url-filtering-block-default-categoriesSets default categories to block in the URL filtering profile.
-
panoramaDeprecatedRuns any command supported in the API.
-
panorama-add-static-routeDeprecatedAdds a static route.
-
panorama-apply-security-profileDeprecatedApplies a security profile to specific rules or rules with a specific tag.
-
panorama-block-vulnerabilityDeprecatedSets a vulnerability signature to block mode.
-
panorama-check-latest-panos-softwareDeprecatedChecks the PAN-OS software version from the repository.
-
panorama-check-logs-statusDeprecatedChecks the status of a log query.
-
panorama-check-traffic-logs-statusDeprecatedDeprecated. Use the pan-os-check-logs-status command instead.
-
panorama-commitDeprecatedCommits a configuration to the Palo Alto firewall or Panorama, but does not validate if the commit was successful. Committing to Panorama does not push the configuration to the firewalls. To push the configuration, run the panorama-push-to-device-group command.
-
panorama-commit-statusDeprecatedReturns commit status for a configuration.
-
panorama-content-update-download-statusDeprecatedChecks the download status of a content update.
-
panorama-content-update-install-statusDeprecatedGets the installation status of the content update.
-
panorama-create-addressDeprecatedCreates an address object.
-
panorama-create-address-groupDeprecatedCreates a static or dynamic address group.
-
panorama-create-anti-spyware-best-practice-profileDeprecatedCreates an anti-spyware best practice profile.
-
panorama-create-antivirus-best-practice-profileDeprecatedCreates an antivirus best practice profile.
-
panorama-create-custom-url-categoryDeprecatedCreates a custom URL category.
-
panorama-create-edlDeprecatedCreates an external dynamic list.
-
panorama-create-file-blocking-best-practice-profileDeprecatedCreates a file blocking best practice profile.
-
panorama-create-ruleDeprecatedCreates a policy rule.
-
panorama-create-serviceDeprecatedCreates a service. Note: overrides the service if it already exists.
-
panorama-create-service-groupDeprecatedCreates a service group.
-
panorama-create-url-filterDeprecatedCreates a URL filtering rule.
-
panorama-create-url-filtering-best-practice-profileDeprecatedCreates a URL filtering best practice profile.
-
panorama-create-vulnerability-best-practice-profileDeprecatedCreates a vulnerability protection best practice profile.
-
panorama-create-wildfire-best-practice-profileDeprecatedCreates a WildFire analysis best practice profile.
-
panorama-custom-block-ruleDeprecatedCreates a custom block policy rule.
-
panorama-delete-addressDeprecatedDeletes an address object.
-
panorama-delete-address-groupDeprecatedDeletes an address group.
-
panorama-delete-custom-url-categoryDeprecatedDeletes a custom URL category.
-
panorama-delete-edlDeprecatedDeletes an external dynamic list.
-
panorama-delete-ruleDeprecatedDeletes a policy rule.
-
panorama-delete-serviceDeprecatedDeletes a service.
-
panorama-delete-service-groupDeprecatedDeletes a service group.
-
panorama-delete-static-routeDeprecatedDeletes a static route.
-
panorama-delete-url-filterDeprecatedDeletes a URL filtering rule.
-
panorama-device-rebootDeprecatedReboots the firewall device.
-
panorama-download-latest-content-updateDeprecatedDownloads the latest content update.
-
panorama-download-panos-statusDeprecatedGets the download status of the target PAN-OS software.
-
panorama-download-panos-versionDeprecatedDownloads the target PAN-OS software version to install on the target device.
-
panorama-edit-address-groupDeprecatedEdits a static or dynamic address group.
-
panorama-edit-custom-url-categoryDeprecatedAdds or removes sites to and from a custom URL category.
-
panorama-edit-edlDeprecatedModifies an element of an external dynamic list.
-
panorama-edit-ruleDeprecatedEdits a policy rule.
-
panorama-edit-service-groupEdits a service group.
-
panorama-edit-url-filterDeprecatedEdits a URL filtering rule.
-
panorama-enforce-wildfire-best-practiceDeprecatedEnforces wildfire best practices to upload files to the maximum size, forwards all file types, and updates the schedule.
-
panorama-get-addressDeprecatedReturns address details for the supplied address name.
-
panorama-get-address-groupDeprecatedGets details for the specified address group.
-
panorama-get-anti-spyware-best-practiceDeprecatedGets anti-spyware best practices.
-
panorama-get-antivirus-best-practiceDeprecatedGet anti-virus best practices.
-
panorama-get-custom-url-categoryDeprecatedReturns information for a custom URL category.
-
panorama-get-edlDeprecatedReturns information for an external dynamic list.
-
panorama-get-file-blocking-best-practiceDeprecatedGets file-blocking best practices.
-
panorama-get-licensesDeprecatedGets information about available PAN-OS licenses and their statuses.
-
panorama-get-logsRetrieves the data of a logs query.
-
panorama-get-pcapDeprecatedReturns information for a Panorama PCAP file. The recommended maximum file size is 5 MB. If the limit is exceeded, you may need to SSH the firewall and run the scp export command to export the PCAP file. See the Palo Alto Networks documentation.
-
panorama-get-predefined-threats-listDeprecatedGets the predefined threats list from a firewall or Panorama and stores it as a JSON file in the context.
-
panorama-get-security-profilesDeprecatedGets information for the specified security profile.
-
panorama-get-serviceDeprecatedReturns service details for the supplied service name.
-
panorama-get-service-groupDeprecatedReturns details for the specified service group.
-
panorama-get-ssl-decryption-rulesDeprecatedGet SSL decryption rules.
-
panorama-get-static-routeDeprecatedReturns the specified static route of a virtual router.
-
panorama-get-traffic-logsDeprecatedDeprecated. Use the pan-os-get-logs command instead.
-
panorama-get-url-categoryGets a URL category from URL filtering. This command is only available on firewall devices.
-
panorama-get-url-category-from-cloudDeprecatedReturns a URL category from URL filtering. This command is only available on firewall devices.
-
panorama-get-url-category-from-hostDeprecatedReturns a URL category from URL filtering. This command is only available on firewall devices.
-
panorama-get-url-filterDeprecatedReturns information for a URL filtering rule.
-
panorama-get-url-filtering-best-practiceDeprecatedViews URL filtering best practices.
-
panorama-get-vulnerability-protection-best-practiceDeprecatedGets vulnerability-protection best practices.
-
panorama-get-wildfire-best-practiceDeprecatedViews WildFire best practices.
-
panorama-get-wildfire-configurationDeprecatedRetrieves the Wildfire configuration.
-
panorama-install-file-content-updateDeprecatedInstalls a specific content update file.
-
panorama-install-latest-content-updateDeprecatedInstalls the latest content update.
-
panorama-install-panos-statusDeprecatedGets the installation status of the PAN-OS software.
-
panorama-install-panos-versionDeprecatedInstalls the target PAN-OS version on the specified target device.
-
panorama-list-address-groupsDeprecatedReturns a list of address groups.
-
panorama-list-addressesDeprecatedReturns a list of addresses.
-
panorama-list-applicationsDeprecatedReturns a list of applications.
-
panorama-list-configured-user-id-agentsDeprecatedRetrieves list of user ID agents configured in the system.
-
panorama-list-edlsDeprecatedReturns a list of external dynamic lists.
-
panorama-list-pcapsDeprecatedReturns a list of all PCAP files by PCAP type. Not available for threat PCAPs.
-
panorama-list-rulesDeprecatedReturns a list of predefined security rules.
-
panorama-list-service-groupsDeprecatedReturns a list of service groups.
-
panorama-list-servicesDeprecatedReturns a list of addresses.
-
panorama-list-static-routesDeprecatedLists the static routes of a virtual router.
-
panorama-move-ruleDeprecatedChanges the location of a policy rule.
-
panorama-push-statusDeprecatedReturns the push status for a configuration.
-
panorama-push-to-device-groupDeprecatedPushes rules from PAN-OS to the configured device group. In order to push the configuration to Prisma Access managed tenants (single or multi- tenancy), use the device group argument with the device group associated with the tenant ID.
-
panorama-query-logsDeprecatedQueries logs in Panorama.
-
panorama-query-traffic-logsDeprecatedDeprecated. Use the pan-os-query-logs command instead.
-
panorama-refresh-edlDeprecatedRefreshes the specified external dynamic list.
-
panorama-register-ip-tagDeprecatedRegisters IP addresses to a tag.
-
panorama-register-user-tagDeprecatedRegisters users to a tag. This command is only available for PAN-OS version 9.x and higher.
-
panorama-security-policy-matchDeprecatedChecks whether a session matches a specified security policy. This command is only available on firewall instances.
-
panorama-show-device-versionDeprecatedShows the firewall device software version.
-
panorama-show-location-ipDeprecatedGets location information for an IP address.
-
panorama-show-user-id-interfaces-configDeprecatedShows the user ID interface configuration.
-
panorama-show-zones-configDeprecatedShows the zones configuration.
-
panorama-unregister-ip-tagDeprecatedUnregisters IP addresses from a tag.
-
panorama-unregister-user-tagDeprecatedUnregisters users from a tag. This command is only available for PAN-OS version 9.x and higher.
-
panorama-upload-content-update-fileDeprecatedUploads a content file to Panorama.
-
panorama-url-filtering-block-default-categoriesDeprecatedSets default categories to block in the URL filtering profile.
-
urlGets a URL category from URL filtering.
import json from typing import cast from unittest.mock import MagicMock, patch import dateparser import demistomock as demisto import panos.errors import pytest import requests_mock from CommonServerPython import CommandResults, DemistoException from defusedxml import ElementTree from freezegun import freeze_time from datetime import datetime from panos.device import Vsys from panos.firewall import Firewall from panos.objects import LogForwardingProfile, LogForwardingProfileMatchList from panos.panorama import DeviceGroup, Panorama, Template, TemplateStack from pytest_mock import MockerFixture from requests_mock.mocker import Mocker as RequestsMock from test_data import fetch_incidents_input, mock_rules integration_firewall_params = { "port": "443", "vsys": "vsys1", "server": "https://1.1.1.1", "key": "thisisabogusAPIKEY!", } mock_demisto_args = {"threat_id": "11111", "vulnerability_profile": "mock_vuln_profile"} integration_panorama_params = { "port": "443", "device_group": "Lab-Devices", "server": "https://1.1.1.1", "key": "thisisabogusAPIKEY!", "template": "test", } def load_json(path): with open(path, encoding="utf-8") as f: return json.loads(f.read()) @pytest.fixture(autouse=True) def set_params(mocker): mocker.patch.object(demisto, "params", return_value=integration_firewall_params) mocker.patch.object(demisto, "args", return_value=mock_demisto_args) @pytest.fixture def patched_requests_mocker(requests_mock): """ This function mocks various PANOS API responses so we can accurately test the instance """ base_url = "{}:{}/api/".format(integration_firewall_params["server"], integration_firewall_params["port"]) # Version information mock_version_xml = """ <response status = "success"> <result> <sw-version>9.0.6</sw-version> <multi-vsys>off</multi-vsys> <model>Panorama</model> <serial>FAKESERIALNUMBER</serial> </result> </response> """ version_path = "{}{}{}".format(base_url, "?type=version&key=", integration_firewall_params["key"]) requests_mock.get(version_path, text=mock_version_xml, status_code=200) mock_response_xml = """ <response status="success" code="20"> <msg>command succeeded</msg> </response> """ requests_mock.post(base_url, text=mock_response_xml, status_code=200) return requests_mock def test_panorama_get_os_version(patched_requests_mocker): import Panorama from Panorama import get_pan_os_version Panorama.URL = "https://1.1.1.1:443/api/" Panorama.API_KEY = "thisisabogusAPIKEY!" r = get_pan_os_version() assert r == "9.0.6" def test_panorama_override_vulnerability(patched_requests_mocker): import Panorama from Panorama import panorama_override_vulnerability Panorama.URL = "https://1.1.1.1:443/api/" r = panorama_override_vulnerability(mock_demisto_args["threat_id"], mock_demisto_args["vulnerability_profile"], "reset-both") assert r["response"]["@status"] == "success" def test_add_argument_list(): from Panorama import add_argument_list list_argument = ["foo", "bar"] response_with_member = add_argument_list(list_argument, "test", True) expected_with_member = "<test><member>foo</member><member>bar</member></test>" assert response_with_member == expected_with_member response_with_member_field_name = add_argument_list(list_argument, "member", True) expected_with_member_field_name = "<member>foo</member><member>bar</member>" assert response_with_member_field_name == expected_with_member_field_name def test_add_argument(): from Panorama import add_argument argument = "foo" response_with_member = add_argument(argument, "test", True) expected_with_member = "<test><member>foo</member></test>" assert response_with_member == expected_with_member response_without_member = add_argument(argument, "test", False) expected_without_member = "<test>foo</test>" assert response_without_member == expected_without_member def test_add_argument_yes_no(): from Panorama import add_argument_yes_no arg = "No" field = "test" option = True response_option_true = add_argument_yes_no(arg, field, option) expected_option_true = "<option><test>no</test></option>" assert response_option_true == expected_option_true option = False response_option_false = add_argument_yes_no(arg, field, option) expected_option_false = "<test>no</test>" assert response_option_false == expected_option_false def test_add_argument_target(): from Panorama import add_argument_target response = add_argument_target("foo", "bar") expected = '<bar><devices><entry name="foo"/></devices></bar>' assert response == expected @pytest.mark.parametrize( "disabled, rules_file, expected_results_file", [ ("yes", "test_data/filter_rules_sample.json", "test_data/filter_rules_expected_result.json"), ], ) def test_filter_rules_by_status(disabled: str, rules_file: str, expected_results_file: str): from Panorama import filter_rules_by_status with open(rules_file) as f: rules = json.loads(f.read()) with open(expected_results_file) as f: expected_result = json.loads(f.read()) result = filter_rules_by_status(disabled, rules) assert result == expected_result def test_get_address(mocker): """ Given: - an address_name argument which does not exist When: - running the panorama_get_address function Then: - Ensure the return value is an empty dictionary """ import Panorama from Panorama import panorama_get_address exception_msg = "Object was not found, verify that the name is correct and that the instance was committed." mocker.patch.object(Panorama, "http_request", side_effect=Exception(exception_msg)) result = panorama_get_address("TEST") assert result == {} def test_get_address_command(mocker): """ Given: - an address_name argument which does not exist When: - running the panorama_get_address_command function Then: - Ensure the return value is None, without any errors, and return_results contains the correct informative message. """ import Panorama from Panorama import panorama_get_address_command mocker.patch.object(Panorama, "panorama_get_address", return_value={}) return_results_mock = mocker.patch.object(Panorama, "return_results") result = panorama_get_address_command({"name": "TEST"}) assert not result assert return_results_mock.call_args[0][0] == "Address name TEST was not found" def test_prettify_addresses_arr(): from Panorama import prettify_addresses_arr addresses_arr = [ {"@name": "my_name", "fqdn": "a.com"}, {"@name": "my_name2", "fqdn": "b.com"}, {"@name": "test", "ip-netmask": "1.1.1.1", "tag": None}, ] response = prettify_addresses_arr(addresses_arr) expected = [ {"Name": "my_name", "FQDN": "a.com"}, {"Name": "my_name2", "FQDN": "b.com"}, {"Name": "test", "IP_Netmask": "1.1.1.1"}, ] assert response == expected def test_prettify_address(): from Panorama import prettify_address address = {"@name": "my_name", "ip-netmask": "1.1.1.1", "description": "lala"} response = prettify_address(address) expected = {"Name": "my_name", "IP_Netmask": "1.1.1.1", "Description": "lala"} assert response == expected def test_prettify_address_tag_none(): from Panorama import prettify_address address = {"@name": "test", "ip-netmask": "1.1.1.1", "tag": None} response = prettify_address(address) expected = {"Name": "test", "IP_Netmask": "1.1.1.1"} assert response == expected def test_prettify_address_group(): from Panorama import prettify_address_group address_group_static = {"@name": "foo", "static": {"member": "address object"}} response_static = prettify_address_group(address_group_static) expected_address_group_static = {"Name": "foo", "Type": "static", "Addresses": "address object"} assert response_static == expected_address_group_static address_group_dynamic = {"@name": "foo", "dynamic": {"filter": "1.1.1.1 and 2.2.2.2"}} response_dynamic = prettify_address_group(address_group_dynamic) expected_address_group_dynamic = {"Name": "foo", "Type": "dynamic", "Match": "1.1.1.1 and 2.2.2.2"} assert response_dynamic == expected_address_group_dynamic address_group_dynamic_tag_none = {"@name": "foo", "dynamic": {"filter": "1.1.1.1 or 2.2.2.2"}, "tag": None} response_dynamic_tag_none = prettify_address_group(address_group_dynamic_tag_none) expected_address_group_dynamic_tag_none = {"Name": "foo", "Type": "dynamic", "Match": "1.1.1.1 or 2.2.2.2"} assert response_dynamic_tag_none == expected_address_group_dynamic_tag_none def test_prettify_service(): from Panorama import prettify_service service = {"@name": "service_name", "description": "foo", "protocol": {"tcp": {"port": "443"}}} response = prettify_service(service) expected = {"Name": "service_name", "Description": "foo", "Protocol": "tcp", "DestinationPort": "443"} assert response == expected def test_prettify_service_tag_none(): from Panorama import prettify_service service = {"@name": "service_name", "description": "foo", "protocol": {"tcp": {"port": "443"}}, "tag": None} response = prettify_service(service) expected = {"Name": "service_name", "Description": "foo", "Protocol": "tcp", "DestinationPort": "443"} assert response == expected def test_prettify_service_group(): from Panorama import prettify_service_group service_group = {"@name": "sg", "members": {"member": ["service1", "service2"]}} response = prettify_service_group(service_group) expected = {"Name": "sg", "Services": ["service1", "service2"]} assert response == expected def test_prettify_service_group_tag_none(): from Panorama import prettify_service_group service_group = {"@name": "sg_group", "members": {"member": ["service1", "service2"]}, "tag": None} response = prettify_service_group(service_group) expected = {"Name": "sg_group", "Services": ["service1", "service2"]} assert response == expected def test_prettify_custom_url_category(): from Panorama import prettify_custom_url_category custom_url_category = {"@name": "foo", "list": {"member": ["a", "b", "c"]}} response = prettify_custom_url_category(custom_url_category) expected = {"Name": "foo", "Sites": ["a", "b", "c"]} assert response == expected def test_panorama_create_custom_url_category_8_x(mocker): """ Given: - an only > 9.x valid argument for custom url category creation When: - running the panorama_create_custom_url_category function - mocking the pan-os version to be 8.x Then: - a proper error is raised """ from Panorama import panorama_create_custom_url_category mocker.patch("Panorama.get_pan_os_major_version", return_value=8) custom_url_category_name = "name" description = "test_desc" type_ = "URL List" with pytest.raises(DemistoException, match="The type and categories arguments are only relevant for PAN-OS 9.x versions."): panorama_create_custom_url_category(custom_url_category_name, type_=type_, description=description) def test_panorama_create_custom_url_category_9_x(mocker): """ Given: - a non valid argument for custom url category creation When: - running the panorama_create_custom_url_category function - mocking the pan-os version to be 9.x Then: - a proper error is raised """ from Panorama import panorama_create_custom_url_category mocker.patch("Panorama.get_pan_os_major_version", return_value=9) custom_url_category_name = "name" type_ = "URL List" categories = "phishing" sites = "a.com" description = "test_desc" with pytest.raises(DemistoException, match="The type argument is mandatory for PAN-OS 9.x versions."): panorama_create_custom_url_category(custom_url_category_name, sites=sites, description=description) with pytest.raises(DemistoException, match="Exactly one of the sites and categories arguments should be defined."): panorama_create_custom_url_category(custom_url_category_name, type_=type_, sites=sites, categories=categories) with pytest.raises(DemistoException, match="URL List type is only for sites, Category Match is only for categories."): panorama_create_custom_url_category(custom_url_category_name, type_=type_, categories=categories) def test_create_url_filter_params_8_x(mocker): """ Given: - a valid argument for url filter creation When: - running the create_url_filter_params utility function - mocking the pan-os version to be 8.x Then: - a proper xml element is generated """ from Panorama import create_url_filter_params mocker.patch("Panorama.get_pan_os_major_version", return_value=8) url_filter_name = "name" action = "alert" url_category_list = "adult" description = "test_desc" url_filter_params = create_url_filter_params( url_filter_name, action, url_category_list=url_category_list, description=description ) assert url_filter_params["element"].find("<action>block</action>") != -1 # if not -1, then it is found def test_create_url_filter_params_9_x(mocker): """ Given: - a valid argument for url filter creation When: - running the create_url_filter_params utility function - mocking the pan-os version to be 9.x Then: - a proper xml element is generated """ from Panorama import create_url_filter_params mocker.patch("Panorama.get_pan_os_major_version", return_value=9) url_filter_name = "name" action = "alert" url_category_list = "adult" description = "test_desc" url_filter_params = create_url_filter_params( url_filter_name, action, url_category_list=url_category_list, description=description ) assert url_filter_params["element"].find("<action>block</action>") == -1 # if -1, then it is not found def test_edit_url_filter_non_valid_args_8_x(mocker): """ Given: - a non valid argument for edit url filter When: - running the edit_url_filter function - mocking the pan-os version to be 8.x Then: - a proper error is raised """ from Panorama import panorama_edit_url_filter url_filter_object = { "@name": "fw_test_pb_dont_delete", "action": "block", "allow": {"member": ["Demisto- block sites", "test3"]}, "allow-list": {"member": "www.thepill2.com"}, "block": {"member": ["abortion", "abused-drugs"]}, "block-list": {"member": "www.thepill.com"}, "credential-enforcement": { "allow": {"member": ["Demisto- block sites", "test3"]}, "block": {"member": ["abortion", "abused-drugs"]}, "log-severity": "medium", }, "description": "gogo", } mocker.patch("Panorama.get_pan_os_major_version", return_value=8) mocker.patch("Panorama.panorama_get_url_filter", return_value=url_filter_object) url_filter_name = "fw_test_pb_dont_delete" element_to_change = "allow_categories" element_value = "gambling" add_remove_element = "remove" err_msg = ( "Only the override_allow_list, override_block_list, description properties can be" " changed in PAN-OS 8.x or earlier versions." ) with pytest.raises(DemistoException, match=err_msg): panorama_edit_url_filter(url_filter_name, element_to_change, element_value, add_remove_element) def test_edit_url_filter_non_valid_args_9_x(mocker): """ Given: - a non valid argument for edit url filter When: - running the edit_url_filter function - mocking the pan-os version to be 9.x Then: - a proper error is raised """ from Panorama import panorama_edit_url_filter url_filter_object = { "@name": "fw_test_pb_dont_delete", "allow": {"member": "Test_pb_custom_url_DONT_DELETE"}, "credential-enforcement": { "block": {"member": ["gambling", "abortion"]}, "log-severity": "medium", }, "description": "wowo", } mocker.patch("Panorama.get_pan_os_major_version", return_value=9) mocker.patch("Panorama.panorama_get_url_filter", return_value=url_filter_object) url_filter_name = "fw_test_pb_dont_delete" element_to_change = "override_block_list" element_value = "gambling" add_remove_element = "remove" err_msg = ( "Only the allow_categories, block_categories, description properties can be changed in PAN-OS 9.x or later versions." ) with pytest.raises(DemistoException, match=err_msg): panorama_edit_url_filter(url_filter_name, element_to_change, element_value, add_remove_element) def http_mock(url: str, method: str, body: dict = {}): return body @pytest.mark.parametrize( "category_name, items", [ ( "category_name", ["www.good.com"], ) ], ) def test_remove_from_custom_url_category(category_name, items, mocker): """ Given: - a valid argument for edit custom url group When: - running the custom_url_category_remove_items function Then: - checks an assertion """ import Panorama from Panorama import panorama_custom_url_category_remove_items return_results_mock = mocker.patch.object(Panorama, "return_results") mocker.patch( "Panorama.panorama_get_custom_url_category", return_value={"description": "description", "list": {"member": "www.test.com"}}, ) mocker.patch("Panorama.get_pan_os_major_version", return_value=9) mocker.patch("Panorama.http_request", side_effect=http_mock) panorama_custom_url_category_remove_items(category_name, items, "URL List") demisto_result_got = return_results_mock.call_args.args[0]["Contents"] assert "www.test.com" in demisto_result_got["element"] class TestQueryLogsCommand: @staticmethod def create_logs_query_queue(status_count, no_logs_found): response_queue = [ MockedResponse( text='<response status="success" code="19"><result><msg><line>query ' "job enqueued with jobid 1</line></msg><job>1</job></result></response>", status_code=200, ) ] for _ in range(status_count): response_queue.append( MockedResponse( text='<response status="success"><result><job><tenq>15:05:47</tenq><tdeq>15:05:47</tdeq><tlast>' '01:00:00</tlast><status>ACT</status><id>1238</id></job><log><logs count="0" progress="20"/' "></log></result></response>", status_code=200, ) ) if no_logs_found: # job has finished without finding any logs response_queue.append( MockedResponse( text='<response status="success"><result><job><tenq>15:05:47</tenq><tdeq>15:05:47</tdeq><tlast>' '15:06:52</tlast><status>FIN</status><id>1</id></job><log><logs count="0"' ' progress="100"/></log></result></response>', status_code=200, ) ) else: with open("test_data/query_logs.xml") as f: # job has finished with finding logs response_queue.append(MockedResponse(text=f.read(), status_code=200)) return response_queue def test_query_logs_command_without_polling(self, mocker): """ Given - an api response indicating a log query job has been created When - querying logs without polling Then - make sure polling is not triggered. - make sure context output indicates that the status of the job is 'Pending' """ import Panorama import requests from Panorama import panorama_query_logs_command Panorama.API_KEY = "thisisabogusAPIKEY!" mocker.patch.object( requests, "request", return_value=MockedResponse( text='<response status="success" code="19"><result><msg><line>query ' "job enqueued with jobid 1</line></msg><job>1</job></result></response>", status_code=200, ), ) command_result = panorama_query_logs_command({"log-type": "traffic", "polling": "false"}) assert command_result.outputs == { "JobID": "1", "Status": "Pending", "LogType": "traffic", "Message": "query job enqueued with jobid 1", } assert not command_result.scheduled_command assert command_result.readable_output == "### Query Logs:\n|JobID|Status|\n|---|---|\n| 1 | Pending |\n" @pytest.mark.parametrize( "status_count, no_logs_found", [(1, False), (2, True), (3, False), (5, True), (8, False), (10, True)] ) def test_query_logs_command_with_polling(self, mocker, status_count, no_logs_found): """ Given - a queue of api responses - responses indicating query logs succeeded or not succeeded. - a status count which means how many times polling was done. When - querying logs with polling Then - make sure the readable output indicating polling is active is printed only once. - make sure context is returned only at the end of polling, and that the context is valid if there are logs available and if there aren't. """ import Panorama import requests from CommonServerPython import ScheduledCommand from Panorama import panorama_query_logs_command Panorama.API_KEY = "thisisabogusAPIKEY!" mocker.patch.object( requests, "request", side_effect=self.create_logs_query_queue(status_count=status_count, no_logs_found=no_logs_found) ) mocker.patch.object(ScheduledCommand, "raise_error_if_not_supported", return_value=None) command_result = panorama_query_logs_command({"log-type": "traffic", "polling": "true"}) assert command_result.readable_output == "Fetching traffic logs for job ID 1..." assert not command_result.outputs # no context should be returned until polling is done. polling_args = {"query_log_job_id": "1", "hide_polling_output": True, "polling": True, "log-type": "traffic"} command_result = panorama_query_logs_command(polling_args) while command_result.scheduled_command: # if scheduled_command is set, it means that command should still poll assert not command_result.readable_output # make sure that indication of polling is printed only once assert not command_result.outputs # make sure no context output is being returned to war-room during polling command_result = panorama_query_logs_command(polling_args) if no_logs_found: assert command_result.outputs == {"JobID": "1", "LogType": "traffic", "Logs": [], "Status": "Completed"} else: partial_expected_outputs = {"JobID": "1", "LogType": "traffic", "Status": "Completed"} assert partial_expected_outputs.items() <= command_result.outputs.items() assert "Logs" in command_result.outputs assert command_result.outputs["Logs"] # make sure there are log outputs available. def test_prettify_edl(): from Panorama import prettify_edl edl = {"@name": "edl_name", "type": {"my_type": {"url": "abc.com", "description": "my_desc"}}} response = prettify_edl(edl) expected = {"Name": "edl_name", "Type": "my_type", "URL": "abc.com", "Description": "my_desc"} assert response == expected def test_build_traffic_logs_query(): """ Given: - a valid arguments for traffic logs query generation When: - running the build_traffic_logs_query utility function Then: - a proper query is generated (addr.src in 192.168.1.222) and (app eq netbios-dg) and (action eq allow) and (port.dst eq 138) """ from Panorama import build_traffic_logs_query source = "192.168.1.222" application = "netbios-dg" action = "allow" to_port = "138" response = build_traffic_logs_query(source, None, None, application, to_port, action) expected = "(addr.src in 192.168.1.222) and (app eq netbios-dg) and (port.dst eq 138) and (action eq allow)" assert response == expected def test_prettify_traffic_logs(): from Panorama import prettify_traffic_logs traffic_logs = [ {"action": "my_action1", "category": "my_category1", "rule": "my_rule1"}, {"action": "my_action2", "category": "my_category2", "rule": "my_rule2"}, ] response = prettify_traffic_logs(traffic_logs) expected = [ {"Action": "my_action1", "Category": "my_category1", "Rule": "my_rule1"}, {"Action": "my_action2", "Category": "my_category2", "Rule": "my_rule2"}, ] assert response == expected def test_build_logs_query(): """ Given: - a valid arguments for logs query generation When: - running the build_logs_query utility function Then: - a proper query is generated ((url contains 'demisto.com') or (url contains 'paloaltonetworks.com')) """ from Panorama import build_logs_query urls_as_string = "demisto.com, paloaltonetworks.com" response = build_logs_query(None, None, None, None, None, None, None, None, None, urls_as_string, None, None) expected = "((url contains 'demisto.com') or (url contains 'paloaltonetworks.com'))" assert response == expected def test_prettify_logs(): from Panorama import prettify_logs traffic_logs = [ {"action": "my_action1", "category": "my_category1", "rule": "my_rule1", "natdport": "100", "bytes": "12"}, {"action": "my_action2", "category": "my_category2", "rule": "my_rule2", "natdport": "101", "bytes_sent": "11"}, ] response = prettify_logs(traffic_logs) expected = [ { "Action": "my_action1", "CategoryOrVerdict": "my_category1", "Rule": "my_rule1", "NATDestinationPort": "100", "Bytes": "12", }, { "Action": "my_action2", "CategoryOrVerdict": "my_category2", "Rule": "my_rule2", "NATDestinationPort": "101", "BytesSent": "11", }, ] assert response == expected prepare_security_rule_inputs = [ ("after", "test_rule_name", ["user1"], "<source-user><member>user1</member></source-user>"), ("after", "test_rule_name", ["user1,user2"], "<source-user><member>user1,user2</member></source-user>"), ] @pytest.mark.parametrize("where, dst, source_user, expected_result", prepare_security_rule_inputs) def test_prepare_security_rule_params(where, dst, source_user, expected_result): """ Given: - valid arguments for the prepare_security_rule_params function When: - running the prepare_security_rule_params utility function Then: - a valid security rule dictionary is returned. """ from Panorama import prepare_security_rule_params params = prepare_security_rule_params( api_action="set", action="drop", destination=["any"], source=["any"], rulename="test", where=where, dst=dst, source_user=source_user, ) assert expected_result in params.get("element", "") prepare_security_rule_fail_inputs = [ ("top", "test_rule_name"), ("bottom", "test_rule_name"), ] @pytest.mark.parametrize("where, dst", prepare_security_rule_fail_inputs) def test_prepare_security_rule_params_fail(where, dst): """ Given: - a non valid arguments for the prepare_security_rule_params function When: - running the prepare_security_rule_params utility function Then: - a proper exception is raised """ from Panorama import prepare_security_rule_params err_msg = "Please provide a dst rule only when the where argument is before or after." with pytest.raises(DemistoException, match=err_msg): prepare_security_rule_params( api_action="set", action="drop", destination=["any"], source=["any"], rulename="test", where=where, dst=dst ) def test_build_policy_match_query(): """ Given: - a valid arguments for policy match query generation When: - running the build_policy_match_query utility function Then: - a proper xml is generated """ from Panorama import build_policy_match_query source = "1.1.1.1" destination = "6.7.8.9" protocol = "1" application = "gmail-base" response = build_policy_match_query(application, None, destination, None, None, None, protocol, source) expected = ( "<test><security-policy-match><source>1.1.1.1</source><destination>6.7.8.9</destination>" "<protocol>1</protocol><application>gmail-base</application></security-policy-match></test>" ) assert response == expected def test_panorama_register_ip_tag_command_wrongful_args(mocker): """ Given: - a non valid arguments for the panorama_register_ip_tag_command function When: - running the panorama_register_ip_tag_command function Then: - a proper exception is raised """ from Panorama import panorama_register_ip_tag_command args = {"IPs": "1.1.1.1", "tag": "test_tag", "persistent": "false", "timeout": "5"} mocker.patch("Panorama.get_pan_os_major_version", return_value=8) with pytest.raises(DemistoException, match="The timeout argument is only applicable on 9.x PAN-OS versions or higher."): panorama_register_ip_tag_command(args) def test_prettify_matching_rule(): from Panorama import prettify_matching_rule matching_rule = {"action": "my_action1", "@name": "very_important_rule", "source": "6.7.8.9", "destination": "any"} response = prettify_matching_rule(matching_rule) expected = {"Action": "my_action1", "Name": "very_important_rule", "Source": "6.7.8.9", "Destination": "any"} assert response == expected def test_prettify_static_route(): from Panorama import prettify_static_route static_route = {"@name": "name1", "destination": "1.2.3.4", "metric": "10", "nexthop": {"fqdn": "demisto.com"}} virtual_router = "my_virtual_router" response = prettify_static_route(static_route, virtual_router) expected = { "Name": "name1", "Destination": "1.2.3.4", "Metric": 10, "NextHop": "demisto.com", "VirtualRouter": "my_virtual_router", } assert response == expected def test_validate_search_time(): from Panorama import validate_search_time assert validate_search_time("2019/12/26") assert validate_search_time("2019/12/26 00:00:00") with pytest.raises(Exception): assert validate_search_time("219/12/26 00:00:00") assert validate_search_time("219/10/35") def test_show_user_id_interface_config_command(): """ Given: - missing template and template_stack arguments for the show_user_id_interface_config_command command When: - running the show_user_id_interface_config_request function Then: - a proper exception is raised """ from Panorama import show_user_id_interface_config_command args = {} str_match = ( "In order to show the User Interface configuration in your Panorama, " "supply either the template or the template_stack arguments." ) with pytest.raises(DemistoException, match=str_match): show_user_id_interface_config_command(args) def test_prettify_user_interface_config(): from Panorama import prettify_user_interface_config raw_response = [ { "@name": "internal", "network": {"layer3": {"member": "ethernet1/2"}, "log-setting": "ToLoggingService"}, "enable-user-identification": "yes", }, {"@name": "External", "network": {"tap": {"member": "ethernet1/1"}, "log-setting": "ToLoggingService"}}, ] response = prettify_user_interface_config(raw_response) expected = [ {"Name": "ethernet1/2", "Zone": "internal", "EnableUserIdentification": "yes"}, {"Name": "ethernet1/1", "Zone": "External", "EnableUserIdentification": "no"}, ] assert response == expected def test_list_configured_user_id_agents_command(mocker): """ Given: - missing template and template_stack arguments for the list_configured_user_id_agents_command command When: - running the list_configured_user_id_agents_request function Then: - a proper exception is raised """ from Panorama import list_configured_user_id_agents_command mocker.patch("Panorama.get_pan_os_major_version", return_value=9) args = {} str_match = ( "In order to show the the User ID Agents in your Panorama, supply either the template or the template_stack arguments." ) with pytest.raises(DemistoException, match=str_match): list_configured_user_id_agents_command(args) def test_prettify_configured_user_id_agents__multi_result(): from Panorama import prettify_configured_user_id_agents raw_response = [ {"@name": "testing2", "serial-number": "panorama2"}, { "@name": "fullinfo", "host-port": { "port": "67", "ntlm-auth": "yes", "ldap-proxy": "yes", "collectorname": "demisto", "secret": "secret", "host": "what", }, "ip-user-mappings": "yes", }, ] response = prettify_configured_user_id_agents(raw_response) expected = [ { "Name": "testing2", "Host": None, "Port": None, "NtlmAuth": "no", "LdapProxy": "no", "CollectorName": None, "Secret": None, "EnableHipCollection": "no", "SerialNumber": "panorama2", "IpUserMapping": "no", "Disabled": "no", }, { "Name": "fullinfo", "Host": "what", "Port": "67", "NtlmAuth": "yes", "LdapProxy": "yes", "CollectorName": "demisto", "Secret": "secret", "EnableHipCollection": "no", "SerialNumber": None, "IpUserMapping": "yes", "Disabled": "no", }, ] assert response == expected def test_prettify_configured_user_id_agents__single_result(): from Panorama import prettify_configured_user_id_agents raw_response = { "@name": "fullinfo", "host-port": { "port": "67", "ntlm-auth": "yes", "ldap-proxy": "yes", "collectorname": "demisto", "secret": "secret", "host": "what", }, "ip-user-mappings": "yes", } response = prettify_configured_user_id_agents(raw_response) expected = { "Name": "fullinfo", "Host": "what", "Port": "67", "NtlmAuth": "yes", "LdapProxy": "yes", "CollectorName": "demisto", "Secret": "secret", "EnableHipCollection": "no", "SerialNumber": None, "IpUserMapping": "yes", "Disabled": "no", } assert response == expected def test_prettify_rule(): from Panorama import prettify_rule with open("test_data/rule.json") as f: rule = json.load(f) with open("test_data/prettify_rule.json") as f: expected_pretty_rule = json.load(f) pretty_rule = prettify_rule(rule) del pretty_rule["DeviceGroup"] assert pretty_rule == expected_pretty_rule class TestPcap: @staticmethod def test_list_pcaps_flow_with_no_existing_pcaps(mocker): """ Given - a response which indicates there are no pcap files on the firewall. When - listing all the available pcap files. Then - make sure that a message which indicates there are no Pcaps is printed out. """ from Panorama import panorama_list_pcaps_command no_pcaps_response = MockedResponse( text='<?xml version="1.0"?>\n<response status="success">\n ' "<result>\n <dir-listing/>\n </result>\n</response>\n", status_code=200, ) mocker.patch("Panorama.http_request", return_value=no_pcaps_response) results_mocker = mocker.patch.object(demisto, "results") panorama_list_pcaps_command({"pcapType": "filter-pcap"}) assert results_mocker.called assert results_mocker.call_args.args[0] == "PAN-OS has no Pcaps of type: filter-pcap." @staticmethod @pytest.mark.parametrize( "api_response, expected_context, expected_markdown_table", [ ( '<?xml version="1.0"?>\n<response status="success">\n <result>\n <dir-listing>\n ' "<file>/pcap</file>\n <file>/pcap_test</file>\n </dir-listing>\n </result>\n</response>\n", ["pcap", "pcap_test"], "### List of Pcaps:\n|Pcap name|\n|---|\n| pcap |\n| pcap_test |\n", ), ( '<?xml version="1.0"?>\n<response status="success">\n <result>\n <dir-listing>\n ' "<file>/pcap_test</file>\n </dir-listing>\n </result>\n</response>\n", ["pcap_test"], "### List of Pcaps:\n|Pcap name|\n|---|\n| pcap_test |\n", ), ], ) def test_list_pcaps_flow(mocker, api_response, expected_context, expected_markdown_table): """ Given - a response which indicates there are two pcaps in the firewall. - a response which indicates there is only one pcap in the firewall. When - listing all the available pcap files. Then - make sure the response is parsed correctly. """ from Panorama import panorama_list_pcaps_command pcaps_response = MockedResponse(text=api_response, status_code=200) mocker.patch("Panorama.http_request", return_value=pcaps_response) results_mocker = mocker.patch.object(demisto, "results") panorama_list_pcaps_command({"pcapType": "filter-pcap"}) called_args = results_mocker.call_args[0][0] assert list(*called_args["EntryContext"].values()) == expected_context assert called_args["HumanReadable"] == expected_markdown_table @staticmethod def test_get_specific_pcap_flow_which_does_not_exist(mocker): """ Given - a response which indicates there are no pcap files on the firewall. When - trying to download a pcap file. Then - make sure that the error message from the api is actually returned. """ from Panorama import panorama_get_pcap_command no_pcaps_response = MockedResponse( text='<?xml version="1.0"?>\n<response status="error">\n <msg>\n ' "<line>test.pcap not present</line>\n </msg>\n</response>\n", status_code=200, headers={"Content-Type": "application/xml"}, ) mocker.patch("Panorama.http_request", return_value=no_pcaps_response) with pytest.raises(Exception, match="line: test.pcap not present"): panorama_get_pcap_command({"pcapType": "filter-pcap", "from": "test"}) @staticmethod def test_get_filter_pcap_without_from_argument(mocker): """ Given - a filter-pcap type without 'from' argument When - trying to download a filter pcap file. Then - make sure that the error message which states that the 'from' argument should be returned is presented. """ from Panorama import panorama_get_pcap_command no_pcaps_response = MockedResponse( text='<?xml version="1.0"?>\n<response status="error">\n <msg>\n ' "<line>test.pcap not present</line>\n </msg>\n</response>\n", status_code=200, headers={"Content-Type": "application/xml"}, ) mocker.patch("Panorama.http_request", return_value=no_pcaps_response) with pytest.raises(Exception, match="cannot download filter-pcap without the from argument"): panorama_get_pcap_command({"pcapType": "filter-pcap"}) class TestPanoramaListApplicationsCommand: @staticmethod @pytest.mark.parametrize("panorama_version", [8, 9]) def test_panorama_list_applications_command(mocker, panorama_version): """ Given - http response of the list of applications. - panorama version 8 & 9. When - getting a list of all the applications in panorama 8/9. Then - a valid context output is returned. """ from Panorama import panorama_list_applications_command mocker.patch("Panorama.http_request", return_value=load_json("test_data/list_applications_response.json")) mocker.patch("Panorama.get_pan_os_major_version", return_value=panorama_version) res = mocker.patch("demistomock.results") panorama_list_applications_command({"predefined": "false"}) assert res.call_args.args[0]["Contents"] == { "@name": "test-playbook-app", "@loc": "Lab-Devices", "subcategory": "infrastructure", "category": "networking", "technology": "client-server", "description": "test-playbook-application-do-not-delete", "risk": "1", } @staticmethod @pytest.mark.parametrize("panorama_version", [8, 9]) def test_panorama_list_applications_command_main_flow(mocker, panorama_version): """ Given - integrations parameters. - pan-os-list-applications command arguments including device_group When - running the pan-os-list-applications command through the main flow Then - make sure the context output is returned as expected. - make sure the device group gets overriden by the command arguments. """ from Panorama import main mocker.patch.object(demisto, "params", return_value=integration_panorama_params) mocker.patch.object(demisto, "args", return_value={"predefined": "false", "device-group": "new-device-group"}) mocker.patch.object(demisto, "command", return_value="pan-os-list-applications") request_mock = mocker.patch("Panorama.http_request", return_value=load_json("test_data/list_applications_response.json")) mocker.patch("Panorama.get_pan_os_major_version", return_value=panorama_version) res = mocker.patch("demistomock.results") main() assert res.call_args.args[0]["Contents"] == { "@name": "test-playbook-app", "@loc": "Lab-Devices", "subcategory": "infrastructure", "category": "networking", "technology": "client-server", "description": "test-playbook-application-do-not-delete", "risk": "1", } # make sure that device group is getting overriden by the device-group from command arguments. assert request_mock.call_args.kwargs["body"] == { "type": "config", "action": "get", "key": "thisisabogusAPIKEY!", "xpath": "/config/devices/entry/device-group/entry[@name='new-device-group']/application/entry", } def test_get_security_profiles_command_main_flow(mocker): """ Given - integrations parameters. - pan-os-get-security-profiles command arguments including device_group When - running the pan-os-get-security-profiles command through the main flow Then - make sure the context output is returned as expected. - make sure the device group gets overriden by the command arguments. """ from Panorama import main mocker.patch.object(demisto, "params", return_value=integration_panorama_params) mocker.patch.object(demisto, "args", return_value={"device-group": "new-device-group"}) mocker.patch.object(demisto, "command", return_value="pan-os-get-security-profiles") expected_security_profile_response = load_json("test_data/get_security_profiles_response.json") request_mock = mocker.patch("Panorama.http_request", return_value=expected_security_profile_response) res = mocker.patch("demistomock.results") main() assert res.call_args.args[0]["Contents"] == expected_security_profile_response # make sure that device group is getting overriden by the device-group from command arguments. assert request_mock.call_args.kwargs["params"] == { "action": "get", "type": "config", "xpath": "/config/devices/entry[@name='localhost.localdomain']/device-group/entry[@name='new-device-group']/profiles", "key": "thisisabogusAPIKEY!", } def test_apply_security_profiles_command_main_flow(mocker): """ Given - integrations parameters. - pan-os-apply-security-profile command arguments including device_group When - running the pan-os-apply-security-profile command through the main flow Then - make sure the context output is returned as expected. - make sure the device group gets overriden by the command arguments. """ from Panorama import main mocker.patch.object(demisto, "params", return_value=integration_panorama_params) mocker.patch.object( demisto, "args", return_value={ "device-group": "new-device-group", "profile_type": "data-filtering", "profile_name": "test-profile", "rule_name": "rule-test", "pre_post": "rule-test", }, ) mocker.patch.object(demisto, "command", return_value="pan-os-apply-security-profile") request_mock = mocker.patch("Panorama.http_request") res = mocker.patch("demistomock.results") main() # make sure that device group is getting overriden by the device-group from command arguments. assert request_mock.call_args.kwargs["params"] == { "action": "set", "type": "config", "xpath": "/config/devices/entry[@name='localhost.localdomain']/device-group/entry[@name='new-device-group']" "/rule-test/security/rules/entry[@name='rule-test']", "key": "thisisabogusAPIKEY!", "element": "<profile-setting><profiles><data-filtering>" "<member>test-profile</member></data-filtering></profiles>" "</profile-setting>", } assert res.call_args.args[0] == "The profile data-filtering = test-profile has been applied to the rule rule-test" def test_apply_security_profiles_command_when_one_already_exists(mocker): """ Given - integrations parameters. - pan-os-apply-security-profile command arguments including device_group - same profile as already exists in the rule When - running the pan-os-apply-security-profile command through the main flow Then - Ensure the request is what's already in the API (the 'element' parameter contains all profiles in the XML) """ from Panorama import main mocker.patch.object(demisto, "params", return_value=integration_panorama_params) mocker.patch.object( demisto, "args", return_value={ "device-group": "new-device-group", "profile_type": "spyware", "profile_name": "strict", "rule_name": "rule-test", "pre_post": "rule-test", }, ) mocker.patch("Panorama.dict_safe_get", return_value={"virus": {"member": "Tap"}, "spyware": {"member": "strict"}}) mocker.patch.object(demisto, "command", return_value="pan-os-apply-security-profile") request_mock = mocker.patch("Panorama.http_request") res = mocker.patch("demistomock.results") main() assert request_mock.call_args.kwargs["params"] == { "action": "set", "type": "config", "xpath": "/config/devices/entry[@name='localhost.localdomain']/device-group/entry[@name='new-device-group']" "/rule-test/security/rules/entry[@name='rule-test']", "key": "thisisabogusAPIKEY!", "element": "<profile-setting><profiles><spyware><member>strict</member></spyware>" "<virus><member>Tap</member></virus></profiles></profile-setting>", } assert res.call_args.args[0] == "The profile spyware = strict has been applied to the rule rule-test" def test_remove_security_profiles_command(mocker): """ Given - integrations parameters. - pan-os-remove-security-profile command arguments When - running the pan-os-remove-security-profile command through the main flow Then - Ensure the given profile type has been removed from the given rule """ from Panorama import main mocker.patch.object(demisto, "params", return_value=integration_panorama_params) mocker.patch.object( demisto, "args", return_value={ "device-group": "new-device-group", "profile_type": "spyware", "rule_name": "rule-test", "pre_post": "rule-test", }, ) mocker.patch("Panorama.dict_safe_get", return_value={"virus": {"member": "Tap"}, "spyware": {"member": "strict"}}) mocker.patch.object(demisto, "command", return_value="pan-os-remove-security-profile") request_mock = mocker.patch("Panorama.http_request") res = mocker.patch("demistomock.results") main() assert request_mock.call_args.kwargs["params"] == { "action": "set", "type": "config", "xpath": "/config/devices/entry[@name='localhost.localdomain']/device-group/entry[@name='new-device-group']" "/rule-test/security/rules/entry[@name='rule-test']", "key": "thisisabogusAPIKEY!", "element": "<profile-setting><profiles><virus><member>Tap</member></virus></profiles></profile-setting>", } assert res.call_args.args[0] == "The profile spyware has been removed from the rule rule-test" class TestPanoramaEditRuleCommand: EDIT_SUCCESS_RESPONSE = {"response": {"@status": "success", "@code": "20", "msg": "command succeeded"}} EDIT_AUDIT_COMMENT_SUCCESS_RESPONSE = {"response": {"@status": "success", "result": "Successfully added comment for xpath"}} @staticmethod @pytest.fixture() def reset_device_group(): import Panorama Panorama.DEVICE_GROUP = "" @staticmethod def test_sanity(mocker, reset_device_group): import Panorama args = { "rulename": "TestRule", "element_to_change": "source", "element_value": "2.3.4.5,3.3.3.3", "behaviour": "add", } commited_rule_item = { "response": { "@status": "success", "@code": "19", "result": { "@total-count": "1", "@count": "1", "source": { "member": ["1.1.1.1", "3.3.3.3", "2.3.4.5"], }, }, } } mocker.patch("Panorama.http_request", return_value=commited_rule_item) Panorama.panorama_edit_rule_command(args) @staticmethod def test_add_to_element_on_uncommited_rule(mocker, reset_device_group): import Panorama args = { "rulename": "TestRule", "element_to_change": "source", "element_value": "2.3.4.5", "behaviour": "add", } uncommited_rule_item = { "response": { "@status": "success", "@code": "19", "result": { "@total-count": "1", "@count": "1", "source": { "@admin": "admin", "@dirtyId": "1616", "@time": "2021/11/27 10:55:18", "member": { "@admin": "admin", "@dirtyId": "1616", "@time": "2021/11/27 10:55:18", "#text": "3.3.3.3", }, }, }, } } mocker.patch("Panorama.http_request", return_value=uncommited_rule_item) Panorama.panorama_edit_rule_command(args) @staticmethod def test_edit_rule_to_disabled_flow(mocker, reset_device_group): """ Given - arguments to change a pre-rule to 'disabled' When - running panorama_edit_rule_command function. Then - make sure the entire command flow succeeds. """ from Panorama import panorama_edit_rule_command args = { "rulename": "test", "element_to_change": "disabled", "element_value": "yes", "behaviour": "replace", "pre_post": "pre-rulebase", } mocker.patch("Panorama.http_request", return_value=TestPanoramaEditRuleCommand.EDIT_SUCCESS_RESPONSE) results_mocker = mocker.patch.object(demisto, "results") panorama_edit_rule_command(args) assert results_mocker.called @staticmethod def test_edit_rule_to_disabled_with_no_element_value(mocker): """ Given - arguments to change a pre-rule to 'disabled' when the element value should be set to 'no' When - running panorama_edit_rule_command function. Then - make sure that the `params['element']` contains the 'no' element value. """ from Panorama import panorama_edit_rule_command args = { "rulename": "test", "element_to_change": "disabled", "element_value": "no", "behaviour": "replace", "pre_post": "pre-rulebase", } http_req_mocker = mocker.patch("Panorama.http_request", return_value=TestPanoramaEditRuleCommand.EDIT_SUCCESS_RESPONSE) panorama_edit_rule_command(args) assert http_req_mocker.call_args.kwargs.get("body").get("element") == "<disabled>no</disabled>" @staticmethod def test_edit_rule_main_flow_disable_rule(mocker): """ Given - panorama integrations parameters. - pan-os-edit-rule command arguments including device_group. - arguments to disable the rule When - running the pan-os-edit-rule command through the main flow Then - make sure the context output is returned as expected. - make sure the device group gets overriden by the command arguments. """ from Panorama import main mocker.patch.object(demisto, "params", return_value=integration_panorama_params) mocker.patch.object( demisto, "args", return_value={ "rulename": "test", "element_to_change": "disabled", "element_value": "no", "behaviour": "replace", "pre_post": "pre-rulebase", "device-group": "new device group", }, ) mocker.patch.object(demisto, "command", return_value="pan-os-edit-rule") request_mock = mocker.patch("Panorama.http_request", return_value=TestPanoramaEditRuleCommand.EDIT_SUCCESS_RESPONSE) res = mocker.patch("demistomock.results") main() # make sure that device group is getting overriden by the device-group from command arguments. assert request_mock.call_args.kwargs["body"] == { "type": "config", "action": "edit", "key": "thisisabogusAPIKEY!", "element": "<disabled>no</disabled>", "xpath": "/config/devices/entry/device-group/entry[@name='new device group']/pre-rulebase" "/security/rules/entry[@name='test']/disabled", } assert res.call_args.args[0]["Contents"] == { "response": {"@status": "success", "@code": "20", "msg": "command succeeded"} } @staticmethod def test_edit_rule_main_flow_update_audit_comment(mocker): """ Given - panorama integrations parameters. - pan-os-edit-rule command arguments including device_group. - arguments to edit audit comment of a rule When - running the pan-os-edit-rule command through the main flow Then - make sure the context output is returned as expected. - make sure the device group gets overriden by the command arguments. """ from Panorama import main mocker.patch.object(demisto, "params", return_value=integration_panorama_params) mocker.patch.object( demisto, "args", return_value={ "rulename": "test", "element_to_change": "audit-comment", "element_value": "some string", "behaviour": "replace", "pre_post": "pre-rulebase", "device-group": "new device group", }, ) mocker.patch.object(demisto, "command", return_value="pan-os-edit-rule") request_mock = mocker.patch( "Panorama.http_request", return_value=TestPanoramaEditRuleCommand.EDIT_AUDIT_COMMENT_SUCCESS_RESPONSE ) res = mocker.patch("demistomock.results") main() # make sure that device group is getting overriden by the device-group from command arguments. assert request_mock.call_args.kwargs["body"] == { "type": "op", "cmd": "<set><audit-comment><xpath>/config/devices/entry[@name='localhost.localdomain']/device-group" "/entry[@name='new device group']/pre-rulebase/security/rules/entry[@name='test']" "</xpath><comment>some string</comment></audit-comment></set>", "key": "thisisabogusAPIKEY!", } assert res.call_args.args[0]["Contents"] == TestPanoramaEditRuleCommand.EDIT_AUDIT_COMMENT_SUCCESS_RESPONSE @staticmethod def test_edit_rule_main_flow_remove_profile_setting_group(mocker): """ Given - panorama integrations parameters. - pan-os-edit-rule command arguments including device_group. - arguments to remove a profile-setting group. When - running the pan-os-edit-rule command through the main flow. Then - make sure the API request body is correct. - make sure the message is correct for the user. """ from Panorama import main mocker.patch.object(demisto, "params", return_value=integration_panorama_params) mocker.patch.object( demisto, "args", return_value={ "rulename": "test", "element_to_change": "profile-setting", "element_value": "some string", "behaviour": "remove", "pre_post": "pre-rulebase", "device-group": "new device group", }, ) mocker.patch.object(demisto, "command", return_value="pan-os-edit-rule") request_mock = mocker.patch( "Panorama.http_request", return_value=TestPanoramaEditRuleCommand.EDIT_AUDIT_COMMENT_SUCCESS_RESPONSE ) res = mocker.patch("demistomock.results") main() # Check: 'action' == set (not edit) assert request_mock.call_args.kwargs["body"]["action"] == "set" # Ensure 'element' wasn't sent with a group (since we removed the profile-setting group) assert request_mock.call_args.kwargs["body"]["element"] == "<profile-setting><group/></profile-setting>" # Make sure the message is correct for the user assert res.call_args.args[0]["HumanReadable"] == "Rule edited successfully." def test_panorama_edit_address_group_command_main_flow_edit_description(mocker): """ Given - integrations parameters. - pan-os-edit-address-group command arguments including device_group and description to add. When - running the pan-os-edit-address-group command through the main flow Then - make sure the context output is returned as expected. - make sure the device group gets overriden by the command arguments. """ from Panorama import main mocker.patch.object(demisto, "params", return_value=integration_panorama_params) mocker.patch.object( demisto, "args", return_value={"name": "test", "description": "test", "match": "1.1.1.1", "device-group": "new device group"}, ) mocker.patch.object(demisto, "command", return_value="pan-os-edit-address-group") request_mock = mocker.patch( "Panorama.http_request", return_value={"response": {"@status": "success", "@code": "20", "msg": "command succeeded"}} ) res = mocker.patch("demistomock.results") main() # make sure that device group is getting overriden by the device-group from command arguments. assert request_mock.call_args.kwargs["body"] == { "action": "edit", "type": "config", "key": "thisisabogusAPIKEY!", "xpath": "/config/devices/entry/device-group/entry[@name='new device group']" "/address-group/entry[@name='test']/description", "element": "<description>test</description>", } assert res.call_args.args[0]["Contents"] == {"response": {"@status": "success", "@code": "20", "msg": "command succeeded"}} assert res.call_args.args[0]["HumanReadable"] == "Address Group test was edited successfully." def test_panorama_edit_address_group_command_pre_11(mocker: MockerFixture): """ Given - PAN-OS version is lower than 11. When - Running the pan-os-edit-address-group command for a static group. Then - Make sure the group is edited correctly. """ import Panorama Panorama.DEVICE_GROUP = integration_panorama_params["device_group"] mocker.patch( "Panorama.panorama_get_address_group", return_value={"@name": "Name", "@loc": "Loc", "static": {"member": ["1", "2"]}}, ) mocker.patch("Panorama.return_results") request_mock = mocker.patch("Panorama.http_request") args = {"type": "static", "element_to_add": "3", "name": "Name"} Panorama.panorama_edit_address_group_command(args) assert "<member>1</member>" in request_mock.call_args_list[0].kwargs["body"]["element"] assert "<member>2</member>" in request_mock.call_args_list[0].kwargs["body"]["element"] assert "<member>3</member>" in request_mock.call_args_list[0].kwargs["body"]["element"] def test_panorama_edit_address_group_command_v_11(mocker: MockerFixture): """ Given - PAN-OS version is greater than 11. When - Running the pan-os-edit-address-group command for a static group. Then - Make sure the group is edited correctly. """ import Panorama Panorama.DEVICE_GROUP = integration_panorama_params["device_group"] mocker.patch( "Panorama.panorama_get_address_group", return_value={ "@name": "Name", "@loc": "Loc", "static": { "member": [ {"@admin": "admin", "@dirtyId": "1", "@time": "2025/01/01 00:00:00", "#text": "1"}, {"@admin": "admin", "@dirtyId": "2", "@time": "2025/01/01 00:00:00", "#text": "2"}, ] }, }, ) mocker.patch("Panorama.return_results") request_mock = mocker.patch("Panorama.http_request") args = {"type": "static", "element_to_add": "3", "name": "Name"} Panorama.panorama_edit_address_group_command(args) assert "<member>1</member>" in request_mock.call_args_list[0].kwargs["body"]["element"] assert "<member>2</member>" in request_mock.call_args_list[0].kwargs["body"]["element"] assert "<member>3</member>" in request_mock.call_args_list[0].kwargs["body"]["element"] def test_panorama_edit_address_group_command_remove_single_address(mocker): """ Given - pan-os-edit-address-group command arguments including a single address to remove. When - running the pan-os-edit-address-group command through the main flow Then - make sure an exception is raised because address group must always have at least one address. """ import Panorama Panorama.DEVICE_GROUP = integration_panorama_params["device_group"] mocker.patch( "Panorama.http_request", return_value={ "response": { "@status": "success", "result": {"entry": {"@name": "test5", "static": {"member": ["5.5.5.5"]}, "description": "dfdf"}}, } }, ) with pytest.raises(DemistoException) as exc_info: Panorama.panorama_edit_address_group_command( {"name": "test", "device-group": "Shared", "type": "static", "element_to_remove": "5.5.5.5"} ) assert exc_info.type == DemistoException assert ( exc_info.value.message == "cannot remove ['5.5.5.5'] addresses from address group test, " "address-group test must have at least one address in its configuration" ) @pytest.mark.parametrize( "action, existing_url_categories_mock, category", [("add", {"list": {"member": []}}, "category1"), ("remove", {"list": {"member": ["category2"]}}, "category2")], ) def test_panorama_edit_custom_url_category_command_main_flow(mocker, action, existing_url_categories_mock, category): """ Given - integrations parameters. - pan-os-edit-custom-url-category command arguments: categories, device-group and action. When - running the pan-os-edit-custom-url-category command through the main flow Then - make sure the context output is returned as expected. - make sure the device group gets overriden by the command arguments. """ from Panorama import main mocker.patch.object(demisto, "params", return_value=integration_panorama_params) mocker.patch.object( demisto, "args", return_value={"name": "test", "action": action, "categories": ["category1"], "device-group": "new device group"}, ) mocker.patch.object(demisto, "command", return_value="pan-os-edit-custom-url-category") request_mock = mocker.patch( "Panorama.http_request", return_value={"response": {"@status": "success", "@code": "20", "msg": "command succeeded"}} ) mocker.patch("Panorama.panorama_get_custom_url_category", return_value=existing_url_categories_mock) mocker.patch("Panorama.get_pan_os_major_version", return_value=9) res = mocker.patch("demistomock.results") main() expected_body_request = { "action": "edit", "type": "config", "xpath": "/config/devices/entry/device-group/entry[@name='new device group']/profiles/custom-url-category" "/entry[@name='test']", "element": f"<entry name='test'><list><member>{category}</member></list><type>Category Match</type></entry>", "key": "thisisabogusAPIKEY!", } # make sure that device group is getting overriden by the device-group from command arguments. assert request_mock.call_args.kwargs["body"] == expected_body_request assert res.call_args.args[0]["Contents"] == {"response": {"@status": "success", "@code": "20", "msg": "command succeeded"}} def test_panorama_edit_custom_url_category_command_main_flow_with_sites(mocker): """ Given - integrations parameters. - pan-os-edit-custom-url-category command arguments: sites, device-group and action = 'add'. When - running the pan-os-edit-custom-url-category command through the main flow Then - make sure the context output is returned as expected. - make sure the sites are being HTML escaped correctly for the site. - make sure the device group gets overriden by the command arguments. """ from Panorama import main existing_url_categories_mock = {"list": {"member": []}} expected_site = "example.com/?a=b&c=d" mocker.patch.object(demisto, "params", return_value=integration_panorama_params) mocker.patch.object( demisto, "args", return_value={"name": "test", "action": "add", "sites": ["example.com/?a=b&c=d"], "device-group": "new device group"}, ) mocker.patch.object(demisto, "command", return_value="pan-os-edit-custom-url-category") request_mock = mocker.patch( "Panorama.http_request", return_value={"response": {"@status": "success", "@code": "20", "msg": "command succeeded"}} ) mocker.patch("Panorama.panorama_get_custom_url_category", return_value=existing_url_categories_mock) mocker.patch("Panorama.get_pan_os_major_version", return_value=9) res = mocker.patch("demistomock.results") main() expected_body_request = { "action": "edit", "element": f"<entry name='test'><list><member>{expected_site}</member></list><type>URL List</type></entry>", "key": "thisisabogusAPIKEY!", "type": "config", "xpath": "/config/devices/entry/device-group/entry[@name='new device " "group']/profiles/custom-url-category/entry[@name='test']", } # make sure that device group is getting overriden by the device-group from command arguments. assert request_mock.call_args.kwargs["body"] == expected_body_request assert res.call_args.args[0]["Contents"] == {"response": {"@status": "success", "@code": "20", "msg": "command succeeded"}} def test_panorama_list_edls_command_main_flow(mocker): """ Given - integrations parameters. - EDLs from panorama (including un-committed). When - running the pan-os-list-edls command through the main flow. Then - make sure the context output is returned as expected. - make sure the http request was sent as expected. """ from Panorama import main mocker.patch.object(demisto, "params", return_value=integration_panorama_params) mocker.patch.object(demisto, "args", return_value={}) mocker.patch.object(demisto, "command", return_value="pan-os-list-edls") request_mock = mocker.patch( "Panorama.http_request", return_value=load_json("test_data/list-edls-including-un-committed-edl.json") ) result = mocker.patch("demistomock.results") main() assert request_mock.call_args.kwargs["params"] == { "action": "get", "type": "config", "xpath": "/config/devices/entry/device-group/entry[@name='Lab-Devices']/external-list/entry", "key": "thisisabogusAPIKEY!", } assert list(result.call_args.args[0]["EntryContext"].values())[0] == [ {"Name": "test-1", "Type": "domain", "URL": "http://test.com", "Recurring": "hourly", "DeviceGroup": "Lab-Devices"}, {"Name": "test-2", "Type": "ip", "URL": "http://test1.com", "Recurring": "five-minute", "DeviceGroup": "Lab-Devices"}, ] def test_panorama_edit_edl_command_main_flow(mocker): """ Given - integrations parameters. - pan-os-edit-edl command arguments including device_group When - running the pan-os-edit-edl command through the main flow Then - make sure the context output is returned as expected. - make sure the device group gets overriden by the command arguments. """ from Panorama import main mocker.patch.object(demisto, "params", return_value=integration_panorama_params) mocker.patch.object( demisto, "args", return_value={ "name": "test", "element_to_change": "description", "element_value": "edl1", "device-group": "new device group", }, ) mocker.patch.object(demisto, "command", return_value="pan-os-edit-edl") mocker.patch("Panorama.panorama_get_edl", return_value={"type": {"test": "test"}}) request_mock = mocker.patch( "Panorama.http_request", return_value={"response": {"@status": "success", "@code": "20", "msg": "command succeeded"}} ) res = mocker.patch("demistomock.results") main() # make sure that device group is getting overriden by the device-group from command arguments. assert request_mock.call_args.kwargs["body"] == { "action": "edit", "type": "config", "key": "thisisabogusAPIKEY!", "xpath": "/config/devices/entry/device-group/entry[@name='new device group']/external-list/ent" "ry[@name='test']/type/test/description", "element": "<description>edl1</description>", } assert res.call_args.args[0]["Contents"] == {"response": {"@status": "success", "@code": "20", "msg": "command succeeded"}} def test_panorama_edit_service_group_command_main_flow(mocker): """ Given - integrations parameters. - pan-os-edit-service-group command arguments including device_group When - running the pan-os-edit-service-group command through the main flow Then - make sure the context output is returned as expected. - make sure the device group gets overriden by the command arguments. """ from Panorama import main mocker.patch.object(demisto, "params", return_value=integration_panorama_params) mocker.patch.object(demisto, "args", return_value={"name": "test", "tag": "tag1", "device-group": "new device group"}) mocker.patch.object(demisto, "command", return_value="pan-os-edit-service-group") request_mock = mocker.patch( "Panorama.http_request", return_value={"response": {"@status": "success", "@code": "20", "msg": "command succeeded"}} ) res = mocker.patch("demistomock.results") main() # make sure that device group is getting overriden by the device-group from command arguments. assert request_mock.call_args.kwargs["body"] == { "action": "edit", "type": "config", "xpath": "/config/devices/entry/device-group/entry[@name='new device group']/service-group/entry[@name='test']/tag", "element": "<tag><member>tag1</member></tag>", "key": "thisisabogusAPIKEY!", } assert res.call_args.args[0]["Contents"] == {"response": {"@status": "success", "@code": "20", "msg": "command succeeded"}} def test_panorama_edit_url_filter_command_main_flow(mocker): """ Given - integrations parameters. - pan-os-edit-url-filter command arguments including device_group When - running the pan-os-edit-url-filter command through the main flow Then - make sure the context output is returned as expected. - make sure the device group gets overriden by the command arguments. """ from Panorama import main mocker.patch.object(demisto, "params", return_value=integration_panorama_params) mocker.patch.object( demisto, "args", return_value={"name": "test", "element_to_change": "description", "device-group": "new device group"} ) mocker.patch.object(demisto, "command", return_value="pan-os-edit-url-filter") request_mock = mocker.patch( "Panorama.http_request", return_value={"response": {"@status": "success", "@code": "20", "msg": "command succeeded"}} ) mocker.patch("Panorama.panorama_get_url_filter", return_value={}) mocker.patch("Panorama.get_pan_os_major_version", return_value=9) res = mocker.patch("demistomock.results") main() # make sure that device group is getting overriden by the device-group from command arguments. assert request_mock.call_args.kwargs["body"] == { "action": "edit", "type": "config", "key": "thisisabogusAPIKEY!", "xpath": "/config/devices/entry/device-group/entry[@name='new device group']" "/profiles/url-filtering/entry[@name='test']/description", "element": "<description>None</description>", } assert res.call_args.args[0]["Contents"] == {"response": {"@status": "success", "@code": "20", "msg": "command succeeded"}} class MockedResponse: def __init__(self, text, status_code, reason="", headers=None): self.status_code = status_code self.text = text self.reason = reason self.headers = headers class TestPanoramaCommitCommand: COMMIT_POLLING_ARGS = { "device-group": "some_device", "admin_name": "some_admin_name", "description": "a simple commit", "polling": "true", } EXPECTED_COMMIT_REQUEST_URL_PARAMS = { "action": "partial", "cmd": "<commit><description>a simple commit</description>" "<partial><device-group><member>some_device</member></device-group>" "<admin><member>some_admin_name</member></admin></partial></commit>", "key": "APIKEY", "type": "commit", } @staticmethod def create_mock_responses(job_commit_status_count): mocked_responses = [ # panorama commit api response mock MockedResponse( text='<response status="success" code="19"><result><msg><line>Commit job ' "enqueued with jobid 123</line></msg><job>123</job></result></response>", status_code=200, ) ] mocked_responses += [ # add a mocked response indicating that the job is still in progress MockedResponse( text='<response status="success"><result><job><tenq>2022/07/16 07:50:04</tenq><tdeq>07:50:04<' "/tdeq><id>123</id><user>app</user><type>Commit</type><status>ACT</status><queued>NO</queued>" "<stoppable>no</stoppable><result>PEND</result><tfin>Still Active</tfin><description></" "description><positionInQ>0</positionInQ><progress>69</progress><warnings></warnings>" "<details></details></job></result></response>", status_code=200, ) for _ in range(job_commit_status_count) ] mocked_responses += [ # add a mocked response indicating that the job has finished. MockedResponse( text='<response status="success"><result><job><tenq>2022/07/16 07:26:05</tenq><tdeq>07:26:05</tdeq>' "<id>7206</id><user>app</user><type>Commit</type><status>FIN</status><queued>NO</queued>" "<stoppable>no</stoppable><result>OK</result><tfin>07:26:24</tfin><description></description>" "<positionInQ>0</positionInQ><progress>100</progress><details><line>Configuration " "committed successfully</line></details><warnings></warnings></job></result></response>", status_code=200, ) ] return mocked_responses @pytest.mark.parametrize( "args, expected_request_params, request_result, expected_demisto_result", [ pytest.param( { "device-group": "some_device", "admin_name": "some_admin_name", "description": "a simple commit", "polling": "false", }, { "action": "partial", "cmd": "<commit><description>a simple commit</description>" "<partial><device-group><member>some_device</member></device-group>" "<admin><member>some_admin_name</member></admin></partial></commit>", "key": "thisisabogusAPIKEY!", "type": "commit", }, MockedResponse( text='<response status="success" code="19"><result><msg>' "<line>Commit job enqueued with jobid 19420</line></msg>" "<job>19420</job></result></response>", status_code=200, reason="", ), { "Description": "a simple commit", "JobID": "19420", "Status": "Pending", "Scope": "Partial", "Details": "device-group=some_device; admin=some_admin_name", }, id="only admin changes commit", ), pytest.param( {"device-group": "some_device", "force_commit": "true", "polling": "false"}, { "action": "partial", "cmd": "<commit><force></force>" "<partial><device-group><member>some_device</member></device-group></partial></commit>", "key": "thisisabogusAPIKEY!", "type": "commit", }, MockedResponse( text='<response status="success" code="19"><result><msg>' "<line>Commit job enqueued with jobid 19420</line></msg>" "<job>19420</job></result></response>", status_code=200, reason="", ), { "Description": "", "JobID": "19420", "Status": "Pending", "Scope": "Partial", "Details": "device-group=some_device", }, id="force commit", ), pytest.param( {"device-group": "some_device", "exclude_device_network_configuration": "true", "polling": "false"}, { "action": "partial", "cmd": "<commit><partial>" "<device-group><member>some_device</member></device-group>" "<device-and-network>excluded</device-and-network>" "</partial></commit>", "key": "thisisabogusAPIKEY!", "type": "commit", }, MockedResponse( text='<response status="success" code="19"><result><msg>' "<line>Commit job enqueued with jobid 19420</line></msg>" "<job>19420</job></result></response>", status_code=200, reason="", ), { "Description": "", "JobID": "19420", "Status": "Pending", "Scope": "Partial", "Details": "device-group=some_device; exclude_device_network_configuration=true", }, id="device and network excluded", ), pytest.param( {"device-group": "some_device", "exclude_shared_objects": "true", "polling": "false"}, { "action": "partial", "cmd": "<commit><partial>" "<device-group><member>some_device</member></device-group>" "<shared-object>excluded</shared-object>" "</partial></commit>", "key": "thisisabogusAPIKEY!", "type": "commit", }, MockedResponse( text='<response status="success" code="19"><result><msg>' "<line>Commit job enqueued with jobid 19420</line></msg>" "<job>19420</job></result></response>", status_code=200, reason="", ), { "Description": "", "JobID": "19420", "Status": "Pending", "Scope": "Partial", "Details": "device-group=some_device; exclude_shared_objects=true", }, id="exclude shared objects", ), pytest.param( {"device-group": "some_device", "polling": "false"}, { "action": "partial", "cmd": "<commit>" "<partial><device-group><member>some_device</member></device-group></partial>" "</commit>", "key": "thisisabogusAPIKEY!", "type": "commit", }, MockedResponse( text='<response status="success" code="19"><result><msg>' "<line>Commit job enqueued with jobid 19420</line></msg>" "<job>19420</job></result></response>", status_code=200, reason="", ), { "Description": "", "JobID": "19420", "Status": "Pending", "Scope": "Partial", "Details": "device-group=some_device", }, id="no args", ), ], ) def test_panorama_commit_command_without_polling( self, mocker, args, expected_request_params, request_result, expected_demisto_result ): """ Given: - commit command arguments and the expected api request without polling When: - Running panorama-commit command Then: - Assert the request url is as expected - Assert that panorama commit returns the correct context output """ import Panorama import requests from Panorama import panorama_commit_command Panorama.API_KEY = "thisisabogusAPIKEY!" request_mock = mocker.patch.object(requests, "request", return_value=request_result) command_result = panorama_commit_command(args) called_request_params = request_mock.call_args.kwargs["data"] # The body part of the request assert called_request_params == expected_request_params # check that the URL is sent as expected. assert command_result.outputs == expected_demisto_result # check context is valid @pytest.mark.parametrize( "args, expected_commit_request_url_params, api_response_queue", [ pytest.param( COMMIT_POLLING_ARGS, EXPECTED_COMMIT_REQUEST_URL_PARAMS, create_mock_responses(job_commit_status_count=1) ), pytest.param( COMMIT_POLLING_ARGS, EXPECTED_COMMIT_REQUEST_URL_PARAMS, create_mock_responses(job_commit_status_count=10) ), pytest.param( COMMIT_POLLING_ARGS, EXPECTED_COMMIT_REQUEST_URL_PARAMS, create_mock_responses(job_commit_status_count=5) ), pytest.param( COMMIT_POLLING_ARGS, EXPECTED_COMMIT_REQUEST_URL_PARAMS, create_mock_responses(job_commit_status_count=8) ), pytest.param( COMMIT_POLLING_ARGS, EXPECTED_COMMIT_REQUEST_URL_PARAMS, create_mock_responses(job_commit_status_count=13) ), pytest.param( COMMIT_POLLING_ARGS, EXPECTED_COMMIT_REQUEST_URL_PARAMS, create_mock_responses(job_commit_status_count=0), # commit job finished instantly (very very rare case!) ), ], ) def test_panorama_commit_command_with_polling(self, mocker, args, expected_commit_request_url_params, api_response_queue): """ Given: - pan-os-commit command arguments - expected structure of the URL to commit pan-os configuration - a queue for api responses of the following: 1) first value in the queue is the panorama commit api response 2) panorama job status api response which indicates job isn't done yet (different number each time) 3) last value in the queue is the panorama job status that indicates it has finished and succeeded When: - running pan-os-commit with polling argument. Then: - make sure that the panorama_commit_command function querying for the commit job ID status until its done. - make sure that eventually after polling the panorama_commit_command, that it returns the expected output. """ import Panorama import requests from CommonServerPython import ScheduledCommand from Panorama import panorama_commit_command Panorama.API_KEY = "APIKEY" request_mock = mocker.patch.object(requests, "request", side_effect=api_response_queue) mocker.patch.object(ScheduledCommand, "raise_error_if_not_supported", return_value=None) command_result = panorama_commit_command(args) description = args.get("description") called_request_params = request_mock.call_args.kwargs["data"] # The body part of the request assert called_request_params == expected_commit_request_url_params # check that the URL is sent as expected. assert command_result.readable_output == f'Waiting for commit "{description}" with job ID 123 to finish...' polling_args = { "commit_job_id": "123", "description": description, "hide_polling_output": True, "polling": True, "device-group": args.get("device-group"), "admin_name": args.get("admin_name"), "template": args.get("template"), "exclude_device_network_configuration": args.get("exclude_device_network_configuration"), "exclude_shared_objects": args.get("exclude_shared_objects"), } command_result = panorama_commit_command(polling_args) while command_result.scheduled_command: # if scheduled_command is set, it means that command should still poll assert not command_result.readable_output # make sure that indication of polling is printed only once assert not command_result.outputs # make sure no context output is being returned to war-room during polling command_result = panorama_commit_command(polling_args) # last response of the command should be job status and the commit description assert command_result.outputs == { "JobID": "123", "Description": description, "Status": "Success", "Scope": "Partial", "Details": "device-group=some_device; admin=some_admin_name", } class TestPanoramaPushToDeviceGroupCommand: @staticmethod def create_mock_responses(push_to_devices_job_status_count): mocked_responses = [ # panorama commit api response mock MockedResponse( text='<response status="success" code="19"><result><msg><line>Push job ' "enqueued with jobid 123</line></msg><job>123</job></result></response>", status_code=200, ) ] mocked_responses += [ # add a mocked response indicating that the job is still in progress MockedResponse( text='<response status="success"><result><job><tenq>2022/07/16 07:50:04</tenq><tdeq>07:50:04<' "/tdeq><id>123</id><user>app</user><type>CommitAll</type><status>ACT</status><queued>NO</queued>" "<stoppable>no</stoppable><result>PEND</result><tfin>Still Active</tfin><description></" "description><positionInQ>0</positionInQ><progress>69</progress><warnings></warnings>" "<details></details></job></result></response>", status_code=200, ) for _ in range(push_to_devices_job_status_count) ] with open("test_data/push_to_device_success.xml") as data_file: mocked_responses += [MockedResponse(text=data_file.read(), status_code=200)] return mocked_responses @pytest.mark.parametrize( "api_response_queue", [ create_mock_responses(push_to_devices_job_status_count=1), create_mock_responses(push_to_devices_job_status_count=3), create_mock_responses(push_to_devices_job_status_count=5), create_mock_responses(push_to_devices_job_status_count=8), create_mock_responses(push_to_devices_job_status_count=10), ], ) def test_panorama_push_to_devices_command_with_polling(self, mocker, api_response_queue): """ Given: - pan-os-push-to-device-group command arguments including device-group. - a queue for api responses of the following: 1) first value in the queue is the panorama push to the device group api response 2) panorama job status api response which indicates job isn't done yet (different number each time) 3) last value in the queue is the panorama job status that indicates it has finished and succeeded When: - running pan-os-push-to-device-group with polling argument = True Then: - make sure that the panorama_push_to_device_group_command function querying for the push job ID status until its done. - make sure that eventually after polling the panorama_push_to_device_group_command, that it returns the expected output. - make sure readable output is printed out only once. - make sure context output is returned only when polling is finished. - make sure the device-group from argument overrides the device-group from parameter in context. """ import Panorama import requests from CommonServerPython import ScheduledCommand from Panorama import panorama_push_to_device_group_command args = {"description": "a simple push", "polling": "true", "device-group": "device-group-from-command-arg"} # mimcs the piece of code which decides which device-group will be set into DEVICE_GROUP parameter. Panorama.DEVICE_GROUP = args.get("device-group") or "device-group-from-integration-params" Panorama.API_KEY = "APIKEY" mocker.patch.object(ScheduledCommand, "raise_error_if_not_supported", return_value=None) mocker.patch.object(requests, "request", side_effect=api_response_queue) command_result = panorama_push_to_device_group_command(args) description = args.get("description") assert ( command_result.readable_output == f"Waiting for Job-ID 123 to finish " f"push changes to device-group {Panorama.DEVICE_GROUP}..." ) polling_args = {"push_job_id": "123", "description": description, "hide_polling_output": True, "polling": True} command_result = panorama_push_to_device_group_command(polling_args) while command_result.scheduled_command: # if scheduled_command is set, it means that command should still poll assert not command_result.readable_output # make sure that indication of polling is printed only once assert not command_result.outputs # make sure no context output is being returned to war-room during polling command_result = panorama_push_to_device_group_command(polling_args) assert command_result.outputs.get("JobID") == "123" assert command_result.outputs.get("DeviceGroup") == "device-group-from-command-arg" assert command_result.outputs.get("Status") == "Completed" assert command_result.outputs.get("Details") assert command_result.outputs.get("Warnings") assert command_result.outputs.get("Description") == "a simple push" @pytest.mark.parametrize( "args, expected_request_params, request_result, expected_demisto_result", [ pytest.param( {"polling": "false"}, { "action": "all", "cmd": '<commit-all><shared-policy><device-group><entry name="some_device"/>' "</device-group></shared-policy></commit-all>", "key": "thisisabogusAPIKEY!", "type": "commit", }, MockedResponse( text='<response status="success" code="19"><result><msg>' "<line>Commit job enqueued with jobid 19420</line></msg>" "<job>19420</job></result></response>", status_code=200, reason="", ), {"DeviceGroup": "some_device", "JobID": "19420", "Status": "Pending"}, id="no args", ), pytest.param( {"serial_number": "1337", "polling": "false"}, { "action": "all", "cmd": '<commit-all><shared-policy><device-group><entry name="some_device">' '<devices><entry name="1337"/></devices></entry></device-group>' "</shared-policy></commit-all>", "key": "thisisabogusAPIKEY!", "type": "commit", }, MockedResponse( text='<response status="success" code="19"><result><msg>' "<line>Commit job enqueued with jobid 19420</line></msg>" "<job>19420</job></result></response>", status_code=200, reason="", ), {"DeviceGroup": "some_device", "JobID": "19420", "Status": "Pending"}, id="serial number", ), pytest.param( {"include-template": "false", "polling": "false"}, { "action": "all", "cmd": '<commit-all><shared-policy><device-group><entry name="some_device"/>' "</device-group><include-template>no</include-template></shared-policy>" "</commit-all>", "key": "thisisabogusAPIKEY!", "type": "commit", }, MockedResponse( text='<response status="success" code="19"><result><msg>' "<line>Commit job enqueued with jobid 19420</line></msg>" "<job>19420</job></result></response>", status_code=200, reason="", ), {"DeviceGroup": "some_device", "JobID": "19420", "Status": "Pending"}, id="do not include template", ), ], ) def test_panorama_push_to_device_group_command(mocker, args, expected_request_params, request_result, expected_demisto_result): """ Given: - command args - request result When: - Running panorama-push-to-device-group command Then: - Assert the request url is as expected - Assert demisto results contain the relevant result information """ import Panorama import requests from Panorama import panorama_push_to_device_group_command request_mock = mocker.patch.object(requests, "request", return_value=request_result) Panorama.DEVICE_GROUP = "some_device" Panorama.API_KEY = "thisisabogusAPIKEY!" result = panorama_push_to_device_group_command(args) called_request_params = request_mock.call_args.kwargs["data"] # The body part of the request assert called_request_params == expected_request_params assert result.outputs == expected_demisto_result @pytest.mark.parametrize( "args, expected_request_params, request_result, expected_demisto_result", [ pytest.param( {}, { "action": "all", "cmd": "<commit-all><template><name>some_template</name></template></commit-all>", "key": "thisisabogusAPIKEY!", "type": "commit", }, MockedResponse( text='<response status="success" code="19"><result><msg>' "<line>Commit job enqueued with jobid 19420</line></msg>" "<job>19420</job></result></response>", status_code=200, reason="", ), {"Panorama.Push(val.JobID == obj.JobID)": {"Template": "some_template", "JobID": "19420", "Status": "Pending"}}, id="no args", ), pytest.param( {"validate-only": "true"}, { "action": "all", "cmd": "<commit-all><template><name>some_template</name>" "<validate-only>yes</validate-only></template></commit-all>", "key": "thisisabogusAPIKEY!", "type": "commit", }, MockedResponse( text='<response status="success" code="19"><result><msg>' "<line>Commit job enqueued with jobid 19420</line></msg>" "<job>19420</job></result></response>", status_code=200, reason="", ), {"Panorama.Push(val.JobID == obj.JobID)": {"Template": "some_template", "JobID": "19420", "Status": "Pending"}}, id="with validate", ), pytest.param( {"serial_number": "1337"}, { "action": "all", "cmd": "<commit-all><template><name>some_template</name><device><member>1337</member>" "</device></template></commit-all>", "key": "thisisabogusAPIKEY!", "type": "commit", }, MockedResponse( text='<response status="success" code="19"><result><msg>' "<line>Commit job enqueued with jobid 19420</line></msg>" "<job>19420</job></result></response>", status_code=200, reason="", ), {"Panorama.Push(val.JobID == obj.JobID)": {"Template": "some_template", "JobID": "19420", "Status": "Pending"}}, id="with device", ), ], ) def test_panorama_push_to_template_command(mocker, args, expected_request_params, request_result, expected_demisto_result): """ Given: - command args - request result When: - Running panorama-push-to-device-group command Then: - Assert the request url is as expected - Assert demisto results contain the relevant result information """ import Panorama import requests from Panorama import panorama_push_to_template_command return_results_mock = mocker.patch.object(Panorama, "return_results") request_mock = mocker.patch.object(requests, "request", return_value=request_result) Panorama.TEMPLATE = "some_template" Panorama.API_KEY = "thisisabogusAPIKEY!" panorama_push_to_template_command(args) called_request_params = request_mock.call_args.kwargs["data"] # The body part of the request assert called_request_params == expected_request_params demisto_result_got = return_results_mock.call_args.args[0]["EntryContext"] assert demisto_result_got == expected_demisto_result @pytest.mark.parametrize( "args, expected_request_params, request_result, expected_demisto_result", [ pytest.param( {"template-stack": "some_template_stack"}, { "action": "all", "cmd": "<commit-all><template-stack><name>some_template_stack</name></template-stack></commit-all>", "key": "thisisabogusAPIKEY!", "type": "commit", }, MockedResponse( text='<response status="success" code="19"><result><msg>' "<line>Commit job enqueued with jobid 19420</line></msg>" "<job>19420</job></result></response>", status_code=200, reason="", ), { "Panorama.Push(val.JobID == obj.JobID)": { "TemplateStack": "some_template_stack", "JobID": "19420", "Status": "Pending", } }, id="no args", ), pytest.param( {"validate-only": "true", "template-stack": "some_template_stack"}, { "action": "all", "cmd": "<commit-all><template-stack><name>some_template_stack</name>" "<validate-only>yes</validate-only></template-stack></commit-all>", "key": "thisisabogusAPIKEY!", "type": "commit", }, MockedResponse( text='<response status="success" code="19"><result><msg>' "<line>Commit job enqueued with jobid 19420</line></msg>" "<job>19420</job></result></response>", status_code=200, reason="", ), { "Panorama.Push(val.JobID == obj.JobID)": { "TemplateStack": "some_template_stack", "JobID": "19420", "Status": "Pending", } }, id="with validate", ), pytest.param( {"serial_number": "1337", "template-stack": "some_template_stack"}, { "action": "all", "cmd": "<commit-all><template-stack><name>some_template_stack<" "/name><device><member>1337</member>" "</device></template-stack></commit-all>", "key": "thisisabogusAPIKEY!", "type": "commit", }, MockedResponse( text='<response status="success" code="19"><result><msg>' "<line>Commit job enqueued with jobid 19420</line></msg>" "<job>19420</job></result></response>", status_code=200, reason="", ), { "Panorama.Push(val.JobID == obj.JobID)": { "TemplateStack": "some_template_stack", "JobID": "19420", "Status": "Pending", } }, id="with device", ), ], ) def test_panorama_push_to_template_stack_command(mocker, args, expected_request_params, request_result, expected_demisto_result): """ Given: - command args - request result When: - Running panorama-push-to-device-group command Then: - Assert the request url is as expected - Assert demisto results contain the relevant result information """ import Panorama import requests from Panorama import panorama_push_to_template_stack_command return_results_mock = mocker.patch.object(Panorama, "return_results") request_mock = mocker.patch.object(requests, "request", return_value=request_result) Panorama.TEMPLATE = "some_template" Panorama.API_KEY = "thisisabogusAPIKEY!" panorama_push_to_template_stack_command(args) called_request_params = request_mock.call_args.kwargs["data"] # The body part of the request assert called_request_params == expected_request_params demisto_result_got = return_results_mock.call_args.args[0]["EntryContext"] assert demisto_result_got == expected_demisto_result def test_get_url_category__url_length_gt_1278(mocker): """ Given: - Error in response indicating the url to get category for is over the allowed length (1278 chars) When: - Run get_url_category command Then: - Validate a commandResult is returned with detailed readable output """ # prepare import Panorama import requests from Panorama import panorama_get_url_category_command Panorama.DEVICE_GROUP = "" mocked_res_dict = { "response": { "@status": "error", "@code": "20", "msg": {"line": "test -> url Node can be at most 1278 characters, but current length: 1288"}, } } mocked_res_obj = requests.Response() mocked_res_obj.status_code = 200 mocked_res_obj._content = json.dumps(mocked_res_dict).encode("utf-8") mocker.patch.object(requests, "request", return_value=mocked_res_obj) mocker.patch.object(Panorama, "xml2json", return_value=mocked_res_obj._content) return_results_mock = mocker.patch.object(Panorama, "return_results") # run panorama_get_url_category_command( url_cmd="url", url="test_url", additional_suspicious=[], additional_malicious=[], reliability="B - Usually reliable" ) # validate assert return_results_mock.call_args[0][0][1].readable_output == "URL Node can be at most 1278 characters." def test_get_url_category_multiple_categories_for_url(mocker): """ Given: - response indicating the url has multiple categories. When: - Run get_url_category command Then: - Validate a commandResult is returned with detailed readable output - Validate only a single DBot score is returned for the URL. """ # prepare import Panorama import requests from Panorama import panorama_get_url_category_command Panorama.DEVICE_GROUP = "" mocked_res_dict = { "response": { "@cmd": "status", "@status": "success", "result": "https://someURL.com not-resolved (Base db) expires in 5 seconds\n" "https://someURL.com shareware-and-freeware online-storage-and-backup low-risk (Cloud db)", } } mocked_res_obj = requests.Response() mocked_res_obj.status_code = 200 mocked_res_obj._content = json.dumps(mocked_res_dict).encode("utf-8") mocker.patch.object(requests, "request", return_value=mocked_res_obj) mocker.patch.object(Panorama, "xml2json", return_value=mocked_res_obj._content) return_results_mock = mocker.patch.object(Panorama, "return_results") # run panorama_get_url_category_command( url_cmd="url", url="test_url", additional_suspicious=[], additional_malicious=[], reliability="B - Usually reliable" ) # validate for i in range(3): assert return_results_mock.call_args[0][0][0].outputs[i].get("Category") in [ "shareware-and-freeware", "online-storage-and-backup", "low-risk", ] # category with highest dbot-score assert return_results_mock.call_args[0][0][1].indicator.dbot_score.score == 1 def test_get_url_category_multiple_categories_for_url_missing_categories(mocker): """ Given: - response indicating the url has multiple categories. When: - Run panorama_get_url_category function Then: - Validate all the expected categories are present """ # prepare import Panorama import requests from Panorama import panorama_get_url_category Panorama.DEVICE_GROUP = "" mocked_res_dict = { "response": { "@cmd": "status", "@status": "success", "result": "https://someURL.com not-resolved (Base db) expires in 5 seconds\n" "https://someURL.com shareware-and-freeware online-storage-and-backup low-risk (Cloud db) artificial-intelligence encrypted-dns", # noqa: E501 } } mocked_res_obj = requests.Response() mocked_res_obj.status_code = 200 mocked_res_obj._content = json.dumps(mocked_res_dict).encode("utf-8") mocker.patch.object(Panorama, "xml2json", return_value=mocked_res_obj._content) mocker.patch.object(requests, "request", return_value=mocked_res_obj) # run results = panorama_get_url_category(url_cmd="url", url="test_url") expected_results = [ "shareware-and-freeware", "online-storage-and-backup", "low-risk", "encrypted-dns", "artificial-intelligence", ] # validate for category in expected_results: assert category in results class TestDevices: def test_with_fw(self): import Panorama Panorama.VSYS = "this is a FW instance" assert list(Panorama.devices()) == [(None, None)] def test_with_specific_target_and_vsys(self): import Panorama Panorama.VSYS = None # this a Panorama instance assert list(Panorama.devices(targets=["target"], vsys_s=["vsys1", "vsys2"])) == [("target", "vsys1"), ("target", "vsys2")] def test_with_specific_target_only(self, requests_mock): import Panorama with open("test_data/devices_list.xml") as data_file: requests_mock.get(Panorama.URL, text=data_file.read()) Panorama.VSYS = None # this a Panorama instance assert list(Panorama.devices(targets=["target1"])) == [("target1", "vsys1"), ("target1", "vsys2")] def test_without_specify(self, requests_mock): import Panorama with open("test_data/devices_list.xml") as data_file: requests_mock.get(Panorama.URL, text=data_file.read()) Panorama.VSYS = None # this a Panorama instance assert list(Panorama.devices()) == [("target1", "vsys1"), ("target1", "vsys2"), ("target2", None)] def load_xml_root_from_test_file(xml_file: str): """Given an XML file, loads it and returns the root element XML object.""" return ElementTree.parse(xml_file).getroot() MOCK_PANORAMA_SERIAL = "111222334455" MOCK_FIREWALL_1_SERIAL = "111111111111111" MOCK_FIREWALL_2_SERIAL = "222222222222222" MOCK_FIREWALL_3_SERIAL = "333333333333333" def mock_software_object(): """Mocks PanDevice.software""" class MockSoftwareObject: versions = { "9.1.0": { "version": "9.1.0", "filename": "Pan-9.1.0", "size": 150, "size_kb": 150000, "release_notes": "https://releasenotes.paloaltonetworks.com", "downloaded": True, "current": True, "latest": True, "uploaded": True, } } def check(self): pass def download(self, *args, **kwargs): pass def install(self, *args, **kwargs): pass return MockSoftwareObject() @pytest.fixture def mock_firewall(): mock_firewall = MagicMock(spec=Firewall) mock_firewall.serial = MOCK_FIREWALL_1_SERIAL mock_firewall.hostname = None mock_firewall.software = mock_software_object() return mock_firewall @pytest.fixture def mock_panorama(): mock_panorama = MagicMock(spec=Panorama) mock_panorama.serial = MOCK_PANORAMA_SERIAL mock_panorama.hostname = None mock_panorama.software = mock_software_object() return mock_panorama def mock_device_groups(): mock_device_group = MagicMock(spec=DeviceGroup) mock_device_group.name = "test-dg" return [mock_device_group] def mock_templates(): mock_template = MagicMock(spec=Template) mock_template.name = "test-template" return [mock_template] def mock_template_stack(): mock_template_stack = MagicMock(spec=TemplateStack) mock_template_stack.name = "test-template-stack" return [mock_template_stack] def mock_vsys(): mock_vsys = MagicMock(spec=Vsys) mock_vsys.name = "vsys1" return [mock_vsys] def mock_address_objects(): from Panorama import AddressObject mock_object_1 = MagicMock(spec=AddressObject) mock_object_1.name = "test-address-1" mock_object_2 = MagicMock(spec=AddressObject) mock_object_2.name = "test-address-2" return [mock_object_1, mock_object_2] def mock_good_log_fowarding_profile(): good_log_forwarding_profile = LogForwardingProfile() good_log_forwarding_profile.enhanced_logging = True return [good_log_forwarding_profile] def mock_bad_log_fowarding_profile(): bad_Log_forwarding_profile = LogForwardingProfile() bad_Log_forwarding_profile.enhanced_logging = False bad_Log_forwarding_profile.name = "test-bad" return [bad_Log_forwarding_profile] def mock_good_log_forwarding_profile_match_list(): return [ LogForwardingProfileMatchList(log_type="traffic"), LogForwardingProfileMatchList(log_type="threat"), ] def mock_good_vulnerability_profile(): from Panorama import VulnerabilityProfile, VulnerabilityProfileRule vulnerability_profile = VulnerabilityProfile() vulnerability_profile.name = "good-vuln-profile" vulnerability_profile.children = [ VulnerabilityProfileRule(severity=["critical"], is_reset_both=True), VulnerabilityProfileRule(severity=["high"], is_reset_both=True), VulnerabilityProfileRule(severity=["medium"], is_alert=True), VulnerabilityProfileRule(severity=["low"], is_alert=True), ] return vulnerability_profile def mock_bad_vulnerability_profile(): from Panorama import VulnerabilityProfile, VulnerabilityProfileRule vulnerability_profile = VulnerabilityProfile() vulnerability_profile.name = "bad-vuln-profile" vulnerability_profile.children = [ VulnerabilityProfileRule(severity=["critical"], is_reset_both=True), VulnerabilityProfileRule(severity=["high"], is_reset_both=True), VulnerabilityProfileRule(severity=["medium"], is_alert=True), ] return vulnerability_profile def mock_good_spyware_profile(): from Panorama import AntiSpywareProfile, AntiSpywareProfileRule antispyware_profile = AntiSpywareProfile() antispyware_profile.name = "good-spyware-profile" antispyware_profile.children = [ AntiSpywareProfileRule(severity=["critical"], is_reset_both=True), AntiSpywareProfileRule(severity=["high"], is_reset_both=True), AntiSpywareProfileRule(severity=["medium"], is_alert=True), AntiSpywareProfileRule(severity=["low"], is_alert=True), ] return antispyware_profile def mock_bad_spyware_profile(): from Panorama import AntiSpywareProfile, AntiSpywareProfileRule antispyware_profile = AntiSpywareProfile() antispyware_profile.name = "bad-spyware-profile" antispyware_profile.children = [ AntiSpywareProfileRule(severity=["critical"], is_reset_both=True), AntiSpywareProfileRule(severity=["high"], is_reset_both=True), AntiSpywareProfileRule(severity=["medium"], is_alert=True), ] return antispyware_profile def mock_good_security_zones(): from Panorama import Zone zone = Zone() zone.log_setting = "example-log-setting" return [Zone(log_setting="example"), Zone(log_setting="second_example")] def mock_bad_security_zones(): from Panorama import Zone zone = Zone() zone.log_setting = "example-log-setting" return [Zone(name="test-bad"), Zone(log_setting="second_example")] def mock_good_security_rules(): from Panorama import SecurityRule return [SecurityRule(group="spg", log_setting="example", log_end=True)] def mock_bad_security_rules(): from Panorama import SecurityRule return [ # Missing SPG SecurityRule(name="test-bad", log_setting="example", log_end=True), # Missing log profile SecurityRule(name="test-bad-no-lfp", group="spg", log_end=True), # Missing log at session end SecurityRule( name="test-bad-no-spg", group="spg", log_setting="example", ), ] def mock_good_url_filtering_profile(): from Panorama import BestPractices, URLFilteringProfile url_filtering_profile = URLFilteringProfile() url_filtering_profile.name = "good-url-filtering-profile" url_filtering_profile.block = BestPractices.URL_BLOCK_CATEGORIES return url_filtering_profile def mock_bad_url_filtering_profile(): from Panorama import URLFilteringProfile url_filtering_profile = URLFilteringProfile() url_filtering_profile.name = "bad-url-filtering-profile" url_filtering_profile.block = ["hacking"] return url_filtering_profile def mock_issue_with_underscores(): return { "container_name": "test-dg", "issue_code": "BP-V-1", "description": "Log forwarding profile is missing enhanced application logging", "name": "test-bad", "hostid": MOCK_FIREWALL_1_SERIAL, } def mock_enhanced_log_forwarding_issue_dict(): return { "containername": "test-dg", "issuecode": "BP-V-1", "description": "Log forwarding profile is missing enhanced application logging", "name": "test-bad", "hostid": MOCK_FIREWALL_1_SERIAL, } def mock_security_zone_no_log_setting_issue_dict(): return { "containername": "test-dg", "issuecode": "BP-V-7", "description": "Security zone has no log forwarding setting", "name": "test-bad", "hostid": MOCK_FIREWALL_1_SERIAL, } def mock_security_rule_log_settings_issue_dict(): return { "containername": "test-dg", "issuecode": "BP-V-8", "description": "Security rule has no log setting", "name": "test-bad-no-lfp", "hostid": MOCK_FIREWALL_1_SERIAL, } def mock_security_rule_security_profile_group_issue_dict(): return { "containername": "test-dg", "issuecode": "BP-V-10", "description": "Security rule has no security profile group", "name": "test-bad-no-spg", "hostid": MOCK_FIREWALL_1_SERIAL, } @pytest.fixture def mock_topology(mock_panorama, mock_firewall): from Panorama import Topology topology = Topology() topology.panorama_objects = { MOCK_PANORAMA_SERIAL: mock_panorama, } topology.firewall_objects = {MOCK_FIREWALL_1_SERIAL: mock_firewall} topology.ha_active_devices = {MOCK_PANORAMA_SERIAL: mock_panorama, MOCK_FIREWALL_1_SERIAL: mock_firewall} topology.ha_pair_serials = { MOCK_PANORAMA_SERIAL: "1.1.1.1", MOCK_FIREWALL_1_SERIAL: MOCK_FIREWALL_2_SERIAL, } return topology @pytest.fixture def mock_firewall_topology(mock_firewall): from Panorama import Topology topology = Topology() topology.firewall_objects = {MOCK_FIREWALL_1_SERIAL: mock_firewall} return topology @pytest.fixture def mock_single_device_topology(mock_panorama): from Panorama import Topology topology = Topology() topology.panorama_objects = { MOCK_PANORAMA_SERIAL: mock_panorama, } topology.ha_active_devices = { MOCK_PANORAMA_SERIAL: mock_panorama, } return topology class TestTopology: """Tests the Topology class and all of it's methods""" SHOW_HA_STATE_ENABLED_XML = "test_data/show_ha_state_enabled.xml" SHOW_HA_STATE_PANORAMA_ENABLED = "test_data/show_ha_state_panorama_enabled.xml" SHOW_HA_STATE_DISABLED_XML = "test_data/show_ha_state_disabled.xml" SHOW_DEVICES_ALL_XML = "test_data/panorama_show_devices_all.xml" @patch("Panorama.Topology.get_all_child_firewalls") @patch("Panorama.run_op_command") def test_add_firewall_device_object(self, patched_run_op_command, _, mock_firewall): """ Given the XML output of show ha state and a firewall object, test it is correctly added to the topology. """ from Panorama import Topology patched_run_op_command.return_value = load_xml_root_from_test_file(TestTopology.SHOW_HA_STATE_DISABLED_XML) topology = Topology() topology.add_device_object(mock_firewall) assert MOCK_FIREWALL_1_SERIAL in topology.firewall_objects @patch("Panorama.Topology.get_all_child_firewalls") @patch("Panorama.run_op_command") def test_add_panorama_device_object(self, patched_run_op_command, _, mock_panorama): """ Given the output of show_ha_state with no entries, assert that the Panorama device has been added to the topolog as a panorama type device. """ from Panorama import Topology patched_run_op_command.return_value = load_xml_root_from_test_file(TestTopology.SHOW_HA_STATE_DISABLED_XML) topology = Topology() topology.add_device_object(mock_panorama) assert MOCK_PANORAMA_SERIAL in topology.panorama_objects assert MOCK_PANORAMA_SERIAL in topology.ha_active_devices assert MOCK_PANORAMA_SERIAL not in topology.firewall_objects @patch("Panorama.Topology.get_all_child_firewalls") @patch("Panorama.run_op_command") def test_add_panorama_device_object_with_ha(self, patched_run_op_command, _, mock_panorama): """ Given a Panorama where High availability is active, test that it is correctly added to the topology. """ from Panorama import Topology patched_run_op_command.return_value = load_xml_root_from_test_file(TestTopology.SHOW_HA_STATE_PANORAMA_ENABLED) topology = Topology() topology.add_device_object(mock_panorama) assert MOCK_PANORAMA_SERIAL in topology.panorama_objects assert MOCK_PANORAMA_SERIAL in topology.ha_active_devices assert MOCK_PANORAMA_SERIAL in topology.ha_pair_serials assert MOCK_PANORAMA_SERIAL not in topology.firewall_objects @patch("Panorama.run_op_command") def test_get_all_child_firewalls(self, patched_run_op_command, mock_panorama): """ Given the output of show devices all, assert that all the devices are added correctly to the topology with the correct HA State information. """ from Panorama import Topology patched_run_op_command.return_value = load_xml_root_from_test_file(TestTopology.SHOW_DEVICES_ALL_XML) topology = Topology() topology.get_all_child_firewalls(mock_panorama) # 222... firewall should be Active, with 111... as it's peer assert MOCK_FIREWALL_2_SERIAL in topology.ha_active_devices assert topology.ha_active_devices.get(MOCK_FIREWALL_2_SERIAL) == MOCK_FIREWALL_1_SERIAL # 333... is standalone assert MOCK_FIREWALL_3_SERIAL in topology.ha_active_devices assert topology.ha_active_devices.get(MOCK_FIREWALL_3_SERIAL) == "STANDALONE" @patch("Panorama.run_op_command") def test_get_active_devices(self, patched_run_op_command, mock_panorama): """ Given a topology with a mixture of active and passive devices, assert that active_devices() returns the correct lists of objects. """ from Panorama import Topology patched_run_op_command.return_value = load_xml_root_from_test_file(TestTopology.SHOW_DEVICES_ALL_XML) topology = Topology() topology.add_device_object(mock_panorama) result_list = list(topology.active_devices()) # Should be 3; panorama, one active firewall in a pair, and one stanadlone firewall (from panorama_show_devices_all.xml) assert len(result_list) == 3 # Same as above by try filtering by serial number result_list = list(topology.active_devices(filter_str=MOCK_FIREWALL_3_SERIAL)) assert len(result_list) == 1 # Now try just getting the "top level" devices - should only return Panorama result_list = list(topology.active_top_level_devices()) assert len(result_list) == 1 assert isinstance(result_list[0], Panorama) @patch("Panorama.Template.refreshall", return_value=mock_templates()) @patch("Panorama.TemplateStack.refreshall", return_value=[]) @patch("Panorama.Vsys.refreshall", return_value=[]) @patch("Panorama.DeviceGroup.refreshall", return_value=mock_device_groups()) def test_get_containers(self, _, __, ___, ____, mock_panorama): """ Given a list of device groups, vsys and templates, and a device, assert that get_all_object_containers() correctly returns the specified containers. """ from Panorama import Topology topology = Topology() topology.add_device_object(mock_panorama) result = topology.get_all_object_containers() # Because it's panorama, should be; [shared, device-group, template] assert len(result) == 3 class TestUtilityFunctions: """Tests all the utility fucntions like dataclass_to_dict, etc""" SHOW_JOBS_ALL_XML = "test_data/show_jobs_all.xml" def test_dataclass_from_dict(self, mock_panorama): """Given a dictionary and dataclass type, assert that it is correctly converted into the dataclass.""" from Panorama import CommitStatus, dataclass_from_dict example_dict = {"job-id": "10", "commit-type": "whatever", "status": "OK", "device-type": "firewall"} mock_panorama.hostname = None result_dataclass: CommitStatus = dataclass_from_dict(mock_panorama, example_dict, CommitStatus) assert result_dataclass.job_id assert result_dataclass.commit_type assert result_dataclass.status assert result_dataclass.device_type # With no hostname, hostid should be the serial number of the device assert result_dataclass.hostid == MOCK_PANORAMA_SERIAL mock_panorama.hostname = "test" mock_panorama.serial = None result_dataclass: CommitStatus = dataclass_from_dict(mock_panorama, example_dict, CommitStatus) # With a hostname and no serial, hostid shold be the hostname assert result_dataclass.hostid == "test" def test_flatten_xml_to_dict(self): """Given an XML element, assert that it is converted into a flat dictionary.""" from Panorama import ShowJobsAllResultData, flatten_xml_to_dict xml_element = load_xml_root_from_test_file(TestUtilityFunctions.SHOW_JOBS_ALL_XML) result_element = xml_element.find("./result/job") result = flatten_xml_to_dict(result_element, {}, ShowJobsAllResultData) assert "type" in result def test_resolve_host_id(self, mock_panorama): """Given a device object, test the hostid, the unique ID of the device from the perspective of the new commands, can always be resolved as either the hostname or serial number. Pan-os-python will populate only one of these, depending on how the device has been connected.""" from Panorama import resolve_host_id mock_panorama.hostname = None result = resolve_host_id(mock_panorama) assert result == MOCK_PANORAMA_SERIAL mock_panorama.hostname = "test" mock_panorama.serial = None result = resolve_host_id(mock_panorama) assert result == "test" def test_resolve_container_name(self, mock_panorama): """Same as hostid but resolve it for a container, like a device group or template. This will always return the name attribute unless it's a device itself, which is the case for shared objects.""" from Panorama import resolve_container_name # Test the "shared" container assert resolve_container_name(mock_panorama) == "shared" device_group = mock_device_groups()[0] assert resolve_container_name(device_group) == "test-dg" def test_dataclass_to_command_results(self): """Given a list of dataclasses, check that this function correctly converts it to a commandResults object.""" from Panorama import PanosObjectReference, dataclasses_to_command_results test_dataclass = PanosObjectReference( hostid=MOCK_FIREWALL_1_SERIAL, container_name="test", object_type="TestObject", name="test_name" ) results = dataclasses_to_command_results(test_dataclass) # Check we get the right table headers when no additional arguments are given assert "container_name|hostid|name|object_type" in results.readable_output assert "### PAN-OS Object" in results.readable_output results = dataclasses_to_command_results( test_dataclass, override_table_name="Test Table", override_table_headers=["hostid", "name", "container_name"] ) # When we provide overrides, check they are rendered correctly in the readable output assert "hostid|name|container_name" in results.readable_output assert "### Test Table" in results.readable_output class TestPanoramaCommand: """ Test all the commands relevant to Panorama All of these commands use the real XML in test_data to ensure it is parsed and converted to dataclasses correctly. """ SHOW_DEVICEGROUPS_XML = "test_data/show_device_groups.xml" SHOW_TEMPLATESTACK_XML = "test_data/show_template_stack.xml" @patch("Panorama.run_op_command") def test_get_device_groups(self, patched_run_op_command, mock_topology): """Given the output XML for show device groups, assert it is parsed into the dataclasses correctly.""" from Panorama import PanoramaCommand patched_run_op_command.return_value = load_xml_root_from_test_file(TestPanoramaCommand.SHOW_DEVICEGROUPS_XML) result = PanoramaCommand.get_device_groups(mock_topology) assert len(result) == 3 assert result[0].name assert result[0].hostid assert result[0].connected assert result[0].serial assert result[0].last_commit_all_state_sp # Support for missing hostname assert not result[2].hostname @patch("Panorama.run_op_command") def test_get_template_stacks(self, patched_run_op_command, mock_topology): """Given the output XML for show template-stacks, assert it is parsed into the dataclasses correctly.""" from Panorama import PanoramaCommand patched_run_op_command.return_value = load_xml_root_from_test_file(TestPanoramaCommand.SHOW_TEMPLATESTACK_XML) result = PanoramaCommand.get_template_stacks(mock_topology) assert len(result) == 2 assert result[0].name assert result[0].hostid assert result[0].connected assert result[0].serial assert result[0].last_commit_all_state_tpl @patch("Panorama.run_op_command") def test_get_template_stacks_without_hostname(self, patched_run_op_command, mock_topology): """Given the output XML for show template-stacks without hostname, assert it is parsed into the dataclasses correctly.""" from Panorama import PanoramaCommand patched_run_op_command.return_value = load_xml_root_from_test_file("test_data/show_template_stack_without_hostname.xml") result = PanoramaCommand.get_template_stacks(mock_topology) assert len(result) == 2 assert result[0].name assert not result[0].hostname assert result[0].hostid assert result[0].connected assert result[0].serial assert result[0].last_commit_all_state_tpl class TestUniversalCommand: """Test all the commands relevant to both Panorama and Firewall devices""" SHOW_SYSTEM_INFO_XML = "test_data/show_system_info.xml" SHOW_JOB_XML = "test_data/show_jobs_all.xml" SHOW_COMMIT_JOB_XML = "test_data/show_commit_jobs_all.xml" SHOW_JOB_WITH_FAILED_XML = "test_data/show_jobs_with_failed.xml" @patch("Panorama.run_op_command") def test_get_system_info(self, patched_run_op_command, mock_topology): """Given the output XML for show system info, assert it is parsed into the dataclasses correctly.""" import Panorama patched_run_op_command.return_value = load_xml_root_from_test_file(TestUniversalCommand.SHOW_SYSTEM_INFO_XML) result = Panorama.UniversalCommand.get_system_info(mock_topology) # Check all attributes of result data have values for result_dataclass in result.result_data: for value in result_dataclass.__dict__.values(): assert value # Check all attributes of summary data have values for result_dataclass in result.summary_data: for value in result_dataclass.__dict__.values(): assert value def test_get_system_info_ignores_platform_injected_args(self, mocker): """ Regression (CRTX-240383): when the command is invoked with a brand-scoped context (e.g. as an Agentix action), the platform injects a 'using-brand' arg. The pan-os-platform-get-system-info handler must not forward it to the typed get_system_info() function (which would raise 'unexpected keyword argument'). """ import Panorama mocker.patch.object(Panorama, "get_topology", return_value=MagicMock()) mocker.patch.object( demisto, "args", return_value={"device_filter_string": "fw1", "target": "007", "using-brand": "Panorama"}, ) mocker.patch.object(demisto, "command", return_value="pan-os-platform-get-system-info") mocker.patch.object(demisto, "params", return_value=integration_firewall_params) get_system_info_mock = mocker.patch.object(Panorama, "get_system_info", return_value=MagicMock()) mocker.patch.object(Panorama, "dataclasses_to_command_results", return_value=MagicMock()) mocker.patch.object(Panorama, "return_results") Panorama.main() # Must have been called without raising, and without the platform-injected key. get_system_info_mock.assert_called_once() _, kwargs = get_system_info_mock.call_args assert "using-brand" not in kwargs assert kwargs == {"device_filter_string": "fw1", "target": "007"} def test_get_available_software(self, mock_topology): """ Test we can convert result from PanDevice.software.check() into the correct dataclasses This does not use patching, but instead the mock objects themselves from mock_topology """ from Panorama import UniversalCommand result = UniversalCommand.get_available_software(mock_topology) # Check all attributes of summary data have values for result_dataclass in result.summary_data: for value in result_dataclass.__dict__.values(): assert value @patch("Panorama.run_op_command") def test_get_jobs(self, patched_run_op_command, mock_topology): """Given the output XML for show jobs all assert it is parsed into the dataclasses correctly.""" from Panorama import UniversalCommand patched_run_op_command.return_value = load_xml_root_from_test_file(TestUniversalCommand.SHOW_JOB_XML) result = UniversalCommand.show_jobs(mock_topology) # Check all attributes of result data have values for result_dataclass in result: for key, value in result_dataclass.__dict__.items(): # Nullable Values if key not in ["description", "user", "details", "warnings"]: assert value @patch("Panorama.run_op_command") @patch("Panorama.demisto.debug") def test_get_jobs_with_failed(self, patched_debug, patched_run_op_command): """Given the output XML for show jobs with a failed job, assert it is skipped.""" from Panorama import Panorama, ShowJobsAllResultData, UniversalCommand patched_run_op_command.return_value = load_xml_root_from_test_file(TestUniversalCommand.SHOW_JOB_WITH_FAILED_XML) MockTopology = type("MockTopology", (), {"all": lambda *x, **y: [Panorama(hostname="123")]}) result = UniversalCommand.show_jobs(MockTopology()) assert patched_debug.call_args_list[0].args[0] == ( "'ShowJobsAllResultData' cannot be instantiated with element: " '{"job": {"type": "Failed-Job", "details": {"line": "job failed because of configd restart"}, "warnings": null}}' '\nerror=TypeError("ShowJobsAllResultData.__init__() missing 9 required positional arguments: ' "'id', 'tfin', 'status', 'result', 'user', 'tenq', 'stoppable', 'positionInQ', and 'progress'\")" ) assert isinstance(result, ShowJobsAllResultData) assert result.__dict__ == { "description": "description", "hostid": "123", "id": 7, "positionInQ": "0", "progress": "100", "result": "OK", "status": "FIN", "stoppable": "no", "tenq": "2024/08/25 22:07:53", "tfin": "2024/08/25 22:09:00", "type": "Job Type", "user": None, "warnings": None, } @patch("Panorama.get_topology") @patch("Panorama.get_jobs") def test_get_jobs_command_polling_terminal(self, patched_get_jobs, patched_get_topology, mock_topology): """ Given: polling=true, a single job id, and a job whose status is 'FIN'. When: get_jobs_command is invoked. Then: The returned CommandResults have no scheduled_command (polling stops). """ from Panorama import ShowJobsAllResultData, get_jobs_command patched_get_topology.return_value = mock_topology patched_get_jobs.return_value = ShowJobsAllResultData( hostid="fw1", id=7, type="Commit", tfin="2024/08/25 22:09:00", status="FIN", result="OK", user="admin", tenq="2024/08/25 22:07:53", stoppable="no", positionInQ=0, progress=100, warnings=None, description="", ) result = get_jobs_command({"polling": "true", "id": "7"}) assert result.scheduled_command is None assert result.outputs["status"] == "FIN" assert result.outputs["result"] == "OK" assert result.outputs["id"] == 7 @patch("Panorama.get_topology") @patch("Panorama.get_jobs") def test_get_jobs_command_polling_still_running(self, patched_get_jobs, patched_get_topology, mock_topology): """ Given: polling=true, a single job id, and a job whose status is 'ACT' (still running). When: get_jobs_command is invoked. Then: The returned CommandResults have a scheduled_command (polling continues). """ from Panorama import ShowJobsAllResultData, get_jobs_command patched_get_topology.return_value = mock_topology patched_get_jobs.return_value = ShowJobsAllResultData( hostid="fw1", id=7, type="Commit", tfin="", status="ACT", result="PEND", user="admin", tenq="2024/08/25 22:07:53", stoppable="no", positionInQ=0, progress=50, warnings=None, description="", ) result = get_jobs_command({"polling": "true", "id": "7"}) assert result.scheduled_command is not None @patch("Panorama.get_topology") @patch("Panorama.get_jobs") def test_get_jobs_command_no_polling(self, patched_get_jobs, patched_get_topology, mock_topology): """ Given: no polling argument (defaults to false). When: get_jobs_command is invoked without polling. Then: The returned CommandResults have no scheduled_command regardless of status. """ from Panorama import ShowJobsAllResultData, get_jobs_command patched_get_topology.return_value = mock_topology patched_get_jobs.return_value = ShowJobsAllResultData( hostid="fw1", id=7, type="Commit", tfin="", status="ACT", result="PEND", user="admin", tenq="2024/08/25 22:07:53", stoppable="no", positionInQ=0, progress=50, warnings=None, description="", ) result = get_jobs_command({"id": "7"}) assert result.scheduled_command is None @patch("Panorama.get_topology") @patch("Panorama.get_jobs") def test_get_jobs_command_polling_no_id_raises(self, patched_get_jobs, patched_get_topology, mock_topology): """ Given: polling=true but no id argument. When: get_jobs_command is invoked. Then: A DemistoException is raised, since polling requires a single job id. """ from Panorama import get_jobs_command patched_get_topology.return_value = mock_topology with pytest.raises(DemistoException, match="The 'id' argument is required when 'polling' is set to true."): get_jobs_command({"polling": "true"}) # get_jobs must not be called when the validation fails. patched_get_jobs.assert_not_called() @patch("Panorama.get_topology") @patch("Panorama.get_jobs") def test_get_jobs_command_polling_ignores_status_and_job_type(self, patched_get_jobs, patched_get_topology, mock_topology): """ Given: polling=true, a single job id, and status/job_type filters provided. When: get_jobs_command is invoked. Then: get_jobs is called with status=None and job_type=None (filters ignored), so a still-running job is not filtered out and polling can continue. """ from Panorama import ShowJobsAllResultData, get_jobs_command patched_get_topology.return_value = mock_topology patched_get_jobs.return_value = ShowJobsAllResultData( hostid="fw1", id=7, type="Downloadxxx", tfin="", status="ACT", result="PEND", user="admin", tenq="2024/08/25 22:07:53", stoppable="no", positionInQ=0, progress=50, warnings=None, description="", ) result = get_jobs_command({"polling": "true", "id": "7", "status": "FIN", "job_type": "Commit"}) # Filters must be dropped while polling by id. assert patched_get_jobs.call_args.kwargs["status"] is None assert patched_get_jobs.call_args.kwargs["job_type"] is None assert patched_get_jobs.call_args.kwargs["id"] == "7" # Job is still running, so polling should continue. assert result.scheduled_command is not None @patch("Panorama.get_topology") @patch("Panorama.get_jobs") def test_get_jobs_command_no_polling_keeps_status_and_job_type(self, patched_get_jobs, patched_get_topology, mock_topology): """ Given: no polling (defaults to false), a job id, and status/job_type filters. When: get_jobs_command is invoked. Then: get_jobs is called with the provided status/job_type (non-polling flow unchanged). """ from Panorama import ShowJobsAllResultData, get_jobs_command patched_get_topology.return_value = mock_topology patched_get_jobs.return_value = ShowJobsAllResultData( hostid="fw1", id=7, type="Commit", tfin="2024/08/25 22:09:00", status="FIN", result="OK", user="admin", tenq="2024/08/25 22:07:53", stoppable="no", positionInQ=0, progress=100, warnings=None, description="", ) get_jobs_command({"id": "7", "status": "FIN", "job_type": "Commit"}) # Non-polling flow must keep applying the filters. assert patched_get_jobs.call_args.kwargs["status"] == "FIN" assert patched_get_jobs.call_args.kwargs["job_type"] == "Commit" def test_download_software(self, mock_topology): """ Test the download software function returns the correct data. The pan-os-python download software actually doesn't return any output itself unless it errors, so we just check our dataclass is set correctly within the function and retuned. """ from Panorama import UniversalCommand result = UniversalCommand.download_software(mock_topology, "9.1.0") # Check all attributes of summary data have values for result_dataclass in result.summary_data: for value in result_dataclass.__dict__.values(): assert value def test_reboot(self, mock_topology): """ Test the reboot function returns the corect data The pan-os-python reboot method actually doesn't return any output itself unless it errors, so we just check our dataclass is set correctly within the function and returned by this function. """ from Panorama import UniversalCommand result = UniversalCommand.reboot(mock_topology, MOCK_PANORAMA_SERIAL) # Check all attributes of summary data have values for result_dataclass in result.summary_data: for value in result_dataclass.__dict__.values(): assert value # We also want to check that if an empty string is passed, an error is returned with pytest.raises( DemistoException, match="filter_str is not the exact ID of a host in this topology; use a more specific filter string.", ): UniversalCommand.reboot(mock_topology, "") # Lets also check that if an invalid hostid is given, we also raise. with pytest.raises( DemistoException, match="filter_str badserialnumber is not the exact ID of " "a host in this topology; use a more specific filter string.", ): UniversalCommand.reboot(mock_topology, "badserialnumber") @patch("Panorama.run_op_command") def test_system_status(self, patched_run_op_command, mock_topology): """ Given a topology object with a mixture of systems in it, assert that check_system_availability returns the correct status based on whether devices are connected or not. """ from Panorama import UniversalCommand patched_run_op_command.return_value = load_xml_root_from_test_file(TestUniversalCommand.SHOW_SYSTEM_INFO_XML) # Check a normal, up device result = UniversalCommand.check_system_availability(mock_topology, MOCK_PANORAMA_SERIAL) assert result.up # Check a device that isn't in the topology result = UniversalCommand.check_system_availability(mock_topology, "fake") assert result assert not result.up def test_system_status_command_polling_device_up(self, mocker, mock_topology): """ Given: - polling=true and a target device that is already up (operational_mode == 'normal'). When: - Running system_status_command. Then: - Polling stops immediately (no scheduled_command) and the SystemStatus context is returned. """ from CommonServerPython import ScheduledCommand from Panorama import CheckSystemStatus, system_status_command mocker.patch("Panorama.get_topology", return_value=mock_topology) mocker.patch( "Panorama.system_status", return_value=CheckSystemStatus(hostid=MOCK_PANORAMA_SERIAL, up=True), ) mocker.patch.object(ScheduledCommand, "raise_error_if_not_supported", return_value=None) args = {"target": MOCK_PANORAMA_SERIAL, "polling": "true"} result = system_status_command(args) assert result.scheduled_command is None assert result.outputs == {"hostid": MOCK_PANORAMA_SERIAL, "up": True} def test_system_status_command_polling_device_down(self, mocker, mock_topology): """ Given: - polling=true and a target device that is not yet available (up=False). When: - Running system_status_command. Then: - A scheduled_command is returned so polling continues. - A "waiting" message is shown. - The last known status (up=False) is still written to context so that on polling timeout the war-room shows the final PANOS.SystemStatus entry. """ from CommonServerPython import ScheduledCommand from Panorama import CheckSystemStatus, system_status_command mocker.patch("Panorama.get_topology", return_value=mock_topology) mocker.patch( "Panorama.system_status", return_value=CheckSystemStatus(hostid=MOCK_PANORAMA_SERIAL, up=False), ) mocker.patch.object(ScheduledCommand, "raise_error_if_not_supported", return_value=None) args = {"target": MOCK_PANORAMA_SERIAL, "polling": "true"} result = system_status_command(args) assert result.scheduled_command is not None assert "Waiting for device" in (result.readable_output or "") # Last-known status must still be in context so a polling timeout leaves the # war-room with a meaningful final entry rather than only a waiting message. assert result.outputs == {"hostid": MOCK_PANORAMA_SERIAL, "up": False} def test_system_status_command_no_polling(self, mocker, mock_topology): """ Given: - polling not provided (default false) even if the device is not up. When: - Running system_status_command. Then: - The command does not poll (no scheduled_command) and returns the current status as-is. """ from Panorama import CheckSystemStatus, system_status_command mocker.patch("Panorama.get_topology", return_value=mock_topology) mocker.patch( "Panorama.system_status", return_value=CheckSystemStatus(hostid=MOCK_PANORAMA_SERIAL, up=False), ) args = {"target": MOCK_PANORAMA_SERIAL} result = system_status_command(args) assert result.scheduled_command is None assert result.outputs == {"hostid": MOCK_PANORAMA_SERIAL, "up": False} class TestFirewallCommand: """Test all the commands relevant only to Firewall instances""" SHOW_ARP_XML = "test_data/show_arp_all.xml" SHOW_ROUTING_SUMMARY_XML = "test_data/show_routing_summary.xml" SHOW_ROUTING_ROUTE_XML = "test_data/show_routing_route.xml" SHOW_GLOBAL_COUNTERS_XML = "test_data/show_counter_global.xml" SHOW_BGP_PEERS_XML = "test_data/show_routing_protocol_bgp_peer.xml" SHOW_HA_STATE_XML = "test_data/show_ha_state_enabled.xml" SHOW_HA_PANORAMA_STATE_XML = "test_data/show_ha_state_panorama_enabled.xml" @patch("Panorama.run_op_command") def test_get_arp_table(self, patched_run_op_command, mock_topology): """Given the output XML for show arp, assert it is parsed into the dataclasses correctly.""" from Panorama import FirewallCommand patched_run_op_command.return_value = load_xml_root_from_test_file(TestFirewallCommand.SHOW_ARP_XML) result = FirewallCommand.get_arp_table(mock_topology) # Check all attributes of result data have values for result_dataclass in result.result_data: for value in result_dataclass.__dict__.values(): assert value # Check all attributes of summary data have values for result_dataclass in result.summary_data: for value in result_dataclass.__dict__.values(): assert value @patch("Panorama.run_op_command") def test_get_routing_summary(self, patched_run_op_command, mock_topology): """Given the output XML for show route summary, assert it is parsed into the dataclasses correctly.""" from Panorama import FirewallCommand patched_run_op_command.return_value = load_xml_root_from_test_file(TestFirewallCommand.SHOW_ROUTING_SUMMARY_XML) result = FirewallCommand.get_routing_summary(mock_topology) # Check all attributes of result data have values for result_dataclass in result.result_data: for value in result_dataclass.__dict__.values(): assert value # Check all attributes of summary data have values for result_dataclass in result.summary_data: for value in result_dataclass.__dict__.values(): assert value @patch("Panorama.run_op_command") def test_get_routes(self, patched_run_op_command, mock_topology): """Given the output XML for show route, assert it is parsed into the dataclasses correctly.""" from Panorama import FirewallCommand patched_run_op_command.return_value = load_xml_root_from_test_file(TestFirewallCommand.SHOW_ROUTING_ROUTE_XML) result = FirewallCommand.get_routes(mock_topology) # Check all attributes of result data have values for result_dataclass in result.result_data: for value in result_dataclass.__dict__.values(): # Attribute may be int 0 assert value is not None # Check all attributes of summary data have values for result_dataclass in result.summary_data: for value in result_dataclass.__dict__.values(): assert value @patch("Panorama.run_op_command") def test_get_counters(self, patched_run_op_command, mock_topology): """Given the output XML for show counters, assert it is parsed into the dataclasses correctly.""" from Panorama import FirewallCommand patched_run_op_command.return_value = load_xml_root_from_test_file(TestFirewallCommand.SHOW_GLOBAL_COUNTERS_XML) result = FirewallCommand.get_counter_global(mock_topology) # Check all attributes of result data have values for result_dataclass in result.result_data: for value in result_dataclass.__dict__.values(): # Attribute may be int 0 assert value is not None # Check all attributes of summary data have values for result_dataclass in result.summary_data: for value in result_dataclass.__dict__.values(): assert value @patch("Panorama.run_op_command") def test_get_bgp_peers(self, patched_run_op_command, mock_topology): """ Given the output XML for show routing protocol bgp peers, assert it is parsed into the dataclasses correctly. """ from Panorama import FirewallCommand patched_run_op_command.return_value = load_xml_root_from_test_file(TestFirewallCommand.SHOW_BGP_PEERS_XML) result = FirewallCommand.get_bgp_peers(mock_topology) # Check all attributes of result data have values for result_dataclass in result.result_data: for value in result_dataclass.__dict__.values(): # Attribute may be int 0 assert value is not None # Check all attributes of summary data have values for result_dataclass in result.summary_data: for value in result_dataclass.__dict__.values(): # Attribute may be int 0 assert value is not None @patch("Panorama.run_op_command") def test_get_ha_status_firewall(self, patched_run_op_command, mock_firewall_topology): """ Given the XML output for a HA firewall which is enabled, ensure the data class is parsed correctly """ from Panorama import FirewallCommand patched_run_op_command.return_value = load_xml_root_from_test_file(TestFirewallCommand.SHOW_HA_STATE_XML) result = FirewallCommand.get_ha_status(mock_firewall_topology) assert result.status != "HA Not enabled." assert result.active is not None assert result.hostid is not None assert result.peer is not None @patch("Panorama.run_op_command") def test_get_ha_status_panorama(self, patched_run_op_command, mock_topology): """Given the XML output for a HA firewall, ensure the dataclasses are parsed correctly""" from Panorama import FirewallCommand patched_run_op_command.return_value = load_xml_root_from_test_file(TestFirewallCommand.SHOW_HA_PANORAMA_STATE_XML) result = FirewallCommand.get_ha_status(mock_topology) # Check all attributes of result data have values for result_dataclass in result: for value in result_dataclass.__dict__.values(): # Attribute may be int 0 assert value is not None @patch("Panorama.run_op_command") def test_update_ha_state(self, patched_run_op_command, mock_topology): """ Test the HA Update command returns the correct data """ from Panorama import FirewallCommand result_dataclass = FirewallCommand.change_status(mock_topology, MOCK_FIREWALL_1_SERIAL, "operational") # Check all attributes of summary data have values for value in result_dataclass.__dict__.values(): assert value @pytest.mark.parametrize( "args, expected_request_params, request_result, expected_demisto_result", [ pytest.param( {"anti_spyware_profile_name": "fake_profile_name", "dns_signature_source": "edl_name", "action": "allow"}, { "action": "set", "type": "config", "xpath": "/config/devices/entry[@name='localhost.localdomain']" "/device-group/entry[@name='fakeDeviceGroup']" "/profiles/spyware/entry[@name='fake_profile_name']", "key": "fakeAPIKEY!", "element": "<botnet-domains>" "<lists>" '<entry name="edl_name"><packet-capture>disable</packet-capture>' "<action><allow/></action></entry>" "</lists>" "<sinkhole><ipv4-address>pan-sinkhole-default-ip</ipv4-address>" "<ipv6-address>::1</ipv6-address></sinkhole>" "</botnet-domains>", }, MockedResponse( text='<response status="success" code="20"><msg>command succeeded</msg></response>', status_code=200, reason="" ), "**success**", ), ], ) def test_panorama_apply_dns_command(mocker, args, expected_request_params, request_result, expected_demisto_result): """ Given: - command args - request result When: - Running panorama-apply-dns Then: - Assert the request url is as expected - Assert Command results contains the relevant result information """ import Panorama import requests from Panorama import apply_dns_signature_policy_command Panorama.API_KEY = "fakeAPIKEY!" Panorama.DEVICE_GROUP = "fakeDeviceGroup" Panorama.VSYS = "" # ensure the Panorama (device-group) xpath is used, not a leaked firewall VSYS request_mock = mocker.patch.object(requests, "request", return_value=request_result) command_result: CommandResults = apply_dns_signature_policy_command(args) called_request_params = request_mock.call_args.kwargs["params"] # The body part of the request assert called_request_params == expected_request_params assert command_result.readable_output == expected_demisto_result def test_panorama_apply_dns_command2(mocker): """ Given: - command args with a singel firewall When: - Running panorama-apply-dns Then: - Assert the request parameters are as expected """ import Panorama from Panorama import apply_dns_signature_policy_command Panorama.API_KEY = "fakeAPIKEY!" Panorama.DEVICE_GROUP = "fakeDeviceGroup" Panorama.VSYS = "" # ensure the Panorama (device-group) xpath is used, not a leaked firewall VSYS request_mock = mocker.patch.object(Panorama, "http_request", return_value={}) apply_dns_signature_policy_command({"anti_spyware_profile_name": "fake_profile_name"}) request_params = request_mock.call_args.kwargs["params"] # The body part of the request assert ( request_params.get("xpath") == "/config/devices/entry[@name='localhost.localdomain']/device-group/entry[@name='fakeDeviceGroup']/" "profiles/spyware/entry[@name='fake_profile_name']" ) # noqa class TestHygieneFunctions: @patch("Panorama.Template.refreshall", return_value=[]) @patch("Panorama.Vsys.refreshall", return_value=[]) @patch("Panorama.DeviceGroup.refreshall", return_value=mock_device_groups()) @patch("Panorama.TemplateStack.refreshall", return_value=[]) def test_check_log_forwarding(self, _, __, ___, ____, mock_topology): """ Test the Hygiene Configuration lookups can validate the log forwarding settings of a device """ from Panorama import HygieneLookups, LogForwardingProfile, LogForwardingProfileMatchList # First, test that a correctly configured LFP and match list don't return a failure LogForwardingProfile.refreshall = MagicMock(return_value=mock_good_log_fowarding_profile()) LogForwardingProfileMatchList.refreshall = MagicMock(return_value=mock_good_log_forwarding_profile_match_list()) result = HygieneLookups.check_log_forwarding_profiles(mock_topology) assert len(result.result_data) == 0 # Trim the "threat" log type and cause a missing log type error LogForwardingProfileMatchList.refreshall = MagicMock(return_value=[mock_good_log_forwarding_profile_match_list()[0]]) result = HygieneLookups.check_log_forwarding_profiles(mock_topology) # Note; because we mock the topology with multiple devices, # it appears that the same LFP is missing in each Container. # This is expected. assert len(result.result_data) == 3 assert result.result_data[0].description == "Log forwarding profile missing log type 'threat'." @patch("Panorama.Template.refreshall", return_value=[]) @patch("Panorama.TemplateStack.refreshall", return_value=[]) @patch("Panorama.Vsys.refreshall", return_value=[]) @patch("Panorama.DeviceGroup.refreshall", return_value=mock_device_groups()) def test_check_vulnerability_profiles(self, _, __, ___, ____, mock_topology): """ Test the Hygiene Configuration lookups can validate the vulnerability profiles """ from Panorama import BestPractices, HygieneLookups, VulnerabilityProfile # First, test that we can get the conforming threat profile, of which there should be one result = HygieneLookups.get_conforming_threat_profiles( [mock_good_vulnerability_profile(), mock_bad_vulnerability_profile()], minimum_block_severities=BestPractices.VULNERABILITY_BLOCK_SEVERITIES, minimum_alert_severities=BestPractices.VULNERABILITY_ALERT_THRESHOLD, ) assert len(result) == 1 VulnerabilityProfile.refreshall = MagicMock( return_value=[mock_good_vulnerability_profile(), mock_bad_vulnerability_profile()] ) result = HygieneLookups.check_security_profiles(topology=mock_topology, profile_type="vulnerability") # Should return no results, as at least one vulnerability profile matches. assert len(result.result_data) == 0 VulnerabilityProfile.refreshall = MagicMock(return_value=[mock_bad_vulnerability_profile()]) result = HygieneLookups.check_security_profiles(topology=mock_topology, profile_type="vulnerability") # Should return one issue, as no Vulnerability profile matches. assert len(result.result_data) == 1 # When both a good and bad profile exist and return_nonconforming_profiles is True, check we get 3 sets of details VulnerabilityProfile.refreshall = MagicMock( return_value=[mock_good_vulnerability_profile(), mock_bad_vulnerability_profile()] ) result = HygieneLookups.check_security_profiles( topology=mock_topology, profile_type="vulnerability", return_nonconforming_profiles=True ) assert len(result.result_data) == 3 @patch("Panorama.Template.refreshall", return_value=[]) @patch("Panorama.TemplateStack.refreshall", return_value=[]) @patch("Panorama.Vsys.refreshall", return_value=[]) @patch("Panorama.DeviceGroup.refreshall", return_value=mock_device_groups()) def test_check_spyware_profiles(self, _, __, ___, ____, mock_topology): """ Test the Hygiene Configuration lookups can validate the Spyware profiles given combinations of good and bad profile objects. """ from Panorama import AntiSpywareProfile, HygieneLookups AntiSpywareProfile.refreshall = MagicMock(return_value=[mock_good_spyware_profile(), mock_bad_spyware_profile()]) # Check when at least one good profile exists - should return no results result = HygieneLookups.check_security_profiles(topology=mock_topology, profile_type="spyware") assert not result.result_data # Check that when return_nonconforming_profiles is True we get back 3 sets of details result = HygieneLookups.check_security_profiles( topology=mock_topology, profile_type="spyware", return_nonconforming_profiles=True ) assert len(result.result_data) == 3 @patch("Panorama.Template.refreshall", return_value=[]) @patch("Panorama.TemplateStack.refreshall", return_value=[]) @patch("Panorama.Vsys.refreshall", return_value=[]) @patch("Panorama.DeviceGroup.refreshall", return_value=mock_device_groups()) def test_check_url_filtering_profiles(self, _, __, ___, ____, mock_topology): """ Test the Hygiene Configuration lookups can validate the URL filtering profiles given combinations of good and bad profiles. """ from Panorama import HygieneLookups, URLFilteringProfile URLFilteringProfile.refreshall = MagicMock(return_value=[mock_good_url_filtering_profile()]) # Check when a good profile exists - should return no results result = HygieneLookups.check_security_profiles(topology=mock_topology, profile_type="url") assert not result.result_data # When there's only bad, should return a result URLFilteringProfile.refreshall = MagicMock(return_value=[mock_bad_url_filtering_profile()]) # Check when a good profile exists - should return no results result = HygieneLookups.check_security_profiles(topology=mock_topology, profile_type="url") assert result.result_data # When both a good and bad profile exist and return_nonconforming_profiles is True, check we get 3 sets of details URLFilteringProfile.refreshall = MagicMock( return_value=[mock_good_url_filtering_profile(), mock_bad_url_filtering_profile()] ) result = HygieneLookups.check_security_profiles( topology=mock_topology, profile_type="url", return_nonconforming_profiles=True ) assert len(result.result_data) == 3 @patch("Panorama.Template.refreshall", return_value=mock_templates()) @patch("Panorama.TemplateStack.refreshall", return_value=[]) @patch("Panorama.Vsys.refreshall", return_value=[]) @patch("Panorama.DeviceGroup.refreshall", return_value=mock_template_stack()) def test_check_security_zones(self, _, __, ___, ____, mock_topology): """ Test the Hygiene Configuration lookups can validate security zones given a comination of good and bad zones. """ from Panorama import HygieneLookups, Zone Zone.refreshall = MagicMock(return_value=mock_good_security_zones()) result = HygieneLookups.check_security_zones(mock_topology) # Result data should be empty as there are only good zones assert not result.result_data Zone.refreshall = MagicMock(return_value=mock_bad_security_zones()) result = HygieneLookups.check_security_zones(mock_topology) # Result data should have one issue as there is a misconfigured security zone assert result.result_data assert "BP-V-7" in [x.issue_code for x in result.result_data] @patch("Panorama.Template.refreshall", return_value=[]) @patch("Panorama.TemplateStack.refreshall", return_value=[]) @patch("Panorama.Vsys.refreshall", return_value=[]) @patch("Panorama.DeviceGroup.refreshall", return_value=mock_device_groups()) def test_check_security_rules(self, _, __, ___, ____, mock_topology): """ Test the Hygiene Configuration lookups can validate security zones given a comination of good and bad zones. """ from Panorama import HygieneLookups, SecurityRule SecurityRule.refreshall = MagicMock(return_value=mock_good_security_rules()) result = HygieneLookups.check_security_rules(mock_topology) # Should not raise any issues assert not result.result_data SecurityRule.refreshall = MagicMock(return_value=mock_bad_security_rules()) result = HygieneLookups.check_security_rules(mock_topology) # Should raise issues for each issue type assert result.result_data assert "BP-V-8" in [x.issue_code for x in result.result_data] assert "BP-V-9" in [x.issue_code for x in result.result_data] assert "BP-V-10" in [x.issue_code for x in result.result_data] def test_hygiene_issue_dict_to_object(self): """ Tests the function can convert a given dictionary of an issue, returned by a hygiene lookup, back into the relevent object. This is to allow the check commands to pass their results directly into the fix commands via XSOAR. """ from Panorama import ConfigurationHygieneIssue, hygiene_issue_dict_to_object result = hygiene_issue_dict_to_object(mock_enhanced_log_forwarding_issue_dict()) assert isinstance(result[0], ConfigurationHygieneIssue) assert len(result) == 1 for value in result[0].__dict__.values(): assert value # If the issue is passed directly from the other command make sure this function works also result = hygiene_issue_dict_to_object(mock_issue_with_underscores()) assert isinstance(result[0], ConfigurationHygieneIssue) assert len(result) == 1 for value in result[0].__dict__.values(): assert value @patch("Panorama.Template.refreshall", return_value=[]) @patch("Panorama.TemplateStack.refreshall", return_value=[]) @patch("Panorama.Vsys.refreshall", return_value=[]) @patch("Panorama.DeviceGroup.refreshall", return_value=mock_device_groups()) def test_fix_log_forwarding_profile_enhanced_logging(self, _, __, ___, ____, mock_topology): """ Tests wthe fix function for enabling enhanced application logging on log forwarding profiles, given an issue referring to a bad log forwarding profile. """ from Panorama import HygieneRemediation, LogForwardingProfile, hygiene_issue_dict_to_object issues = hygiene_issue_dict_to_object(mock_enhanced_log_forwarding_issue_dict()) LogForwardingProfile.refreshall = MagicMock(return_value=mock_bad_log_fowarding_profile()) LogForwardingProfile.apply = MagicMock() result = HygieneRemediation.fix_log_forwarding_profile_enhanced_logging(mock_topology, issues) # Should be at least one result assert result for value in result[0].__dict__.values(): assert value @patch("Panorama.Template.refreshall", return_value=[]) @patch("Panorama.TemplateStack.refreshall", return_value=[]) @patch("Panorama.Vsys.refreshall", return_value=[]) @patch("Panorama.DeviceGroup.refreshall", return_value=mock_device_groups()) def test_fix_security_zone_no_log_setting(self, _, __, ___, ____, mock_topology): """ Tests wthe fix function for setting a log forwarding profile on security zones when none is currently set """ from Panorama import HygieneRemediation, Zone, hygiene_issue_dict_to_object issues = hygiene_issue_dict_to_object(mock_security_zone_no_log_setting_issue_dict()) Zone.refreshall = MagicMock(return_value=mock_bad_security_zones()) Zone.apply = MagicMock() result = HygieneRemediation.fix_security_zone_no_log_setting(mock_topology, issues, "test") # Should be at least one result, as we provided an issue. assert result for value in result[0].__dict__.values(): assert value @patch("Panorama.Template.refreshall", return_value=[]) @patch("Panorama.TemplateStack.refreshall", return_value=[]) @patch("Panorama.Vsys.refreshall", return_value=[]) @patch("Panorama.DeviceGroup.refreshall", return_value=mock_device_groups()) def test_fix_security_rule_log_settings(self, _, __, ___, ____, mock_topology): """ Tests the function that adds a log forwarding profile to a security rule when one isn't present. """ from Panorama import HygieneRemediation, SecurityRule, hygiene_issue_dict_to_object issues = hygiene_issue_dict_to_object(mock_security_rule_log_settings_issue_dict()) SecurityRule.refreshall = MagicMock(return_value=mock_bad_security_rules()) SecurityRule.apply = MagicMock() result = HygieneRemediation.fix_secuity_rule_log_settings(mock_topology, issues, "test") # Should be at least one result, as we provided an issue. assert result for value in result[0].__dict__.values(): assert value @patch("Panorama.Template.refreshall", return_value=[]) @patch("Panorama.TemplateStack.refreshall", return_value=[]) @patch("Panorama.Vsys.refreshall", return_value=[]) @patch("Panorama.DeviceGroup.refreshall", return_value=mock_device_groups()) def test_fix_security_rule_profile_settings(self, _, __, ___, ____, mock_topology): """ Tests the function that adds sets the security profile group when no SPG is currently provided """ from Panorama import HygieneRemediation, SecurityRule, hygiene_issue_dict_to_object issues = hygiene_issue_dict_to_object(mock_security_rule_log_settings_issue_dict()) SecurityRule.refreshall = MagicMock(return_value=mock_bad_security_rules()) SecurityRule.apply = MagicMock() result = HygieneRemediation.fix_security_rule_security_profile_group(mock_topology, issues, "test") # Should be at least one result, as we provided an issue. assert result for value in result[0].__dict__.values(): assert value class TestObjectFunctions: @patch("Panorama.Template.refreshall", return_value=[]) @patch("Panorama.TemplateStack.refreshall", return_value=[]) @patch("Panorama.Vsys.refreshall", return_value=[]) @patch("Panorama.DeviceGroup.refreshall", return_value=mock_device_groups()) def test_get_objects(self, _, __, ___, ____, mock_single_device_topology): """ Tests that we can get various object types and the filtering logic, by object type and name, works correctly. """ from Panorama import AddressObject, ObjectGetter # Use side effects so that objects are only returned from one container AddressObject.refreshall = MagicMock(side_effect=[mock_address_objects(), []]) # Test with no filter first result = ObjectGetter.get_object_reference(mock_single_device_topology, "AddressObject") assert "test-address-1" in [x.name for x in result] assert "test-address-2" in [x.name for x in result] # Same as above but with a filter on object name AddressObject.refreshall = MagicMock(side_effect=[mock_address_objects(), []]) result = ObjectGetter.get_object_reference(mock_single_device_topology, "AddressObject", object_name="test-address-1") assert "test-address-1" in [x.name for x in result] assert "test-address-2" not in [x.name for x in result] # Same as above but include a regex filter AddressObject.refreshall = MagicMock(side_effect=[mock_address_objects(), []]) result = ObjectGetter.get_object_reference( mock_single_device_topology, "AddressObject", object_name="test-address-\d+", use_regex="true" ) assert "test-address-1" in [x.name for x in result] assert "test-address-2" in [x.name for x in result] # Test broken regex AddressObject.refreshall = MagicMock(side_effect=[mock_address_objects(), []]) with pytest.raises(DemistoException): result = ObjectGetter.get_object_reference( mock_single_device_topology, "AddressObject", object_name="test-address-(\d+", use_regex="true" ) assert not result @pytest.mark.parametrize( "expected_request_params, target", [ pytest.param( {"type": "op", "cmd": "<show><system><info/></system></show>", "key": "fakeAPIKEY!", "target": "fake-target"}, "fake-target", ), pytest.param( { "type": "op", "cmd": "<show><system><info/></system></show>", "key": "fakeAPIKEY!", }, None, ), ], ) def test_add_target_arg(mocker, expected_request_params, target): """ Given: - a call to the function with or without the target args When: - panorama_show_device_version_command - (or any other function with the target arg) Then: - Assert that the target param was added or not to the https request """ import Panorama from Panorama import panorama_show_device_version Panorama.API_KEY = "fakeAPIKEY!" Panorama.DEVICE_GROUP = "fakeDeviceGroup" request_mock = mocker.patch.object(Panorama, "http_request", return_value={"response": {"result": {"system": "fake_data"}}}) panorama_show_device_version(target) called_request_params = request_mock.call_args.kwargs["params"] assert called_request_params == expected_request_params @pytest.mark.parametrize( "rule , expected_result", [ pytest.param({"target": {"devices": {"entry": [{"@name": "fw1"}, {"@name": "fw2"}]}}}, True), pytest.param({"target": {"devices": {"entry": {"@name": "fw1"}}}}, True), pytest.param({"target": {"devices": {"entry": {"@name": "fw2"}}}}, False), pytest.param({"target": {"devices": {"entry": [{"@name": "fw1"}]}}}, True), ], ) def test_target_filter(rule, expected_result): """ Given: - a rule (dict) and a target (str) - 'fw1' When: - filtering rules by target Then: - return True if the rule contains the target and False otherwise """ from Panorama import target_filter assert target_filter(rule, "fw1") == expected_result def test_check_latest_version_hr(mocker): """ Given: - a response from panorma of latest version When: - calling the command - pan-os-check-latest-panos-software Then: - filter the 5 latest results and present in a markdown """ import requests from Panorama import panorama_check_latest_panos_software_command with open("test_data/latest_versions.xml") as xml_file: text = xml_file.read() with open("test_data/5_latest_version.md") as md_file: markdown_assert = md_file.read() mr = MockedResponse(text=text, status_code=200, reason="") mocker.patch.object(requests, "request", return_value=mr) command_res: CommandResults = panorama_check_latest_panos_software_command() assert markdown_assert == command_res.readable_output def test_pan_os_get_running_config(mocker): """ Given - A target serial number When - Returning the running config Then - File returned should be called 'running_config' The contents should be XML and not JSON """ from Panorama import pan_os_get_running_config return_mock = """ <response status='error' code='13'><msg><line>SOME_SERIAL_NUMBER not connected</line></msg></response> """ mocker.patch("Panorama.http_request", return_value=return_mock) created_file = pan_os_get_running_config({"target": "SOME_SERIAL_NUMBER", "filename": "running_config"}) assert created_file["File"] == "running_config" def test_pan_os_get_merged_config(mocker): """ Given - A target serial number When - Returning the merged config Then - File returned should be called 'merged_config' The contents should be XML and not JSON """ from Panorama import pan_os_get_merged_config return_mock = """ <response status='error' code='13'><msg><line>SOME_SERIAL_NUMBER not connected</line></msg></response> """ mocker.patch("Panorama.http_request", return_value=return_mock) created_file = pan_os_get_merged_config({"target": "SOME_SERIAL_NUMBER"}) assert created_file["File"] == "merged_config" class TestPanOSListTemplatesCommand: def test_pan_os_list_templates_main_flow(self, mocker): """ Given: - Panorama instance configuration. When: - running the pan-os-list-templates through the main flow. Then: - make sure the context output is parsed correctly. - make sure the xpath and the request is correct. - make sure "Variable=None' is parsed successfully. """ from Panorama import main mock_request = mocker.patch( "Panorama.http_request", return_value=load_json("test_data/list_templates_including_uncommitted.json") ) mocker.patch.object(demisto, "params", return_value=integration_panorama_params) mocker.patch.object(demisto, "args", return_value={}) mocker.patch.object(demisto, "command", return_value="pan-os-list-templates") result = mocker.patch("demistomock.results") main() assert list(result.call_args.args[0]["EntryContext"].values())[0] == [ { "Name": "test-1", "Description": None, "Variable": [ {"Name": None, "Type": None, "Value": None, "Description": None}, {"Name": None, "Type": None, "Value": None, "Description": None}, ], }, { "Name": "test-2", "Description": "just a test description", "Variable": [ { "Name": "$variable-1", "Type": "ip-netmask", "Value": "1.1.1.1", "Description": "description for $variable-1", } ], }, { "Name": "test-3", "Description": None, "Variable": [], }, ] assert mock_request.call_args.kwargs["params"] == { "type": "config", "action": "get", "key": "thisisabogusAPIKEY!", "xpath": "/config/devices/entry[@name='localhost.localdomain']/template", } def test_pan_os_list_templates_main_flow_firewall_instance(self): """ Given: - Firewall instance configuration. When: - running the pan_os_list_templates_command function. Then: - make sure an exception is raised because hte pan-os-list-templates can run only on Panorama instances. """ import Panorama from Panorama import pan_os_list_templates_command Panorama.VSYS = "vsys" # VSYS are only firewall instances Panorama.DEVICE_GROUP = "" # device-groups are only panorama instances. with pytest.raises(DemistoException): pan_os_list_templates_command({}) class TestPanOSListNatRulesCommand: @pytest.mark.parametrize( "args, params, expected_url_params", [ pytest.param( {"pre_post": "pre-rulebase", "show_uncommitted": "false"}, integration_panorama_params, { "type": "config", "action": "show", "key": "thisisabogusAPIKEY!", "xpath": "/config/devices/entry[@name='localhost.localdomain']" "/device-group/entry[@name='Lab-Devices']/pre-rulebase/nat", }, ), pytest.param( {"show_uncommitted": "false"}, integration_firewall_params, { "action": "show", "key": "thisisabogusAPIKEY!", "type": "config", "xpath": "/config/devices/entry[@name='localhost.localdomain']/vsys/entry[@name='vsys1']/rulebase/nat", }, ), pytest.param( {"pre_post": "pre-rulebase", "show_uncommitted": "true", "name": "test"}, integration_panorama_params, { "action": "get", "key": "thisisabogusAPIKEY!", "type": "config", "xpath": "/config/devices/entry[@name='localhost.localdomain']/device-group/entry" "[@name='Lab-Devices']/pre-rulebase/nat/rules/entry[@name='test']", }, ), pytest.param( {"show_uncommitted": "true", "name": "test"}, integration_firewall_params, { "action": "get", "key": "thisisabogusAPIKEY!", "type": "config", "xpath": "/config/devices/entry[@name='localhost.localdomain']/vsys/entry[@name='vsys1']" "/rulebase/nat/rules/entry[@name='test']", }, ), ], ) def test_pan_os_list_rules_command_main_flow(self, mocker, args, params, expected_url_params): """ Given: - Panorama instance configuration. - Firewall instance configuration. - Panorama instance configuration to get a specific nat-rule. - Firewall instance configuration to get a specific nat-rule. When: - running the pan-os-list-nat-rules through the main flow. Then: - make sure the context output is parsed correctly. - make sure the xpath and the request is correct for both panorama/firewall. """ from Panorama import main expected_context = [ { "Name": "test", "Tags": "test tag", "SourceZone": "1.1.1.1", "DestinationZone": "1.1.1.1", "SourceAddress": "any", "DestinationAddress": "any", "DestinationInterface": None, "Service": "any", "Description": None, "SourceTranslation": None, "DynamicDestinationTranslation": None, "DestinationTranslation": None, "Disabled": "yes", }, { "Name": "test-2", "Tags": None, "SourceZone": "2.2.2.2", "DestinationZone": "2.2.2.2", "SourceAddress": "any", "DestinationAddress": "any", "DestinationInterface": None, "Service": "any", "Description": None, "SourceTranslation": None, "DynamicDestinationTranslation": None, "DestinationTranslation": None, "Disabled": "no", }, ] mock_request = mocker.patch("Panorama.http_request", return_value=load_json("test_data/list-nat-rules-response.json")) mocker.patch.object(demisto, "params", return_value=params) mocker.patch.object(demisto, "args", return_value=args) mocker.patch.object(demisto, "command", return_value="pan-os-list-nat-rules") result = mocker.patch("demistomock.results") main() assert list(result.call_args.args[0]["EntryContext"].values())[0] == expected_context assert mock_request.call_args.kwargs["params"] == expected_url_params class TestCreatePanOSNatRuleCommand: CREATE_NAT_RULE = {"response": {"@status": "success", "@code": "20", "msg": "command succeeded"}} @pytest.mark.parametrize( "args, params, expected_url_params", [ pytest.param( { "rulename": "test", "description": "test", "pre_post": "pre-rulebase", "source_translation_type": "static-ip", "source_translated_address": "1.1.1.1", "source_translated_address_type": "translated-address", "destination_translation_type": "none", }, integration_panorama_params, { "xpath": "/config/devices/entry[@name='localhost.localdomain']/device-group" "/entry[@name='Lab-Devices']/pre-rulebase/nat/rules/entry[@name='test']", "element": "<source-translation><static-ip><translated-address>1.1.1.1<" "/translated-address></static-ip></source-translation><description>test</description>", "action": "set", "type": "config", "key": "thisisabogusAPIKEY!", }, ), pytest.param( { "rulename": "test", "description": "test", "source_translation_type": "static-ip", "source_translated_address": "1.1.1.1", "source_translated_address_type": "translated-address", "destination_translation_type": "none", }, integration_firewall_params, { "xpath": "/config/devices/entry[@name='localhost.localdomain']/vsys/" "entry[@name='vsys1']/rulebase/nat/rules/entry[@name='test']", "element": "<source-translation><static-ip><translated-address>1.1.1.1<" "/translated-address></static-ip></source-translation><description>test</description>", "action": "set", "type": "config", "key": "thisisabogusAPIKEY!", }, ), pytest.param( { "rulename": "test", "description": "test", "destination_zone": "1.1.1.1", "source_zone": "2.2.2.2", "pre_post": "pre-rulebase", "source_address": "1.1.1.1,2.2.2.2", "source_translation_type": "dynamic-ip", "source_translated_address_type": "translated-address", "source_translated_address": "1.1.1.1,2.2.2.2", "destination_translation_type": "none", "audit_comment": "test comment", }, integration_panorama_params, { "action": "set", "element": "<source-translation><dynamic-ip><translated-address><member>1.1.1.1</member>" "<member>2.2.2.2</member></translated-address></dynamic-ip></source-translation><to>" "<member>1.1.1.1</member></to><from><member>2.2.2.2</member></from><source><member>" "1.1.1.1</member><member>2.2.2.2</member></source><description>test</description>", "key": "thisisabogusAPIKEY!", "type": "config", "xpath": "/config/devices/entry[@name='localhost.localdomain']/device-group/entry" "[@name='Lab-Devices']/pre-rulebase/nat/rules/entry[@name='test']", "audit-comment": "test comment", }, ), pytest.param( { "rulename": "test", "description": "test", "destination_zone": "1.1.1.1", "source_zone": "2.2.2.2", "source_address": "1.1.1.1,2.2.2.2", "source_translation_type": "dynamic-ip", "source_translated_address_type": "translated-address", "source_translated_address": "1.1.1.1,2.2.2.2", "destination_translation_type": "none", "audit_comment": "test comment", }, integration_firewall_params, { "action": "set", "element": "<source-translation><dynamic-ip><translated-address><member>1.1.1.1</member>" "<member>2.2.2.2</member></translated-address></dynamic-ip></source-translation><to>" "<member>1.1.1.1</member></to><from><member>2.2.2.2</member></from><source>" "<member>1.1.1.1</member><member>2.2.2.2</" "member></source><description>test</description>", "key": "thisisabogusAPIKEY!", "type": "config", "xpath": "/config/devices/entry[@name='localhost.localdomain']/vsys/" "entry[@name='vsys1']/rulebase/nat/rules/entry[@name='test']", "audit-comment": "test comment", }, ), ], ) def test_pan_os_create_nat_rule_command_main_flow(self, mocker, args, params, expected_url_params): """ Given: - Panorama instance configuration with source_translation_type, source_translated_address and source_translated_address_type - Firewall instance configuration with source_translation_type, source_translated_address and source_translated_address_type - Panorama instance configuration with basic parameter configurations along with dynamic-ip - firewall instance configuration with basic parameter configurations along with dynamic-ip When: - running the pan-os-create-nat-rule through the main flow. Then: - make sure the xpath/element and the request is correct for both panorama/firewall. """ from Panorama import main mock_request = mocker.patch( "Panorama.http_request", return_value={"response": {"@status": "success", "@code": "20", "msg": "command succeeded"}} ) mocker.patch.object(demisto, "params", return_value=params) mocker.patch.object(demisto, "args", return_value=args) mocker.patch.object(demisto, "command", return_value="pan-os-create-nat-rule") main() assert mock_request.call_args.kwargs["params"] == expected_url_params @pytest.mark.parametrize( "args, params, expected_url_params", [ pytest.param( {"rulename": "test", "pre_post": "pre-rulebase"}, integration_panorama_params, { "action": "delete", "key": "thisisabogusAPIKEY!", "type": "config", "xpath": "/config/devices/entry[@name='localhost.localdomain']/device-group/entry" "[@name='Lab-Devices']/pre-rulebase/nat/rules/entry[@name='test']", }, ), pytest.param( {"rulename": "test"}, integration_firewall_params, { "action": "delete", "key": "thisisabogusAPIKEY!", "type": "config", "xpath": "/config/devices/entry[@name='localhost.localdomain']/vsys/entry" "[@name='vsys1']/rulebase/nat/rules/entry[@name='test']", }, ), ], ) def test_pan_os_delete_nat_rule_command_main_flow(mocker, args, params, expected_url_params): """ Given: - Panorama instance configuration with a specific rulename. - Firewall instance configuration with a specific rulename. When: - running the pan-os-delete-nat-rule through the main flow. Then: - make sure the xpath/element and the request is correct for both panorama/firewall. """ from Panorama import main mock_request = mocker.patch( "Panorama.http_request", return_value={"response": {"@status": "success", "@code": "20", "msg": "command succeeded"}} ) mocker.patch.object(demisto, "params", return_value=params) mocker.patch.object(demisto, "args", return_value=args) mocker.patch.object(demisto, "command", return_value="pan-os-delete-nat-rule") main() assert mock_request.call_args.kwargs["params"] == expected_url_params class TestPanOSEditNatRule: @pytest.mark.parametrize( "args, params, expected_url_params", [ pytest.param( { "rulename": "test", "pre_post": "pre-rulebase", "element_to_change": "source_translation_dynamic_ip", "behavior": "replace", "element_value": "1.1.1.1,2.2.2.2", }, integration_panorama_params, { "action": "edit", "element": "<translated-address><member>1.1.1.1</member><member>2.2.2.2</member></translated-address>", "key": "thisisabogusAPIKEY!", "type": "config", "xpath": "/config/devices/entry[@name='localhost.localdomain']/device-group/entry[" "@name='Lab-Devices']/pre-rulebase/nat/rules/entry[@name='test']/source-translation" "/dynamic-ip/translated-address", }, ), pytest.param( {"rulename": "test", "element_to_change": "source_zone", "behavior": "replace", "element_value": "1.1.1.1"}, integration_firewall_params, { "action": "edit", "element": "<from><member>1.1.1.1</member></from>", "key": "thisisabogusAPIKEY!", "type": "config", "xpath": "/config/devices/entry[@name='localhost.localdomain']/vsys/entry[@name='vsys1']" "/rulebase/nat/rules/entry[@name='test']/from", }, ), pytest.param( { "rulename": "test", "pre_post": "pre-rulebase", "element_to_change": "destination_translation_dynamic_distribution_method", "behavior": "replace", "element_value": "Round Robin", }, integration_panorama_params, { "action": "edit", "element": "<distribution>Round Robin</distribution>", "key": "thisisabogusAPIKEY!", "type": "config", "xpath": "/config/devices/entry[@name='localhost.localdomain']/device-group/entry" "[@name='Lab-Devices']/pre-rulebase/nat/rules/entry[@name='test']/" "dynamic-destination-translation/distribution", }, ), pytest.param( { "rulename": "test", "element_to_change": "source_translation_static_ip", "behavior": "replace", "element_value": "1.1.1.1", }, integration_firewall_params, { "action": "edit", "element": "<translated-address>1.1.1.1</translated-address>", "key": "thisisabogusAPIKEY!", "type": "config", "xpath": "/config/devices/entry[@name='localhost.localdomain']/vsys/entry[@name='vsys1']/rulebase/" "nat/rules/entry[@name='test']/source-translation/static-ip/translated-address", }, ), ], ) def test_pan_os_nat_rule_replace_action_main_flow(self, mocker, args, params, expected_url_params): """ Given - Panorama instance when replacing source_translation_dynamic_ip to a new value - Firewall instance when replacing source_zone to a new value. - Panorama instance when replacing destination_translation_dynamic_distribution_method to a new value. - Firewall instance when replacing source_translation_static_ip to a new value. When - running the pan-os-edit-nat-rule through the main flow. Then - make sure the xpath/element and the request is correct for both panorama/firewall. """ from Panorama import main mock_request = mocker.patch( "Panorama.http_request", return_value={"response": {"@status": "success", "@code": "20", "msg": "command succeeded"}} ) mocker.patch.object(demisto, "params", return_value=params) mocker.patch.object(demisto, "args", return_value=args) mocker.patch.object(demisto, "command", return_value="pan-os-edit-nat-rule") main() assert mock_request.call_args.kwargs["params"] == expected_url_params @pytest.mark.parametrize("nat_rule_object", ["destination_translation_ip", "destination_interface", "nat_type"]) def test_pan_os_add_or_remove_un_listable_objects(self, nat_rule_object): """ Given - un-listable nat-rules object. When - running the pan-os-edit-nat-rule command. Then - make sure an exception is raised. """ from Panorama import pan_os_edit_nat_rule_command with pytest.raises(ValueError): pan_os_edit_nat_rule_command({"element_to_change": nat_rule_object, "rulename": "test", "action": "add"}) @pytest.mark.parametrize( "args, params, expected_url_params", [ pytest.param( { "rulename": "test", "pre_post": "pre-rulebase", "element_to_change": "source_zone", "behavior": "add", "element_value": "2.2.2.2,3.3.3.3", }, integration_panorama_params, { "action": "edit", "element": "<from><member>2.2.2.2</member><member>3.3.3.3</member><member>1.1.1.1</member></from>", "key": "thisisabogusAPIKEY!", "type": "config", "xpath": "/config/devices/entry[@name='localhost.localdomain']/device-group/entry" "[@name='Lab-Devices']/pre-rulebase/nat/rules/entry[@name='test']/from", }, ), pytest.param( {"rulename": "test", "element_to_change": "source_zone", "behavior": "add", "element_value": "2.2.2.2,3.3.3.3"}, integration_firewall_params, { "action": "edit", "element": "<from><member>2.2.2.2/member><member>1.1.1.1/member></from>", "key": "thisisabogusAPIKEY!", "type": "config", "xpath": "/config/devices/entry[@name='localhost.localdomain']/vsys/entry[@name='vsys1']" "/rulebase/nat/rules/entry[@name='test']/from", }, ), ], ) def test_pan_os_nat_rule_add_action_main_flow(self, mocker, args, params, expected_url_params): """ Given - Panorama instance when adding a new value to source_zone. - Firewall instance when adding a new value to source_zone. When - running the pan-os-edit-nat-rule through the main flow. Then - make sure the xpath/element and the request is correct for both panorama/firewall. """ from Panorama import main mock_request = mocker.patch( "Panorama.http_request", return_value={ "response": { "@status": "success", "@code": "19", "result": {"@total-count": "1", "@count": "1", "from": {"member": "1.1.1.1"}}, } }, ) mocker.patch.object(demisto, "params", return_value=params) mocker.patch.object(demisto, "args", return_value=args) mocker.patch.object(demisto, "command", return_value="pan-os-edit-nat-rule") main() assert mock_request.call_args.kwargs["params"]["xpath"] == expected_url_params["xpath"] assert "1.1.1.1" in mock_request.call_args.kwargs["params"]["element"] assert "2.2.2.2" in mock_request.call_args.kwargs["params"]["element"] assert "3.3.3.3" in mock_request.call_args.kwargs["params"]["element"] @pytest.mark.parametrize( "args, params, expected_url_params", [ pytest.param( { "rulename": "test", "pre_post": "pre-rulebase", "element_to_change": "source_zone", "behavior": "remove", "element_value": "2.2.2.2,3.3.3.3", }, integration_panorama_params, { "action": "edit", "element": "<from><member>1.1.1.1</member></from>", "key": "thisisabogusAPIKEY!", "type": "config", "xpath": "/config/devices/entry[@name='localhost.localdomain']/device-group/entry" "[@name='Lab-Devices']/pre-rulebase/nat/rules/entry[@name='test']/from", }, ), pytest.param( { "rulename": "test", "element_to_change": "source_zone", "behavior": "remove", "element_value": "2.2.2.2,3.3.3.3", }, integration_firewall_params, { "action": "edit", "element": "<from><member>1.1.1.1</member></from>", "key": "thisisabogusAPIKEY!", "type": "config", "xpath": "/config/devices/entry[@name='localhost.localdomain']/vsys/entry[@name='vsys1']/" "rulebase/nat/rules/entry[@name='test']/from", }, ), ], ) def test_pan_os_nat_rule_remove_action_main_flow(self, mocker, args, params, expected_url_params): """ Given - Panorama instance when removing a value from source_zone. - Firewall instance when removing a value from source_zone. When - running the pan-os-edit-nat-rule through the main flow. Then - make sure the xpath/element and the request is correct for both panorama/firewall. """ from Panorama import main mock_request = mocker.patch( "Panorama.http_request", return_value={ "response": { "@status": "success", "@code": "19", "result": {"@total-count": "1", "@count": "1", "from": {"member": ["1.1.1.1", "2.2.2.2", "3.3.3.3"]}}, } }, ) mocker.patch.object(demisto, "params", return_value=params) mocker.patch.object(demisto, "args", return_value=args) mocker.patch.object(demisto, "command", return_value="pan-os-edit-nat-rule") main() assert mock_request.call_args.kwargs["params"]["xpath"] == expected_url_params["xpath"] assert mock_request.call_args.kwargs["params"] == expected_url_params @staticmethod def test_pan_os_edit_nat_rule_command_audit_comment_main_flow(mocker): """ Given - panorama integrations parameters. - pan-os-edit-nat-rule command arguments including device_group. - arguments to edit audit comment of a rule When - running the pan-os-edit-nat-rule command through the main flow Then - make sure the context output is returned as expected. - make sure the device group gets overriden by the command arguments. """ from Panorama import main mocker.patch.object(demisto, "params", return_value=integration_panorama_params) mocker.patch.object( demisto, "args", return_value={ "rulename": "test", "element_to_change": "audit-comment", "element_value": "some string", "pre_post": "pre-rulebase", "device-group": "new device group", }, ) mocker.patch.object(demisto, "command", return_value="pan-os-edit-nat-rule") request_mock = mocker.patch( "Panorama.http_request", return_value=TestPanoramaEditRuleCommand.EDIT_AUDIT_COMMENT_SUCCESS_RESPONSE ) res = mocker.patch("demistomock.results") main() assert request_mock.call_args.kwargs["params"] == { "type": "op", "cmd": "<set><audit-comment><xpath>/config/devices/entry[@name='localhost.localdomain']/device-group" "/entry[@name='new device group']/pre-rulebase/nat/rules/entry[@name='test']" "</xpath><comment>some string</comment></audit-comment></set>", "key": "thisisabogusAPIKEY!", } assert res.call_args.args[0]["Contents"] == TestPanoramaEditRuleCommand.EDIT_AUDIT_COMMENT_SUCCESS_RESPONSE class TestPanOSListVirtualRouters: @pytest.mark.parametrize( "args, params, expected_url_params, mocked_response_path", [ pytest.param( {"pre_post": "pre-rulebase", "show_uncommitted": "false", "virtual_router": "test"}, integration_panorama_params, { "type": "config", "action": "show", "key": "thisisabogusAPIKEY!", "xpath": "/config/devices/entry[@name='localhost.localdomain']/template/entry[@name='test']/" "config/devices/entry[@name='localhost.localdomain']/network/virtual-router/entry" "[@name='test']", }, "test_data/list-virtual-routers-response.json", ), pytest.param( {"show_uncommitted": "false", "virtual_router": "test"}, integration_firewall_params, { "type": "config", "action": "show", "key": "thisisabogusAPIKEY!", "xpath": "/config/devices/entry[@name='localhost.localdomain']/network/virtual-router/entry[@name='test']", }, "test_data/list-virtual-routers-response.json", ), pytest.param( {"pre_post": "pre-rulebase", "show_uncommitted": "true", "virtual_router": "test"}, integration_panorama_params, { "type": "config", "action": "get", "key": "thisisabogusAPIKEY!", "xpath": "/config/devices/entry[@name='localhost.localdomain']/template/entry[@name='test']" "/config/devices/entry[@name='localhost.localdomain']/network/virtual-router" "/entry[@name='test']", }, "test_data/list-virtual-routers-response-un-commited-router.json", ), pytest.param( {"show_uncommitted": "true", "virtual_router": "test"}, integration_firewall_params, { "type": "config", "action": "get", "key": "thisisabogusAPIKEY!", "xpath": "/config/devices/entry[@name='localhost.localdomain']/network/virtual-router/entry[@name='test']", }, "test_data/list-virtual-routers-response-un-commited-router.json", ), ], ) def test_pan_os_list_virtual_routers_command_main_flow(self, mocker, args, params, expected_url_params, mocked_response_path): """ Given: - Panorama instance configuration and name to retrieve a specific virtual router that was committed. - Firewall instance configuration and name to retrieve a specific virtual router that was committed. - Panorama instance configuration and name to retrieve a specific virtual router that was not committed. - Firewall instance configuration and name to retrieve a specific virtual router that was not committed. When: - running the pan-os-list-virtual-routers through the main flow. Then: - make sure the context output is parsed correctly for both un-committed and committed cases. - make sure the xpath and the request is correct for both panorama/firewall. """ from Panorama import main mock_request = mocker.patch("Panorama.http_request", return_value=load_json(mocked_response_path)) mocker.patch.object(demisto, "params", return_value=params) mocker.patch.object(demisto, "args", return_value=args) mocker.patch.object(demisto, "command", return_value="pan-os-list-virtual-routers") result = mocker.patch("demistomock.results") main() assert list(result.call_args.args[0]["EntryContext"].values())[0] == [ { "BGP": {"enable": "no", "routing-options": {"graceful-restart": {"enable": "yes"}}}, "ECMP": {"algorithm": {"ip-modulo": "None"}}, "Interface": None, "Multicast": None, "Name": "test", "OSPF": {"enable": "no"}, "OSPFv3": {"enable": "no"}, "RIP": {"enable": "no"}, "RedistributionProfile": None, "StaticRoute": None, } ] assert mock_request.call_args.kwargs["params"] == expected_url_params class TestPanOSListRedistributionProfiles: @pytest.mark.parametrize( "args, params, expected_url_params", [ pytest.param( {"virtual_router": "virtual-router-1", "template": "test-override"}, integration_panorama_params, { "type": "config", "action": "get", "key": "thisisabogusAPIKEY!", "xpath": "/config/devices/entry[@name='localhost.localdomain']/template/entry[" "@name='test-override']/config/devices/entry[@name='localhost.localdomain']/network" "/virtual-router/entry[@name='virtual-router-1']/protocol/redist-profile", }, ), pytest.param( {"virtual_router": "virtual-router-1"}, integration_firewall_params, { "action": "get", "key": "thisisabogusAPIKEY!", "type": "config", "xpath": "/config/devices/entry[@name='localhost.localdomain']/network/virtual-router/" "entry[@name='virtual-router-1']/protocol/redist-profile", }, ), ], ) def test_pan_os_list_redistribution_profiles_main_flow(self, mocker, args, params, expected_url_params): """ Given: - Panorama instance configuration and name to retrieve redistribution profiles that were not committed. - Firewall instance configuration and name to retrieve redistribution profiles that were not committed. When: - running the pan-os-list-redistribution-profiles through the main flow. Then: - make sure the context output is parsed correctly. - make sure the xpath and the request is correct for both panorama/firewall and that template gets overriden when using panorama instance. """ from Panorama import main mock_request = mocker.patch( "Panorama.http_request", return_value=load_json("test_data/list-redistribution-profiles-un-committed-response.json") ) mocker.patch.object(demisto, "params", return_value=params) mocker.patch.object(demisto, "args", return_value=args) mocker.patch.object(demisto, "command", return_value="pan-os-list-redistribution-profiles") result = mocker.patch("demistomock.results") main() assert list(result.call_args.args[0]["EntryContext"].values())[0] == [ { "Name": "test1", "Priority": "1", "Action": "redist", "FilterInterface": "loopback", "FilterType": ["bgp", "connect", "ospf", "rip", "static"], "FilterDestination": "1.1.1.1", "FilterNextHop": "2.2.2.2", "BGP": {"Community": ["local-as", "no-export"], "ExtendedCommunity": "0x4164ACFCE33404EA"}, "OSPF": {"PathType": ["ext-1", "ext-2", "inter-area", "intra-area"], "Area": ["1.1.1.1", "2.2.2.2"], "Tag": "1"}, }, { "Name": "test-2", "Priority": "123", "Action": "no-redist", "FilterInterface": None, "FilterType": None, "FilterDestination": None, "FilterNextHop": None, "BGP": None, "OSPF": None, }, ] assert mock_request.call_args.kwargs["params"] == expected_url_params class TestPanOSCreateRedistributionProfile: @pytest.mark.parametrize( "args, params, expected_url_params", [ pytest.param( { "virtual_router": "virtual-router", "name": "redistribution-profile", "priority": "12", "action": "redist", "filter_bgp_extended_community": "0x4164ACFCE33404EA", "filter_source_type": "bgp,ospf", "filter_ospf_area": "1.1.1.1,2.2.2.2", }, integration_panorama_params, { "xpath": "/config/devices/entry[@name='localhost.localdomain']/template/entry[@name='test']/" "config/devices/entry[@name='localhost.localdomain']/network/virtual-router/entry[" "@name='virtual-router']/protocol/redist-profile/entry[@name='redistribution-profile']", "element": "<priority>12</priority><action><redist/></action><filter><ospf><area><member>1.1.1.1<" "/member><member>2.2.2.2</member></area></ospf><bgp><extended-community>" "<member>0x4164ACFCE33404EA</member></extended-community></bgp><type><member>bgp" "</member><member>ospf</member></type></filter>", "action": "set", "type": "config", "key": "thisisabogusAPIKEY!", }, ), pytest.param( { "virtual_router": "virtual-router", "name": "redistribution-profile", "interface": "loopback", "filter_ospf_tag": "1.1.1.1,2.2.2.2", "filter_source_type": "ospf,bgp", "filter_ospf_path_type": "ext-1,ext-2", }, integration_firewall_params, { "xpath": "/config/devices/entry[@name='localhost.localdomain']/network/virtual-router/entry" "[@name='virtual-router']/protocol/redist-profile/entry[@name='redistribution-profile']", "element": "<filter><ospf><path-type><member>ext-1</member><member>ext-2</member></path-type><tag>" "<member>1.1.1.1</member><member>2.2.2.2</member></tag></ospf><type><member>" "ospf</member><member>bgp</member></type><interface><member>loopback</member>" "</interface></filter>", "action": "set", "type": "config", "key": "thisisabogusAPIKEY!", }, ), ], ) def test_pan_os_create_redistribution_profile_command_main_flow(self, mocker, args, params, expected_url_params): """ Given: - Panorama instance configuration and arguments to create a redistribution-profile. - Firewall instance configuration and arguments to create a redistribution-profile. When: - running the pan-os-create-redistribution-profile through the main flow. Then: - make sure the xpath and the request is correct for both panorama/firewall. """ from Panorama import main mock_request = mocker.patch( "Panorama.http_request", return_value={"response": {"@status": "success", "@code": "20", "msg": "command succeeded"}} ) mocker.patch.object(demisto, "params", return_value=params) mocker.patch.object(demisto, "args", return_value=args) mocker.patch.object(demisto, "command", return_value="pan-os-create-redistribution-profile") main() assert mock_request.call_args.kwargs["params"] == expected_url_params class TestPanOSEditRedistributionProfile: @pytest.mark.parametrize( "args, params, expected_url_params", [ pytest.param( { "virtual_router": "virtual-router", "name": "redistribution-profile", "element_to_change": "priority", "element_value": "50", "behavior": "replace", }, integration_panorama_params, { "xpath": "/config/devices/entry[@name='localhost.localdomain']/template/entry[@name='test']/" "config/devices/entry[@name='localhost.localdomain']/network/virtual-router/entry" "[@name='virtual-router']/protocol/redist-profile/entry[@name='redistribution-profile']" "/priority", "element": "<priority>50</priority>", "action": "edit", "type": "config", "key": "thisisabogusAPIKEY!", }, ), pytest.param( { "virtual_router": "virtual-router", "name": "redistribution-profile", "element_to_change": "filter_type", "element_value": "bgp,ospf", "behavior": "replace", }, integration_panorama_params, { "xpath": "/config/devices/entry[@name='localhost.localdomain']/template/entry[@name='test']/config" "/devices/entry[@name='localhost.localdomain']/network/virtual-router/entry" "[@name='virtual-router']/protocol/redist-profile/entry[@name='redistribution-profile']" "/filter/type", "element": "<type><member>bgp</member><member>ospf</member></type>", "action": "edit", "type": "config", "key": "thisisabogusAPIKEY!", }, ), pytest.param( { "virtual_router": "virtual-router", "name": "redistribution-profile", "element_to_change": "filter_ospf_area", "element_value": "1.1.1.1,2.2.2.2,3.3.3.3", "behavior": "replace", }, integration_panorama_params, { "xpath": "/config/devices/entry[@name='localhost.localdomain']/template/entry[@name='test']/config" "/devices/entry[@name='localhost.localdomain']/network/virtual-router/entry" "[@name='virtual-router']/protocol/redist-profile/entry[@name='redistribution-profile']" "/filter/ospf/area", "element": "<area><member>1.1.1.1</member><member>2.2.2.2</member><member>3.3.3.3</member></area>", "action": "edit", "type": "config", "key": "thisisabogusAPIKEY!", }, ), pytest.param( { "virtual_router": "virtual-router", "name": "redistribution-profile", "element_to_change": "filter_bgp_extended_community", "element_value": "0x4164ACFCE33404EA", "behavior": "replace", }, integration_firewall_params, { "xpath": "/config/devices/entry[@name='localhost.localdomain']/network/virtual-router/entry" "[@name='virtual-router']/protocol/redist-profile/entry[@name='redistribution-profile']" "/filter/bgp/community", "element": "<extended-community><member>0x4164ACFCE33404EA</member></extended-community>", "action": "edit", "type": "config", "key": "thisisabogusAPIKEY!", }, ), pytest.param( { "virtual_router": "virtual-router", "name": "redistribution-profile", "element_to_change": "filter_destination", "element_value": "1.1.1.1,2.2.2.2", "behavior": "replace", }, integration_firewall_params, { "xpath": "/config/devices/entry[@name='localhost.localdomain']/network/virtual-router/entry" "[@name='virtual-router']/protocol/redist-profile/entry[@name='redistribution-profile']" "/filter/destination", "element": "<destination><member>1.1.1.1</member><member>2.2.2.2</member></destination>", "action": "edit", "type": "config", "key": "thisisabogusAPIKEY!", }, ), ], ) def test_pan_os_edit_redistribution_profile_command_replace_action_main_flow(self, mocker, args, params, expected_url_params): """ Tests several cases where behavior == 'replace' Given: - Panorama instance configuration and priority object of a redistribution-profile to edit. - Panorama instance configuration and filter_type object of a redistribution-profile to edit. - Panorama instance configuration and filter_ospf_area object of a redistribution-profile to edit. - Firewall instance configuration and filter_bgp_extended_community object of a redistribution-profile to edit. - Firewall instance configuration and filter_destination object of a redistribution-profile to edit. When: - running the pan-os-edit-redistribution-profile through the main flow. Then: - make sure the xpath and the request is correct for both panorama/firewall. """ from Panorama import main mock_request = mocker.patch( "Panorama.http_request", return_value={"response": {"@status": "success", "@code": "20", "msg": "command succeeded"}} ) mocker.patch.object(demisto, "params", return_value=params) mocker.patch.object(demisto, "args", return_value=args) mocker.patch.object(demisto, "command", return_value="pan-os-edit-redistribution-profile") main() assert mock_request.call_args.kwargs["params"] == expected_url_params @pytest.mark.parametrize( "args, params, expected_url_params", [ pytest.param( { "virtual_router": "virtual-router", "name": "redistribution-profile", "element_to_change": "filter_nexthop", "element_value": "2.2.2.2,3.3.3.3", "behavior": "add", }, integration_panorama_params, { "xpath": "/config/devices/entry[@name='localhost.localdomain']/template/entry[@name='test']" "/config/devices/entry[@name='localhost.localdomain']/network/virtual-router" "/entry[@name='virtual-router']/protocol/redist-profile/entry" "[@name='redistribution-profile']/filter/nexthop", "element": "<nexthop><member>1.1.1.1</member><member>3.3.3.3</member><member>2.2.2.2</member></nexthop>", "action": "edit", "type": "config", "key": "thisisabogusAPIKEY!", }, ), pytest.param( { "virtual_router": "virtual-router", "name": "redistribution-profile", "element_to_change": "filter_nexthop", "element_value": "2.2.2.2,3.3.3.3", "behavior": "add", }, integration_firewall_params, { "xpath": "/config/devices/entry[@name='localhost.localdomain']/network/virtual-router/entry" "[@name='virtual-router']/protocol/redist-profile/entry[@name='redistribution-profile']" "/filter/nexthop", "element": "<nexthop><member>1.1.1.1</member><member>2.2.2.2</member><member>3.3.3.3</member></nexthop>", "action": "edit", "type": "config", "key": "thisisabogusAPIKEY!", }, ), ], ) def test_pan_os_edit_redistribution_profile_command_add_action_main_flow(self, mocker, args, params, expected_url_params): """ Tests cases where behavior == 'add' Given: - Panorama instance configuration and nexthop object of a redistribution-profile to add. - Firewall instance configuration and nexthop object of a redistribution-profile to add. When: - running the pan-os-edit-redistribution-profile through the main flow. Then: - make sure the xpath and the request is correct for both panorama/firewall. """ from Panorama import main mock_request = mocker.patch( "Panorama.http_request", return_value={ "response": { "@status": "success", "@code": "19", "result": {"@total-count": "1", "@count": "1", "nexthop": {"member": "1.1.1.1"}}, } }, ) mocker.patch.object(demisto, "params", return_value=params) mocker.patch.object(demisto, "args", return_value=args) mocker.patch.object(demisto, "command", return_value="pan-os-edit-redistribution-profile") main() assert mock_request.call_args.kwargs["params"]["xpath"] == expected_url_params["xpath"] assert "1.1.1.1" in mock_request.call_args.kwargs["params"]["element"] assert "2.2.2.2" in mock_request.call_args.kwargs["params"]["element"] assert "3.3.3.3" in mock_request.call_args.kwargs["params"]["element"] @pytest.mark.parametrize( "args, params, expected_url_params", [ pytest.param( { "virtual_router": "virtual-router", "name": "redistribution-profile", "element_to_change": "filter_ospf_area", "element_value": "1.1.1.1", "behavior": "remove", }, integration_panorama_params, { "xpath": "/config/devices/entry[@name='localhost.localdomain']/template/entry[@name='test']" "/config/devices/entry[@name='localhost.localdomain']/network/virtual-router/entry" "[@name='virtual-router']/protocol/redist-profile/entry" "[@name='redistribution-profile']/filter/ospf/area", "element": "<area />", "action": "edit", "type": "config", "key": "thisisabogusAPIKEY!", }, ), pytest.param( { "virtual_router": "virtual-router", "name": "redistribution-profile", "element_to_change": "filter_ospf_area", "element_value": "1.1.1.1", "behavior": "remove", }, integration_firewall_params, { "xpath": "/config/devices/entry[@name='localhost.localdomain']/network/virtual-router/entry" "[@name='virtual-router']/protocol/redist-profile/entry[@name='redistribution-profile']" "/filter/ospf/area", "element": "<area />", "action": "edit", "type": "config", "key": "thisisabogusAPIKEY!", }, ), ], ) def test_pan_os_edit_redistribution_profile_command_remove_action_main_flow(self, mocker, args, params, expected_url_params): """ Tests cases where behavior == 'remove' Given: - Panorama instance configuration and area object of a redistribution-profile to remove. - Firewall instance configuration and area object of a redistribution-profile to remove. When: - running the pan-os-edit-redistribution-profile through the main flow. Then: - make sure the xpath and the request is correct for both panorama/firewall. """ from Panorama import main mock_request = mocker.patch( "Panorama.http_request", return_value={ "response": { "@status": "success", "@code": "19", "result": {"@total-count": "1", "@count": "1", "area": {"member": ["1.1.1.1"]}}, } }, ) mocker.patch.object(demisto, "params", return_value=params) mocker.patch.object(demisto, "args", return_value=args) mocker.patch.object(demisto, "command", return_value="pan-os-edit-redistribution-profile") main() assert mock_request.call_args.kwargs["params"] == expected_url_params @pytest.mark.parametrize( "args, params, expected_url_params", [ pytest.param( {"virtual_router": "virtual-router", "name": "redistribution-profile"}, integration_panorama_params, { "xpath": "/config/devices/entry[@name='localhost.localdomain']/template/entry[@name='test']/c" "onfig/devices/entry[@name='localhost.localdomain']/network/virtual-router/entry" "[@name='virtual-router']/protocol/redist-profile/entry[@name='redistribution-profile']", "action": "delete", "type": "config", "key": "thisisabogusAPIKEY!", }, ), pytest.param( {"virtual_router": "virtual-router", "name": "redistribution-profile"}, integration_firewall_params, { "xpath": "/config/devices/entry[@name='localhost.localdomain']/network/virtual-router/entry" "[@name='virtual-router']/protocol/redist-profile/entry[@name='redistribution-profile']", "action": "delete", "type": "config", "key": "thisisabogusAPIKEY!", }, ), ], ) def test_pan_os_delete_redistribution_profile_command_main_flow(mocker, args, params, expected_url_params): """ Given: - Panorama instance configuration and arguments to delete a redistribution-profile. - Firewall instance configuration and arguments to delete a redistribution-profile. When: - running the pan-os-delete-redistribution-profile through the main flow. Then: - make sure the xpath and the request is correct for both panorama/firewall. """ from Panorama import main mock_request = mocker.patch( "Panorama.http_request", return_value={"response": {"@status": "success", "@code": "20", "msg": "command succeeded"}} ) mocker.patch.object(demisto, "params", return_value=params) mocker.patch.object(demisto, "args", return_value=args) mocker.patch.object(demisto, "command", return_value="pan-os-delete-redistribution-profile") main() assert mock_request.call_args.kwargs["params"] == expected_url_params class TestPanOSListPBFRulesCommand: @pytest.mark.parametrize( "args, params, expected_url_params", [ pytest.param( {"pre_post": "pre-rulebase", "show_uncommitted": "true"}, integration_panorama_params, { "type": "config", "action": "get", "key": "thisisabogusAPIKEY!", "xpath": "/config/devices/entry[@name='localhost.localdomain']/device-group" "/entry[@name='Lab-Devices']/pre-rulebase/pbf", }, ), pytest.param( {"show_uncommitted": "true"}, integration_firewall_params, { "type": "config", "action": "get", "key": "thisisabogusAPIKEY!", "xpath": "/config/devices/entry[@name='localhost.localdomain']/vsys/entry[@name='vsys1']/rulebase/pbf", }, ), ], ) def test_pan_os_list_pbf_command_un_committed_rules_main_flow(self, mocker, args, params, expected_url_params): """ Given: - Panorama instance configuration and arguments to get all the un-committed PBF rules. - Firewall instance configuration and arguments to get all the un-committed PBF rules. When: - running the pan-os-list-pbf-rules through the main flow. Then: - make sure the context output is parsed correctly. - make sure the xpath and the request is correct for both panorama/firewall. """ from Panorama import main expected_context = [ { "Name": "test", "Description": "this is a test description", "Tags": ["test tag", "dag_test_tag"], "SourceZone": "1.1.1.1", "SourceInterface": None, "SourceAddress": "1.1.1.1", "SourceUser": "pre-logon", "DestinationAddress": "1.1.1.1", "Action": { "forward": { "nexthop": {"ip-address": "2.2.2.2"}, "monitor": {"profile": "profile", "disable-if-unreachable": "no", "ip-address": "1.1.1.1"}, "egress-interface": "a2", } }, "EnforceSymmetricReturn": {"nexthop-address-list": {"entry": {"@name": "1.1.1.1"}}, "enabled": "yes"}, "Target": {"negate": "no"}, "Application": "3pc", "Service": "application-default", "Disabled": None, }, { "Name": "test2", "Description": None, "Tags": None, "SourceZone": ["1.1.1.1", "2.2.2.2"], "SourceInterface": None, "SourceAddress": "any", "SourceUser": "any", "DestinationAddress": "any", "Action": {"no-pbf": {}}, "EnforceSymmetricReturn": {"enabled": "no"}, "Target": {"negate": "no"}, "Application": "any", "Service": "any", "Disabled": "yes", }, { "Name": "test3", "Description": None, "Tags": None, "SourceZone": None, "SourceInterface": "a2", "SourceAddress": "any", "SourceUser": "any", "DestinationAddress": "any", "Action": {"discard": {}}, "EnforceSymmetricReturn": {"enabled": "no"}, "Target": {"negate": "no"}, "Application": "any", "Service": "any", "Disabled": "no", }, ] mock_request = mocker.patch( "Panorama.http_request", return_value=load_json("test_data/list-pbf-rules-response-un-committed.json") ) mocker.patch.object(demisto, "params", return_value=params) mocker.patch.object(demisto, "args", return_value=args) mocker.patch.object(demisto, "command", return_value="pan-os-list-pbf-rules") result = mocker.patch("demistomock.results") main() assert list(result.call_args.args[0]["EntryContext"].values())[0] == expected_context assert mock_request.call_args.kwargs["params"] == expected_url_params @pytest.mark.parametrize( "args, params, expected_url_params", [ pytest.param( {"pre_post": "pre-rulebase", "show_uncommitted": "false", "rulename": "test"}, integration_panorama_params, { "type": "config", "action": "show", "key": "thisisabogusAPIKEY!", "xpath": "/config/devices/entry[@name='localhost.localdomain']/device-group/entry" "[@name='Lab-Devices']/pre-rulebase/pbf/rules/entry[@name='test']", }, ), pytest.param( {"show_uncommitted": "false", "rulename": "test"}, integration_firewall_params, { "type": "config", "action": "show", "key": "thisisabogusAPIKEY!", "xpath": "/config/devices/entry[@name='localhost.localdomain']/vsys/entry[@name='vsys1']" "/rulebase/pbf/rules/entry[@name='test']", }, ), ], ) def test_pan_os_list_pbf_command_committed_rules_main_flow(self, mocker, args, params, expected_url_params): """ Given: - Panorama instance configuration and arguments to get a specific committed PBF rule. - Firewall instance configuration and arguments to get a specific committed PBF rule. When: - running the pan-os-list-pbf-rules through the main flow. Then: - make sure the context output is parsed correctly. - make sure the xpath and the request is correct for both panorama/firewall. """ from Panorama import main expected_context = [ { "Name": "test", "Description": "this is a test description", "Tags": ["test tag", "dag_test_tag"], "SourceZone": "1.1.1.1", "SourceInterface": None, "Disabled": None, "SourceAddress": "1.1.1.1", "SourceUser": "pre-logon", "DestinationAddress": "1.1.1.1", "Action": { "forward": { "nexthop": {"ip-address": "2.2.2.2"}, "monitor": {"profile": "profile", "disable-if-unreachable": "no", "ip-address": "1.1.1.1"}, "egress-interface": "a2", } }, "EnforceSymmetricReturn": {"nexthop-address-list": {"entry": {"@name": "1.1.1.1"}}, "enabled": "yes"}, "Target": {"negate": "no"}, "Application": "3pc", "Service": "application-default", } ] mock_request = mocker.patch( "Panorama.http_request", return_value=load_json("test_data/list-pbf-rules-response-commited.json") ) mocker.patch.object(demisto, "params", return_value=params) mocker.patch.object(demisto, "args", return_value=args) mocker.patch.object(demisto, "command", return_value="pan-os-list-pbf-rules") result = mocker.patch("demistomock.results") main() assert list(result.call_args.args[0]["EntryContext"].values())[0] == expected_context assert mock_request.call_args.kwargs["params"] == expected_url_params class TestCreatePBFRuleCommand: @pytest.mark.parametrize( "args, params, expected_url_params", [ pytest.param( { "rulename": "test", "description": "test", "pre_post": "pre-rulebase", "negate_source": "yes", "action": "forward", "egress_interface": "egress-interface", "nexthop": "none", "destination_address": "any", "enforce_symmetric_return": "no", }, integration_panorama_params, { "xpath": "/config/devices/entry[@name='localhost.localdomain']/device-group/entry" "[@name='Lab-Devices']/pre-rulebase/pbf/rules/entry[@name='test']", "element": "<action><forward><egress-interface>egress-interface</egress-interface></forward>" "</action><enforce-symmetric-return><enabled>no</enabled></enforce-symmetric-return>" "<destination><member>any</member></destination><description>test</description>" "<negate-source>yes</negate-source>", "action": "set", "type": "config", "key": "thisisabogusAPIKEY!", }, ), pytest.param( { "rulename": "test", "description": "test", "action": "no-pbf", "source_zone": "1.1.1.1,2.2.2.2", "enforce_symmetric_return": "yes", "nexthop_address_list": "1.1.1.1,2.2.2.2", "nexthop": "ip-address", "nexthop_value": "1.1.1.1", }, integration_firewall_params, { "action": "set", "element": "<action><no-pbf/></action><enforce-symmetric-return><enabled>yes</enabled>" '<nexthop-address-list><entry name="1.1.1.1"/><entry name="2.2.2.2"/>' "</nexthop-address-list></enforce-symmetric-return><description>test" "</description><from><zone><member>1.1.1.1" "</member><member>2.2.2.2</member></zone></from>", "key": "thisisabogusAPIKEY!", "type": "config", "xpath": "/config/devices/entry[@name='localhost.localdomain']/vsys/entry[@name='vsys1']" "/rulebase/pbf/rules/entry[@name='test']", }, ), pytest.param( { "rulename": "test", "description": "test", "action": "discard", "destination_address": "1.1.1.1,2.2.2.2", "tags": "tag1,tag2", "nexthop_address_list": "1.1.1.1,2.2.2.2", "nexthop": "fqdn", "nexthop_value": "1.1.1.1/24", "pre_post": "pre-rulebase", "enforce_symmetric_return": "yes", "audit_comment": "test comment", }, integration_panorama_params, { "action": "set", "element": "<action><discard/></action><enforce-symmetric-return><enabled>yes</" "enabled><nexthop-address-list><entry " 'name="1.1.1.1"/><entry name="2.2.2.2"/></nexthop-address-list>' "</enforce-symmetric-return><destination>" "<member>1.1.1.1</member><member>2.2.2.2</member>" "</destination><description>test</description>", "key": "thisisabogusAPIKEY!", "type": "config", "xpath": "/config/devices/entry[@name='localhost.localdomain']/device-group/entry" "[@name='Lab-Devices']/pre-rulebase/pbf/rules/entry[@name='test']", "audit-comment": "test comment", }, ), pytest.param( { "rulename": "test", "description": "test", "action": "forward", "egress_interface": "egress-interface", "source_zone": "all access zone external", "nexthop": "none", "enforce_symmetric_return": "no", "audit_comment": "test comment", }, integration_firewall_params, { "action": "set", "element": "<action><forward><egress-interface>egress-interface</egress-interface></forward>" "</action><enforce-symmetric-return><enabled>no</enabled></enforce-symmetric-return>" "<description>test</description><from><zone>" "<member>all access zone external</member></zone></from>", "key": "thisisabogusAPIKEY!", "type": "config", "xpath": "/config/devices/entry[@name='localhost.localdomain']/vsys/entry[@name='vsys1']" "/rulebase/pbf/rules/entry[@name='test']", "audit-comment": "test comment", }, ), ], ) def test_pan_os_create_pbf_rule_command_main_flow(self, mocker, args, params, expected_url_params): """ Given: - Panorama instance configuration with forward action and egress_interface arguments. - Firewall instance configuration with no-pbf action and ip-address as nexthop arguments. - Panorama instance configuration with discard action and fqdn as nexthop arguments. - firewall instance configuration with basic parameter configurations along with dynamic-ip When: - running the pan-os-create-pbf-rule through the main flow. Then: - make sure the xpath/element and the request is correct for both panorama/firewall. """ from Panorama import main mock_request = mocker.patch( "Panorama.http_request", return_value={"response": {"@status": "success", "@code": "20", "msg": "command succeeded"}} ) mocker.patch.object(demisto, "params", return_value=params) mocker.patch.object(demisto, "args", return_value=args) mocker.patch.object(demisto, "command", return_value="pan-os-create-pbf-rule") main() assert mock_request.call_args.kwargs["params"] == expected_url_params class TestPanOSEditPBFRule: @pytest.mark.parametrize( "args, params, expected_url_params", [ pytest.param( { "rulename": "test", "element_to_change": "action_forward_egress_interface", "element_value": "interface-1", "pre_post": "pre-rulebase", "behavior": "replace", }, integration_panorama_params, { "action": "edit", "element": "<egress-interface>interface-1</egress-interface>", "key": "thisisabogusAPIKEY!", "type": "config", "xpath": "/config/devices/entry[@name='localhost.localdomain']/device-group/entry" "[@name='Lab-Devices']/pre-rulebase/pbf/rules/entry[@name='test']/" "action/forward/egress-interface", }, ), pytest.param( { "rulename": "test", "element_to_change": "action_forward_no_pbf", "pre_post": "pre-rulebase", "behavior": "replace", }, integration_panorama_params, { "action": "edit", "element": "<action><no-pbf/></action>", "key": "thisisabogusAPIKEY!", "type": "config", "xpath": "/config/devices/entry[@name='localhost.localdomain']/device-group/entry" "[@name='Lab-Devices']/pre-rulebase/pbf/rules/entry[@name='test']/action", }, ), pytest.param( { "rulename": "test", "element_to_change": "action_forward_discard", "pre_post": "pre-rulebase", "behavior": "replace", }, integration_panorama_params, { "action": "edit", "element": "<action><discard/></action>", "key": "thisisabogusAPIKEY!", "type": "config", "xpath": "/config/devices/entry[@name='localhost.localdomain']/device-group/entry" "[@name='Lab-Devices']/pre-rulebase/pbf/rules/entry[@name='test']/action", }, ), pytest.param( { "rulename": "test", "element_to_change": "nexthop_address_list", "element_value": "1.1.1.1,2.2.2.2", "behavior": "replace", }, integration_firewall_params, { "action": "edit", "element": '<nexthop-address-list><entry name="1.1.1.1"/><entry name="2.2.2.2"/></nexthop-address-list>', "key": "thisisabogusAPIKEY!", "type": "config", "xpath": "/config/devices/entry[@name='localhost.localdomain']/vsys/" "entry[@name='vsys1']/rulebase/pbf/rules/entry[@name='test']" "/enforce-symmetric-return/nexthop-address-list", }, ), pytest.param( { "rulename": "test", "element_to_change": "source_zone", "element_value": "1.1.1.1,2.2.2.2", "behavior": "replace", }, integration_firewall_params, { "action": "edit", "element": "<zone><member>1.1.1.1</member><member>2.2.2.2</member></zone>", "key": "thisisabogusAPIKEY!", "type": "config", "xpath": "/config/devices/entry[@name='localhost.localdomain']/vsys/entry" "[@name='vsys1']/rulebase/pbf/rules/entry[@name='test']/from/zone", }, ), ], ) def test_pan_os_edit_pbf_rule_command_replace_operation_main_flow(self, mocker, args, params, expected_url_params): """ Tests several cases when behavior == 'replace' Given: - Panorama instance configuration and egress-interface object of a pbf-rule to edit. - Panorama instance configuration and action='no-pbf' object of a pbf-rule to edit. - Panorama instance configuration and action='discard' object of a pbf-rule to edit. - Firewall instance configuration and nexthop_address_list object of a pbf-rule to edit. - Firewall instance configuration and source_zone object of a pbf-rule to edit. When: - running the pan-os-edit-pbf-rule through the main flow. Then: - make sure the xpath and the request is correct for both panorama/firewall. """ from Panorama import main mock_request = mocker.patch( "Panorama.http_request", return_value={"response": {"@status": "success", "@code": "20", "msg": "command succeeded"}} ) mocker.patch.object(demisto, "params", return_value=params) mocker.patch.object(demisto, "args", return_value=args) mocker.patch.object(demisto, "command", return_value="pan-os-edit-pbf-rule") main() assert mock_request.call_args.kwargs["params"] == expected_url_params @pytest.mark.parametrize( "args, params, expected_url_params", [ pytest.param( { "rulename": "test", "element_to_change": "nexthop_address_list", "element_value": "2.2.2.2,3.3.3.3", "behavior": "add", "pre_post": "pre-rulebase", }, integration_panorama_params, { "xpath": "/config/devices/entry[@name='localhost.localdomain']/device-group/entry" "[@name='Lab-Devices']/pre-rulebase/pbf/rules/entry[@name='test']/enforce-symmetric-return" "/nexthop-address-list", "element": '<nexthop-address-list><entry name="1.1.1.1"/><entry name="2.2.2.2"/>' '<entry name="3.3.3.3"/></nexthop-address-list>', "action": "edit", "type": "config", "key": "thisisabogusAPIKEY!", }, ), pytest.param( { "rulename": "test", "element_to_change": "nexthop_address_list", "element_value": "2.2.2.2,3.3.3.3", "behavior": "add", }, integration_firewall_params, { "xpath": "/config/devices/entry[@name='localhost.localdomain']/vsys/entry[@name='vsys1']" "/rulebase/pbf/rules/entry[@name='test']/enforce-symmetric-return/nexthop-address-list", "element": '<nexthop-address-list><entry name="2.2.2.2"/><entry name="3.3.3.3"/>' '<entry name="1.1.1.1"/></nexthop-address-list>', "action": "edit", "type": "config", "key": "thisisabogusAPIKEY!", }, ), ], ) def test_pan_os_edit_pbf_rule_command_add_action_main_flow(self, mocker, args, params, expected_url_params): """ Tests cases where behavior == 'add' Given: - Panorama instance configuration and nexthop-address-list object of a pbf-rule to add. - Firewall instance configuration and nexthop-address-list object of a pbf-rule to add. When: - running the pan-os-edit-pbf-rule through the main flow. Then: - make sure the xpath and the request is correct for both panorama/firewall. """ from Panorama import main mock_request = mocker.patch( "Panorama.http_request", return_value={ "response": { "@status": "success", "@code": "19", "result": {"@total-count": "1", "@count": "1", "nexthop-address-list": {"member": "1.1.1.1"}}, } }, ) mocker.patch.object(demisto, "params", return_value=params) mocker.patch.object(demisto, "args", return_value=args) mocker.patch.object(demisto, "command", return_value="pan-os-edit-pbf-rule") main() assert mock_request.call_args.kwargs["params"]["xpath"] == expected_url_params["xpath"] assert "1.1.1.1" in mock_request.call_args.kwargs["params"]["element"] assert "2.2.2.2" in mock_request.call_args.kwargs["params"]["element"] assert "3.3.3.3" in mock_request.call_args.kwargs["params"]["element"] @pytest.mark.parametrize( "args, params, expected_url_params", [ pytest.param( { "rulename": "test", "element_to_change": "application", "element_value": "application-1", "behavior": "remove", "pre_post": "pre-rulebase", }, integration_panorama_params, { "xpath": "/config/devices/entry[@name='localhost.localdomain']/device-group/entry" "[@name='Lab-Devices']/pre-rulebase/pbf/rules/entry[@name='test']/application", "element": "<application><member>application-2</member></application>", "action": "edit", "type": "config", "key": "thisisabogusAPIKEY!", }, ), pytest.param( {"rulename": "test", "element_to_change": "application", "element_value": "application-1", "behavior": "remove"}, integration_firewall_params, { "xpath": "/config/devices/entry[@name='localhost.localdomain']/vsys/entry[@name='vsys1']/" "rulebase/pbf/rules/entry[@name='test']/application", "element": "<application><member>application-2</member></application>", "action": "edit", "type": "config", "key": "thisisabogusAPIKEY!", }, ), ], ) def test_pan_os_edit_pbf_rule_command_remove_action_main_flow(self, mocker, args, params, expected_url_params): """ Tests cases where behavior == 'remove' Given: - Panorama instance configuration and address object of a PBF-rule to remove. - Firewall instance configuration and address object of a PBF-rule to remove. When: - running the pan-os-edit-pbf-rule through the main flow. Then: - make sure the xpath and the request is correct for both panorama/firewall. """ from Panorama import main mock_request = mocker.patch( "Panorama.http_request", return_value={ "response": { "@status": "success", "@code": "19", "result": {"@total-count": "1", "@count": "1", "application": {"member": ["application-1", "application-2"]}}, } }, ) mocker.patch.object(demisto, "params", return_value=params) mocker.patch.object(demisto, "args", return_value=args) mocker.patch.object(demisto, "command", return_value="pan-os-edit-pbf-rule") main() assert mock_request.call_args.kwargs["params"] == expected_url_params @staticmethod def test_pan_os_edit_pbf_rule_command_audit_comment_main_flow(mocker): """ Given - panorama integrations parameters. - pan-os-edit-pbf-rule command arguments including device_group. - arguments to edit audit comment of a rule When - running the pan-os-edit-pbf-rule command through the main flow Then - make sure the context output is returned as expected. - make sure the device group gets overriden by the command arguments. """ from Panorama import main mocker.patch.object(demisto, "params", return_value=integration_panorama_params) mocker.patch.object( demisto, "args", return_value={ "rulename": "test", "element_to_change": "audit-comment", "element_value": "some string", "pre_post": "pre-rulebase", "device-group": "new device group", }, ) mocker.patch.object(demisto, "command", return_value="pan-os-edit-pbf-rule") request_mock = mocker.patch( "Panorama.http_request", return_value=TestPanoramaEditRuleCommand.EDIT_AUDIT_COMMENT_SUCCESS_RESPONSE ) res = mocker.patch("demistomock.results") main() assert request_mock.call_args.kwargs["params"] == { "type": "op", "cmd": "<set><audit-comment><xpath>/config/devices/entry[@name='localhost.localdomain']/device-group" "/entry[@name='new device group']/pre-rulebase/pbf/rules/entry[@name='test']" "</xpath><comment>some string</comment></audit-comment></set>", "key": "thisisabogusAPIKEY!", } assert res.call_args.args[0]["Contents"] == TestPanoramaEditRuleCommand.EDIT_AUDIT_COMMENT_SUCCESS_RESPONSE @pytest.mark.parametrize( "args, params, expected_url_params", [ pytest.param( {"rulename": "test", "pre_post": "pre-rulebase"}, integration_panorama_params, { "action": "delete", "key": "thisisabogusAPIKEY!", "type": "config", "xpath": "/config/devices/entry[@name='localhost.localdomain']/device-group/entry" "[@name='Lab-Devices']/pre-rulebase/pbf/rules/entry[@name='test']", }, ), pytest.param( {"rulename": "test"}, integration_firewall_params, { "action": "delete", "key": "thisisabogusAPIKEY!", "type": "config", "xpath": "/config/devices/entry[@name='localhost.localdomain']/vsys/entry" "[@name='vsys1']/rulebase/pbf/rules/entry[@name='test']", }, ), ], ) def test_pan_os_delete_pbf_rule_command_main_flow(mocker, args, params, expected_url_params): """ Given: - Panorama instance configuration with a specific rulename. - Firewall instance configuration with a specific rulename. When: - running the pan-os-delete-pbf-rule through the main flow. Then: - make sure the xpath/element and the request is correct for both panorama/firewall. """ from Panorama import main mock_request = mocker.patch( "Panorama.http_request", return_value={"response": {"@status": "success", "@code": "20", "msg": "command succeeded"}} ) mocker.patch.object(demisto, "params", return_value=params) mocker.patch.object(demisto, "args", return_value=args) mocker.patch.object(demisto, "command", return_value="pan-os-delete-pbf-rule") main() assert mock_request.call_args.kwargs["params"] == expected_url_params @pytest.mark.parametrize( "args, params, expected_url_params", [ pytest.param( {"name": "address", "element_to_change": "fqdn", "element_value": "1.1.1.1"}, integration_panorama_params, { "xpath": "/config/devices/entry/device-group/entry[@name='Lab-Devices']/address" '/entry[@name="address"]/fqdn', # noqa: ISC001 "element": "<fqdn>1.1.1.1</fqdn>", "action": "edit", "type": "config", "key": "thisisabogusAPIKEY!", }, ), pytest.param( {"name": "address", "element_to_change": "ip_range", "element_value": "1.1.1.1-1.1.1.8"}, integration_panorama_params, { "xpath": "/config/devices/entry/device-group/entry[@name='Lab-Devices']" '/address/entry[@name="address"]/ip-range', "element": "<ip-range>1.1.1.1-1.1.1.8</ip-range>", "action": "edit", "type": "config", "key": "thisisabogusAPIKEY!", }, ), pytest.param( {"name": "address", "element_to_change": "tag", "element_value": "tag1,tag2"}, integration_firewall_params, { "xpath": "/config/devices/entry/vsys/entry[@name='vsys1']/address/entry[@name=\"address\"]/tag", "element": "<tag><member>tag1</member><member>tag2</member></tag>", "action": "edit", "type": "config", "key": "thisisabogusAPIKEY!", }, ), ], ) def test_pan_os_edit_address_group_command_main_flow(mocker, args, params, expected_url_params): """ Given: - Panorama instance configuration and fqdn object of an address to edit. - Panorama instance configuration and ip-range object of an address to edit. - Firewall instance configuration and tag object of an address to edit. When: - running the pan-os-edit-address through the main flow. Then: - make sure the xpath and the request is correct for both panorama/firewall. """ from Panorama import main mock_request = mocker.patch( "Panorama.http_request", return_value={"response": {"@status": "success", "@code": "20", "msg": "command succeeded"}} ) mocker.patch.object(demisto, "params", return_value=params) mocker.patch.object(demisto, "args", return_value=args) mocker.patch.object(demisto, "command", return_value="pan-os-edit-address") main() assert mock_request.call_args.kwargs["params"] == expected_url_params @pytest.mark.parametrize( "args, params, expected_url_params", [ pytest.param( {"show_uncommitted": "true"}, integration_panorama_params, { "type": "config", "action": "get", "key": "thisisabogusAPIKEY!", "xpath": "/config/devices/entry/device-group/entry[@name='Lab-Devices']/application-group", }, ), pytest.param( {"show_uncommitted": "true"}, integration_firewall_params, { "type": "config", "action": "get", "key": "thisisabogusAPIKEY!", "xpath": "/config/devices/entry/vsys/entry[@name='vsys1']/application-group", }, ), ], ) def test_pan_os_list_application_groups_command_main_flow(mocker, args, params, expected_url_params): """ Given: - Panorama instance configuration to retrieve all un-committed applications-groups. - Firewall instance configuration to retrieve all un-committed applications-groups. When: - running the pan-os-list-application-groups through the main flow. Then: - make sure the context output is parsed correctly for both un-committed and committed cases. - make sure the xpath and the request is correct for both panorama/firewall. """ from Panorama import main mock_request = mocker.patch( "Panorama.http_request", return_value=load_json("test_data/list_application_groups_un_committed.json") ) mocker.patch.object(demisto, "params", return_value=params) mocker.patch.object(demisto, "args", return_value=args) mocker.patch.object(demisto, "command", return_value="pan-os-list-application-groups") result = mocker.patch("demistomock.results") main() assert list(result.call_args.args[0]["EntryContext"].values())[0] == [ {"Applications": ["application-3"], "Members": 1, "Name": "test"}, {"Applications": ["application-1", "application-2"], "Members": 2, "Name": "test-2"}, ] assert mock_request.call_args.kwargs["params"] == expected_url_params @pytest.mark.parametrize( "args, params, expected_url_params", [ pytest.param( {"name": "test", "applications": "application1,application2", "device-group": "test-device-group"}, integration_panorama_params, { "xpath": "/config/devices/entry/device-group/entry[@name='test-device-group']" "/application-group/entry[@name='test']", "element": "<members><member>application1</member><member>application2</member></members>", "action": "set", "type": "config", "key": "thisisabogusAPIKEY!", }, ), pytest.param( {"name": "test", "applications": "application1,application2"}, integration_firewall_params, { "xpath": "/config/devices/entry/vsys/entry[@name='vsys1']/application-group/entry[@name='test']", "element": "<members><member>application1</member><member>application2</member></members>", "action": "set", "type": "config", "key": "thisisabogusAPIKEY!", }, ), ], ) def test_pan_os_create_application_group_command_main_flow(mocker, args, params, expected_url_params): """ Given: - Panorama instance configuration and arguments to create an application group. - Firewall instance configuration and arguments to create an application group. When: - running the pan-os-create-application-group through the main flow. Then: - make sure the xpath and the request is correct for both panorama/firewall. - make sure the context is returned correctly. """ from Panorama import main mock_request = mocker.patch( "Panorama.http_request", return_value={"response": {"@status": "success", "@code": "20", "msg": "command succeeded"}} ) mocker.patch.object(demisto, "params", return_value=params) mocker.patch.object(demisto, "args", return_value=args) mocker.patch.object(demisto, "command", return_value="pan-os-create-application-group") result = mocker.patch("demistomock.results") main() assert list(result.call_args.args[0]["EntryContext"].values())[0] == { "Name": "test", "Applications": ["application1", "application2"], "Members": 2, } assert mock_request.call_args.kwargs["params"] == expected_url_params class TestPanOSEditApplicationGroupCommand: @pytest.mark.parametrize( "args, params, expected_url_params", [ pytest.param( {"name": "test", "applications": "application-2", "action": "add"}, integration_panorama_params, { "xpath": "/config/devices/entry/device-group/entry[@name='Lab-Devices']" "/application-group/entry[@name='test']/members", "element": "<members><member>application-1</member><member>application-2</member></members>", "action": "edit", "type": "config", "key": "thisisabogusAPIKEY!", }, ), pytest.param( {"name": "test", "applications": "application-2", "action": "add"}, integration_firewall_params, { "xpath": "/config/devices/entry/vsys/entry[@name='vsys1']/application-group/entry[@name='test']/members", "element": "<members><member>application-2</member><member>application-1</member></members>", "action": "edit", "type": "config", "key": "thisisabogusAPIKEY!", }, ), ], ) def test_pan_os_edit_application_group_main_flow_add_action(self, mocker, args, params, expected_url_params): """ Tests cases where action == 'add' Given: - Panorama instance configuration and applications object of an application-group to add. - Firewall instance configuration and applications object of an application-group to add. When: - running the pan-os-edit-application-group through the main flow. Then: - make sure the xpath and the request is correct for both panorama/firewall. """ from Panorama import main responses = [ { "response": { "@status": "success", "@code": "19", "result": {"@total-count": "1", "@count": "1", "members": {"member": "application-1"}}, } }, {"response": {"@status": "success", "@code": "20", "msg": "command succeeded"}}, { "response": { "@status": "success", "@code": "19", "result": { "@total-count": "1", "@count": "1", "members": { "@admin": "admin", "@dirtyId": "809", "@time": "2022/09/14 04:12:11", "member": [ {"@admin": "admin", "@dirtyId": "809", "@time": "2022/09/14 04:12:11", "#text": "application-1"}, {"@admin": "admin", "@dirtyId": "809", "@time": "2022/09/14 04:12:11", "#text": "application-2"}, ], }, }, } }, ] mock_request = mocker.patch("Panorama.http_request", side_effect=responses) mocker.patch.object(demisto, "params", return_value=params) mocker.patch.object(demisto, "args", return_value=args) mocker.patch.object(demisto, "command", return_value="pan-os-edit-application-group") main() assert mock_request.mock_calls[1].kwargs["params"]["xpath"] == expected_url_params["xpath"] assert "application-1" in mock_request.mock_calls[1].kwargs["params"]["element"] assert "application-2" in mock_request.mock_calls[1].kwargs["params"]["element"] @pytest.mark.parametrize( "args, params, expected_url_params", [ pytest.param( {"name": "test", "applications": "application-2", "action": "remove"}, integration_panorama_params, { "xpath": "/config/devices/entry/device-group/entry[@name='Lab-Devices']/application-group/" "entry[@name='test']/members", "element": "<members><member>application-1</member></members>", "action": "edit", "type": "config", "key": "thisisabogusAPIKEY!", }, ), pytest.param( {"name": "test", "applications": "application-2", "action": "remove"}, integration_firewall_params, { "xpath": "/config/devices/entry/vsys/entry[@name='vsys1']/application-group/entry[@name='test']/members", "element": "<members><member>application-1</member></members>", "action": "edit", "type": "config", "key": "thisisabogusAPIKEY!", }, ), ], ) def test_pan_os_edit_application_group_main_flow_remove_action(self, mocker, args, params, expected_url_params): """ Tests cases where action == 'remove' Given: - Panorama instance configuration and an application object of an application-group to remove. - Firewall instance configuration and an application object of an application-group to remove. When: - running the pan-os-edit-application-group through the main flow. Then: - make sure the xpath and the request is correct for both panorama/firewall. """ from Panorama import main responses = [ { "response": { "@status": "success", "@code": "19", "result": {"@total-count": "1", "@count": "1", "members": {"member": ["application-1", "application-2"]}}, } }, {"response": {"@status": "success", "@code": "20", "msg": "command succeeded"}}, { "response": { "@status": "success", "@code": "19", "result": { "@total-count": "1", "@count": "1", "members": { "@admin": "admin", "@dirtyId": "809", "@time": "2022/09/14 04:12:11", "member": [ {"@admin": "admin", "@dirtyId": "809", "@time": "2022/09/14 04:12:11", "#text": "application-1"} ], }, }, } }, ] mock_request = mocker.patch("Panorama.http_request", side_effect=responses) mocker.patch.object(demisto, "params", return_value=params) mocker.patch.object(demisto, "args", return_value=args) mocker.patch.object(demisto, "command", return_value="pan-os-edit-application-group") main() assert mock_request.mock_calls[1].kwargs["params"] == expected_url_params @pytest.mark.parametrize( "args, params, expected_url_params", [ pytest.param( {"name": "test", "applications": "application-2", "action": "remove"}, integration_panorama_params, { "xpath": "/config/devices/entry/device-group/entry[@name='Lab-Devices']/application-group/entry[@name='test']", "action": "delete", "type": "config", "key": "thisisabogusAPIKEY!", }, ), pytest.param( {"name": "test", "applications": "application-2", "action": "remove"}, integration_firewall_params, { "xpath": "/config/devices/entry/vsys/entry[@name='vsys1']/application-group/entry[@name='test']", "action": "delete", "type": "config", "key": "thisisabogusAPIKEY!", }, ), ], ) def test_pan_os_delete_application_group_command_main_flow(mocker, args, params, expected_url_params): """ Given: - Panorama instance with a name of the application-group to delete. - Firewall instance with a name of the application-group to delete. When: - running the pan-os-delete-application-group through the main flow. Then: - make sure the xpath/element and the request is correct for both panorama/firewall. """ from Panorama import main mock_request = mocker.patch( "Panorama.http_request", return_value={"response": {"@status": "success", "@code": "20", "msg": "command succeeded"}} ) mocker.patch.object(demisto, "params", return_value=params) mocker.patch.object(demisto, "args", return_value=args) mocker.patch.object(demisto, "command", return_value="pan-os-delete-application-group") main() assert mock_request.call_args.kwargs["params"] == expected_url_params @pytest.mark.parametrize( "args, params, expected_url_params", [ pytest.param( {"IPs": "2.2.2.2", "tag": "test"}, integration_firewall_params, { "type": "user-id", "cmd": '<uid-message><version>2.0</version><type>update</type><payload><register><entry ip="2.2.2.2" ' 'persistent="1"><tag><member>test</member></tag></entry></register></payload></uid-message>', "key": "thisisabogusAPIKEY!", "vsys": "vsys1", }, ), pytest.param( {"IPs": "2.2.2.2", "tag": "test"}, integration_panorama_params, { "type": "user-id", "cmd": '<uid-message><version>2.0</version><type>update</type><payload><register><entry ip="2.2.2.2" ' 'persistent="1"><tag><member>test</member></tag></entry></register></payload></uid-message>', "key": "thisisabogusAPIKEY!", }, ), ], ) def test_pan_os_register_ip_tag_command_main_flow(mocker, args, params, expected_url_params): """ Given: - Panorama instance with IP tag to register (without vsys). - Firewall instance with IP tag to register (with vsys). When: - running the pan-os-register-ip-tag through the main flow. Then: - make sure the params and the request is correct for both panorama/firewall. """ from Panorama import main mock_request = mocker.patch( "Panorama.http_request", return_value={ "response": {"@status": "success", "result": {"uid-response": {"version": "2.0", "payload": {"register": None}}}} }, ) mocker.patch("Panorama.get_pan_os_major_version", return_value=9) mocker.patch.object(demisto, "params", return_value=params) mocker.patch.object(demisto, "args", return_value=args) mocker.patch.object(demisto, "command", return_value="pan-os-register-ip-tag") main() assert mock_request.call_args.kwargs["body"] == expected_url_params @pytest.mark.parametrize( "args", [ {"ip_netmask": "1", "ip_range": "2", "fqdn": "3", "ip_wildcard": "4", "name": "test"}, {"ip_netmask": "1", "ip_range": "2", "fqdn": "3", "name": "test"}, {"ip_netmask": "1", "ip_range": "2", "name": "test"}, {"ip_netmask": "1", "fqdn": "3", "name": "test"}, {"ip_range": "2", "fqdn": "3", "name": "test"}, {"ip_range": "2", "fqdn": "3", "ip_wildcard": "4", "name": "test"}, ], ) def test_pan_os_create_address_main_flow_error(args): """ Given: - more than one ip_netmask/ip_range/fqdn/ip_wildcard as command arguments When: - running the panorama_create_address_command function Then: - make sure an exception is raised saying only one of ip_netmask/ip_range/fqdn/ip_wildcard can be the command input. """ from Panorama import panorama_create_address_command with pytest.raises(DemistoException): panorama_create_address_command(args) @pytest.mark.parametrize( "device_group, vsys, response, args, error", [ ( "test", "", '<response status="success" code="19"> \ <result total-count="0" count="0"> \ </result> \ </response>', {"name": "test", "tag": "not exist"}, "Failed to create the address object since the tags `{'not exist'}` does not exist. " "You can use the `create_tag` argument to create the tag.", ), ( "", "vsys1", '<response status="success" code="19"> \ <result total-count="1" count="1"> \ <tag admin="admin" dirtyId="3" time="2023/04/23 01:41:22"> \ <entry name="exist" admin="admin" dirtyId="3" time="2023/04/23 01:18:03"/> \ </tag> \ </result> \ </response>', {"name": "test", "tag": "exist, not exist", "create_tag": "Yes"}, "Please specify exactly one of the following arguments: fqdn, ip_netmask, ip_range, ip_wildcard.", ), ], ) def test_pan_os_create_address_with_not_exist_tag(mocker, device_group, vsys, response, args, error): """ Given: - Tags that does not exist in the system as command arguments When: - Running the panorama_create_address_command function Then: - Make sure an exception is raised saying only tags that already exist in system can be the command input. """ from Panorama import panorama_create_address_command mocker.patch("Panorama.DEVICE_GROUP", device_group) mocker.patch("Panorama.VSYS", vsys) mocker.patch("Panorama.URL", "https://example.com") with requests_mock.Mocker() as m: m.get("https://example.com", text=response, status_code=200) m.post("https://example.com", text=response, status_code=200) with pytest.raises(DemistoException) as e: panorama_create_address_command(args) assert e.value.message == error """ FETCH INCIDENTS """ class TestFetchIncidentsHelperFunctions: @pytest.mark.parametrize( "query, last_fetch, expected_result", fetch_incidents_input.test_add_time_filter_to_query_parameter_args ) def test_add_time_filter_to_query_parameter(self, query, last_fetch, expected_result): """ Given: - a query from parameters When: - every fetch incidents cycle starts Then: - add_time_filter_to_query_parameter function will append time_generated parameter to the original query to filleter according to the queries log type last fetch time. """ from Panorama import add_time_filter_to_query_parameter assert add_time_filter_to_query_parameter(query, last_fetch, "time_generated") == expected_result @pytest.mark.parametrize("params, expected_result", fetch_incidents_input.test_parse_queries_args) def test_log_types_queries_to_dict(self, params, expected_result): """ Given: - valid parameters dictionary When: - test_log_types_queries_to_dict function is called Then: - assert that the returned queries_dict value is valid """ from Panorama import log_types_queries_to_dict assert log_types_queries_to_dict(params) == expected_result def test_incident_entry_to_incident_context(self): """ Given: - raw incident entry represented by a dictionary When: - incident_entry_to_incident_context function is called Then: - assert that the returned context formatted incident entry is valid """ from Panorama import DATE_FORMAT, incident_entry_to_incident_context raw_entry = {"seqno": "1", "time_generated": "2022/01/01 12:00", "type": "TYPE", "device_name": "dummy_device"} if occured := dateparser.parse("2022/01/01 12:00", settings={"TIMEZONE": "UTC"}): context_entry = { "name": "dummy_device 1", "occurred": occured.strftime(DATE_FORMAT), "rawJSON": json.dumps(raw_entry), } assert incident_entry_to_incident_context(raw_entry) == context_entry @pytest.mark.parametrize( "last_fetch_dict, first_fetch, queries_dict, expected_result", fetch_incidents_input.test_get_fetch_start_datetime_dict_args, ) @freeze_time("2022-01-02 11:00:00 UTC") def test_get_fetch_start_datetime_dict(self, last_fetch_dict, first_fetch, queries_dict, expected_result): """ Given: - last fetch dictionary - first fetch parameter - queries dictionary from parameters When: - get_fetch_start_datetime_dict function is called Then: - assert that the updated dictionary with fetch start time per log_type is valid """ from Panorama import get_fetch_start_datetime_dict result_dict = get_fetch_start_datetime_dict(last_fetch_dict, first_fetch, queries_dict) assert fetch_incidents_input.assert_datetime_objects(result_dict.get("X_log_type"), expected_result.get("X_log_type")) assert fetch_incidents_input.assert_datetime_objects(result_dict.get("Y_log_type"), expected_result.get("Y_log_type")) @pytest.mark.parametrize("incident_entries, expected_result", fetch_incidents_input.test_parse_incident_entries_args) def test_get_parsed_incident_entries(self, incident_entries, expected_result): from Panorama import LastFetchTimes, LastIDs, get_parsed_incident_entries last_id_dict = LastIDs() last_fetch_dict = LastFetchTimes(Url="2022/01/01 12:00:00") res = get_parsed_incident_entries({"Url": incident_entries}, last_fetch_dict, last_id_dict) assert last_id_dict.get("Url") == expected_result[0] assert last_fetch_dict["Url"] == expected_result[1] # type: ignore assert res == expected_result[2] @pytest.mark.parametrize( "incident_entries_dict, last_fetch_dict, last_id_dict, expected_result", fetch_incidents_input.get_parsed_incident_entries_args, ) def test_get_parsed_incident_entries_2(self, mocker, incident_entries_dict, last_fetch_dict, last_id_dict, expected_result): from Panorama import get_parsed_incident_entries assert get_parsed_incident_entries(incident_entries_dict, last_fetch_dict, last_id_dict) == expected_result @pytest.mark.parametrize("response, debug_msg, expected_result", fetch_incidents_input.get_query_entries_by_id_request_args) def test_get_query_entries_by_id_request(self, mocker, response, debug_msg, expected_result): """ Given: - A valid Panorama job id. When: 1. The Panorama job has already finished. 2. The Panorama job is still running (not finished). Then: 1. Verify the command output is the returned response, and the debug message is called with 'FIN' status. 2. Retry to query the job status in 1 second, and return empty dict if max retries exceeded. """ from Panorama import get_query_entries_by_id_request mocker.patch("Panorama.http_request", return_value=response) assert get_query_entries_by_id_request("000", 1) == expected_result class TestFetchIncidentsFlows: def test_first_fetch_with_no_incidents_flow(self, mocker): """ Given: - first fetch cycle. When: - no incident returned from fetch request. Then: - no incidents should be returned. """ from Panorama import fetch_incidents last_run = {} first_fetch = "24 hours" queries_dict = {"X_log_type": "(receive_time geq '2021/01/22 08:00:00)"} max_fetch = {"X_log_type": 10} mocker.patch("Panorama.get_query_entries", return_value={}) new_last_run, incident_entries_list = fetch_incidents(last_run, first_fetch, queries_dict, max_fetch, 5) assert incident_entries_list == [] assert new_last_run["last_fetch_dict"] == {"X_log_type": ""} assert new_last_run["last_id_dict"] == {} def test_first_fetch_with_one_incident_flow(self, mocker): """ Given: - first fetch cycle. When: - using fetch incidents. - one incident returned from fetch request. Then: - The only incident should be returned. - X_log_type last fetch should be created. - X_log_type last id should be created. """ from Panorama import fetch_incidents last_run = {} first_fetch = "24 hours" queries_dict = {"X_log_type": "(receive_time geq '2021/01/01 08:00:00)"} max_fetch = {"X_log_type": 10} raw_entries = { "seqno": "000000001", "type": "X_log_type", "time_generated": "2022/1/1 12:00:00", "device_name": "device_for_test", } expected_parsed_incident_entries = { "name": "device_for_test 000000001", "occurred": "2022-01-01T12:00:00Z", "rawJSON": json.dumps(raw_entries), } fetch_start_datetime_dict = {"X_log_type": dateparser.parse("2022/1/1 11:00:00", settings={"TIMEZONE": "UTC"})} mocker.patch("Panorama.get_query_entries", return_value=[raw_entries]) mocker.patch("Panorama.get_fetch_start_datetime_dict", return_value=fetch_start_datetime_dict) new_last_run, incident_entries_dict = fetch_incidents(last_run, first_fetch, queries_dict, max_fetch, 5) assert incident_entries_dict[0] == expected_parsed_incident_entries assert new_last_run["last_fetch_dict"].get("X_log_type", "") == "2022-01-01 12:00:00" assert new_last_run["last_id_dict"].get("X_log_type", "") == {"device_for_test": "000000001"} def test_second_fetch_with_no_incidents_flow(self, mocker): """ Given: - second fetch cycle. When: - using fetch incidents. - no new incidents are returned from the fetch request. Then: - no fetch incidents should be returned. - last_fetch_dict X_log_type value should not be updated. - last_id_dict X_log_type value should not be updated. """ from Panorama import fetch_incidents last_run = {"last_fetch_dict": {"X_log_type": "2022-01-01T12:00:00"}, "last_id_dict": {"X_log_type": "000000001"}} first_fetch = "24 hours" queries_dict = {"X_log_type": "(receive_time geq '2021/01/01 08:00:00)"} max_fetch = {"X_log_type": 10} raw_entries = [] expected_parsed_incident_entries = [] fetch_start_datetime_dict = {"X_log_type": dateparser.parse("2022/1/1 12:00:00", settings={"TIMEZONE": "UTC"})} mocker.patch("Panorama.get_query_entries", return_value=raw_entries) mocker.patch("Panorama.get_fetch_start_datetime_dict", return_value=fetch_start_datetime_dict) new_last_run, incident_entries_dict = fetch_incidents(last_run, first_fetch, queries_dict, max_fetch, 5) assert incident_entries_dict == expected_parsed_incident_entries assert new_last_run["last_fetch_dict"].get("X_log_type", "") == "2022-01-01T12:00:00" assert new_last_run["last_id_dict"].get("X_log_type", "") == "000000001" def test_second_fetch_with_two_incidents_with_same_log_type_flow(self, mocker): """ Given: - second fetch cycle with. When: - using fetch incidents. - one incident with an existing log type is returned (X_log_type). - the incident has a time generated value that is greater than last fetch time. Then: - the fetched incident should be returned. - last_fetch_dict X_log_type value should be updated. - last_id_dict X_log_type value should be updated. """ from Panorama import fetch_incidents last_run = { "last_fetch_dict": {"X_log_type": "2022-01-01 13:00:00"}, "last_id_dict": {"X_log_type": {"dummy_device": "000000001"}}, } first_fetch = "24 hours" queries_dict = {"X_log_type": "(receive_time geq '2021/01/01 08:00:00)"} max_fetch = {"X_log_type": 10} raw_entries = [ {"seqno": "000000002", "type": "X_log_type", "time_generated": "2022/1/1 13:00:00", "device_name": "dummy_device"} ] expected_parsed_incident_entries = [ {"name": "dummy_device 000000002", "occurred": "2022-01-01T13:00:00Z", "rawJSON": json.dumps(raw_entries[0])} ] fetch_start_datetime_dict = {"X_log_type": dateparser.parse("2022/1/1 12:00:00", settings={"TIMEZONE": "UTC"})} mocker.patch("Panorama.get_query_entries", return_value=raw_entries) mocker.patch("Panorama.get_fetch_start_datetime_dict", return_value=fetch_start_datetime_dict) new_last_run, incident_entries_dict = fetch_incidents(last_run, first_fetch, queries_dict, max_fetch, 5) assert incident_entries_dict == expected_parsed_incident_entries assert new_last_run["last_fetch_dict"].get("X_log_type", "") == "2022-01-01 13:00:00" assert new_last_run["last_id_dict"].get("X_log_type", "") == {"dummy_device": "000000002"} def test_second_fetch_with_two_incidents_with_different_log_types_flow(self, mocker): """ Given: - second fetch cycle. When: - using fetch incidents. - two incidents of two deferent log types (X_log_type, Y_log_type) are returned from the fetch time. - both incidents has the same generated time that is later than the last fetch run time. - one incident of X_log_type already have a last fetch run and last id, the second incident of type Y_log_Type don't. Then: - both incidents should be returned. - Y_log_type last fetch should be created. - Y_log_type last id is created. - X_log_type last fetch time will be updated. - X_log_type last id is updated. """ from Panorama import fetch_incidents last_run = { "last_fetch_dict": {"X_log_type": "2022-01-01 12:00:00"}, "last_id_dict": {"X_log_type": {"dummy_device1": "000000001"}}, } first_fetch = "24 hours" queries_dict = { "X_log_type": "(receive_time geq '2021/01/01 08:00:00)", "Y_log_type": "(receive_time geq '2021/01/01 08:00:00)", } max_fetch = {"X_log_type": 10} raw_entries = [ {"seqno": "000000002", "type": "X_log_type", "time_generated": "2022-01-01 13:00:00", "device_name": "dummy_device1"}, {"seqno": "000000001", "type": "Y_log_type", "time_generated": "2022-01-01 13:00:00", "device_name": "dummy_device2"}, ] fetch_incidents_request_result = {"X_log_type": [raw_entries[0]], "Y_log_type": [raw_entries[1]]} expected_parsed_incident_entries = [ {"name": "dummy_device1 000000002", "occurred": "2022-01-01T13:00:00Z", "rawJSON": json.dumps(raw_entries[0])}, {"name": "dummy_device2 000000001", "occurred": "2022-01-01T13:00:00Z", "rawJSON": json.dumps(raw_entries[1])}, ] fetch_start_datetime_dict = { "X_log_type": dateparser.parse("2022/1/1 11:00:00", settings={"TIMEZONE": "UTC"}), "Y_log_type": dateparser.parse("2022/1/1 11:00:00", settings={"TIMEZONE": "UTC"}), } mocker.patch("Panorama.fetch_incidents_request", return_value=fetch_incidents_request_result) mocker.patch("Panorama.get_fetch_start_datetime_dict", return_value=fetch_start_datetime_dict) new_last_run, incident_entries_dict = fetch_incidents(last_run, first_fetch, queries_dict, max_fetch, 5) assert incident_entries_dict == expected_parsed_incident_entries assert new_last_run["last_fetch_dict"].get("X_log_type", "") == "2022-01-01 13:00:00" assert new_last_run["last_id_dict"].get("X_log_type", "") == {"dummy_device1": "000000002"} assert new_last_run["last_fetch_dict"].get("Y_log_type", "") == "2022-01-01 13:00:00" assert new_last_run["last_id_dict"].get("Y_log_type", "") == {"dummy_device2": "000000001"} def test_second_fetch_with_two_incidents_with_different_log_types_and_different_last_fetch_flow(self, mocker): """ Given: - second fetch cycle. When: - using fetch incidents. - two incidents of two deferent log types (X_log_type, Y_log_type) are returned from the fetch time. - both incidents has the same generated time that is later than the last fetch run time. - both incidents log types has a last fetch run and last id. Then: - both incidents should be returned. - Y_log_type last fetch should be created. - Y_log_type last id is created. - X_log_type last fetch time will be updated. - X_log_type last id is updated. """ from Panorama import fetch_incidents last_run = { "last_fetch_dict": {"X_log_type": "2022-01-01 11:00:00", "Y_log_type": "2022-01-01 13:00:00"}, "last_id_dict": {"X_log_type": {"dummy_device1": "000000001"}, "Y_log_type": {"dummy_device2": "000000002"}}, } first_fetch = "24 hours" queries_dict = { "X_log_type": "(receive_time geq '2021/01/01 08:00:00)", "Y_log_type": "(receive_time geq '2021/01/01 08:00:00)", } max_fetch = {"X_log_type": 10} X_log_type_raw_entries = [ {"seqno": "000000002", "type": "X_log_type", "time_generated": "2022-01-01 13:00:00", "device_name": "dummy_device1"} ] Y_log_type_raw_entries = [ {"seqno": "000000003", "type": "Y_log_type", "time_generated": "2022-01-01 13:00:00", "device_name": "dummy_device2"} ] fetch_incidents_request_result = {"X_log_type": X_log_type_raw_entries, "Y_log_type": Y_log_type_raw_entries} expected_parsed_incident_entries = [ { "name": "dummy_device1 000000002", "occurred": "2022-01-01T13:00:00Z", "rawJSON": json.dumps(X_log_type_raw_entries[0]), }, { "name": "dummy_device2 000000003", "occurred": "2022-01-01T13:00:00Z", "rawJSON": json.dumps(Y_log_type_raw_entries[0]), }, ] fetch_start_datetime_dict = { "X_log_type": dateparser.parse("2022/1/1 11:00:00", settings={"TIMEZONE": "UTC"}), "Y_log_type": dateparser.parse("2022/1/1 11:00:00", settings={"TIMEZONE": "UTC"}), } mocker.patch("Panorama.fetch_incidents_request", return_value=fetch_incidents_request_result) mocker.patch("Panorama.get_fetch_start_datetime_dict", return_value=fetch_start_datetime_dict) new_last_run, incident_entries_dict = fetch_incidents(last_run, first_fetch, queries_dict, max_fetch, 5) assert incident_entries_dict == expected_parsed_incident_entries assert new_last_run["last_fetch_dict"].get("X_log_type", "") == "2022-01-01 13:00:00" assert new_last_run["last_id_dict"].get("X_log_type", "") == {"dummy_device1": "000000002"} assert new_last_run["last_fetch_dict"].get("Y_log_type", "") == "2022-01-01 13:00:00" assert new_last_run["last_id_dict"].get("Y_log_type", "") == {"dummy_device2": "000000003"} def test_find_largest_id_per_device(mocker): """ Given: - list of dictionaries representing raw entries, some contain seqno and some don't, some contain device_name and When: - find_largest_id_per_device is called. Then: - return a dictionary with the largest id per device and skip entries that don't contain seqno or device_name. """ raw_entries = [ {"device_name": "dummy_device1", "seqno": "000000001"}, {"device_name": "dummy_device1", "seqno": "000000002"}, {"device_name": "dummy_device2", "seqno": "000000001"}, {"device_name": "dummy_device7"}, {"seqno": "000000008"}, ] from Panorama import find_largest_id_per_device res = find_largest_id_per_device(raw_entries) assert res == {"dummy_device1": "000000002", "dummy_device2": "000000001"} def test_filter_fetched_entries(mocker): """ Given: - list of dictionaries representing raw entries with seqno, device_name, and time_generated fields - dictionary with the largest id per device (id_dict) - dictionary with last fetch times per log type (last_fetch_dict) When: - filter_fetched_entries is called with the new timestamp-based filtering logic Then: - return a dictionary with entries filtered based on: 1. Logs with time_generated > last_fetch_time are always kept (no seqno comparison) 2. Logs with time_generated == last_fetch_time are kept only if seqno > last_id 3. Logs missing required fields (seqno, device_name, time_generated) are skipped 4. Correlation logs are filtered by @logid instead of seqno """ from Panorama import LastFetchTimes, LastIDs, filter_fetched_entries # Test case 1: Regular log types with timestamp-based filtering raw_entries = { "log_type1": [ # Missing time_generated - should be skipped {"device_name": "dummy_device1", "seqno": "000000001"}, # time_generated > last_fetch_time - should be kept regardless of seqno {"device_name": "dummy_device1", "seqno": "000000002", "time_generated": "2022-01-01 14:00:00"}, # time_generated == last_fetch_time, seqno > last_id - should be kept {"device_name": "dummy_device2", "seqno": "000000002", "time_generated": "2022-01-01 13:00:00"}, # time_generated == last_fetch_time, seqno <= last_id - should be filtered out {"device_name": "dummy_device2", "seqno": "000000001", "time_generated": "2022-01-01 13:00:00"}, ], "log_type2": [ # New log type with no previous fetch - should be kept {"device_name": "dummy_device3", "seqno": "000000004", "time_generated": "2022-01-01 12:00:00"}, # Missing device_name - should be skipped {"seqno": "000000007", "time_generated": "2022-01-01 12:00:00"}, ], } id_dict = LastIDs( log_type1={"dummy_device1": "000000003", "dummy_device2": "000000001"} # type: ignore[typeddict-item] ) last_fetch_dict = LastFetchTimes( log_type1="2022-01-01 13:00:00" # type: ignore[typeddict-item] ) res = filter_fetched_entries(raw_entries, id_dict, last_fetch_dict) # Expected: only entries that pass the new filtering logic assert res == { "log_type1": [ # Entry with time_generated > last_fetch_time (14:00 > 13:00) {"device_name": "dummy_device1", "seqno": "000000002", "time_generated": "2022-01-01 14:00:00"}, # Entry with time_generated == last_fetch_time and seqno (2) > last_id (1) {"device_name": "dummy_device2", "seqno": "000000002", "time_generated": "2022-01-01 13:00:00"}, ], "log_type2": [ # New log type - all valid entries are kept {"device_name": "dummy_device3", "seqno": "000000004", "time_generated": "2022-01-01 12:00:00"} ], } # Test case 2: Correlation log type (uses @logid instead of seqno) corr_entries = { "Correlation": [ {"@logid": "1", "match_time": "2022-01-01 12:00:00"}, {"@logid": "2", "match_time": "2022-01-01 13:00:00"}, {"@logid": "3", "match_time": "2022-01-01 14:00:00"}, ] } corr_id_dict = LastIDs(Correlation=1) # type: ignore[typeddict-item] corr_last_fetch_dict = LastFetchTimes() corr_res = filter_fetched_entries(corr_entries, corr_id_dict, corr_last_fetch_dict) # Expected: only entries with @logid > 1 assert corr_res == { "Correlation": [ {"@logid": "2", "match_time": "2022-01-01 13:00:00"}, {"@logid": "3", "match_time": "2022-01-01 14:00:00"}, ] } @pytest.mark.parametrize("name_match, name_contain, filters, expected_result", mock_rules.get_mock_rules_and_application) def test_build_xpath_filter(name_match, name_contain, filters, expected_result): from Panorama import build_xpath_filter mock_result = build_xpath_filter(name_match, name_contain, filters) assert mock_result == expected_result @pytest.mark.parametrize( "sample_file, expected_result_file", [ ("test_data/prettify_edls_arr_sample.json", "test_data/prettify_edls_arr_expected_result.json"), ], ) def test_prettify_edls_arr(sample_file, expected_result_file): """ Given: - raw response from api represented by a dictionary When: - calling panorama_list_edls and there is only one edl in response Then: - assert that the returned value after prettify is correct """ from Panorama import prettify_edls_arr with open(sample_file) as f: sample = json.loads(f.read()) with open(expected_result_file) as f: expected_result = json.loads(f.read()) mock_result = prettify_edls_arr(sample) assert mock_result == expected_result def test_panorama_list_rules(): import Panorama Panorama.URL = "https://1.1.1.1:443/" Panorama.API_KEY = "thisisabogusAPIKEY!" mock_version_xml = """ <response status="success" code="19"> <result total-count="1" count="1"> <entry name="hehe 2"> <to> <member>any</member> </to> <from> <member>any</member> </from> <source> <member>any</member> </source> <destination> <member>any</member> </destination> <source-user> <member>any</member> </source-user> <category> <member>any</member> </category> <application> <member>dns</member> <member>http</member> </application> <service> <member>application-default</member> </service> <hip-profiles> <member>any</member> </hip-profiles> <action>allow</action> </entry> </result> </response> """ xpath = "/config/devices/entry/vsys/entry[@name='vsys1']/rulebase/security/rules/entry" query = "(application/member eq 'dns')" with requests_mock.Mocker() as m: mock_request = m.get("https://1.1.1.1:443", text=mock_version_xml, status_code=200) rules = Panorama.panorama_list_rules(xpath, query=query) assert rules["application"]["member"][0] == "dns" assert ( mock_request.last_request.qs["xpath"][0] == "/config/devices/entry/vsys/entry[@name='vsys1']/rulebase/security/rules/entry[(application/member = 'dns')]" ) def test_prettify_rules(): """ Given: - rule entry. When: - Running the prettify_rules method. Then: - Ensure no errors are raised. """ from Panorama import prettify_rules test_rule = { "@name": "test", "@uuid": "11111-111-111-11", "source": {"@loc": "test", "member": [{"@loc": "test", "#text": "text"}, "Failing String"]}, } prettier_rules = prettify_rules(test_rule) assert "Failing String" in prettier_rules[0].get("Source") @pytest.mark.parametrize("include_shared", ["No", "Yes"]) def test_panorama_list_tags(mocker, include_shared): """ Given: - The include_shared argument. When: - Running the pan_os_list_tag_command method. Then: - Ensure the returned tags list output and HR table is as expected. """ import Panorama import requests Panorama.URL = "https://1.1.1.1:443/" Panorama.API_KEY = "thisisabogusAPIKEY!" Panorama.DEVICE_GROUP = "" tags_response_xml = """<response status="success" code="19"><result total-count="1" count="1"> <tag admin="admin" dirtyId="6" time="2023/05/28 06:51:22"> <entry name="tag1"> <color>color13</color> </entry> <entry name="tag2"> <color>color39</color> </entry> <entry name="tag3"> <color>color39</color> <disable-override>no</disable-override> <comments>text text text</comments> </entry></tag></result></response>""" shared_tags_response_xml = """<response status="success" code="19"><result total-count="1" count="1"> <tag admin="admin" dirtyId="6" time="2023/05/28 06:51:22"> <entry name="sharedtag1"> <color>color15</color> </entry> <entry name="sharedtag2"> <color>color34</color> </entry></tag></result></response>""" tags_mock_response = MockedResponse(text=tags_response_xml, status_code=200) shared_tags_mock_response = MockedResponse(text=shared_tags_response_xml, status_code=200) mocker.patch.object(requests, "request", side_effect=[tags_mock_response, shared_tags_mock_response]) expected_outputs_tags_list = [ {"name": "tag1", "color": "color13", "location": ""}, {"name": "tag2", "color": "color39", "location": ""}, {"name": "tag3", "color": "color39", "location": "", "disable-override": "no", "comments": "text text text"}, ] expected_hr_result = ( "### Tags:\n|Name|Color|Comment|Location|\n|---|---|---|---|\n| tag1 | color13" " | | |\n| tag2 | color39 | | |\n| tag3 | color39 | text text text | |\n" ) if include_shared == "Yes": expected_outputs_tags_list.extend( [ {"name": "sharedtag1", "color": "color15", "location": "shared"}, {"name": "sharedtag2", "color": "color34", "location": "shared"}, ] ) expected_hr_result += "| sharedtag1 | color15 | | shared |\n| sharedtag2 | color34 | | shared |\n" command_results = Panorama.pan_os_list_tag_command({"include_shared_tags": include_shared}) assert command_results.outputs == expected_outputs_tags_list assert command_results.readable_output == expected_hr_result def test_pan_os_create_tag_command(mocker): """ Given: - The tag name to create. When: - Running the pan_os_create_tag_command method. Then: - Ensure the returned response and readable outputs is as expected. """ import Panorama import requests Panorama.URL = "https://1.1.1.1:443/" Panorama.API_KEY = "thisisabogusAPIKEY!" expected_text_response = '<response status="success" code="20"><msg>command succeeded</msg></response>' create_tag_mock_response = MockedResponse(text=expected_text_response, status_code=200) mocker.patch.object(requests, "request", return_value=create_tag_mock_response) command_results = Panorama.pan_os_create_tag_command({"name": "testtag"}) assert command_results.raw_response == {"response": {"@status": "success", "@code": "20", "msg": "command succeeded"}} assert command_results.readable_output == 'The tag with name "testtag" was created successfully.' @pytest.mark.parametrize("is_shared", [False, True]) def test_pan_os_edit_tag_command(mocker, is_shared): """ Given: - The command arguments to edit the tag. When: 1. The tag is not in a shared device group. 2. The tag is in a shared device group. - Running the pan_os_edit_tag_command method. Then: - Ensure the request method call counts is according to if the tag is shared. - Ensure the returned response and readable outputs is as expected. """ import Panorama import requests Panorama.URL = "https://1.1.1.1:443/" Panorama.API_KEY = "thisisabogusAPIKEY!" expected_first_text_response_if_shared = ( '<response status="error" code="12"><msg><line>Edit breaks config validity</line></msg></response>' ) expected_text_response = '<response status="success" code="20"><msg>command succeeded</msg></response>' expected_list_text_response = """<response status="success" code="19"><result total-count="1" count="1"> <tag admin="admin" dirtyId="6" time="2023/05/28 06:51:22"> <entry name="testtag"> <color>color39</color> <disable-override>no</disable-override> <comments>text text text</comments> </entry></tag></result></response>""" expected_request_count = 4 if is_shared else 3 edit_tag_mock_response = MockedResponse(text=expected_text_response, status_code=200) edit_tag_first_mock_response = MockedResponse(text=expected_first_text_response_if_shared, status_code=200) list_tag_mr = MockedResponse(text=expected_list_text_response, status_code=200) responses = ( [list_tag_mr, list_tag_mr, edit_tag_first_mock_response, edit_tag_mock_response] if is_shared else [list_tag_mr, list_tag_mr, edit_tag_mock_response] ) request_mocker = mocker.patch.object(requests, "request", side_effect=responses) command_results = Panorama.pan_os_edit_tag_command({"name": "testtag", "new_name": "newtesttag"}) assert request_mocker.call_count == expected_request_count assert command_results.raw_response == {"response": {"@status": "success", "@code": "20", "msg": "command succeeded"}} assert command_results.readable_output == 'The tag with name "testtag" was edited successfully.' @pytest.mark.parametrize("is_shared", [False, True]) def test_pan_os_delete_tag_command(mocker, is_shared): """ Given: - The tag name to delete. When: 1. The tag is not in a shared device group. 2. The tag is in a shared device group. - Running the pan_os_delete_tag_command method. Then: - Ensure the request method call counts is according to if the tag is shared. - Ensure the returned response and readable outputs is as expected. """ import Panorama import requests Panorama.URL = "https://1.1.1.1:443/" Panorama.API_KEY = "thisisabogusAPIKEY!" Panorama.DEVICE_GROUP = "somedevice" expected_first_text_response_if_shared = '<response status="success" code="7"><msg>Object doesn\'t exist</msg></response>' expected_second_text_response_if_shared = ( '<response status="success" code="19"><result total-count="2" count="2">' '<entry name="somedevice"></entry></result></response>' ) expected_text_response = '<response status="success" code="20"><msg>command succeeded</msg></response>' expected_request_count = 3 if is_shared else 1 delete_tag_mock_response = MockedResponse(text=expected_text_response, status_code=200) delete_tag_first_mock_response = MockedResponse(text=expected_first_text_response_if_shared, status_code=200) delete_tag_second_mock_response = MockedResponse(text=expected_second_text_response_if_shared, status_code=200) responses = ( [delete_tag_first_mock_response, delete_tag_second_mock_response, delete_tag_mock_response] if is_shared else [delete_tag_mock_response] ) request_mocker = mocker.patch.object(requests, "request", side_effect=responses) command_results = Panorama.pan_os_delete_tag_command({"name": "testtag", "new_name": "newtesttag"}) assert request_mocker.call_count == expected_request_count assert command_results.raw_response == {"response": {"@status": "success", "@code": "20", "msg": "command succeeded"}} assert command_results.readable_output == 'The tag with name "testtag" was deleted successfully.' @pytest.mark.parametrize( "device_group, vsys, args, expected_response", [ ( "device_group", "", {"disable_override": True, "comment": ""}, "<disable-override>yes</disable-override><comments></comments>", ), ("", "vsys1", {"disable_override": True, "comment": ""}, "<comments></comments>"), ], ) def test_build_tag_element(mocker, device_group, vsys, args, expected_response): """ Given: - given the disable_override argument that isn't supported with Firewall instances When: - Running the build_tag_element function Then: - Ensure that the expected response matches the actual response. (ignoring the disable_override argument when using Firewall instances) """ from Panorama import build_tag_element mocker.patch("Panorama.DEVICE_GROUP", device_group) mocker.patch("Panorama.VSYS", vsys) response = build_tag_element(**args) assert response == expected_response @pytest.mark.parametrize( ( "element_to_change, context_element, element_value, current_objects_items, params_element, " "expected_exception, expected_warning, expected_warning_exit" ), [ ("tag", "Tags", ["tag3"], ["tag3"], "<tag></tag>", False, False, False), # Last tag ("tag", "Tags", ["tag2"], ["tag3", "tag2"], "<tag><member>tag3</member></tag>", False, False, False), # Not last tag ("tag", "Tags", ["nonexistent_tag"], ["tag1"], "", False, True, True), # Non-existent tag > exit ( "tag", "Tags", ["nonexistent_tag", "tag1"], ["tag1"], "<tag></tag>", False, True, False, ), # Non-existent tag & existent > warning ("source", "Source", ["source"], ["source"], "", True, False, False), # raise exception ], ) def test_panorama_edit_rule_items_remove( mocker, element_to_change, context_element, element_value, current_objects_items, params_element, expected_exception, expected_warning, expected_warning_exit, ): """ Given: - element_to_change: The element to be changed in the rule. - element_value: The value(s) to be removed from the element. - current_objects_items: The current items present in the element. - params_element: The expected element value in the request body. - expected_exception: Flag indicating whether an exception is expected to be raised. - expected_warning: Flag indicating whether a warning is expected to be returned. - expected_warning_exit: Flag indicating whether the warning is expected to trigger an exit. When: - Running the panorama_edit_rule_items function to remove element from rule. Then: - Ensure that the expected response matches the actual response. - If expected_exception is True, assert that the correct exception is raised. - If expected_warning is True, assert that the correct warning message is returned. - If expected_warning_exit is True, assert that the warning triggers an exit. - If expected_warning_exit is False, assert the correct values in the request body, the success message, and the call to return_results. """ from Panorama import panorama_edit_rule_items mocker.patch("Panorama.VSYS", "vsys1") mocker.patch("Panorama.DEVICE_GROUP", "") mocker.patch("Panorama.panorama_get_current_element", return_value=current_objects_items) mock_return_warning = mocker.patch("Panorama.return_warning") request_mock = mocker.patch("Panorama.http_request", return_value=TestPanoramaEditRuleCommand.EDIT_SUCCESS_RESPONSE) return_results_mock = mocker.patch("Panorama.return_results") if expected_exception: with pytest.raises(Exception, match=f"The object: {element_to_change} must have at least one item."): panorama_edit_rule_items("rulename", element_to_change, element_value, "remove") else: panorama_edit_rule_items("rulename", element_to_change, element_value, "remove") if expected_warning: mock_return_warning.assert_called_once_with( "The following tags do not exist: nonexistent_tag", exit=expected_warning_exit ) if not expected_warning_exit: assert request_mock.call_args.kwargs["body"]["action"] == "edit" assert request_mock.call_args.kwargs["body"]["element"] == params_element assert return_results_mock.call_args[0][0]["HumanReadable"] == "Rule edited successfully." assert isinstance( return_results_mock.call_args[0][0]["EntryContext"]["Panorama.SecurityRule(val.Name == obj.Name)"][ context_element ], list, ) def test_list_device_groups_names(mocker): from Panorama import list_device_groups_names mocker.patch("Panorama.get_device_groups_names", return_value=["Test-Device", "Test-Device-2"]) result = list_device_groups_names() assert result.outputs == ["Test-Device", "Test-Device-2"] assert result.readable_output == "### Device Group Names:\n|Group Name|\n|---|\n| Test-Device |\n| Test-Device-2 |\n" def test_panorama_list_security_profile_group_command(mocker): """ Given: - A Panorama instance with security profile groups. When: - Running the pan_os_list_security_profile_group_command. Then: - Ensure the returned security profile groups list output and HR table is as expected. """ import Panorama import requests Panorama.URL = "https://1.1.1.1:443/" Panorama.API_KEY = "thisisabogusAPIKEY!" Panorama.DEVICE_GROUP = "" tags_response_xml = """<response status="success" code="19"><result total-count="2" count="2"> <entry name="test1" loc=""> <virus><member>default</member></virus><spyware><member>default</member></spyware> <vulnerability><member>default</member></vulnerability><url-filtering><member>default</member></url-filtering> </entry> <entry name="test2" loc=""> <virus><member>default</member></virus><spyware><member>default</member></spyware> <vulnerability><member>default</member></vulnerability><url-filtering><member>default</member></url-filtering> <wildfire-analysis><member>test wildfire analysis</member></wildfire-analysis><file-blocking> <member>basic file blocking</member></file-blocking><data-filtering><member>test data filtering</member></data-filtering> </entry> </result></response>""" mock_response = MockedResponse(text=tags_response_xml, status_code=200) mocker.patch.object(requests, "request", return_value=mock_response) expected_outputs_tags_list = [ { "virus": "default", "spyware": "default", "vulnerability": "default", "url-filtering": "default", "name": "test1", "location": "", }, { "virus": "default", "spyware": "default", "vulnerability": "default", "url-filtering": "default", "wildfire-analysis": "test wildfire analysis", "file-blocking": "basic file blocking", "data-filtering": "test data filtering", "name": "test2", "location": "", }, ] expected_hr_result = ( "### Security Profile Groups:\n|Name|Location|Antivirus Profile|Anti-Spyware Profile|Vulnerability " "Protection Profile|URL Filtering Profile|File Blocking Profile|Data Filtering Profile|WildFire " "Analysis Profile|\n|---|---|---|---|---|---|---|---|---|\n| test1 | | default | default | default | " "default | | | |\n| test2 | | default | default | default | default | basic file blocking | test " "data filtering | test wildfire analysis |\n" ) command_results = Panorama.pan_os_list_security_profile_groups_command({}) assert command_results.outputs == expected_outputs_tags_list assert command_results.readable_output == expected_hr_result def test_pan_os_create_security_profile_group_command(mocker): """ Given: - The security profile groups name to create. When: - Running the pan_os_create_security_profile_group_command. Then: - Ensure the returned response and readable outputs is as expected. """ import Panorama import requests Panorama.URL = "https://1.1.1.1:443/" Panorama.API_KEY = "thisisabogusAPIKEY!" expected_text_response = '<response status="success" code="20"><msg>command succeeded</msg></response>' mock_response = MockedResponse(text=expected_text_response, status_code=200) mocker.patch.object(requests, "request", return_value=mock_response) command_results = Panorama.pan_os_create_security_profile_group_command({"group_name": "test_spg"}) assert command_results.raw_response == {"response": {"@status": "success", "@code": "20", "msg": "command succeeded"}} assert command_results.readable_output == 'Successfully created Security Profile Group: "test_spg"' def test_pan_os_edit_security_profile_group_command(mocker): """ Given: - The profile_to_change and the value arguments to edit in the security profile groups. When: - Running the pan_os_edit_security_profile_group_command. Then: - Ensure the returned response and readable outputs is as expected. """ import Panorama import requests Panorama.URL = "https://1.1.1.1:443/" Panorama.API_KEY = "thisisabogusAPIKEY!" expected_text_response = '<response status="success" code="20"><msg>command succeeded</msg></response>' mock_response = MockedResponse(text=expected_text_response, status_code=200) mocker.patch.object(requests, "request", return_value=mock_response) command_results = Panorama.pan_os_edit_security_profile_group_command({"group_name": "test_spg"}) assert command_results.raw_response == {"response": {"@status": "success", "@code": "20", "msg": "command succeeded"}} assert command_results.readable_output == 'Successfully edited Security Profile Group: "test_spg"' def test_pan_os_delete_security_profile_group_command(mocker): """ Given: - The security profile groups name to delete. When: - Running the pan_os_delete_security_profile_group_command. Then: - Ensure the returned response and readable outputs is as expected. """ import Panorama import requests Panorama.URL = "https://1.1.1.1:443/" Panorama.API_KEY = "thisisabogusAPIKEY!" Panorama.DEVICE_GROUP = "somedevice" expected_text_response = '<response status="success" code="20"><msg>command succeeded</msg></response>' mock_response = MockedResponse(text=expected_text_response, status_code=200) mocker.patch.object(requests, "request", return_value=mock_response) command_results = Panorama.pan_os_delete_security_profile_group_command({"group_name": "test_spg"}) assert command_results.raw_response == {"response": {"@status": "success", "@code": "20", "msg": "command succeeded"}} assert command_results.readable_output == 'Successfully deleted Security Profile Group: "test_spg"' @pytest.mark.parametrize( "profile_name, profile_type, device_group, action, threat_id, expected_xpath", [ # test cases for device_group ( "name", "vulnerability", "device_group", "set", "1000", ( "/config/devices/entry[@name='localhost.localdomain']" "/device-group/entry[@name='device_group']" "/profiles/vulnerability/entry[@name='name']/threat-exception" ), ), ( "name", "spyware", "device_group", "set", "1000", ( "/config/devices/entry[@name='localhost.localdomain']" "/device-group/entry[@name='device_group']" "/profiles/spyware/entry[@name='name']/threat-exception" ), ), # test case for VSYS ( "name", "vulnerability", None, "set", "1000", ( "/config/devices/entry[@name='localhost.localdomain']" "/vsys/entry[@name='vsys']" "/profiles/vulnerability/entry[@name='name']/threat-exception" ), ), ( "name", "spyware", None, "set", "1000", ( "/config/devices/entry[@name='localhost.localdomain']" "/vsys/entry[@name='vsys']" "/profiles/spyware/entry[@name='name']/threat-exception" ), ), # test case for EDIT action type ( "name", "spyware", "device_group", "edit", "1000", ( "/config/devices/entry[@name='localhost.localdomain']" "/device-group/entry[@name='device_group']" "/profiles/spyware/entry[@name='name']/threat-exception" "/entry[@name='1000']" ), ), ( "name", "vulnerability", "device_group", "edit", "1000", ( "/config/devices/entry[@name='localhost.localdomain']" "/device-group/entry[@name='device_group']" "/profiles/vulnerability/entry[@name='name']/threat-exception" "/entry[@name='1000']" ), ), # test case for DELETE action type ( "name", "vulnerability", "device_group", "delete", "1000", ( "/config/devices/entry[@name='localhost.localdomain']" "/device-group/entry[@name='device_group']" "/profiles/vulnerability/entry[@name='name']/threat-exception" "/entry[@name='1000']" ), ), ( "name", "spyware", "device_group", "delete", "1000", ( "/config/devices/entry[@name='localhost.localdomain']" "/device-group/entry[@name='device_group']" "/profiles/spyware/entry[@name='name']/threat-exception" "/entry[@name='1000']" ), ), ( "name", "spyware", None, "delete", "1000", ( "/config/devices/entry[@name='localhost.localdomain']" "/vsys/entry[@name='vsys']" "/profiles/spyware/entry[@name='name']/threat-exception" "/entry[@name='1000']" ), ), ], ) def test_pan_os_xpath_creation_for_exception_crud(profile_name, profile_type, device_group, action, threat_id, expected_xpath): """ Given: - A profile name, profile type, device group name, action, and threat ID. When: - Running build_xpath_for_profile_exception_commands function to generate the XPath. Then: - Ensure the returned XPath is correctly constructed for both Vulnerability Protection and Anti Spyware profiles. """ import Panorama Panorama.VSYS = "vsys" result = Panorama.build_xpath_for_profile_exception_commands(profile_name, profile_type, device_group, action, threat_id) assert result == expected_xpath def test_pan_os_check_profile_type_by_given_profile_name(mocker): """ Given: - A profile name that could exist in either 'Vulnerability Protection Profile' or 'Anti Spyware Profile'. When: - Checking the profile type by the given profile name. Then: - Ensure the correct profile type is returned or an appropriate exception is raised. """ import Panorama mocker.patch( "Panorama.get_all_profile_names_from_profile_type", side_effect=[ ["profile_1", "profile_2"], ["profile_3", "profile_4"], [], ["profile_3"], ["profile_5"], ["profile_5"], [], [], ], ) result = Panorama.check_profile_type_by_given_profile_name("profile_1", "device_group") assert result == "vulnerability" result = Panorama.check_profile_type_by_given_profile_name("profile_3", None) assert result == "spyware" with pytest.raises( DemistoException, match="Profile name was found both in Vulnerability Protection Profiles " "and in Anti Spyware Profiles. Please specify profile_type.", ): Panorama.check_profile_type_by_given_profile_name("profile_5", "device_group") with pytest.raises( DemistoException, match="Profile name was not found in Vulnerability Protection Profiles or in Anti Spyware Profiles." ): Panorama.check_profile_type_by_given_profile_name("profile_6", "device_group") def test_pan_os_get_threat_id_from_predefined_threats(mocker): """ Given: - A threat name that may match a threat name, ID, or CVE in the predefined threats list. When: - Searching for the threat ID using the provided threat name. Then: - Ensure the correct threat ID, name, and CVEs are returned, or an appropriate exception is raised. """ import Panorama mock_predefined_threats = [ {"@name": "10003", "threatname": "Test Threat 1", "cve": {"member": ["CVE-2023-1234"]}}, {"@name": "10004", "threatname": "Test Threat 2", "cve": {"member": ["CVE-2023-5678"]}}, {"@name": "10005", "threatname": "Test Threat 3", "cve": {"member": ["CVE-2023-9012"]}}, ] mocker.patch.object(Panorama, "get_predefined_threats_list", return_value=mock_predefined_threats) result = Panorama.get_threat_id_from_predefined_threats("Test Threat 1") assert result == ("10003", "Test Threat 1", ["CVE-2023-1234"]) result = Panorama.get_threat_id_from_predefined_threats("10004") assert result == ("10004", "Test Threat 2", ["CVE-2023-5678"]) result = Panorama.get_threat_id_from_predefined_threats("CVE-2023-9012") assert result == ("10005", "Test Threat 3", ["CVE-2023-9012"]) with pytest.raises(DemistoException, match="Threat was not found."): Panorama.get_threat_id_from_predefined_threats("Nonexistent Threat") def test_pan_os_add_profile_exception(mocker): """ Given: - A profile name, profile type, threat name, and device group. When: - Running the `pan_os_add_profile_exception_command` to add an exception to a security profile. Then: - Ensure the returned response indicates the successful creation of the exception with the correct threat name and ID. """ import Panorama mock_response = {"response": {"@status": "success", "@code": "20", "msg": "command succeeded"}} mocker.patch.object(Panorama, "http_request", return_value=mock_response) mocker.patch.object(Panorama, "get_threat_id_from_predefined_threats", return_value=("1000", "threatname", "cve")) command_results = Panorama.pan_os_add_profile_exception_command( args={ "profile_name": "test_spg", "threat_name": "1000", "profile_type": "Vulnerability Protection Profile", "device_group": "device_group", } ) assert command_results.raw_response == {"response": {"@status": "success", "@code": "20", "msg": "command succeeded"}} assert command_results.readable_output == ( 'Successfully created exception "threatname" with threat ID 1000 in the "test_spg" profile of type "vulnerability".' ) def test_pan_os_edit_profile_exception(mocker): """ Given: - A profile name, profile type, threat name, and device group. When: - Running the `pan_os_edit_profile_exception_command` to edit an exception in a security profile. Then: - Ensure the returned response indicates the successful editing of the exception with the correct threat name and ID. """ import Panorama Panorama.URL = "https://1.1.1.1:443/" Panorama.API_KEY = "thisisabogusAPIKEY!" Panorama.DEVICE_GROUP = "device_group" mock_response = {"response": {"@status": "success", "@code": "20", "msg": "command succeeded"}} mocker.patch.object(Panorama, "http_request", return_value=mock_response) mocker.patch.object(Panorama, "get_threat_id_from_predefined_threats", return_value=("1000", "threatname", "cve")) command_results = Panorama.pan_os_edit_profile_exception_command( args={ "profile_name": "test_spg", "threat_name": "1000", "profile_type": "Vulnerability Protection Profile", "device_group": "device_group", } ) assert command_results.raw_response == {"response": {"@status": "success", "@code": "20", "msg": "command succeeded"}} assert command_results.readable_output == ( 'Successfully edited exception "threatname" with threat ID 1000 in the "test_spg" profile of type "vulnerability".' ) def test_pan_os_delete_profile_exception(mocker): """ Given: - A profile name, profile type, threat name, and device group. When: - Running the `pan_os_delete_profile_exception_command` to delete an exception from a security profile. Then: - Ensure the returned response indicates the successful deletion of the exception with the correct threat name and ID. """ import Panorama mock_response = {"response": {"@status": "success", "@code": "20", "msg": "command succeeded"}} mocker.patch.object(Panorama, "http_request", return_value=mock_response) mocker.patch.object(Panorama, "get_threat_id_from_predefined_threats", return_value=("1000", "threatname", "cve")) command_results = Panorama.pan_os_delete_profile_exception_command( args={ "profile_name": "test_spg", "threat_name": "1000", "profile_type": "Vulnerability Protection Profile", "device_group": "device_group", } ) assert command_results.raw_response == {"response": {"@status": "success", "@code": "20", "msg": "command succeeded"}} assert command_results.readable_output == ( 'Successfully deleted exception "threatname" with threat ID 1000 in the "test_spg" profile of type "vulnerability".' ) def test_pan_os_list_profile_exception(mocker): """ Given: - A profile name and profile type. When: - Running the `pan_os_list_profile_exception_command` to list exceptions in a security profile. Then: - Ensure the returned response is of type `CommandResults` and the readable output lists the correct profile exceptions. """ import Panorama Panorama.URL = "https://1.1.1.1:443/" Panorama.API_KEY = "thisisabogusAPIKEY!" Panorama.DEVICE_GROUP = "device_group" mocker.patch.object( Panorama, "profile_exception_crud_requests", return_value=( { "raw_response": { "response": { "result": { "threat-exception": { "entry": [ { "@name": "10003", "action": {"block": {}}, "exempt-ip": {"entry": {"@name": "192.168.1.1"}}, "packet-capture": "yes", "@admin": "admin1", "@dirtyId": "dirty1", "@time": "2024-08-14T12:00:00", }, { "@name": "10002", "action": {"allow": {}}, "packet-capture": "no", "@admin": "admin2", "@dirtyId": "dirty2", "@time": "2024-08-14T12:00:00", }, ] } } }, }, "exception_id": "id", "exception_name": "name", "profile_type": "vulnerability", } ), ) mocker.patch.object(Panorama, "get_threat_id_from_predefined_threats", return_value=("test", "threatname", "cve")) args = {"profile_name": "test_profile", "profile_type": "Vulnerability Protection Profile"} result = Panorama.pan_os_list_profile_exception_command(args) assert isinstance(result, CommandResults) expected_hr = [ { "ID": "10003", "Name": "threatname", "CVE": "cve", "Action": "block", "Exempt IP": "192.168.1.1", "Packet Capture": "yes", }, { "ID": "10002", "Name": "threatname", "CVE": "cve", "Action": "allow", "Exempt IP": "", "Packet Capture": "no", }, ] expected_output = { "Name": "test_profile", "Exception": [ { "id": "10003", "name": "threatname", "CVE": "cve", "action": "block", "packet-capture": "yes", "exempt-ip": "192.168.1.1", }, { "id": "10002", "name": "threatname", "CVE": "cve", "action": "allow", "packet-capture": "no", }, ], } assert "Profile Exceptions" in result.readable_output for hr_entry in expected_hr: for _, value in hr_entry.items(): assert value in result.readable_output assert result.outputs == expected_output assert result.outputs_prefix == "Panorama.Vulnerability" assert result.outputs_key_field == "Name" def test_fetch_incidents_correlation(mocker: MockerFixture): """ Given: - When: - Then: - """ from Panorama import LastFetchTimes, LastIDs, LastRun, MaxFetch, QueryMap, fetch_incidents corr_logs = load_json("test_data/corr_logs.json") mock_get_query_entries = mocker.patch("Panorama.get_query_entries") last_fetch_dict = LastFetchTimes(Correlation="2024/04/08 07:22:54") last_id_dict = LastIDs(Correlation=0) max_fetch_dict = MaxFetch(Correlation=10) last_run = LastRun(last_fetch_dict=last_fetch_dict, last_id_dict=last_id_dict, max_fetch_dict=max_fetch_dict) # assert duplicates are removed: mock_get_query_entries.return_value = corr_logs[:5] _, entries = fetch_incidents(last_run, "2024/04/08 07:22:54", QueryMap(Correlation="query"), max_fetch_dict, 1) assert entries[0]["name"] == "Correlation 1" assert "CORRELATION" in entries[0]["rawJSON"] assert mock_get_query_entries.call_args_list[0].args == ( "Correlation", "(query) and (match_time geq '2024/04/08 07:22:54')", 10, 1, 0, ) # asserting that "match_time" is used instead of "time_generated". assert last_fetch_dict == LastFetchTimes(Correlation="2024-04-09 07:22:54") # the max date assert last_id_dict == LastIDs(Correlation=4) assert max_fetch_dict == MaxFetch(Correlation=10) # test with dict from older versions last_id_dict["Correlation"] = cast(int, {}) _, entries = fetch_incidents(last_run, "2024/04/08 07:22:54", QueryMap(Correlation="query"), max_fetch_dict, 1) assert entries[0]["name"] == "Correlation 1" def test_fetch_incidents_offset(mocker: MockerFixture): """ Given: Panorama incidents. When: Using fetch-incidents command using offset to get the next incidents. Then: Assert the correct amount of incidents were fetched and the correct offset value was stored. """ from Panorama import LastFetchTimes, LastIDs, LastRun, MaxFetch, Offset, QueryMap, fetch_incidents corr_logs = load_json("test_data/corr_logs_time_dif.json") mock_get_query_entries = mocker.patch("Panorama.get_query_entries") last_fetch_dict = LastFetchTimes(Correlation="2024/04/08 07:22:54") last_id_dict = LastIDs() max_fetch_dict = MaxFetch(Correlation=5) offset_dict = Offset(Correlation=0) last_run = LastRun( last_fetch_dict=last_fetch_dict, last_id_dict=last_id_dict, max_fetch_dict=max_fetch_dict, offset_dict=offset_dict ) # assert duplicates are removed: mock_get_query_entries.return_value = corr_logs[:5] new_last_run, entries = fetch_incidents(last_run, "2024/04/08 07:22:54", QueryMap(Correlation="query"), max_fetch_dict, 1) assert entries[0]["name"] == "Correlation 1" assert "CORRELATION" in entries[0]["rawJSON"] assert mock_get_query_entries.call_args_list[0].args == ( "Correlation", "(query) and (match_time geq '2024/04/08 07:22:54')", 5, 1, 0, ) # asserting that "match_time" is used instead of "time_generated". assert last_fetch_dict == LastFetchTimes(Correlation="2024-04-08 07:22:54") # the max date assert last_id_dict == LastIDs(Correlation=5) assert max_fetch_dict == MaxFetch(Correlation=5) assert offset_dict == Offset(Correlation=5) mock_get_query_entries.return_value = corr_logs[5:] new_last_run, entries = fetch_incidents(new_last_run, "2024/04/08 07:22:54", QueryMap(Correlation="query"), max_fetch_dict, 1) assert entries[0]["name"] == "Correlation 6" assert "CORRELATION" in entries[0]["rawJSON"] assert mock_get_query_entries.call_args_list[1].args == ( "Correlation", "(query) and (match_time geq '2024/04/08 07:22:54')", 5, 1, 5, ) # asserting that "match_time" is used instead of "time_generated". assert last_fetch_dict == LastFetchTimes(Correlation="2024-04-08 07:22:55") # the max date assert last_id_dict == LastIDs(Correlation=10) assert max_fetch_dict == MaxFetch(Correlation=5) assert offset_dict == Offset(Correlation=2) def test_build_master_key_create_or_update_cmd(): """ Given: - Command arguments for updating Panorama / PAN-OS master key When: - Calling build_master_key_create_or_update_cmd. Assert: - Correct XML command string. """ from Panorama import build_master_key_create_or_update_cmd # Set args = { "current_master_key": "MyFakeMasterKey1", "new_master_key": "MyFakeMasterKey2", "lifetime_in_hours": "2160", "reminder_in_hours": "1992", } # Arrange cmd = build_master_key_create_or_update_cmd(args, action="update") # Assert assert cmd == ( "<request><master-key><lifetime>2160</lifetime><reminder>1992</reminder>" "<new-master-key>MyFakeMasterKey2</new-master-key>" "<current-master-key>MyFakeMasterKey1</current-master-key>" "<on-hsm>no</on-hsm></master-key></request>" ) def test_pan_os_create_master_key_command(requests_mock: RequestsMock): """ Given: - Command arguments for creating Panorama / PAN-OS master key When: - Calling pan_os_create_master_key_command. Assert: - Correct human readable output and raw response. """ import Panorama from Panorama import pan_os_create_master_key_command, xml2json # Set args = {"master_key": "MyFakeMasterKey1", "lifetime_in_hours": "2160", "reminder_in_hours": "1992"} Panorama.URL = "https://1.1.1.1:443/api/" xml_root = load_xml_root_from_test_file("test_data/create_master_key.xml") response_result = xml_root.find("result").text xml_response_text = ElementTree.tostring(xml_root, encoding="unicode") requests_mock.get(Panorama.URL, text=xml_response_text) # Arrange command_results: CommandResults = pan_os_create_master_key_command(args) # Assert assert command_results.readable_output == ( f"{response_result}. \n\n⚠️ The current API key is no longer valid! (by design) " "Generate a new API key and update it in the integration instance configuration to keep using the integration." ) assert command_results.raw_response == json.loads(xml2json(xml_response_text)) def test_pan_os_get_master_key_details_command(mocker: MockerFixture, requests_mock: RequestsMock): """ When: - Calling pan_os_get_master_key_command. Assert: - Correct human readable, context output, and raw response. """ import Panorama from Panorama import pan_os_get_master_key_details_command, xml2json # Set Panorama.URL = "https://1.1.1.1:443/api/" xml_root = load_xml_root_from_test_file("test_data/get_master_key.xml") xml_response_text = ElementTree.tostring(xml_root, encoding="unicode") requests_mock.get(Panorama.URL, text=xml_response_text) table_to_markdown = mocker.patch("Panorama.tableToMarkdown") # Arrange command_results: CommandResults = pan_os_get_master_key_details_command() table_name: str = table_to_markdown.call_args[0][0] table_data: dict = table_to_markdown.call_args[0][1] raw_response: dict = json.loads(xml2json(xml_response_text)) # Assert assert table_name == "Master Key Details" assert table_data == raw_response["response"]["result"] assert command_results.outputs == raw_response["response"]["result"] assert command_results.raw_response == raw_response @patch("Panorama.run_op_command") def test_show_jobs_id_not_found(patched_run_op_command): """ Given: - A specific job_id (23) When: - running show_jobs function Then: - Ensure DemistoException is thrown with ann informative message (since the given ID does not exist in all devices) """ from Panorama import UniversalCommand patched_run_op_command.side_effect = panos.errors.PanDeviceXapiError("job 23 not found") MockTopology = type("MockTopology", (), {"all": lambda *x, **y: [Panorama(hostname="123")]}) with pytest.raises(DemistoException, match="The given ID 23 is not found in all devices of the topology."): UniversalCommand.show_jobs(topology=MockTopology(), id=23) @patch("Panorama.TemplateStack.refreshall") @patch("Panorama.Template.refreshall") @patch("Panorama.run_op_command") def test_pan_os_get_certificate_info_command( patched_run_op_command, template_refreshall, template_stack_refreshall, mocker: MockerFixture, requests_mock: RequestsMock ): """ Test pan-os-get-certificate-expiration command. This test validates that: 1. The command correctly fetches certificates from Panorama devices 2. The command correctly fetches certificates from Firewall devices 3. The command correctly fetches predefined certificates 4. The command returns appropriate output """ from Panorama import pan_os_get_certificate_info_command def side_effect_func(device, cmd, **kwargs): if cmd == "request certificate show": return load_xml_root_from_test_file("test_data/request_certificate_show.xml") elif cmd == "show config running": return load_xml_root_from_test_file("test_data/show_running_config.xml") elif cmd == "show config pushed-template": return load_xml_root_from_test_file("test_data/show_config_pushed_template.xml") else: return None mock_template = MagicMock(spec=Template) mock_template.devices = [] template_refreshall.return_value = [mock_template] mock_template_stack = MagicMock(spec=TemplateStack) mock_template_stack.devices = [MOCK_FIREWALL_1_SERIAL] template_stack_refreshall.return_value = [mock_template_stack] patched_run_op_command.side_effect = side_effect_func # # Mock Panorama device mock_panorama = MagicMock(spec=Panorama) mock_panorama.hostname = "panorama.test" mock_panorama_devices = [mock_panorama] # # Mock Firewall device mock_firewall = MagicMock(spec=Firewall) mock_firewall.serial = MOCK_FIREWALL_1_SERIAL mock_firewall.parent = MagicMock(get=lambda x: "panorama.test" if x == "hostname" else None) mock_firewall_devices = [mock_firewall] # Mock empty topology mock_topology = MagicMock() mock_topology.panorama_devices.return_value = mock_panorama_devices mock_topology.firewall_devices.return_value = mock_firewall_devices Panorama.URL = "https://1.1.1.1:443/api/" # Define output of http request to "/config/predefined/certificate" with open("test_data/config_predefined_certificate.txt") as f: requests_mock.get(Panorama.URL, text=f.read()) result = pan_os_get_certificate_info_command(topology=mock_topology, args={"show_expired_only": False}) assert isinstance(result, CommandResults) assert result.outputs == load_json("test_data/get_certificate_info_command.json") class TestDynamicUpdateCommands: @pytest.mark.parametrize( "update_type_str, expected_api_call", [ ("APP_THREAT", "<request><content><upgrade><download><latest/></download></upgrade></content></request>"), ("ANTIVIRUS", "<request><anti-virus><upgrade><download><latest/></download></upgrade></anti-virus></request>"), ("WILDFIRE", "<request><wildfire><upgrade><download><latest/></download></upgrade></wildfire></request>"), ( "GP", "<request><global-protect-clientless-vpn><upgrade><download><latest/></download></upgrade></global-protect-clientless-vpn></request>", ), ], ) def test_download_latest_dynamic_update_content(self, update_type_str, expected_api_call, mocker): """Test that for each dynamic update type, the correct API call is made. Args: update_type_str (str): Type of dynamic update to download. expected_api_call (str): Expected API call to download the given update type. """ from Panorama import panorama_download_latest_dynamic_update_content from Panorama import DynamicUpdateType update_type = getattr(DynamicUpdateType, update_type_str) mock_request = mocker.patch("Panorama.http_request", return_value={}) panorama_download_latest_dynamic_update_content(update_type=update_type, target="1337") request_call_args = mock_request.call_args[1] assert request_call_args["body"]["cmd"] == expected_api_call def test_panorama_check_latest_dynamic_update_command(self, mocker): """test_panorama_check_latest_dynamic_update_command Test function to check current status of dynamic updates. Test the function that gathers information on latest available and currently installed dynamic updates using sample PAN-OS API responses to ensure the data is processed and the function returns the expected reaponse. """ from Panorama import panorama_check_latest_dynamic_update_command # Side-effect function to return the proper NGFW API response for the requested dynamic update type def side_effect_function(update_type, target): if update_type.name == "APP_THREAT": return load_json("test_data/pan-os-check-latest-dynamic-update-status_apiresponse_app-threat.json") elif update_type.name == "ANTIVIRUS": return load_json("test_data/pan-os-check-latest-dynamic-update-status_apiresponse_antivirus.json") elif update_type.name == "WILDFIRE": return load_json("test_data/pan-os-check-latest-dynamic-update-status_apiresponse_wildfire.json") elif update_type.name == "GP": return load_json("test_data/pan-os-check-latest-dynamic-update-status_apiresponse_gp.json") else: return None mock_api_call = mocker.patch("Panorama.panorama_check_latest_dynamic_update_content") mock_api_call.side_effect = side_effect_function mock_return_results = mocker.patch("Panorama.return_results") panorama_check_latest_dynamic_update_command({"target": "1337"}) # Prepare results for comparison returned_commandresults: CommandResults = mock_return_results.call_args[0][0] expected_returned_output = load_json("test_data/pan-os-check-latest-dynamic-update-status_expected-returned-outputs.json") expected_returned_readable = ( "### Dynamic Update Status Summary\n|Update Type|Is Up To Date|Latest Available " "Version|Currently Installed Version|\n|---|---|---|---|\n| Content | True | 8987-9481 | 8987-9481 |\n| " "AntiVirus | False | 5212-5732 | 5211-5731 |\n| WildFire | False | 986250-990242 | 986026-990018 |\n| GP | " "True | 98-260 | 98-260 |\n\n\n**Total Content Types Outdated: 2**" ) assert returned_commandresults.outputs == expected_returned_output assert returned_commandresults.readable_output == expected_returned_readable def test_panorama_check_latest_dynamic_update_panorama_instance(self, mocker): """ Given: - A panorama instance (VSYS instance parameter is set to ''). - target argument is not specified (set to ''). When: - Calling the panorama_check_latest_dynamic_update_command. Then: - Verify that an exception is raised askung the user to specify a target firewall when running from a Panorama instance. """ from Panorama import panorama_check_latest_dynamic_update_command # VSYS global variable is set to '' by default, which means we are simulating a run from a Panorama instance. mocker.patch("Panorama.VSYS", "") with pytest.raises(DemistoException) as e: panorama_check_latest_dynamic_update_command({"target": ""}) assert "When running from a Panorama instance, you must specify the target argument." in str(e.value) def test_panorama_check_latest_dynamic_update_command_empty_response(self, mocker): """ Tests the scenario were the response from the 'panorama_check_latest_dynamic_update_content' api call, includes no entries - which means that the Firewall probably doesn't have any App/Threat or Antivirus, or Wildfire or GP installed. Given: - a Panorama instance. - Mock response for the 'panorama_check_latest_dynamic_update_content' api call, with no entries. When: - Calling the panorama_check_latest_dynamic_update_command. Then: - Verify that the outputs include no versions (all versions set to N/A). - Verify that the expected debug log is created. """ from Panorama import panorama_check_latest_dynamic_update_command mocker.patch( "Panorama.panorama_check_latest_dynamic_update_content", return_value={ "response": { "@status": "success", "result": {"content-updates": {"@last-updated-at": "2025/06/11 13:40:16 PDT", "entry": []}}, } }, ) mock_return_results = mocker.patch("Panorama.return_results") mock_debug = mocker.patch.object(demisto, "debug") panorama_check_latest_dynamic_update_command({"target": "1337"}) # Prepare results for comparison returned_commandresults: CommandResults = mock_return_results.call_args[0][0] expected_returned_output = { "Content": {"LatestAvailable": {}, "CurrentlyInstalled": {}, "IsUpToDate": False}, "AntiVirus": {"LatestAvailable": {}, "CurrentlyInstalled": {}, "IsUpToDate": False}, "WildFire": {"LatestAvailable": {}, "CurrentlyInstalled": {}, "IsUpToDate": False}, "GP": {"LatestAvailable": {}, "CurrentlyInstalled": {}, "IsUpToDate": False}, "ContentTypesOutOfDate": {"Count": 4}, } expected_returned_readable = ( "### Dynamic Update Status Summary\n|Update Type|Is Up To Date|Latest Available " "Version|Currently Installed Version|\n|---|---|---|---|\n| Content | False | N/A | N/A |" "\n| AntiVirus | False | N/A | N/A |\n| WildFire | False | N/A | N/A |\n| GP | False | N/A " "| N/A |\n\n\n**Total Content Types Outdated: 4**" ) assert mock_debug.call_args[0][0] == ( "No available updates " "(Firewall probably doesn't have any global-protect-clientless-vpn installed)." ) assert returned_commandresults.outputs == expected_returned_output assert returned_commandresults.readable_output == expected_returned_readable def test_panorama_check_latest_dynamic_update_command_no_gp_license(self, mocker): """ Tests the scenario were there is no Global Protect license on the Firewall. Given: - a Panorama instance. - Mock response for the 'panorama_check_latest_dynamic_update_content' api call, with an exception regfarding the GP missing license. When: - Calling the panorama_check_latest_dynamic_update_command. Then: - Verify that the outputs include the versions of the content, wildfire and antivirus, and the error message egarding the gp missing license. - Verify that the human readable output includes the versions of the versions of the content, wildfire and antivirus, and the error message regarding the gp missing license. """ from Panorama import panorama_check_latest_dynamic_update_command # Side-effect function to return the proper NGFW API response for the requested dynamic update type def side_effect_function(update_type, target): if update_type.name == "APP_THREAT": return load_json("test_data/pan-os-check-latest-dynamic-update-status_apiresponse_app-threat.json") elif update_type.name == "ANTIVIRUS": return load_json("test_data/pan-os-check-latest-dynamic-update-status_apiresponse_antivirus.json") elif update_type.name == "WILDFIRE": return load_json("test_data/pan-os-check-latest-dynamic-update-status_apiresponse_wildfire.json") elif update_type.name == "GP": raise Exception("There is no Global Protext Gateway license on the box") else: return None mock_api_call = mocker.patch("Panorama.panorama_check_latest_dynamic_update_content") mock_api_call.side_effect = side_effect_function mock_return_results = mocker.patch("Panorama.return_results") panorama_check_latest_dynamic_update_command({"target": "1337"}) # Prepare results for comparison returned_commandresults: CommandResults = mock_return_results.call_args[0][0] expected_returned_output = load_json( "test_data/pan-os-check-latest-dynamic-update-status_expected-returned-outputs-no-gp" "-license.json" ) expected_returned_readable = ( "### Dynamic Update Status Summary\n|Update Type|Is Up To Date|Latest Available " "Version|Currently Installed Version|\n|---|---|---|---|\n| Content | True | 8987-9481 | 8987-9481 |\n| " "AntiVirus | False | 5212-5732 | 5211-5731 |\n| WildFire | False | 986250-990242 | 986026-990018 |\n| GP | " "False | An Error received from Panorama API: 'There is no Global Protect Gateway license on the box.' |" " N/A |\n\n\n**Total Content Types Outdated: 2**" ) assert returned_commandresults.outputs == expected_returned_output assert returned_commandresults.readable_output == expected_returned_readable def test_panorama_check_latest_dynamic_update_command_no_wildfire_license(self, mocker): """ Tests the scenario were there is no WildFire license on the Firewall. Given: - a Panorama instance. - Mock response for the 'panorama_check_latest_dynamic_update_content' api call, with an exception regarding the WildFire missing license. When: - Calling the panorama_check_latest_dynamic_update_command. Then: - Verify that the outputs include the versions of the content, antivirus and the error message regarding the WildFire missing license. - Verify that the human-readable output includes the versions of the versions of the content, antivirus and the error message regarding the WildFire missing license. """ from Panorama import panorama_check_latest_dynamic_update_command # Side-effect function to return the proper NGFW API response for the requested dynamic update type def side_effect_function(update_type, target): if update_type.name == "APP_THREAT": return load_json("test_data/pan-os-check-latest-dynamic-update-status_apiresponse_app-threat.json") elif update_type.name == "ANTIVIRUS": return load_json("test_data/pan-os-check-latest-dynamic-update-status_apiresponse_antivirus.json") elif update_type.name == "GP": return load_json("test_data/pan-os-check-latest-dynamic-update-status_apiresponse_gp.json") elif update_type.name == "WILDFIRE": raise Exception("There is not wildfire license on the box") else: return None mock_api_call = mocker.patch("Panorama.panorama_check_latest_dynamic_update_content") mock_api_call.side_effect = side_effect_function mock_return_results = mocker.patch("Panorama.return_results") panorama_check_latest_dynamic_update_command({"target": "1337"}) # Prepare results for comparison returned_commandresults: CommandResults = mock_return_results.call_args[0][0] expected_returned_output = load_json( "test_data/pan-os-check-latest-dynamic-update-status_expected-returned-outputs-no-wildfire" "-license.json" ) expected_returned_readable = ( "### Dynamic Update Status Summary\n|Update Type|Is Up To Date|Latest Available " "Version|Currently Installed Version|\n|---|---|---|---|\n|" " Content | True | 8987-9481 | 8987-9481 |\n| " "AntiVirus | False | 5212-5732 | 5211-5731 |\n|" " WILDFIRE | False | An Error received from Panorama API: 'There is not wildfire license on the box.' | N/A |\n|" " GP | True | 98-260 | 98-260 |\n\n\n" "**Total Content Types Outdated: 1**" ) assert returned_commandresults.outputs == expected_returned_output assert returned_commandresults.readable_output == expected_returned_readable @pytest.mark.parametrize( "update_phase, job_id, api_response_payload", [ ( "start-no-polling", "", { "response": { "@status": "success", "@code": "19", "result": {"msg": {"line": "Download job enqueued with jobid 1309"}, "job": "1309"}, }, }, ), ( "start-with-polling", "", { "response": { "@status": "success", "@code": "19", "result": {"msg": {"line": "Download job enqueued with jobid 1309"}, "job": "1309"}, }, }, ), ( "check", "1309", { "response": { "@status": "success", "result": { "job": { "tenq": "2025/06/15 10:55:53", "tdeq": "(null)", "id": "1311", "user": None, "type": "Downld", "status": "PEND", "queued": "YES", "stoppable": "yes", "result": "PEND", "tfin": None, "description": None, "positionInQ": "0", "progress": "0", "details": None, "warnings": None, } }, }, }, ), ( "finished", "1309", { "response": { "@status": "success", "result": { "job": { "tenq": "2025/06/15 10:34:51", "tdeq": "10:34:51", "id": "1309", "user": None, "type": "Downld", "status": "FIN", "queued": "NO", "stoppable": "no", "result": "OK", "tfin": "2025/06/15 10:34:53", "description": None, "positionInQ": "0", "progress": "2025/06/15 10:34:53", "details": { "line": [ "File successfully downloaded", "Successfully downloaded", "Applications and Threats version: 8988-9483", ] }, "warnings": None, }, }, }, }, ), ], ) def test_panorama_download_latest_dynamic_update_command(self, update_phase, job_id, api_response_payload, mocker): from Panorama import DynamicUpdateType from Panorama import panorama_download_latest_dynamic_update_command from CommonServerPython import ScheduledCommand mocker.patch("Panorama.panorama_download_latest_dynamic_update_content", return_value=api_response_payload) mocker.patch("Panorama.panorama_content_update_download_status", return_value=api_response_payload) mock_command_return = mocker.patch("Panorama.return_results") if update_phase == "start-no-polling": """ Run the command for the first time, with an API response indicating the job has been enqueued. Verify that the response contains job info with no subsquent scheduled command. """ panorama_download_latest_dynamic_update_command(DynamicUpdateType.ANTIVIRUS, {"target": "1337", "polling": "false"}) returned_results = mock_command_return.call_args[0][0] assert returned_results.scheduled_command is None assert returned_results.readable_output == "Content download JobID 1309 started on device 1337." elif update_phase == "start-with-polling": """ Run the command for the first time, with an API response indicating the job has been enqueued. Verify that the response contains a ScheduledCommand object to poll for job status and that the default polling timeout/interval are applied when not provided. """ panorama_download_latest_dynamic_update_command(DynamicUpdateType.ANTIVIRUS, {"target": "1337"}) returned_results = mock_command_return.call_args[0][0] assert isinstance(returned_results.scheduled_command, ScheduledCommand) assert returned_results.scheduled_command._timeout == "3600" assert returned_results.scheduled_command._next_run == "30" elif update_phase == "check": """ Run the command as if a download has been started and check for the status of it. Verify that when the API response shows that the job is still pending that a ScheduledCommand object is returned to continue to poll for the download to complete, honoring custom timeout_in_seconds/interval_in_seconds when provided. """ panorama_download_latest_dynamic_update_command( DynamicUpdateType.ANTIVIRUS, { "target": "1337", "job_id": job_id, "timeout_in_seconds": "1200", "interval_in_seconds": "45", }, ) returned_results = mock_command_return.call_args[0][0] assert isinstance(returned_results.scheduled_command, ScheduledCommand) assert returned_results.scheduled_command._timeout == "1200" assert returned_results.scheduled_command._next_run == "45" elif update_phase == "finished": """ Run the command as if a download has been completed. Verify that when the API response shows the job is finished that the function returns a CommandResult that includes the expected outputs and does not continue to poll. """ panorama_download_latest_dynamic_update_command(DynamicUpdateType.ANTIVIRUS, {"target": "1337", "job_id": job_id}) returned_results = mock_command_return.call_args[0][0] assert isinstance(returned_results, dict) assert returned_results["Contents"] == { "response": { "@status": "success", "result": { "job": { "tenq": "2025/06/15 10:34:51", "tdeq": "10:34:51", "id": "1309", "user": None, "type": "Downld", "status": "FIN", "queued": "NO", "stoppable": "no", "result": "OK", "tfin": "2025/06/15 10:34:53", "description": None, "positionInQ": "0", "progress": "2025/06/15 10:34:53", "details": { "line": [ "File successfully downloaded", "Successfully downloaded", "Applications and Threats version: 8988-9483", ] }, "warnings": None, } }, } } assert ( returned_results["HumanReadable"] == "### AntiVirus update download status:\n|JobID|Status|Details|\n|---|---|---|\n| 1309 | Completed |" " tenq: 2025/06/15 10:34:51<br>tdeq: 10:34:51<br>id: 1309<br>user: null<br>type: Downld<br>status: " "FIN<br>queued: NO<br>stoppable: no<br>result: OK<br>tfin: 2025/06/15 10:34:53<br>description: " 'null<br>positionInQ: 0<br>progress: 2025/06/15 10:34:53<br>details: {"line": ' '["File successfully downloaded", "Successfully downloaded", "Applications and ' 'Threats version: 8988-9483"]}<br>warnings: null |\n' ) assert returned_results["EntryContext"] == { "Panorama.AntiVirus.Download(val.JobID == obj.JobID)": { "JobID": "1309", "Status": "Completed", "Details": { "tenq": "2025/06/15 10:34:51", "tdeq": "10:34:51", "id": "1309", "user": None, "type": "Downld", "status": "FIN", "queued": "NO", "stoppable": "no", "result": "OK", "tfin": "2025/06/15 10:34:53", "description": None, "positionInQ": "0", "progress": "2025/06/15 10:34:53", "details": { "line": [ "File successfully downloaded", "Successfully downloaded", "Applications and Threats version: 8988-9483", ] }, "warnings": None, }, } } @pytest.mark.parametrize( "install_phase, job_id, api_response_payload", [ ( "start-no-polling", "", { "response": { "@status": "success", "@code": "19", "result": {"msg": {"line": "Content install job enqueued with jobid 1318"}, "job": "1318"}, } }, ), ( "start-with-polling", "", { "response": { "@status": "success", "@code": "19", "result": {"msg": {"line": "Content install job enqueued with jobid 1318"}, "job": "1318"}, } }, ), ( "check", "1318", { "response": { "@status": "success", "result": { "job": { "tenq": "2025/06/15 12:43:29", "tdeq": "12:43:29", "id": "1318", "user": None, "type": "Antivirus", "status": "ACT", "queued": "NO", "stoppable": "no", "result": "PEND", "tfin": None, "description": None, "positionInQ": "0", "progress": "20", "warnings": None, "details": None, } }, } }, ), ( "finished", "1318", { "response": { "@status": "success", "result": { "job": { "tenq": "2025/06/15 12:43:29", "tdeq": "12:43:29", "id": "1318", "user": "admin", "type": "Antivirus", "status": "FIN", "queued": "NO", "stoppable": "no", "result": "OK", "tfin": "2025/06/15 12:44:21", "description": None, "positionInQ": "0", "progress": "2025/06/15 12:44:21", "details": {"line": "Job completed successfully"}, "warnings": None, } }, } }, ), ], ) def test_panorama_install_latest_dynamic_update_command(self, install_phase, job_id, api_response_payload, mocker): from Panorama import DynamicUpdateType from Panorama import panorama_install_latest_dynamic_update_command from CommonServerPython import ScheduledCommand mocker.patch("Panorama.panorama_install_latest_dynamic_update", return_value=api_response_payload) mocker.patch("Panorama.panorama_content_update_install_status", return_value=api_response_payload) mock_command_return = mocker.patch("Panorama.return_results") if install_phase == "start-no-polling": """ Run the command for the first time, with an API response indicating the job has been enqueued. Verify that the response contains job info with no subsequent scheduled command. """ panorama_install_latest_dynamic_update_command(DynamicUpdateType.ANTIVIRUS, {"target": "1337", "polling": "false"}) returned_results = mock_command_return.call_args[0][0] assert returned_results.scheduled_command is None assert returned_results.readable_output == "Content install JobID 1318 started on device 1337." elif install_phase == "start-with-polling": """ Run the command for the first time, with an API response indicating the job has been enqueued. Verify that the response contains a ScheduledCommand object to poll for job status and that the default polling timeout/interval are applied when not provided. """ panorama_install_latest_dynamic_update_command(DynamicUpdateType.ANTIVIRUS, {"target": "1337"}) returned_results = mock_command_return.call_args[0][0] assert isinstance(returned_results.scheduled_command, ScheduledCommand) assert returned_results.scheduled_command._timeout == "3600" assert returned_results.scheduled_command._next_run == "30" elif install_phase == "check": """ Run the command as if an install has been started and check for the status of it. Verify that when the API response shows that the job is still pending that a ScheduledCommand object is returned to continue to poll for the install to complete, honoring custom timeout_in_seconds/interval_in_seconds when provided. """ panorama_install_latest_dynamic_update_command( DynamicUpdateType.ANTIVIRUS, { "target": "1337", "job_id": job_id, "timeout_in_seconds": "1200", "interval_in_seconds": "45", }, ) returned_results = mock_command_return.call_args[0][0] assert isinstance(returned_results.scheduled_command, ScheduledCommand) assert returned_results.scheduled_command._timeout == "1200" assert returned_results.scheduled_command._next_run == "45" elif install_phase == "finished": """ Run the command as if an install has been completed. Verify that when the API response shows the job is finished that the function returns a CommandResult that includes the expected outputs and does not continue to poll. """ panorama_install_latest_dynamic_update_command(DynamicUpdateType.ANTIVIRUS, {"target": "1337", "job_id": job_id}) returned_results = mock_command_return.call_args[0][0] assert isinstance(returned_results, dict) assert returned_results["Contents"] == { "response": { "@status": "success", "result": { "job": { "tenq": "2025/06/15 12:43:29", "tdeq": "12:43:29", "id": "1318", "user": "admin", "type": "Antivirus", "status": "FIN", "queued": "NO", "stoppable": "no", "result": "OK", "tfin": "2025/06/15 12:44:21", "description": None, "positionInQ": "0", "progress": "2025/06/15 12:44:21", "details": {"line": "Job completed successfully"}, "warnings": None, } }, } } assert ( returned_results["HumanReadable"] == "### AntiVirus update install status:\n|JobID|Status|Details|\n|---|---|---|\n| 1318 | Completed | " "tenq: 2025/06/15 12:43:29<br>tdeq: 12:43:29<br>id: 1318<br>user: admin<br>type: Antivirus<br>" "status: FIN<br>queued: NO<br>stoppable: no<br>result: OK<br>tfin: 2025/06/15 12:44:21<br>" 'description: null<br>positionInQ: 0<br>progress: 2025/06/15 12:44:21<br>details: {"line": ' '"Job completed successfully"}<br>warnings: null |\n' ) assert returned_results["EntryContext"] == { "Panorama.AntiVirus.Install(val.JobID == obj.JobID)": { "JobID": "1318", "Status": "Completed", "Details": { "tenq": "2025/06/15 12:43:29", "tdeq": "12:43:29", "id": "1318", "user": "admin", "type": "Antivirus", "status": "FIN", "queued": "NO", "stoppable": "no", "result": "OK", "tfin": "2025/06/15 12:44:21", "description": None, "positionInQ": "0", "progress": "2025/06/15 12:44:21", "details": {"line": "Job completed successfully"}, "warnings": None, }, } } @pytest.mark.parametrize( ("vsys", "rules", "rulebase", "expected_cmd"), [ ( "vsys1", "Rule1", "qos", b'<show><rule-hit-count><vsys><vsys-name><entry name="vsys1"><rule-base><entry name="qos"><rules>' b"<list><member>Rule1</member></list></rules></entry></rule-base></entry></vsys-name></vsys>" b"</rule-hit-count></show>", ), ( "vsys3", "Rule1,Rule2,Rule3", "security", b'<show><rule-hit-count><vsys><vsys-name><entry name="vsys3"><rule-base><entry name="security"><rules><list>' b"<member>Rule1</member><member>Rule2</member><member>Rule3</member>" b"</list></rules></entry></rule-base></entry></vsys-name></vsys></rule-hit-count></show>", ), ], ) def test_build_rule_hit_count_xml(vsys, rules, rulebase, expected_cmd): """Test the build_rule_hit_count_xml return value. Args: vsys: Virtual system name or "all" for all virtual systems rules: Rule names (single rule, multiple comma-separated rules, or "all") rulebase: The firewall rulebase to check expected_cmd: Expected XML command that should be generated mock_topology: Mocked topology fixture mocker: Pytest mocker fixture """ from Panorama import FirewallCommand import xml.etree.ElementTree as ET xml_root = FirewallCommand.build_rule_hit_count_xml(vsys, rulebase, rules) cmd = ET.tostring(xml_root, encoding="unicode").encode() assert cmd == expected_cmd @freeze_time("2025-06-26 13:00:00 UTC") @pytest.mark.parametrize( ("rulebase_type", "unused_only", "no_new_hits_since_dt", "length_expected"), [ ("security", "false", None, 10), # Should result in 10 returned records. ("security", "true", None, 6), # Should result in 6 returned records. ( "security", "false", datetime.strptime("2025/06/26 00:00:00Z", "%Y/%m/%d %H:%M:%SZ"), 8, ), # Should result in 8 returned records. ], ) def test_get_hitcounts(rulebase_type, unused_only, no_new_hits_since_dt, length_expected, mock_topology, mocker): """Test the FirewallCommand.get_hitcounts method with various filter parameters. Verify it returns the correct number of rules from the sample data based on the filter conditions. Args: rulebase_type: The type of rulebase to query (e.g., "security") unused_only: Whether to filter for unused rules only ("true"/"false") no_new_hits_since_dt: Optional datetime to filter rules with no new hits since this time length_expected: Expected number of rules in the result mock_topology: Mocked topology fixture mocker: Pytest mocker fixture """ from Panorama import FirewallCommand rule_hitcounts_data = "test_data/get_rule_hitcounts_rule_hits.xml" pushed_policy_data = "test_data/get_rule_hitcounts_pushed_policy.xml" mocker.patch( "Panorama.run_op_command", side_effect=[load_xml_root_from_test_file(pushed_policy_data), load_xml_root_from_test_file(rule_hitcounts_data)], ) mocker.patch("Panorama.demisto.callingContext", return_value={"context": {"IntegrationInstance": "Panorama_test_instance"}}) result = FirewallCommand.get_hitcounts( topology=mock_topology, rulebase_type=rulebase_type, vsys_arg="vsys1", rules_arg="all", no_new_hits_since=no_new_hits_since_dt, device_filter_string=None, target=None, unused_only=unused_only, ) assert result is not None assert len(result) == length_expected @pytest.mark.parametrize( "unused_only, no_new_hits_since, expected_count", [ # Case 1: unused_only=False, no filter -> all rules returned ("false", None, 4), # Case 2: unused_only=True -> only rules with hit_count=0 ("true", None, 2), # Case 3: unused_only=False, no_new_hits_since recent -> only rules older than filter ("false", dateparser.parse("12 hours ago", settings={"TIMEZONE": "UTC"}), 4), # Case 4: unused_only=True, no_new_hits_since recent -> only old unused rules ("true", dateparser.parse("12 hours ago", settings={"TIMEZONE": "UTC"}), 2), ], ) def test_get_hitcounts_filters_param(unused_only, no_new_hits_since, expected_count, mocker): """Test get_hitcounts with different unused_only and no_new_hits_since values.""" import xml.etree.ElementTree as ET from Panorama import FirewallCommand # ---------------------------- # Mock topology and firewall # ---------------------------- mock_firewall = mocker.Mock() mock_firewall.id = "FW1" mock_topology = mocker.Mock() mock_topology.firewalls.return_value = [mock_firewall] mock_topology.panorama_objects = [] vsys_list = ["vsys1", "vsys2"] mocker.patch.object(FirewallCommand, "get_vsys_list", return_value=vsys_list) # ---------------------------- # Fake run_op_command returns 2 rules per VSYS # ---------------------------- def fake_run_op(firewall, cmd, cmd_xml=False): xml_root = ET.Element("show") rhc = ET.SubElement(xml_root, "rule-hit-count") vsys_elem = ET.SubElement(rhc, "vsys") vsys_name_elem = ET.SubElement(vsys_elem, "vsys-name") entry = ET.SubElement(vsys_name_elem, "entry", name="vsys_placeholder") rb = ET.SubElement(entry, "rule-base") rb_entry = ET.SubElement(rb, "entry", name="security") rules_elem = ET.SubElement(rb_entry, "rules") # Helper to add rule entry with all required fields def add_rule(name, hit_count, last_hit_timestamp): rule = ET.SubElement(rules_elem, "entry", name=name) ET.SubElement(rule, "hit_count").text = str(hit_count) ET.SubElement(rule, "last_hit_timestamp").text = last_hit_timestamp # Add required extra fields for ShowRuleHitCountResult ET.SubElement(rule, "latest").text = "false" ET.SubElement(rule, "last_reset_timestamp").text = "0" ET.SubElement(rule, "first_hit_timestamp").text = "0" ET.SubElement(rule, "rule_creation_timestamp").text = "0" ET.SubElement(rule, "rule_modification_timestamp").text = "0" # Rule1: hit_count=0, old timestamp (1970) add_rule("Rule1", 0, "0") # Rule2: hit_count=5, recent timestamp '2025-03-20T14:52:04Z' add_rule("Rule2", 5, "1742482324") return xml_root mocker.patch("Panorama.run_op_command", side_effect=fake_run_op) # Patch demisto mocker.patch("Panorama.demisto.debug") mocker.patch("Panorama.demisto.callingContext", new={"context": {"IntegrationInstance": "test_instance"}}) # Patch build_rule_hit_count_xml to use original original_build_xml = FirewallCommand.build_rule_hit_count_xml mocker.patch.object( FirewallCommand, "build_rule_hit_count_xml", side_effect=lambda vsys_name, rb, rules: original_build_xml(vsys_name, rb, rules), ) # ---------------------------- # Call function # ---------------------------- results = FirewallCommand.get_hitcounts( mock_topology, "security", "all", "Rule1,Rule2", no_new_hits_since=no_new_hits_since, device_filter_string=None, target=None, unused_only=unused_only, ) # ---------------------------- # Assert total rules returned # ---------------------------- assert len(results) == expected_count # Optional: check that returned rules match filters for r in results: if unused_only == "true": assert r.hit_count == 0 if no_new_hits_since is not None: last_hit_dt = datetime.strptime(r.last_hit_timestamp, "%Y-%m-%dT%H:%M:%SZ") assert last_hit_dt <= no_new_hits_since @pytest.mark.parametrize( "pre_post, expected_names", [ # No filter -> every rule comes back: pre-pushed, post-pushed and local. (None, {"PreRule", "PostRule", "LocalRule"}), # pre_rulebase -> only the Panorama-pushed pre-rulebase rule. ("pre_rulebase", {"PreRule"}), # post_rulebase -> only the Panorama-pushed post-rulebase rule. ("post_rulebase", {"PostRule"}), ], ) def test_get_hitcounts_pre_post_filter(pre_post, expected_names, mocker): """Validate the new ``pre_post`` filter in ``FirewallCommand.get_hitcounts``. Given: - A topology with one firewall and one vsys. - The Panorama-pushed policy enrichment returns one rule in ``pre-rulebase`` ("PreRule") and one rule in ``post-rulebase`` ("PostRule"); these populate ``result.position`` with the underscore form ("pre_rulebase" / "post_rulebase"). - The ``show rule-hit-count`` response contains those two pushed rules plus a local firewall rule ("LocalRule") that is NOT present in the pushed-policy map. When: - Calling ``get_hitcounts`` with the ``pre_post`` kwarg unset / "pre_rulebase" / "post_rulebase". Then: - With no filter, all three rules are returned. - With a ``pre_post`` value set, only the matching Panorama-pushed rule is returned; the rule from the other position AND the local rule are both excluded. """ import xml.etree.ElementTree as ET from Panorama import FirewallCommand, PushedSharedPolicy # Topology with a single firewall and a single vsys. mock_firewall = mocker.Mock() mock_firewall.id = "FW1" mock_firewall.serial = "111111111111111" mock_firewall.hostname = None mock_topology = mocker.Mock() mock_topology.firewalls.return_value = [mock_firewall] mock_topology.panorama_objects = [] mocker.patch.object(FirewallCommand, "get_vsys_list", return_value=["vsys1"]) # Stub the pushed-policy lookup directly with the underscore-position form that the real # code stores on ``result.position``. This avoids re-asserting XML-parsing behavior and # isolates the test to the pre_post filter logic. pushed_map = { "PreRule": PushedSharedPolicy(hostid="FW1", name="PreRule", policy_type="security", position="pre_rulebase", loc="DG-1"), "PostRule": PushedSharedPolicy( hostid="FW1", name="PostRule", policy_type="security", position="post_rulebase", loc="DG-1" ), } mocker.patch.object(FirewallCommand, "get_pushed_shared_policy_rules", return_value=pushed_map) # Fake ``show rule-hit-count`` response containing all three rules (pre, post, local). def fake_run_op(firewall, cmd, cmd_xml=False): xml_root = ET.Element("show") rhc = ET.SubElement(xml_root, "rule-hit-count") vsys_elem = ET.SubElement(rhc, "vsys") vsys_name_elem = ET.SubElement(vsys_elem, "vsys-name") entry = ET.SubElement(vsys_name_elem, "entry", name="vsys1") rb = ET.SubElement(entry, "rule-base") rb_entry = ET.SubElement(rb, "entry", name="security") rules_elem = ET.SubElement(rb_entry, "rules") for name in ("PreRule", "PostRule", "LocalRule"): rule = ET.SubElement(rules_elem, "entry", name=name) ET.SubElement(rule, "hit_count").text = "10" ET.SubElement(rule, "last_hit_timestamp").text = "1742482324" ET.SubElement(rule, "latest").text = "false" ET.SubElement(rule, "last_reset_timestamp").text = "0" ET.SubElement(rule, "first_hit_timestamp").text = "0" ET.SubElement(rule, "rule_creation_timestamp").text = "0" ET.SubElement(rule, "rule_modification_timestamp").text = "0" return xml_root mocker.patch("Panorama.run_op_command", side_effect=fake_run_op) mocker.patch("Panorama.demisto.debug") mocker.patch("Panorama.demisto.callingContext", new={"context": {"IntegrationInstance": "test_instance"}}) results = FirewallCommand.get_hitcounts( mock_topology, "security", "vsys1", "all", no_new_hits_since=None, device_filter_string=None, target=None, unused_only="false", pre_post=pre_post, ) returned_names = {r.name for r in results} assert returned_names == expected_names # When the filter is set, every returned row must come from Panorama at the requested position # — local rules and rules from the other rulebase must be excluded. if pre_post is not None: for r in results: assert r.is_from_panorama is True assert r.position == pre_post def test_get_hitcounts_vsys_specific_enrichment(mocker): """ Test that get_hitcounts performs per-vsys enrichment and uses the updated XPath logic. Given: - A topology with one firewall and two vsys (vsys1, vsys2). - Each vsys has different Panorama-pushed rules (vsys1 has "PanoramaRule_v1", vsys2 has "PanoramaRule_v2"). - Each vsys also has a local rule that is NOT in the pushed policy data. When: - Calling get_hitcounts with vsys_arg="all". Then: - get_pushed_shared_policy_rules is called once per vsys (2 times total), each with the correct vsys_name. - The pushed-shared-policy command includes the vsys name in the XML. - Rules from vsys1 are enriched only with vsys1's pushed policy data (and vice versa). - The new XPath './/panorama/{position}/...' correctly finds rules in the XML response. - Local rules (not in pushed policy) have is_from_panorama=False. """ import xml.etree.ElementTree as ET from Panorama import FirewallCommand # Mock topology and firewall mock_firewall = mocker.Mock() mock_firewall.id = "FW1" mock_firewall.serial = "111111111111111" mock_firewall.hostname = None mock_topology = mocker.Mock() mock_topology.firewalls.return_value = [mock_firewall] mock_topology.panorama_objects = [] mocker.patch.object(FirewallCommand, "get_vsys_list", return_value=["vsys1", "vsys2"]) # Build per-vsys pushed policy XML responses (new format with .//panorama/ XPath) def build_pushed_policy_xml(vsys_name: str) -> ET.Element: root = ET.Element("response", status="success") result_elem = ET.SubElement(root, "result") policy = ET.SubElement(result_elem, "policy") panorama_elem = ET.SubElement(policy, "panorama") # Pre-rulebase with a vsys-specific rule pre_rb = ET.SubElement(panorama_elem, "pre-rulebase") security = ET.SubElement(pre_rb, "security") rules = ET.SubElement(security, "rules") rule_name = f"PanoramaRule_{vsys_name.replace('vsys', 'v')}" dg_name = f"DG-{vsys_name}" entry = ET.SubElement(rules, "entry", name=rule_name, loc=dg_name) # Add a child element so the entry is not considered "empty" by ElementTree # (bool(element) returns False for elements with no children, causing dataclass_from_element to return None) ET.SubElement(entry, "action", loc=dg_name).text = "allow" return root pushed_policy_vsys1 = build_pushed_policy_xml("vsys1") pushed_policy_vsys2 = build_pushed_policy_xml("vsys2") # Build a hitcount response XML containing both a Panorama rule and a local rule def build_hitcount_xml(vsys_name: str) -> ET.Element: root = ET.Element("response", status="success") result_elem = ET.SubElement(root, "result") rhc = ET.SubElement(result_elem, "rule-hit-count") vsys_elem = ET.SubElement(rhc, "vsys") vsys_name_elem = ET.SubElement(vsys_elem, "vsys-name") entry = ET.SubElement(vsys_name_elem, "entry", name=vsys_name) rb = ET.SubElement(entry, "rule-base") rb_entry = ET.SubElement(rb, "entry", name="security") rules_elem = ET.SubElement(rb_entry, "rules") panorama_rule_name = f"PanoramaRule_{vsys_name.replace('vsys', 'v')}" local_rule_name = f"LocalRule_{vsys_name}" for rule_name in [panorama_rule_name, local_rule_name]: rule = ET.SubElement(rules_elem, "entry", name=rule_name) ET.SubElement(rule, "hit_count").text = "10" ET.SubElement(rule, "last_hit_timestamp").text = "1742482324" ET.SubElement(rule, "latest").text = "false" ET.SubElement(rule, "last_reset_timestamp").text = "0" ET.SubElement(rule, "first_hit_timestamp").text = "0" ET.SubElement(rule, "rule_creation_timestamp").text = "0" ET.SubElement(rule, "rule_modification_timestamp").text = "0" return root hitcount_vsys1 = build_hitcount_xml("vsys1") hitcount_vsys2 = build_hitcount_xml("vsys2") """ Mock run_op_command to return vsys-specific responses The new code calls run_op_command in this order per vsys: 1. pushed-shared-policy (enrichment) 2. hitcount query So we need to mock 4 responses for 2 vsys: pushed1, hitcount1, pushed2, hitcount2 """ run_op_responses = [pushed_policy_vsys1, hitcount_vsys1, pushed_policy_vsys2, hitcount_vsys2] run_op_mock = mocker.patch("Panorama.run_op_command", side_effect=run_op_responses) mocker.patch("Panorama.demisto.debug") mocker.patch("Panorama.demisto.callingContext", new={"context": {"IntegrationInstance": "test_instance"}}) results = FirewallCommand.get_hitcounts( topology=mock_topology, rulebase_type="security", vsys_arg="all", rules_arg="all", no_new_hits_since=None, device_filter_string=None, target=None, unused_only="false", ) # Total of 4 rules returned (2 per vsys) assert len(results) == 4 # run_op_command called 4 times total (pushed + hitcount per vsys) assert run_op_mock.call_count == 4 # Verify the pushed-shared-policy commands include vsys name # Call 0: pushed policy for vsys1 pushed_call_1_cmd = run_op_mock.call_args_list[0] assert "vsys1" in pushed_call_1_cmd.kwargs.get("cmd", pushed_call_1_cmd[1].get("cmd", "")) # Call 2: pushed policy for vsys2 pushed_call_2_cmd = run_op_mock.call_args_list[2] assert "vsys2" in pushed_call_2_cmd.kwargs.get("cmd", pushed_call_2_cmd[1].get("cmd", "")) # Verify per-vsys enrichment: Panorama rules are correctly enriched vsys1_results = [r for r in results if r.vsys == "vsys1"] vsys2_results = [r for r in results if r.vsys == "vsys2"] assert len(vsys1_results) == 2 assert len(vsys2_results) == 2 # vsys1's Panorama rule should be enriched with vsys1's DG vsys1_panorama_rule = next(r for r in vsys1_results if r.name == "PanoramaRule_v1") assert vsys1_panorama_rule.is_from_panorama is True assert vsys1_panorama_rule.from_dg_name == "DG-vsys1" assert vsys1_panorama_rule.position == "pre_rulebase" # vsys1's local rule should NOT be enriched vsys1_local_rule = next(r for r in vsys1_results if r.name == "LocalRule_vsys1") assert vsys1_local_rule.is_from_panorama is False assert vsys1_local_rule.from_dg_name == "" # vsys2's Panorama rule should be enriched with vsys2's DG (not vsys1's) vsys2_panorama_rule = next(r for r in vsys2_results if r.name == "PanoramaRule_v2") assert vsys2_panorama_rule.is_from_panorama is True assert vsys2_panorama_rule.from_dg_name == "DG-vsys2" assert vsys2_panorama_rule.position == "pre_rulebase" # vsys2's local rule should NOT be enriched vsys2_local_rule = next(r for r in vsys2_results if r.name == "LocalRule_vsys2") assert vsys2_local_rule.is_from_panorama is False assert vsys2_local_rule.from_dg_name == "" # Verify no cross-vsys enrichment leakage # PanoramaRule_v1 should NOT appear in vsys2 results vsys2_rule_names = {r.name for r in vsys2_results} assert "PanoramaRule_v1" not in vsys2_rule_names # PanoramaRule_v2 should NOT appear in vsys1 results vsys1_rule_names = {r.name for r in vsys1_results} assert "PanoramaRule_v2" not in vsys1_rule_names def test_panorama_upload_content_update_file_command_uses_basename(mocker): """ Given: A file entry whose name contains directory components (e.g. 'subdir/firmware.bin'). When: panorama_upload_content_update_file_command is called. Then: Only the basename is used for the local copy destination and os.remove is called for cleanup. """ import Panorama mocker.patch.object( demisto, "getFilePath", return_value={"path": "/tmp/fake_path/firmware.bin", "name": "subdir/firmware.bin"}, ) copy_mock = mocker.patch("shutil.copy") mock_file = mocker.mock_open(read_data=b"fake content") mocker.patch("builtins.open", mock_file) mocker.patch( "Panorama.http_request", return_value={"response": {"@status": "success", "msg": "upload succeeded"}}, ) remove_mock = mocker.patch("os.remove") mocker.patch("os.path.isfile", return_value=True) mocker.patch.object(Panorama, "API_KEY", "test_key") mocker.patch.object(Panorama, "URL", "https://test.example.com") Panorama.panorama_upload_content_update_file_command({"category": "content", "entryID": "entry123"}) # Assert shutil.copy was called with basename only (not the full subdir/firmware.bin) assert copy_mock.call_args[0][1] == "firmware.bin" # Assert os.remove was called remove_mock.assert_called_once_with("firmware.bin")