mirror of
https://github.com/DaLaw2/NetGuardia.git
synced 2026-08-24 14:10:28 +09:00
refactor(style): sweep variant call sites — struct → tuple syntax
Follow-up to 3acd2eb error/log variant redesign. Updates 15 call sites across adapter/persistence, telegram, correlation, detection, notification, SOAR, audit, and Suricata to match the new tuple-style traceable!/loggable! variant signatures. No behavior change; net -25 lines. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
3acd2ebf96
commit
c4ac70fbe1
@ -26,7 +26,7 @@ impl AccessControlPort for EbpfAccessControlAdapter {
|
||||
async fn block_ip(&self, ip: &str) -> Result<(), Error> {
|
||||
let addr: IpAddr = ip
|
||||
.parse()
|
||||
.map_err(|_| Error::from(EbpfError::InvalidIpAddress { ip: ip.to_string() }))?;
|
||||
.map_err(|_| Error::from(EbpfError::InvalidIpAddress(ip.to_string())))?;
|
||||
match addr {
|
||||
IpAddr::V4(v4) => {
|
||||
let socket = SocketAddrV4::new(v4, 0);
|
||||
@ -46,7 +46,7 @@ impl AccessControlPort for EbpfAccessControlAdapter {
|
||||
async fn unblock_ip(&self, ip: &str) -> Result<(), Error> {
|
||||
let addr: IpAddr = ip
|
||||
.parse()
|
||||
.map_err(|_| Error::from(EbpfError::InvalidIpAddress { ip: ip.to_string() }))?;
|
||||
.map_err(|_| Error::from(EbpfError::InvalidIpAddress(ip.to_string())))?;
|
||||
match addr {
|
||||
IpAddr::V4(v4) => {
|
||||
let socket = SocketAddrV4::new(v4, 0);
|
||||
|
||||
@ -620,10 +620,7 @@ impl Database {
|
||||
)
|
||||
.map_err(|e| -> Error {
|
||||
if e.to_string().contains("UNIQUE constraint") {
|
||||
DatabaseError::UserAlreadyExists {
|
||||
username: username.to_string(),
|
||||
}
|
||||
.into()
|
||||
DatabaseError::UserAlreadyExists(username.to_string()).into()
|
||||
} else {
|
||||
e.into()
|
||||
}
|
||||
|
||||
@ -130,10 +130,7 @@ impl TelegramAdapter {
|
||||
if status.as_u16() == 401 || status.as_u16() == 403 {
|
||||
let body = resp.text().await.unwrap_or_default();
|
||||
if body.contains("chat not found") || body.contains("CHAT_NOT_FOUND") {
|
||||
return Err(NotificationError::TelegramChatNotFound {
|
||||
chat_id: chat_id.to_string(),
|
||||
}
|
||||
.into());
|
||||
return Err(NotificationError::TelegramChatNotFound(chat_id.to_string()).into());
|
||||
}
|
||||
return Err(NotificationError::TelegramAuthError.into());
|
||||
}
|
||||
@ -156,10 +153,7 @@ impl TelegramAdapter {
|
||||
sleep(Duration::from_secs(retry_after)).await;
|
||||
continue;
|
||||
} else {
|
||||
return Err(NotificationError::TelegramRateLimited {
|
||||
retry_after_secs: retry_after,
|
||||
}
|
||||
.into());
|
||||
return Err(NotificationError::TelegramRateLimited(retry_after).into());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -74,11 +74,11 @@ impl BotnetDetector {
|
||||
};
|
||||
|
||||
if let Some(unique_sources) = should_alert {
|
||||
log!(DetectionLog::BotnetDetected {
|
||||
dst_ip: key.clone(),
|
||||
log!(DetectionLog::BotnetDetected(
|
||||
key.clone(),
|
||||
unique_sources,
|
||||
window_secs: BOTNET_WINDOW_SECS,
|
||||
});
|
||||
BOTNET_WINDOW_SECS,
|
||||
));
|
||||
|
||||
// source_ip = the latest attacker; dest_ip = the victim being targeted.
|
||||
// SOAR blocks source_ip, so we must NOT put the victim here.
|
||||
|
||||
@ -72,7 +72,7 @@ impl CorrelationEngine {
|
||||
fn cleanup(&self) {
|
||||
let removed = self.botnet.cleanup() + self.scan.cleanup() + self.lateral.cleanup();
|
||||
if removed > 0 {
|
||||
log!(DetectionLog::CorrelationCleanup { removed });
|
||||
log!(DetectionLog::CorrelationCleanup(removed));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -74,11 +74,11 @@ impl LateralMovementDetector {
|
||||
};
|
||||
|
||||
if let Some(unique_dests) = should_alert {
|
||||
log!(DetectionLog::LateralMovementDetected {
|
||||
src_ip: key.clone(),
|
||||
log!(DetectionLog::LateralMovementDetected(
|
||||
key.clone(),
|
||||
unique_dests,
|
||||
window_secs: LATERAL_WINDOW_SECS,
|
||||
});
|
||||
LATERAL_WINDOW_SECS,
|
||||
));
|
||||
|
||||
let event = DetectionEvent {
|
||||
source: DetectionSource::Correlation,
|
||||
|
||||
@ -72,11 +72,7 @@ impl ScanDetector {
|
||||
};
|
||||
|
||||
if let Some((unique_ports, last_dst_ip)) = should_alert {
|
||||
log!(DetectionLog::ScanDetected {
|
||||
src_ip: key.clone(),
|
||||
unique_ports,
|
||||
window_secs: SCAN_WINDOW_SECS,
|
||||
});
|
||||
log!(DetectionLog::ScanDetected(key.clone(), unique_ports, SCAN_WINDOW_SECS,));
|
||||
|
||||
let event = DetectionEvent {
|
||||
source: DetectionSource::Correlation,
|
||||
|
||||
@ -126,13 +126,13 @@ impl BeaconingDetector {
|
||||
// Phase 2: selective write-lock only for entries that need last_alerted update.
|
||||
for (key, cv, count) in alerts {
|
||||
let (src_ip, dst_ip, dst_port) = &key;
|
||||
log!(DetectionLog::BeaconingDetected {
|
||||
src_ip: src_ip.clone(),
|
||||
dst_ip: dst_ip.clone(),
|
||||
dst_port: *dst_port,
|
||||
log!(DetectionLog::BeaconingDetected(
|
||||
src_ip.clone(),
|
||||
dst_ip.clone(),
|
||||
*dst_port,
|
||||
cv,
|
||||
count,
|
||||
});
|
||||
));
|
||||
|
||||
let event = DetectionEvent {
|
||||
source: DetectionSource::Beaconing,
|
||||
|
||||
@ -104,10 +104,7 @@ impl DetectionOrchestrator {
|
||||
entry.sources.push(event.source.clone());
|
||||
}
|
||||
}
|
||||
log!(DetectionLog::DetectionDeduplicated {
|
||||
source_ip: event.source_ip,
|
||||
attack_type: event.attack_type,
|
||||
});
|
||||
log!(DetectionLog::DetectionDeduplicated(event.source_ip, event.attack_type,));
|
||||
return;
|
||||
}
|
||||
|
||||
@ -115,15 +112,15 @@ impl DetectionOrchestrator {
|
||||
let threat_event = self.enrich(&event).await;
|
||||
let sources = vec![event.source.clone()];
|
||||
|
||||
log!(DetectionLog::DetectionEmitted {
|
||||
source_ip: event.source_ip.clone(),
|
||||
attack_type: event.attack_type.clone(),
|
||||
confidence: event.confidence,
|
||||
ae_score: event.ae_score,
|
||||
anomaly_score: event.anomaly_score,
|
||||
c2_score: event.c2_score,
|
||||
sources_count: sources.len(),
|
||||
});
|
||||
log!(DetectionLog::DetectionEmitted(
|
||||
event.source_ip.clone(),
|
||||
event.attack_type.clone(),
|
||||
event.confidence,
|
||||
event.ae_score,
|
||||
event.anomaly_score,
|
||||
event.c2_score,
|
||||
sources.len(),
|
||||
));
|
||||
|
||||
// Record dedup entry (LRU-bounded)
|
||||
self.dedup.put(
|
||||
|
||||
@ -77,19 +77,18 @@ impl NotificationService {
|
||||
/// Send a test email using current SMTP config.
|
||||
pub fn test_smtp(&self) -> Result<String, Error> {
|
||||
let smtp_client = SmtpClient::from_database(self.repo.as_ref(), Some(self.secrets.as_ref()))?;
|
||||
let smtp = smtp_client.ok_or_else(|| MiscError::ValidationError {
|
||||
message: "SMTP not configured. Set smtp_host, smtp_port, smtp_username, smtp_password first. \
|
||||
If smtp_username is not an email address, also set smtp_sender."
|
||||
.into(),
|
||||
let smtp = smtp_client.ok_or_else(|| {
|
||||
MiscError::ValidationError(
|
||||
"SMTP not configured. Set smtp_host, smtp_port, smtp_username, smtp_password first. \
|
||||
If smtp_username is not an email address, also set smtp_sender.",
|
||||
)
|
||||
})?;
|
||||
|
||||
let recipient = self
|
||||
.repo
|
||||
.get_setting("smtp_recipient")?
|
||||
.filter(|r| !r.is_empty())
|
||||
.ok_or_else(|| MiscError::ValidationError {
|
||||
message: "No smtp_recipient configured.".into(),
|
||||
})?;
|
||||
.ok_or_else(|| MiscError::ValidationError("No smtp_recipient configured."))?;
|
||||
|
||||
smtp.send(
|
||||
&recipient,
|
||||
|
||||
@ -138,10 +138,10 @@ impl SoarEngine {
|
||||
action_order: order,
|
||||
action_type: atype,
|
||||
params: serde_json::from_str(¶ms_str).unwrap_or_else(|e| {
|
||||
log!(SoarLog::PlaybookError {
|
||||
name: pb.name.clone(),
|
||||
error: format!("Malformed action params JSON: {}", e),
|
||||
});
|
||||
log!(SoarLog::PlaybookError(
|
||||
pb.name.clone(),
|
||||
format!("Malformed action params JSON: {e}"),
|
||||
));
|
||||
Value::Object(Default::default())
|
||||
}),
|
||||
});
|
||||
|
||||
@ -162,10 +162,10 @@ impl System {
|
||||
log!(MLLog::ModelsLoaded(
|
||||
self.app_services.ml_models.get_model_info("classifier")
|
||||
));
|
||||
log!(MLLog::ConfigLoaded {
|
||||
features: self.inference_config.num_ae_features(),
|
||||
attacks: self.inference_config.num_attack_types()
|
||||
});
|
||||
log!(MLLog::ConfigLoaded(
|
||||
self.inference_config.num_ae_features(),
|
||||
self.inference_config.num_attack_types(),
|
||||
));
|
||||
|
||||
// aya_log_init + attach_xdp only make sense if the eBPF objects
|
||||
// loaded. When eBPF is unavailable we skip both; the rest of the
|
||||
|
||||
@ -32,7 +32,7 @@ impl AuditLogger {
|
||||
this.handle_audit_event(&event);
|
||||
}
|
||||
Err(RecvError::Lagged(n)) => {
|
||||
log!(AuditLog::AuditLagged { count: n });
|
||||
log!(AuditLog::AuditLagged(n));
|
||||
}
|
||||
Err(RecvError::Closed) => {
|
||||
log!(AuditLog::AuditChannelClosed);
|
||||
@ -55,7 +55,7 @@ impl AuditLogger {
|
||||
this.handle_drift_event(&event);
|
||||
}
|
||||
Err(RecvError::Lagged(n)) => {
|
||||
log!(AuditLog::AuditLagged { count: n });
|
||||
log!(AuditLog::AuditLagged(n));
|
||||
}
|
||||
Err(RecvError::Closed) => {
|
||||
log!(AuditLog::AuditChannelClosed);
|
||||
@ -71,18 +71,15 @@ impl AuditLogger {
|
||||
|
||||
fn handle_audit_event(&self, event: &AuditEvent) {
|
||||
// Always emit a structured log line
|
||||
log!(AuditLog::AuditEvent {
|
||||
actor: event.actor.clone(),
|
||||
action: event.action.clone()
|
||||
});
|
||||
log!(AuditLog::AuditEvent(event.actor.clone(), event.action.clone(),));
|
||||
|
||||
// Attempt DB insert; on failure, log a warning but do not panic
|
||||
if let Err(e) = self.db.insert_audit_log(&event.actor, &event.action, &event.detail) {
|
||||
log!(AuditLog::AuditDbWriteFailed {
|
||||
error: e.to_string(),
|
||||
actor: event.actor.clone(),
|
||||
action: event.action.clone()
|
||||
});
|
||||
log!(AuditLog::AuditDbWriteFailed(
|
||||
e.to_string(),
|
||||
event.actor.clone(),
|
||||
event.action.clone(),
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
@ -93,12 +90,10 @@ impl AuditLogger {
|
||||
})
|
||||
.to_string();
|
||||
|
||||
log!(AuditLog::AuditDriftEvent {
|
||||
count: event.drifted_features.len()
|
||||
});
|
||||
log!(AuditLog::AuditDriftEvent(event.drifted_features.len()));
|
||||
|
||||
if let Err(e) = self.db.insert_audit_log("system", "ml_drift_detected", &detail) {
|
||||
log!(AuditLog::AuditDriftDbWriteFailed { error: e.to_string() });
|
||||
log!(AuditLog::AuditDriftDbWriteFailed(e.to_string()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -87,25 +87,22 @@ impl SuricataManager {
|
||||
|
||||
let pid = child.id().unwrap_or(0);
|
||||
*self.health.write() = SuricataHealth::Running { pid };
|
||||
log!(SuricataLog::Started { pid });
|
||||
log!(SuricataLog::Started(pid));
|
||||
|
||||
tokio::select! {
|
||||
exit = child.wait() => {
|
||||
let reason = match exit {
|
||||
Ok(status) => format!("exited with {}", status),
|
||||
Err(e) => format!("wait error: {}", e),
|
||||
Ok(status) => format!("exited with {status}"),
|
||||
Err(e) => format!("wait error: {e}"),
|
||||
};
|
||||
if self.config.suricata.auto_restart_on_crash {
|
||||
let backoff = self.config.suricata.restart_backoff_secs;
|
||||
log!(SuricataLog::CrashedRestartPending {
|
||||
reason: reason.clone(),
|
||||
backoff,
|
||||
});
|
||||
log!(SuricataLog::CrashedRestartPending(reason.clone(), backoff));
|
||||
*self.health.write() = SuricataHealth::Stopped { reason };
|
||||
sleep(Duration::from_secs(backoff)).await;
|
||||
continue;
|
||||
} else {
|
||||
log!(SuricataLog::Stopped { reason: reason.clone() });
|
||||
log!(SuricataLog::Stopped(reason.clone()));
|
||||
*self.health.write() = SuricataHealth::Stopped { reason };
|
||||
return;
|
||||
}
|
||||
@ -138,11 +135,11 @@ impl SuricataManager {
|
||||
let sc = &self.config.suricata;
|
||||
let iface = &self.config.network.ingress_ifname;
|
||||
|
||||
log!(SuricataLog::Spawning {
|
||||
binary: sc.binary_path.clone(),
|
||||
config: sc.config_path.clone(),
|
||||
iface: iface.clone(),
|
||||
});
|
||||
log!(SuricataLog::Spawning(
|
||||
sc.binary_path.clone(),
|
||||
sc.config_path.clone(),
|
||||
iface.clone(),
|
||||
));
|
||||
|
||||
let mut cmd = Command::new(&sc.binary_path);
|
||||
cmd.arg("-c")
|
||||
|
||||
@ -63,7 +63,7 @@ impl SuricataMonitor {
|
||||
// Wait until the file exists — Suricata spawns asynchronously and
|
||||
// may take a few seconds to create eve.json.
|
||||
if !Path::new(&path).exists() {
|
||||
log!(SuricataLog::MonitorWaitingForFile { path: path.clone() });
|
||||
log!(SuricataLog::MonitorWaitingForFile(path.clone()));
|
||||
while !Path::new(&path).exists() {
|
||||
sleep(FILE_WAIT_INTERVAL).await;
|
||||
}
|
||||
@ -79,7 +79,7 @@ impl SuricataMonitor {
|
||||
// Seek to end so we only see new content from this point. Suricata
|
||||
// writes a large volume at startup that we don't want to replay.
|
||||
let mut pos: u64 = file.seek(SeekFrom::End(0)).await.unwrap_or_default();
|
||||
log!(SuricataLog::MonitorAttached { path: path.clone() });
|
||||
log!(SuricataLog::MonitorAttached(path.clone()));
|
||||
|
||||
let mut reader = BufReader::new(file);
|
||||
let mut line = String::new();
|
||||
@ -161,12 +161,12 @@ impl SuricataMonitor {
|
||||
_ => 0.50,
|
||||
};
|
||||
|
||||
log!(SuricataLog::AlertForwarded {
|
||||
log!(SuricataLog::AlertForwarded(
|
||||
sid,
|
||||
src: src_ip.clone(),
|
||||
dst: dest_ip.clone(),
|
||||
src_ip.clone(),
|
||||
dest_ip.clone(),
|
||||
signature,
|
||||
});
|
||||
));
|
||||
|
||||
Some(DetectionEvent {
|
||||
source: DetectionSource::Suricata,
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user