PAN-OS-GetAvailablePANOSSoftware
This script is a wrapper for the 'pano-os-platform-get-available-software' command, adding options to return only images newer than is currently installed to minimize amount of context data generated.
python · PAN-OS by Palo Alto Networks
Details
| ID | PAN-OS-GetAvailablePANOSSoftware |
|---|---|
| Language | python |
| From Version | 6.10.0 |
| Docker Image | demisto/python3:3.12.13.10116658 |
README
This script is a wrapper for the ‘pano-os-platform-get-available-software’ command, adding options to return only images newer than is currently installed to minimize amount of context data generated.
Script Data
| Name | Description |
|---|---|
| Script Type | python3 |
| Cortex XSOAR Version | 6.10.0 |
Dependencies
This script uses the following commands and scripts.
- Panorama
- pan-os-platform-get-available-software
Used In
This script is used in the following playbooks and scripts.
- PAN-OS - Firewall Upgrade Readiness Checks
Inputs
| Argument Name | Description |
|---|---|
| device_filter_string | The string by which to filter the results to only show specific hostnames or serial numbers. |
| target | The target number of the firewall. Used only on a Panorama instance. |
| panos_instance_name | The instance name of the PAN-OS Integration to use. Specify only one instance. |
| newer_images_only | Whether to return only images newer than currently installed. |
Outputs
| Path | Description | Type |
|---|---|---|
| PANOS.SoftwareVersions.Summary.hostid | The host ID. | String |
| PANOS.SoftwareVersions.Summary.version | The software version in Major.Minor.Maint format. | String |
| PANOS.SoftwareVersions.Summary.filename | The software version filename. | String |
| PANOS.SoftwareVersions.Summary.size | The size of the software in MB. | String |
| PANOS.SoftwareVersions.Summary.size_kb | The size of the software in KB. | String |
| PANOS.SoftwareVersions.Summary.release_notes | The link to version release notes in the Palo Alto Networks knowledge base. | String |
| PANOS.SoftwareVersions.Summary.downloaded | True if the software version is present on the system. | Boolean |
| PANOS.SoftwareVersions.Summary.current | True if this is the currently installed software on the system. | Boolean |
| PANOS.SoftwareVersions.Summary.latest | True if this is the most recently released software for this platform. | Boolean |
| PANOS.SoftwareVersions.Summary.uploaded | True if the software version has been uploaded to the system. | Boolean |
import demistomock as demisto # noqa: F401 from CommonServerPython import * # noqa: F401 import traceback from typing import Any demisto.debug("pack name = PAN-OS by Palo Alto Networks, pack version = 2.2.7") def run_command(args: dict) -> dict: """run_command Runs the `pano-os-platform-get-available-software` command using the specified Integration Instance Args: args (dict): Script arguments Raises: Exception: Raises exception if the executed command returns an error response Returns: dict: A tuple of two lists: the command results list and command errors list. """ # Set command args allowed_args = ["device_filter_string", "target", "panos_instance_name"] command_args = {k: args.get(k) for k in allowed_args if k in args} # Rename 'instance_name' key to 'using' to match the command syntax, if one was provided if "panos_instance_name" in command_args: command_args["using"] = command_args.pop("panos_instance_name") # Execute the command res = demisto.executeCommand("pan-os-platform-get-available-software", command_args) # Check if the command returned an error and raise exception if needed if is_error(res): raise Exception(f"Error executing pan-os-platform-get-system-info: {get_error(res)}") # Return command results return res def get_current_version_and_base_version(versions: list) -> tuple[dict, dict]: """get_current_version_and_base_version Identify the currently installed software version and its required base version. Args: versions (list): List of PAN-OS images as returned from `pano-os-platform-get-available-software` command Raises: Exception: Raises an exception if list is missing an entry indicating the currently installed version Returns: tuple[dict]: Software image information for the current version and its required base version """ # Identify the software image labeled as currently installed for item in versions: if item["current"]: # Calculate base version of this image base_image_parts = item["version"].split(".") if base_image_parts[-1] != "0": base_image_parts = base_image_parts[0:2] base_image_parts.append("0") base_image_version = ".".join(base_image_parts) else: base_image_version = item["version"] base_version: dict = next((v for v in versions if v.get("version") == base_image_version), {}) return item, base_version # If no currently installed image was found, raise an error raise Exception("Command results did not contain a version labeled as current.") def parse_version(version: str) -> tuple[int, ...]: """parse_version Splits a PAN-OS software version string into parts. Args: version (str): The PAN-OS version string (e.g. "11.2.1-h2") Returns: tuple[str]: Parts of the PAN-OS version (major, feature, minor, hotfix) """ # Split the version into main parts and hotfix parts parts = version.split(".") major = int(parts[0]) feature = int(parts[1]) minor_and_hotfix = parts[2].split("-") minor = int(minor_and_hotfix[0]) # Identify if a hotfix version was included if len(minor_and_hotfix) == 2: # Get the hotfix number without the "h" hotfix = int(minor_and_hotfix[1][1:]) else: # No hotfix part identified - set it to 0 hotfix = 0 return (major, feature, minor, hotfix) def is_version_newer(left_image_version: str, right_image_version: str) -> bool: """is_version_newer Determine if the right PAN-OS version is newer than the left. Args: left_image_version (str): PAN-OS software version right_image_version (str): PAN-OS software version Returns: bool: True if right version newer than left, else False """ left_version_parts = parse_version(left_image_version) right_version_parts = parse_version(right_image_version) for left_part, right_part in zip(left_version_parts, right_version_parts): if left_part < right_part: return True elif left_part > right_part: return False return False # Versions are the same def filter_images(command_result: dict) -> dict: """filter_images Filter the command results from `pano-os-platform-get-available-software` to include only the currently installed release, it's required base version, and versions that are newer than currently installed. Args: command_result (dict): command results from `pano-os-platform-get-available-software` Returns: dict: Command result object with older version entries removed """ # Filter the command results to only include details of images newer than is currently installed on the device current_version, base_version = get_current_version_and_base_version(command_result[0]["Contents"]["Summary"]) # Initialize list of newer images, and include current and base versions for comparison newer_images = [current_version, base_version] # Store initial command result to be updated with filtered results filtered_command_result = command_result for version in command_result[0]["Contents"]["Summary"]: if is_version_newer(current_version.get("version", ""), version.get("version")): newer_images.append(version) # Replace versions in command result with filtered list filtered_command_result[0]["Contents"]["Summary"] = newer_images # Replace versions in entry context with filtered list filtered_command_result[0]["EntryContext"]["PANOS.SoftwareVersions"]["Summary"] = newer_images return filtered_command_result def get_available_software(args: dict[str, Any]) -> dict: """get_available_software Retrieves available PAN-OS software images and filters the output if specified. Args: args (Dict[str, Any]): Script arguments Returns: dict: Command result object """ # Store newer_images_only argument value and remove from args to pass to the command newer_images_only = args.pop("newer_images_only", "no") # Run PAN-OS command and get results command_result = run_command(args) if newer_images_only == "yes": filtered_command_result = filter_images(command_result) return filtered_command_result else: return command_result def main(): args = demisto.args() try: return_results(get_available_software(args)) except Exception as err: return_error(str(err), error=traceback.format_exc()) if __name__ in ("__main__", "__builtin__", "builtins"): main()