diff --git a/Parseurs_config_Firewall/src/scripts/objets/__pycache__/data.cpython-312.pyc b/Parseurs_config_Firewall/src/scripts/objets/__pycache__/data.cpython-312.pyc new file mode 100644 index 0000000..14691de Binary files /dev/null and b/Parseurs_config_Firewall/src/scripts/objets/__pycache__/data.cpython-312.pyc differ diff --git a/gui_firewall.py b/gui_firewall.py index d8eb0e6..505520b 100644 --- a/gui_firewall.py +++ b/gui_firewall.py @@ -1,3 +1,4 @@ +from multiprocessing import process import subprocess import os import sys @@ -5,6 +6,32 @@ 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): @@ -44,6 +71,326 @@ class ToolTip: 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(False, False) + + 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") + + 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( @@ -64,7 +411,7 @@ def open_firewall_gui(root, BASE_DIR): app = tk.Toplevel(root) app.title("Analyse Configuration Firewall") - app.geometry("800x400") + app.geometry("800x450") app.resizable(False, False) firewall_var = tk.StringVar() @@ -218,6 +565,13 @@ def open_firewall_gui(root, BASE_DIR): 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,