spawn_access_control/
security_analyzer.rsuse crate::audit::AuditLogEntry;
use crate::audit::ActionResult;
use chrono::{DateTime, Utc, Duration};
use std::collections::HashMap;
use serde::{Serialize, Deserialize};
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct SuspiciousPattern {
pub pattern_type: String,
pub confidence: f64,
pub first_seen: DateTime<Utc>,
pub last_seen: DateTime<Utc>,
pub occurrences: u32,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct SecurityReport {
pub timestamp: DateTime<Utc>,
pub suspicious_patterns: HashMap<String, Vec<SuspiciousPattern>>,
pub recent_failures: usize,
pub risk_level: RiskLevel,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub enum RiskLevel {
Low,
Medium,
High,
Critical,
}
#[derive(Debug, Clone)]
pub struct SecurityAnalyzer {
#[allow(dead_code)]
access_history: Vec<AuditLogEntry>,
suspicious_patterns: HashMap<String, Vec<SuspiciousPattern>>,
config: SecurityConfig,
}
impl SecurityAnalyzer {
pub fn new(config: SecurityConfig) -> Self {
Self {
access_history: Vec::new(),
suspicious_patterns: HashMap::new(),
config,
}
}
pub fn analyze_recent_activity(&self, accesses: &[AuditLogEntry]) -> SecurityReport {
let now = Utc::now();
let recent_window = self.config.recent_window;
let recent_failures = accesses.iter()
.filter(|entry| (now - entry.timestamp).num_minutes() < recent_window.num_minutes())
.filter(|entry| matches!(entry.result, ActionResult::Failure { .. }))
.count();
SecurityReport {
timestamp: now,
suspicious_patterns: self.suspicious_patterns.clone(),
recent_failures,
risk_level: self.calculate_risk_level(recent_failures),
}
}
fn calculate_risk_level(&self, recent_failures: usize) -> RiskLevel {
if recent_failures > 5 {
RiskLevel::Critical
} else if recent_failures > 2 {
RiskLevel::High
} else if recent_failures > 0 {
RiskLevel::Medium
} else {
RiskLevel::Low
}
}
}
#[derive(Debug, Clone)]
pub struct SecurityConfig {
pub recent_window: Duration,
pub max_failures: u32,
pub min_suspicious_score: f64,
}
impl Default for SecurityConfig {
fn default() -> Self {
Self {
recent_window: Duration::minutes(30),
max_failures: 5,
min_suspicious_score: 0.7,
}
}
}