Simplifier l'API Check Point avec le SDK Python

Simplifier l'API Check Point avec le SDK PythonL'interaction avec les API révèle toute sa puissance lorsqu'elle est utilisée conjointement avec le code d'un programme, permettant de générer dynamiquement des requêtes API et d'analyser les réponses des API. Cependant, cette interaction reste encore peu connue. Kit de développement logiciel Python (ci-après dénommé Python SDK) pour API de gestion des points de contrôle, mais en vain. Cela simplifie grandement la vie des développeurs et des passionnés d'automatisation. Python a récemment gagné en popularité, et j'ai décidé de combler ce manque et de passer en revue ses principales fonctionnalités. Kit de développement Python Check Point APICet article constitue un excellent complément à un autre article sur Habr Vérifiez l'API R80.10. Contrôle via CLI, scripts et plusNous verrons comment écrire des scripts avec le SDK Python et détaillerons les nouvelles fonctionnalités de l'API de gestion de la version 1.6 (prise en charge depuis la version R80.40). Pour comprendre cet article, vous aurez besoin de connaissances de base sur l'utilisation des API et de Python.

Check Point développe activement des API et actuellement, les suivantes ont été publiées :

Le SDK Python ne prend actuellement en charge que l'interaction avec l'API de gestion et API GaiaNous couvrirons les classes, méthodes et variables les plus importantes dans ce module.

Simplifier l'API Check Point avec le SDK Python

Installation du module

Module cpapi S'installe rapidement et facilement à partir de Dépôt GitHub officiel de Check Point par pépin. Des instructions d'installation détaillées sont disponibles dans README.mdCe module est compatible avec les versions 2.7 et 3.7 de Python. Cet article présente des exemples utilisant Python 3.7. Cependant, le SDK Python peut être exécuté directement depuis le serveur de gestion Check Point (Smart Management), mais seul Python 2.7 est pris en charge. Le code de la version 2.7 sera donc présenté dans la dernière section. Immédiatement après l'installation du module, je vous recommande de consulter les exemples disponibles dans les répertoires. exemples_python2 и exemples_python3.

Mise en route

Afin que nous puissions travailler avec les composants du module cpapi, nous devons l'importer depuis le module cpapi au moins deux cours obligatoires :

APIClient и APIClientArgs

from cpapi import APIClient, APIClientArgs

classe APIClientArgs est responsable des paramètres de connexion au serveur API et de la classe APIClient Responsable de l'interaction avec l'API.

Nous définissons les paramètres de connexion

Pour définir différents paramètres de connexion à l'API, vous devez créer une instance de la classe APIClientArgsEn principe, ses paramètres sont prédéfinis et lors de l'exécution du script sur le serveur de gestion, ils n'ont pas besoin d'être spécifiés.

client_args = APIClientArgs()

Cependant, lors de l'exécution sur un hôte tiers, vous devez au moins spécifier l'adresse IP ou le nom d'hôte du serveur API (également appelé serveur de gestion). Dans l'exemple ci-dessous, nous définissons le paramètre de connexion au serveur et lui attribuons l'adresse IP du serveur de gestion sous forme de chaîne.

client_args = APIClientArgs(server='192.168.47.241')

Regardons tous les paramètres et leurs valeurs par défaut qui peuvent être utilisés lors de la connexion au serveur API :

Arguments de la méthode __init__ de la classe APIClientArgs

class APIClientArgs:
    """
    This class provides arguments for APIClient configuration.
    All the arguments are configured with their default values.
    """

    # port is set to None by default, but it gets replaced with 443 if not specified
    # context possible values - web_api (default) or 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
        # management server fingerprint
        self.fingerprint = fingerprint
        # session-id.
        self.sid = sid
        # management server name or IP-address
        self.server = server
        # debug level
        self.http_debug_level = http_debug_level
        # an array with all the api calls (for debug purposes)
        self.api_calls = api_calls if api_calls else []
        # name of debug file. If left empty, debug data will not be saved to disk.
        self.debug_file = debug_file
        # HTTP proxy server address (without "http://")
        self.proxy_host = proxy_host
        # HTTP proxy port
        self.proxy_port = proxy_port
        # Management server's API version
        self.api_version = api_version
        # Indicates that the client should not check the server's certificate
        self.unsafe = unsafe
        # Indicates that the client should automatically accept and save the server's certificate
        self.unsafe_auto_accept = unsafe_auto_accept
        # The context of using the client - defaults to web_api
        self.context = context

Je pense que les arguments qui peuvent être utilisés dans les instances de la classe APIClientArgs sont intuitivement compréhensibles pour les administrateurs Check Point et ne nécessitent pas de commentaires supplémentaires.

Connexion via APIClient et gestionnaire de contexte

classe APIClient L'utilisation du gestionnaire de contexte est plus pratique. Il suffit de transmettre à l'instance de classe APIClient les paramètres de connexion définis à l'étape précédente.

with APIClient(client_args) as client:

Le gestionnaire de contexte n'appelle pas automatiquement la connexion au serveur d'API, mais il effectue une déconnexion à sa fermeture. Si, pour une raison quelconque, la déconnexion n'est pas nécessaire après avoir terminé les appels d'API, vous devez commencer à travailler sans utiliser le gestionnaire de contexte :

client = APIClient(clieng_args)

Vérification de la connexion

Le moyen le plus simple de vérifier si la connexion se déroule selon les paramètres spécifiés est d'utiliser la méthode vérifier_empreinte_fingerprint. Si la vérification du hachage SHA1 pour l'empreinte du certificat du serveur API a échoué (la méthode a renvoyé Faux), cela est généralement dû à des problèmes de connexion et nous pouvons arrêter l'exécution du programme (ou donner à l'utilisateur la possibilité de corriger les données de connexion) :

    if client.check_fingerprint() is False:
        print("Could not get the server's fingerprint - Check connectivity with the server.")
        exit(1)

Veuillez noter qu'à l'avenir, la classe APIClient vérifiera chaque appel d'API (méthodes appel_API и requête_API(nous en parlerons plus loin) l'empreinte SHA1 du certificat sur le serveur d'API. Cependant, si une erreur est détectée lors de la vérification de l'empreinte SHA1 du certificat du serveur d'API (certificat inconnu ou modifié), la méthode vérifier_empreinte_fingerprint Permettra d'ajouter et de modifier automatiquement des informations sur la machine locale. Cette option peut être désactivée (mais uniquement recommandée pour l'exécution de scripts sur le serveur API lui-même, lors d'une connexion à 127.0.0.1) à l'aide de l'argument APIClientArgs : acceptation_automatique_non_sécurisée (voir plus d'informations sur APIClientArgs plus haut dans « Définition des paramètres de connexion »).

client_args = APIClientArgs(unsafe_auto_accept=True)

Connectez-vous au serveur API

У APIClient il existe jusqu'à 3 méthodes de connexion au serveur API, et chacune d'entre elles mémorise la valeur sid(session-id), qui est utilisé automatiquement dans chaque appel d'API ultérieur dans l'en-tête (le nom dans l'en-tête pour ce paramètre est X-chkp-sid), il n'est donc pas nécessaire de traiter davantage ce paramètre.

Méthode de connexion

Option utilisant le login et le mot de passe (dans l'exemple, le nom d'utilisateur admin et le mot de passe 1q2w3e sont passés comme arguments positionnels) :

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

La méthode de connexion dispose également de paramètres facultatifs supplémentaires disponibles, voici leurs noms et leurs 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==" il s'agit de la valeur de la clé API pour l'un des utilisateurs du serveur de gestion avec la méthode d'autorisation de la clé API) :

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

En méthode connexion_avec_clé_api les mêmes paramètres optionnels sont disponibles que dans la méthode vous connecter.

méthode login_as_root

Option de connexion à une machine locale avec un serveur API :

     login = client.login_as_root()

Il n'y a que deux paramètres facultatifs disponibles pour cette méthode :

domain=None, payload=None

Et enfin l'API s'appelle elle-même

Nous avons deux options pour effectuer des appels API via des méthodes appel_API и requête_APIVoyons quelle est la différence entre eux.

appel_API

Cette méthode s'applique à tous les appels. Si nécessaire, nous devons transmettre la dernière partie de l'appel d'API et la charge utile dans le corps de la requête. Si la charge utile est vide, elle peut être omise :

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

La sortie de cette requête est en dessous de la coupe :

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 de cette requête est en dessous de la coupe :

In [25]: show_host                                                              
Out[25]: 
APIResponse({
    "data": {
        "color": "black",
        "comments": "",
        "domain": {
            "domain-type": "domain",
            "name": "SMC User",
            "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": "unlocked",
            "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": "black",
            "comments": "",
            "domain": {
                "domain-type": "domain",
                "name": "SMC User",
                "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": "unlocked",
                "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
})

requête_API

Précisons d'emblée que cette méthode ne s'applique qu'aux appels dont la sortie suppose un décalage. Ce type de sortie se produit lorsqu'elle contient ou peut contenir une grande quantité d'informations. Par exemple, il peut s'agir d'une requête demandant la liste de tous les objets de type hôte créés sur le serveur de gestion. Pour ce type de requête, l'API renvoie une liste de 50 objets par défaut (vous pouvez augmenter la limite à 500 objets dans la réponse). Afin d'éviter de devoir extraire les informations plusieurs fois en modifiant le paramètre de décalage dans la requête API, la méthode api_query effectue cette opération automatiquement. Exemples d'appels nécessitant cette méthode : sessions d'émission, hôtes d'émission, réseaux d'émission, caractères génériques d'émission, groupes d'émission, plages d'adresses d'émission, passerelles simples d'émission, clusters simples d'émission, rôles d'accès d'émission, clients de confiance d'émission, packages d'émission. En fait, dans le nom de ces appels API, nous voyons des mots au pluriel, donc ces appels seront plus faciles à gérer via requête_API

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

La sortie de cette requête est en dessous de la coupe :

In [21]: show_hosts                                                             
Out[21]: 
APIResponse({
    "data": [
        {
            "domain": {
                "domain-type": "domain",
                "name": "SMC User",
                "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": "SMC User",
                "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": "SMC User",
                        "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": "SMC User",
                        "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 d'API

Après cela, vous pouvez utiliser les variables et les méthodes de la classe. Réponse API(à l'intérieur comme à l'extérieur du gestionnaire de contexte). La classe Réponse API Il existe 4 méthodes prédéfinies et 5 variables, nous nous attarderons plus en détail sur les plus importantes.

Simplifier l'API Check Point avec le SDK Python

succès

Tout d'abord, il serait judicieux de vérifier que l'appel d'API a réussi et a renvoyé un résultat. Il existe une méthode pour cela. succès:

In [49]: api_versions.success                                                   
Out[49]: True

Renvoie True si l'appel d'API a réussi (code de réponse : 200) et False en cas d'échec (tout autre code de réponse). Cette option est pratique à utiliser immédiatement après l'appel d'API pour afficher différentes informations selon le code de réponse.

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

code d'état

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

In [62]: api_versions.status_code                                               
Out[62]: 400

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

définir_statut_de_succès

Dans ce cas, il peut être nécessaire de modifier la valeur du statut de réussite. Techniquement, vous pouvez y saisir n'importe quelle valeur, même une chaîne de caractères standard. Un exemple concret serait de réinitialiser ce paramètre à False sous certaines conditions. Ci-dessous, observez l'exemple où des tâches sont en cours d'exécution sur le serveur de gestion, mais nous considérerons cette requête comme infructueuse (nous définirons la variable de réussite à ). Faux, malgré le fait que l'appel API ait réussi et ait 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

réponse()

La méthode de réponse vous permet de visualiser un 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']}}

données,

Vous permet de voir uniquement le corps de la réponse sans informations inutiles.

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

Message d'erreur

Ces informations ne sont disponibles que lorsqu'une erreur s'est produite lors du traitement de la requête API (code de réponse aucun 200). Exemple de sortie

In [107]: api_versions.error_message                                            
Out[107]: 'code: generic_err_invalid_parameter_namenmessage: Unrecognized parameter [1]n'

Exemples utiles

Les exemples suivants utilisent des appels d’API qui ont été ajoutés dans la version 1.6 de l’API de gestion.

Commençons par examiner comment fonctionnent les appels. ajouter un hôte и ajouter-une-plage-d'adressesSupposons que nous devions créer toutes les adresses IP du sous-réseau 192.168.0.0/24, dont le dernier octet est 5, comme objets de type hôte, et écrire toutes les autres adresses IP comme objets de type plage d'adresses. Dans ce cas, excluez l'adresse de sous-réseau et l'adresse de diffusion.

Voici un script qui résout ce problème et crée 50 objets de type hôte et 51 objets de type plage d'adresses. La résolution du problème nécessite 101 appels d'API (sans compter l'appel de publication final). De plus, à l'aide du module timeit, nous calculons 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, ce script prend entre 30 et 50 secondes à s'exécuter, selon la charge sur le serveur de gestion.

Voyons maintenant comment résoudre le même problème en utilisant un appel API ajouter-des-objets-par-lot, dont la prise en charge a été ajoutée à l'API version 1.6. Cet appel permet de créer simultanément plusieurs objets dans 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 entre 3 et 7 secondes, selon la charge du serveur de gestion. Autrement dit, sur 101 objets, l'appel d'API par lots est 10 fois plus rapide en moyenne. Sur un nombre plus important d'objets, la différence est encore plus marquée.

Voyons maintenant comment travailler avec ensemble-d'objets-lotGrâce à cet appel d'API, nous pouvons modifier n'importe quel paramètre en bloc. Définissons la première moitié des adresses de l'exemple précédent (jusqu'à 124 hôtes, et les plages correspondantes) en couleur terre de Sienne, et la seconde moitié en kaki.

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

Vous pouvez supprimer plusieurs objets dans un seul appel d'API en utilisant supprimer-objets-lot. Voyons maintenant un exemple de code qui supprime tous les hôtes précédemment créés via ajouter-des-objets-par-lot.

Suppression d'objets avec 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 fonctions des nouvelles versions du logiciel Check Point acquièrent immédiatement des appels d'API. Ainsi, la version R80.40 a vu l'apparition de fonctionnalités telles que « Revenir à la révision » et « Tâche intelligente », et les appels d'API correspondants ont été immédiatement préparés. De plus, toutes les fonctionnalités de passage des consoles héritées au mode Politique unifiée bénéficient également d'une prise en charge API. Par exemple, une mise à jour très attendue de la version R80.40 a permis le passage de la politique d'inspection HTTPS du mode hérité au mode Politique unifiée, et cette fonctionnalité a immédiatement reçu des appels d'API. Voici un exemple de code ajoutant une règle en première position de la politique d'inspection HTTPS, excluant trois catégories de l'inspection (Santé, Finance, Services gouvernementaux), interdites par 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" : "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")

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

Tout est pareil README.md Contient des informations sur l'exécution de scripts Python directement depuis le serveur de contrôle. Cela peut être utile si vous ne parvenez pas à vous connecter au serveur API depuis une autre machine. J'ai enregistré une vidéo de six minutes expliquant l'installation du module. cpapi et les fonctionnalités d'exécution de scripts Python sur le serveur de gestion. Par exemple, un script est exécuté pour automatiser la configuration d'une nouvelle passerelle pour une tâche telle que l'audit réseau. Contrôle de sécurité. Une des fonctionnalités que j'ai dû gérer : dans Python 2.7, la fonction n'est pas encore apparue contribution, la fonction est donc utilisée pour traiter les informations saisies par l'utilisateur entrée brute. Sinon, le code est le même que pour le lancement depuis d'autres machines, il est seulement plus pratique d'utiliser la fonction login_as_root, afin de ne pas avoir à spécifier à nouveau votre propre nom d'utilisateur, mot de passe et adresse IP du serveur de contrôle.

Voir la vidéo

Script pour une configuration rapide de Security CheckUp

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("Could not get the server's fingerprint - Check connectivity with the server.")
       #     exit(1)
        login_res = client.login_as_root()

        if login_res.success is False:
            print("Login failed:n{}".format(login_res.error_message))
            exit(1)

        gw_name = raw_input("Enter the gateway name:")
        gw_ip = raw_input("Enter the gateway IP address:")
        if sys.stdin.isatty():
            sic = getpass.getpass("Enter one-time password for the gateway(SIC): ")
        else:
            print("Attention! Your password will be shown on the screen!")
            sic = raw_input("Enter one-time password for the gateway(SIC): ")
        version = raw_input("Enter the gateway version(like 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("Secure connection with the gateway hasn't established!")
            exit(1)
        elif add_gw.success:
            print("The gateway was added successfully.")
            gw_uid = add_gw.data['uid']
            gw_name = add_gw.data['name']
        else:
            print("Failed to add the gateway - {}".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("The policy has been changed successfully")
        else:
            print("Failed to change the policy- {}".format(change_policy.error_message))
        change_rule = client.api_call("set-access-rule", {"name" : "Cleanup rule", "layer" : "Network", "action": "Accept", "track": {"type": "Detailed Log", "accounting": "true"}})
        if change_rule.success:
            print("The cleanup rule has been changed successfully")
        else:
            print("Failed to change the cleanup rule- {}".format(change_rule.error_message))

        # publish the result
        publish_res = client.api_call("publish", {})
        if publish_res.success:
            print("The changes were published successfully.")
        else:
                print("Failed to publish the changes - {}".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("The access policy has been installed")
        else:
                print("Failed to install access policy - {}".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("The threat prevention policy has been installed")
        else:
            print("Failed to install threat prevention policy - {}".format(install_tp_policy.error_message))
        
        # add passwords and passphrases to dictionary
        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" : "Add passwords and passphrases", "script" : "printf "{}" >> $FWDIR/conf/additional_pass.conf".format(line), "targets" : gw_name})
                if add_password_dictionary.success:
                    print("The password dictionary line {} was added successfully".format(line_num))
                else:
                    print("Failed to add the dictionary - {}".format(add_password_dictionary.error_message))

main()

Exemple de fichier avec un dictionnaire de mots de passe additional_pass.conf
{
"passwords" : ["malware","malicious","infected","Infected"],
"phrases" : ["password","Password","Pass","pass","codigo","key","pwd","пароль","Пароль","Ключ","ключ","шифр","Шифр"]
}

Conclusion

Cet article ne couvre que les possibilités de travail de base SDK Python et module cpapi(Comme vous l'aurez deviné, ce sont en fait des synonymes), et après avoir étudié le code de ce module, vous découvrirez encore plus de possibilités d'utilisation. Vous souhaiterez peut-être le compléter avec vos propres classes, fonctions, méthodes et variables. Vous pouvez partager vos développements et consulter d'autres scripts pour Check Point dans la section hub de code dans la communauté Échecs et mats, qui rassemble à la fois les développeurs de produits et les utilisateurs.

Bon codage et merci d'avoir lu jusqu'au bout !

Source: habr.com

Achetez un hébergement fiable pour les sites avec protection DDoS, serveurs VPS VDS 🔥 Achetez un hébergement web fiable avec protection DDoS, serveurs VPS et VDS | ProHoster