Below is the script i have been working on that helps to display all the firewall policies of a device group. Now I'm having trouble in making the script display the Rule usage, as used, partially used, or unused as shown next to a policy. The script keeps on returning N/A every time i run it. Can someone help?
import requests
import xml.etree.ElementTree as ET
PANORAMA_HOST = ''
API_KEY = ''
requests.packages.urllib3.disable_warnings(requests.packages.urllib3.exceptions.InsecureRequestWarning)
def get_device_groups():
url = f"{PANORAMA_HOST}/api/?type=config&action=get&key={API_KEY}&xpath=/config/devices/entry[@name='localhost.localdomain']/device-group"
try:
response = requests.get(url, verify=False)
if response.status_code != 200:
print(f"Error: Received status code {response.status_code}")
exit()
root = ET.fromstring(response.text)
except requests.RequestException as e:
print(f"Network error occurred: {e}")
exit()
except ET.ParseError:
print("Error: Unable to parse XML. Check if the API key or URL is correct.")
exit()
dg_list = []
for entry in root.findall(".//device-group/entry"😞
name = entry.attrib.get('name')
parent_elem = entry.find("parent")
parent_name = parent_elem.text if parent_elem is not None else None
dg_list.append({'name': name, 'parent': parent_name})
return dg_list
def build_hierarchy(device_groups😞
tree = {}
for dg in device_groups:
parent = dg['parent']
name = dg['name']
if parent not in tree:
tree[parent] = []
tree[parent].append(name)
return tree
def print_tree(tree, parent=None, indent='', numbered_list=None😞
if numbered_list is None:
numbered_list = []
children = tree.get(parent, [])
for child in sorted(children😞
numbered_list.append(child)
print(f"{len(numbered_list)}. {indent}{child}")
print_tree(tree, parent=child, indent=indent + ' ', numbered_list=numbered_list)
return numbered_list
def get_text_list(rule_elem, tag😞
return [e.text for e in rule_elem.findall(f"./{tag}/member")]
def get_rule_usage_data(device_group😞
cmd = f"<show><running><security-policy><usage><type>pre</type><vsys><entry name='{device_group}'/></vsys></usage></security-policy></running></show>"
url = f"{PANORAMA_HOST}/api/?type=op&cmd={cmd}&key={API_KEY}"
try:
response = requests.get(url, verify=False)
if response.status_code != 200:
print(f"Error fetching rule usage: {response.status_code}")
return {}
root = ET.fromstring(response.text)
usage_data = {}
for entry in root.findall(".//entry"😞
rule_name = entry.findtext("rule-name")
usage = entry.findtext("rule-usage")
apps_seen = entry.findtext("apps-seen")
usage_data[rule_name] = {
'rule_usage': usage,
'apps_seen': apps_seen
}
return usage_data
except Exception as e:
print(f"Error while fetching rule usage: {e}")
return {}
def check_rule_traffic_logs(rule_name, device_group, time_range='last-30-days'😞
query = f"(rule eq '{rule_name}')"
url = (f"{PANORAMA_HOST}/api/?type=log&log-type=traffic&key={API_KEY}"
f"&query={query}&device-group={device_group}&time-range={time_range}")
try:
response = requests.get(url, verify=False)
if response.status_code != 200:
print(f"Error checking logs for rule '{rule_name}': {response.status_code}")
return None
root = ET.fromstring(response.text)
entries = root.findall(".//entry")
return len(entries) > 0
except Exception as e:
print(f"Log check error for rule '{rule_name}': {e}")
return None
def get_security_policies(device_group😞
print("Fetching rule usage data...")
rule_usage_data = get_rule_usage_data(device_group)
xpath = f"/config/devices/entry[@name='localhost.localdomain']/device-group/entry[@name='{device_group}']/pre-rulebase/security/rules"
url = f"{PANORAMA_HOST}/api/?type=config&action=get&key={API_KEY}&xpath={xpath}"
try:
response = requests.get(url, verify=False)
if response.status_code != 200:
print(f"Error fetching policies: {response.status_code}")
return
root = ET.fromstring(response.text)
rules = root.findall(".//rules/entry")
if not rules:
print("\nNo security policies found in this device group.")
return
print(f"\nSecurity Policies in '{device_group}':\n")
for rule in rules:
rule_name = rule.attrib.get('name')
usage_info = rule_usage_data.get(rule_name, {})
rule_usage = usage_info.get('rule_usage', 'N/A')
apps_seen = usage_info.get('apps_seen', 'N/A')
print(f"- Rule Name : {rule_name}")
print(f" From : {get_text_list(rule, 'from')}")
print(f" To : {get_text_list(rule, 'to')}")
print(f" Source : {get_text_list(rule, 'source')}")
print(f" Destination : {get_text_list(rule, 'destination')}")
print(f" Application : {get_text_list(rule, 'application')}")
print(f" Service : {get_text_list(rule, 'service')}")
print(f" Source User : {get_text_list(rule, 'source-user')}")
print(f" Category : {get_text_list(rule, 'category')}")
print(f" HIP Profiles : {get_text_list(rule, 'hip-profiles')}")
print(f" Tags : {get_text_list(rule, 'tag')}")
print(f" Description : {rule.findtext('description')}")
print(f" Action : {rule.findtext('action')}")
print(f" Rule Type : {rule.findtext('rule-type')}")
print(f" Disabled : {rule.findtext('disabled')}")
print(f" Target : {rule.findtext('target')}")
print(f" Rule Usage : {rule_usage}")
print(f" Apps Seen : {apps_seen}")
# === New: Traffic log check ===
is_used_30d = check_rule_traffic_logs(rule_name, device_group, time_range='last-30-days')
is_used_90d = check_rule_traffic_logs(rule_name, device_group, time_range='last-90-days')
print(f" Used in Last 30 Days : {'Yes' if is_used_30d else 'No'}")
print(f" Used in Last 90 Days : {'Yes' if is_used_90d else 'No'}")
print()
except Exception as e:
print(f"Error while fetching/parsing policies: {e}")
# === Main Execution ===
if __name__ == "__main__":
print("Fetching device groups...")
device_groups = get_device_groups()
if not device_groups:
print("No device groups found.")
exit()
print("\nAvailable Device Groups (Hierarchy):")
tree = build_hierarchy(device_groups)
numbered_dgs = print_tree(tree, parent=None)
try:
selected_index = int(input("\nEnter the number corresponding to the device group: "))
selected_dg = numbered_dgs[selected_index - 1]
except (ValueError, IndexError😞
print("Invalid selection. Please run the script again and enter a valid number.")
exit()
print(f"\nYou selected device group: {selected_dg}")
get_security_policies(selected_dg)