Created
October 9, 2023 09:27
-
-
Save itsecworks/400697f586532b84ba34f7b03ffdbc47 to your computer and use it in GitHub Desktop.
Palo Alto Panorama - Object Auditing scripts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/python3 | |
# -*- coding: utf-8 -*- | |
# Author: Ist wurst... | |
# | |
# Description: | |
# ------------- | |
# This script finds the reverse duplicates like: | |
# /-h_9.9.9.9 | |
#IP:9.9.9.9\32 = | |
# \-h_quadnine | |
# | |
# people tend to recreate objects that exists already with a new name... | |
# | |
import xml.etree.ElementTree as ET | |
xml_input = 'C:/Users/joe/Downloads/Panorama_20230926/panorama.xml' | |
file_output = 'C:/Users/joe/Downloads/objlist_exact_duplicates_by_content.txt' | |
tree = ET.parse(xml_input) | |
root = tree.getroot() | |
dict = {} | |
for node_addr in root.findall("./shared/address/entry"): | |
dg_name = "shared" | |
for node in node_addr: | |
if node.tag in ["ip-netmask", "fqdn", "ip-range"]: | |
if dg_name not in dict: | |
dict[dg_name] = {} | |
if node.text not in dict[dg_name]: | |
dict[dg_name][node.text] = {} | |
dict[dg_name][node.text]["type"] = node.tag | |
dict[dg_name][node.text]["objects"] = [node_addr.attrib["name"]] | |
else: | |
dict[dg_name][node.text]["objects"].append(node_addr.attrib["name"]) | |
for node_dg in root.findall("./devices/entry/device-group/entry"): | |
dg_name = node_dg.attrib["name"] | |
for dg_node in node_dg: | |
if (dg_node.tag) == "address": | |
for node_addr2 in dg_node: | |
for node2 in node_addr2: | |
if node2.tag in ["ip-netmask", "fqdn", "ip-range"]: | |
if dg_name not in dict: | |
dict[dg_name] = {} | |
if node2.text not in dict[dg_name]: | |
dict[dg_name][node2.text] = {} | |
dict[dg_name][node2.text]["type"] = node2.tag | |
dict[dg_name][node2.text]["objects"] = [node_addr2.attrib["name"]] | |
else: | |
dict[dg_name][node2.text]["objects"].append(node_addr2.attrib["name"]) | |
nuc = 0 | |
uc = 0 | |
dict2 = {} | |
with open(file_output, 'w') as fp1: | |
for dg in dict: | |
for key in dict[dg]: | |
if len(dict[dg][key]["objects"]) > 1: | |
for entry in dict[dg][key]["objects"]: | |
fp1.write(dg + "," + str(key) + "," + dict[dg][key]["type"] + "," + str(entry) + "\n") | |
nuc += 1 | |
if len(dict[dg][key]["objects"]) not in dict2: | |
dict2[len(dict[dg][key]["objects"])] = 1 | |
else: | |
dict2[len(dict[dg][key]["objects"])] += 1 | |
else: | |
uc += 1 | |
print("unique-nonu-counts," + dg + "," + str(uc) + "," + str(nuc)) | |
for counts in dict2: | |
print("multiplied," + dg + "," + str(counts) + "," + str(dict2[counts])) | |
dict2 = {} | |
nuc = 0 | |
uc = 0 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/python3 | |
# -*- coding: utf-8 -*- | |
# Author: Ist wurst... | |
# | |
# Description: | |
# ------------- | |
# This script find the unused objects with in panorama device-group hierarchy. | |
# | |
import xml.etree.ElementTree as ET | |
xml_input = 'C:/Users/joe/Downloads/Panorama_20230926/panorama.xml' | |
fileoutput_nu = 'C:/Users/joe/Downloads/objlist_notused.txt' | |
def getallchild(dg, dict, llist): | |
if dg not in dict: | |
return llist | |
else: | |
llist += dict[dg] | |
for ch_dg in dict[dg]: | |
return getallchild(ch_dg, dict, llist) | |
tree = ET.parse(xml_input) | |
root = tree.getroot() | |
readonly_node = root.find("./readonly") | |
dg_children = {} | |
for dg in readonly_node.findall("./devices/entry/device-group/entry"): | |
dg_name = dg.attrib["name"] | |
if dg.find("./parent-dg") is not None: | |
parent_dg_name = dg.find("./parent-dg").text | |
if parent_dg_name not in dg_children: | |
dg_children[parent_dg_name] = [dg_name] | |
else: | |
dg_children[parent_dg_name].append(dg_name) | |
with open(fileoutput_nu, 'w') as fp1: | |
for dg in root.findall("./devices/entry/device-group/entry"): | |
dg_name = dg.attrib["name"] | |
mylist = [] | |
dg_allchild_names = getallchild(dg_name, dg_children, mylist) | |
addresses = dg.find("./address") | |
post_rulebase = dg.find("./post-rulebase") | |
pre_rulebase = dg.find("./pre-rulebase") | |
address_group = dg.find("./address-group") | |
if addresses is not None: | |
for addr in addresses: | |
addr_name = addr.attrib["name"] | |
if pre_rulebase is None or (len(pre_rulebase) > 0 and str(ET.tostring(pre_rulebase)).find(addr_name) == -1): | |
if post_rulebase is None or (len(post_rulebase) > 0 and str(ET.tostring(post_rulebase)).find(addr_name) == -1): | |
if address_group is None or (len(address_group) > 0 and str(ET.tostring(address_group)).find(addr_name) == -1): | |
notfound = True | |
if len(dg_allchild_names) > 0: | |
for child_dg_name in dg_allchild_names: | |
child_dg = root.find("./devices/entry/device-group/entry[@name='" + child_dg_name + "']") | |
post_rulebase = child_dg.find("./post-rulebase") | |
pre_rulebase = child_dg.find("./pre-rulebase") | |
address_group = dg.find("./address-group") | |
if pre_rulebase is None or (len(pre_rulebase) > 0 and str(ET.tostring(pre_rulebase)).find(addr_name) == -1): | |
notfound = False | |
if post_rulebase is None or (len(post_rulebase) > 0 and str(ET.tostring(post_rulebase)).find(addr_name) == -1): | |
notfound = False | |
if address_group is None or (len(address_group) > 0 and str(ET.tostring(address_group)).find(addr_name) == -1): | |
notfound = False | |
if notfound is True: | |
fp1.write("{0}, {1}\n".format(dg_name, addr_name)) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment