Nous simplifions le travail avec l'API Check Point grĂące au SDK Python

Nous simplifions le travail avec l'API Check Point grĂące au SDK PythonToute la puissance de l'interaction avec l'API se dĂ©voile lors de son utilisation conjointe avec du code, permettant de gĂ©nĂ©rer dynamiquement des requĂȘtes API et des outils d'analyse des rĂ©ponses API. Cependant, cela reste encore peu remarquĂ©. Kit de DĂ©veloppement Logiciel Python (ci-aprĂšs — SDK Python) pour l'API de Gestion Check Point, Ă  tort. Il facilite considĂ©rablement la vie aux dĂ©veloppeurs et aux passionnĂ©s d'automatisation. Python a acquis une immense popularitĂ© ces derniĂšres annĂ©es et j'ai dĂ©cidĂ© de combler ce vide et de faire un aperçu des principales possibilitĂ©s Kit de DĂ©veloppement Python de l'API Check Point. Cet article sert d'excellente complĂ©ment Ă  un autre article sur Habr. API Check Point R80.10. Gestion via CLI, scripts et plus encore. Nous allons voir comment Ă©crire des scripts en utilisant le SDK Python et nous nous attarderons en dĂ©tail sur la nouvelle fonctionnalitĂ© de l'API de Gestion dans la version 1.6 (supportĂ©e depuis R80.40). Pour comprendre cet article, des connaissances de base sur le travail avec les API et Python sont nĂ©cessaires.

Check Point développe activement son API et à ce jour, les suivantes sont disponibles :

Le SDK Python prend actuellement en charge uniquement l'interaction avec l'API de Gestion et l'API Gaia. Nous examinerons les classes, méthodes et variables les plus importantes dans ce module.

Nous simplifions le travail avec l'API Check Point grĂące au SDK Python

Installation du module

Module cpapi s'installe rapidement et simplement depuis le dĂ©pĂŽt officiel Check Point sur github Ă  l'aide de pip. Une instruction dĂ©taillĂ©e sur l'installation est disponible dans README.md. Ce module est adaptĂ© pour fonctionner avec les versions Python 2.7 et 3.7. Dans cet article, des exemples seront prĂ©sentĂ©s en utilisant Python 3.7. Cependant, le SDK Python peut ĂȘtre exĂ©cutĂ© directement depuis le serveur de gestion Check Point (Smart Management), mais seule la version Python 2.7 y est supportĂ©e, donc la derniĂšre section fournira le code pour la version 2.7. Juste aprĂšs l'installation du module, je recommande de consulter les exemples dans les rĂ©pertoires examples_python2 et examples_python3.

Commencer

Pour que nous puissions travailler avec les composants du module cpapi, il est nécessaire d'importer à partir du module cpapi au moins deux classes nécessaires :

APIClient et APIClientArgs

from cpapi import APIClient, APIClientArgs

Classe APIClientArgs s’occupent des paramùtres de connexion au serveur API, et la classe APIClient s’occupe de l’interaction avec l’API.

Définissons les paramÚtres de connexion

Pour définir divers paramÚtres de connexion à l'API, il faut créer une instance de la classe APIClientArgs. En principe, ses paramÚtres sont prédéfinis et lors de l'exécution du script sur le serveur de gestion, il n'est pas nécessaire de les spécifier.

client_args = APIClientArgs()

Mais lors de l'exĂ©cution sur un hĂ©bergeur tiers, il est nĂ©cessaire de spĂ©cifier au moins l'adresse IP ou le nom d’hĂŽte du serveur API (Ă©galement le serveur de gestion). Dans l'exemple ci-dessous, nous dĂ©finissons le paramĂštre de connexion server et lui assignons l'adresse IP du serveur de gestion sous forme de chaĂźne.

client_args = APIClientArgs(server='192.168.47.241')

Voyons tous les paramÚtres et leurs valeurs par défaut que l'on peut utiliser pour se connecter au serveur API :

Arguments de la méthode __init__ de la classe APIClientArgs

class APIClientArgs:
    """
    Cette classe fournit des arguments pour la configuration d'APIClient.
    Tous les arguments sont configurés avec leurs valeurs par défaut.
    """

    # le port est défini sur None par défaut, mais il est remplacé par 443 s'il n'est pas spécifié
    # valeurs possibles du contexte - web_api (par défaut) ou 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
        # empreinte du serveur de gestion
        self.fingerprint = fingerprint
        # session-id.
        self.sid = sid
        # nom ou adresse IP du serveur de gestion
        self.server = server
        # niveau de débogage
        self.http_debug_level = http_debug_level
        # un tableau avec tous les appels API (à des fins de débogage)
        self.api_calls = api_calls if api_calls else []
        # nom du fichier de débogage. S'il est laissé vide, les données de débogage ne seront pas sauvegardées sur le disque.
        self.debug_file = debug_file
        # adresse du serveur proxy HTTP (sans "http://")
        self.proxy_host = proxy_host
        # port proxy HTTP
        self.proxy_port = proxy_port
        # version API du serveur de gestion
        self.api_version = api_version
        # Indique que le client ne doit pas vérifier le certificat du serveur
        self.unsafe = unsafe
        # Indique que le client doit accepter et sauvegarder automatiquement le certificat du serveur
        self.unsafe_auto_accept = unsafe_auto_accept
        # Le contexte d'utilisation du client - par défaut web_api
        self.context = context

Je suppose que les arguments que l'on peut utiliser dans les instances de la classe APIClientArgs sont intuitivement clairs pour les administrateurs Check Point et ne nécessitent pas de commentaires supplémentaires.

Connectons-nous via APIClient et le gestionnaire de contexte

Classe APIClient Il est plus pratique de l'utiliser via le gestionnaire de contexte. Tout ce qui doit ĂȘtre transmis Ă  une instance de la classe APIClient ce sont les paramĂštres de connexion dĂ©finis Ă  l'Ă©tape prĂ©cĂ©dente.

with APIClient(client_args) as client:

Le gestionnaire de contexte n'effectuera pas automatiquement l'appel login sur le serveur API, mais il effectuera l'appel logout à la sortie. Si pour une raison quelconque le logout à la fin du travail avec les appels API n'est pas nécessaire, il faut commencer le travail sans utiliser le gestionnaire de contexte :

client = APIClient(clieng_args)

Vérification de la connexion

Il est plus simple de vĂ©rifier si la connexion passe avec les paramĂštres donnĂ©s en utilisant la mĂ©thode check_fingerprint. Si la vĂ©rification du hash sha1 pour le fingerprint du certificat du serveur API Ă©choue (la mĂ©thode retourne False), cela est gĂ©nĂ©ralement dĂ» Ă  des problĂšmes de connexion et nous pouvons arrĂȘter l'exĂ©cution du programme (ou permettre Ă  l'utilisateur de corriger les donnĂ©es de connexion) :

    if client.check_fingerprint() is False:
        print("Impossible d'obtenir le fingerprint du serveur - Vérifiez la connectivité avec le serveur.")
        exit(1)

Notez que plus tard, la classe APIClient vĂ©rifiera Ă  chaque appel API (mĂ©thodes api_call et api_query, dont nous parlerons un peu plus loin) le sha1 fingerprint du certificat sur le serveur API. En cas d'erreur lors de la vĂ©rification du sha1 fingerprint du certificat du serveur API (certificat inconnu ou modifiĂ©), la mĂ©thode check_fingerprint offrira la possibilitĂ© d'ajouter/modifier les informations Ă  son sujet sur la machine locale de maniĂšre automatique. Cette vĂ©rification peut ĂȘtre complĂštement dĂ©sactivĂ©e (mais cela ne peut ĂȘtre recommandĂ© que lors de l'exĂ©cution de scripts sur le serveur API lui-mĂȘme, en se connectant Ă  127.0.0.1), en utilisant l'argument APIClientArgs — unsafe_auto_accept voir plus de dĂ©tails sur APIClientArgs prĂ©cĂ©demment dans «DĂ©finir les paramĂštres de connexion».

client_args = APIClientArgs(unsafe_auto_accept=True)

Connexion au serveur API

Il y a APIClient trois mĂ©thodes de connexion au serveur API, et chacune d'elles mĂ©morise la valeur sid(identifiant de session), qui est automatiquement utilisĂ©e dans chaque appel API suivant dans l'en-tĂȘte (le nom dans l'en-tĂȘte pour ce paramĂštre — X-chkp-sid), donc il n'est pas nĂ©cessaire de traiter ce paramĂštre supplĂ©mentaire.

Méthode de connexion

Option avec utilisation du login et du mot de passe (dans l'exemple, le nom d'utilisateur admin et le mot de passe 1q2w3e sont passés en tant qu'arguments positionnels) :

     login = client.login('admin', '1q2w3e')  

Dans la méthode de connexion, des paramÚtres optionnels supplémentaires sont également disponibles, je vous donne leurs noms et valeurs par défaut :

continue_last_session=False, domain=None, read_only=False, payload=None

Méthode login_with_api_key

Option utilisant une clé API (prise en charge à partir de la version de gestion R80.40 / Management API v1.6, «3TsbPJ8ZKjaJGvFyoFqHFA==» c'est la valeur de la clé API pour l'un des utilisateurs sur le serveur de gestion avec la méthode d'autorisation clé API) :

     login = client.login_with_api_key('3TsbPJ8ZKjaJGvFyoFqHFA==') 

Dans la mĂ©thode login_with_api_key les mĂȘmes paramĂštres optionnels sont disponibles que dans la mĂ©thode login.

Méthode login_as_root

Option de connexion Ă  la machine locale avec le serveur API :

     login = client.login_as_root()

Pour cette méthode, seulement deux paramÚtres optionnels sont disponibles :

domain=None, payload=None

Et enfin, les appels API eux-mĂȘmes

Nous avons deux options pour faire des appels API via les méthodes. api_call et api_queryVoyons maintenant la différence entre elles.

api_call

Cette mĂ©thode est applicable pour tous les appels. Nous devons transmettre la derniĂšre partie de l'appel API et le payload dans le corps de la requĂȘte si nĂ©cessaire. Si le payload est vide, il n'est pas nĂ©cessaire de le transmettre :

api_versions = client.api_call('show-api-versions') 

La sortie pour cette requĂȘte est ci-dessous :

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'})

La sortie pour cette requĂȘte est ci-dessous :

Dans [25]: show_host                                                              
Out[25]: 
APIResponse({
    "data": {
        "color": "noir",
        "comments": "",
        "domain": {
            "domain-type": "domaine",
            "name": "Utilisateur 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": "déverrouillé",
            "validation-state": "ok"
        },
        "name": "h_8.8.8.8",
        "nat-settings": {
            "auto-rule": false
        },
        "read-only": false,
        "tags": [],
        "type": "hĂŽte",
        "uid": "c210af07-1939-49d3-a351-953a9c471d9e"
    },
    "res_obj": {
        "data": {
            "color": "noir",
            "comments": "",
            "domain": {
                "domain-type": "domaine",
                "name": "Utilisateur 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": "déverrouillé",
                "validation-state": "ok"
            },
            "name": "h_8.8.8.8",
            "nat-settings": {
                "auto-rule": false
            },
            "read-only": false,
            "tags": [],
            "type": "hĂŽte",
            "uid": "c210af07-1939-49d3-a351-953a9c471d9e"
        },
        "status_code": 200
    },
    "status_code": 200,
    "success": true
})

api_query

Je prĂ©cise tout de suite que cette mĂ©thode n'est applicable que pour les appels dont la sortie comprend un offset. Ce type de sortie se produit lorsqu'il contient ou peut contenir une grande quantitĂ© d'informations. Par exemple, cela peut ĂȘtre une requĂȘte pour obtenir la liste de tous les objets de type hĂŽte créés sur le serveur de gestion. Pour de telles requĂȘtes, l'API renvoie par dĂ©faut une liste de 50 objets (le limite peut ĂȘtre augmentĂ©e jusqu'Ă  500 objets dans la rĂ©ponse). Et pour Ă©viter de tirer l'information plusieurs fois en changeant le paramĂštre offset dans la requĂȘte API, il existe une mĂ©thode api_query qui effectue ce travail automatiquement. Exemples d'appels oĂč cette mĂ©thode est nĂ©cessaire : 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. En fait, dans le nom de ces appels API, nous voyons des mots au pluriel, donc ces appels seront plus faciles Ă  traiter via api_query

show_hosts = client.api_query('show-hosts') 

La sortie pour cette requĂȘte est ci-dessous :

Dans [21]: show_hosts                                                             
Sortie[21]: 
APIResponse({
    "data": [
        {
            "domain": {
                "domain-type": "domain",
                "name": "Utilisateur 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": "Utilisateur 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": "Utilisateur 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": "Utilisateur 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
})

Traitement des résultats des appels API

AprĂšs cela, vous pouvez utiliser les variables et mĂ©thodes de la classe APIResponse(Ă  l’intĂ©rieur du gestionnaire de contexte ou Ă  l’extĂ©rieur). La classe APIResponse prĂ©cĂšde 4 mĂ©thodes et 5 variables, sur les plus importantes nous nous attarderons davantage.

Nous simplifions le travail avec l'API Check Point grĂące au SDK Python

success

Pour commencer, il serait bon de s'assurer que l'appel API a été effectué avec succÚs et a renvoyé un résultat. Pour cela, il existe une méthode success:

Dans [49]: api_versions.success                                                   
Sortie[49]: True

Renvoie True si l'appel API a Ă©tĂ© rĂ©ussi (Code de rĂ©ponse — 200) et False si non rĂ©ussi (tout autre code de rĂ©ponse). Pratique Ă  utiliser immĂ©diatement aprĂšs l'appel API, afin d'afficher diffĂ©rentes informations en fonction du code de rĂ©ponse.

if api_ver.success: 
    print(api_versions.data) 
else: 
    print(api_versions.err_message) 

statuscode

Renvoie le code de réponse aprÚs l'exécution de l'appel API.

Dans [62]: api_versions.status_code                                               
Sortie[62]: 400

Codes de réponse possibles : 200,400,401,403,404,409,500,501.

set_success_status

Il peut ĂȘtre nĂ©cessaire de modifier la valeur du statut success. Techniquement, on peut y mettre n'importe quoi, mĂȘme une simple chaĂźne. Mais un exemple rĂ©el pourrait ĂȘtre de rĂ©initialiser ce paramĂštre Ă  False dans certaines conditions associĂ©es. Ci-dessous, vous pouvez voir un exemple oĂč il y a des tĂąches exĂ©cutĂ©es sur le serveur de gestion, mais nous allons considĂ©rer cette demande comme Ă©chouĂ©e (nous allons dĂ©finir la variable success Ă  False, mĂȘme si l'appel API a rĂ©ussi et a renvoyĂ© le code 200).

for task in task_result.data["tasks"]:
    if task["status"] == "failed" or task["status"] == "partially succeeded":
        task_result.set_success_status(False)
        break

response()

La méthode response permet de voir le dictionnaire avec le code de réponse (status_code) et le corps de la réponse (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

Permet de voir uniquement le corps de la réponse (body) sans informations superflues.

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

Cette information est disponible uniquement lorsqu'une erreur s'est produite lors du traitement de la requĂȘte API (code de rĂ©ponse ne 200). Exemple de sortie

In [107]: api_versions.error_message                                            
Out[107]: 'code: generic_err_invalid_parameter_name
message: Unrecognized parameter [1]
'

Exemples utiles

Ci-dessous, vous trouverez des exemples utilisant des appels API qui ont été ajoutés dans la version Management API 1.6.

Commençons par examiner le fonctionnement des appels add-host et add-address-range. Supposons que nous devions crĂ©er tous les adresses IP de la sous-rĂ©seau 192.168.0.0/24 en tant qu'objets de type hĂŽte dont le dernier octet est 5, tandis que toutes les autres adresses IP doivent ĂȘtre enregistrĂ©es en tant qu'objets de type plage d'adresses. De plus, l'adresse de sous-rĂ©seau et l'adresse de diffusion doivent ĂȘtre exclues.

Ainsi, ci-dessous, vous trouverez un script qui résout cette tùche et crée 50 objets de type hÎte et 51 objets de type plage d'adresses. La tùche nécessite 101 appels API (sans compter l'appel final publish). De plus, avec le module timeit, nous mesurons le temps d'exécution du script jusqu'à la publication des modifications.

Script utilisant add-host et 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')

Dans mon environnement de laboratoire, l'exécution de ce script prend de 30 à 50 secondes, selon la charge sur le serveur de gestion.

Voyons maintenant comment rĂ©soudre cette tĂąche avec un appel API. add-objects-batch, dont la prise en charge a Ă©tĂ© ajoutĂ©e dans la version API 1.6. Cet appel permet de crĂ©er plusieurs objets en une seule requĂȘte API. De plus, il peut s'agir d'objets de diffĂ©rents types (par exemple des hĂŽtes, des sous-rĂ©seaux et des plages d'adresses). Ainsi, notre tĂąche peut ĂȘtre rĂ©solue dans le cadre d'un seul appel API.

Script utilisant 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')

L'exécution de ce script dans mon environnement de laboratoire prend de 3 à 7 secondes, selon la charge sur le serveur de gestion. Ainsi, en moyenne, l'appel API de type batch fonctionne 10 fois plus vite pour 101 objets. Pour un plus grand nombre d'objets, la différence sera encore plus impressionnante.

Voyons maintenant comment travailler avec set-objects-batch. Grùce à cet appel API, nous pouvons modifier en masse n'importe quel paramÚtre. Configurons la premiÚre moitié des adresses de l'exemple précédent (jusqu'à .124 pour les hÎtes, y compris les plages) avec la couleur sienna, et la seconde moitié des adresses avec la couleur khaki.

Modification de la couleur des objets créés dans l'exemple précédent.

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")

Il est possible de supprimer de nombreux objets en un seul appel API en utilisant delete-objects-batch. Voyons maintenant un exemple de code qui supprime tous les hÎtes créés précédemment via add-objects-batch.

La suppression d'objets Ă  l'aide de 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)

Toutes les fonctionnalitĂ©s qui apparaissent dans les nouvelles versions du logiciel Check Point sont immĂ©diatement accompagnĂ©es d'appels API. Ainsi, dans R80.40, des « fonctionnalitĂ©s » telles que Revert to revision et Smart Task ont Ă©tĂ© introduites, et des appels API correspondants ont Ă©tĂ© prĂ©parĂ©s. De plus, toute la fonctionnalitĂ© lors de la transition des consoles Legacy au mode Unified Policy est Ă©galement Ă©quipĂ©e de support API. Par exemple, la mise Ă  jour tant attendue dans la version R80.40 a Ă©tĂ© le transfert de la politique d'inspection HTTPS du mode Legacy au mode Unified Policy, et cette fonctionnalitĂ© a immĂ©diatement reçu des appels API. Voici un exemple de code qui ajoute en premiĂšre position une rĂšgle Ă  la politique d'inspection HTTPS excluant de l'inspection 3 catĂ©gories (SantĂ©, Finances, Services gouvernementaux) qui ne peuvent ĂȘtre inspectĂ©es en vertu de la lĂ©gislation de plusieurs pays.

Ajouter une rĂšgle Ă  la politique d'inspection HTTPS

from cpapi import APIClient, APIClientArgs

client_args = APIClientArgs(server="192.168.47.240")

data = {
  "layer" : "Default Layer",
  "position" : "top",
  "name" : "Exigences légales",
  "action": "bypass",
  "site-category": ["Santé", "Gouvernement / Militaire", "Services financiers"]
}

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")

Exécution de scripts Python sur le serveur de gestion Check Point

Tout de mĂȘme README.md il contient des informations sur la façon d'exĂ©cuter des scripts Python directement Ă  partir du serveur de gestion. Cela peut ĂȘtre pratique lorsque vous n'avez pas la possibilitĂ© de vous connecter au serveur API depuis une autre machine. J'ai enregistrĂ© une vidĂ©o de six minutes oĂč j'examine l'installation du module cpapi et les particularitĂ©s d'exĂ©cution des scripts Python sur le serveur de gestion. En tant qu'exemple, un script est exĂ©cutĂ© pour automatiser la configuration d'une nouvelle passerelle pour une tĂąche tels que l'audit rĂ©seau VĂ©rification de sĂ©curitĂ©. Parmi les particularitĂ©s rencontrĂ©es : dans la version Python 2.7, la fonction input, n'est pas encore disponible, donc pour traiter les informations saisies par l'utilisateur, on utilise la fonction raw_input. Sinon, le code est le mĂȘme que pour une exĂ©cution Ă  partir d'autres machines, il est juste plus pratique d'utiliser la fonction login_as_root, pour ne pas avoir Ă  saisir encore une fois votre propre nom d'utilisateur, mot de passe et adresse IP du serveur de gestion.

Lire la vidéo

Script pour la configuration rapide de la vérification de sécurité

from __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("Impossible d'obtenir l'empreinte du serveur - Vérifiez la connectivité avec le serveur.")
       #     exit(1)
        login_res = client.login_as_root()

        if login_res.success is False:
            print("Échec de la connexion:n{}".format(login_res.error_message))
            exit(1)

        gw_name = raw_input("Entrez le nom de la passerelle:")
        gw_ip = raw_input("Entrez l'adresse IP de la passerelle:")
        if sys.stdin.isatty():
            sic = getpass.getpass("Entrez le mot de passe Ă  usage unique pour la passerelle (SIC): ")
        else:
            print("Attention! Votre mot de passe s'affichera à l'écran!")
            sic = raw_input("Entrez le mot de passe Ă  usage unique pour la passerelle (SIC): ")
        version = raw_input("Entrez la version de la passerelle (comme 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("La connexion sécurisée avec la passerelle n'a pas été établie!")
            exit(1)
        elif add_gw.success:
            print("La passerelle a été ajoutée avec succÚs.")
            gw_uid = add_gw.data['uid']
            gw_name = add_gw.data['name']
        else:
            print("Échec de l'ajout de la passerelle - {}".format(add_gw.error_message))
            exit(1)

        change_policy = client.api_call("set-access-layer", {"name" : "Network", "applications-and-url-filtering": "true", "content-awareness": "true"})
        if change_policy.success:
            print("La politique a été changée avec succÚs")
        else:
            print("Échec du changement de la politique - {}".format(change_policy.error_message))
        change_rule = client.api_call("set-access-rule", {"name" : "RĂšgle de nettoyage", "layer" : "Network", "action": "Accept", "track": {"type": "Detailed Log", "accounting": "true"}})
        if change_rule.success:
            print("La rÚgle de nettoyage a été changée avec succÚs")
        else:
            print("Échec du changement de la rùgle de nettoyage - {}".format(change_rule.error_message))

        # publier le résultat
        publish_res = client.api_call("publish", {})
        if publish_res.success:
            print("Les changements ont été publiés avec succÚs.")
        else:
                print("Échec de la publication des changements - {}".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("La politique d'accÚs a été installée")
        else:
                print("Échec de l'installation de la politique d'accùs - {}".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("La politique de prévention des menaces a été installée")
        else:
            print("Échec de l'installation de la politique de prĂ©vention des menaces - {}".format(install_tp_policy.error_message))
        
        # ajouter des mots de passe et phrases secrĂštes au dictionnaire
        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" : "Ajouter des mots de passe et des phrases secrĂštes", "script" : "printf "{}" >> $FWDIR/conf/additional_pass.conf".format(line), "targets" : gw_name})
                if add_password_dictionary.success:
                    print("La ligne {} du dictionnaire de mots de passe a été ajoutée avec succÚs".format(line_num))
                else:
                    print("Échec de l'ajout du dictionnaire - {}".format(add_password_dictionary.error_message))

main()

Exemple de fichier avec un dictionnaire de mots de passe additional_pass.conf
{
"passwords" : ["maliciel","malveillant","infecté","Infecté"],
"phrases" : ["mot de passe","Mot de passe","Pass","pass","codigo","clĂ©","pwd","ĐżĐ°Ń€ĐŸĐ»ŃŒ","ĐŸĐ°Ń€ĐŸĐ»ŃŒ","Ключ","Đșлюч","шофр","йофр"]
}

Conclusion

Cet article traite uniquement des fonctionnalitĂ©s de base du travail Python SDK et du module cpapi(comme vous l'avez peut-ĂȘtre devinĂ©, ce sont en fait des synonymes), et en Ă©tudiant le code de ce module, vous dĂ©couvrirez encore plus de possibilitĂ©s de travail avec lui. Il est possible que vous souhaitiez l'enrichir avec vos propres classes, fonctions, mĂ©thodes et variables. Vous pouvez toujours partager vos rĂ©alisations et consulter d'autres scripts pour Check Point dans la section CodeHub de la communautĂ© CheckMates, qui rĂ©unit des dĂ©veloppeurs de produits et des utilisateurs.

Bon code et merci d'avoir lu jusqu'Ă  la fin !

Source : habr.com

Acheter un hĂ©bergement fiable pour les sites avec protection DDoS, serveurs VPS VDS đŸ”„ Acheter un hĂ©bergement fiable pour les sites avec protection DDoS, serveurs VPS VDS | ProHoster