Check Point R80.10 API. Π£ΠΏΡ€Π°Π²Π»Π΅Π½ΠΈΠ΅ Ρ‡Π΅Ρ€Π΅Π· CLI, скрипты ΠΈ Π½Π΅ Ρ‚ΠΎΠ»ΡŒΠΊΠΎ

Check Point R80.10 API. Π£ΠΏΡ€Π°Π²Π»Π΅Π½ΠΈΠ΅ Ρ‡Π΅Ρ€Π΅Π· CLI, скрипты ΠΈ Π½Π΅ Ρ‚ΠΎΠ»ΡŒΠΊΠΎ

Π£Π²Π΅Ρ€Π΅Π½, Ρ‡Ρ‚ΠΎ Ρƒ ΠΊΠ°ΠΆΠ΄ΠΎΠ³ΠΎ, ΠΊΡ‚ΠΎ ΠΊΠΎΠ³Π΄Π°-Π»ΠΈΠ±ΠΎ Ρ€Π°Π±ΠΎΡ‚Π°Π» с Check Point, Π²ΠΎΠ·Π½ΠΈΠΊΠ°Π»Π° прСтСнзия ΠΏΠΎ ΠΏΠΎΠ²ΠΎΠ΄Ρƒ нСвозмоТности ΠΏΡ€Π°Π²ΠΊΠΈ ΠΊΠΎΠ½Ρ„ΠΈΠ³ΡƒΡ€Π°Ρ†ΠΈΠΈ ΠΈΠ· ΠΊΠΎΠΌΠ°Π½Π΄Π½ΠΎΠΉ строки. Π­Ρ‚ΠΎ особСнно Π΄ΠΈΠΊΠΎ для Ρ‚Π΅Ρ…, ΠΊΡ‚ΠΎ Π΄ΠΎ этого Ρ€Π°Π±ΠΎΡ‚Π°Π» с Cisco ASA, Π³Π΄Π΅ Π°Π±ΡΠΎΠ»ΡŽΡ‚Π½ΠΎ всС ΠΌΠΎΠΆΠ½ΠΎ Π½Π°ΡΡ‚Ρ€ΠΎΠΈΡ‚ΡŒ Π² CLI. Π£ Check Point-Π° всС Π½Π°ΠΎΠ±ΠΎΡ€ΠΎΡ‚ β€” всС настройки бСзопасности Π²Ρ‹ΠΏΠΎΠ»Π½ΡΠ»ΠΈΡΡŒ ΠΈΡΠΊΠ»ΡŽΡ‡ΠΈΡ‚Π΅Π»ΡŒΠ½ΠΎ ΠΈΠ· графичСского интСрфСйса. Однако, Π½Π΅ΠΊΠΎΡ‚ΠΎΡ€Ρ‹Π΅ Π²Π΅Ρ‰ΠΈ ΡΠΎΠ²Π΅Ρ€ΡˆΠ΅Π½Π½ΠΎ Π½Π΅ ΡƒΠ΄ΠΎΠ±Π½ΠΎ Π΄Π΅Π»Π°Ρ‚ΡŒ Ρ‡Π΅Ρ€Π΅Π· GUI (Π΄Π°ΠΆΠ΅ Ρ‚Π°ΠΊΠΎΠΉ ΡƒΠ΄ΠΎΠ±Π½Ρ‹ΠΉ ΠΊΠ°ΠΊ Ρƒ Check Point). К ΠΏΡ€ΠΈΠΌΠ΅Ρ€Ρƒ Π·Π°Π΄Π°Ρ‡Π° ΠΏΠΎ добавлСнию 100 Π½ΠΎΠ²Ρ‹Ρ… хостов ΠΈΠ»ΠΈ сСтСй прСвращаСтся Π² Π΄ΠΎΠ»Π³ΡƒΡŽ ΠΈ Π½ΡƒΠ΄Π½ΡƒΡŽ ΠΏΡ€ΠΎΡ†Π΅Π΄ΡƒΡ€Ρƒ. Для ΠΊΠ°ΠΆΠ΄ΠΎΠ³ΠΎ ΠΎΠ±ΡŠΠ΅ΠΊΡ‚Π° придСтся нСсколько Ρ€Π°Π· ΠΊΠ»ΠΈΠΊΠ°Ρ‚ΡŒ ΠΌΡ‹ΡˆΠΊΠΎΠΉ ΠΈ Π²Π±ΠΈΠ²Π°Ρ‚ΡŒ ip-адрСс. Π’ΠΎ ΠΆΠ΅ самоС касаСтся создания Π³Ρ€ΡƒΠΏΠΏΡ‹ сайтов ΠΈΠ»ΠΈ массового Π²ΠΊΠ»ΡŽΡ‡Π΅Π½ΠΈΡ/ΠΎΡ‚ΠΊΠ»ΡŽΡ‡Π΅Π½ΠΈΡ IPS сигнатур. ΠŸΡ€ΠΈ этом Π²Π΅Π»ΠΈΠΊΠ° Π²Π΅Ρ€ΠΎΡΡ‚Π½ΠΎΡΡ‚ΡŒ Π΄ΠΎΠΏΡƒΡΡ‚ΠΈΡ‚ΡŒ ΠΎΡˆΠΈΠ±ΠΊΡƒ.

ΠžΡ‚Π½ΠΎΡΠΈΡ‚Π΅Π»ΡŒΠ½ΠΎ Π½Π΅Π΄Π°Π²Π½ΠΎ ΡΠ»ΡƒΡ‡ΠΈΠ»ΠΎΡΡŒ β€œΡ‡ΡƒΠ΄ΠΎβ€. Π‘ Π²Ρ‹Ρ…ΠΎΠ΄ΠΎΠΌ Π½ΠΎΠ²ΠΎΠΉ вСрсии Gaia R80 Π±Ρ‹Π»Π° анонсирована Π²ΠΎΠ·ΠΌΠΎΠΆΠ½ΠΎΡΡ‚ΡŒ использования API, Ρ‡Ρ‚ΠΎ ΠΎΡ‚ΠΊΡ€Ρ‹Π²Π°Π΅Ρ‚ ΡˆΠΈΡ€ΠΎΠΊΠΈΠ΅ возмоТности ΠΏΠΎ Π°Π²Ρ‚ΠΎΠΌΠ°Ρ‚ΠΈΠ·Π°Ρ†ΠΈΠΈ настроСк, Π°Π΄ΠΌΠΈΠ½ΠΈΡΡ‚Ρ€ΠΈΡ€ΠΎΠ²Π°Π½ΠΈΡŽ, ΠΌΠΎΠ½ΠΈΡ‚ΠΎΡ€ΠΈΠ½Π³Ρƒ ΠΈ Ρ‚.Π΄. Π’Π΅ΠΏΠ΅Ρ€ΡŒ ΠΌΠΎΠΆΠ½ΠΎ:

  • ΡΠΎΠ·Π΄Π°Π²Π°Ρ‚ΡŒ ΠΎΠ±ΡŠΠ΅ΠΊΡ‚Ρ‹;
  • Π΄ΠΎΠ±Π°Π²Π»ΡΡ‚ΡŒ ΠΈΠ»ΠΈ ΠΏΡ€Π°Π²ΠΈΡ‚ΡŒ access-list-Ρ‹;
  • Π²ΠΊΠ»ΡŽΡ‡Π°Ρ‚ΡŒ/ΠΎΡ‚ΠΊΠ»ΡŽΡ‡Π°Ρ‚ΡŒ Π±Π»Π΅ΠΉΠ΄Ρ‹;
  • Π½Π°ΡΡ‚Ρ€Π°ΠΈΠ²Π°Ρ‚ΡŒ сСтСвыС интСрфСйсы;
  • ΠΈΠ½ΡΡ‚Π°Π»Π»ΠΈΡ€ΠΎΠ²Π°Ρ‚ΡŒ ΠΏΠΎΠ»ΠΈΡ‚ΠΈΠΊΠΈ;
  • ΠΈ ΠΌΠ½ΠΎΠ³ΠΎΠ΅ Π΄Ρ€ΡƒΠ³ΠΎΠ΅.

Если чСстно, Π½Π΅ понимаю ΠΊΠ°ΠΊ эта Π½ΠΎΠ²ΠΎΡΡ‚ΡŒ ΠΏΡ€ΠΎΡˆΠ»Π° ΠΌΠΈΠΌΠΎ Π₯Π°Π±Ρ€Π°. Π’ Π΄Π°Π½Π½ΠΎΠΉ ΡΡ‚Π°Ρ‚ΡŒΠ΅ ΠΌΡ‹ Π²ΠΊΡ€Π°Ρ‚Ρ†Π΅ опишСм ΠΊΠ°ΠΊ ΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚ΡŒΡΡ API ΠΈ ΠΏΡ€ΠΈΠ²Π΅Π΄Π΅ΠΌ нСсколько практичСских ΠΏΡ€ΠΈΠΌΠ΅Ρ€ΠΎΠ² настройки CheckPoint с ΠΏΠΎΠΌΠΎΡ‰ΡŒΡŽ скриптов.

Π‘Ρ€Π°Π·Ρƒ Ρ…ΠΎΡ‚Π΅Π» Π±Ρ‹ ΠΎΠ³ΠΎΠ²ΠΎΡ€ΠΈΡ‚ΡŒΡΡ, API ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠ΅Ρ‚ΡΡ Ρ‚ΠΎΠ»ΡŒΠΊΠΎ для Management сСрвСра. Π’.Π΅. ΡƒΠΏΡ€Π°Π²Π»ΡΡ‚ΡŒ шлюзами Π±Π΅Π· Management сСрвСра ΠΏΠΎ ΠΏΡ€Π΅ΠΆΠ½Π΅ΠΌΡƒ Π½Π΅Π²ΠΎΠ·ΠΌΠΎΠΆΠ½ΠΎ.

ΠšΠΎΠΌΡƒ Π² ΠΏΡ€ΠΈΠ½Ρ†ΠΈΠΏΠ΅ ΠΌΠΎΠΆΠ΅Ρ‚ ΠΏΡ€ΠΈΠ³ΠΎΠ΄ΠΈΡ‚ΡŒΡΡ Π΄Π°Π½Π½Ρ‹ΠΉ API?

  1. БистСмныС администраторы, ΠΊΠΎΡ‚ΠΎΡ€Ρ‹Π΅ хотят ΡƒΠΏΡ€ΠΎΡΡ‚ΠΈΡ‚ΡŒ ΠΈΠ»ΠΈ Π°Π²Ρ‚ΠΎΠΌΠ°Ρ‚ΠΈΠ·ΠΈΡ€ΠΎΠ²Π°Ρ‚ΡŒ Ρ€ΡƒΡ‚ΠΈΠ½Π½Ρ‹Π΅ Π·Π°Π΄Π°Ρ‡ΠΈ ΠΏΠΎ настройкС Check Point;
  2. Компании, ΠΊΠΎΡ‚ΠΎΡ€Ρ‹Π΅ хотят ΠΈΠ½Ρ‚Π΅Π³Ρ€ΠΈΡ€ΠΎΠ²Π°Ρ‚ΡŒ Check Point с Π΄Ρ€ΡƒΠ³ΠΈΠΌΠΈ Ρ€Π΅ΡˆΠ΅Π½ΠΈΡΠΌΠΈ (систСмы Π²ΠΈΡ€Ρ‚ΡƒΠ°Π»ΠΈΠ·Π°Ρ†ΠΈΠΈ, Ρ‚ΠΈΠΊΠ΅Ρ‚-систСмы, систСмы управлСния конфигурациями ΠΈ Ρ‚.Π΄.);
  3. БистСмныС ΠΈΠ½Ρ‚Π΅Π³Ρ€Π°Ρ‚ΠΎΡ€Ρ‹, ΠΊΠΎΡ‚ΠΎΡ€Ρ‹Π΅ хотят ΡΡ‚Π°Π½Π΄Π°Ρ€Ρ‚ΠΈΠ·ΠΈΡ€ΠΎΠ²Π°Ρ‚ΡŒ настройки ΠΈΠ»ΠΈ ΡΠΎΠ·Π΄Π°Ρ‚ΡŒ Π΄ΠΎΠΏΠΎΠ»Π½ΠΈΡ‚Π΅Π»ΡŒΠ½Ρ‹Π΅ ΠΏΡ€ΠΎΠ΄ΡƒΠΊΡ‚Ρ‹ связанныС с Check Point.

Виповая схСма

И Ρ‚Π°ΠΊ, прСдставим Ρ‚ΠΈΠΏΠΎΠ²ΡƒΡŽ схСму с Check Point:

Check Point R80.10 API. Π£ΠΏΡ€Π°Π²Π»Π΅Π½ΠΈΠ΅ Ρ‡Π΅Ρ€Π΅Π· CLI, скрипты ΠΈ Π½Π΅ Ρ‚ΠΎΠ»ΡŒΠΊΠΎ

Как ΠΎΠ±Ρ‹Ρ‡Π½ΠΎ Ρƒ нас Π΅ΡΡ‚ΡŒ шлюз (SG), сСрвСр управлСния (SMS) ΠΈ консоль администратора (SmartConsole). ΠŸΡ€ΠΈ этом ΠΎΠ±Ρ‹Ρ‡Π½Ρ‹ΠΉ процСсс настройки шлюза выглядит ΡΠ»Π΅Π΄ΡƒΡŽΡ‰ΠΈΠΌ ΠΎΠ±Ρ€Π°Π·ΠΎΠΌ:

Check Point R80.10 API. Π£ΠΏΡ€Π°Π²Π»Π΅Π½ΠΈΠ΅ Ρ‡Π΅Ρ€Π΅Π· CLI, скрипты ΠΈ Π½Π΅ Ρ‚ΠΎΠ»ΡŒΠΊΠΎ

Π’.Π΅. сначала Π½Π΅ΠΎΠ±Ρ…ΠΎΠ΄ΠΈΠΌΠΎ Π½Π° ΠΊΠΎΠΌΠΏΡŒΡŽΡ‚Π΅Ρ€Π΅ администратора Π·Π°ΠΏΡƒΡΡ‚ΠΈΡ‚ΡŒ SmartConsole, с ΠΏΠΎΠΌΠΎΡ‰ΡŒΡŽ ΠΊΠΎΡ‚ΠΎΡ€ΠΎΠΉ ΠΌΡ‹ ΠΏΠΎΠ΄ΠΊΠ»ΡŽΡ‡Π°Π΅ΠΌΡΡ ΠΊ Management-сСрвСру (SMS). На SMS Π²Ρ‹ΠΏΠΎΠ»Π½ΡΡŽΡ‚ΡΡ настройки бСзопасности, Π° ΡƒΠΆΠ΅ Π·Π°Ρ‚Π΅ΠΌ ΠΏΡ€ΠΈΠΌΠ΅Π½ΡΡŽΡ‚ΡΡ (install policy) Π½Π° шлюз (SG).

ΠŸΡ€ΠΈ использовании Management API, ΠΌΡ‹ Π² ΠΏΡ€ΠΈΠ½Ρ†ΠΈΠΏΠ΅ ΠΌΠΎΠΆΠ΅ΠΌ ΠΏΡ€ΠΎΠΏΡƒΡΡ‚ΠΈΡ‚ΡŒ ΠΏΠ΅Ρ€Π²Ρ‹ΠΉ ΠΏΡƒΠ½ΠΊΡ‚ (запуск SmartConsole) ΠΈ ΠΏΡ€ΠΈΠΌΠ΅Π½ΡΡ‚ΡŒ API-ΠΊΠΎΠΌΠ°Π½Π΄Ρ‹ нСпосрСдствСнно ΠΊ Management-сСрвСру (SMS).

Бпособы использования API

Для ΠΏΡ€Π°Π²ΠΊΠΈ ΠΊΠΎΠ½Ρ„ΠΈΠ³ΡƒΡ€Π°Ρ†ΠΈΠΈ с ΠΏΠΎΠΌΠΎΡ‰ΡŒΡŽ API Π΅ΡΡ‚ΡŒ Ρ‡Π΅Ρ‚Ρ‹Ρ€Π΅ основных способа:

1) Π‘ ΠΏΠΎΠΌΠΎΡ‰ΡŒΡŽ ΡƒΡ‚ΠΈΠ»ΠΈΡ‚Ρ‹ mgmt_cli

ΠŸΡ€ΠΈΠΌΠ΅Ρ€ β€” # mgmt_cli add host name host1 ip-address 192.168.2.100
Данная ΠΊΠΎΠΌΠ°Π½Π΄Π° запускаСтся ΠΈΠ· ΠΊΠΎΠΌΠ°Π½Π΄Π½ΠΎΠΉ строки Management-сСрвСра (SMS). Π”ΡƒΠΌΠ°ΡŽ синтаксис ΠΊΠΎΠΌΠ°Π½Π΄Ρ‹ понятСн β€” создаСтся host1 с адрСсом 192.168.2.100.

2) Π’Π²ΠΎΠ΄ΠΈΡ‚ΡŒ API ΠΊΠΎΠΌΠ°Π½Π΄Ρ‹ Ρ‡Π΅Ρ€Π΅Π· clish (Π² Ρ€Π΅ΠΆΠΈΠΌΠ΅ expert)

По сути, всС Ρ‡Ρ‚ΠΎ Π²Π°ΠΌ Π½ΡƒΠΆΠ½ΠΎ, это Π·Π°Π»ΠΎΠ³ΠΈΠ½ΠΈΡ‚ΡŒΡΡ Π² ΠΊΠΎΠΌΠ°Π½Π΄Π½ΠΎΠΉ строкС (mgmt login) ΠΏΠΎΠ΄ ΡƒΡ‡Π΅Ρ‚Π½ΠΎΠΉ записью, которая ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠ΅Ρ‚ΡΡ ΠΏΡ€ΠΈ ΠΏΠΎΠ΄ΠΊΠ»ΡŽΡ‡Π΅Π½ΠΈΠΈ Ρ‡Π΅Ρ€Π΅Π· SmartConsole (Π»ΠΈΠ±ΠΎ root-ΡƒΡ‡Π΅Ρ‚ΠΊΠ°). Π—Π°Ρ‚Π΅ΠΌ ΡƒΠΆΠ΅ Π²Ρ‹ ΠΌΠΎΠΆΠ΅Ρ‚Π΅ Π²Π²ΠΎΠ΄ΠΈΡ‚ΡŒ API-ΠΊΠΎΠΌΠ°Π½Π΄Ρ‹ (Π² этом случаС Π½Π΅Ρ‚ нСобходимости ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚ΡŒ ΠΏΠ΅Ρ€Π΅Π΄ ΠΊΠ°ΠΆΠ΄ΠΎΠΉ ΠΊΠΎΠΌΠ°Π½Π΄ΠΎΠΉ ΡƒΡ‚ΠΈΠ»ΠΈΡ‚Ρƒ mgmt_cli). МоТно ΡΠΎΠ·Π΄Π°Π²Π°Ρ‚ΡŒ ΠΏΠΎΠ»Π½ΠΎΡ†Π΅Π½Π½Ρ‹Π΅ BASH-скрипты. ΠŸΡ€ΠΈΠΌΠ΅Ρ€ скрипта, ΠΊΠΎΡ‚ΠΎΡ€Ρ‹ΠΉ создаСт хост:

Bash-скрипт

#!/bin/bash

main() {
    clear

    #LOGIN (don't ask for username and password, user is already logged in to Management server as 'root' user)
    mgmt_cli login --root true > id_add_host.txt
    on_error_print_and_exit "Error: Failed to login, check that the server is up and running (run 'api status')"

    #READ HOST NAME
    printf "Enter host name:n"
    read -e host_name
    on_empty_input_print_and_exit "$host_name" "Error: The host's name cannot be empty."

    #READ IP ADDRESS
    printf "nEnter host IP address:n"
    read -e ip
    on_empty_input_print_and_exit "$ip" "Error: The host's IP address cannot be empty."

    #CREATE HOST
    printf "Creating new host: $host_name with IP address: $ipn"
    new_host_response=$(mgmt_cli add host name $host_name ip-address $ip -s id_add_host.txt 2> /dev/null)
    on_error_print_and_exit "Error: Failed to create host object. n$new_host_response"

    #PUBLISH THE CHANGES
    printf "nPublishing the changesn"
    mgmt_cli publish --root true -s id_add_host.txt &> /dev/null
    on_error_print_and_exit "Error: Failed to publish the changes."

    #LOGOUT
    logout
	
	printf "Done.n"
}

logout(){
	mgmt_cli logout --root true -s id_add_host.txt &> /dev/null
}

on_error_print_and_exit(){
    if [ $? -ne 0 ]; then
        handle_error "$1" 
	fi
}

handle_error(){
    printf "n$1n" #print error message
    mgmt_cli discard --root true -s id_add_host.txt &> /dev/null
    logout
    exit 1
}

on_empty_input_print_and_exit(){
	if [ -z "$1" ]; then
		printf "$2n" #print error message
		logout
		exit 0
	fi
}

# Script starts here. Call function "main".
main

Если интСрСсно, Ρ‚ΠΎ ΠΌΠΎΠΆΠ½ΠΎ ΠΏΠΎΡΠΌΠΎΡ‚Ρ€Π΅Ρ‚ΡŒ ΡΠΎΠΎΡ‚Π²Π΅Ρ‚ΡΡ‚Π²ΡƒΡŽΡ‰Π΅Π΅ Π²ΠΈΠ΄Π΅ΠΎ:

3) Π§Π΅Ρ€Π΅Π· SmartConsole, ΠΎΡ‚ΠΊΡ€Ρ‹Π² ΠΎΠΊΠ½ΠΎ CLI

ВсС Ρ‡Ρ‚ΠΎ Π½ΡƒΠΆΠ½ΠΎ ΡΠ΄Π΅Π»Π°Ρ‚ΡŒ, это Π·Π°ΠΏΡƒΡΡ‚ΠΈΡ‚ΡŒ окошко CLI прямо ΠΈΠ· SmartConsole, ΠΊΠ°ΠΊ это ΠΏΠΎΠΊΠ°Π·Π°Π½ΠΎ Π½Π° ΠΊΠ°Ρ€Ρ‚ΠΈΠ½ΠΊΠ΅ Π½ΠΈΠΆΠ΅.

Check Point R80.10 API. Π£ΠΏΡ€Π°Π²Π»Π΅Π½ΠΈΠ΅ Ρ‡Π΅Ρ€Π΅Π· CLI, скрипты ΠΈ Π½Π΅ Ρ‚ΠΎΠ»ΡŒΠΊΠΎ

Π’ этом ΠΎΠΊΠ½Π΅ ΠΌΠΎΠΆΠ½ΠΎ сразу Π½Π°Ρ‡ΠΈΠ½Π°Ρ‚ΡŒ Π²Π²ΠΎΠ΄ΠΈΡ‚ΡŒ API-ΠΊΠΎΠΌΠ°Π½Π΄Ρ‹.

4) Web Services. Π˜ΡΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚ΡŒ HTTPS Post request (REST API)

На наш взгляд это ΠΎΠ΄ΠΈΠ½ ΠΈΠ· самых пСрспСктивных способов, Ρ‚.ΠΊ. позволяСт β€œΡΡ‚Ρ€ΠΎΠΈΡ‚ΡŒβ€ Ρ†Π΅Π»Ρ‹Π΅ прилоТСния ΠΏΠΎ ΡƒΠΏΡ€Π°Π²Π»Π΅Π½ΠΈΡŽ сСрвСром управлСния (извиняюсь Π·Π° Ρ‚Π°Π²Ρ‚ΠΎΠ»ΠΎΠ³ΠΈΡŽ). НиТС ΠΌΡ‹ рассмотрим Π΄Π°Π½Π½Ρ‹ΠΉ ΠΌΠ΅Ρ‚ΠΎΠ΄ Ρ‡ΡƒΡ‚ΡŒ ΠΏΠΎΠ΄Ρ€ΠΎΠ±Π½Π΅Π΅.

Если Ρ€Π΅Π·ΡŽΠΌΠΈΡ€ΠΎΠ²Π°Ρ‚ΡŒ:

  1. API + cli большС ΠΏΠΎΠ΄Ρ…ΠΎΠ΄ΠΈΡ‚ для людСй, ΠΊΡ‚ΠΎ ΠΏΡ€ΠΈΠ²Ρ‹ΠΊ ΠΊ Cisco;
  2. API + shell для примСнСния скриптов ΠΈ выполнСния Ρ€ΡƒΡ‚ΠΈΠ½Π½Ρ‹Ρ… Π·Π°Π΄Π°Ρ‡;
  3. REST API для Π°Π²Ρ‚ΠΎΠΌΠ°Ρ‚ΠΈΠ·Π°Ρ†ΠΈΠΈ.

Π’ΠΊΠ»ΡŽΡ‡Π΅Π½ΠΈΠ΅ API

По-ΡƒΠΌΠΎΠ»Ρ‡Π°Π½ΠΈΡŽ, API Π²ΠΊΠ»ΡŽΡ‡Π΅Π½ Π½Π° ΠΌΠ΅Π½Π΅Π΄ΠΆΠΌΠ΅Π½Ρ‚ сСрвСрах с объСмом RAM Π±ΠΎΠ»Π΅Π΅ 4Π“Π± ΠΈ standalone конфигурациях с RAM Π±ΠΎΠ»Π΅Π΅ 8Π“Π±. ΠŸΡ€ΠΎΠ²Π΅Ρ€ΠΈΡ‚ΡŒ статус ΠΌΠΎΠΆΠ½ΠΎ с ΠΏΠΎΠΌΠΎΡ‰ΡŒΡŽ ΠΊΠΎΠΌΠ°Π½Π΄Ρ‹: api status

Если окаТСтся, Ρ‡Ρ‚ΠΎ api Π²Ρ‹ΠΊΠ»ΡŽΡ‡Π΅Π½, Ρ‚ΠΎ Π΅Π³ΠΎ довольно просто Π²ΠΊΠ»ΡŽΡ‡ΠΈΡ‚ΡŒ Ρ‡Π΅Ρ€Π΅Π· SmartConsole: Manage & Settings > Blades > Management API > Advanced Settings

Check Point R80.10 API. Π£ΠΏΡ€Π°Π²Π»Π΅Π½ΠΈΠ΅ Ρ‡Π΅Ρ€Π΅Π· CLI, скрипты ΠΈ Π½Π΅ Ρ‚ΠΎΠ»ΡŒΠΊΠΎ

Π—Π°Ρ‚Π΅ΠΌ ΠΎΠΏΡƒΠ±Π»ΠΈΠΊΠΎΠ²Π°Ρ‚ΡŒ (Publish) измСнСния ΠΈ Π²Ρ‹ΠΏΠΎΠ»Π½ΠΈΡ‚ΡŒ ΠΊΠΎΠΌΠ°Π½Π΄Ρƒ api restart.

Web requests + Python

Для выполнСния API-ΠΊΠΎΠΌΠ°Π½Π΄ ΠΌΠΎΠΆΠ½ΠΎ ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚ΡŒ Web-запросы с ΠΏΡ€ΠΈΠΌΠ΅Π½Π΅Π½ΠΈΠ΅ΠΌ Python ΠΈ Π±ΠΈΠ±Π»ΠΈΠΎΡ‚Π΅ΠΊ requests, json. Π’ ΠΎΠ±Ρ‰Π΅ΠΌ Π²ΠΈΠ΄Π΅ структура web-запроса состоит ΠΈΠ· Ρ‚Ρ€Π΅Ρ… частСй:

1)АдрСс

(https://<managemenet server>:<port>/web_api/<command>) 


2) HTTP Headers

content-Type: application/json
x-chkp-sid: <session ID token as returned by the login command>


3) Request payload

Text in JSON format containing the different parameters

ΠŸΡ€ΠΈΠΌΠ΅Ρ€ для Π²Ρ‹Π·ΠΎΠ²Π° Ρ€Π°Π·Π»ΠΈΡ‡Π½Ρ‹Ρ… ΠΊΠΎΠΌΠ°Π½Π΄:


def api_call(ip_addr, port, command, json_payload, sid):
    url = 'https://' + ip_addr + ':' + str(port) + '/web_api/' + command
    if sid == β€œβ€:
        request_headers = {'Content-Type' : 'application/json'}
    else:
        request_headers = {'Content-Type' : 'application/json', 'X-chkp-sid' : sid}
    r = requests.post(url,data=json.dumps(json_payload), headers=request_headers,verify=False)
    return r.json()                                        
'xxx.xxx.xxx.xxx' -> Ip address GAIA

ΠŸΡ€ΠΈΠ²Π΅Π΄Π΅ΠΌ нСсколько Ρ‚ΠΈΠΏΠΎΠ²Ρ‹Ρ… Π·Π°Π΄Π°Ρ‡, с ΠΊΠΎΡ‚ΠΎΡ€Ρ‹ΠΌΠΈ Ρ‡Π°Ρ‰Π΅ всСго приходится ΡΡ‚Π°Π»ΠΊΠΈΠ²Π°Ρ‚ΡŒΡΡ ΠΏΡ€ΠΈ администрировании Check Point.

1) ΠŸΡ€ΠΈΠΌΠ΅Ρ€ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΉ Π°Π²Ρ‚ΠΎΡ€ΠΈΠ·Π°Ρ†ΠΈΠΈ ΠΈ Π»ΠΎΠ³Π°ΡƒΡ‚Π°:

Π‘ΠΊΡ€ΠΈΠΏΡ‚


    payload = {β€˜user’: β€˜your_user’, β€˜password’ : β€˜your_password’}
    response = api_call('xxx.xxx.xxx.xxx', 443, 'login',payload, '')
    return response["sid"]

    response = api_call('xxx.xxx.xxx.xxx', 443,'logout', {} ,sid)
    return response["message"]

2) Π’ΠΊΠ»ΡŽΡ‡Π΅Π½ΠΈΠ΅ блэйдов ΠΈ настройка сСти:

Π‘ΠΊΡ€ΠΈΠΏΡ‚


new_gateway_data = {'name':'CPGleb','anti-bot':True,'anti-virus' : True,'application-control':True,'ips':True,'url-filtering':True,'interfaces':
                    [{'name':"eth0",'topology':'external','ipv4-address': 'xxx.xxx.xxx.xxx',"ipv4-network-mask": "255.255.255.0"},
                     {'name':"eth1",'topology':'internal','ipv4-address': 'xxx.xxx.xxx.xxx',"ipv4-network-mask": "255.255.255.0"}]}
new_gateway_result = api_call('xxx.xxx.xxx.xxx', 443,'set-simple-gateway', new_gateway_data ,sid)
print(json.dumps(new_gateway_result))

3) ИзмСнСниС ΠΏΡ€Π°Π²ΠΈΠ» мСТсСтСвого экрана:

Π‘ΠΊΡ€ΠΈΠΏΡ‚


new_access_data={'name':'Cleanup rule','layer':'Network','action':'Accept'}
new_access_result = api_call('xxx.xxx.xxx.xxx', 443,'set-access-rule', new_access_data ,sid)
print(json.dumps(new_access_result))

4)Π”ΠΎΠ±Π°Π²Π»Π΅Π½ΠΈΠ΅ Application layer:

Π‘ΠΊΡ€ΠΈΠΏΡ‚


add_access_layer_application={ 'name' : 'application123',"applications-and-url-filtering" : True,"firewall" : False}
add_access_layer_application_result = api_call('xxx.xxx.xxx.xxx', 443,'add-access-layer', add_access_layer_application ,sid)
print(json.dumps(add_access_layer_application_result))

set_package_layer={"name" : "Standard","access":True,"access-layers" : {"add" : [ { "name" : "application123","position" :2}]} ,"installation-targets" : "CPGleb"}
set_package_layer_result = api_call('xxx.xxx.xxx.xxx', 443,'set-package', set_package_layer ,sid)
print(json.dumps(set_package_layer_result))

5) Publish ΠΈ установка ΠΏΠΎΠ»ΠΈΡ‚ΠΈΠΊΠΈ, ΠΏΡ€ΠΎΠ²Π΅Ρ€ΠΊΠ° выполнСния ΠΊΠΎΠΌΠ°Π½Π΄Ρ‹ (task-id):

Π‘ΠΊΡ€ΠΈΠΏΡ‚


publish_result = api_call('xxx.xxx.xxx.xxx', 443,"publish", {},sid)
print("publish result: " + json.dumps(publish_result))
new_policy = {'policy-package':'Standard','access':True,'targets':['CPGleb']}
new_policy_result = api_call('xxx.xxx.xxx.xxx', 443,'install-policy', new_policy ,sid)
print(json.dumps(new_policy_result)

task_id=(json.dumps(new_policy_result ["task-id"]))
len_str=len(task_id)
task_id=task_id[1:(len_str-1)]
show_task_id ={'task-id':(task_id)}
show_task=api_call('xxx.xxx.xxx.xxx',443,'show-task',show_task_id,sid)
print(json.dumps(show_task))

6) Π”ΠΎΠ±Π°Π²ΠΈΡ‚ΡŒ хост:

Π‘ΠΊΡ€ΠΈΠΏΡ‚


new_host_data = {'name':'JohnDoePc', 'ip-address': '192.168.0.10'}
new_host_result = api_call('xxx.xxx.xxx.xxx', 443,'add-host', new_host_data ,sid)
print(json.dumps(new_host_result))

7) Π”ΠΎΠ±Π°Π²ΠΈΡ‚ΡŒ ΠΏΠΎΠ»Π΅ Threat Prevention:

Π‘ΠΊΡ€ΠΈΠΏΡ‚


set_package_layer={'name':'Standard','threat-prevention' :True,'installation-targets':'CPGleb'}
set_package_layer_result = api_call('xxx.xxx.xxx.xxx', 443,'set-package',set_package_layer,sid)
print(json.dumps(set_package_layer_result))

8) ΠŸΠΎΡΠΌΠΎΡ‚Ρ€Π΅Ρ‚ΡŒ список сСссий

Π‘ΠΊΡ€ΠΈΠΏΡ‚


new_session_data = {'limit':'50', 'offset':'0','details-level' : 'standard'}
new_session_result = api_call('xxx.xxx.xxx.xxx', 443,'show-sessions', new_session_data ,sid)
print(json.dumps(new_session_result))

9) Π‘ΠΎΠ·Π΄Π°Ρ‚ΡŒ Π½ΠΎΠ²Ρ‹ΠΉ ΠΏΡ€ΠΎΡ„ΠΈΠ»ΡŒ:

Π‘ΠΊΡ€ΠΈΠΏΡ‚


add_threat_profile={'name':'Apeiron', "active-protections-performance-impact" : "low","active-protections-severity" : "low or above","confidence-level-medium" : "prevent",
  "confidence-level-high" : "prevent", "threat-emulation" : True,"anti-virus" : True,"anti-bot" : True,"ips" : True,
  "ips-settings" : { "newly-updated-protections" : "staging","exclude-protection-with-performance-impact" : True,"exclude-protection-with-performance-impact-mode" : "High or lower"},
  "overrides" : [ {"protection" : "3Com Network Supervisor Directory Traversal","capture-packets" : True,"action" : "Prevent","track" : "Log"},
                  {"protection" : "7-Zip ARJ Archive Handling Buffer Overflow", "capture-packets" : True,"action" : "Prevent","track" : "Log"} ]}
add_threat_profile_result=api_call('xxx.xxx.xxx.xxx',443,'add-threat-profile',add_threat_profile,sid)
print(json.dumps(add_threat_profile_result))  

10) ΠŸΠΎΠΌΠ΅Π½ΡΡ‚ΡŒ дСйствиС для IPS сигнатуры:

Π‘ΠΊΡ€ΠΈΠΏΡ‚


set_threat_protection={
  "name" : "3Com Network Supervisor Directory Traversal",
  "overrides" : [{ "profile" : "Apeiron","action" : "Detect","track" : "Log","capture-packets" : True},
    { "profile" : "Apeiron", "action" : "Detect", "track" : "Log", "capture-packets" : False} ]}
set_threat_protection_result=api_call('xxx.xxx.xxx.xxx',443,'set-threat-protection',set_threat_protection,sid)
print(json.dumps(set_threat_protection_result))

11) Π”ΠΎΠ±Π°Π²ΠΈΡ‚ΡŒ свой сСрвис:

Π‘ΠΊΡ€ΠΈΠΏΡ‚


add_service_udp={    "name" : "Dota2_udp", "port" : '27000-27030',
"keep-connections-open-after-policy-installation" : False,
"session-timeout" : 0, "match-for-any" : True,
"sync-connections-on-cluster" : True,
"aggressive-aging" : {"enable" : True, "timeout" : 360,"use-default-timeout" : False  },
"accept-replies" : False}
add_service_udp_results=api_call('xxx.xxx.xxx.xxx',443,"add-service-udp",add_service_udp,sid)
print(json.dumps(add_service_udp_results))

12) Π”ΠΎΠ±Π°Π²ΠΈΡ‚ΡŒ ΠΊΠ°Ρ‚Π΅Π³ΠΎΡ€ΠΈΡŽ, сайт ΠΈΠ»ΠΈ Π³Ρ€ΡƒΠΏΠΏΡƒ:

Π‘ΠΊΡ€ΠΈΠΏΡ‚


add_application_site_category={  "name" : "Valve","description" : "Valve Games"}
add_application_site_category_results=api_call('xxx.xxx.xxx.xxx',443,"add-application-site-category",add_application_site_category,sid)
print(json.dumps(add_application_site_category_results))

add_application_site={    "name" : "Dota2", "primary-category" : "Valve",  "description" : "Dotka",
  "url-list" : [ "www.dota2.ru" ], "urls-defined-as-regular-expression" : False}
add_application_site_results=api_call('xxx.xxx.xxx.xxx',443,"add-application-site " , 
add_application_site , sid)
print(json.dumps(add_application_site_results))

add_application_site_group={"name" : "Games","members" : [ "Dota2"]}
add_application_site_group_results=api_call('xxx.xxx.xxx.xxx',443,"add-application-site-group",add_application_site_group,sid)
print(json.dumps(add_application_site_group_results))

ΠšΡ€ΠΎΠΌΠ΅ Ρ‚ΠΎΠ³ΠΎ, с ΠΏΠΎΠΌΠΎΡ‰ΡŒΡŽ Web API Π²Ρ‹ ΠΌΠΎΠΆΠ΅Ρ‚Π΅ Π΄ΠΎΠ±Π°Π²Π»ΡΡ‚ΡŒ ΠΈ ΡƒΠ΄Π°Π»ΡΡ‚ΡŒ сСти, хосты, Ρ€ΠΎΠ»ΠΈ доступа ΠΈ Ρ‚.Π΄. Π•ΡΡ‚ΡŒ Π²ΠΎΠ·ΠΌΠΎΠΆΠ½ΠΎΡΡ‚ΡŒ настройки Π±Π»Π΅ΠΉΠ΄ΠΎΠ² Antivirus, Antibot, IPS, VPN. Π’ΠΎΠ·ΠΌΠΎΠΆΠ½Π° Π΄Π°ΠΆΠ΅ установка Π»ΠΈΡ†Π΅Π½Π·ΠΈΠΉ с ΠΏΠΎΠΌΠΎΡ‰ΡŒΡŽ ΠΊΠΎΠΌΠ°Π½Π΄Ρ‹ run-script. Π‘ΠΎ всСми API-ΠΊΠΎΠΌΠ°Π½Π΄Π°ΠΌΠΈ Check Point ΠΌΠΎΠΆΠ½ΠΎ ΠΎΠ·Π½Π°ΠΊΠΎΠΌΠΈΡ‚ΡŒΡΡ здСсь.

Check Point API + Postman

Π’Π°ΠΊΠΆΠ΅ ΡƒΠ΄ΠΎΠ±Π½ΠΎ ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚ΡŒ Check Point Web API Π² связкС с Postman. Postman ΠΈΠΌΠ΅Π΅Ρ‚ дСсктопныС вСрсии для Windows, Linux ΠΈ MacOS. ΠšΡ€ΠΎΠΌΠ΅ Ρ‚ΠΎΠ³ΠΎ, Π΅ΡΡ‚ΡŒ ΠΏΠ»Π°Π³ΠΈΠ½ для Google Chrome. Им ΠΌΡ‹ ΠΈ Π²ΠΎΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠ΅ΠΌΡΡ. Для Π½Π°Ρ‡Π°Π»Π° Π½Π΅ΠΎΠ±Ρ…ΠΎΠ΄ΠΈΠΌΠΎ Π½Π°ΠΉΡ‚ΠΈ Postman Π² Google Chrome Store ΠΈ ΡƒΡΡ‚Π°Π½ΠΎΠ²ΠΈΡ‚ΡŒ:

Check Point R80.10 API. Π£ΠΏΡ€Π°Π²Π»Π΅Π½ΠΈΠ΅ Ρ‡Π΅Ρ€Π΅Π· CLI, скрипты ΠΈ Π½Π΅ Ρ‚ΠΎΠ»ΡŒΠΊΠΎ

Π‘ ΠΏΠΎΠΌΠΎΡ‰ΡŒΡŽ этой ΡƒΡ‚ΠΈΠ»ΠΈΡ‚Ρ‹ ΠΌΡ‹ смоТСм Ρ„ΠΎΡ€ΠΌΠΈΡ€ΠΎΠ²Π°Ρ‚ΡŒ Web-запросы ΠΊ API Check Point. Π§Ρ‚ΠΎΠ±Ρ‹ Π½Π΅ Π·Π°ΠΏΠΎΠΌΠΈΠ½Π°Ρ‚ΡŒ всС API-ΠΊΠΎΠΌΠ°Π½Π΄Ρ‹, Π΅ΡΡ‚ΡŒ Π²ΠΎΠ·ΠΌΠΎΠΆΠ½ΠΎΡΡ‚ΡŒ ΠΈΠΌΠΏΠΎΡ€Ρ‚ΠΈΡ€ΠΎΠ²Π°Ρ‚ΡŒ Ρ‚Π°ΠΊ Π½Π°Π·Ρ‹Π²Π°Π΅ΠΌΡ‹Π΅ collection-Ρ‹ (ΡˆΠ°Π±Π»ΠΎΠ½Ρ‹), ΠΊΠΎΡ‚ΠΎΡ€Ρ‹Π΅ ΡƒΠΆΠ΅ содСрТат всС Π½Π΅ΠΎΠ±Ρ…ΠΎΠ΄ΠΈΠΌΡ‹Π΅ ΠΊΠΎΠΌΠ°Π½Π΄Ρ‹:

Check Point R80.10 API. Π£ΠΏΡ€Π°Π²Π»Π΅Π½ΠΈΠ΅ Ρ‡Π΅Ρ€Π΅Π· CLI, скрипты ΠΈ Π½Π΅ Ρ‚ΠΎΠ»ΡŒΠΊΠΎ

Π—Π΄Π΅ΡΡŒ Π²Ρ‹ Π½Π°ΠΉΠ΄Π΅Ρ‚Π΅ collection для R80.10. ПослС ΠΈΠΌΠΏΠΎΡ€Ρ‚Π° Π½Π°ΠΌ станут доступны ΡˆΠ°Π±Π»ΠΎΠ½Ρ‹ API-ΠΊΠΎΠΌΠ°Π½Π΄:

Check Point R80.10 API. Π£ΠΏΡ€Π°Π²Π»Π΅Π½ΠΈΠ΅ Ρ‡Π΅Ρ€Π΅Π· CLI, скрипты ΠΈ Π½Π΅ Ρ‚ΠΎΠ»ΡŒΠΊΠΎ

На ΠΌΠΎΠΉ взгляд, это ΠΎΡ‡Π΅Π½ΡŒ ΡƒΠ΄ΠΎΠ±Π½ΠΎ. МоТно вСсьма быстро ΠΏΡ€ΠΈΡΡ‚ΡƒΠΏΠΈΡ‚ΡŒ ΠΊ Ρ€Π°Π·Ρ€Π°Π±ΠΎΡ‚ΠΊΠ΅ ΠΏΡ€ΠΈΠ»ΠΎΠΆΠ΅Π½ΠΈΠΉ с использованиСм Check Point API.

Check Point + Ansible

Π’Π°ΠΊΠΆΠ΅ Ρ…ΠΎΡ‚Π΅Π»ΠΎΡΡŒ Π±Ρ‹ ΠΎΡ‚ΠΌΠ΅Ρ‚ΠΈΡ‚ΡŒ, Ρ‡Ρ‚ΠΎ сущСствуСт Ansible ΠΌΠΎΠ΄ΡƒΠ»ΡŒ для CheckPoint API. ΠœΠΎΠ΄ΡƒΠ»ΡŒ позволяСт ΡƒΠΏΡ€Π°Π²Π»ΡΡ‚ΡŒ конфигурациями, Π½ΠΎ ΠΎΠ½ Π½Π΅ Ρ‚Π°ΠΊ ΡƒΠ΄ΠΎΠ±Π΅Π½ для Ρ€Π΅ΡˆΠ΅Π½ΠΈΡ экзотичСских Π·Π°Π΄Π°Ρ‡. НаписаниС скриптов Π½Π° любом языкС программирования Π΄Π°Π΅Ρ‚ Π±ΠΎΠ»Π΅Π΅ Π³ΠΈΠ±ΠΊΠΈΠ΅ ΠΈ ΡƒΠ΄ΠΎΠ±Π½Ρ‹Π΅ Ρ€Π΅ΡˆΠ΅Π½ΠΈΡ.

Π’Ρ‹Π²ΠΎΠ΄

На этом ΠΏΠΎΠΆΠ°Π»ΡƒΠΉ ΠΌΡ‹ Π·Π°ΠΊΠΎΠ½Ρ‡ΠΈΠΌ наш нСбольшой ΠΎΠ±Π·ΠΎΡ€ Check Point API. На ΠΌΠΎΠΉ взгляд эта функция Π±Ρ‹Π»Π° ΠΎΡ‡Π΅Π½ΡŒ Π΄ΠΎΠ»Π³ΠΎΠΆΠ΄Π°Π½Π½ΠΎΠΉ ΠΈ Π½Π΅ΠΎΠ±Ρ…ΠΎΠ΄ΠΈΠΌΠΎΠΉ. ПоявлСниС API ΠΎΡ‚ΠΊΡ€Ρ‹Π²Π°Π΅Ρ‚ ΠΎΡ‡Π΅Π½ΡŒ ΡˆΠΈΡ€ΠΎΠΊΠΈΠ΅ возмоТности ΠΊΠ°ΠΊ для систСмных администраторов, Ρ‚Π°ΠΊ ΠΈ для систСмных ΠΈΠ½Ρ‚Π΅Π³Ρ€Π°Ρ‚ΠΎΡ€ΠΎΠ², ΠΊΠΎΡ‚ΠΎΡ€Ρ‹Π΅ Ρ€Π°Π±ΠΎΡ‚Π°ΡŽΡ‚ с ΠΏΡ€ΠΎΠ΄ΡƒΠΊΡ‚Π°ΠΌΠΈ Check Point. ΠžΡ€ΠΊΠ΅ΡΡ‚Ρ€Π°Ρ†ΠΈΡ, автоматизация, обратная связь с SIEM… всС это Ρ‚Π΅ΠΏΠ΅Ρ€ΡŒ Π²ΠΎΠ·ΠΌΠΎΠΆΠ½ΠΎ.

P.S. Π‘ΠΎΠ»ΡŒΡˆΠ΅ статСй ΠΎ Check Point Π²Ρ‹ ΠΊΠ°ΠΊ всСгда ΠΌΠΎΠΆΠ΅Ρ‚Π΅ Π½Π°ΠΉΡ‚ΠΈ Π² нашСм Π±Π»ΠΎΠ³Π΅ Π₯Π°Π±Ρ€ ΠΈΠ»ΠΈ Π² Π±Π»ΠΎΠ³Π΅ Π½Π° сайтС.

P.S.S. Π—Π°Π΄Π°Ρ‚ΡŒ тСхничСскиС вопросы, связанныС с настройкой Check Point, ΠΌΠΎΠΆΠ½ΠΎ здСсь

Волько зарСгистрированныС ΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚Π΅Π»ΠΈ ΠΌΠΎΠ³ΡƒΡ‚ ΡƒΡ‡Π°ΡΡ‚Π²ΠΎΠ²Π°Ρ‚ΡŒ Π² опросС. Π’ΠΎΠΉΠ΄ΠΈΡ‚Π΅, поТалуйста.

ΠŸΠ»Π°Π½ΠΈΡ€ΡƒΠ΅Ρ‚Π΅ Π»ΠΈ Π²Ρ‹ ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚ΡŒ API?

  • 70,6%Π”Π°12

  • 23,5%НСт4

  • 5,9%Π£ΠΆΠ΅ ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΡŽ1

ΠŸΡ€ΠΎΠ³ΠΎΠ»ΠΎΡΠΎΠ²Π°Π»ΠΈ 17 ΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚Π΅Π»Π΅ΠΉ. Π’ΠΎΠ·Π΄Π΅Ρ€ΠΆΠ°Π»ΠΈΡΡŒ 3 ΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚Π΅Π»Ρ.

Π˜ΡΡ‚ΠΎΡ‡Π½ΠΈΠΊ: habr.com