Files
Analyse_Reseaux/gui_firewall.py
2026-01-15 11:37:51 +01:00

662 lines
20 KiB
Python

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(
"<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
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
# 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()