forked from JulieChv/Analyse_Reseaux
222 lines
8.0 KiB
Markdown
222 lines
8.0 KiB
Markdown
|
|
|
||
|
|
# Guide de Développement : Créer son propre Parseur Firewall
|
||
|
|
|
||
|
|
Ce guide explique comment étendre l'outil d'analyse réseau en ajoutant un nouveau parseur pour un modèle de firewall non supporté nativement (ex: CheckPoint, Fortinet, etc.).
|
||
|
|
|
||
|
|
> **Note :** Tout au long de ce guide, remplacez **`MODELE`** (en majuscule ou minuscule) par le nom de la marque ou du modèle du firewall ciblé.
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## Étape 1 : Création du script de parsing
|
||
|
|
|
||
|
|
Dans le dossier `Parseurs_config_Firewall/src/scripts/` (ou `script/` selon votre arborescence), créez un nouveau fichier Python nommé **`json_MODELE.py`**.
|
||
|
|
|
||
|
|
*Il est fortement recommandé de s'inspirer des parseurs existants comme `json_Forcepoint.py`, `json_Stormshield.py` ou `json_PaloAlto.py`.*
|
||
|
|
|
||
|
|
Voici le squelette de code à utiliser (exemple basé sur des logs au format XML) :
|
||
|
|
|
||
|
|
```python
|
||
|
|
#!/usr/bin/env python3
|
||
|
|
"""
|
||
|
|
Parser pour configuration MODELE XML vers un format json normalisé OpenConfig YANG
|
||
|
|
Extrait les groupes d'objets, objets, groupes de services, services, routes, interfaces et règles
|
||
|
|
"""
|
||
|
|
|
||
|
|
import xml.etree.ElementTree as ET
|
||
|
|
import json
|
||
|
|
from scripts.export_modele import ParserMixin
|
||
|
|
from scripts.objets.data import AddressObject, AddressGroup, ServiceObject, ServiceGroup, Interface, SecurityRule, StaticRoute, VirtualRouter
|
||
|
|
from pathlib import Path
|
||
|
|
|
||
|
|
class ModeleParser(ParserMixin):
|
||
|
|
"""Parser pour fichier Modele"""
|
||
|
|
|
||
|
|
def __init__(self, xml_file_path: str):
|
||
|
|
"""Initialise le parser avec le chemin du fichier"""
|
||
|
|
self.xml_file = xml_file_path
|
||
|
|
self.tree = None
|
||
|
|
self.root = None
|
||
|
|
self.config = {
|
||
|
|
'address_objects': [],
|
||
|
|
'address_groups': [],
|
||
|
|
'service_objects': [],
|
||
|
|
'service_groups': [],
|
||
|
|
'interfaces': [],
|
||
|
|
'virtual_routers': [],
|
||
|
|
'static_routes': [],
|
||
|
|
'security_rules': []
|
||
|
|
}
|
||
|
|
|
||
|
|
def load_xml(self):
|
||
|
|
"""Charge le fichier XML"""
|
||
|
|
try:
|
||
|
|
self.tree = ET.parse(self.xml_file)
|
||
|
|
self.root = self.tree.getroot()
|
||
|
|
print(f"✓ Fichier XML chargé: {self.xml_file}")
|
||
|
|
except ET.ParseError as e:
|
||
|
|
print(f"✗ Erreur de parsing XML: {e}")
|
||
|
|
raise
|
||
|
|
except FileNotFoundError:
|
||
|
|
print(f"✗ Fichier non trouvé: {self.xml_file}")
|
||
|
|
raise
|
||
|
|
|
||
|
|
def _parse_address_objects(self):
|
||
|
|
"""Parse les objets adresse"""
|
||
|
|
address_objects = []
|
||
|
|
|
||
|
|
# TODO: Parcourir le XML et instancier des objets AddressObject
|
||
|
|
|
||
|
|
self.config['address_objects'] = address_objects
|
||
|
|
print(f"✓ Trouvé {len(address_objects)} objets adresse")
|
||
|
|
|
||
|
|
def _parse_address_groups(self):
|
||
|
|
"""Parse les groupes d'adresses"""
|
||
|
|
address_groups = []
|
||
|
|
|
||
|
|
# TODO: Parcourir le XML et instancier des objets AddressGroup
|
||
|
|
|
||
|
|
self.config['address_groups'] = address_groups
|
||
|
|
print(f"✓ Trouvé {len(address_groups)} groupes d'adresses")
|
||
|
|
|
||
|
|
def _parse_service_objects(self):
|
||
|
|
"""Parse les objets service"""
|
||
|
|
service_objects = []
|
||
|
|
|
||
|
|
# TODO: Parcourir le XML et instancier des objets ServiceObject
|
||
|
|
|
||
|
|
self.config['service_objects'] = service_objects
|
||
|
|
print(f"✓ Trouvé {len(service_objects)} objets service")
|
||
|
|
|
||
|
|
def _parse_service_groups(self):
|
||
|
|
"""Parse les groupes de services"""
|
||
|
|
service_groups = []
|
||
|
|
|
||
|
|
# TODO: Parcourir le XML et instancier des objets ServiceGroup
|
||
|
|
|
||
|
|
self.config['service_groups'] = service_groups
|
||
|
|
print(f"✓ Trouvé {len(service_groups)} groupes de services")
|
||
|
|
|
||
|
|
def _parse_interfaces(self):
|
||
|
|
"""Parse les interfaces réseau"""
|
||
|
|
interfaces = []
|
||
|
|
|
||
|
|
# TODO: Parcourir le XML et instancier des objets Interface
|
||
|
|
|
||
|
|
self.config['interfaces'] = interfaces
|
||
|
|
print(f"✓ Trouvé {len(interfaces)} interfaces")
|
||
|
|
|
||
|
|
def _parse_virtual_routers(self):
|
||
|
|
"""Parse les virtual-routers et leurs routes statiques"""
|
||
|
|
virtual_routers = []
|
||
|
|
|
||
|
|
# TODO: Parcourir le XML, instancier des VirtualRouter et injecter les StaticRoute
|
||
|
|
|
||
|
|
self.config['virtual_routers'] = virtual_routers
|
||
|
|
print(f"✓ Trouvé {len(virtual_routers)} virtual-routers")
|
||
|
|
|
||
|
|
def _parse_security_rules(self):
|
||
|
|
"""Parse les règles de sécurité"""
|
||
|
|
security_rules = []
|
||
|
|
|
||
|
|
# TODO: Parcourir le XML et instancier des objets SecurityRule
|
||
|
|
|
||
|
|
self.config['security_rules'] = security_rules
|
||
|
|
print(f"✓ Trouvé {len(security_rules)} règles de sécurité")
|
||
|
|
|
||
|
|
def parse_all(self):
|
||
|
|
"""Parse tous les éléments de configuration"""
|
||
|
|
print("Début du parsing de la configuration MODELE...")
|
||
|
|
|
||
|
|
self.load_xml()
|
||
|
|
self._parse_address_objects()
|
||
|
|
self._parse_address_groups()
|
||
|
|
self._parse_service_objects()
|
||
|
|
self._parse_service_groups()
|
||
|
|
self._parse_interfaces()
|
||
|
|
self._parse_virtual_routers()
|
||
|
|
self._parse_security_rules()
|
||
|
|
|
||
|
|
print("✓ Parsing terminé avec succès!")
|
||
|
|
|
||
|
|
def export_to_json(self, output_file: str):
|
||
|
|
"""Exporte la configuration au format JSON OpenConfig"""
|
||
|
|
fw_name = ""
|
||
|
|
deviceconfig = self.root.find(".//deviceconfig/system/hostname")
|
||
|
|
if deviceconfig is not None and deviceconfig.text:
|
||
|
|
fw_name = deviceconfig.text.strip()
|
||
|
|
|
||
|
|
openconfig_data = self.to_openconfig_yang("MODELE", [fw_name])
|
||
|
|
|
||
|
|
with open(output_file, 'w', encoding='utf-8') as f:
|
||
|
|
json.dump(openconfig_data, f, indent=2, ensure_ascii=False)
|
||
|
|
|
||
|
|
print(f"✓ Configuration exportée vers: {output_file}")
|
||
|
|
|
||
|
|
def generate_json_modele(input_file: str, output_file: str):
|
||
|
|
"""Génère le fichier JSON OpenConfig à partir du fichier XML MODELE"""
|
||
|
|
xml_file = Path(input_file)
|
||
|
|
if not xml_file.exists():
|
||
|
|
print(f"✗ Erreur: Le fichier '{xml_file}' n'existe pas")
|
||
|
|
return
|
||
|
|
|
||
|
|
try:
|
||
|
|
parser = ModeleParser(str(xml_file))
|
||
|
|
parser.parse_all()
|
||
|
|
parser.print_summary()
|
||
|
|
parser.export_to_json(output_file)
|
||
|
|
print(f"\n✓ Conversion terminée! Vérifiez le fichier: {output_file}")
|
||
|
|
except Exception as e:
|
||
|
|
print(f"✗ Erreur: {e}")
|
||
|
|
return
|
||
|
|
|
||
|
|
if __name__ == "__main__":
|
||
|
|
import sys
|
||
|
|
if len(sys.argv) != 2:
|
||
|
|
print("Usage: python json_MODELE.py <fichier_config.xml>")
|
||
|
|
sys.exit(1)
|
||
|
|
|
||
|
|
xml_file = sys.argv[1]
|
||
|
|
if not Path(xml_file).exists():
|
||
|
|
print(f"✗ Erreur: Le fichier '{xml_file}' n'existe pas")
|
||
|
|
sys.exit(1)
|
||
|
|
|
||
|
|
try:
|
||
|
|
parser = ModeleParser(xml_file)
|
||
|
|
parser.parse_all()
|
||
|
|
parser.print_summary()
|
||
|
|
output_file = 'output_Modele.json'
|
||
|
|
parser.export_to_json(output_file)
|
||
|
|
print(f"\n✓ Conversion terminée! Vérifiez le fichier: {output_file}")
|
||
|
|
except Exception as e:
|
||
|
|
print(f"✗ Erreur: {e}")
|
||
|
|
sys.exit(1)
|
||
|
|
|
||
|
|
```
|
||
|
|
|
||
|
|
## É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.json_MODELE import generate_json_modele
|
||
|
|
```
|
||
|
|
|
||
|
|
2. Ajoutez la condition correspondante dans le bloc de sélection du type de firewall :
|
||
|
|
```python
|
||
|
|
elif firewall_type == "modele":
|
||
|
|
generate_json_modele(input_data, output_file_json)
|
||
|
|
```
|
||
|
|
|
||
|
|
3. Mettez à jour les instructions textuelles d'usage affichées dans la console si le paramètre saisi est incorrect afin d'inclure `"modele"` dans la liste des choix valides.
|
||
|
|
|
||
|
|
|
||
|
|
## É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. Repérez le composant de sélection (Menu déroulant / ComboBox ou liste de boutons radio) listant les firewalls.
|
||
|
|
3. Ajoutez **`MODELE`** à la liste des choix graphiques.
|
||
|
|
|
||
|
|
> **Important :** faire attention si le script prend en compte un dossier ou un fichier.
|