ajout doc + correction

This commit is contained in:
Chevallier
2026-06-01 09:51:24 +02:00
parent 2a357d4d90
commit ee160fc06c
17 changed files with 684 additions and 60 deletions

119
CREATE_FIREWALL_TOOL.md Normal file
View File

@@ -0,0 +1,119 @@
# Guide de Développement : Créer son propre outil Firewall
Ce guide explique comment étendre l'outil d'analyse réseau en ajoutant un nouveau outil pour les firewalls.
> **Note :** Tout au long de ce guide, remplacez **`OUTIL`** (en majuscule ou minuscule) par le nom de l'outil que vous souhaitez développer'.
---
## Étape 1 : Création du script de l'outil
Dans le dossier `Parseurs_config_Firewall/src/scripts/` (ou `script/` selon votre arborescence), créez un nouveau fichier Python nommé **`export_OUTIL.py`**.
*Il est fortement recommandé de s'inspirer des parseurs existants comme `export_matrice_routage.py`, `export_matrice_flux.py` ou `export_interfaces.py`.*
Voici le squelette de code à utiliser :
```python
def export_to_excel(json_file_path, output_file_excel):
"""
Export firewall data from JSON to Excel
Args:
json_file_path: Path to the JSON file to process
output_file_excel: Path to the output Excel file
"""
# Votre code
```
## Étape 2 : Intégration dans le moteur principal (`main.py`)
Pour que le script global prenne en charge le nouveau modèle, ouvrez le fichier `Parseurs_config_Firewall/src/main.py` :
1. Importez votre nouvelle fonction en haut du fichier :
```python
from scripts.export_OUTIL import export_to_excel as export_OUTIL_to_excel
```
2. Ajoutez la condition correspondante dans le bloc de sélection de l'outil :
```python
if "-X" in sys.argv:
print(f"\nGénération de l'export les OUTIL...")
if "-o" in sys.argv:
o_index = sys.argv.index("-o")
if o_index + 1 < len(sys.argv):
output_file_excel = os.path.join(f"{output_path}OUTIL_{firewall_type}_{sys.argv[o_index + 1]}.xlsx")
else:
print("Erreur: nom de fichier de sortie manquant après '-o'.")
sys.exit(1)
else:
timestamp = time.strftime("%Y%m%d")
output_file_excel = f"{output_path}OUTIL_{firewall_type}_{timestamp}.xlsx"
output_file_excel = verify_if_file_exists(output_file_excel)
excel_file = export_OUTIL_to_excel(output_file_json, output_file_excel)
print(f"✓ Processus terminé. Fichiers générés:\n - JSON: {output_file_json}\n - Excel: {excel_file}")
```
> **Note :** Remplacez **`X`** de la première ligne par la lettre souhaitez (en dehors de celles déjà existante [o,f,r,i])'.
3. Mettez à jour les instructions textuelles d'usage affichées dans la console si le paramètre saisi est incorrect afin d'inclure `"OUTIL"` dans la liste des choix valides.
```python
print(" -X Generate OUTIL report (optional)")
```
> **Note :** Remplacez **`X`** par la lettre précédemmment choisi'.
## Étape 3 : Adaptation de l'Interface Graphique (GUI)
Afin que le nouveau modèle apparaisse dans l'interface graphique unifiée :
1. Ouvrez le fichier de gestion de la GUI (`gui_firewall.py` racine ou script GUI dédié).
2. Dans la fonction `open_firewall_gui_multi` :
- Ajouter la variable :
```python
OUTIL = tk.BooleanVar()
```
- Dans la fonction `process()`, ajouter :
```python
if OUTIL.get():
cmd.append("-X")
```
- Ajouter égalemment dans la fonction `open_firewall_gui_multi`, le bouton de sélection de l'outil avec les autres existant :
```python
ttk.Checkbutton(
content,
text="Description courte de l'outil",
variable=OUTIL
).pack(anchor="w", padx=10, pady=(0, 0))
OUTIL.set(True)
```
3. Dans la fonction `open_firewall_gui` :
- Répéter les mêmes opérations que pour `open_firewall_gui_multi`
- Dans la fonction `update_output_label(*args)` ajouter et modifier les éléments suivants :
```python
def update_output_label(*args):
...
if output_var.get(): #ligne déjà existante
f_OUTIL = os.path.join(OUTPUT_DIR, f"OUTIL_{fw}_{output_var.get()}.xlsx")
...
else :
f_OUTIL = os.path.join(OUTPUT_DIR, f"OUTIL_{fw}_{dt}.xlsx")
...
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 "") + ("\n" + f_OUTIL if OUTIL.get() else "")) #ligne déjà existante a modifier
```
- Ajouter vers la fin de la fonction `open_firewall_gui` avec les autres existant :
```python
OUTIL.trace_add("write", update_output_label)
```
4. Ouvrez le fichier de gestion principale de la GUI (`main.py` racine ou script GUI dédié).
- Dans la fonction `open_main_gui()` ajouter dans le Label du Firewall :
```python
"\n + possibilité de générer un rapport des OUTIL",
```

View File

@@ -404,7 +404,7 @@ Pour que le script global prenne en charge le nouveau modèle, ouvrez le fichier
import scripts.json_modele as json_modele
```
2. Ajoutez la condition correspondante dans le bloc de sélection du type de firewall :
2. Ajoutez la condition correspondante dans le bloc de sélection du type de switch :
```python
elif switch_type == "modele":
json_modele.generate_json_modele(input_data, output_file1_json, output_file2_json)

119
CREATE_SWITCH_TOOL.md Normal file
View File

@@ -0,0 +1,119 @@
# Guide de Développement : Créer son propre outil Switch
Ce guide explique comment étendre l'outil d'analyse réseau en ajoutant un nouveau outil pour les switches.
> **Note :** Tout au long de ce guide, remplacez **`OUTIL`** (en majuscule ou minuscule) par le nom de l'outil que vous souhaitez développer'.
---
## Étape 1 : Création du script de l'outil
Dans le dossier `Parseurs_logs_Switch/src/scripts/` (ou `script/` selon votre arborescence), créez un nouveau fichier Python nommé **`export_OUTIL.py`**.
*Il est fortement recommandé de s'inspirer des parseurs existants comme `export_rapport_stack.py`, `export_rapport_interfaces.py`, `export_rapport_uplink.py` ou `export_schema_infra.py`.*
Voici le squelette de code à utiliser :
```python
def main(output_dir, output_file)
"""
Export switch data from JSON to Excel
Args:
json_file_path: Path to the JSON file to process
output_file: Path to the output Excel file
"""
# Votre code
```
## Étape 2 : Intégration dans le moteur principal (`main.py`)
Pour que le script global prenne en charge le nouveau modèle, ouvrez le fichier `Parseurs_logs_Switch/src/main.py` :
1. Importez votre nouvelle fonction en haut du fichier :
```python
from scripts.export_OUTIL import main as rapport_OUTIL
```
2. Ajoutez la condition correspondante dans le bloc de sélection de l'outil :
```python
if "-X" in sys.argv:
print(f"\nGénération de OUTIL...")
if "-o" in sys.argv:
o_index = sys.argv.index("-o")
if o_index + 1 < len(sys.argv):
output_file_html = os.path.join(f"{output_path}OUTIL_{switch_type}_{sys.argv[o_index + 1]}.html")
else:
print("Erreur: nom de fichier de sortie manquant après '-o'.")
sys.exit(1)
else:
timestamp = time.strftime("%Y%m%d")
output_file_html = f"{output_path}OUTIL_{switch_type}_{timestamp}.html"
output_file_html = verify_if_file_exists(output_file_html)
html_file = OUTIL(output_path, output_file_html)
print(f"✓ Processus terminé. Fichiers générés:\n - JSON: {output_file1_json} & {output_file2_json}\n - HTML: {html_file}")
```
> **Note :** Remplacez **`X`** de la première ligne par la lettre souhaitez (en dehors de celles déjà existante [o,d,u,s,i])'.
3. Mettez à jour les instructions textuelles d'usage affichées dans la console si le paramètre saisi est incorrect afin d'inclure `"OUTIL"` dans la liste des choix valides.
```python
print(" -X Generate OUTIL report (optional)")
```
> **Note :** Remplacez **`X`** par la lettre précédemmment choisi'.
## Étape 3 : Adaptation de l'Interface Graphique (GUI)
Afin que le nouveau modèle apparaisse dans l'interface graphique unifiée :
1. Ouvrez le fichier de gestion de la GUI (`gui_switch.py` racine ou script GUI dédié).
2. Dans la fonction `open_switch_gui_multi` :
- Ajouter la variable :
```python
OUTIL = tk.BooleanVar()
```
- Dans la fonction `process()`, ajouter :
```python
if OUTIL.get():
cmd.append("-X")
```
- Ajouter égalemment dans la fonction `open_switch_gui_multi`, le bouton de sélection de l'outil avec les autres existant :
```python
ttk.Checkbutton(
content,
text="Description courte de l'outil",
variable=OUTIL
).pack(anchor="w", padx=10, pady=(0, 0))
OUTIL.set(True)
```
3. Dans la fonction `open_switch_gui` :
- Répéter les mêmes opérations que pour `open_switch_gui_multi`
- Dans la fonction `update_output_label(*args)` ajouter et modifier les éléments suivants :
```python
def update_output_label(*args):
...
if output_var.get(): #ligne déjà existante
f_OUTIL = os.path.join(OUTPUT_DIR, f"OUTIL_{fw}_{output_var.get()}.xlsx")
...
else :
f_OUTIL = os.path.join(OUTPUT_DIR, f"OUTIL_{fw}_{dt}.xlsx")
...
output_label_var.set("Fichier de sortie :\n" + s_json1 + "\n" + s_json2 + ("\n" + s_uplink if rapport_uplink.get() else "") + ("\n" + s_stack if rapport_stack.get() else "") + ("\n" + s_interfaces if rapport_interfaces.get() else "") + ("\n" + s_schema if schema_infra.get() else "") + ("\n" + f_OUTIL if OUTIL.get() else "")) #ligne déjà existante a modifier
```
- Ajouter vers la fin de la fonction `open_switch_gui` avec les autres existant :
```python
OUTIL.trace_add("write", update_output_label)
```
4. Ouvrez le fichier de gestion principale de la GUI (`main.py` racine ou script GUI dédié).
- Dans la fonction `open_main_gui()` ajouter dans le Label du Switch :
```python
"\n + possibilité de générer un rapport des OUTIL",
```

BIN
Computacenter_logo.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 86 KiB

View File

@@ -6,6 +6,7 @@ Cet outil permet de **parser les configurations de différents types de firewall
- Il fournit également la possibilité de générer une **matrice de flux au format Excel** pour visualiser les communications et règles de trafic dans linfrastructure.
- Il founit également la possibilité de générer une **matrice de routage au format Excel** pour visualiser les routes statiques dans linfrastructure.
- Il founit également la possibilité de générer le **détail des interfaces au format Excel** pour visualiser la configuration des interfaces.
## Fonctionnalités principales
@@ -46,6 +47,10 @@ Cet outil permet de **parser les configurations de différents types de firewall
- Script Python qui utilise le JSON normalisé pour générer automatiquement une matrice Excel détaillant :
- les routes statiques
7. **Génération des interfaces**
- Script Python qui utilise le JSON normalisé pour générer automatiquement une matrice Excel détaillant :
- la configuration des interfaces
## Utilisation
### Pré-requis
@@ -59,9 +64,9 @@ pip install -r .\src\requirements.txt
#### Commandes principales
```bash
python3 .\src\main.py stormshield .\src\input\backup\ -f -r
python3 .\src\main.py paloalto .\src\input\nomfichier -f -r
python3 .\src\main.py forcepoint .\src\input\nomfichier -f -r
python3 .\src\main.py stormshield .\src\input\backup\ -f -r -i
python3 .\src\main.py paloalto .\src\input\nomfichier -f -r -i
python3 .\src\main.py forcepoint .\src\input\nomfichier -f -r -i
```
#### Options
@@ -70,6 +75,8 @@ python3 .\src\main.py forcepoint .\src\input\nomfichier -f -r
| -o [nom_fichier] | Spécifie le nom du fichier JSON de sortie (optionnel)
| -f | Génère un rapport Excel de type matrice de flux (optionnel)
| -r | Génère un rapport Excel de type matrice de routage (optionnel)
| -i | Generate interface report (optional)
---
## Arborescence du projet

View File

@@ -6,6 +6,7 @@ from scripts.json_Stormshield import generate_json_stormshield
from scripts.json_Forcepoint import generate_json_forcepoint
from scripts.export_matrice_flux import export_to_excel as export_flux_to_excel
from scripts.export_matrice_routage import export_to_excel as export_routing_to_excel
from scripts.export_interfaces import export_to_excel as export_interfaces_to_excel
def verify_if_file_exists(name):
base, ext = os.path.splitext(name)
@@ -24,6 +25,7 @@ def main():
print(" -o <output_file> Specify output JSON file name (optional)")
print(" -f Generate matrix flux report (optional)")
print(" -r Generate routing matrix report (optional)")
print(" -i Generate interface report (optional)")
sys.exit(1)
firewall_type = sys.argv[1].lower()
@@ -85,5 +87,21 @@ def main():
excel_file = export_routing_to_excel(output_file_json, output_file_excel)
print(f"✓ Processus terminé. Fichiers générés:\n - JSON: {output_file_json}\n - Excel: {excel_file}")
if "-i" in sys.argv:
print(f"\nGénération de l'export les interfaces...")
if "-o" in sys.argv:
o_index = sys.argv.index("-o")
if o_index + 1 < len(sys.argv):
output_file_excel = os.path.join(f"{output_path}interfaces_{firewall_type}_{sys.argv[o_index + 1]}.xlsx")
else:
print("Erreur: nom de fichier de sortie manquant après '-o'.")
sys.exit(1)
else:
timestamp = time.strftime("%Y%m%d")
output_file_excel = f"{output_path}interfaces_{firewall_type}_{timestamp}.xlsx"
output_file_excel = verify_if_file_exists(output_file_excel)
excel_file = export_interfaces_to_excel(output_file_json, output_file_excel)
print(f"✓ Processus terminé. Fichiers générés:\n - JSON: {output_file_json}\n - Excel: {excel_file}")
if __name__ == "__main__":
main()

View File

@@ -0,0 +1,201 @@
import json
import pandas as pd
from openpyxl import load_workbook
from openpyxl.styles import PatternFill, Border, Side, Alignment, Font
from openpyxl.utils import get_column_letter
center = Alignment(horizontal="center", vertical="center", wrap_text=True)
left = Alignment(horizontal="left", vertical="center", wrap_text=True)
header_fill = PatternFill(start_color="2F5496", fill_type="solid")
iface_fill = PatternFill(start_color="BDD7EE", fill_type="solid")
sub_fill = PatternFill(start_color="DDEBF7", fill_type="solid")
disabled_fill= PatternFill(start_color="F2F2F2", fill_type="solid")
thick_border = Border(*(Side(style="thick"),)*4)
thin_border = Border(*(Side(style="thin"),)*4)
medium_side = Side(style="medium")
def _thin(top=False, bottom=False, left_s=False, right_s=False):
return Border(
top=Side(style="thin") if top else Side(style=None),
bottom=Side(style="thin") if bottom else Side(style=None),
left=Side(style="thin") if left_s else Side(style=None),
right=Side(style="thin") if right_s else Side(style=None),
)
def _build_vrf_map(data):
"""Retourne {interface_name: vrf_name} depuis network-instances."""
vrf_map = {}
for ni in data.get("openconfig-network-instance:network-instances", {}).get("network-instance", []):
vrf_name = ni.get("name", "")
for iface in ni.get("interfaces", {}).get("interface", []):
iface_id = iface.get("id", "")
if iface_id:
vrf_map[iface_id] = vrf_name
return vrf_map
def _parse_interfaces(data):
vrf_map = _build_vrf_map(data)
rows = []
for iface in data.get("openconfig-interfaces:interfaces", {}).get("interface", []):
cfg = iface.get("config", {})
iface_name = cfg.get("name", iface.get("name", ""))
iface_type = cfg.get("type", "")
iface_desc = cfg.get("description", "")
enabled = cfg.get("enabled", True)
subinterfaces = iface.get("subinterfaces", {}).get("subinterface", [])
if not subinterfaces:
rows.append({
"Interface": iface_name,
"Type": iface_type,
"Description": iface_desc,
"Enabled": "Oui" if enabled else "Non",
"VLAN": "",
"IP": "",
"Préfixe": "",
"VRF": vrf_map.get(iface_name, ""),
"_is_sub": False,
})
else:
for sub in subinterfaces:
sub_cfg = sub.get("config", {})
vlan = sub.get("index", sub_cfg.get("index", ""))
sub_name = f"{iface_name}.{vlan}" if vlan != 0 else iface_name
sub_enabled = sub_cfg.get("enabled", enabled)
addresses = (
sub.get("oc-ip:ipv4", {})
.get("oc-ip:addresses", {})
.get("oc-ip:address", [])
)
if not addresses:
rows.append({
"Interface": iface_name,
"Type": iface_type,
"Description": iface_desc,
"Enabled": "Oui" if sub_enabled else "Non",
"VLAN": "" if vlan == 0 else vlan,
"IP": "",
"Préfixe": "",
"VRF": vrf_map.get(sub_name, vrf_map.get(iface_name, "")),
"_is_sub": vlan != 0,
})
else:
for addr in addresses:
addr_cfg = addr.get("oc-ip:config", {})
rows.append({
"Interface": iface_name,
"Type": iface_type,
"Description": iface_desc,
"Enabled": "Oui" if sub_enabled else "Non",
"VLAN": "" if vlan == 0 else vlan,
"IP": addr_cfg.get("oc-ip:ip", ""),
"Préfixe": addr_cfg.get("oc-ip:prefix-length", ""),
"VRF": vrf_map.get(sub_name, vrf_map.get(iface_name, "")),
"_is_sub": vlan != 0,
})
return rows
def _style_interfaces(ws):
COLS = {
"Interface": 1,
"Type": 2,
"Description": 3,
"Enabled": 4,
"VLAN": 5,
"IP": 6,
"Préfixe": 7,
"VRF": 8,
}
N = len(COLS)
for col in range(1, N + 1):
cell = ws.cell(row=1, column=col)
cell.fill = header_fill
cell.font = Font(bold=True, color="FFFFFF", size=10)
cell.alignment = center
cell.border = thin_border
ws.freeze_panes = "A2"
max_width = {c: len(str(ws.cell(row=1, column=c).value or "")) for c in range(1, N + 1)}
prev_iface = None
group_start = 2
for row in range(2, ws.max_row + 1):
iface_val = ws.cell(row=row, column=COLS["Interface"]).value
enabled = ws.cell(row=row, column=COLS["Enabled"]).value
is_last = (row == ws.max_row)
next_iface = ws.cell(row=row + 1, column=COLS["Interface"]).value if not is_last else None
if enabled == "Non":
row_fill = disabled_fill
elif ws.cell(row=row, column=COLS["VLAN"]).value:
row_fill = sub_fill
else:
row_fill = iface_fill
for col in range(1, N + 1):
cell = ws.cell(row=row, column=col)
if col != COLS["Interface"]:
cell.fill = row_fill
cell.alignment = left if col not in (COLS["Enabled"], COLS["VLAN"], COLS["Préfixe"]) else center
cell.border = thin_border
val = cell.value
max_width[col] = max(max_width[col], len(str(val or "")))
if iface_val != next_iface or is_last:
if row > group_start:
ws.merge_cells(
start_row=group_start, start_column=COLS["Interface"],
end_row=row, end_column=COLS["Interface"]
)
for r in range(group_start, row + 1):
c = ws.cell(r, COLS["Interface"])
c.fill = iface_fill
c.font = Font(bold=True, size=10)
c.alignment = center
c.border = thick_border
group_start = row + 1
ws.row_dimensions[row].height = 18
for col, width in max_width.items():
ws.column_dimensions[get_column_letter(col)].width = min(width + 4, 45)
def export_to_excel(json_file_path: str, output_file_excel: str) -> str:
with open(json_file_path, "r", encoding="utf-8") as f:
data = json.load(f)
rows = _parse_interfaces(data)
export_rows = [{k: v for k, v in r.items() if k != "_is_sub"} for r in rows]
df = pd.DataFrame(export_rows, columns=[
"Interface", "Type", "Description", "Enabled", "VLAN", "IP", "Préfixe", "VRF"
])
with pd.ExcelWriter(output_file_excel, engine="openpyxl") as writer:
df.to_excel(writer, sheet_name="Interfaces", index=False)
wb = load_workbook(output_file_excel)
_style_interfaces(wb["Interfaces"])
wb.save(output_file_excel)
print(f"✓ Export interfaces OK : {output_file_excel}")
return output_file_excel

View File

@@ -8,6 +8,8 @@ from openpyxl import load_workbook
from scripts.style_excel.style_address_groups import style_address_groups
from scripts.style_excel.style_service_groups import style_service_groups
from scripts.style_excel.style_matrice_flux import style_matrice_flux
from scripts.style_excel.style_addresses import style_addresses
from scripts.style_excel.style_services import style_services
def export_to_excel(json_file_path, output_file_excel):
"""
@@ -192,20 +194,46 @@ def export_to_excel(json_file_path, output_file_excel):
for m in cfg.get("members", [])
])
df_addresses = pd.DataFrame([
{
"Name": name,
"IP / Masque": cfg.get("ip_netmask", "") if "/" in cfg.get("ip_netmask", "")
else (cfg.get("ip_netmask", "") + "/32" if cfg.get("ip_netmask") else ""),
"Description": cfg.get("description", ""),
"Tags": cfg.get("misc", ""),
}
for name, cfg in sorted(addresses.items())
])
df_services = pd.DataFrame([
{
"Name": name,
"Protocol": cfg.get("protocol", ""),
"Port": cfg.get("port", ""),
"Description": cfg.get("description", ""),
}
for name, cfg in sorted(services.items())
])
# === Export Excel ===
firewall_type = data.get("firewall-device", {}).get("type", "firewall").replace(" ","_").lower()
date = time.strftime("%Y%m%d")
with pd.ExcelWriter(output_file_excel, engine="openpyxl") as writer:
df_addr.to_excel(writer,sheet_name="Address-Groups",index=False)
df_srv.to_excel(writer,sheet_name="Service-Groups",index=False)
df.to_excel(writer,sheet_name="Matrice Flux",index=False,startrow=1)
df_addresses.to_excel(writer, sheet_name="Addresses", index=False)
df_addr.to_excel(writer, sheet_name="Address-Groups", index=False)
df_services.to_excel(writer, sheet_name="Services", index=False)
df_srv.to_excel(writer, sheet_name="Service-Groups", index=False)
df.to_excel(writer, sheet_name="Matrice Flux", index=False, startrow=1)
wb = load_workbook(output_file_excel)
if "Sheet1" in wb.sheetnames:
del wb["Sheet1"]
style_addresses(wb["Addresses"])
style_address_groups(wb["Address-Groups"], address_groups)
style_services(wb["Services"])
style_service_groups(wb["Service-Groups"], service_groups)
style_matrice_flux(wb["Matrice Flux"])

View File

@@ -38,37 +38,46 @@ class ParserMixin:
"name": interface.name,
"config": {
"name": interface.name,
"type": "iana-if-type:ethernetCsmacd" if interface.interface_type == "ethernet" else "iana-if-type:ieee8023adLag",
"type": interface.interface_type if interface.interface_type else None,
"enabled": interface.enabled,
"description": interface.comment or ""
}
}
if interface.ip:
intf_config["subinterfaces"] = {
"subinterface": [
{
subinterfaces = [
{
"index": interface.misc or 0,
"config": {
"index": interface.misc or 0,
"config": {
"index": interface.misc or 0,
"enabled": interface.enabled
},
"oc-ip:ipv4": {
"oc-ip:addresses": {
"oc-ip:address": [
{
"enabled": interface.enabled
},
"oc-ip:ipv4": {
"oc-ip:addresses": {
"oc-ip:address": [
{
"oc-ip:ip": interface.ip,
"oc-ip:config": {
"oc-ip:ip": interface.ip,
"oc-ip:config": {
"oc-ip:ip": interface.ip,
"oc-ip:prefix-length": interface.netmask if interface.netmask else 24
}
"oc-ip:prefix-length": interface.netmask if interface.netmask else 24
}
]
}
}
]
}
}
]
}
}
]
if interface.interface_type == "vlan":
subinterfaces.append({
"index": interface.vlan or None,
"config": {
"index": interface.vlan or None,
}
})
intf_config["subinterfaces"] = {"subinterface": subinterfaces}
openconfig["openconfig-interfaces:interfaces"]["interface"].append(intf_config)

View File

@@ -46,13 +46,17 @@ class StormshieldParser(ParserMixin):
current_section = line.strip("[]")
continue
inline_comment = ""
if "#" in line:
inline_comment = line.split("#", 1)[1].strip()
if current_section in ("Host", "Network", "Fqdn"):
match = re.match(r"([^=]+)=([^,#]+)", line)
if match:
name = match.group(1).strip()
ip = match.group(2).strip()
self.config["address_objects"].append(
AddressObject(name=name, ip_netmask=ip)
AddressObject(name=name, ip_netmask=ip, description=inline_comment)
)
elif current_section == "Service":
@@ -62,7 +66,7 @@ class StormshieldParser(ParserMixin):
port = match.group(2)
proto = match.group(3).lower()
self.config["service_objects"].append(
ServiceObject(name=name, protocol=proto, port=port)
ServiceObject(name=name, protocol=proto, port=port, description=inline_comment)
)
def _parse_address_groups(self):
@@ -156,18 +160,7 @@ class StormshieldParser(ParserMixin):
def _add_interface(self, section_name, data):
"""Crée un objet Interface à partir dune section complète"""
if section_name.lower().startswith("vlan"):
iface_type = "vlan"
elif section_name.lower().startswith("bridge"):
iface_type = "bridge"
elif section_name.lower().startswith("wifi"):
iface_type = "wifi"
elif section_name.lower().startswith("loopback"):
iface_type = "loopback"
elif section_name.lower().startswith("agg"):
iface_type = "aggregate"
else:
iface_type = "ethernet"
iface_type = section_name.rstrip("0123456789")
enabled = data.get("State", "0") == "1"
name = data.get("Name", section_name)
@@ -187,6 +180,7 @@ class StormshieldParser(ParserMixin):
comment=comment,
interface_type=iface_type,
enabled=enabled,
vlan=data.get("Tag") if data.get("Tag") and iface_type == "vlan" else None
)
self.config["interfaces"].append(interface)

View File

@@ -61,6 +61,7 @@ class Interface:
comment: str = None
interface_type: str = None
enabled: bool = True
vlan: str = None
@dataclass
class SecurityRule:

View File

@@ -0,0 +1,44 @@
from openpyxl.styles import PatternFill, Border, Side, Alignment, Font
from openpyxl.utils import get_column_letter
center = Alignment(horizontal="center", vertical="center")
left = Alignment(horizontal="left", vertical="center")
red_fill = PatternFill(start_color="FF9999", fill_type="solid")
yellow_fill = PatternFill(start_color="FFFF99", fill_type="solid")
thick_border = Border(*(Side(style="thick"),)*4)
thin_border = Border(*(Side(style="thin"),)*4)
def style_addresses(ws):
col_name, col_ip, col_desc, col_tags = 1, 2, 3, 4
max_width = {1: 0, 2: 0, 3: 0, 4: 0}
for row in range(2, ws.max_row + 1):
name = ws.cell(row=row, column=col_name).value
ip = ws.cell(row=row, column=col_ip).value
desc = ws.cell(row=row, column=col_desc).value
tags = ws.cell(row=row, column=col_tags).value
ws.cell(row=row, column=col_name).fill = red_fill
ws.cell(row=row, column=col_name).font = Font(bold=True)
ws.cell(row=row, column=col_name).alignment = left
ws.cell(row=row, column=col_name).border = thin_border
for col in (col_ip, col_desc, col_tags):
ws.cell(row=row, column=col).alignment = left
ws.cell(row=row, column=col).border = thick_border
ws.cell(row=row, column=col).fill = yellow_fill
max_width[1] = max(max_width[1], len(str(name or "")))
max_width[2] = max(max_width[2], len(str(ip or "")))
max_width[3] = max(max_width[3], len(str(desc or "")))
max_width[4] = max(max_width[4], len(str(tags or "")))
for col in max_width:
ws.column_dimensions[get_column_letter(col)].width = max_width[col] + 2
for row in range(2, ws.max_row + 1):
ws.row_dimensions[row].height = 18

View File

@@ -0,0 +1,51 @@
from openpyxl.styles import PatternFill, Border, Side, Alignment, Font
from openpyxl.utils import get_column_letter
center = Alignment(horizontal="center", vertical="center")
left = Alignment(horizontal="left", vertical="center")
red_fill = PatternFill(start_color="FF9999", fill_type="solid")
yellow_fill = PatternFill(start_color="FFFF99", fill_type="solid")
thick_border = Border(*(Side(style="thick"),)*4)
thin_border = Border(*(Side(style="thin"),)*4)
def style_services(ws):
col_name, col_proto, col_port, col_desc = 1, 2, 3, 4
max_width = {1: 0, 2: 0, 3: 0, 4: 0}
for row in range(2, ws.max_row + 1):
name = ws.cell(row=row, column=col_name).value
proto = ws.cell(row=row, column=col_proto).value
port = ws.cell(row=row, column=col_port).value
desc = ws.cell(row=row, column=col_desc).value
ws.cell(row=row, column=col_name).fill = red_fill
ws.cell(row=row, column=col_name).font = Font(bold=True)
ws.cell(row=row, column=col_name).alignment = left
ws.cell(row=row, column=col_name).border = thin_border
ws.cell(row=row, column=col_proto).alignment = center
ws.cell(row=row, column=col_proto).border = thick_border
ws.cell(row=row, column=col_proto).fill = yellow_fill
ws.cell(row=row, column=col_port).alignment = center
ws.cell(row=row, column=col_port).border = thick_border
ws.cell(row=row, column=col_port).fill = yellow_fill
ws.cell(row=row, column=col_desc).alignment = left
ws.cell(row=row, column=col_desc).border = thick_border
ws.cell(row=row, column=col_desc).fill = yellow_fill
max_width[1] = max(max_width[1], len(str(name or "")))
max_width[2] = max(max_width[2], len(str(proto or "")))
max_width[3] = max(max_width[3], len(str(port or "")))
max_width[4] = max(max_width[4], len(str(desc or "")))
for col in max_width:
ws.column_dimensions[get_column_letter(col)].width = max_width[col] + 2
for row in range(2, ws.max_row + 1):
ws.row_dimensions[row].height = 18

View File

@@ -15,6 +15,7 @@ Données extraites : Fichiers et dossiers de configurations d'origine.
Rapports générés :
- Matrice de flux (Excel) pour visualiser les communications et les règles de trafic.
- Matrice de routage (Excel) pour cartographier les routes statiques.
- Détail des interfaces (Excel) pour visualiser la configuration des interfaces.
```
- Module Switch

View File

@@ -75,11 +75,12 @@ class ToolTip:
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.geometry("800x500")
app2.resizable(True, True)
matrice_flux = tk.BooleanVar()
matrice_routage = tk.BooleanVar()
interfaces = tk.BooleanVar()
content = make_scrollable(app2)
@@ -158,6 +159,8 @@ def open_firewall_gui_multi(app, OUTPUT_DIR, HELP_FILE_FW, FIREWALL_DIR, FIREWAL
cmd.append("-f")
if matrice_routage.get():
cmd.append("-r")
if interfaces.get():
cmd.append("-i")
cmd.append("-o")
if item["type"] == "file":
@@ -376,9 +379,16 @@ def open_firewall_gui_multi(app, OUTPUT_DIR, HELP_FILE_FW, FIREWALL_DIR, FIREWAL
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))
).pack(anchor="w", padx=10, pady=(0, 0))
matrice_routage.set(True)
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)
ttk.Label(
content,
text="Dossier de sortie :",
@@ -418,7 +428,7 @@ def open_firewall_gui(root, BASE_DIR):
app = tk.Toplevel(root)
app.title("Analyse Configuration Firewall")
app.geometry("800x450")
app.geometry("800x500")
app.resizable(True, True)
firewall_var = tk.StringVar()
@@ -427,6 +437,7 @@ def open_firewall_gui(root, BASE_DIR):
matrice_flux = tk.BooleanVar()
matrice_routage = tk.BooleanVar()
interfaces = tk.BooleanVar()
def browse_input():
fw_type = firewall_var.get()
@@ -453,22 +464,15 @@ def open_firewall_gui(root, BASE_DIR):
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")
f_interfaces = os.path.join(OUTPUT_DIR, f"interfaces_{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")
f_interfaces = os.path.join(OUTPUT_DIR, f"interfaces_{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)
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 ""))
app.update_idletasks()
def open_output_folder():
@@ -518,9 +522,10 @@ def open_firewall_gui(root, BASE_DIR):
if matrice_flux.get():
cmd.append("-f")
if matrice_routage.get():
cmd.append("-r")
if interfaces.get():
cmd.append("-i")
print("Commande exécutée :", " ".join(cmd))
print("Dossier courant (cwd) :", FIREWALL_DIR)
@@ -636,15 +641,23 @@ def open_firewall_gui(root, BASE_DIR):
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))
).pack(anchor="w", padx=10, pady=(0, 0))
matrice_routage.set(True)
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)
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)
interfaces.trace_add("write", update_output_label)
update_output_label()
ttk.Button(

View File

@@ -6,6 +6,7 @@ Cet outil permet de **récupérer les données des configurations de différents
- Il fournit également la possibilité de générer une **matrice de flux au format Excel** pour visualiser les communications et règles de trafic dans linfrastructure.
- Il founit également la possibilité de générer une **matrice de routage au format Excel** pour visualiser les routes statiques dans linfrastructure.
- Il founit également la possibilité de générer le **détail des interfaces au format Excel** pour visualiser la configuration des interfaces.
## Utilisation

26
main.py
View File

@@ -58,9 +58,10 @@ def bootstrap_venv():
def relaunch_in_venv():
print("[INFO] Relance du script dans le venv…")
script_path = os.path.abspath(__file__)
subprocess.check_call([
venv_python(),
__file__
script_path
])
sys.exit(0)
@@ -68,14 +69,30 @@ def relaunch_in_venv():
def open_main_gui():
root = tk.Tk()
root.title("Analyse Réseau")
root.geometry("650x350")
root.geometry("650x500")
root.resizable(True, True)
header_frame = tk.Frame(root)
header_frame.pack(fill="x", pady=10, padx=10)
logo_path = os.path.join(BASE_DIR, "Computacenter_logo.png")
if os.path.isfile(logo_path):
try:
logo_img = tk.PhotoImage(file=logo_path)
logo_img = logo_img.subsample(15, 15)
logo_label = tk.Label(header_frame, image=logo_img)
logo_label.image = logo_img
logo_label.pack(side="right")
except Exception as e:
print(f"[WARN] Impossible de charger le logo : {e}")
ttk.Label(
root,
text="Analyse Réseau",
font=("Arial", 16, "bold")
).pack(pady=20)
).pack(pady=(0, 20))
ttk.Label(
root,
@@ -94,7 +111,8 @@ def open_main_gui():
root,
text="(Convertir les données au format normalisé Yang dans un fichier JSON)" \
"\n + possibilité de générer une matrice de flux en Excel" \
"\n + possibilité de générer une matrice de routage en Excel (route statique uniquement)",
"\n + possibilité de générer une matrice de routage en Excel (route statique uniquement)" \
"\n + possibilité de générer un rapport des interfaces en Excel",
font=("Arial", 9, "italic"),
anchor="center",
justify="center"