use serde::{Deserialize, Serialize}; #[derive(Debug, Clone, Deserialize, Serialize)] pub struct Config { pub backend: BackendConfig, pub agent: AgentConfig, pub scan: ScanConfig, pub api: ApiConfig, } #[derive(Debug, Clone, Deserialize, Serialize)] pub struct BackendConfig { pub url: String, pub token: String, } #[derive(Debug, Clone, Deserialize, Serialize)] pub struct AgentConfig { pub id: String, pub hostname: String, } #[derive(Debug, Clone, Deserialize, Serialize)] pub struct ScanConfig { pub subnets: Vec, pub interval_seconds: u64, pub ping_timeout_ms: u64, pub service_timeout_ms: u64, pub concurrency: usize, pub ports: Vec, } #[derive(Debug, Clone, Deserialize, Serialize)] pub struct ApiConfig { pub listen: String, } impl Config { pub fn load(path: &str) -> anyhow::Result { let content = std::fs::read_to_string(path)?; let mut cfg: Config = serde_yaml::from_str(&content)?; cfg.resolve_defaults(); Ok(cfg) } fn resolve_defaults(&mut self) { if self.agent.hostname.is_empty() { self.agent.hostname = detect_hostname(); } if self.agent.id.is_empty() { self.agent.id = format!("scan-{}", self.agent.hostname); } } } fn detect_hostname() -> String { // Lecture directe de /etc/hostname (Linux) std::fs::read_to_string("/etc/hostname") .map(|s| s.trim().to_string()) .unwrap_or_else(|_| "unknown".into()) }