Cała moc interakcji z API ujawnia się przy wspólnym użyciu z kodem programistycznym, gdy pojawiają się możliwości dynamicznego formułowania zapytań API oraz narzędzi do analizy odpowiedzi API. Jednak wciąż pozostaje mało zauważone Python Software Development Kit (dalej — Python SDK) dla Check Point Management API, co jest niesłuszne. Znacząco ułatwia życie programistom i entuzjastom automatyzacji. Python zyskał ogromną popularność w ostatnim czasie i postanowiłem wypełnić lukę, przedstawiając przegląd podstawowych możliwości . Niniejszy artykuł stanowi doskonałe uzupełnienie innego artykułu na Habra . Rozważymy, jak napisać skrypty przy użyciu Python SDK i skupimy się bardziej na nowym funkcjonalności Management API w wersji 1.6 (obsługiwanej od R80.40). Do zrozumienia artykułu potrzebna będzie podstawowa wiedza na temat pracy z API i Pythonem.
Check Point aktywnie rozwija API i obecnie pojawiły się:
- — praca z serwerem zarządzania przez API (i możliwość wykonywania skryptów na bramkach zarządzanych przez serwer zarządzania)
- — praca z bramkami bezpieczeństwa
- — praca z piaskownicą w chmurze Check Point
- — praca z blade Identity Awareness na bramkach
- — praca z portalem zarządzania bramkami SMB ()
- — interakcja z kontrolerami IoT
- — praca z (rozwiązanie SD-WAN security)
- — praca z
Python SDK obecnie obsługuje interakcję tylko z Management API i Gaia API. Rozważymy najważniejsze klasy, metody i zmienne w tym module.

Instalacja modułu
Moduł cpapi instalacja jest szybka i prosta z z pomocą pip. Szczegółowa instrukcja instalacji znajduje się w . Moduł ten jest dostosowany do pracy z wersjami Pythona 2.7 i 3.7. W artykule przykłady będą podane z użyciem Pythona 3.7. Jednak Python SDK można uruchamiać bezpośrednio z serwera zarządzania Check Point (Smart Management), ale na nich obsługiwana jest tylko wersja Python 2.7, dlatego w ostatniej sekcji zostanie podany kod dla wersji 2.7. Tuż po zainstalowaniu modułu zalecam zapoznanie się z przykładami w katalogach examples_python2 i examples_python3.
Rozpoczęcie pracy
Aby umożliwić nam pracę z komponentami modułu cpapi, należy zaimportować je z modułu cpapi co najmniej dwie wymagane klasy:
APIClient i APIClientArgs
from cpapi import APIClient, APIClientArgs
Klasa APIClientArgs odpowiada za parametry połączenia z API serwerem, a klasa APIClient odpowiada za interakcję z API.
Definiujemy parametry połączenia
Aby określić różne parametry połączenia z API, należy utworzyć instancję klasy APIClientArgs. W zasadzie jej parametry są zdefiniowane wcześniej, więc podczas uruchamiania skryptu na serwerze zarządzania nie trzeba ich podawać.
client_args = APIClientArgs()Jednak podczas uruchamiania na zewnętrznym hoście należy podać co najmniej adres IP lub nazwę hosta serwera API (to ten sam serwer zarządzania). W poniższym przykładzie definiujemy parametr połączenia server i przypisujemy mu w postaci ciągu adres IP serwera zarządzania.
client_args = APIClientArgs(server='192.168.47.241')Przyjrzyjmy się wszystkim parametrom i ich wartościom domyślnym, które można wykorzystać podczas połączenia z serwerem API:
Argumenty metody __init__ klasy APIClientArgs
class APIClientArgs:
"""
Ta klasa dostarcza argumenty do konfiguracji APIClient.
Wszystkie argumenty są skonfigurowane z ich wartościami domyślnymi.
"""
# port jest ustawiony na None domyślnie, ale zostaje zastąpiony przez 443, jeśli nie jest określony
# wartości kontekstu - web_api (domyślnie) lub gaia_api
def __init__(self, port=None, fingerprint=None, sid=None, server="127.0.0.1", http_debug_level=0,
api_calls=None, debug_file="", proxy_host=None, proxy_port=8080,
api_version=None, unsafe=False, unsafe_auto_accept=False, context="web_api"):
self.port = port
# odcisk palca serwera zarządzania
self.fingerprint = fingerprint
# identyfikator sesji.
self.sid = sid
# nazwa serwera zarządzania lub adres IP
self.server = server
# poziom debugowania
self.http_debug_level = http_debug_level
# tablica ze wszystkimi wywołaniami API (do celów debugowania)
self.api_calls = api_calls if api_calls else []
# nazwa pliku debugowania. Jeśli pozostawiony pusty, dane debugowania nie będą zapisywane na dysku.
self.debug_file = debug_file
# adres serwera proxy HTTP (bez "http://")
self.proxy_host = proxy_host
# port serwera proxy HTTP
self.proxy_port = proxy_port
# wersja API serwera zarządzania
self.api_version = api_version
# Wskazuje, że klient nie powinien sprawdzać certyfikatu serwera
self.unsafe = unsafe
# Wskazuje, że klient powinien automatycznie zaakceptować i zapisać certyfikat serwera
self.unsafe_auto_accept = unsafe_auto_accept
# Kontekst użycia klienta - domyślnie web_api
self.context = contextUważam, że argumenty, które można wykorzystać w instancjach klasy APIClientArgs, są intuicyjnie zrozumiałe dla administratorów Check Point i nie wymagają dodatkowych komentarzy.
Łączymy się za pomocą APIClient i menedżera kontekstu
Klasa APIClient najwygodniej jest korzystać z menedżera kontekstu. Wszystko, co należy przekazać instancji klasy APIClient, to parametry połączenia, które zostały określone w poprzednim kroku.
with APIClient(client_args) as client:
Menadżer kontekstu nie będzie automatycznie wywoływał login na serwerze API, jednak wykona wywołanie logout po jego zakończeniu. Jeśli z jakichś przyczyn wywołanie logout po pracy z wywołaniami API nie jest wymagane, należy rozpocząć pracę bez użycia menadżera kontekstu:
client = APIClient(client_args)Sprawdzenie połączenia
Najprościej jest sprawdzić, czy połączenie odbywa się zgodnie z zdefiniowanymi parametrami, używając metody check_fingerprint. Jeśli sprawdzenie sumy kontrolnej sha1 dla certyfikatu fingerprint serwera API nie zakończy się pomyślnie (metoda zwróciła Fałsz), zazwyczaj jest to spowodowane problemami z połączeniem i możemy zatrzymać działanie programu (lub dać użytkownikowi możliwość poprawienia danych do połączenia):
if client.check_fingerprint() is False:
print("Nie można uzyskać fingerprintu serwera - Sprawdź łączność z serwerem.")
exit(1)
Pamiętaj, że w przyszłości klasa APIClient będzie sprawdzać przy każdym wywołaniu API (metody api_call i api_query, o których będzie mowa później) sha1 fingerprint certyfikatu na serwerze API. A jeśli podczas sprawdzania sha1 fingerprint certyfikatu na serwerze API wystąpi błąd (certyfikat jest nieznany lub został zmieniony), metoda check_fingerprint umożliwi dodanie/zmienienie informacji o nim na lokalnej maszynie w trybie automatycznym. Tę kontrolę można całkowicie wyłączyć (jednak zaleca się to tylko w przypadku uruchamiania skryptów na samym serwerze API, podczas łączenia z 127.0.0.1), używając argumentu APIClientArgs — unsafe_auto_accept (szczegóły na temat APIClientArgs wcześniej w „Określenie parametrów połączenia”).
client_args = APIClientArgs(unsafe_auto_accept=True)Logowanie na serwerze API
U APIClient są trzy metody logowania na serwerze API, a każda z nich przechowuje wartość sid(session-id), która jest automatycznie używana w każdym kolejnym wywołaniu API w nagłówku (nazwa tego parametru w nagłówku to X-chkp-sid), więc nie ma potrzeby dodatkowego przetwarzania tego parametru.
Metoda login
Opcja z użyciem loginu i hasła (w przykładzie nazwa użytkownika admin i hasło 1q2w3e przekazane jako argumenty pozycyjne):
login = client.login('admin', '1q2w3e') W metodzie login dostępne są również dodatkowe opcjonalne parametry, podaję ich nazwy i wartości domyślne:
continue_last_session=False, domain=None, read_only=False, payload=NoneMetoda login_with_api_key
Opcja z użyciem klucza API (wspierana od wersji zarządzania R80.40/Management API v1.6, „3TsbPJ8ZKjaJGvFyoFqHFA==” to jest wartość klucza API dla jednego z użytkowników na serwerze zarządzania z metodą autoryzacji klucza API:
login = client.login_with_api_key('3TsbPJ8ZKjaJGvFyoFqHFA==') W metodzie login_with_api_key dostępne są takie same opcjonalne parametry jak w metodzie login.
Metoda login_as_root
Opcja logowania na lokalną maszynę z serwerem API:
login = client.login_as_root()Dla tej metody dostępne są tylko dwa opcjonalne parametry:
domain=None, payload=NoneI w końcu same wywołania API
Mamy dwie opcje wykonywania wywołań API przez metody api_call i api_query. Zobaczmy, na czym polega różnica.
api_call
Ta metoda jest stosowalna dla każdego wywołania. Musimy przekazać ostatnią część do wywołania API i payload w ciele żądania w razie potrzeby. Jeśli payload jest pusty, nie trzeba go w ogóle przekazywać:
api_versions = client.api_call('show-api-versions') Wynik dla tego zapytania poniżej:
In [23]: api_versions
Out[23]:
APIResponse({
"data": {
"current-version": "1.6",
"supported-versions": [
"1",
"1.1",
"1.2",
"1.3",
"1.4",
"1.5",
"1.6"
]
},
"res_obj": {
"data": {
"current-version": "1.6",
"supported-versions": [
"1",
"1.1",
"1.2",
"1.3",
"1.4",
"1.5",
"1.6"
]
},
"status_code": 200
},
"status_code": 200,
"success": true
})
show_host = client.api_call('show-host', {'name' : 'h_8.8.8.8'})Wynik dla tego zapytania poniżej:
W [25]: show_host
Out[25]:
APIResponse({
"data": {
"color": "czarny",
"comments": "",
"domain": {
"domain-type": "domena",
"name": "Użytkownik SMC",
"uid": "41e821a0-3720-11e3-aa6e-0800200c9fde"
},
"groups": [],
"icon": "Objects/host",
"interfaces": [],
"ipv4-address": "8.8.8.8",
"meta-info": {
"creation-time": {
"iso-8601": "2020-05-01T21:49+0300",
"posix": 1588358973517
},
"creator": "admin",
"last-modifier": "admin",
"last-modify-time": {
"iso-8601": "2020-05-01T21:49+0300",
"posix": 1588358973517
},
"lock": "odblokowane",
"validation-state": "ok"
},
"name": "h_8.8.8.8",
"nat-settings": {
"auto-rule": false
},
"read-only": false,
"tags": [],
"type": "host",
"uid": "c210af07-1939-49d3-a351-953a9c471d9e"
},
"res_obj": {
"data": {
"color": "czarny",
"comments": "",
"domain": {
"domain-type": "domena",
"name": "Użytkownik SMC",
"uid": "41e821a0-3720-11e3-aa6e-0800200c9fde"
},
"groups": [],
"icon": "Objects/host",
"interfaces": [],
"ipv4-address": "8.8.8.8",
"meta-info": {
"creation-time": {
"iso-8601": "2020-05-01T21:49+0300",
"posix": 1588358973517
},
"creator": "admin",
"last-modifier": "admin",
"last-modify-time": {
"iso-8601": "2020-05-01T21:49+0300",
"posix": 1588358973517
},
"lock": "odblokowane",
"validation-state": "ok"
},
"name": "h_8.8.8.8",
"nat-settings": {
"auto-rule": false
},
"read-only": false,
"tags": [],
"type": "host",
"uid": "c210af07-1939-49d3-a351-953a9c471d9e"
},
"status_code": 200
},
"status_code": 200,
"success": true
})
api_query
Od razu zaznaczam, że ta metoda dotyczy wywołań, których rezultaty zakładają offset (przesunięcie). Taki rezultat następuje, gdy zawiera lub może zawierać dużą ilość informacji. Na przykład może to być zapytanie o listę wszystkich utworzonych obiektów typu host na serwerze zarządzania. Dla takich zapytań API zwraca domyślnie listę 50 obiektów (limit można zwiększyć do 500 obiektów w odpowiedzi). I aby nie pobierać informacji kilka razy, zmieniając parametr offset w zapytaniu API, istnieje metoda api_query, która wykonuje tę pracę automatycznie. Przykłady wywołań, w których potrzeba tej metody: show-sessions, show-hosts, show-networks, show-wildcards, show-groups, show-address-ranges, show-simple-gateways, show-simple-clusters, show-access-roles, show-trusted-clients, show-packages. W rzeczywistości w nazwach tych wywołań API widzimy słowa w liczbie mnogiej, więc te wywołania będzie łatwiej przetwarzać przez api_query
show_hosts = client.api_query('show-hosts') Wynik dla tego zapytania poniżej:
W [21]: pokaz_hosty
Out[21]:
APIResponse({
"data": [
{
"domain": {
"domain-type": "domain",
"name": "Użytkownik SMC",
"uid": "41e821a0-3720-11e3-aa6e-0800200c9fde"
},
"ipv4-address": "192.168.47.1",
"name": "h_192.168.47.1",
"type": "host",
"uid": "5d7d7086-d70b-4995-971a-0583b15a2bfc"
},
{
"domain": {
"domain-type": "domain",
"name": "Użytkownik SMC",
"uid": "41e821a0-3720-11e3-aa6e-0800200c9fde"
},
"ipv4-address": "8.8.8.8",
"name": "h_8.8.8.8",
"type": "host",
"uid": "c210af07-1939-49d3-a351-953a9c471d9e"
}
],
"res_obj": {
"data": {
"from": 1,
"objects": [
{
"domain": {
"domain-type": "domain",
"name": "Użytkownik SMC",
"uid": "41e821a0-3720-11e3-aa6e-0800200c9fde"
},
"ipv4-address": "192.168.47.1",
"name": "h_192.168.47.1",
"type": "host",
"uid": "5d7d7086-d70b-4995-971a-0583b15a2bfc"
},
{
"domain": {
"domain-type": "domain",
"name": "Użytkownik SMC",
"uid": "41e821a0-3720-11e3-aa6e-0800200c9fde"
},
"ipv4-address": "8.8.8.8",
"name": "h_8.8.8.8",
"type": "host",
"uid": "c210af07-1939-49d3-a351-953a9c471d9e"
}
],
"to": 2,
"total": 2
},
"status_code": 200
},
"status_code": 200,
"success": true
})
Przetwarzanie wyników wywołań API
Po tym można używać zmiennych i metod klasy APIResponse(zarówno wewnątrz menedżera kontekstu, jak i na zewnątrz). Klasa APIResponse ma zdefiniowane 4 metody i 5 zmiennych, na najważniejszych zatrzymamy się dokładniej.

success
Na początek byłoby dobrze upewnić się, że wywołanie API zakończyło się sukcesem i zwróciło wynik. W tym celu dostępna jest metoda success:
W [49]: api_versions.success
Out[49]: True
Zwraca True, jeśli wywołanie API zakończyło się sukcesem (Kod odpowiedzi — 200) i False, jeśli nie udało się (jakikolwiek inny kod odpowiedzi). Łatwo używać od razu po wywołaniu API, aby w zależności od kodu odpowiedzi wyświetlić różne informacje.
if api_ver.success:
print(api_versions.data)
else:
print(api_versions.err_message) statuscode
Zwraca kod odpowiedzi po wykonaniu wywołania API.
W [62]: api_versions.status_code
Out[62]: 400
Możliwe kody odpowiedzi: 200,400,401,403,404,409,500,501.
set_success_status
W takim przypadku może być konieczne zmienienie wartości statusu success. Technicznie można tam umieścić cokolwiek, nawet zwykły ciąg. Przykładem może być zresetowanie tego parametru do False w określonych warunkach towarzyszących. Zobacz poniżej przykład, gdy są zadania wykonywane na serwerze zarządzania, ale uznamy ten żądanie za nieudane (ustawimy zmienną success na Fałsz, mimo że wywołanie API było udane i zwróciło kod 200).
for task in task_result.data["tasks"]:
if task["status"] == "failed" or task["status"] == "partially succeeded":
task_result.set_success_status(False)
breakresponse()
Metoda response pozwala zobaczyć słownik z kodem odpowiedzi (status_code) oraz z ciałem odpowiedzi (body).
In [94]: api_versions.response()
Out[94]:
{'status_code': 200,
'data': {'current-version': '1.6',
'supported-versions': ['1', '1.1', '1.2', '1.3', '1.4', '1.5', '1.6']}}
data
Pozwala zobaczyć tylko ciało odpowiedzi (body) bez zbędnych informacji.
In [93]: api_versions.data
Out[93]:
{'current-version': '1.6',
'supported-versions': ['1', '1.1', '1.2', '1.3', '1.4', '1.5', '1.6']}
error_message
Ta informacja jest dostępna tylko wtedy, gdy podczas przetwarzania żądania API wystąpił błąd (kod odpowiedzi nie 200). Przykład wyniku
In [107]: api_versions.error_message
Out[107]: 'code: generic_err_invalid_parameter_namenmessage: Unrecognized parameter [1]n'
Przykłady użycia
Poniżej przedstawiono przykłady, w których używane są wywołania API, które zostały dodane w wersji Management API 1.6.
Na początek przyjrzyjmy się pracy wywołań add-host i add-address-range. Załóżmy, że musimy utworzyć jako obiekty typu host wszystkie adresy IP w podsieci 192.168.0.0/24, których ostatni oktet wynosi 5, a wszystkie pozostałe adresy IP zapisać jako obiekty typu zakres adresów. Przy tym należy wykluczyć adres podsieci i adres rozgłoszeniowy.
Zatem poniżej przedstawiony jest skrypt, który rozwiązuje to zadanie i tworzy 50 obiektów typu host oraz 51 obiekt typu zakres adresów. Na rozwiązanie zadania potrzeba 101 wywołań API (nie licząc końcowego wywołania publish). Ponadto za pomocą modułu timeit obliczamy czas realizacji skryptu do momentu opublikowania zmian.
Skrypt z użyciem add-host i add-address-range
import timeit
from cpapi import APIClient, APIClientArgs
start = timeit.default_timer()
first_ip = 1
last_ip = 4
client_args = APIClientArgs(server="192.168.47.240")
with APIClient(client_args) as client:
login = client.login_with_api_key('3TsbPJ8ZKjaJGvFyoFqHFA==')
for ip in range(5,255,5):
add_host = client.api_call("add-host", {"name" : f"h_192.168.0.{ip}", "ip-address": f'192.168.0.{ip}'})
while last_ip < 255:
add_range = client.api_call("add-address-range", {"name": f"r_192.168.0.{first_ip}-{last_ip}", "ip-address-first": f"192.168.0.{first_ip}", "ip-address-last": f"192.168.0.{last_ip}"})
first_ip+=5
last_ip+=5
stop = timeit.default_timer()
publish = client.api_call("publish")
print(f'Time to execute batch request: {stop - start} seconds')
W moim środowisku laboratoryjnym wykonanie tego skryptu zajmuje od 30 do 50 sekund, w zależności od obciążenia serwera zarządzającego.
A teraz przyjrzyjmy się, jak rozwiązać ten sam problem za pomocą wywołania API. add-objects-batch, którego wsparcie dodano w wersji API 1.6. To wywołanie pozwala na utworzenie wielu obiektów w jednym zapytaniu API. Mogą to być obiekty różnych typów (np. hosty, podsieci i zakresy adresów). Dzięki temu nasza kwestia może być rozwiązana w ramach jednego wywołania API.
Skrypt z użyciem add-objects-batch
import timeit
from cpapi import APIClient, APIClientArgs
start = timeit.default_timer()
client_args = APIClientArgs(server="192.168.47.240")
objects_list_ip = []
objects_list_range = []
for ip in range(5,255,5):
data = {"name": f'h_192.168.0.{ip}', "ip-address": f'192.168.0.{ip}'}
objects_list_ip.append(data)
first_ip = 1
last_ip = 4
while last_ip < 255:
data = {"name": f"r_192.168.0.{first_ip}-{last_ip}", "ip-address-first": f"192.168.0.{first_ip}", "ip-address-last": f"192.168.0.{last_ip}"}
objects_list_range.append(data)
first_ip+=5
last_ip+=5
data_for_batch = {
"objects" : [ {
"type" : "host",
"list" : objects_list_ip
}, {
"type" : "address-range",
"list" : objects_list_range
}]
}
with APIClient(client_args) as client:
login = client.login_with_api_key('3TsbPJ8ZKjaJGvFyoFqHFA==')
add_objects_batch = client.api_call("add-objects-batch", data_for_batch)
stop = timeit.default_timer()
publish = client.api_call("publish")
print(f'Time to execute batch request: {stop - start} seconds')
A wykonanie tego skryptu w moim środowisku laboratoryjnym zajmuje od 3 do 7 sekund, w zależności od obciążenia serwera zarządzającego. Oznacza to, że w średnim przypadku wywołanie API typu batch dla 101 obiektów działa 10 razy szybciej. Przy większej liczbie obiektów różnica będzie jeszcze bardziej imponująca.
Teraz przyjrzyjmy się, jak pracować z set-objects-batch. Dzięki temu wywołaniu API możemy masowo zmienić dowolny parametr. Skonfigurujmy dla pierwszej połowy adresów z poprzedniego przykładu (do .124 hosta, a także zakresów) kolor sienna, a drugiej połowie adresów przypiszmy kolor khaki.
Zmiana koloru obiektów stworzonych w poprzednim przykładzie
from cpapi import APIClient, APIClientArgs
client_args = APIClientArgs(server="192.168.47.240")
objects_list_ip_first = []
objects_list_range_first = []
objects_list_ip_second = []
objects_list_range_second = []
for ip in range(5,125,5):
data = {"name": f'h_192.168.0.{ip}', "color": "sienna"}
objects_list_ip_first.append(data)
for ip in range(125,255,5):
data = {"name": f'h_192.168.0.{ip}', "color": "khaki"}
objects_list_ip_second.append(data)
first_ip = 1
last_ip = 4
while last_ip < 125:
data = {"name": f"r_192.168.0.{first_ip}-{last_ip}", "color": "sienna"}
objects_list_range_first.append(data)
first_ip+=5
last_ip+=5
while last_ip < 255:
data = {"name": f"r_192.168.0.{first_ip}-{last_ip}", "color": "khaki"}
objects_list_range_second.append(data)
first_ip+=5
last_ip+=5
data_for_batch_first = {
"objects" : [ {
"type" : "host",
"list" : objects_list_ip_first
}, {
"type" : "address-range",
"list" : objects_list_range_first
}]
}
data_for_batch_second = {
"objects" : [ {
"type" : "host",
"list" : objects_list_ip_second
}, {
"type" : "address-range",
"list" : objects_list_range_second
}]
}
with APIClient(client_args) as client:
login = client.login_with_api_key('3TsbPJ8ZKjaJGvFyoFqHFA==')
set_objects_batch_first = client.api_call("set-objects-batch", data_for_batch_first)
set_objects_batch_second = client.api_call("set-objects-batch", data_for_batch_second)
publish = client.api_call("publish")
Usuwanie wielu obiektów w jednym wywołaniu API można osiągnąć za pomocą delete-objects-batch. A teraz spójrzmy na przykład kodu, który usuwa wszystkie hosty utworzone wcześniej przez add-objects-batch.
Usuwanie obiektów za pomocą delete-objects-batch
from cpapi import APIClient, APIClientArgs
client_args = APIClientArgs(server="192.168.47.240")
objects_list_ip = []
objects_list_range = []
for ip in range(5,255,5):
data = {"name": f'h_192.168.0.{ip}'}
objects_list_ip.append(data)
first_ip = 1
last_ip = 4
while last_ip < 255:
data = {"name": f"r_192.168.0.{first_ip}-{last_ip}"}
objects_list_range.append(data)
first_ip+=5
last_ip+=5
data_for_batch = {
"objects" : [ {
"type" : "host",
"list" : objects_list_ip
}, {
"type" : "address-range",
"list" : objects_list_range
}]
}
with APIClient(client_args) as client:
login = client.login_with_api_key('3TsbPJ8ZKjaJGvFyoFqHFA==')
delete_objects_batch = client.api_call("delete-objects-batch", data_for_batch)
publish = client.api_call("publish")
print(delete_objects_batch.data)
Wszystkie funkcje, które pojawiają się w nowych wydaniach oprogramowania Check Point, natychmiast zyskują również wywołania API. W wersji R80.40 pojawiły się takie funkcje jak Revert to revision i Smart Task, dla których od razu przygotowano odpowiednie wywołania API. Co więcej, cała funkcjonalność przy przejściu z konsol Legacy do trybu Unified Policy również otrzymuje wsparcie API. Na przykład, długo oczekiwaną aktualizacją w wersji R80.40 był transfer polityki HTTPS Inspection z trybu Legacy do trybu Unified Policy, a ta funkcjonalność natychmiast uzyskała wywołania API. Oto przykład kodu, który dodaje na górną pozycję polityki HTTPS Inspection regułę, która wyłącza z inspekcji 3 kategorie (Zdrowie, Finanse, Usługi Publiczne), które są zabronione do inspekcji zgodnie z prawodawstwem w wielu krajach.
Dodaj regułę do polityki HTTPS Inspection
from cpapi import APIClient, APIClientArgs
client_args = APIClientArgs(server="192.168.47.240")
data = {
"layer" : "Default Layer",
"position" : "top",
"name" : "Legal Requirements",
"action": "bypass",
"site-category": ["Health", "Government / Military", "Financial Services"]
}
with APIClient(client_args) as client:
login = client.login_with_api_key('3TsbPJ8ZKjaJGvFyoFqHFA==')
add_https_rule = client.api_call("add-https-rule", data)
publish = client.api_call("publish")
Uruchamianie skryptów Python na serwerze zarządzania Check Point
Wszystko to samo zawiera informacje, jak uruchamiać skrypty w Pythonie bezpośrednio z serwera zarządzania. Może to być wygodne, gdy nie masz możliwości połączenia z serwerem API z innej maszyny. Nagrałem sześcio-minutowe wideo, w którym omawiam instalację modułu cpapi i cechy uruchamiania skryptów Python na serwerze zarządzania. Jako przykład uruchamiany jest skrypt, który automatyzuje konfigurację nowego bramy dla zadania, takiego jak audyt sieci Security CheckUp. Z ciekawostek, z którymi przyszło się zmierzyć: w wersji Pythona 2.7 jeszcze nie pojawiła się funkcja input, dlatego do przetwarzania informacji, które wprowadza użytkownik, używana jest funkcja raw_input. W pozostałym zakresie, kod jest taki sam jak dla uruchamiania z innych maszyn, tylko wygodniej jest używać funkcji login_as_root, aby nie podawać ponownie własnych nazwy użytkownika, hasła i adresu IP serwera zarządzania.

Skrypt do szybkiej konfiguracji Security CheckUp
z __future__ import print_function
import getpass
import sys, os
sys.path.append(os.path.abspath(os.path.join(os.path.dirname(__file__), '..')))
from cpapi import APIClient, APIClientArgs
def main():
with APIClient() as client:
# if client.check_fingerprint() is False:
# print("Nie można uzyskać odcisku palca serwera - Sprawdź łączność z serwerem.")
# exit(1)
login_res = client.login_as_root()
if login_res.success is False:
print("Logowanie nie powiodło się:n{}".format(login_res.error_message))
exit(1)
gw_name = raw_input("Wprowadź nazwę bramy:")
gw_ip = raw_input("Wprowadź adres IP bramy:")
if sys.stdin.isatty():
sic = getpass.getpass("Wprowadź jednorazowe hasło dla bramy (SIC): ")
else:
print("Uwaga! Twoje hasło będzie wyświetlane na ekranie!")
sic = raw_input("Wprowadź jednorazowe hasło dla bramy (SIC): ")
version = raw_input("Wprowadź wersję bramy (np. RXX.YY):")
add_gw = client.api_call("add-simple-gateway", {'name' : gw_name, 'ipv4-address' : gw_ip, 'one-time-password' : sic, 'version': version.capitalize(), 'application-control' : 'true', 'url-filtering' : 'true', 'ips' : 'true', 'anti-bot' : 'true', 'anti-virus' : 'true', 'threat-emulation' : 'true'})
if add_gw.success and add_gw.data['sic-state'] != "communicating":
print("Bezpieczne połączenie z bramą nie zostało nawiązane!")
exit(1)
elif add_gw.success:
print("Bramę dodano pomyślnie.")
gw_uid = add_gw.data['uid']
gw_name = add_gw.data['name']
else:
print("Nie udało się dodać bramy - {}".format(add_gw.error_message))
exit(1)
change_policy = client.api_call("set-access-layer", {"name" : "Sieć", "applications-and-url-filtering": "true", "content-awareness": "true"})
if change_policy.success:
print("Polityka została pomyślnie zmieniona")
else:
print("Nie udało się zmienić polityki- {}".format(change_policy.error_message))
change_rule = client.api_call("set-access-rule", {"name" : "Reguła czyszczenia", "layer" : "Sieć", "action": "Akceptuj", "track": {"type": "Szczegółowy log", "accounting": "true"}})
if change_rule.success:
print("Reguła czyszczenia została pomyślnie zmieniona")
else:
print("Nie udało się zmienić reguły czyszczenia- {}".format(change_rule.error_message))
# publikuj wynik
publish_res = client.api_call("publish", {})
if publish_res.success:
print("Zmiany zostały pomyślnie opublikowane.")
else:
print("Nie udało się opublikować zmian - {}".format(install_tp_policy.error_message))
install_access_policy = client.api_call("install-policy", {"policy-package" : "Standard", "access" : 'true', "threat-prevention" : 'false', "targets" : gw_uid})
if install_access_policy.success:
print("Polityka dostępu została zainstalowana")
else:
print("Nie udało się zainstalować polityki dostępu - {}".format(install_tp_policy.error_message))
install_tp_policy = client.api_call("install-policy", {"policy-package" : "Standard", "access" : 'false', "threat-prevention" : 'true', "targets" : gw_uid})
if install_tp_policy.success:
print("Polityka zapobiegania zagrożeniom została zainstalowana")
else:
print("Nie udało się zainstalować polityki zapobiegania zagrożeniom - {}".format(install_tp_policy.error_message))
# dodaj hasła i frazy zabezpieczające do słownika
with open('additional_pass.conf') as f:
line_num = 0
for line in f:
line_num += 1
add_password_dictionary = client.api_call("run-script", {"script-name" : "Dodaj hasła i frazy zabezpieczające", "script" : "printf "{}" >> $FWDIR/conf/additional_pass.conf".format(line), "targets" : gw_name})
if add_password_dictionary.success:
print("Linia słownika haseł {} została pomyślnie dodana".format(line_num))
else:
print("Nie udało się dodać słownika - {}".format(add_password_dictionary.error_message))
main() Przykład pliku z słownikiem haseł additional_pass.conf
{
"passwords" : ["złośliwe oprogramowanie","malicious","zainfekowane","Zainfekowane"],
"phrases" : ["hasło","Hasło","Pass","pass","kod","klucz","pwd","пароль","Пароль","Ключ","ключ","шифр","Шифр"]
}
Podsumowanie
Ten artykuł omawia tylko podstawowe możliwości pracy Python SDK i modułu cpapi(jak mogłeś się domyślić, to w zasadzie synonimy), a analizując kod w tym module odkryjesz jeszcze więcej możliwości pracy z nim. Nie ma wątpliwości, że możesz zapragnąć wzbogacić go o własne klasy, funkcje, metody i zmienne. Zawsze możesz dzielić się swoimi osiągnięciami i przeglądać inne skrypty dla Check Point w sekcji w społeczności , która łączy zarówno twórców produktów, jak i użytkowników.
Miłej pracy z kodem i dziękujemy, że dotarłeś do końca!
Źródło: habr.com
