Skip to content

Instantly share code, notes, and snippets.

@fahadysf
Created August 31, 2023 08:54
Show Gist options
  • Save fahadysf/f7a490df78367c2eff97348a816468ef to your computer and use it in GitHub Desktop.
Save fahadysf/f7a490df78367c2eff97348a816468ef to your computer and use it in GitHub Desktop.
Simple Python script to backup the running config from PAN-OS Firewalls or Panorama
import os
import sys
import requests
import argparse
import getpass
import time
# This is a simple Python script which can be run as a Scheduled Task
# to backup the running config from PAN-OS Firewalls or Panorama. Tested to work with
# Python 3.11.5 on Mac OSX and Windows Server 2019.
# --------------------------
# License: MIT License
# Copyright (c) 2023 Fahad Yousuf <fahadysf@gmail.com>
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in all
# copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
# SOFTWARE.
# ---- CONFIG PARAMETERS ----
home_dir = os.path.expanduser("~")
api_key_path = home_dir + "/.secure/"
backup_path = home_dir + "/panos-backup/"
# ---------------------------
def create_paths(api_key_path: str, backup_path: str) -> None:
# Create the backup and API key folders if they don't exist
if not os.path.exists(api_key_path):
os.makedirs(api_key_path)
if not os.path.exists(backup_path):
os.makedirs(backup_path)
return
def get_api_key(
api_key_path: str, panos_ip: str, panos_username: str, panos_password: str
) -> str:
# Check if API key file exists
api_key_file = f"{api_key_path}panos_api_key.{panos_ip}.{panos_username}.key"
if os.path.exists(api_key_file):
print("API key found in " + api_key_file)
# Read API key from file
with open(api_key_file, "r") as file:
api_key = file.read().replace("\n", "")
else:
# Generate API key and save it to file
if panos_password is None:
# Input password without echo to terminal
panos_password = getpass.getpass("PAN-OS password: ")
api_key = generate_api_key(panos_ip, panos_username, panos_password)
try:
with open(api_key_file, "w") as file:
file.write(api_key)
except Exception as e:
print("Error: " + str(e))
sys.exit(1)
else:
print("API key saved to " + api_key_file)
return api_key
def generate_api_key(panos_ip: str, panos_username: str, panos_password: str) -> str:
# Generate API key by sending username and urlencoded password
encoded_password = requests.utils.quote(panos_password, safe="")
url = f"https://{panos_ip}/api/?type=keygen&user={panos_username}&password={encoded_password}"
response = requests.get(url, verify=False)
try:
api_key = response.text.split("<key>")[1].split("</key>")[0]
except Exception as e:
print("Error: " + str(e))
print("Response: " + response.text)
sys.exit(1)
return api_key
def backup_running_config(panos_ip: str, api_key: str) -> None:
# Backup running config
url = f"https://{panos_ip}/api/?type=export&category=configuration&key={api_key}"
response = requests.get(url, verify=False)
try:
# Save response to file with timestamp yyyyMMdd-HHmm
backup_file_path = (
f"{backup_path}{time.strftime('%Y%m%d-%H%M')}-running-config-{panos_ip}.xml"
)
with open(backup_file_path, "w") as file:
file.write(response.text)
except Exception as e:
print("Error: " + str(e))
sys.exit(1)
else:
print("Backup saved to " + backup_file_path)
return
if __name__ == "__main__":
# Get panos_ip, panos_username, panos_password from command line
parser = argparse.ArgumentParser()
parser.add_argument("panos_ip", help="PAN-OS IP address or hostname")
parser.add_argument("panos_username", help="PAN-OS username")
# Add panos_password as optional argument
parser.add_argument(
"panos_password",
nargs="?",
help="PAN-OS password. If not provided, you will be prompted to enter it.",
)
parser.add_help = True
args = parser.parse_args()
panos_ip = args.panos_ip
panos_username = args.panos_username
# Display help message if no arguments are provided
if len(sys.argv) == 1:
parser.print_help(sys.stderr)
sys.exit(1)
# Create the backup and API key folders if they don't exist
create_paths(api_key_path, backup_path)
# Get API key from file or generate it
api_key = get_api_key(api_key_path, panos_ip, panos_username, args.panos_password)
# Backup running config
backup_running_config(panos_ip, api_key)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment