Simplificando la API de Check Point con el SDK de Python

Simplificando la API de Check Point con el SDK de PythonTodo el poder de la interacción con las API se revela cuando se usa junto con el código del programa, cuando es posible generar dinámicamente solicitudes de API y herramientas para analizar las respuestas de las API. Sin embargo, sigue siendo imperceptible. Kit de desarrollo de software Python (en adelante denominado SDK de Python) para API de gestión de puntos de control, pero en vano. Simplifica significativamente la vida de los desarrolladores y entusiastas de la automatización. Python ha ganado una enorme popularidad últimamente y decidí llenar el vacío y revisar las características principales. Kit de desarrollo de Python API de Check Point. Este artículo sirve como una excelente adición a otro artículo sobre Habré. Compruebe la API R80.10 del punto. Gestión vía CLI, scripts y más. Veremos cómo escribir scripts usando el SDK de Python y veremos más de cerca la nueva funcionalidad de la API de administración en la versión 1.6 (compatible a partir de R80.40). Para comprender el artículo, necesitará conocimientos básicos sobre cómo trabajar con API y Python.

Check Point está desarrollando activamente la API y por el momento se ha lanzado lo siguiente:

Actualmente, el SDK de Python solo admite la interacción con la API de administración y API de Gaia. Veremos las clases, métodos y variables más importantes en este módulo.

Simplificando la API de Check Point con el SDK de Python

Instalación del módulo

Módulo cpapi Se instala rápida y fácilmente desde repositorio oficial de Check Point en github a través de pepita. Las instrucciones de instalación detalladas están disponibles en README.md. Este módulo está adaptado para funcionar con las versiones 2.7 y 3.7 de Python. En este artículo, se darán ejemplos utilizando Python 3.7. Sin embargo, el SDK de Python se puede ejecutar directamente desde Check Point Management Server (Smart Management), pero solo es compatible con Python 2.7, por lo que la última sección proporcionará el código para la versión 2.7. Inmediatamente después de instalar el módulo, recomiendo mirar los ejemplos en los directorios. ejemplos_python2 и ejemplos_python3.

Primeros pasos

Para que podamos trabajar con los componentes del módulo cpapi, necesitamos importar desde el módulo cpapi al menos dos clases requeridas:

Cliente API и APIClientArgs

from cpapi import APIClient, APIClientArgs

clase APIClientArgs es responsable de los parámetros de conexión al servidor API, y la clase Cliente API es responsable de la interacción con la API.

Determinar los parámetros de conexión

Para definir varios parámetros para conectarse a la API, debe crear una instancia de la clase APIClientArgs. En principio, sus parámetros están predefinidos y al ejecutar el script en el servidor de control no es necesario especificarlos.

client_args = APIClientArgs()

Pero cuando se ejecuta en un host de terceros, debe especificar al menos la dirección IP o el nombre de host del servidor API (también conocido como servidor de administración). En el siguiente ejemplo, definimos el parámetro de conexión del servidor y le asignamos la dirección IP del servidor de administración como una cadena.

client_args = APIClientArgs(server='192.168.47.241')

Veamos todos los parámetros y sus valores predeterminados que se pueden usar al conectarse al servidor API:

Argumentos del método __init__ de la clase 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

Creo que los argumentos que se pueden utilizar en instancias de la clase APIClientArgs son intuitivos para los administradores de Check Point y no requieren comentarios adicionales.

Conexión a través de APIClient y administrador de contexto

clase Cliente API La forma más cómoda de utilizarlo es a través del administrador de contexto. Todo lo que se debe pasar a una instancia de la clase APIClient son los parámetros de conexión que se definieron en el paso anterior.

with APIClient(client_args) as client:

El administrador de contexto no realizará automáticamente una llamada de inicio de sesión al servidor API, pero realizará una llamada de cierre de sesión al salir de él. Si por alguna razón no es necesario cerrar sesión después de terminar de trabajar con llamadas API, debe comenzar a trabajar sin usar el administrador de contexto:

client = APIClient(clieng_args)

Comprobación de conexión

La forma más sencilla de comprobar si la conexión cumple con los parámetros especificados es utilizar el método comprobar_huella digital. Si falla la verificación de la suma hash sha1 para la huella digital del certificado API del servidor (el método devuelto Falso), entonces esto suele ser causado por problemas de conexión y podemos detener la ejecución del programa (o darle al usuario la oportunidad de corregir los datos de conexión):

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

Tenga en cuenta que en el futuro la clase Cliente API comprobará cada llamada API (métodos llamada_api и api_query, hablaremos de ellos un poco más) certificado de huella digital sha1 en el servidor API. Pero si al comprobar la huella digital sha1 del certificado del servidor API se detecta un error (el certificado es desconocido o ha sido modificado), el método comprobar_huella digital brindará la oportunidad de agregar/cambiar información sobre él en la máquina local automáticamente. Esta verificación se puede deshabilitar por completo (pero esto solo se puede recomendar si los scripts se ejecutan en el servidor API, cuando se conecta a 127.0.0.1), usando el argumento APIClientArgs: inseguro_auto_accept (consulte más sobre APIClientArgs anteriormente en “Definición de parámetros de conexión”).

client_args = APIClientArgs(unsafe_auto_accept=True)

Inicie sesión en el servidor API

У Cliente API Hay hasta 3 métodos para iniciar sesión en el servidor API y cada uno de ellos comprende el significado. sid(id-sesión), que se utiliza automáticamente en cada llamada API posterior en el encabezado (el nombre en el encabezado de este parámetro es x-chkp-sid), por lo que no es necesario seguir procesando este parámetro.

método de inicio de sesión

Opción que usa nombre de usuario y contraseña (en el ejemplo, el nombre de usuario admin y la contraseña 1q2w3e se pasan como argumentos posicionales):

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

Parámetros opcionales adicionales también están disponibles en el método de inicio de sesión; aquí están sus nombres y valores predeterminados:

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

Método login_with_api_key

Opción que utiliza una clave API (compatible a partir de la versión de administración R80.40/Management API v1.6, "3TsbPJ8ZKjaJGvFyoFqHFA==" este es el valor de la clave API para uno de los usuarios en el servidor de administración con el método de autorización de clave API):

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

en método login_with_api_key Los mismos parámetros opcionales están disponibles como en el método. Inicie sesión.

método login_as_root

Opción para iniciar sesión en una máquina local con un servidor API:

     login = client.login_as_root()

Sólo hay dos parámetros opcionales disponibles para este método:

domain=None, payload=None

Y finalmente la API se llama a sí misma.

Tenemos dos opciones para realizar llamadas API a través de métodos. llamada_api и api_query. Averigüemos cuál es la diferencia entre ellos.

llamada_api

Este método es aplicable para cualquier llamada. Necesitamos pasar la última parte de la llamada a la API y la carga útil en el cuerpo de la solicitud si es necesario. Si la carga útil está vacía, no se puede transferir en absoluto:

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

Salida para esta solicitud debajo del corte:

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

Salida para esta solicitud debajo del corte:

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

Permítanme hacer una reserva de inmediato: este método es aplicable solo para llamadas cuya salida implica compensación. Tal inferencia ocurre cuando contiene o puede contener una gran cantidad de información. Por ejemplo, esto podría ser una solicitud de una lista de todos los objetos de host creados en el servidor de administración. Para este tipo de solicitudes, la API devuelve una lista de 50 objetos de forma predeterminada (puede aumentar el límite a 500 objetos en la respuesta). Y para no extraer la información varias veces, cambiando el parámetro de compensación en la solicitud de API, existe un método api_query que hace esto automáticamente. Ejemplos de llamadas donde se necesita este método: mostrar-sesiones, mostrar-presentadores, mostrar-redes, mostrar-comodines, mostrar-grupos, mostrar-rangos-de-direcciones, mostrar-pasarelas-simples, mostrar-clústeres-simples, mostrar-roles-de-acceso, mostrar-clientes-confiables, paquetes-show. De hecho, vemos palabras en plural en el nombre de estas llamadas API, por lo que estas llamadas serán más fáciles de manejar a través de api_query

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

Salida para esta solicitud debajo del corte:

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

Procesando los resultados de las llamadas API

Después de esto puedes usar las variables y métodos de la clase. Respuesta API(tanto dentro como fuera del administrador de contexto). en la clase Respuesta API Están predefinidos 4 métodos y 5 variables, nos detendremos en los más importantes con más detalle.

Simplificando la API de Check Point con el SDK de Python

comercial

Para empezar, sería una buena idea asegurarse de que la llamada a la API se haya realizado correctamente y haya arrojado un resultado. Hay un método para esto. comercial:

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

Devuelve Verdadero si la llamada API fue exitosa (código de respuesta: 200) y Falso si no fue exitosa (cualquier otro código de respuesta). Es conveniente usarlo inmediatamente después de una llamada a la API para mostrar información diferente según el código de respuesta.

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

código de estado

Devuelve el código de respuesta después de realizar una llamada a la API.

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

Posibles códigos de respuesta: 200,400,401,403,404,409,500,501.

establecer_estado_éxito

En este caso, puede que sea necesario cambiar el valor del estado de éxito. Técnicamente, puedes poner cualquier cosa allí, incluso una cuerda normal. Pero un ejemplo real sería restablecer este parámetro a False bajo ciertas condiciones. A continuación, preste atención al ejemplo en el que hay tareas ejecutándose en el servidor de administración, pero consideraremos que esta solicitud no tuvo éxito (configuraremos la variable de éxito en Falso, a pesar de que la llamada API fue exitosa y devolvió el código 200).

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

respuesta()

El método de respuesta le permite ver el diccionario con el código de respuesta (status_code) y el cuerpo de la respuesta (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']}}

datos

Le permite ver solo el cuerpo de la respuesta (body) sin información innecesaria.

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

mensaje de error

Esta información está disponible solo cuando ocurre un error al procesar la solicitud de API (código de respuesta no 200). Salida de ejemplo

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

Ejemplos útiles

Los siguientes son ejemplos que utilizan las llamadas API que se agregaron en Management API 1.6.

Primero, veamos cómo funcionan las llamadas. agregar-host и agregar rango de direcciones. Digamos que necesitamos crear todas las direcciones IP de la subred 192.168.0.0/24, cuyo último octeto es 5, como objetos del tipo de host, y escribir todas las demás direcciones IP como objetos del tipo de rango de direcciones. En este caso, excluya la dirección de subred y la dirección de transmisión.

Entonces, a continuación se muestra un script que resuelve este problema y crea 50 objetos del tipo de host y 51 objetos del tipo de rango de direcciones. Para resolver el problema, se requieren 101 llamadas API (sin contar la llamada de publicación final). Además, utilizando el módulo timeit, calculamos el tiempo que tarda en ejecutarse el script hasta que se publican los cambios.

Script usando add-host y 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')

En mi entorno de laboratorio, este script tarda entre 30 y 50 segundos en ejecutarse, dependiendo de la carga en el servidor de administración.

Ahora veamos cómo resolver el mismo problema usando una llamada API. agregar-objetos-por lotes, cuyo soporte se agregó en la versión 1.6 de API. Esta llamada le permite crear muchos objetos a la vez en una solicitud de API. Además, pueden ser objetos de diferentes tipos (por ejemplo, hosts, subredes y rangos de direcciones). Por lo tanto, nuestra tarea se puede resolver en el marco de una llamada API.

Script usando agregar-objetos-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')

Y ejecutar este script en mi entorno de laboratorio lleva de 3 a 7 segundos, dependiendo de la carga en el servidor de administración. Es decir, en promedio, en 101 objetos API, una llamada de tipo por lotes se ejecuta 10 veces más rápido. En un mayor número de objetos la diferencia será aún más impresionante.

Ahora veamos cómo trabajar con conjunto-de-objetos-por lotes. Usando esta llamada API, podemos cambiar masivamente cualquier parámetro. Configuremos la primera mitad de las direcciones del ejemplo anterior (hasta .124 hosts y rangos también) en el color siena y asignemos el color caqui a la segunda mitad de las direcciones.

Cambiar el color de los objetos creados en el ejemplo anterior

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

Puede eliminar varios objetos en una llamada API usando eliminar-objetos-por lotes. Ahora veamos un ejemplo de código que elimina todos los hosts creados previamente mediante agregar-objetos-por lotes.

Eliminar objetos usando eliminar-objetos-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)

Todas las funciones que aparecen en las nuevas versiones del software Check Point adquieren inmediatamente llamadas API. Por lo tanto, en R80.40 aparecieron "características" como Revertir a revisión y Smart Task, y se prepararon inmediatamente las correspondientes llamadas API para ellas. Además, todas las funciones al pasar de consolas heredadas al modo de Política unificada también adquieren soporte API. Por ejemplo, la actualización tan esperada en la versión de software R80.40 fue el cambio de la política de inspección HTTPS del modo heredado al modo de política unificada, y esta funcionalidad recibió inmediatamente llamadas API. A continuación se muestra un ejemplo de código que agrega una regla a la posición superior de la política de inspección HTTPS que excluye 3 categorías de la inspección (Salud, Finanzas, Servicios gubernamentales), cuya inspección está prohibida de acuerdo con las leyes de varios países.

Agregar una regla a la política de inspección 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")

Ejecutar scripts de Python en el servidor de administración de Check Point

Todo es lo mismo README.md contiene información sobre cómo ejecutar scripts de Python directamente desde el servidor de control. Esto puede resultar útil cuando no puede conectarse al servidor API desde otra máquina. Grabé un video de seis minutos en el que observo cómo instalar el módulo. cpapi y características de ejecución de scripts Python en el servidor de control. Como ejemplo, se ejecuta un script que automatiza la configuración de una nueva puerta de enlace para una tarea como la auditoría de red. Chequeo de seguridad. Entre las características con las que tuve que lidiar: la función aún no ha aparecido en Python 2.7 Las opciones de entrada, por lo que para procesar la información que ingresa el usuario se utiliza una función Datos crudos. De lo contrario, el código es el mismo que para iniciar desde otras máquinas, solo que es más conveniente utilizar la función login_as_root, para no volver a especificar su propio nombre de usuario, contraseña y dirección IP del servidor de administración.

Script para configuración rápida 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 archivo de ejemplo con un diccionario de contraseñas adicional_pass.conf
{
"passwords" : ["malware","malicious","infected","Infected"],
"phrases" : ["password","Password","Pass","pass","codigo","key","pwd","пароль","Пароль","Ключ","ключ","шифр","Шифр"] }

Conclusión

Este artículo examina sólo las posibilidades básicas de trabajo. SDK de Python y módulo cpapi(como habrás adivinado, en realidad son sinónimos), y al estudiar el código de este módulo descubrirás aún más posibilidades al trabajar con él. Es posible que desee complementarlo con sus propias clases, funciones, métodos y variables. Siempre puedes compartir tu trabajo y ver otros guiones para Check Point en la sección Código Hub en la comunidad Jaque mate, que reúne tanto a los desarrolladores de productos como a los usuarios.

¡Feliz codificación y gracias por leer hasta el final!

Fuente: habr.com

Añadir un comentario