pulseengine_mcp_auth/monitoring/
security_monitor.rs

1//! Security Monitoring and Dashboard System
2//!
3//! This module provides comprehensive security monitoring capabilities including
4//! real-time metrics, alerting, threat detection, and security dashboards.
5
6use crate::{
7    AuthContext,
8    security::{SecuritySeverity, SecurityViolation, SecurityViolationType},
9    session::Session,
10};
11use serde::{Deserialize, Serialize};
12use std::collections::{HashMap, VecDeque};
13use std::sync::Arc;
14use thiserror::Error;
15use tokio::sync::RwLock;
16use tracing::{debug, error, info, warn};
17use uuid::Uuid;
18
19/// Errors that can occur during security monitoring
20#[derive(Debug, Error)]
21pub enum MonitoringError {
22    #[error("Alert not found: {alert_id}")]
23    AlertNotFound { alert_id: String },
24
25    #[error("Metric not found: {metric_name}")]
26    MetricNotFound { metric_name: String },
27
28    #[error("Configuration error: {reason}")]
29    ConfigError { reason: String },
30
31    #[error("Storage error: {0}")]
32    StorageError(String),
33
34    #[error("Serialization error: {0}")]
35    SerializationError(String),
36}
37
38/// Security event types for monitoring
39#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
40pub enum SecurityEventType {
41    /// Authentication events
42    AuthSuccess,
43    AuthFailure,
44    InvalidApiKey,
45    ExpiredToken,
46
47    /// Session events
48    SessionCreated,
49    SessionExpired,
50    SessionTerminated,
51    MaxSessionsExceeded,
52
53    /// Security violations
54    InjectionAttempt,
55    SizeLimit,
56    RateLimit,
57    UnauthorizedAccess,
58
59    /// Permission events
60    PermissionDenied,
61    RoleEscalation,
62
63    /// System events
64    SystemError,
65    ConfigChange,
66}
67
68/// Security event details
69#[derive(Debug, Clone, Serialize, Deserialize)]
70pub struct SecurityEvent {
71    /// Unique event identifier
72    pub event_id: String,
73
74    /// Event type
75    pub event_type: SecurityEventType,
76
77    /// Event severity
78    pub severity: SecuritySeverity,
79
80    /// Event timestamp
81    pub timestamp: chrono::DateTime<chrono::Utc>,
82
83    /// User/session context
84    pub user_id: Option<String>,
85    pub session_id: Option<String>,
86    pub api_key_id: Option<String>,
87
88    /// Request context
89    pub client_ip: Option<String>,
90    pub user_agent: Option<String>,
91    pub method: Option<String>,
92
93    /// Event details
94    pub description: String,
95    pub metadata: HashMap<String, String>,
96
97    /// Geographic information (if available)
98    pub country: Option<String>,
99    pub city: Option<String>,
100}
101
102impl SecurityEvent {
103    /// Create a new security event
104    pub fn new(
105        event_type: SecurityEventType,
106        severity: SecuritySeverity,
107        description: String,
108    ) -> Self {
109        Self {
110            event_id: Uuid::new_v4().to_string(),
111            event_type,
112            severity,
113            timestamp: chrono::Utc::now(),
114            user_id: None,
115            session_id: None,
116            api_key_id: None,
117            client_ip: None,
118            user_agent: None,
119            method: None,
120            description,
121            metadata: HashMap::new(),
122            country: None,
123            city: None,
124        }
125    }
126
127    /// Add user context to event
128    pub fn with_user_context(mut self, auth_context: &AuthContext) -> Self {
129        self.user_id = auth_context.user_id.clone();
130        self.api_key_id = auth_context.api_key_id.clone();
131        self
132    }
133
134    /// Add session context to event
135    pub fn with_session_context(mut self, session: &Session) -> Self {
136        self.session_id = Some(session.session_id.clone());
137        self.user_id = Some(session.user_id.clone());
138        self.client_ip = session.client_ip.clone();
139        self.user_agent = session.user_agent.clone();
140        self
141    }
142
143    /// Add request context to event
144    pub fn with_request_context(
145        mut self,
146        client_ip: Option<String>,
147        user_agent: Option<String>,
148        method: Option<String>,
149    ) -> Self {
150        self.client_ip = client_ip;
151        self.user_agent = user_agent;
152        self.method = method;
153        self
154    }
155
156    /// Add metadata to event
157    pub fn with_metadata(mut self, key: String, value: String) -> Self {
158        self.metadata.insert(key, value);
159        self
160    }
161}
162
163/// Security metrics aggregated over time
164#[derive(Debug, Clone, Serialize, Deserialize)]
165pub struct SecurityMetrics {
166    /// Time period for these metrics
167    pub period_start: chrono::DateTime<chrono::Utc>,
168    pub period_end: chrono::DateTime<chrono::Utc>,
169
170    /// Authentication metrics
171    pub auth_success_count: u64,
172    pub auth_failure_count: u64,
173    pub invalid_api_key_count: u64,
174    pub expired_token_count: u64,
175
176    /// Session metrics
177    pub sessions_created: u64,
178    pub sessions_expired: u64,
179    pub sessions_terminated: u64,
180    pub active_sessions: u64,
181
182    /// Security violation metrics
183    pub injection_attempts: u64,
184    pub size_limit_violations: u64,
185    pub rate_limit_violations: u64,
186    pub unauthorized_access_attempts: u64,
187
188    /// Permission metrics
189    pub permission_denied_count: u64,
190    pub role_escalation_attempts: u64,
191
192    /// Top source IPs by event count
193    pub top_source_ips: Vec<(String, u64)>,
194
195    /// Top user agents by event count
196    pub top_user_agents: Vec<(String, u64)>,
197
198    /// Top methods by event count
199    pub top_methods: Vec<(String, u64)>,
200
201    /// Geographic distribution
202    pub country_distribution: HashMap<String, u64>,
203}
204
205impl Default for SecurityMetrics {
206    fn default() -> Self {
207        let now = chrono::Utc::now();
208        Self {
209            period_start: now,
210            period_end: now,
211            auth_success_count: 0,
212            auth_failure_count: 0,
213            invalid_api_key_count: 0,
214            expired_token_count: 0,
215            sessions_created: 0,
216            sessions_expired: 0,
217            sessions_terminated: 0,
218            active_sessions: 0,
219            injection_attempts: 0,
220            size_limit_violations: 0,
221            rate_limit_violations: 0,
222            unauthorized_access_attempts: 0,
223            permission_denied_count: 0,
224            role_escalation_attempts: 0,
225            top_source_ips: Vec::new(),
226            top_user_agents: Vec::new(),
227            top_methods: Vec::new(),
228            country_distribution: HashMap::new(),
229        }
230    }
231}
232
233/// Security alert configuration
234#[derive(Debug, Clone, Serialize, Deserialize)]
235pub struct AlertRule {
236    /// Unique alert rule identifier
237    pub rule_id: String,
238
239    /// Alert rule name
240    pub name: String,
241
242    /// Alert description
243    pub description: String,
244
245    /// Event types to monitor
246    pub event_types: Vec<SecurityEventType>,
247
248    /// Minimum severity level
249    pub min_severity: SecuritySeverity,
250
251    /// Threshold for triggering alert
252    pub threshold: AlertThreshold,
253
254    /// Time window for threshold evaluation
255    pub time_window: chrono::Duration,
256
257    /// Alert cooldown period
258    pub cooldown: chrono::Duration,
259
260    /// Whether this rule is enabled
261    pub enabled: bool,
262
263    /// Alert actions to take
264    pub actions: Vec<AlertAction>,
265}
266
267/// Alert threshold configurations
268#[derive(Debug, Clone, Serialize, Deserialize)]
269pub enum AlertThreshold {
270    /// Count threshold (e.g., more than 10 events)
271    Count(u64),
272
273    /// Rate threshold (e.g., more than 5 events per minute)
274    Rate {
275        count: u64,
276        duration: chrono::Duration,
277    },
278
279    /// Percentage threshold (e.g., more than 50% failures)
280    Percentage {
281        numerator_events: Vec<SecurityEventType>,
282        denominator_events: Vec<SecurityEventType>,
283        threshold: f64,
284    },
285}
286
287/// Actions to take when alert is triggered
288#[derive(Debug, Clone, Serialize, Deserialize)]
289pub enum AlertAction {
290    /// Log the alert
291    Log { level: String },
292
293    /// Send email notification
294    Email { recipients: Vec<String> },
295
296    /// Send webhook notification
297    Webhook {
298        url: String,
299        payload_template: String,
300    },
301
302    /// Block IP address
303    BlockIp { duration: chrono::Duration },
304
305    /// Disable user
306    DisableUser { user_id: String },
307
308    /// Rate limit user
309    RateLimit {
310        user_id: String,
311        limit: u32,
312        duration: chrono::Duration,
313    },
314}
315
316/// Active security alert
317#[derive(Debug, Clone, Serialize, Deserialize)]
318pub struct SecurityAlert {
319    /// Unique alert identifier
320    pub alert_id: String,
321
322    /// Alert rule that triggered this alert
323    pub rule_id: String,
324
325    /// Alert rule name
326    pub rule_name: String,
327
328    /// Alert triggered timestamp
329    pub triggered_at: chrono::DateTime<chrono::Utc>,
330
331    /// Alert resolved timestamp (if resolved)
332    pub resolved_at: Option<chrono::DateTime<chrono::Utc>>,
333
334    /// Alert severity
335    pub severity: SecuritySeverity,
336
337    /// Alert description
338    pub description: String,
339
340    /// Events that triggered this alert
341    pub triggering_events: Vec<String>, // Event IDs
342
343    /// Alert metadata
344    pub metadata: HashMap<String, String>,
345
346    /// Actions taken for this alert
347    pub actions_taken: Vec<String>,
348}
349
350/// Configuration for security monitoring
351#[derive(Debug, Clone)]
352pub struct SecurityMonitorConfig {
353    /// Maximum number of events to keep in memory
354    pub max_events_in_memory: usize,
355
356    /// Maximum number of alerts to keep in memory
357    pub max_alerts_in_memory: usize,
358
359    /// How long to keep events in memory
360    pub event_retention: chrono::Duration,
361
362    /// How long to keep alerts in memory
363    pub alert_retention: chrono::Duration,
364
365    /// Metrics aggregation interval
366    pub metrics_interval: chrono::Duration,
367
368    /// Enable geographic IP lookup
369    pub enable_geolocation: bool,
370
371    /// Enable real-time monitoring
372    pub enable_realtime: bool,
373
374    /// Enable alert processing
375    pub enable_alerts: bool,
376}
377
378impl Default for SecurityMonitorConfig {
379    fn default() -> Self {
380        Self {
381            max_events_in_memory: 10000,
382            max_alerts_in_memory: 1000,
383            event_retention: chrono::Duration::days(7),
384            alert_retention: chrono::Duration::days(30),
385            metrics_interval: chrono::Duration::minutes(5),
386            enable_geolocation: false,
387            enable_realtime: true,
388            enable_alerts: true,
389        }
390    }
391}
392
393/// Security monitoring and dashboard system
394pub struct SecurityMonitor {
395    config: SecurityMonitorConfig,
396    events: Arc<RwLock<VecDeque<SecurityEvent>>>,
397    alerts: Arc<RwLock<Vec<SecurityAlert>>>,
398    alert_rules: Arc<RwLock<Vec<AlertRule>>>,
399    metrics_cache: Arc<RwLock<HashMap<String, SecurityMetrics>>>,
400    last_cleanup: Arc<RwLock<chrono::DateTime<chrono::Utc>>>,
401}
402
403impl SecurityMonitor {
404    /// Create a new security monitor
405    pub fn new(config: SecurityMonitorConfig) -> Self {
406        Self {
407            config,
408            events: Arc::new(RwLock::new(VecDeque::new())),
409            alerts: Arc::new(RwLock::new(Vec::new())),
410            alert_rules: Arc::new(RwLock::new(Vec::new())),
411            metrics_cache: Arc::new(RwLock::new(HashMap::new())),
412            last_cleanup: Arc::new(RwLock::new(chrono::Utc::now())),
413        }
414    }
415
416    /// Create with default configuration
417    pub fn with_default_config() -> Self {
418        Self::new(SecurityMonitorConfig::default())
419    }
420
421    /// Record a security event
422    pub async fn record_event(&self, event: SecurityEvent) {
423        debug!("Recording security event: {:?}", event.event_type);
424
425        let mut events = self.events.write().await;
426        events.push_back(event.clone());
427
428        // Enforce memory limits
429        while events.len() > self.config.max_events_in_memory {
430            events.pop_front();
431        }
432
433        drop(events);
434
435        // Process alerts if enabled
436        if self.config.enable_alerts {
437            self.process_alerts_for_event(&event).await;
438        }
439
440        // Update real-time metrics
441        if self.config.enable_realtime {
442            self.update_realtime_metrics(&event).await;
443        }
444    }
445
446    /// Record a security violation
447    pub async fn record_violation(&self, violation: &SecurityViolation) {
448        let event_type = match violation.violation_type {
449            SecurityViolationType::InjectionAttempt => SecurityEventType::InjectionAttempt,
450            SecurityViolationType::SizeLimit => SecurityEventType::SizeLimit,
451            SecurityViolationType::RateLimit => SecurityEventType::RateLimit,
452            SecurityViolationType::UnauthorizedMethod => SecurityEventType::UnauthorizedAccess,
453            _ => SecurityEventType::SystemError,
454        };
455
456        let mut event = SecurityEvent::new(
457            event_type,
458            violation.severity.clone(),
459            violation.description.clone(),
460        );
461
462        if let Some(field) = &violation.field {
463            event = event.with_metadata("field".to_string(), field.clone());
464        }
465
466        if let Some(value) = &violation.value {
467            event = event.with_metadata("value".to_string(), value.clone());
468        }
469
470        self.record_event(event).await;
471    }
472
473    /// Record authentication event
474    pub async fn record_auth_event(
475        &self,
476        event_type: SecurityEventType,
477        auth_context: Option<&AuthContext>,
478        client_ip: Option<String>,
479        user_agent: Option<String>,
480        description: String,
481    ) {
482        let severity = match event_type {
483            SecurityEventType::AuthFailure | SecurityEventType::InvalidApiKey => {
484                SecuritySeverity::Medium
485            }
486            SecurityEventType::ExpiredToken => SecuritySeverity::Low,
487            SecurityEventType::AuthSuccess => SecuritySeverity::Low,
488            _ => SecuritySeverity::Medium,
489        };
490
491        let mut event = SecurityEvent::new(event_type, severity, description)
492            .with_request_context(client_ip, user_agent, None);
493
494        if let Some(auth) = auth_context {
495            event = event.with_user_context(auth);
496        }
497
498        self.record_event(event).await;
499    }
500
501    /// Record session event
502    pub async fn record_session_event(
503        &self,
504        event_type: SecurityEventType,
505        session: &Session,
506        description: String,
507    ) {
508        let severity = match event_type {
509            SecurityEventType::MaxSessionsExceeded => SecuritySeverity::High,
510            SecurityEventType::SessionExpired => SecuritySeverity::Low,
511            _ => SecuritySeverity::Low,
512        };
513
514        let event =
515            SecurityEvent::new(event_type, severity, description).with_session_context(session);
516
517        self.record_event(event).await;
518    }
519
520    /// Get recent security events
521    pub async fn get_recent_events(&self, limit: Option<usize>) -> Vec<SecurityEvent> {
522        let events = self.events.read().await;
523        let limit = limit.unwrap_or(100);
524
525        events.iter().rev().take(limit).cloned().collect()
526    }
527
528    /// Get events by type
529    pub async fn get_events_by_type(
530        &self,
531        event_type: SecurityEventType,
532        since: Option<chrono::DateTime<chrono::Utc>>,
533        limit: Option<usize>,
534    ) -> Vec<SecurityEvent> {
535        let events = self.events.read().await;
536        let since = since.unwrap_or_else(|| chrono::Utc::now() - chrono::Duration::hours(24));
537        let limit = limit.unwrap_or(1000);
538
539        events
540            .iter()
541            .filter(|e| e.event_type == event_type && e.timestamp >= since)
542            .rev()
543            .take(limit)
544            .cloned()
545            .collect()
546    }
547
548    /// Get events by user
549    pub async fn get_events_by_user(
550        &self,
551        user_id: &str,
552        since: Option<chrono::DateTime<chrono::Utc>>,
553        limit: Option<usize>,
554    ) -> Vec<SecurityEvent> {
555        let events = self.events.read().await;
556        let since = since.unwrap_or_else(|| chrono::Utc::now() - chrono::Duration::hours(24));
557        let limit = limit.unwrap_or(1000);
558
559        events
560            .iter()
561            .filter(|e| {
562                e.user_id.as_ref().map(|u| u == user_id).unwrap_or(false) && e.timestamp >= since
563            })
564            .rev()
565            .take(limit)
566            .cloned()
567            .collect()
568    }
569
570    /// Generate security metrics for a time period
571    pub async fn generate_metrics(
572        &self,
573        start: chrono::DateTime<chrono::Utc>,
574        end: chrono::DateTime<chrono::Utc>,
575    ) -> SecurityMetrics {
576        let events = self.events.read().await;
577        let mut metrics = SecurityMetrics {
578            period_start: start,
579            period_end: end,
580            ..Default::default()
581        };
582
583        let mut ip_counts = HashMap::new();
584        let mut user_agent_counts = HashMap::new();
585        let mut method_counts = HashMap::new();
586
587        for event in events.iter() {
588            if event.timestamp >= start && event.timestamp <= end {
589                // Count by event type
590                match event.event_type {
591                    SecurityEventType::AuthSuccess => metrics.auth_success_count += 1,
592                    SecurityEventType::AuthFailure => metrics.auth_failure_count += 1,
593                    SecurityEventType::InvalidApiKey => metrics.invalid_api_key_count += 1,
594                    SecurityEventType::ExpiredToken => metrics.expired_token_count += 1,
595                    SecurityEventType::SessionCreated => metrics.sessions_created += 1,
596                    SecurityEventType::SessionExpired => metrics.sessions_expired += 1,
597                    SecurityEventType::SessionTerminated => metrics.sessions_terminated += 1,
598                    SecurityEventType::InjectionAttempt => metrics.injection_attempts += 1,
599                    SecurityEventType::SizeLimit => metrics.size_limit_violations += 1,
600                    SecurityEventType::RateLimit => metrics.rate_limit_violations += 1,
601                    SecurityEventType::UnauthorizedAccess => {
602                        metrics.unauthorized_access_attempts += 1
603                    }
604                    SecurityEventType::PermissionDenied => metrics.permission_denied_count += 1,
605                    SecurityEventType::RoleEscalation => metrics.role_escalation_attempts += 1,
606                    _ => {}
607                }
608
609                // Aggregate IP addresses
610                if let Some(ip) = &event.client_ip {
611                    *ip_counts.entry(ip.clone()).or_insert(0) += 1;
612                }
613
614                // Aggregate user agents
615                if let Some(ua) = &event.user_agent {
616                    *user_agent_counts.entry(ua.clone()).or_insert(0) += 1;
617                }
618
619                // Aggregate methods
620                if let Some(method) = &event.method {
621                    *method_counts.entry(method.clone()).or_insert(0) += 1;
622                }
623
624                // Aggregate countries
625                if let Some(country) = &event.country {
626                    *metrics
627                        .country_distribution
628                        .entry(country.clone())
629                        .or_insert(0) += 1;
630                }
631            }
632        }
633
634        // Sort and take top items
635        metrics.top_source_ips = Self::top_items(ip_counts, 10);
636        metrics.top_user_agents = Self::top_items(user_agent_counts, 10);
637        metrics.top_methods = Self::top_items(method_counts, 10);
638
639        metrics
640    }
641
642    /// Get current security dashboard data
643    pub async fn get_dashboard_data(&self) -> SecurityDashboard {
644        let now = chrono::Utc::now();
645        let hour_ago = now - chrono::Duration::hours(1);
646        let day_ago = now - chrono::Duration::days(1);
647
648        let hourly_metrics = self.generate_metrics(hour_ago, now).await;
649        let daily_metrics = self.generate_metrics(day_ago, now).await;
650        let recent_events = self.get_recent_events(Some(50)).await;
651        let active_alerts = self.get_active_alerts().await;
652
653        SecurityDashboard {
654            timestamp: now,
655            hourly_metrics,
656            daily_metrics,
657            recent_events,
658            active_alerts,
659            system_health: self.get_system_health().await,
660        }
661    }
662
663    /// Add alert rule
664    pub async fn add_alert_rule(&self, rule: AlertRule) {
665        let mut rules = self.alert_rules.write().await;
666        rules.push(rule);
667        info!("Added new alert rule");
668    }
669
670    /// Get active alerts
671    pub async fn get_active_alerts(&self) -> Vec<SecurityAlert> {
672        let alerts = self.alerts.read().await;
673        alerts
674            .iter()
675            .filter(|a| a.resolved_at.is_none())
676            .cloned()
677            .collect()
678    }
679
680    /// Resolve alert
681    pub async fn resolve_alert(&self, alert_id: &str) -> Result<(), MonitoringError> {
682        let mut alerts = self.alerts.write().await;
683
684        if let Some(alert) = alerts.iter_mut().find(|a| a.alert_id == alert_id) {
685            alert.resolved_at = Some(chrono::Utc::now());
686            info!("Resolved alert: {}", alert_id);
687            Ok(())
688        } else {
689            Err(MonitoringError::AlertNotFound {
690                alert_id: alert_id.to_string(),
691            })
692        }
693    }
694
695    /// Start background monitoring tasks
696    pub async fn start_background_tasks(&self) -> tokio::task::JoinHandle<()> {
697        let monitor = self.clone();
698
699        tokio::spawn(async move {
700            let mut cleanup_interval =
701                tokio::time::interval(chrono::Duration::hours(1).to_std().unwrap());
702            let mut metrics_interval =
703                tokio::time::interval(monitor.config.metrics_interval.to_std().unwrap());
704
705            loop {
706                tokio::select! {
707                    _ = cleanup_interval.tick() => {
708                        if let Err(e) = monitor.cleanup_old_data().await {
709                            error!("Failed to cleanup old monitoring data: {}", e);
710                        }
711                    }
712                    _ = metrics_interval.tick() => {
713                        if let Err(e) = monitor.update_metrics_cache().await {
714                            error!("Failed to update metrics cache: {}", e);
715                        }
716                    }
717                }
718            }
719        })
720    }
721
722    // Helper methods
723
724    fn top_items(mut counts: HashMap<String, u64>, limit: usize) -> Vec<(String, u64)> {
725        let mut items: Vec<(String, u64)> = counts.drain().collect();
726        items.sort_by(|a, b| b.1.cmp(&a.1));
727        items.truncate(limit);
728        items
729    }
730
731    async fn process_alerts_for_event(&self, event: &SecurityEvent) {
732        let rules = self.alert_rules.read().await;
733
734        for rule in rules.iter() {
735            if !rule.enabled {
736                continue;
737            }
738
739            if rule.event_types.contains(&event.event_type) && event.severity >= rule.min_severity {
740                // Check if threshold is met
741                if self.check_alert_threshold(rule, event).await {
742                    self.trigger_alert(rule, event).await;
743                }
744            }
745        }
746    }
747
748    async fn check_alert_threshold(&self, rule: &AlertRule, _event: &SecurityEvent) -> bool {
749        let now = chrono::Utc::now();
750        let window_start = now - rule.time_window;
751
752        let events = self.events.read().await;
753        let relevant_events: Vec<&SecurityEvent> = events
754            .iter()
755            .filter(|e| {
756                e.timestamp >= window_start
757                    && rule.event_types.contains(&e.event_type)
758                    && e.severity >= rule.min_severity
759            })
760            .collect();
761
762        match &rule.threshold {
763            AlertThreshold::Count(threshold) => relevant_events.len() as u64 >= *threshold,
764            AlertThreshold::Rate { count, duration: _ } => relevant_events.len() as u64 >= *count,
765            AlertThreshold::Percentage {
766                numerator_events,
767                denominator_events,
768                threshold,
769            } => {
770                let numerator = relevant_events
771                    .iter()
772                    .filter(|e| numerator_events.contains(&e.event_type))
773                    .count() as f64;
774
775                let denominator = relevant_events
776                    .iter()
777                    .filter(|e| denominator_events.contains(&e.event_type))
778                    .count() as f64;
779
780                if denominator > 0.0 {
781                    (numerator / denominator) * 100.0 >= *threshold
782                } else {
783                    false
784                }
785            }
786        }
787    }
788
789    async fn trigger_alert(&self, rule: &AlertRule, event: &SecurityEvent) {
790        let alert = SecurityAlert {
791            alert_id: Uuid::new_v4().to_string(),
792            rule_id: rule.rule_id.clone(),
793            rule_name: rule.name.clone(),
794            triggered_at: chrono::Utc::now(),
795            resolved_at: None,
796            severity: event.severity.clone(),
797            description: format!("Alert triggered: {}", rule.description),
798            triggering_events: vec![event.event_id.clone()],
799            metadata: HashMap::new(),
800            actions_taken: Vec::new(),
801        };
802
803        warn!(
804            "Security alert triggered: {} - {}",
805            alert.rule_name, alert.description
806        );
807
808        let mut alerts = self.alerts.write().await;
809        alerts.push(alert);
810
811        // Enforce memory limits
812        while alerts.len() > self.config.max_alerts_in_memory {
813            alerts.remove(0);
814        }
815    }
816
817    async fn update_realtime_metrics(&self, _event: &SecurityEvent) {
818        // Update real-time metrics cache
819        // This would typically update counters, rates, etc.
820        debug!("Updated real-time metrics");
821    }
822
823    async fn cleanup_old_data(&self) -> Result<(), MonitoringError> {
824        let now = chrono::Utc::now();
825        let event_cutoff = now - self.config.event_retention;
826        let alert_cutoff = now - self.config.alert_retention;
827
828        // Cleanup old events
829        let mut events = self.events.write().await;
830        let original_count = events.len();
831        events.retain(|e| e.timestamp >= event_cutoff);
832        let events_removed = original_count - events.len();
833
834        drop(events);
835
836        // Cleanup old alerts
837        let mut alerts = self.alerts.write().await;
838        let original_alert_count = alerts.len();
839        alerts.retain(|a| a.triggered_at >= alert_cutoff);
840        let alerts_removed = original_alert_count - alerts.len();
841
842        if events_removed > 0 || alerts_removed > 0 {
843            info!(
844                "Cleaned up {} old events and {} old alerts",
845                events_removed, alerts_removed
846            );
847        }
848
849        Ok(())
850    }
851
852    async fn update_metrics_cache(&self) -> Result<(), MonitoringError> {
853        let now = chrono::Utc::now();
854        let hour_ago = now - chrono::Duration::hours(1);
855
856        let metrics = self.generate_metrics(hour_ago, now).await;
857
858        let mut cache = self.metrics_cache.write().await;
859        cache.insert("hourly".to_string(), metrics);
860
861        // Keep only recent metrics in cache
862        let day_ago = now - chrono::Duration::days(1);
863        cache.retain(|_, metrics| metrics.period_start >= day_ago);
864
865        Ok(())
866    }
867
868    async fn get_system_health(&self) -> SystemHealth {
869        let events = self.events.read().await;
870        let alerts = self.alerts.read().await;
871
872        SystemHealth {
873            events_in_memory: events.len(),
874            active_alerts: alerts.iter().filter(|a| a.resolved_at.is_none()).count(),
875            last_event_time: events.back().map(|e| e.timestamp),
876            memory_usage_mb: self.estimate_memory_usage().await,
877        }
878    }
879
880    async fn estimate_memory_usage(&self) -> u64 {
881        // Rough estimate of memory usage in MB
882        let events = self.events.read().await;
883        let alerts = self.alerts.read().await;
884
885        let event_size_estimate = events.len() * 1024; // ~1KB per event
886        let alert_size_estimate = alerts.len() * 512; // ~512B per alert
887
888        ((event_size_estimate + alert_size_estimate) / 1024 / 1024) as u64
889    }
890}
891
892impl Clone for SecurityMonitor {
893    fn clone(&self) -> Self {
894        Self {
895            config: self.config.clone(),
896            events: Arc::clone(&self.events),
897            alerts: Arc::clone(&self.alerts),
898            alert_rules: Arc::clone(&self.alert_rules),
899            metrics_cache: Arc::clone(&self.metrics_cache),
900            last_cleanup: Arc::clone(&self.last_cleanup),
901        }
902    }
903}
904
905/// Security dashboard data structure
906#[derive(Debug, Clone, Serialize, Deserialize)]
907pub struct SecurityDashboard {
908    pub timestamp: chrono::DateTime<chrono::Utc>,
909    pub hourly_metrics: SecurityMetrics,
910    pub daily_metrics: SecurityMetrics,
911    pub recent_events: Vec<SecurityEvent>,
912    pub active_alerts: Vec<SecurityAlert>,
913    pub system_health: SystemHealth,
914}
915
916/// System health information
917#[derive(Debug, Clone, Serialize, Deserialize)]
918pub struct SystemHealth {
919    pub events_in_memory: usize,
920    pub active_alerts: usize,
921    pub last_event_time: Option<chrono::DateTime<chrono::Utc>>,
922    pub memory_usage_mb: u64,
923}
924
925/// Helper function to create default alert rules
926pub fn create_default_alert_rules() -> Vec<AlertRule> {
927    vec![
928        AlertRule {
929            rule_id: "high_auth_failures".to_string(),
930            name: "High Authentication Failures".to_string(),
931            description: "Multiple authentication failures detected".to_string(),
932            event_types: vec![
933                SecurityEventType::AuthFailure,
934                SecurityEventType::InvalidApiKey,
935            ],
936            min_severity: SecuritySeverity::Medium,
937            threshold: AlertThreshold::Count(10),
938            time_window: chrono::Duration::minutes(5),
939            cooldown: chrono::Duration::minutes(15),
940            enabled: true,
941            actions: vec![AlertAction::Log {
942                level: "warn".to_string(),
943            }],
944        },
945        AlertRule {
946            rule_id: "injection_attempts".to_string(),
947            name: "Injection Attempts".to_string(),
948            description: "Potential injection attacks detected".to_string(),
949            event_types: vec![SecurityEventType::InjectionAttempt],
950            min_severity: SecuritySeverity::High,
951            threshold: AlertThreshold::Count(3),
952            time_window: chrono::Duration::minutes(10),
953            cooldown: chrono::Duration::minutes(30),
954            enabled: true,
955            actions: vec![
956                AlertAction::Log {
957                    level: "error".to_string(),
958                },
959                AlertAction::BlockIp {
960                    duration: chrono::Duration::hours(1),
961                },
962            ],
963        },
964        AlertRule {
965            rule_id: "rate_limit_violations".to_string(),
966            name: "Rate Limit Violations".to_string(),
967            description: "Excessive rate limit violations".to_string(),
968            event_types: vec![SecurityEventType::RateLimit],
969            min_severity: SecuritySeverity::Medium,
970            threshold: AlertThreshold::Count(20),
971            time_window: chrono::Duration::minutes(5),
972            cooldown: chrono::Duration::minutes(10),
973            enabled: true,
974            actions: vec![AlertAction::Log {
975                level: "warn".to_string(),
976            }],
977        },
978    ]
979}
980
981#[cfg(test)]
982mod tests {
983    use super::*;
984
985    #[tokio::test]
986    async fn test_security_monitor_creation() {
987        let monitor = SecurityMonitor::with_default_config();
988
989        // Test that monitor was created successfully
990        assert!(monitor.config.enable_realtime);
991        assert!(monitor.config.enable_alerts);
992    }
993
994    #[tokio::test]
995    async fn test_event_recording() {
996        let monitor = SecurityMonitor::with_default_config();
997
998        let event = SecurityEvent::new(
999            SecurityEventType::AuthFailure,
1000            SecuritySeverity::Medium,
1001            "Test authentication failure".to_string(),
1002        );
1003
1004        monitor.record_event(event).await;
1005
1006        let events = monitor.get_recent_events(Some(10)).await;
1007        assert_eq!(events.len(), 1);
1008        assert_eq!(events[0].event_type, SecurityEventType::AuthFailure);
1009    }
1010
1011    #[tokio::test]
1012    async fn test_metrics_generation() {
1013        let monitor = SecurityMonitor::with_default_config();
1014
1015        // Record some test events
1016        monitor
1017            .record_event(SecurityEvent::new(
1018                SecurityEventType::AuthSuccess,
1019                SecuritySeverity::Low,
1020                "Success".to_string(),
1021            ))
1022            .await;
1023
1024        monitor
1025            .record_event(SecurityEvent::new(
1026                SecurityEventType::AuthFailure,
1027                SecuritySeverity::Medium,
1028                "Failure".to_string(),
1029            ))
1030            .await;
1031
1032        let now = chrono::Utc::now();
1033        let hour_ago = now - chrono::Duration::hours(1);
1034
1035        let metrics = monitor.generate_metrics(hour_ago, now).await;
1036
1037        assert_eq!(metrics.auth_success_count, 1);
1038        assert_eq!(metrics.auth_failure_count, 1);
1039    }
1040
1041    #[tokio::test]
1042    async fn test_alert_rules() {
1043        let monitor = SecurityMonitor::with_default_config();
1044
1045        let rule = AlertRule {
1046            rule_id: "test_rule".to_string(),
1047            name: "Test Rule".to_string(),
1048            description: "Test alert rule".to_string(),
1049            event_types: vec![SecurityEventType::AuthFailure],
1050            min_severity: SecuritySeverity::Medium,
1051            threshold: AlertThreshold::Count(1),
1052            time_window: chrono::Duration::minutes(5),
1053            cooldown: chrono::Duration::minutes(1),
1054            enabled: true,
1055            actions: vec![AlertAction::Log {
1056                level: "warn".to_string(),
1057            }],
1058        };
1059
1060        monitor.add_alert_rule(rule).await;
1061
1062        // Record an event that should trigger the alert
1063        monitor
1064            .record_event(SecurityEvent::new(
1065                SecurityEventType::AuthFailure,
1066                SecuritySeverity::Medium,
1067                "Test failure".to_string(),
1068            ))
1069            .await;
1070
1071        // Give some time for alert processing
1072        tokio::time::sleep(tokio::time::Duration::from_millis(100)).await;
1073
1074        let active_alerts = monitor.get_active_alerts().await;
1075        assert!(!active_alerts.is_empty());
1076    }
1077
1078    #[tokio::test]
1079    async fn test_dashboard_data() {
1080        let monitor = SecurityMonitor::with_default_config();
1081
1082        // Record some events
1083        monitor
1084            .record_event(SecurityEvent::new(
1085                SecurityEventType::SessionCreated,
1086                SecuritySeverity::Low,
1087                "Session created".to_string(),
1088            ))
1089            .await;
1090
1091        let dashboard = monitor.get_dashboard_data().await;
1092
1093        assert!(!dashboard.recent_events.is_empty());
1094        assert_eq!(dashboard.hourly_metrics.sessions_created, 1);
1095    }
1096}