2026-01-15 09:37:42 +01:00
from multiprocessing import process
2026-01-14 14:15:06 +01:00
import subprocess
import os
import sys
2026-01-08 13:51:16 +01:00
import tkinter as tk
from tkinter import ttk , filedialog , messagebox
from datetime import datetime
from threading import Thread
2026-01-15 09:37:42 +01:00
from pathlib import Path
def make_scrollable ( parent ) :
canvas = tk . Canvas ( parent , highlightthickness = 0 )
scrollbar = ttk . Scrollbar ( parent , orient = " vertical " , command = canvas . yview )
scrollable_frame = ttk . Frame ( canvas )
scrollable_frame . bind (
" <Configure> " ,
lambda e : canvas . configure ( scrollregion = canvas . bbox ( " all " ) )
)
canvas . create_window ( ( 0 , 0 ) , window = scrollable_frame , anchor = " nw " )
def on_configure ( event ) :
canvas . itemconfig ( " frame " , width = canvas . winfo_width ( ) )
canvas . create_window ( ( 0 , 0 ) , window = scrollable_frame , anchor = " nw " , tags = " frame " )
canvas . bind ( " <Configure> " , on_configure )
canvas . configure ( yscrollcommand = scrollbar . set )
canvas . pack ( side = " left " , fill = " both " , expand = True )
scrollbar . pack ( side = " right " , fill = " y " )
canvas . bind_all ( " <MouseWheel> " , lambda e : canvas . yview_scroll ( int ( - 1 * ( e . delta / 120 ) ) , " units " ) )
return scrollable_frame
2026-01-08 13:51:16 +01:00
class ToolTip :
def __init__ ( self , widget , text ) :
self . widget = widget
self . text = text
self . tipwindow = None
widget . bind ( " <Enter> " , self . show )
widget . bind ( " <Leave> " , self . hide )
def show ( self , event = None ) :
if self . tipwindow or not self . text :
return
x = self . widget . winfo_rootx ( ) + 20
y = self . widget . winfo_rooty ( ) + 20
self . tipwindow = tw = tk . Toplevel ( self . widget )
tw . wm_overrideredirect ( True )
tw . wm_geometry ( f " + { x } + { y } " )
label = tk . Label (
tw ,
text = self . text ,
justify = " left " ,
background = " #ffffe0 " ,
relief = " solid " ,
borderwidth = 1 ,
font = ( " Arial " , 9 ) ,
padx = 8 ,
pady = 4
)
label . pack ( )
def hide ( self , event = None ) :
if self . tipwindow :
self . tipwindow . destroy ( )
self . tipwindow = None
2026-01-15 09:37:42 +01:00
# Contenu fenêtre Analyse Firewall Multi
def open_firewall_gui_multi ( app , OUTPUT_DIR , HELP_FILE_FW , FIREWALL_DIR , FIREWALL_MAIN ) :
app2 = tk . Toplevel ( app )
app2 . title ( " Analyse Configuration Firewall - Plusieurs firewall " )
2026-06-01 09:51:24 +02:00
app2 . geometry ( " 800x500 " )
2026-01-15 11:37:51 +01:00
app2 . resizable ( True , True )
2026-01-15 09:37:42 +01:00
matrice_flux = tk . BooleanVar ( )
matrice_routage = tk . BooleanVar ( )
2026-06-01 09:51:24 +02:00
interfaces = tk . BooleanVar ( )
2026-01-15 09:37:42 +01:00
content = make_scrollable ( app2 )
def open_output_folder ( ) :
if sys . platform == " win32 " :
os . startfile ( OUTPUT_DIR )
elif sys . platform == " darwin " :
subprocess . run ( [ " open " , OUTPUT_DIR ] )
else :
subprocess . run ( [ " xdg-open " , OUTPUT_DIR ] )
def open_help ( ) :
if not os . path . exists ( HELP_FILE_FW ) :
messagebox . showerror ( " Erreur " , " Le fichier d ' aide est introuvable. " )
return
if sys . platform == " win32 " :
os . startfile ( HELP_FILE_FW )
elif sys . platform == " darwin " :
subprocess . run ( [ " open " , HELP_FILE_FW ] )
else :
subprocess . run ( [ " xdg-open " , HELP_FILE_FW ] )
def get_selected_firewall ( vars_dict ) :
for fw , var in vars_dict . items ( ) :
if var . get ( ) :
return fw
return None
def run_parser_multi ( ) :
selections = [ ]
for name , vars_dict in file_selections . items ( ) :
fw = get_selected_firewall ( vars_dict )
if fw :
selections . append ( {
" type " : " file " ,
" name " : name ,
" firewall " : fw
} )
for name , vars_dict in dir_selections . items ( ) :
fw = get_selected_firewall ( vars_dict )
if fw :
selections . append ( {
" type " : " dir " ,
" name " : name ,
" firewall " : fw
} )
if not selections :
messagebox . showwarning (
" Aucune sélection " ,
" Veuillez sélectionner au moins un fichier ou dossier. "
)
return
content . config ( cursor = " watch " )
progress_bar = ttk . Progressbar ( content , mode = " indeterminate " )
progress_bar . pack ( pady = 10 , fill = " x " , padx = 10 )
progress_bar . start ( 10 )
def process ( ) :
try :
for item in selections :
input_path = str ( INPUT_DIR / item [ " name " ] )
cmd = [
sys . executable ,
FIREWALL_MAIN ,
item [ " firewall " ] ,
input_path
]
if matrice_flux . get ( ) :
cmd . append ( " -f " )
if matrice_routage . get ( ) :
cmd . append ( " -r " )
2026-06-01 09:51:24 +02:00
if interfaces . get ( ) :
cmd . append ( " -i " )
2026-01-15 09:37:42 +01:00
2026-01-15 11:37:51 +01:00
cmd . append ( " -o " )
if item [ " type " ] == " file " :
base_name = os . path . splitext ( item [ " name " ] ) [ 0 ]
cmd . append ( base_name )
else :
cmd . append ( item [ " name " ] )
2026-01-15 09:37:42 +01:00
print ( " Commande exécutée : " , " " . join ( cmd ) )
subprocess . run ( cmd , cwd = FIREWALL_DIR , check = True )
def on_success ( ) :
progress_bar . stop ( )
progress_bar . destroy ( )
content . config ( cursor = " " )
messagebox . showinfo ( " Succès " , " Tous les traitements sont terminés. " )
open_output_folder ( )
app2 . destroy ( )
app2 . after ( 0 , on_success )
except subprocess . CalledProcessError as e :
def on_error ( ) :
progress_bar . stop ( )
progress_bar . destroy ( )
content . config ( cursor = " " )
messagebox . showerror (
" Erreur " ,
f " Erreur lors de l ' exécution du traitement. \n \n { e } "
)
app2 . after ( 0 , on_error )
Thread ( target = process , daemon = True ) . start ( )
def create_table ( parent , title , items , mode ) :
"""
mode = ' file ' or ' dir '
"""
style = ttk . Style ( )
style . configure (
" Table.TFrame " ,
background = " white " ,
borderwidth = 1 ,
relief = " solid "
)
style . configure (
" Table.TLabel " ,
background = " white "
)
style . configure (
" Table.TCheckbutton " ,
background = " white "
)
style . map (
" Table.TCheckbutton " ,
background = [ ( " disabled " , " #f0f0f0 " ) ] ,
foreground = [ ( " disabled " , " #a0a0a0 " ) ]
)
ttk . Label (
parent ,
text = title ,
font = ( " Arial " , 10 , " bold " )
) . pack ( anchor = " w " , padx = 10 , pady = ( 0 , 4 ) )
table = ttk . Frame ( parent , style = " Table.TFrame " )
table . pack ( fill = " x " , padx = 10 )
table . columnconfigure ( 0 , weight = 1 )
if mode == " file " : n = " Fichier source "
else : n = " Dossier source "
headers = [ n , " Stormshield " , " Palo-Alto " , " Forcepoint " ]
for col , text in enumerate ( headers ) :
ttk . Label (
table ,
text = text ,
style = " Table.TLabel " ,
font = ( " Arial " , 9 , " bold " )
) . grid ( row = 0 , column = col , padx = 8 , pady = 6 , sticky = " e " if col > 0 else " w " )
ttk . Separator ( table , orient = " horizontal " ) . grid (
row = 1 , column = 0 , columnspan = 4 , sticky = " ew " , pady = ( 0 , 2 )
)
selections = { }
grid_row = 2
for name in items :
ttk . Label (
table ,
text = name ,
style = " Table.TLabel "
) . grid ( row = grid_row , column = 0 , sticky = " w " , padx = 8 , pady = 4 )
var_storm = tk . BooleanVar ( )
var_palo = tk . BooleanVar ( )
var_force = tk . BooleanVar ( )
def make_command ( active , others ) :
def cmd ( ) :
if active . get ( ) :
for var in others :
var . set ( False )
return cmd
cb_storm = ttk . Checkbutton (
table ,
variable = var_storm ,
style = " Table.TCheckbutton " ,
command = make_command ( var_storm , [ var_palo , var_force ] )
)
cb_palo = ttk . Checkbutton (
table ,
variable = var_palo ,
style = " Table.TCheckbutton " ,
command = make_command ( var_palo , [ var_storm , var_force ] )
)
cb_force = ttk . Checkbutton (
table ,
variable = var_force ,
style = " Table.TCheckbutton " ,
command = make_command ( var_force , [ var_storm , var_palo ] )
)
cb_storm . grid ( row = grid_row , column = 1 , sticky = " n " , padx = 8 )
cb_palo . grid ( row = grid_row , column = 2 , sticky = " n " , padx = 8 )
cb_force . grid ( row = grid_row , column = 3 , sticky = " n " , padx = 8 )
if mode == " file " :
cb_storm . state ( [ " disabled " ] )
elif mode == " dir " :
cb_palo . state ( [ " disabled " ] )
cb_force . state ( [ " disabled " ] )
selections [ name ] = {
" stormshield " : var_storm ,
" paloalto " : var_palo ,
" forcepoint " : var_force
}
# Séparateur interligne
ttk . Separator ( table , orient = " horizontal " ) . grid (
row = grid_row + 1 ,
column = 0 ,
columnspan = 4 ,
sticky = " ew "
)
grid_row + = 2
return selections
INPUT_DIR = Path ( OUTPUT_DIR ) . parent / " input "
if not INPUT_DIR . exists ( ) :
messagebox . showerror ( " Erreur " , f " Dossier input introuvable : { INPUT_DIR } " )
return
header_frame = ttk . Frame ( content )
header_frame . pack ( fill = " x " , padx = 10 , pady = 5 )
ttk . Button (
header_frame ,
text = " Help " ,
width = 6 ,
command = open_help
) . pack ( side = " right " )
ttk . Label (
header_frame ,
text = " Génération de fichiers JSON au format normalisé YANG à partir des configurations de plusieurs firewalls " ,
font = ( " Arial " , 8 , " bold " )
) . pack ( side = " left " )
ttk . Label (
content ,
text = " /! \\ Mettre les fichiers/dossiers de configurations dans le dossier `./Parseurs_config_Firewall/src/input/` " ,
font = ( " Arial " , 9 , " italic " ) ,
) . pack ( anchor = " w " , padx = 10 , pady = ( 0 , 10 ) )
ttk . Label (
content ,
text = " Sélectionnez les fichiers ou dossiers de configuration source à traiter : " ,
font = ( " Arial " , 10 )
) . pack ( anchor = " w " , padx = 10 )
files = [ item . name for item in INPUT_DIR . iterdir ( ) if item . is_file ( ) ]
dirs = [ item . name for item in INPUT_DIR . iterdir ( ) if item . is_dir ( ) ]
file_selections = create_table (
content ,
" 🗎 Liste des fichiers de configuration source " ,
files ,
mode = " file "
)
dir_selections = create_table (
content ,
" 🗁 Liste des dossiers de configuration source " ,
dirs ,
mode = " dir "
)
ttk . Checkbutton (
content ,
text = " Générer la matrice de flux en Excel " ,
variable = matrice_flux
) . pack ( anchor = " w " , padx = 10 , pady = ( 10 , 0 ) )
matrice_flux . set ( True )
ttk . Checkbutton (
content ,
text = " Générer la matrice de routage en Excel (route statique uniquement) " ,
variable = matrice_routage
2026-06-01 09:51:24 +02:00
) . pack ( anchor = " w " , padx = 10 , pady = ( 0 , 0 ) )
2026-01-15 09:37:42 +01:00
matrice_routage . set ( True )
2026-06-01 09:51:24 +02:00
ttk . Checkbutton (
content ,
text = " Générer la configuration des interfaces en Excel " ,
variable = interfaces
) . pack ( anchor = " w " , padx = 10 , pady = ( 0 , 10 ) )
interfaces . set ( True )
2026-01-15 09:37:42 +01:00
ttk . Label (
content ,
text = " Dossier de sortie : " ,
) . pack ( anchor = " w " , padx = 10 )
ttk . Button (
content ,
text = " Ouvrir le dossier de sortie " ,
command = open_output_folder
) . pack ( anchor = " w " , padx = 10 )
ttk . Button (
content ,
text = " Lancer le traitement " ,
command = run_parser_multi
) . pack ( pady = 15 )
content . mainloop ( )
2026-01-14 14:15:06 +01:00
# Contenu fenêtre Analyse Firewall
def open_firewall_gui ( root , BASE_DIR ) :
FIREWALL_DIR = os . path . join (
BASE_DIR ,
" Parseurs_config_Firewall "
)
2026-01-08 13:51:16 +01:00
2026-01-14 14:15:06 +01:00
FIREWALL_MAIN = os . path . join (
FIREWALL_DIR ,
" src " ,
" main.py "
2026-01-08 13:51:16 +01:00
)
2026-01-14 14:15:06 +01:00
HELP_FILE_FW = os . path . join ( BASE_DIR , " help_Firewall.md " )
OUTPUT_DIR = os . path . join ( FIREWALL_DIR , " src " , " output " )
os . makedirs ( OUTPUT_DIR , exist_ok = True )
2026-01-08 13:51:16 +01:00
app = tk . Toplevel ( root )
app . title ( " Analyse Configuration Firewall " )
2026-06-01 09:51:24 +02:00
app . geometry ( " 800x500 " )
2026-01-15 11:37:51 +01:00
app . resizable ( True , True )
2026-01-08 13:51:16 +01:00
firewall_var = tk . StringVar ( )
input_var = tk . StringVar ( )
output_var = tk . StringVar ( )
2026-01-14 08:52:25 +01:00
matrice_flux = tk . BooleanVar ( )
matrice_routage = tk . BooleanVar ( )
2026-06-01 09:51:24 +02:00
interfaces = tk . BooleanVar ( )
2026-01-08 13:51:16 +01:00
def browse_input ( ) :
fw_type = firewall_var . get ( )
if fw_type == " " :
messagebox . showerror ( " Erreur " , " Veuillez d ' abord sélectionner un type de firewall. " )
return
if fw_type . lower ( ) == " stormshield " :
path = filedialog . askdirectory ( title = " Sélectionnez le dossier d ' entrée " , parent = app )
else :
path = filedialog . askopenfilename ( title = " Sélectionnez le fichier d ' entrée " , parent = app )
if path :
input_var . set ( path )
def update_output_label ( * args ) :
if firewall_var . get ( ) == " " :
output_label_var . set ( " Fichier de sortie : " )
return
else :
fw = firewall_var . get ( ) . lower ( )
if output_var . get ( ) :
f_json = os . path . join ( OUTPUT_DIR , f " { fw } _ { output_var . get ( ) } .json " )
2026-01-14 08:52:25 +01:00
f_flux = os . path . join ( OUTPUT_DIR , f " matrice_flux_ { fw } _ { output_var . get ( ) } .xlsx " )
f_routage = os . path . join ( OUTPUT_DIR , f " matrice_routage_ { fw } _ { output_var . get ( ) } .xlsx " )
2026-06-01 09:51:24 +02:00
f_interfaces = os . path . join ( OUTPUT_DIR , f " interfaces_ { fw } _ { output_var . get ( ) } .xlsx " )
2026-01-08 13:51:16 +01:00
else :
dt = datetime . now ( ) . strftime ( " % Y % m %d " )
f_json = os . path . join ( OUTPUT_DIR , f " { fw } _ { dt } .json " )
2026-01-14 08:52:25 +01:00
f_flux = os . path . join ( OUTPUT_DIR , f " matrice_flux_ { fw } _ { dt } .xlsx " )
f_routage = os . path . join ( OUTPUT_DIR , f " matrice_routage_ { fw } _ { dt } .xlsx " )
2026-06-01 09:51:24 +02:00
f_interfaces = os . path . join ( OUTPUT_DIR , f " interfaces_ { fw } _ { dt } .xlsx " )
2026-01-14 08:52:25 +01:00
2026-06-01 09:51:24 +02:00
output_label_var . set ( " Fichier de sortie : \n " + f_json + ( " \n " + f_flux if matrice_flux . get ( ) else " " ) + ( " \n " + f_routage if matrice_routage . get ( ) else " " ) + ( " \n " + f_interfaces if interfaces . get ( ) else " " ) )
2026-01-08 13:51:16 +01:00
app . update_idletasks ( )
def open_output_folder ( ) :
if sys . platform == " win32 " :
os . startfile ( OUTPUT_DIR )
elif sys . platform == " darwin " :
subprocess . run ( [ " open " , OUTPUT_DIR ] )
else :
subprocess . run ( [ " xdg-open " , OUTPUT_DIR ] )
def open_help ( ) :
if not os . path . exists ( HELP_FILE_FW ) :
messagebox . showerror ( " Erreur " , " Le fichier d ' aide est introuvable. " )
return
if sys . platform == " win32 " :
os . startfile ( HELP_FILE_FW )
elif sys . platform == " darwin " :
subprocess . run ( [ " open " , HELP_FILE_FW ] )
else :
subprocess . run ( [ " xdg-open " , HELP_FILE_FW ] )
def run_parser ( ) :
if not firewall_var . get ( ) :
messagebox . showerror ( " Erreur " , " Veuillez sélectionner un type de firewall. " )
return
if not input_var . get ( ) :
messagebox . showerror ( " Erreur " , " Veuillez sélectionner un fichier ou dossier d ' entrée. " )
return
app . config ( cursor = " watch " )
progress_bar = ttk . Progressbar ( app , mode = " indeterminate " )
progress_bar . pack ( pady = 10 , fill = " x " , padx = 10 )
progress_bar . start ( 10 )
app . update_idletasks ( )
def process ( ) :
cmd = [
2026-01-14 14:15:06 +01:00
sys . executable ,
2026-01-08 13:51:16 +01:00
FIREWALL_MAIN ,
firewall_var . get ( ) ,
input_var . get ( )
]
if output_var . get ( ) :
cmd . extend ( [ " -o " , output_var . get ( ) ] )
2026-01-14 08:52:25 +01:00
if matrice_flux . get ( ) :
cmd . append ( " -f " )
if matrice_routage . get ( ) :
cmd . append ( " -r " )
2026-06-01 09:51:24 +02:00
if interfaces . get ( ) :
cmd . append ( " -i " )
2026-01-08 13:51:16 +01:00
print ( " Commande exécutée : " , " " . join ( cmd ) )
print ( " Dossier courant (cwd) : " , FIREWALL_DIR )
try :
subprocess . run (
cmd ,
cwd = FIREWALL_DIR ,
check = True
)
def on_success ( ) :
progress_bar . stop ( )
progress_bar . destroy ( )
app . config ( cursor = " " )
messagebox . showinfo ( " Succès " , " Traitement terminé avec succès. " )
open_output_folder ( )
app . destroy ( )
app . after ( 0 , on_success )
except subprocess . CalledProcessError as e :
def on_error ( ) :
progress_bar . stop ( )
progress_bar . destroy ( )
app . config ( cursor = " " )
messagebox . showerror (
" Erreur " ,
f " Erreur lors de l ' exécution du traitement. \n \n { e } "
)
app . after ( 0 , on_error )
Thread ( target = process , daemon = True ) . start ( )
header_frame = ttk . Frame ( app )
header_frame . pack ( fill = " x " , padx = 10 , pady = 5 )
ttk . Button (
header_frame ,
text = " Help " ,
width = 6 ,
command = open_help
) . pack ( side = " right " )
ttk . Label (
header_frame ,
text = " Génération d ' un fichier JSON au format normalisé YANG à partir des configurations d ' un firewall " ,
font = ( " Arial " , 8 , " bold " )
) . pack ( side = " left " )
2026-01-15 09:37:42 +01:00
ttk . Button (
app ,
text = " Plusieurs firewall " ,
command = lambda : open_firewall_gui_multi ( app , OUTPUT_DIR , HELP_FILE_FW , FIREWALL_DIR , FIREWALL_MAIN )
) . pack ( anchor = " w " , padx = 10 )
2026-01-08 13:51:16 +01:00
ttk . Label ( app , text = " Type de firewall " ) . pack ( anchor = " w " , padx = 10 , pady = 5 )
ttk . Combobox (
app ,
values = [ " paloalto " , " stormshield " , " forcepoint " ] ,
textvariable = firewall_var ,
state = " readonly "
) . pack ( fill = " x " , padx = 10 )
input_label_var = tk . StringVar ( )
input_label_var . set ( " Fichier ou dossier de configuration source " )
input_label_frame = ttk . Frame ( app )
input_label_frame . pack ( anchor = " w " , padx = 5 , pady = 5 )
info_label = ttk . Label (
input_label_frame ,
text = " ⓘ " ,
cursor = " hand2 "
)
info_label . pack ( side = " right " )
ttk . Label (
input_label_frame ,
textvariable = input_label_var
) . pack ( side = " left " , padx = ( 5 , 0 ) )
ToolTip (
info_label ,
" /! \\ Mettre le fichier/dossier de configurations \n "
" dans le dossier `/Parseurs_config_Firewall/src/input/` /! \\ "
)
def update_input_label ( * args ) :
fw_type = firewall_var . get ( ) . lower ( )
if fw_type == " stormshield " :
input_label_var . set ( " Dossier de configuration source " )
else :
input_label_var . set ( " Fichier de configuration source " )
firewall_var . trace_add ( " write " , update_input_label )
input_frame = ttk . Frame ( app )
input_frame . pack ( fill = " x " , padx = 10 )
ttk . Entry ( input_frame , textvariable = input_var ) . pack ( side = " left " , fill = " x " , expand = True )
ttk . Button ( input_frame , text = " Parcourir " , command = browse_input ) . pack ( side = " right " )
ttk . Label ( app , text = " Nom de sortie (optionnel) " ) . pack ( anchor = " w " , padx = 10 , pady = 5 )
ttk . Entry ( app , textvariable = output_var ) . pack ( fill = " x " , padx = 10 )
ttk . Checkbutton (
app ,
text = " Générer la matrice de flux en Excel " ,
2026-01-14 08:52:25 +01:00
variable = matrice_flux
) . pack ( anchor = " w " , padx = 10 , pady = ( 10 , 0 ) )
matrice_flux . set ( True )
ttk . Checkbutton (
app ,
text = " Générer la matrice de routage en Excel (route statique uniquement) " ,
variable = matrice_routage
2026-06-01 09:51:24 +02:00
) . pack ( anchor = " w " , padx = 10 , pady = ( 0 , 0 ) )
2026-01-14 08:52:25 +01:00
matrice_routage . set ( True )
2026-01-08 13:51:16 +01:00
2026-06-01 09:51:24 +02:00
ttk . Checkbutton (
app ,
text = " Générer la configuration des interfaces en Excel " ,
variable = interfaces
) . pack ( anchor = " w " , padx = 10 , pady = ( 0 , 10 ) )
interfaces . set ( True )
2026-01-08 13:51:16 +01:00
output_label_var = tk . StringVar ( )
ttk . Label ( app , textvariable = output_label_var ) . pack ( anchor = " w " , padx = 10 )
firewall_var . trace_add ( " write " , update_output_label )
output_var . trace_add ( " write " , update_output_label )
2026-01-14 08:52:25 +01:00
matrice_flux . trace_add ( " write " , update_output_label )
matrice_routage . trace_add ( " write " , update_output_label )
2026-06-01 09:51:24 +02:00
interfaces . trace_add ( " write " , update_output_label )
2026-01-08 13:51:16 +01:00
update_output_label ( )
ttk . Button (
app ,
text = " Ouvrir le dossier de sortie " ,
command = open_output_folder
) . pack ( anchor = " w " , padx = 10 )
ttk . Button (
app ,
text = " Lancer le traitement " ,
command = run_parser
) . pack ( pady = 15 )
2026-01-14 14:15:06 +01:00
app . mainloop ( )