본문 바로가기
Python

Fortigate 방화벽 Hit Count 수집 (export 안되는 버전 전용) (수정1)

by Ao1 2022. 8. 19.

설치할 모듈: paramiko,pandas,openpyxl

firewall_hitcount.py
0.01MB

 

#-------------------------------------------#
#-------------------------------------------#
#                                           #
#        Fortigate hit count                #
#          Version 1.1.0                    #
#         Make Jo Sung Jin                  #
#                                           #
#-------------------------------------------#
import os
import sys

sys.path.append(os.getcwd() + "\lib")

import paramiko
import time
import argparse
import csv
import pandas as pd
from io import StringIO

parser = argparse.ArgumentParser(description='FireWall Hitcount')

# 입력받을 인자값 등록
parser.add_argument('-ti', metavar='[tacas_id]', required=True, help='TACAS ID', type=str)
parser.add_argument('-tp', metavar='[tacas_pw]', required=True, help='TACAS PW', type=str)
parser.add_argument('-p', metavar='[list_file_path]', required=True, help='List File path', type=str)
parser.add_argument('-i', metavar='[file_path]', required=True, help='File path', type=str)
parser.add_argument('-c', metavar='Command Choice', required=False, help='cmd=no vdom, su_cmd=vdom', type=str, default='cmd')

# 입력받은 인자값을 args에 저장 (type: namespace)
args = parser.parse_args()

ID = args.ti            # TACAS ID
PASSWD = args.tp        # TACAS PASSWORD

LIST_FILE_NAME = args.p         # xlsx file Name exe) Test.xlsx
FILE_NAME= args.i               # CSV flie Name exe) Test.csv

Command = args.c                # Command Choice

cmd = 'diagnose firewall iprope show 100004 '
su_cmd = 'diagnose firewall iprope show 100004 '

# SSH 연결
def ssh_connect(HOST,HOSTNAME,com,*po_id):
    ssh = paramiko.SSHClient()
    ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
    
    try:
        ssh.connect(HOST, username=ID, password=PASSWD,allow_agent=False,look_for_keys=False)
        shell = ssh.invoke_shell()

        if 'su_cmd' == Command:
            shell.send('config vdom\n')
            time.sleep(1)
            shell.send('edit root\n')
            time.sleep(1)
        
        for i in range(0,len(po_id)):
            shell.send(com + po_id[i] +'\n')
            time.sleep(1)
            print(str(i) + '/' + str(len(po_id)-1) + ' Policy extraction complete')

        print('ALL Policy extraction complete')
                   
        time.sleep(2)
        ssh.close()
        output = shell.recv(2097152)

        str_output = str(output)
        final_output = str_output.split('\\r\\n')
        ssh_log = ssh_log_gen(*final_output)
        create_csv(modfy(ssh_log),HOSTNAME)
        print('END')
        
    except Exception as e:
        print(e)
        error_log(HOST,HOSTNAME)
    except EOFError:
        pass
    
# SSH 로그값 가공
def ssh_log_gen(*Str):
    io = StringIO()
    print(*Str, file=io, sep='\n')
    return io.getvalue()

# 에러 시 로그
def error_log(host,hostname):
    f_err = open(PATH + '/error.log','a')
    f_err.write(hostname + '( ' + host + ')' + '\n')

# xlsx 시트 추가 (값byte,hit count)
def create_csv(args,HOSTNAME):
    print('create_csv: ' + str(len(args)-1))
    
    for i in range(0,len(args)+1):
        if i == 0:
            r[i].insert(1,'FirstUsed')
            r[i].insert(2,'LastUsed')
            r[i].insert(3,'Bytes')
            r[i].insert(4,'Hit count')
        else:
            r[i].insert(1,args[i-1][0])
            r[i].insert(2,args[i-1][1])
            r[i].insert(3,args[i-1][2])
            r[i].insert(4,args[i-1][3])


    fn = open(PATH + '\\' + HOSTNAME + '.csv','w', newline='', encoding='utf-8-sig')
    wr = csv.writer(fn)
    for x in range(0,len(r)):
        wr.writerow(r[x])
    fn.close()
    
# 디렉토리 생성
def createDir(DIR):
    if not os.path.exists(DIR):
        os.makedirs(DIR)
        
# 단위 변환기
def conversion(byte):
    global conversion_byte
    
    conversion_byte = []
    
    for i in range(0,len(byte)):
        if float(byte[i]) < 1000:
            conversion_byte.append(byte[i]+'B')
            continue
        
        if float(byte[i]) // float(1000) < 1000:
            kB = float(byte[i]) / float(1000)
            conversion_byte.append('%0.2f' % kB +'KB')
            continue

        if float(byte[i]) // float(1000000) < 1000:
            MB = float(byte[i]) / float(1000000)
            conversion_byte.append('%0.2f' % MB +'MB')
            continue
        
        if float(byte[i]) // float(1000000000) < 1000:
            GB = float(byte[i]) / float(1000000000)
            conversion_byte.append('%0.2f' % GB +'GB')
            continue

        if float(byte[i]) // float(1000000000000) < 1000:
            TB = float(byte[i]) / float(1000000000000)
            conversion_byte.append('%0.2f' % TB +'TB')
            continue

        if float(byte[i]) // float(1000000000000000) < 1000:
            PB = float(byte[i]) / float(1000000000000000)
            conversion_byte.append('%0.2f' % PB +'PB')
            continue
        
    return conversion_byte
    
# byte,hot count 도출
def modfy(args_1):
    args_byte = []
    args_hit = []
    args_first = []
    args_last = []
    

    value_byte_1 = []
    value_hit_1 = []
    value_first_1 = []
    value_last_1 = []
    
    count = 0

    args_2 = args_1.replace(' ',',')
    args_3 = args_2.split(',')

    # 문자열 일치 배열 생성
    index_First = [i for i in range(len(args_3)) if 'first:' in args_3[i]]
    index_Last = [i for i in range(len(args_3)) if 'last:' in args_3[i]]
    index_byte = [i for i in range(len(args_3)) if 'pkts/bytes' in args_3[i]]
    index_hit = [i for i in range(len(args_3)) if 'hit' in args_3[i]]

    args = [[0 for i in range(4)] for j in range(len(index_byte))]


    # byte 가공 배열 생성
    for a in range(0,len(index_byte)):
        args_byte.append(args_3[index_byte[a]])

    # Hit count 가공 배열 생성
    for b in range(0,len(index_hit)):
        args_hit.append(args_3[index_hit[b]+1])

    print('hit count Check Complete')

    # FirstUsed 가공 배열 생성
    for c in range(0,len(index_First)):
        args_first_sub = args_3[index_First[c]],args_3[index_First[c]+1]
        args_first_act = ' '.join(args_first_sub)
        args_first.append(args_first_act)

    print('FirstUsed Check Complete')

    # LastUsed 가공 배열 생성
    for d in range(0,len(index_Last)):
        args_last_sub = args_3[index_Last[d]],args_3[index_Last[d]+1]
        args_last_act = ' '.join(args_last_sub)
        args_last.append(args_last_act)

    print('LastUsed Check Complete')
        
    # byte 값만 추출하는 배열 생성  
    for i in range(0,len(args_byte)):
        value_byte = args_byte[i]
        
        byte_cut_num = value_byte.rfind('/')
        value_byte_1.append(value_byte[byte_cut_num+1:])


    print('byte Check Complete')

    
    # byte 단위변환기 호출
    conversion(value_byte_1)
    
    print('byte Conversion Complete')
    
    # 2차원 배열 args에 값 저장
    print('modfy: ' + str(len(args_byte)-1))
    
    for j in range(0,len(args_byte)):
        args[j][2] = conversion_byte[j]
            
        if value_byte_1[j] != '0':

            value_first = args_first[count]
            value_last = args_last[count]
            value_hit = args_hit[count]

            first_cut_num = value_first.rfind('t')
            value_first_1.append(value_first[first_cut_num+2:])
            args[j][0] = value_first_1[count]
            
            last_cut_num = value_last.rfind('t')
            value_last_1.append(value_last[last_cut_num+2:24])
            args[j][1] = value_last_1[count]

            hit_cut_num = value_hit.rfind(':')
            value_hit_1.append(value_hit[hit_cut_num+1:-1])    
            args[j][3] = value_hit_1[count]
            
            count += 1
        else:
            args[j][0] = ''
            args[j][1] = ''
            args[j][3] = ''
            
        print(str(j) + ' Processed')

    print('modfy Complete')

    return args

# 메인 엔진
def file_read(LIST_FILE,FILE):
    global r
    global LIST_HOSTNAME
    global LIST_HOST
    global PATH
    
    line_count = []

    f_xlsx = pd.read_excel(LIST_FILE, engine = "openpyxl", sheet_name=0)
    LIST_HOSTNAME = f_xlsx['hostname']
    LIST_HOST = f_xlsx['ip']

    f = open(FILE,'rt',encoding='utf-8')
    rdr = csv.reader(f)
    r = list(rdr)
    f.close()

    PATH = './HIT_CSV'
    createDir(PATH)

    for i in range(0,len(r)):
        if i == 0:
            pass
        else:
            line_count.append(r[i][0])
    
    f_csv_name = os.path.basename(FILE)
    F_NAME, f_ext = os.path.splitext(f_csv_name)

    for i in range(0,len(LIST_HOSTNAME)):
        if F_NAME == LIST_HOSTNAME[i]:
            if Command == 'cmd':
                ssh_connect(LIST_HOST[i],LIST_HOSTNAME[i],cmd,*line_count)
            elif Command == 'su_cmd':
                ssh_connect(LIST_HOST[i],LIST_HOSTNAME[i],su_cmd,*line_count)
            
file_read(LIST_FILE_NAME,FILE_NAME)