Simplifier l'API Check Point avec le SDK Python

Simplifier l'API Check Point avec le SDK PythonLa pleine puissance de l'interaction avec l'API est révélée lorsqu'elle est utilisée avec le code du programme, lorsqu'il devient possible de générer dynamiquement des requêtes API et des outils d'analyse des réponses API. Cependant, il reste encore inaperçu Kit de développement logiciel Python (ci-après - Python SDK) pour API de gestion des points de contrôle, mais en vain. Il simplifie considérablement la vie des développeurs et des amateurs d'automatisation. Python a acquis une immense popularité ces dernières années et j'ai décidé de combler l'écart et de revoir les principales fonctionnalités. Kit de développement Python de l'API Check Point. Cet article est un excellent complément à un autre article sur Habré Vérifiez l'API R80.10. Contrôle via CLI, scripts et plus. Nous verrons comment écrire des scripts à l'aide du SDK Python et nous nous attarderons sur la nouvelle fonctionnalité de l'API de gestion dans la version 1.6 (supportée depuis R80.40). Pour comprendre l'article, vous aurez besoin de connaissances de base sur l'utilisation de l'API et de Python.

Check Point développe activement l'API et pour le moment les éléments suivants sont nés :

Le SDK Python ne prend actuellement en charge que l'interaction avec l'API de gestion et API Gaïa. Nous 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 installé rapidement et facilement à partir de Dépôt officiel de Check Point sur github par pépin. Les instructions d'installation détaillées se trouvent dans README.md. Ce module est adapté pour fonctionner avec les versions 2.7 et 3.7 de Python. Dans cet article, les exemples seront donnés en utilisant Python 3.7. Cependant, le SDK Python peut être exécuté directement à partir du serveur de gestion Check Point (Smart Management), mais ils ne prennent en charge que Python 2.7, donc le code de la version 2.7 sera donné dans la dernière section. Immédiatement après l'installation du module, je recommande de regarder les exemples dans les répertoires exemples_python2 и exemples_python3.

Mise en route

Pour que nous puissions travailler avec les composants du module cpapi, il est nécessaire d'importer depuis le module CPAPI au moins deux cours obligatoires :

Client API и APIClientArgs

from cpapi import APIClient, APIClientArgs

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

Définition des paramètres de connexion

Pour définir différents paramètres de connexion à l'API, vous devez 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 contrôle, ils peuvent être omis.

client_args = APIClientArgs()

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

client_args = APIClientArgs(server='192.168.47.241')

Voyons ensemble tous les paramètres et leurs valeurs par défaut utilisables lors de la connexion au serveur API :

Arguments pour 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 pouvant être utilisés dans les instances de la classe APIClientArgs sont intuitifs pour les administrateurs de Check Point et ne nécessitent pas de commentaires supplémentaires.

Connexion via APIClient et Context Manager

classe Client API il est plus pratique de l'utiliser via le gestionnaire de contexte. Tout ce qui doit être passé à une instance de la classe APIClient sont les paramètres de connexion qui ont été définis à la dernière étape.

with APIClient(client_args) as client:

Le gestionnaire de contexte n'effectuera pas automatiquement d'appel de connexion au serveur API, mais il effectuera un appel de déconnexion en le quittant. Si, pour une raison quelconque, vous n'avez pas besoin de vous déconnecter lorsque vous avez fini de travailler avec les appels d'API, vous devez commencer à travailler sans utiliser le gestionnaire de contexte :

client = APIClient(clieng_args)

Vérification de la connexion

Il est plus facile de vérifier si la connexion passe selon les paramètres spécifiés en utilisant la méthode check_fingerprint. Si la vérification de la somme de hachage sha1 pour l'empreinte digitale du certificat de l'API du serveur a échoué (la méthode a renvoyé Faux), alors cela est généralement causé par des problèmes de connexion et nous pouvons arrêter le programme de s'exécuter (ou donner à l'utilisateur la possibilité de corriger les données pour la 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 Client API vérifiera à chaque appel d'API (méthodes api_call и api_query, nous en reparlerons un peu plus loin) empreinte sha1 du certificat sur le serveur API. Mais si une erreur est détectée lors de la vérification de l'empreinte sha1 du certificat de l'API du serveur (le certificat est inconnu ou a été modifié), la méthode check_fingerprint offrira la possibilité d'ajouter / modifier des informations à ce sujet sur la machine locale en mode automatique. Cette vérification peut être complètement désactivée (mais cela ne peut être recommandé que si les scripts sont exécutés sur le serveur API lui-même, lors de la connexion à 127.0.0.1), en utilisant l'argument APIClientArgs - unsafe_auto_accept (En savoir plus sur APIClientArgs plus haut dans "Définition des paramètres de connexion").

client_args = APIClientArgs(unsafe_auto_accept=True)

Connectez-vous au serveur API

У Client API il y a jusqu'à 3 méthodes de connexion sur le serveur API, et chacune d'elles se souvient de la valeur sid(session-id), qui est utilisé automatiquement dans chaque appel d'API suivant dans l'en-tête (le nom dans l'en-tête de 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 login et mot de passe (dans l'exemple, le nom d'utilisateur admin et le mot de passe 1q2w3e sont passés en arguments positionnels) :

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

Des paramètres facultatifs supplémentaires sont également disponibles dans la méthode de connexion, 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 (supportée depuis 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 sur le serveur de gestion avec la méthode d'autorisation de clé API) :

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

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

méthode login_as_root

Possibilité de se connecter à une machine locale avec un serveur API :

     login = client.login_as_root()

Seuls deux paramètres facultatifs sont disponibles pour cette méthode :

domain=None, payload=None

Et enfin l'API s'appelle

Nous avons deux options pour effectuer des appels d'API via des méthodes api_call и api_query. Voyons quelle est la différence entre eux.

api_call

Cette méthode est applicable à tous les appels. Nous devons passer la dernière partie de l'appel api et de la charge utile dans le corps de la requête si nécessaire. Si la charge utile est vide, elle ne peut pas du tout être transférée :

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

La sortie de cette requête sous 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 sous 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
})

api_query

Je ferai tout de suite une réserve sur le fait que cette méthode n'est applicable que pour les appels dont la sortie implique un décalage (décalage). Une telle conclusion se produit lorsqu'elle contient ou peut contenir une grande quantité d'informations. Par exemple, il peut s'agir d'une demande de liste de tous les objets créés de type hôte sur le serveur de gestion. Pour de telles requêtes, l'API renvoie une liste de 50 objets par défaut (vous pouvez augmenter la limite à 500 objets dans la réponse). Et pour ne pas extraire les informations plusieurs fois, en modifiant le paramètre offset dans la requête API, il existe une méthode api_query qui fait 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, afficher les forfaits. En fait, dans le nom de ces appels d'API, nous voyons des mots au pluriel, donc ces appels seront plus faciles à traiter à travers api_query

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

La sortie de cette requête sous 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
})

Gérer les résultats des appels d'API

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

Simplifier l'API Check Point avec le SDK Python

succès

Pour commencer, il serait bien de s'assurer 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 s'il a échoué (tout autre code de réponse). Il est pratique de l'utiliser immédiatement après l'appel de l'API pour 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) 

code d'état

Renvoie le code de réponse après qu'un appel d'API a été effectué.

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

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

set_success_status

Dans ce cas, il peut être nécessaire de modifier la valeur de l'état de réussite. Techniquement, vous pouvez y mettre n'importe quoi, même une chaîne normale. Mais un exemple réel serait de réinitialiser un paramètre donné sur False sous certaines conditions d'accompagnement. Ci-dessous, faites attention à l'exemple lorsqu'il y a des tâches en cours d'exécution sur le serveur de gestion, mais nous considérerons cette requête comme infructueuse (nous définirons la variable success sur Faux, même si l'appel d'API a réussi et a renvoyé un 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 consulter 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']}}

données

Vous permet de voir uniquement le corps de la réponse (body) 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

Voici des exemples qui utilisent les appels d'API qui ont été ajoutés dans la version 1.6 de l'API de gestion.

Voyons d'abord comment fonctionnent les appels. ajouter un hôte и ajouter une plage d'adresses. Supposons que nous devions créer toutes les adresses IP du sous-réseau 192.168.0.0/24 en tant qu'objets de type hôte, dont le dernier octet est 5, et écrire toutes les adresses IP restantes en tant qu'objets de type plage d'adresses. Dans ce cas, excluez l'adresse de sous-réseau et l'adresse de diffusion.

Ainsi, ci-dessous se trouve 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. 101 appels d'API sont nécessaires pour résoudre le problème (sans compter l'appel de publication final). De plus, en utilisant le module timeit, nous calculons le temps d'exécution du script jusqu'à ce que les modifications soient publiées.

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, selon la charge sur le serveur de gestion.

Et maintenant, voyons comment résoudre le même problème en utilisant l'appel API ajout-d'objets-lot, dont la prise en charge a été ajoutée dans l'API version 1.6. Cet appel vous permet de créer plusieurs objets à la fois dans une 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 en 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')

Et dans mon environnement de laboratoire, ce script prend de 3 à 7 secondes pour s'exécuter, selon la charge sur le serveur de gestion. Soit, en moyenne, sur 101 objets API, un appel de type batch s'exécute 10 fois plus vite. Sur plus d'objets, la différence sera encore plus impressionnante.

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

Changer 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 en un seul appel d'API à l'aide de supprimer-objets-lot. Et maintenant, regardons un exemple de code qui supprime tous les hôtes créés précédemment via ajout-d'objets-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 fonctionnalités qui apparaissent dans les nouvelles versions du logiciel Check Point acquièrent immédiatement des appels API. Ainsi, dans R80.40, des «fonctionnalités» telles que Revenir à la révision et Smart Task sont apparues, et les appels d'API correspondants ont été immédiatement préparés pour elles. De plus, toutes les fonctionnalités lors du passage des consoles Legacy au mode Unified Policy acquièrent également la prise en charge de l'API. Par exemple, la mise à jour tant attendue de la version logicielle R80.40 était le déplacement de la politique d'inspection HTTPS du mode Legacy au mode Unified Policy, et cette fonctionnalité a immédiatement reçu des appels d'API. Voici un exemple de code qui ajoute une règle à la première position de la politique d'inspection HTTPS qui exclut 3 catégories de l'inspection (Santé, Finance, Services publics), qui sont interdites d'inspection conformément aux lois dans un certain nombre de 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 Check Point Management Server

Tout dans le même README.md 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 ne pouvez pas vous connecter au serveur d'API à partir d'une autre machine. J'ai enregistré une vidéo de six minutes dans laquelle j'envisage l'installation du module CPAPI et les fonctionnalités d'exécution de scripts Python sur le serveur de contrôle. Par exemple, un script est exécuté qui automatise la configuration d'une nouvelle passerelle pour une tâche telle que l'audit d'un réseau Bilan de sécurité. Parmi les fonctionnalités auxquelles j'ai dû faire face : dans la version Python 2.7, la fonction n'est pas encore apparue contribution, donc pour traiter les informations saisies par l'utilisateur, la fonction est utilisée entrée brute. Sinon, le code est le même que pour l'exécution à partir d'autres machines, seulement il est plus pratique d'utiliser la fonction connexion_as_root, afin de ne plus spécifier votre propre nom d'utilisateur, mot de passe et adresse IP du serveur de gestion.

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

Un exemple de fichier avec un dictionnaire de mot 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 principales caractéristiques de l'œuvre SDK Python et modules CPAPI(comme vous pouvez le deviner, ce sont en fait des synonymes), et en étudiant le code dans ce module, vous découvrirez encore plus de possibilités pour l'utiliser. Il est possible que vous ayez envie de le compléter avec vos propres classes, fonctions, méthodes et variables. Vous pouvez toujours partager votre travail et voir d'autres scripts pour Check Point dans la section hub de code dans la communauté Échecs et mats, qui regroupe à la fois les développeurs de produits et les utilisateurs.

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

Source: habr.com

Ajouter un commentaire