Palo Alto API backup konfiguracji – Python skrypt
by admin · Grudzień 28, 2017
Korzystając z API możemy na firewallach Palo Alto wykonywać komendy przez przeglądarkę jednym zapytaniem bez konieczności otwierania interfejsu do zarządzania i klikania po menu.
PRZYKŁAD
Do celów demonstracji możliwości API na Palo Alto posłużyłem się topologią zbudowaną z GNS3 składającą się z 3 firewalli, switcha oraz dwóch maszyn wirtualnych (gns3-webterm – do dostepu do API przez przeglądarkę, oraz NetworkAutomation – maszyna z pythonem na której będziemy pisać skrypt).
TOPOLOGIA
API
W celu dostępu do API musimy wygenerować klucz API, który będzie wykorzystywany do zapytań do API. Klucz jest generowany z użytkownika i hasła, więc jeśli posiadamy kilka firewalli i na każdym z nich mamy tego samego usera i hasło to klucz będzie taki sam dla każdego urządzenia.
Do generacji klucza służy następujące zapytanie:
https://firewall_ip/api/?type=keygen&user=username&password=password
Sprawdźmy jak to wygląda na żywo. W tym celu wchodzimy do gns3-webterm i wpisujemy w przeglądarce podany URL zamieniając firewall_ip na jeden z adresów IP firewalli oraz wpisując poprawny login i hasło:
https://192.168.0.201/api/?type=keygen&user=admin&password=admin
Jak widać z powyższego screena dostaliśmy w odpowiedzi plik XML, który zawiera klucz postaci:
LUFRPT14MW5xOEo1R09KVlBZNnpnemh0VHRBOWl6TGM9bXcwM3JHUGVhRlNiY0dCR0srNERUQT09
To samo możemy uzyskać na maszynie NetworkAutomation korzystając z programu curl i komendy:
root@NetworkAutomation-1:~# curl -X GET 'https://192.168.0.201/api/?type=keygen&user=admin&password=admin' --insecure
<response status = 'success'><result><key>LUFRPT14MW5xOEo1R09KVlBZNnpnemh0VHRBOWl6TGM9bXcwM3JHUGVhRlNiY0dCR0srNERUQT09</key></result></response>
Po otrzymaniu klucza możemy wykonać jakąś komendę przez API. Listę komend i składnię zapytań możemy znaleźć wpisując w przeglądarce https://firewall_ip/api
Do eksportu konfiguracji służy zapytanie postaci:
https://firewall_ip/api/?type=export&category=configuration&key=<key>
gdzie <key> to klucz otrzymany z wcześniejszej komendy. Całe zapytanie wygląda więc następująco:
https://192.168.0.201/api/?type=export&category=configuration&key=LUFRPT14MW5xOEo1R09KVlBZNnpnemh0VHRBOWl6TGM9bXcwM3JHUGVhRlNiY0dCR0srNERUQT09
Spróbujmy teraz to samo uzyskać korzystając z curl’a:
root@NetworkAutomation-1:~# curl -X GET 'https://192.168.0.201/api/?type=export&category=configuration&key=LUFRPT14MW5xOEo1R09KVlBZNnpnemh0VHRBOWl6TGM9bXcwM3JHUGVhRlNiY0dCR0srNERUQT09' --insecure
<config version="7.1.0" urldb="paloaltonetworks"><mgt-config><users><entry name="admin"><phash>fnRL/G5lXVMug</phash><permissions><role-based><superuser>yes</superuser></role-based></permissions></entry></users></mgt-config><shared><application/><application-group/><service/><service-group/><botnet><configuration><http><dynamic-dns><enabled>yes</enabled><threshold>5</threshold></dynamic-dns><malware-sites><enabled>yes</enabled><threshold>5</threshold></malware-sites><recent-domains><enabled>yes</enabled><threshold>5</threshold></recent-domains><ip-domains><enabled>yes</enabled><threshold>10</threshold></ip-domains><executables-from-unknown-sites><enabled>yes</enabled><threshold>5</threshold></executables-from-unknown-sites></http><other-applications><irc>yes</irc></other-applications><unknown-applications><unknown-tcp><destinations-per-hour>10</destinations-per-hour><sessions-per-hour>10</sessions-per-hour><session-length><maximum-bytes>100</maximum-bytes><minimum-bytes>50</minimum-bytes></session-length></unknown-tcp><unknown-udp><destinations-per-hour>10</destinations-per-hour><sessions-per-hour>10</sessions-per-hour><session-length><maximum-bytes>100</maximum-bytes><minimum-bytes>50</minimum-bytes></session-length></unknown-udp></unknown-applications></configuration> ........
Widzimy, że otrzymaliśmy ten sam plik xml. Teraz możemy spróbować napisać skrypt, który wykona tą operację za nas i zapisze taki plik na dysk, dla każdego z firewalli.
SKRYPT
Skrypt jest bardzo prosty i wygląda nastepująco:
backup_config.py
#!/usr/bin/python
import requests, datetime
from lxml import etree
firewalls_ip = [
'192.168.0.201',
'192.168.0.202',
'192.168.0.203'
]
date_1 = datetime.datetime.now().strftime("%Y-%m-%d_%H:%M")
key = 'LUFRPT14MW5xOEo1R09KVlBZNnpnemh0VHRBOWl6TGM9bXcwM3JHUGVhRlNiY0dCR0srNERUQT09'
params = (
('type', 'export'),
('category', 'configuration'),
('key', key),
)
for hostname in firewalls_ip:
print "Saving config for : %s" %hostname
url = "https://"+hostname+"/api/"
response = requests.get(url, params=params, verify=False)
xml_str = response.text
root = etree.fromstring(xml_str)
filename = "running-config-"+hostname+"-"+date_1+".xml"
file = open(filename,"w")
file.write("""\n""")
file.write(etree.tostring(root, pretty_print=True))
file.close()
Sprawdźmy jego działanie w praktyce:
root@NetworkAutomation-1:~# ./backup_config.py
Saving config for : 192.168.0.201
/usr/local/lib/python2.7/dist-packages/urllib3/connectionpool.py:858: InsecureRequestWarning: Unverified HTTPS request is being made. Adding certificate verification is strongly advised. See: https://urllib3.readthedocs.io/en/latest/advanced-usage.html#ssl-warnings
InsecureRequestWarning)
Saving config for : 192.168.0.202
/usr/local/lib/python2.7/dist-packages/urllib3/connectionpool.py:858: InsecureRequestWarning: Unverified HTTPS request is being made. Adding certificate verification is strongly advised. See: https://urllib3.readthedocs.io/en/latest/advanced-usage.html#ssl-warnings
InsecureRequestWarning)
Saving config for : 192.168.0.203
/usr/local/lib/python2.7/dist-packages/urllib3/connectionpool.py:858: InsecureRequestWarning: Unverified HTTPS request is being made. Adding certificate verification is strongly advised. See: https://urllib3.readthedocs.io/en/latest/advanced-usage.html#ssl-warnings
InsecureRequestWarning)
Skrypt wykonał się z ostrzeżeniami, ale możemy je zignorować. Pojawiły się one, ponieważ wszystkie urządzenia posiadają domyślne certyfikaty, które nie są zaufane.
Sprawdźmy teraz jak wygląda katalog w którym jest skrypt:
-rwxr-xr-x 1 root root 809 Dec 28 19:36 backup_config.py
-rw-r--r-- 1 root root 9161 Dec 28 19:36 running-config-192.168.0.201-2017-12-28_19:36.xml
-rw-r--r-- 1 root root 9161 Dec 28 19:36 running-config-192.168.0.202-2018-12-28_19:36.xml
-rw-r--r-- 1 root root 9161 Dec 28 19:36 running-config-192.168.0.203-2018-12-28_19:36.xml
Widać, że stworzone zostały trzy pliki zgodnie z oczekiwaniami dla każdego z firewalli. Otwórzmy teraz jeden z nich i zobaczmy jak wygląda:
root@NetworkAutomation-1:~# cat running-config-192.168.0.201-2017-12-28_19:36.xml
<?xml version="1.0"?>
<config version="7.1.0" urldb="paloaltonetworks">
<mgt-config>
<users>
<entry name="admin">
<phash>fnRL/G5lXVMug</phash>
<permissions>
<role-based>
<superuser>yes</superuser>
</role-based>
</permissions>
</entry>
</users>
</mgt-config>
<shared>
<application/>
<application-group/>
<service/>
<service-group/>
<botnet>
<configuration>
<http>
<dynamic-dns>
<enabled>yes</enabled>
<threshold>5</threshold>
</dynamic-dns>
...
PODSUMOWANIE
Jak widać API na urządzeniach Palo Alto umożliwia w łatwy sposób eksportować konfigurację, dzięki czemu w przypadku awarii urządzenia mamy kopię konfiguracji. Jest to bardzo przydatne zwłaszcza w sytuacji gdy mamy wiele firewalli do administracji. W kolejnych wpisach pokaże więcej możliwości wykorzystania API na urządzeniach Palo Alto.