Automating the Palo Alto NGFW's Process/Deamon Restarts with Python PEXPECT

cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 
General Articles
6 min read
Cyber Elite
No ratings

In my previous article, Automating the Palo Alto NGFW's Process/Deamon Restarts,” I detailed how to orchestrate process restarts using TCL Expect paired with Bash scripts. While TCL Expect remains a classic approach for SSH-based network automation, modern engineering workflows are far better served by utilizing Python alongside the pexpect module. (I highly recommend reviewing that original article for foundational context).

 

I also previously demonstrated how to achieve this scale using Ansible AWX inside LIVEcommunity (Use Ansible AWX to automate the Palo Alto NGFW's management and even Process/Daemon Restarts!). However, if your environment already runs Cortex XSOAR or Cortex XSIAM, spinning up an entire multi-container Ansible AWX infrastructure—potentially managed on top of Kubernetes (K8s)—just to trigger a process restart is likely excessive.

 

Because Cortex XSOAR already features robust, native content packs for standard PAN-OS commands (available via the Palo Alto Networks Marketplace), we can streamline the architecture. By embedding a custom pexpect script directly into XSOAR, the process restart logic integrates cleanly into a broader, automated CI/CD pipeline without the overhead of external container orchestrators.

 

nikoolayy1_0-1778420526161.png

 

To get started, you will need an environment running Ubuntu with Python 3 (installed by default in recent Ubuntu distributions). We recommend using a Python virtual environment (venv) to isolate your pip packages. Think of a virtual environment as one of the original forms of virtualization pre-dating Docker containers—though, as demonstrated at the end of this guide, building a dedicated container remains a highly effective option as well.

 

python3 --version
Python 3.12.3

apt install -y python3-venv
python3 -m venv /home/niki/panos-venv
source /home/niki/panos-venv/bin/activate
pip install pexpect packaging

 

The script below demonstrates how to programmatically restart a specific daemon process across multiple Palo Alto Networks firewalls sequentially. The script reads targeted firewall management IP addresses or hostnames line-by-line from a local file named firewalls.txt located in the same directory.

 

#!/usr/bin/env python3

import pexpect
import sys
import getpass

USERNAME = input("Username: ")
PASSWORD = getpass.getpass("Password: ")

#
# Process variable
#
PROCESS_NAME = "web-server"

PROMPT = r"\S+@\S+>"

with open("firewalls.txt") as f:
    FW_LIST = [line.strip() for line in f if line.strip()]

for FW_IP in FW_LIST:

    print(f"\n===== CONNECTING TO {FW_IP} =====\n")

    child = pexpect.spawn(
        f"ssh -tt -o StrictHostKeyChecking=no {USERNAME}@{FW_IP}",
        encoding="utf-8",
        timeout=120
    )

    child.logfile = sys.stdout

    #
    # Login
    #
    child.expect("Password:")
    child.sendline(PASSWORD)

    child.expect(PROMPT)

    #
    # CLI settings
    #
    child.sendline("set cli scripting-mode on")
    child.expect(PROMPT)

    child.sendline("set cli pager off")
    child.expect(PROMPT)

    child.sendline("set cli terminal width 500")
    child.expect(PROMPT)

    #
    # Restart process
    #
    COMMAND = f"debug software restart process {PROCESS_NAME}"

    print(f"\nRunning command: {COMMAND}\n")

    child.sendline(COMMAND)

    #
    # Wait for command echo
    #
    child.expect(COMMAND)

    #
    # Wait for prompt
    #
    child.expect(PROMPT)

    output = child.before

    print("\n========== COMMAND OUTPUT ==========\n")
    print(output)
    print("\n====================================\n")

    #
    # Exit
    #
    child.sendline("exit")
    child.expect(pexpect.EOF)

    print(f"\nSession closed for {FW_IP}\n")

 

Below is an example execution trace running the automation script. The username and password credentials are securely collected at runtime via prompt inputs, and the target firewall parameters are parsed sequentially out of the local firewalls.txt file.

 

In this execution log, the script successfully authenticates to the firewall, configures the terminal environment variables, and executes the target daemon restart command:

 

 python restart-script.py sslmgr
Username: admin
Password:

===== CONNECTING TO 192.168.1.108 =====

(admin@192.168.1.108) Password: xxxx

Last login: Sun May 10 09:12:46 2026 from 192.168.1.106



Number of failed attempts since last successful login: 0



admin@PA-VM> set cli scripting-mode on
admin@PA-VM> set cli scripting-mode on
set cli pager off
set cli terminal width 500

Running command: debug software restart process sslmgr

debug software restart process sslmgr
set cli pager off
admin@PA-VM> set cli terminal width 500
admin@PA-VM> debug software restart process sslmgr
admin@PA-VM>

========== COMMAND OUTPUT ==========




====================================

exit
exit
Process sslmgr was restarted by user admin
admin@PA-VM> Connection to 192.168.1.108 closed.

Session closed for 192.168.1.108

 

The source code for this automation script is available on my GitHub repository:

 

 Nikoolayy1/palo-alto-python-scripts

 

For almost all other operational and configuration tasks, I highly recommend using the Palo Alto Networks PAN-OS SDK for Python 1.12.1 documentation.

 

If you try to run a standard operational command like show system info via raw SSH and extract specific values (such as the software version) using Python's re (regex) or xml modules, you will quickly find that parsing raw text or complex XML schemas is incredibly difficult and prone to breaking. Just stick with the  Python SDK that uses the API and only use the pexpect module for process restarts.

 

For the python SDK you will need the below python packages:

pip install pan-os-python
pip install setuptools

 

Example code is:

 

    fw = Firewall(
        hostname=FW_IP,
        api_username=USERNAME,
        api_password=PASSWORD,
    )

    result = fw.op("show system info")

    sw_version = result.find(".//sw-version").text
    hostname = result.find(".//hostname").text
    logdb_version = result.find(".//logdb-version").text

    print("hostname:", hostname)
    print("sw-version:", sw_version)
    print("logdb-version:", logdb_version

 

Emphasizing the power of combining the two tools (the Python SDK for conditional checking and pexpect for execution) to build smart automation.

 

You can find a complete, end-to-end example on my GitHub repository demonstrating how to combine these two methodologies effectively.

The complete script uses the PAN-OS Python SDK to cleanly query the firewall's current software version. If the SDK detects a specific target baseline—for instance, PAN-OS 10.1.4—the script then conditionally triggers the fallback pexpect SSH routine to perform the daemon process restart.

Attempting to build this type of conditional logic using legacy TCL Expect would be extraordinarily difficult. Fetching raw SSH output, passing it across tools, and attempting to parse the string variables manually using regex or Bash filters is simply too fragile for modern production workflows. Combining the native SDK with pexpect provides a highly robust, enterprise-ready automation wrapper.

 

palo-alto-python-scripts/restart-if-version.py at main · Nikoolayy1/palo-alto-python-scripts

 

To package your automation dependencies seamlessly and ensure your scripts run consistently across your entire team, you can wrap your environment inside a Docker container.

 

The configuration below establishes a persistent volume mount between your host operating system's directory (<home directory>/scripts/py) and the container workspace. This allows you to easily share and modify Python scripts on your local system while the container handles the secure execution baseline.

 

cat Dockerfile
FROM python:3.11-slim

RUN apt-get update && apt-get install -y \
    openssh-client \
    sshpass \
    iputils-ping \
    curl \
    && rm -rf /var/lib/apt/lists/*

RUN pip install --no-cache-dir \
    pexpect \
    packaging \
    pan-os-python

WORKDIR /app

COPY . /app

CMD ["/bin/bash"]


docker build -t panos-python:1.0 .

docker run -it --rm   -v /home/niki/scripts/py:/app   panos-python:1.0
Rate this article:
Comments
Community Manager

@nikoolayy1 Terrific breakdown! I really appreciate the context you provided around Cortex XSOAR!

  • 87 Views
  • 1 comments
  • 1 Likes
Contributors
Labels
Article Dashboard
Version history
Last Updated:
‎06-09-2026 06:30 AM
Updated by: