Simplifying the Check Point API with the Python SDK

Simplifying the Check Point API with the Python SDKThe full power of interacting with the API is revealed when used together with the program code, when it becomes possible to dynamically generate API requests and tools for analyzing API responses. However, it still remains unobserved Python Software Development Kit (hereinafter - Python SDK) for Check Point Management API, but in vain. It significantly simplifies the life of developers and lovers of automation. Python has gained immense popularity in recent years and I decided to close the gap and review the main features. Check Point API Python Development Kit. This article serves as an excellent addition to another article on Habré Check Point R80.10 API. Control via CLI, scripts and more. We will look at how to write scripts using the Python SDK and dwell on the new functionality of the Management API in version 1.6 (supported since R80.40). To understand the article, you will need basic knowledge of working with the API and Python.

Check Point is actively developing the API and at the moment the following have been born:

The Python SDK currently only supports interaction with the Management API and Gaia API. We will cover the most important classes, methods and variables in this module.

Simplifying the Check Point API with the Python SDK

Installing the module

Module cpapi installed quickly and easily from Check Point official repository on github through pip. Detailed installation instructions are in README.md. This module is adapted to work with Python versions 2.7 and 3.7. In this article, the examples will be given using Python 3.7. However, the Python SDK can be run directly from the Check Point management server (Smart Management), but they only support Python 2.7, so the code for version 2.7 will be given in the last section. Immediately after installing the module, I recommend looking at the examples in the directories examples_python2 и examples_python3.

Beginning of work

In order for us to be able to work with the components of the cpapi module, it is necessary to import from the module cpapi at least two required classes:

APIClient и APIClientArgs

from cpapi import APIClient, APIClientArgs

Class APIClientArgs is responsible for the connection parameters to the API server, and the class APIClient responsible for interacting with the API.

Defining connection parameters

To define various parameters for connecting to the API, you need to create an instance of the class APIClientArgs. In principle, its parameters are predefined, and when running the script on the control server, they can be omitted.

client_args = APIClientArgs()

But when running on a third-party host, you must specify at least the IP address or host name of the API server (aka the management server). In the example below, we define the connection parameter server and assign it as a string the IP address of the management server.

client_args = APIClientArgs(server='192.168.47.241')

Let's take a look at all the parameters and their default values ​​that can be used when connecting to the API server:

Arguments for the __init__ method of the APIClientArgs class

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

I believe that the arguments that can be used in instances of the APIClientArgs class are intuitive for Check Point administrators and do not need additional comments.

Connecting via APIClient and Context Manager

Class APIClient it is most convenient to use through the context manager. All that needs to be passed to an instance of the APIClient class is the connection parameters that were defined in the last step.

with APIClient(client_args) as client:

The context manager will not automatically make a login call to the API server, but it will make a logout call when exiting it. If for some reason you don't need to logout when you finish working with API calls, you need to start working without using the context manager:

client = APIClient(clieng_args)

Connection check

It is easiest to check if the connection passes according to the specified parameters using the method check_fingerprint. If the verification of the sha1 hash sum for the fingerprint of the server API certificate failed (the method returned False), then this is usually caused by connection problems and we can stop the program from running (or give the user the opportunity to correct the data for the connection):

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

Please note that in the future the class APIClient will check on every API call (methods api_call и api_query, we will talk about them a little further) sha1 fingerprint of the certificate on the API server. But if an error is detected when checking the sha1 fingerprint of the server API certificate (the certificate is unknown or has been changed), the method check_fingerprint will provide an opportunity to add / change information about it on the local machine in automatic mode. This check can be disabled altogether (but this can only be recommended if scripts are run on the API server itself, when connecting to 127.0.0.1), using the APIClientArgs argument - unsafe_auto_accept (See more about APIClientArgs earlier in "Defining Connection Parameters").

client_args = APIClientArgs(unsafe_auto_accept=True)

Login to API server

У APIClient there are as many as 3 login methods on the API server, and each of them remembers the value sid(session-id), which is used automatically in each subsequent API call in the header (the name in the header of this parameter is X-chkp-sid), so there is no need to further process this parameter.

login method

Option using login and password (in the example, the username admin and password 1q2w3e are passed as positional arguments):

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

Additional optional parameters are also available in the login method, here are their names and default values:

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

login_with_api_key method

Option using an api key (supported since the management version R80.40/Management API v1.6, "3TsbPJ8ZKjaJGvFyoFqHFA==" this is the value of the API key for one of the users on the management server with the API key authorization method):

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

In method login_with_api_key the same optional parameters are available as in the method login.

login_as_root method

Option to login to a local machine with an API server:

     login = client.login_as_root()

Only two optional parameters are available for this method:

domain=None, payload=None

And finally the API calls themselves

We have two options for making API calls through methods api_call и api_query. Let's see what is the difference between them.

api_call

This method is applicable to any calls. We need to pass the last part for the api call and payload in the request body if necessary. If payload is empty, then it can not be transferred at all:

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

The output for this request under the cut:

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

The output for this request under the cut:

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

I’ll make a reservation right away that this method is applicable only for calls whose output implies an offset (shift). Such a conclusion occurs when it contains or may contain a large amount of information. For example, this could be a request for a list of all created objects of type host on the management server. For such requests, the API returns a list of 50 objects by default (you can increase the limit to 500 objects in the response). And in order not to pull the information several times, changing the offset parameter in the API request, there is an api_query method that does this work automatically. Examples of calls where this method is needed: show-sessions, show-hosts, show-networks, show-wildcards, show-groups, show-address-ranges, show-simple-gateways, show-simple-clusters, show-access-roles, show-trusted-clients, show packages. In fact, in the name of these API calls, we see words in the plural, so these calls will be easier to process through api_query

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

The output for this request under the cut:

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

Handling the results of API calls

After that, you can use the variables and methods of the class APIResponse(both inside the context manager and outside). At the class APIResponse 4 methods and 5 variables are predefined, we will dwell on the most important ones in more detail.

Simplifying the Check Point API with the Python SDK

success

To begin with, it would be nice to make sure that the API call was successful and returned a result. There is a method for this success:

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

Returns True if the API call was successful (response code - 200) and False if not successful (any other response code). It is convenient to use immediately after the API call to display different information depending on the response code.

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

status code

Returns the response code after an API call has been made.

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

Possible response codes: 200,400,401,403,404,409,500,501.

set_success_status

In this case, it may be necessary to change the value of the success status. Technically, you can put anything there, even a regular string. But a real example would be resetting a given parameter to False under certain accompanying conditions. Below, pay attention to the example when there are tasks running on the management server, but we will consider this request unsuccessful (we will set the success variable to False, even though the API call was successful and returned a 200 code).

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

response()

The response method allows you to look at the dictionary with the response code (status_code) and the response body (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']}}

date

Allows you to see only the body of the response (body) without unnecessary information.

In [93]: api_versions.data                                                      
Out[93]: 
{'current-version': '1.6',
 'supported-versions': ['1', '1.1', '1.2', '1.3', '1.4', '1.5', '1.6']}

error_message

This information is available only when an error occurred while processing the API request (response code not 200). Output example

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

Useful examples

The following are examples that use the API calls that were added in the 1.6 version of the Management API.

First, let's look at how calls work. add-host и add-address-range. Suppose we need to create all ip addresses of the subnet 192.168.0.0/24 as objects of the host type, the last octet of which is 5, and write all the remaining ip addresses as objects of the address range type. In this case, exclude the subnet address and the broadcast address.

So, below is a script that solves this problem and creates 50 objects of the host type and 51 objects of the address range type. 101 API calls are required to solve the problem (not counting the final publish call). Also, using the timeit module, we calculate the time to execute the script until the changes are published.

Script using add-host and 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')

In my lab environment, this script takes between 30 and 50 seconds to complete, depending on the load on the management server.

And now let's see how to solve the same problem using the API call add-objects-batch, support for which was added in API version 1.6. This call allows you to create many objects at once in one API request. Moreover, these can be objects of different types (for example, hosts, subnets and address ranges). Thus, our task can be solved within a single API call.

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

And in my lab environment, this script takes from 3 to 7 seconds to execute, depending on the load on the management server. That is, on average, on 101 API objects, a call of the batch type executes 10 times faster. On more objects, the difference will be even more impressive.

Now let's see how to work with set-objects-batch. With this API call, we can bulk change any parameter. Let's set the first half of the addresses from the previous example (up to .124 hosts, and the ranges too) to be sienna, and the second half of the addresses to be khaki.

Changing the color of the objects created in the previous example

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

You can delete multiple objects in one API call using delete-objects-batch. And now let's look at a code example that removes all hosts created earlier through add-objects-batch.

Deleting objects with 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)

All features that appear in new releases of Check Point software immediately acquire API calls. So, in R80.40, such “features” as Revert to revision and Smart Task appeared, and the corresponding API calls were immediately prepared for them. Moreover, all the functionality when switching from Legacy consoles to Unified Policy mode also acquires API support. For example, the long-awaited update in software version R80.40 was the move of the HTTPS Inspection policy from Legacy mode to Unified Policy mode, and this functionality immediately received API calls. Here is an example of code that adds a rule to the top position of the HTTPS Inspection policy that excludes 3 categories from inspection (Health, Finance, Public Services), which are prohibited from inspection in accordance with the laws in a number of countries.

Add Rule to HTTPS Inspection Policy

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

Running Python Scripts on the Check Point Management Server

All in the same README.md contains information on how to run Python scripts directly from the management server. This can be handy when you can't connect to the API server from another machine. I recorded a six-minute video in which I consider the installation of the module cpapi and features of running Python scripts on the control server. As an example, a script is run that automates the configuration of a new gateway for a task such as auditing a network Security CheckUp. Of the features that I had to deal with: in the Python 2.7 version, the function has not yet appeared input, so to process the information that the user enters, the function is used raw_input. Otherwise, the code is the same as for running from other machines, only it is more convenient to use the function login_as_root, so as not to specify your own username, password and IP address of the management server again.

Script for quick configuration of 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()

An example of a file with a password dictionary additional_pass.conf
{
"passwords" : ["malware","malicious","infected","Infected"],
"phrases" : ["password","Password","Pass","pass","codigo","key","pwd","пароль","Пароль","Ключ","ключ","шифр","Шифр"] }

Conclusion

This article covers only the main features of the work Python SDK and module cpapi(as you might guess, these are actually synonyms), and by studying the code in this module, you will discover even more possibilities for working with it. It is possible that you will have a desire to supplement it with your own classes, functions, methods and variables. You can always share your work and view other scripts for Check Point in the section codehub in the community CheckMates, which combines both product developers and users.

Happy coding and thanks for reading to the end!

Source: habr.com

Add a comment