Если вы работаете в крупном дата-центре и ваша задача заключается в поддержке межсетевых экранов (Cisco ASA), то вы наверняка сталкивались с огромным количеством строк в их конфигурациях. Эти конфигурации могут включать тысячи объектов и правил доступа (Access Lists).

Для выполнения задач аудита вам иногда нужно найти все правила доступа для определённого сервера, например, с IP-адресом A.B.C.D. В других случаях требуется добавить новое правило доступа, но перед этим необходимо убедиться, что уже существует аналогичное правило. Например, если существует группа клиентов, подключающихся к какому-то серверу, вам нужно найти соответствующее правило и добавить нового клиента в эту группу.

Для решения таких задач существуют коммерческие продукты, такие как Algosec, Tufin и др. Однако несколько Python-скриптов могут выполнить эти задачи не менее эффективно. Далее я покажу примеры таких программ на Python.

Напомню, что Python предустановлен в любой версии Linux и доступен бесплатно.

Я разделил процесс на несколько простых шагов:

  1. Преобразование аксес-листов и сетевых объектов в CSV-файл.

  2. Поиск всех правил, разрешающих доступ от адреса 10.0.3.10 к адресу 5.5.15.100. Для этого необходимо найти все подсети, содержащие данные IP-адреса.

В аксес листе Cisco ASA можно указать IP адреса источника и назначения, но также можно указывать сетевой объект или группу объектов. Группа объектов может включать в себя другие группы объектов. Если выполнить команду show access-list, то увидим расшифровку всех объектов в IP префиксы, что упрощает конвертацию в CSV файл

ciscoasa# show access-list
access-list gl1 line 1 extended permit tcp object-group og1 object-group og12 eq ssh (hitcnt=0) 0xf57a470f
  access-list gl1 line 1 extended permit tcp 10.0.3.0 255.255.255.0 host 10.0.0.3 eq ssh (hitcnt=0) 0x23c38b59
  access-list gl1 line 1 extended permit tcp 10.0.3.0 255.255.255.0 10.0.0.0 255.255.255.0 eq ssh (hitcnt=0) 0x3bc77b3d
  access-list gl1 line 1 extended permit tcp 10.0.41.0 255.255.255.0 host 10.0.0.3 eq ssh (hitcnt=0) 0xed8dff32
  access-list gl1 line 1 extended permit tcp 10.0.41.0 255.255.255.0 10.0.0.0 255.255.255.0 eq ssh (hitcnt=0) 0xcde224d1
access-list gl1 line 2 extended permit tcp host 10.0.0.3 host 100.100.100.1 eq www (hitcnt=0) 0xf80a10d6
access-list gl1 line 3 extended permit tcp object on1 object on2 eq ssh (hitcnt=0) 0x70f8adb4
  access-list gl1 line 3 extended permit tcp host 10.0.0.3 10.0.0.0 255.255.255.0 eq ssh (hitcnt=0) 0x70f8adb4
access-list gl2 line 1 extended permit tcp object-group og1 object-group og12 eq https (hitcnt=0) 0xd0d468b5
  access-list gl2 line 1 extended permit tcp 10.0.3.0 255.255.255.0 host 10.0.0.3 eq https (hitcnt=0) 0xae19c8fe
  access-list gl2 line 1 extended permit tcp 10.0.3.0 255.255.255.0 10.0.0.0 255.255.255.0 eq https (hitcnt=0) 0x93b63bc0
  access-list gl2 line 1 extended permit tcp 10.0.41.0 255.255.255.0 host 10.0.0.3 eq https (hitcnt=0) 0x07c7a712
  access-list gl2 line 1 extended permit tcp 10.0.41.0 255.255.255.0 10.0.0.0 255.255.255.0 eq https (hitcnt=0) 0xa7ced8a9
access-list gl2 line 2 extended permit ip object-group og1 object-group og12 (hitcnt=0) 0x516db3da
  access-list gl2 line 2 extended permit ip 10.0.3.0 255.255.255.0 host 10.0.0.3 (hitcnt=0) 0x258b842a
  access-list gl2 line 2 extended permit ip 10.0.3.0 255.255.255.0 10.0.0.0 255.255.255.0 (hitcnt=0) 0xd82afa19
  access-list gl2 line 2 extended permit ip 10.0.41.0 255.255.255.0 host 10.0.0.3 (hitcnt=0) 0x3d4864ae
  access-list gl2 line 2 extended permit ip 10.0.41.0 255.255.255.0 10.0.0.0 255.255.255.0 (hitcnt=0) 0xf4e436ba
access-list gl2 line 3 extended permit tcp object on1 object on2 eq 121 (hitcnt=0) 0xac470d2c
  access-list gl2 line 3 extended permit tcp host 10.0.0.3 10.0.0.0 255.255.255.0 eq 121 (hitcnt=0) 0xac470d2c
access-list gl2 line 4 extended permit tcp host 10.0.0.3 10.0.0.0 255.255.255.0 eq ssh (hitcnt=0) 0x5ce66931
access-list gl2 line 5 extended permit tcp object on4_16 object on4_8 eq https (hitcnt=0) 0xd1faa964
  access-list gl2 line 5 extended permit tcp 10.0.0.0 255.255.0.0 10.0.0.0 255.0.0.0 eq https (hitcnt=0) 0xd1faa964
access-list gl2 line 6 extended permit tcp object on4_16 object-group og5 eq https (hitcnt=0) 0x99c5cc7d
  access-list gl2 line 6 extended permit tcp 10.0.0.0 255.255.0.0 host 1.1.1.1 eq https (hitcnt=0) 0xe802825a
  access-list gl2 line 6 extended permit tcp 10.0.0.0 255.255.0.0 host 5.5.5.1 eq https (hitcnt=0) 0x80a1e5b3
  access-list gl2 line 6 extended permit tcp 10.0.0.0 255.255.0.0 5.5.15.0 255.255.255.0 eq https (hitcnt=0) 0x25de07fd

далее python преобразует аксес лист в CSV файл:

gl1,1,10.0.3.0,255.255.255.0,10.0.0.3,255.255.255.255,ssh
gl1,1,10.0.3.0,255.255.255.0,10.0.0.0,255.255.255.0,ssh
gl1,1,10.0.41.0,255.255.255.0,10.0.0.3,255.255.255.255,ssh
gl1,1,10.0.41.0,255.255.255.0,10.0.0.0,255.255.255.0,ssh
gl1,2,10.0.0.3,255.255.255.255,100.100.100.1,255.255.255.255,www
gl1,3,10.0.0.3,255.255.255.255,10.0.0.0,255.255.255.0,ssh
gl2,1,10.0.3.0,255.255.255.0,10.0.0.3,255.255.255.255,https
gl2,1,10.0.3.0,255.255.255.0,10.0.0.0,255.255.255.0,https
gl2,1,10.0.41.0,255.255.255.0,10.0.0.3,255.255.255.255,https
gl2,1,10.0.41.0,255.255.255.0,10.0.0.0,255.255.255.0,https
gl2,2,10.0.3.0,255.255.255.0,10.0.0.3,255.255.255.255,ip
gl2,2,10.0.3.0,255.255.255.0,10.0.0.0,255.255.255.0,ip
gl2,2,10.0.41.0,255.255.255.0,10.0.0.3,255.255.255.255,ip
gl2,2,10.0.41.0,255.255.255.0,10.0.0.0,255.255.255.0,ip
gl2,3,10.0.0.3,255.255.255.255,10.0.0.0,255.255.255.0,121
gl2,4,10.0.0.3,255.255.255.255,10.0.0.0,255.255.255.0,ssh
gl2,5,10.0.0.0,255.255.0.0,10.0.0.0,255.0.0.0,https
gl2,6,10.0.0.0,255.255.0.0,1.1.1.1,255.255.255.255,https
gl2,6,10.0.0.0,255.255.0.0,5.5.5.1,255.255.255.255,https
gl2,6,10.0.0.0,255.255.0.0,5.5.15.0,255.255.255.0,https

Обычным текстовым поиском можно найти искомый IP адрес, но нельзя найти все префиксы в которые входит этот IP адрес. Для этой цели есть библиотека ipaddress. Следующий Python скрипт делает этот поиск:

#!/usr/bin/python3
#  usage " python asa_ip_check.py fw_name src_ip dst_ip"

import csv
import ipaddress
import sys
from sys import argv

args = sys.argv
csv_file_src = args[1]+'.csv'    # "
ip_src = args[2]                 # 
ip_dst = args[3]
                                 #app = args[4]

with open(csv_file_src, 'r') as file:           # ip_src
    reader = csv.reader(file, delimiter=",")
    for row in reader:
        if (ipaddress.ip_address(ip_src) in ipaddress.ip_network(f"{row[2]}/{row[3]}", strict=False) and ipaddress.ip_address(ip_dst) in ipaddress.ip_network(f"{row[4]}/{row[5]}", strict=False)):
            print ( ip_src ," and ", ip_dst , ' in ', row)

В какой строке разрешен доступ от адреса 10.0.3.10 к адресу 5.5.15.100 ?

E:\asa_rules_test>python asa_ip_check.py asa 10.0.3.10 5.5.15.100
10.0.3.10  and  5.5.15.100  in  ['gl2', '6', '10.0.0.0', '255.255.0.0', '5.5.15.0', '255.255.255.0', 'https']

далее python преобразующий выход команды show access-list в CSV файл


#!/usr/bin/python3
#  usage " python asa_acl_to_csv.py fw_name " it will open configuration file fw_name.conf

import csv
import sys
from sys import argv

args = sys.argv

# Set the input and output file names
input_file = args[1] + '.conf'                           # asa show access-list to file fw_name.conf
output_file = args[1] + '.csv'                           # address-set  to   fw_name.csv"

# Open the input and output files
with open(input_file, "r") as f, open(output_file, "w", newline="") as out_file:
    reader = csv.reader(f, delimiter=" ")
    writer = csv.writer(out_file)

    add_name = None
    for row in reader: 
        aclname = ''
        aclline = ''
        aclsrc  = ''
        aclspr  = ''
        acldst  = ''
        acldpr  = ''
        aclapp  = ''
        try:
            if ( not ("object" in row) and not ("object-group" in row) and not ("remark" in row) ):
                if ((row[0] == "access-list") and (row[2] == "line") and (row[5] == "permit") ):
                    aclname = row[1]
                    aclline = row[3]
                    if (row[7] == "host"):
                        aclsrc  = row[8]
                        aclspr  = '255.255.255.255'
                        if (row[9] == "host"):
                            acldst  = row[10]
                            acldpr  = '255.255.255.255'
                            aclapp  = row[12]
                        else:
                            acldst  = row[9]
                            acldpr  = row[10]
                            aclapp  = row[12]                            
                    else:
                        aclsrc  = row[7]
                        aclspr  = row[8]
                        if (row[9] == "host"):
                            acldst  = row[10]
                            acldpr  = '255.255.255.255'
                            aclapp  = row[12]     
                        else:
                            acldst  = row[9]
                            acldpr  = row[10]
                            aclapp  = row[12]
                    if (row[6] == "ip"):
                            aclapp  = row[6]                      
                elif ((row[2] == "access-list") and (row[4] == "line") and (row[7] == "permit") ):
                    aclname = row[3]
                    aclline = row[5]     
                    if (row[9] == "host"):
                        aclsrc  = row[10]
                        aclspr  = '255.255.255.255'
                        if (row[11] == "host"):
                            acldst  = row[12]
                            acldpr  = '255.255.255.255'
     
                        else:
                            acldst  = row[11]
                            acldpr  = row[12]
                            aclapp  = row[14]                            
                    else:
                        aclsrc  = row[9]
                        aclspr  = row[10]
                        if (row[11] == "host"):
                            acldst  = row[12]
                            acldpr  = '255.255.255.255'
                            aclapp  = row[14]     
                        else:
                            acldst  = row[11]
                            acldpr  = row[12]                        
                            aclapp  = row[14]
                    if (row[8] == "ip"):
                            aclapp  = row[8]                                                    
                print(aclname,aclline,aclsrc,aclspr,acldst,acldpr,aclapp)
                writer.writerow([aclname,aclline,aclsrc,aclspr,acldst,acldpr,aclapp]) 
        except:
            print(row)
out_file.close()

Комментарии (0)