ipwatch
This commit is contained in:
167
backend/app/core/config.py
Executable file
167
backend/app/core/config.py
Executable file
@@ -0,0 +1,167 @@
|
||||
"""
|
||||
Configuration management pour IPWatch
|
||||
Charge et valide le fichier config.yaml
|
||||
"""
|
||||
import yaml
|
||||
from pathlib import Path
|
||||
from typing import Dict, Any, List, Optional
|
||||
from pydantic import BaseModel, Field
|
||||
|
||||
|
||||
class AppConfig(BaseModel):
|
||||
"""Configuration de l'application"""
|
||||
name: str = "IPWatch"
|
||||
version: str = "1.0.0"
|
||||
debug: bool = False
|
||||
|
||||
|
||||
class NetworkConfig(BaseModel):
|
||||
"""Configuration réseau"""
|
||||
cidr: str
|
||||
gateway: Optional[str] = None
|
||||
dns: Optional[List[str]] = None
|
||||
|
||||
|
||||
class ScanConfig(BaseModel):
|
||||
"""Configuration des scans"""
|
||||
ping_interval: int = 60 # secondes
|
||||
ping_count: int = 1 # Nombre de ping par IP
|
||||
port_scan_interval: int = 300 # secondes
|
||||
parallel_pings: int = 50
|
||||
timeout: float = 1.0
|
||||
force_vendor_update: bool = False
|
||||
|
||||
|
||||
class PortsConfig(BaseModel):
|
||||
"""Configuration des ports à scanner"""
|
||||
ranges: List[str] = ["22", "80", "443", "3389", "8080"]
|
||||
protocols: Optional[Dict[int, str]] = None # Mapping port -> protocole
|
||||
|
||||
|
||||
class HistoryConfig(BaseModel):
|
||||
"""Configuration de l'historique"""
|
||||
retention_hours: int = 24
|
||||
|
||||
|
||||
class UIConfig(BaseModel):
|
||||
"""Configuration UI"""
|
||||
offline_transparency: float = 0.5
|
||||
show_mac: bool = True
|
||||
show_vendor: bool = True
|
||||
cell_size: int = 30
|
||||
font_size: int = 10
|
||||
cell_gap: float = 2
|
||||
details_font_size: int = 13
|
||||
details_spacing: int = 2
|
||||
architecture_title_font_size: int = 18
|
||||
|
||||
|
||||
class LinksConfig(BaseModel):
|
||||
"""Configuration des liens"""
|
||||
hardware_bench_url: Optional[str] = None
|
||||
|
||||
|
||||
class ColorsConfig(BaseModel):
|
||||
"""Configuration des couleurs"""
|
||||
free: str = "#75715E"
|
||||
online_known: str = "#A6E22E"
|
||||
online_unknown: str = "#66D9EF"
|
||||
offline_known: str = "#F92672"
|
||||
offline_unknown: str = "#AE81FF"
|
||||
mac_changed: str = "#FD971F"
|
||||
network_device: str = "#1E3A8A"
|
||||
|
||||
|
||||
class OPNsenseConfig(BaseModel):
|
||||
"""Configuration OPNsense API"""
|
||||
enabled: bool = False
|
||||
host: str = ""
|
||||
api_key: str = ""
|
||||
api_secret: str = ""
|
||||
verify_ssl: bool = False
|
||||
protocol: str = "http" # "http" ou "https"
|
||||
|
||||
|
||||
class DatabaseConfig(BaseModel):
|
||||
"""Configuration base de données"""
|
||||
path: str = "./data/db.sqlite"
|
||||
|
||||
|
||||
class SubnetConfig(BaseModel):
|
||||
"""Configuration d'un sous-réseau"""
|
||||
name: str
|
||||
cidr: str
|
||||
start: str
|
||||
end: str
|
||||
description: str
|
||||
|
||||
|
||||
class HostConfig(BaseModel):
|
||||
"""Configuration d'un hôte avec sa localisation"""
|
||||
name: str
|
||||
location: str
|
||||
ip: Optional[str] = None
|
||||
ip_parent: Optional[str] = None
|
||||
ip_enfant: Optional[List[str]] = None
|
||||
|
||||
|
||||
class IPWatchConfig(BaseModel):
|
||||
"""Configuration complète IPWatch"""
|
||||
model_config = {"arbitrary_types_allowed": True}
|
||||
|
||||
app: AppConfig = Field(default_factory=AppConfig)
|
||||
network: NetworkConfig
|
||||
subnets: List[SubnetConfig] = Field(default_factory=list)
|
||||
ip_classes: Dict[str, Any] = Field(default_factory=dict)
|
||||
scan: ScanConfig = Field(default_factory=ScanConfig)
|
||||
ports: PortsConfig = Field(default_factory=PortsConfig)
|
||||
locations: List[str] = Field(default_factory=list)
|
||||
hosts: List[HostConfig] = Field(default_factory=list)
|
||||
history: HistoryConfig = Field(default_factory=HistoryConfig)
|
||||
ui: UIConfig = Field(default_factory=UIConfig)
|
||||
links: LinksConfig = Field(default_factory=LinksConfig)
|
||||
colors: ColorsConfig = Field(default_factory=ColorsConfig)
|
||||
database: DatabaseConfig = Field(default_factory=DatabaseConfig)
|
||||
opnsense: OPNsenseConfig = Field(default_factory=OPNsenseConfig)
|
||||
|
||||
|
||||
class ConfigManager:
|
||||
"""Gestionnaire de configuration singleton"""
|
||||
_instance: Optional['ConfigManager'] = None
|
||||
_config: Optional[IPWatchConfig] = None
|
||||
|
||||
def __new__(cls):
|
||||
if cls._instance is None:
|
||||
cls._instance = super().__new__(cls)
|
||||
return cls._instance
|
||||
|
||||
def load_config(self, config_path: str = "./config.yaml") -> IPWatchConfig:
|
||||
"""Charge la configuration depuis le fichier YAML"""
|
||||
path = Path(config_path)
|
||||
|
||||
if not path.exists():
|
||||
raise FileNotFoundError(f"Fichier de configuration non trouvé: {config_path}")
|
||||
|
||||
with open(path, 'r', encoding='utf-8') as f:
|
||||
yaml_data = yaml.safe_load(f)
|
||||
|
||||
self._config = IPWatchConfig(**yaml_data)
|
||||
self._config_path = config_path
|
||||
return self._config
|
||||
|
||||
def reload_config(self) -> IPWatchConfig:
|
||||
"""Recharge la configuration depuis le fichier"""
|
||||
if not hasattr(self, '_config_path'):
|
||||
self._config_path = "./config.yaml"
|
||||
return self.load_config(self._config_path)
|
||||
|
||||
@property
|
||||
def config(self) -> IPWatchConfig:
|
||||
"""Retourne la configuration actuelle"""
|
||||
if self._config is None:
|
||||
raise RuntimeError("Configuration non chargée. Appelez load_config() d'abord.")
|
||||
return self._config
|
||||
|
||||
|
||||
# Instance globale
|
||||
config_manager = ConfigManager()
|
||||
Reference in New Issue
Block a user