Disable/Remove bulk security rules in Palo Alto NGFWs using Python

Disabling and removing bulk security rules can be frustrating and time-consuming when you have many security rules in place. To address this issue I have written a Python script to make this easy and save some time rather than manually disabling each one separately. “Long Live Python!”

First, we must get an API key from the device to authenticate. To do that, we can run the following Python script;

=
import requests # Configuration FIREWALL_IP = '192.168.1.10' # Replace with your firewall's IP address USERNAME = 'USER-ID' # Replace with your username PASSWORD = 'PASSWORD' # Replace with your password def get_api_key(firewall_ip, username, password): """ Fetch the API key from the firewall using the keygen endpoint. """ url = f'https://{firewall_ip}/api/?type=keygen&user={username}&password={password}' try: # Make the GET request with SSL verification disabled response = requests.get(url, verify=False) # Check if the request was successful if response.status_code == 200: print("Response received:") print(response.text) else: print(f"Error: Received status code {response.status_code}") print(response.text) except requests.exceptions.RequestException as e: print(f"Failed to connect to the firewall: {e}") if __name__ == "__main__": get_api_key(FIREWALL_IP, USERNAME, PASSWORD)

The above Python script will generate a key like this;

<response status = 'success'><result><key>AIzaSyDaGmWKa4JsXZ-HjGw7ISLn_3namBGewQeAIzaSyDaGmWKa4JsXZ-HjGw7ISLn_3namBGewQe==</key></result></response>

It will prompt wrong credential errors when your password contains special characters, such as ! #, *, etc. If you are facing this, replace your special characters in the password as explained here. If your password is Test#123, use Test%23123

After getting the API key, we can proceed with the bulk disable and removal of the firewall policies. The following Python scipts will not commit the changes after completion. So, we have to commit the changes manually by login to the firewall. – Always verify the changes you have made, someone said to me :D. There are two python scripts listed, to disable and delete.

1. To disable the bulk security policies, run the following Python script using the text file named rules-disable.txt. Ensure that the rules-disable.txt file contains the names of the security rules to be disabled.

Names of the seuciry rules should be listed in rules-disable.txt as follows;

Python Script to Disable Security Rules:

      =
      import requests # Configuration FIREWALL_IP = '192.168.10.210' # Replace with your firewall's IP address API_KEY = 'YOUR_API_KEY' # Replace with your API key # Load rules from a file def load_rules(file_path): try: with open(file_path, 'r') as file: rules = [line.strip() for line in file.readlines()] return rules except FileNotFoundError: print(f"Error: File '{file_path}' not found.") return [] def disable_security_policy(firewall_ip, api_key, rule_name): """ Disable a specific security policy rule on the firewall. """ url = f'https://{firewall_ip}/api/?type=config&action=set' xpath = f"/config/devices/entry[@name='localhost.localdomain']/vsys/entry[@name='vsys1']/rulebase/security/rules/entry[@name='{rule_name}']" element = "yes" payload = {'key': api_key, 'xpath': xpath, 'element': element} try: response = requests.get(url, params=payload, verify=False) if response.status_code == 200: print(f"Successfully disabled rule: {rule_name}") else: print(f"Failed to disable rule: {rule_name}") print(f"Status Code: {response.status_code}, Response: {response.text}") except requests.exceptions.RequestException as e: print(f"Failed to connect to the firewall for rule {rule_name}: {e}") def main(): # Specify the path to the file containing the rules file_path = 'rules-disable.txt' rules = load_rules(file_path) if rules: for rule in rules: disable_security_policy(FIREWALL_IP, API_KEY, rule) else: print("No rules to process.") if __name__ == "__main__": main()

      After the successful disabling of the security rules, you will be getting messages like:

      Successfully disabled rule: Rule1

      2. To delete bulk security policies, run the following Python script with the text file named rules-delete.txt. Ensure that the rules-delete.txt file contains the names of the security rules to be deleted, listed as previously explained. When exporting security rules from Palo Alto devices, disabled rules appear with a [Disable] tag, e.g., [Disable] Rule1. The script handles this by removing the [Disable] tag and extracting only the rule name. So, we can delete the disabled rules as well using the script.

      Python Script to Delete Security Rules:

      =
      import requests # Configuration FIREWALL_IP = '192.168.10.210' # Replace with your firewall's IP address API_KEY = 'YOUR_API_KEY' # Replace with your API key # Load rules from a file and clean up the names def load_rules(file_path): """ Load and clean the list of rules from the specified file. Removes '[Disabled]' prefix if present in the rule name. """ try: with open(file_path, 'r') as file: # Strip whitespace and remove '[Disabled]' if present rules = [ line.replace('[Disabled]', '').strip() for line in file.readlines() if line.strip() ] return rules except FileNotFoundError: print(f"Error: File '{file_path}' not found.") return [] # Function to delete security policies def delete_security_policy(firewall_ip, api_key, rule_name): """ Delete a specific security policy rule from the firewall. """ url = f'https://{firewall_ip}/api/?type=config&action=delete' xpath = f"/config/devices/entry[@name='localhost.localdomain']/vsys/entry[@name='vsys1']/rulebase/security/rules/entry[@name='{rule_name}']" payload = {'key': api_key, 'xpath': xpath} try: response = requests.get(url, params=payload, verify=False) if response.status_code == 200: print(f"Successfully deleted rule: {rule_name}") else: print(f"Failed to delete rule: {rule_name}") print(f"Status Code: {response.status_code}, Response: {response.text}") except requests.exceptions.RequestException as e: print(f"Failed to connect to the firewall for rule {rule_name}: {e}") # Main function def main(): # Specify the path to the file containing the rules to delete file_path = 'rules-delete.txt' rules = load_rules(file_path) if rules: print(f"Found {len(rules)} rules to delete.") for rule in rules: delete_security_policy(FIREWALL_IP, API_KEY, rule) else: print("No rules to delete. Ensure the file is not empty and contains valid rule names.") if __name__ == "__main__": main()

      Hope this solution will save you time, thank you.

      Author photo
      Publication date:
      Hi! I’m Shanuka, a skilled Network Engineer working for an IT-based company in Sri Lanka. I specialize in designing, implementing, and securing complex networks, with a keen interest in emerging technologies such as cloud computing, automation, and AI-driven system optimization.

      Leave a Reply

      Your email address will not be published. Required fields are marked *