Facilitando o trabalho com a API do Check Point usando o SDK do Python

Facilitando o trabalho com a API do Check Point usando o SDK do PythonTodo o poder da interação com a API é revelado quando combinado com o código de programação, dando origem à possibilidade de formar dinamicamente solicitações de API e ferramentas para analisar respostas da API. No entanto, permanece pouco reconhecido até agora Kit de Desenvolvimento de Software Python (daqui em diante — Python SDK) para API de Gestão Check Point, e isso é um erro. Ele simplifica consideravelmente a vida dos desenvolvedores e entusiastas da automação. O Python ganhou uma enorme popularidade recentemente e eu decidi preencher essa lacuna e fazer uma visão geral das principais funcionalidades Kit de Desenvolvimento Python da API Check Point. Este artigo serve como uma excelente complementação a outro artigo no Habr Check Point R80.10 API. Gestão através de CLI, scripts e mais. Nós vamos discutir como escrever scripts utilizando o Python SDK e focar mais nas novas funcionalidades da API de Gestão na versão 1.6 (suportada a partir do R80.40). Para entender o artigo, serão necessários conhecimentos básicos sobre o funcionamento da API e do Python.

A Check Point está ativamente desenvolvendo a API e atualmente surgiram:

O SDK Python atualmente suporta interação apenas com a API de Gestão e API Gaia. Vamos examinar as classes, métodos e variáveis mais importantes deste módulo.

Facilitando o trabalho com a API do Check Point usando o SDK do Python

Instalação do módulo

Módulo cpapi é rápido e fácil de instalar a partir do repositório oficial da Check Point no GitHub com pip. Um guia detalhado de instalação está disponível em README.md. Este módulo é compatível com as versões Python 2.7 e 3.7. Neste artigo, os exemplos serão apresentados usando o Python 3.7. No entanto, o Python SDK pode ser executado diretamente do servidor de gestão Check Point (Smart Management), mas apenas a versão Python 2.7 é suportada, portanto, na última seção, o código será apresentado para a versão 2.7. Logo após a instalação do módulo, recomendo verificar os exemplos nos diretórios examples_python2 e examples_python3.

Início

Para que tenhamos a possibilidade de trabalhar com os componentes do módulo cpapi, precisamos importar do módulo cpapi pelo menos duas classes necessárias:

APIClient e APIClientArgs

from cpapi import APIClient, APIClientArgs

Classe APIClientArgs responsável pelos parâmetros de conexão com o servidor API, enquanto a classe APIClient é responsável pela interação com a API.

Definindo os parâmetros de conexão

Para definir diferentes parâmetros de conexão com a API, é necessário criar uma instância da classe APIClientArgs. Basicamente, seus parâmetros são predefinidos e, ao executar o script no servidor de gerenciamento, não é necessário especificá-los.

client_args = APIClientArgs()

Mas ao executar em um host externo, é necessário especificar pelo menos o endereço IP ou o nome do host do servidor API (também conhecido como servidor de gerenciamento). No exemplo abaixo, definimos o parâmetro de conexão server e atribuímos a ele, como uma string, o endereço IP do servidor de gerenciamento.

client_args = APIClientArgs(server='192.168.47.241')

Vamos dar uma olhada em todos os parâmetros e seus valores padrão que podem ser usados ao conectar-se ao servidor API:

Argumentos do método __init__ da classe APIClientArgs

class APIClientArgs:
    """
    Esta classe fornece argumentos para a configuração do APIClient.
    Todos os argumentos são configurados com seus valores padrão.
    """

    # a porta é definida como None por padrão, mas é substituída por 443 se não for especificada
    # valores possíveis do contexto - web_api (padrão) ou gaia_api
    def __init__(self, port=None, fingerprint=None, sid=None, server="127.0.0.1", http_debug_level=0,
                 api_calls=None, debug_file="", proxy_host=None, proxy_port=8080,
                 api_version=None, unsafe=False, unsafe_auto_accept=False, context="web_api"):
        self.port = port
        # impressora do servidor de gerenciamento
        self.fingerprint = fingerprint
        # session-id.
        self.sid = sid
        # nome ou endereço IP do servidor de gerenciamento
        self.server = server
        # nível de depuração
        self.http_debug_level = http_debug_level
        # um array com todas as chamadas da API (para fins de depuração)
        self.api_calls = api_calls if api_calls else []
        # nome do arquivo de depuração. Se deixado vazio, os dados de depuração não serão salvos no disco.
        self.debug_file = debug_file
        # endereço do servidor proxy HTTP (sem "http://")
        self.proxy_host = proxy_host
        # porta do proxy HTTP
        self.proxy_port = proxy_port
        # versão da API do servidor de gerenciamento
        self.api_version = api_version
        # Indica que o cliente não deve verificar o certificado do servidor
        self.unsafe = unsafe
        # Indica que o cliente deve aceitar e salvar automaticamente o certificado do servidor
        self.unsafe_auto_accept = unsafe_auto_accept
        # O contexto de uso do cliente - o padrão é web_api
        self.context = context

Acredito que os argumentos que podem ser usados nas instâncias da classe APIClientArgs sejam intuitivos para os administradores do Check Point e não necessitem de comentários adicionais.

Conectando-se através do APIClient e do gerenciador de contexto

Classe APIClient é mais conveniente usar através do gerenciador de contexto. Tudo o que precisa ser passado para a instância da classe APIClient são os parâmetros de conexão que foram definidos na etapa anterior.

with APIClient(client_args) as client:

O gerenciador de contexto não realizará automaticamente a chamada de login na API do servidor, mas ele fará a chamada de logout ao sair. Se, por algum motivo, a chamada de logout não for necessária ao final do trabalho com as chamadas da API, você deve iniciar o trabalho sem usar o gerenciador de contexto:

client = APIClient(clieng_args)

Verificação de conexão

É mais fácil verificar se a conexão passa pelos parâmetros especificados usando o método check_fingerprint. Se a verificação do hash sha1 para o certificado fingerprint da API do servidor falhar (o método retornar False), isso geralmente é causado por problemas de conexão e podemos interromper a execução do programa (ou dar ao usuário a chance de corrigir os dados de conexão):

    if client.check_fingerprint() is False:
        print("Não foi possível obter o fingerprint do servidor - Verifique a conectividade com o servidor.")
        exit(1)

Tenha em mente que a classe APIClient verificará a cada chamada da API (métodos api_call e api_query, que serão discutidos mais adiante) o fingerprint sha1 do certificado na API do servidor. Se um erro for detectado durante a verificação do fingerprint sha1 do certificado da API do servidor (certificado desconhecido ou alterado), o método check_fingerprint oferecerá a possibilidade de adicionar/alterar as informações sobre ele no computador local de forma automática. Essa verificação pode ser completamente desativada (mas isso só é recomendado na execução de scripts no próprio servidor da API, ao se conectar a 127.0.0.1), usando o argumento APIClientArgs — unsafe_auto_accept (veja mais sobre APIClientArgs anteriormente em "Definindo parâmetros de conexão").

client_args = APIClientArgs(unsafe_auto_accept=True)

Login na API do servidor

Na APIClient existem 3 métodos de login na API do servidor, e cada um deles armazena o valor sid(session-id), que é utilizado automaticamente em cada chamada subsequente da API no cabeçalho (o nome no cabeçalho deste parâmetro — X-chkp-sid), então não é necessário processar esse parâmetro adicionalmente.

Método login

Opção usando login e senha (no exemplo, o nome de usuário admin e a senha 1q2w3e foram passados como argumentos posicionais):

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

No método login, também estão disponíveis parâmetros opcionais adicionais, aqui estão seus nomes e valores padrão:

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

Método login_with_api_key

Opção usando a chave API (suportada a partir da versão de gerenciamento R80.40/Management API v1.6, «3TsbPJ8ZKjaJGvFyoFqHFA==» este é o valor da chave API para um dos usuários no servidor de gerenciamento com o método de autorização API key):

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

No método login_with_api_key os mesmos parâmetros opcionais estão disponíveis como no método login.

O método login_as_root

Uma variante de login na máquina local com o servidor API:

     login = client.login_as_root()

Para este método, apenas dois parâmetros opcionais estão disponíveis:

domain=None, payload=None

E finalmente os próprios chamadas API

Temos duas opções para fazer chamadas API através dos métodos api_call e api_query. Vamos entender qual é a diferença entre elas.

api_call

Este método é aplicável a qualquer chamada. Precisamos passar a última parte para a chamada API e o payload no corpo da solicitação, se necessário. Se o payload estiver vazio, não precisa ser passado:

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

Saída para esta solicitação abaixo:

Em [23]: api_versions                                                           
Saída[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'})

Saída para esta solicitação abaixo:

Em [25]: show_host                                                              
Out[25]: 
APIResponse({
    "data": {
        "color": "preto",
        "comments": "",
        "domain": {
            "domain-type": "domínio",
            "name": "Usuário SMC",
            "uid": "41e821a0-3720-11e3-aa6e-0800200c9fde"
        },
        "groups": [],
        "icon": "Objects/host",
        "interfaces": [],
        "ipv4-address": "8.8.8.8",
        "meta-info": {
            "creation-time": {
                "iso-8601": "2020-05-01T21:49+0300",
                "posix": 1588358973517
            },
            "creator": "admin",
            "last-modifier": "admin",
            "last-modify-time": {
                "iso-8601": "2020-05-01T21:49+0300",
                "posix": 1588358973517
            },
            "lock": "desbloqueado",
            "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": "preto",
            "comments": "",
            "domain": {
                "domain-type": "domínio",
                "name": "Usuário SMC",
                "uid": "41e821a0-3720-11e3-aa6e-0800200c9fde"
            },
            "groups": [],
            "icon": "Objects/host",
            "interfaces": [],
            "ipv4-address": "8.8.8.8",
            "meta-info": {
                "creation-time": {
                    "iso-8601": "2020-05-01T21:49+0300",
                    "posix": 1588358973517
                },
                "creator": "admin",
                "last-modifier": "admin",
                "last-modify-time": {
                    "iso-8601": "2020-05-01T21:49+0300",
                    "posix": 1588358973517
                },
                "lock": "desbloqueado",
                "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

Deixe-me esclarecer que este método é aplicável apenas para chamadas cujo retorno pressupõe offset (deslocamento). Esse retorno ocorre quando ele contém ou pode conter uma grande quantidade de informações. Por exemplo, isso pode ser uma solicitação de lista de todos os objetos do tipo host criados no servidor de gerenciamento. Para tais solicitações, a API retorna uma lista de 50 objetos por padrão (o limite pode ser aumentado para 500 objetos na resposta). E para evitar fazer múltiplas chamadas para obter informações mudando o parâmetro offset na solicitação da API, existe o método api_query, que realiza esse trabalho automaticamente. Exemplos de chamadas onde esse método é necessário: 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. Na verdade, no nome dessas chamadas da API vemos palavras no plural, então essas chamadas serão mais fáceis de serem processadas através de api_query

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

Saída para esta solicitação abaixo:

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

Processamento de resultados de chamadas de API

Após isso, é possível utilizar variáveis e métodos da classe APIResponse(tanto dentro do gerenciador de contexto quanto fora dele). A classe APIResponse possui 4 métodos e 5 variáveis predefinidas, nos concentraremos nas mais importantes.

Facilitando o trabalho com a API do Check Point usando o SDK do Python

success

Para começar, seria bom garantir que a chamada da API foi bem-sucedida e retornou um resultado. Para isso, existe o método success:

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

Retorna True se a chamada da API foi bem-sucedida (Código de resposta — 200) e False se não foi bem-sucedida (qualquer outro código de resposta). É conveniente usar logo após a chamada da API, para exibir informações diferentes dependendo do código de resposta.

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

statuscode

Retorna o código de resposta após a execução da chamada da API.

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

Códigos de resposta possíveis: 200,400,401,403,404,409,500,501.

set_success_status

No entanto, pode ser necessário alterar o valor do status success. Tecnicamente, pode-se colocar qualquer coisa lá, até mesmo uma string comum. Mas um exemplo real pode ser redefinir esse parâmetro para False sob certas condições associadas. Abaixo, observe o exemplo em que existem tarefas sendo executadas no servidor de gerenciamento, mas consideraremos essa solicitação como falhada (definiremos a variável success em False, embora a chamada da API tenha sido bem-sucedida e retornado o 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

response()

O método response permite ver um dicionário com o código de resposta (status_code) e o corpo da resposta (body).

In [94]: api_versions.response()                                                
Out[94]: 
{'status_code': 200,
 'data': {'current-version': '1.6',
  'supported-versions': ['1', '1.1', '1.2', '1.3', '1.4', '1.5', '1.6']}}

data

Permite ver apenas o corpo da resposta (body) sem informações excessivas.

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

Essas informações estão disponíveis apenas quando ocorre um erro ao processar a solicitação da API (código de resposta não 200). Exemplo de saída

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

Exemplos úteis

Abaixo estão exemplos que utilizam chamadas de API que foram adicionadas na versão Management API 1.6.

Para começar, vamos examinar o funcionamento das chamadas add-host e add-address-range. Suponha que precisamos criar como objetos do tipo host todos os endereços IP da sub-rede 192.168.0.0/24, cujo último octeto seja 5, enquanto todos os outros endereços IP devem ser registrados como objetos do tipo intervalo de endereços. Além disso, o endereço da sub-rede e o endereço de broadcast devem ser excluídos.

Assim, abaixo está um script que resolve essa tarefa e cria 50 objetos do tipo host e 51 objetos do tipo intervalo de endereços. Para resolver a tarefa, são necessárias 101 chamadas de API (sem contar a chamada final de publicação). Além disso, com o módulo timeit, calculamos o tempo de execução do script até o momento da publicação das alterações.

Script utilizando add-host e 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')

No meu ambiente de laboratório, a execução deste script leva de 30 a 50 segundos, dependendo da carga no servidor de gerenciamento.

Agora vamos ver como resolver essa mesma tarefa usando uma chamada de API add-objects-batch, cujo suporte foi adicionado na versão da API 1.6. Essa chamada permite criar muitos objetos de uma só vez com uma única solicitação API. Além disso, esses podem ser objetos de tipos diferentes (como hosts, sub-redes e intervalos de endereços). Assim, nossa tarefa pode ser resolvida em uma única chamada API.

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

A execução deste script no meu ambiente de laboratório leva de 3 a 7 segundos, dependendo da carga no servidor de gerenciamento. Ou seja, em média, a chamada de API do tipo batch para 101 objetos é 10 vezes mais rápida. Com um maior número de objetos, a diferença será ainda mais impressionante.

Agora vamos ver como trabalhar com set-objects-batch. Com essa chamada de API, podemos alterar em massa qualquer parâmetro. Vamos definir a cor sienna para a primeira metade dos endereços do exemplo anterior (até .124 do host, incluindo os intervalos) e a cor khaki para a segunda metade dos endereços.

Alteração da cor dos objetos criados no exemplo 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")

É possível remover vários objetos em uma única chamada de API usando delete-objects-batch. Agora, vamos ver um exemplo de código que remove todos os hosts criados anteriormente através de add-objects-batch.

Removendo objetos usando 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)

Todas as funcionalidades que aparecem nas novas versões do software Check Point ganham imediatamente chamadas de API. Assim, no R80.40 surgiram recursos como Revert to revision e Smart Task, e para eles foram prontamente preparadas as chamadas de API correspondentes. Além disso, toda a funcionalidade ao migrar do modo Legacy para o modo Unified Policy também passa a ter suporte da API. Por exemplo, uma atualização esperada na versão de software R80.40 foi a migração da política de Inspeção HTTPS do modo Legacy para o modo Unified Policy, e essa funcionalidade imediatamente obteve chamadas de API. Aqui está um exemplo de código que adiciona, na posição mais alta, uma regra na política de Inspeção HTTPS que exclui da inspeção 3 categorias (Saúde, Finanças, Serviços Públicos), que são proibidas de serem inspecionadas de acordo com a legislação em vários países.

Adicionar regra à política de Inspeção HTTPS

from cpapi import APIClient, APIClientArgs

client_args = APIClientArgs(server="192.168.47.240")

data = {
  "layer" : "Camada Padrão",
  "position" : "top",
  "name" : "Requisitos Legais",
  "action": "bypass",
  "site-category": ["Saúde", "Governo / Militar", "Serviços Financeiros"]
}

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

Execução de scripts Python no servidor de gerenciamento Check Point

Tudo na mesma README.md contém informações sobre como executar scripts em Python diretamente do servidor de gerenciamento. Isso pode ser conveniente quando você não tem a capacidade de se conectar ao servidor da API de outra máquina. Eu gravei um vídeo de seis minutos no qual examino a instalação do módulo cpapi e as particularidades da execução de scripts Python no servidor de gerenciamento. Como exemplo, estou executando um script que automatiza a configuração de um novo gateway para uma tarefa como auditoria de rede. Security CheckUp. Entre as particularidades que enfrentei: na versão Python 2.7 ainda não existe a função input, portanto, para processar as informações inseridas pelo usuário, usa-se a função raw_input. No restante, o código é o mesmo que para execução em outras máquinas, apenas é mais conveniente usar a função login_as_root, para não precisar inserir novamente seu próprio nome de usuário, senha e endereço IP do servidor de gerenciamento.

Por que no hosting comum a administração do PrestaShop é lenta, e no seu não é?

Script para configuração rápida do 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("Não foi possível obter a impressão digital do servidor - Verifique a conectividade com o servidor.")
       #     exit(1)
        login_res = client.login_as_root()

        if login_res.success is False:
            print("Falha no login:n{}".format(login_res.error_message))
            exit(1)

        gw_name = raw_input("Digite o nome do gateway:")
        gw_ip = raw_input("Digite o endereço IP do gateway:")
        if sys.stdin.isatty():
            sic = getpass.getpass("Digite a senha temporária para o gateway (SIC): ")
        else:
            print("Atenção! Sua senha será exibida na tela!")
            sic = raw_input("Digite a senha temporária para o gateway (SIC): ")
        version = raw_input("Digite a versão do gateway (como 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("A conexão segura com o gateway não foi estabelecida!")
            exit(1)
        elif add_gw.success:
            print("O gateway foi adicionado com sucesso.")
            gw_uid = add_gw.data['uid']
            gw_name = add_gw.data['name']
        else:
            print("Falha ao adicionar o gateway - {}".format(add_gw.error_message))
            exit(1)

        change_policy = client.api_call("set-access-layer", {"name" : "Rede", "applications-and-url-filtering": "true", "content-awareness": "true"})
        if change_policy.success:
            print("A política foi alterada com sucesso")
        else:
            print("Falha ao alterar a política - {}".format(change_policy.error_message))
        change_rule = client.api_call("set-access-rule", {"name" : "Regra de Limpeza", "layer" : "Rede", "action": "Accept", "track": {"type": "Registro Detalhado", "accounting": "true"}})
        if change_rule.success:
            print("A regra de limpeza foi alterada com sucesso")
        else:
            print("Falha ao alterar a regra de limpeza - {}".format(change_rule.error_message))

        # publicar o resultado
        publish_res = client.api_call("publish", {})
        if publish_res.success:
            print("As alterações foram publicadas com sucesso.")
        else:
                print("Falha ao publicar as alterações - {}".format(install_tp_policy.error_message))

        install_access_policy = client.api_call("install-policy", {"policy-package" : "Padrão", "access" : 'true',  "threat-prevention" : 'false', "targets" : gw_uid})
        if install_access_policy.success:
            print("A política de acesso foi instalada")
        else:
                print("Falha ao instalar a política de acesso - {}".format(install_tp_policy.error_message))

        install_tp_policy = client.api_call("install-policy", {"policy-package" : "Padrão", "access" : 'false',  "threat-prevention" : 'true', "targets" : gw_uid})
        if install_tp_policy.success:
            print("A política de prevenção de ameaças foi instalada")
        else:
            print("Falha ao instalar a política de prevenção de ameaças - {}".format(install_tp_policy.error_message))
        
        # adicionar senhas e frases-senha ao dicionário
        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" : "Adicionar senhas e frases-senha", "script" : "printf "{}" >> $FWDIR/conf/additional_pass.conf".format(line), "targets" : gw_name})
                if add_password_dictionary.success:
                    print("A linha do dicionário de senhas {} foi adicionada com sucesso".format(line_num))
                else:
                    print("Falha ao adicionar o dicionário - {}".format(add_password_dictionary.error_message))

main()

Exemplo de arquivo com o dicionário de senhas additional_pass.conf
{
"passwords" : ["malware","malicioso","infectado","Infectado"],
"phrases" : ["senha","Senha","Pass","pass","codigo","chave","pwd","senha","Senha","Chave","chave","código","Códigos"]
}

Conclusão

Este artigo considera apenas as principais funcionalidades de trabalho Python SDK e do módulo cpapi(como você pode supor, são essencialmente sinônimos), e estudando o código deste módulo, você descobrirá ainda mais possibilidades na sua utilização. É possível que você tenha o desejo de complementá-lo com suas próprias classes, funções, métodos e variáveis. Você sempre pode compartilhar seus trabalhos e revisar outros scripts para Check Point na seção CodeHub na comunidade CheckMates, que reúne tanto desenvolvedores de produtos quanto usuários.

Feliz codificação e obrigado por ler até o final!

Fonte: habr.com

Compre hospedagem confiável para sites com proteção contra DDoS, servidores VPS VDS 🔥 Compre hospedagem confiável para sites com proteção contra DDoS, servidores VPS VDS | ProHoster