from multiprocessing import process import subprocess import os import sys import tkinter as tk from tkinter import ttk, filedialog, messagebox from datetime import datetime from threading import Thread 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( "", 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("", on_configure) canvas.configure(yscrollcommand=scrollbar.set) canvas.pack(side="left", fill="both", expand=True) scrollbar.pack(side="right", fill="y") canvas.bind_all("", lambda e: canvas.yview_scroll(int(-1*(e.delta/120)), "units")) return scrollable_frame class ToolTip: def __init__(self, widget, text): self.widget = widget self.text = text self.tipwindow = None widget.bind("", self.show) widget.bind("", 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 # 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") app2.geometry("800x450") app2.resizable(True, True) matrice_flux = tk.BooleanVar() matrice_routage = tk.BooleanVar() 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") cmd.append("-o") if item["type"] == "file": base_name = os.path.splitext(item["name"])[0] cmd.append(base_name) else: cmd.append(item["name"]) 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 ).pack(anchor="w", padx=10, pady=(0, 10)) matrice_routage.set(True) 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() # Contenu fenêtre Analyse Firewall def open_firewall_gui(root, BASE_DIR): FIREWALL_DIR = os.path.join( BASE_DIR, "Parseurs_config_Firewall" ) FIREWALL_MAIN = os.path.join( FIREWALL_DIR, "src", "main.py" ) 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) app = tk.Toplevel(root) app.title("Analyse Configuration Firewall") app.geometry("800x450") app.resizable(True, True) firewall_var = tk.StringVar() input_var = tk.StringVar() output_var = tk.StringVar() matrice_flux = tk.BooleanVar() matrice_routage = tk.BooleanVar() 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") 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") else: dt = datetime.now().strftime("%Y%m%d") f_json = os.path.join(OUTPUT_DIR, f"{fw}_{dt}.json") 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") if not matrice_flux.get(): if not matrice_routage.get(): output_label_var.set("Fichier de sortie :\n" + f_json) else: output_label_var.set("Fichiers de sortie :\n" + f_json + "\n" + f_routage) else: if not matrice_routage.get(): output_label_var.set("Fichiers de sortie :\n" + f_json + "\n" + f_flux) else: output_label_var.set("Fichiers de sortie :\n" + f_json + "\n" + f_flux + "\n" + f_routage) 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 = [ sys.executable, FIREWALL_MAIN, firewall_var.get(), input_var.get() ] if output_var.get(): cmd.extend(["-o", output_var.get()]) if matrice_flux.get(): cmd.append("-f") if matrice_routage.get(): cmd.append("-r") 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") 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) 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", 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 ).pack(anchor="w", padx=10, pady=(0, 10)) matrice_routage.set(True) 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) matrice_flux.trace_add("write", update_output_label) matrice_routage.trace_add("write", update_output_label) 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) app.mainloop()