matrice de routage ajouté | reformatage

This commit is contained in:
Chevallier
2026-01-14 08:52:25 +01:00
parent df6334febc
commit 496cb00803
14 changed files with 380 additions and 88 deletions

View File

@@ -0,0 +1,97 @@
import json
import re
import pandas as pd
import ipaddress
import time
from collections import deque
from openpyxl import load_workbook
from scripts.style_excel.style_matrice_routage import style_matrice_routage
def is_pure_cidr(value):
try:
ipaddress.ip_network(value, strict=False)
return True
except ValueError:
return False
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
"""
with open(json_file_path, "r", encoding="utf-8") as f:
data = json.load(f)
address_objects = {}
addr_objs = data.get(
"custom-firewall-objects:firewall-objects", {}
).get("address", [])
for obj in addr_objs:
name = obj.get("name")
ip_netmask = obj.get("config", {}).get("ip_netmask")
if name and ip_netmask:
address_objects[name] = ip_netmask
rows = []
network_instances = data.get(
"openconfig-network-instance:network-instances", {}
).get("network-instance", [])
for ni in network_instances:
equipement = ni.get("name", "")
protocols = ni.get("protocols", {}).get("protocol", [])
for proto in protocols:
if proto.get("identifier") != "STATIC":
continue
static_routes = proto.get("static-routes", {}).get("static", [])
for route in static_routes:
prefix = route.get("prefix", "")
# Découpage réseau / masque
resolved_prefix = prefix
if not is_pure_cidr(prefix):
resolved_prefix = address_objects.get(prefix, prefix)
try:
net = ipaddress.ip_network(resolved_prefix, strict=False)
reseau = str(net.network_address)
masque = str(net.netmask)
except ValueError:
reseau = resolved_prefix
masque = ""
next_hops = route.get("next-hops", {}).get("next-hop", [])
for nh in next_hops:
nh_config = nh.get("config", {})
rows.append({
"Equipement": equipement,
"Réseau destination": reseau,
"Masque": masque,
"Next Hop": nh_config.get("next-hop", ""),
"Metrique": nh_config.get("metric", ""),
"Commentaire": prefix
})
df = pd.DataFrame(rows)
with pd.ExcelWriter(output_file_excel, engine="openpyxl") as writer:
df.to_excel(writer,sheet_name="Routes statiques",index=False,startrow=1)
wb = load_workbook(output_file_excel)
if "Sheet1" in wb.sheetnames:
del wb["Sheet1"]
style_matrice_routage(wb["Routes statiques"])
wb.save(output_file_excel)
print(f"✓ Export Excel OK: {output_file_excel}")
return output_file_excel

View File

@@ -196,59 +196,95 @@ class StormshieldParser(ParserMixin):
if not os.path.exists(route_path):
return
virtual_routers = {}
default_route = None
section = None
with open(route_path, encoding="utf-8", errors="ignore") as f:
for raw_line in f:
line = raw_line.strip()
if not line or line.startswith("#"):
if not line or line.startswith("off") or line.startswith("#"):
continue
if line.startswith("[") and line.endswith("]"):
section = line.strip("[]")
continue
# ===== Default route =====
if section == "Config" and line.startswith("DefaultRoute="):
self.config["default_route"] = line.split("=", 1)[1].strip()
default_route = line.split("=", 1)[1].strip()
elif section == "StaticRoutes" and not line.startswith("#"):
parts = line.split(",")
if len(parts) >= 2:
self.config["static_routes"].append({
"destination": parts[0],
"interface": parts[1],
"extra": parts[2:] if len(parts) > 2 else []
})
# ===== Static routes =====
elif section == "StaticRoutes":
parts = [p.strip() for p in line.split(",")]
if len(parts) < 2:
continue
static_routes = []
if self.config["default_route"]:
static_routes.append(
destination = parts[0]
vr_name = None
interface = None
next_hop_ip = None
# Format : VR->NextHop
if "->" in parts[1]:
vr_name, next_hop_ip = map(str.strip, parts[1].split("->", 1))
interface = vr_name
else:
vr_name = parts[1]
interface = parts[1]
# Création VR si absent
if vr_name not in virtual_routers:
virtual_routers[vr_name] = {
"interfaces": set(),
"static_routes": []
}
virtual_routers[vr_name]["interfaces"].add(interface)
static_route = StaticRoute(
name=f"{vr_name}-static-{len(virtual_routers[vr_name]['static_routes']) + 1}",
destination=destination,
metric=None,
next_vr=None,
next_hop_ip=next_hop_ip,
interface=interface,
bfd_profile=None
)
virtual_routers[vr_name]["static_routes"].append(static_route)
# ===== Default VR (route par défaut) =====
if default_route:
vr_name = "default"
virtual_routers.setdefault(vr_name, {
"interfaces": set(),
"static_routes": []
})
virtual_routers[vr_name]["static_routes"].insert(
0,
StaticRoute(
name="default-route",
destination="0.0.0.0/0",
metric=1,
next_hop_ip=self.config["default_route"],
interface=None
next_vr=None,
next_hop_ip=default_route,
interface=None,
bfd_profile=None
)
)
for idx, route in enumerate(self.config["static_routes"]):
static_routes.append(
StaticRoute(
name=f"static-{idx+1}",
destination=route["destination"],
metric=1,
next_hop_ip=None,
interface=route["interface"]
)
# ===== Construction finale =====
self.config["virtual_routers"] = [
VirtualRouter(
name=vr_name,
interfaces=list(data["interfaces"]),
static_routes=data["static_routes"]
)
vr = VirtualRouter(
name="default-vr",
interfaces=[r["interface"] for r in self.config["static_routes"]],
static_routes=static_routes
)
self.config["virtual_routers"] = [vr]
for vr_name, data in virtual_routers.items()
]
# def _parse_slotinfo_file(self):
# path = os.path.join(self.base_dir, "Filter", "slotinfo")

View File

@@ -0,0 +1,58 @@
from openpyxl.styles import Alignment, PatternFill, Font, Border, Side
from openpyxl.utils import get_column_letter
def style_matrice_routage(ws):
headers = [
"Equipement",
"Réseau destination",
"Masque",
"Next Hop",
"Metrique",
"Commentaire"
]
header_fill = PatternFill("solid", fgColor="1F4E78")
header_font = Font(color="FFFFFF", bold=True)
header_alignment = Alignment(horizontal="center", vertical="center")
cell_alignment_left = Alignment(horizontal="left", vertical="center")
cell_alignment_center = Alignment(horizontal="center", vertical="center")
thin_border = Border(
left=Side(style="thin"),
right=Side(style="thin"),
top=Side(style="thin"),
bottom=Side(style="thin")
)
for col_idx, header in enumerate(headers, start=1):
cell = ws.cell(row=1, column=col_idx, value=header)
cell.fill = header_fill
cell.font = header_font
cell.alignment = header_alignment
cell.border = thin_border
column_widths = {
"A": 22, # Equipement
"B": 22, # Réseau destination
"C": 18, # Masque
"D": 20, # Next Hop
"E": 12, # Metrique
"F": 30 # Commentaire
}
for col_letter, width in column_widths.items():
ws.column_dimensions[col_letter].width = width
for row in ws.iter_rows(min_row=2, max_row=ws.max_row, max_col=len(headers)):
for cell in row:
cell.border = thin_border
if cell.column in (1, 2, 4, 6):
cell.alignment = cell_alignment_left
else:
cell.alignment = cell_alignment_center
ws.freeze_panes = "A2"
ws.auto_filter.ref = ws.dimensions