eventuali_core/security/
audit.rs

1use crate::Result;
2use serde::{Deserialize, Serialize};
3use std::collections::{HashMap, BTreeMap, HashSet};
4use chrono::{DateTime, Utc, Duration};
5use uuid::Uuid;
6use sha2::{Sha256, Digest};
7
8/// Comprehensive audit trail system for enterprise compliance
9pub struct AuditManager {
10    audit_entries: Vec<AuditTrailEntry>,
11    search_index: AuditSearchIndex,
12    integrity_chain: IntegrityChain,
13    retention_policy: RetentionPolicy,
14    compliance_settings: ComplianceSettings,
15    alert_rules: Vec<AuditAlertRule>,
16}
17
18/// Enhanced audit entry with compliance features
19#[derive(Debug, Clone, Serialize, Deserialize)]
20pub struct AuditTrailEntry {
21    pub entry_id: String,
22    pub event_type: AuditEventType,
23    pub user_id: String,
24    pub session_id: Option<String>,
25    pub action: String,
26    pub resource: String,
27    pub resource_id: Option<String>,
28    pub timestamp: DateTime<Utc>,
29    pub ip_address: Option<String>,
30    pub user_agent: Option<String>,
31    pub outcome: AuditOutcome,
32    pub risk_level: RiskLevel,
33    pub metadata: HashMap<String, String>,
34    pub compliance_tags: HashSet<ComplianceTag>,
35    pub data_classification: DataClassification,
36    pub integrity_hash: String,
37    pub previous_hash: Option<String>,
38    pub correlation_id: Option<String>,
39    pub geographic_location: Option<String>,
40    pub duration_ms: Option<u64>,
41    pub error_details: Option<String>,
42}
43
44/// Types of audit events for comprehensive tracking
45#[derive(Debug, Clone, Serialize, Deserialize, Hash, PartialEq, Eq, PartialOrd, Ord)]
46pub enum AuditEventType {
47    Authentication,
48    Authorization, 
49    DataAccess,
50    DataModification,
51    SystemAccess,
52    ConfigurationChange,
53    SecurityViolation,
54    PrivilegedOperation,
55    DataExport,
56    AccountManagement,
57    SessionManagement,
58    PolicyViolation,
59    Backup,
60    Recovery,
61    SystemMaintenance,
62}
63
64/// Audit outcome for compliance reporting
65#[derive(Debug, Clone, Serialize, Deserialize)]
66pub enum AuditOutcome {
67    Success,
68    Failure,
69    Partial,
70    Warning,
71    Blocked,
72    Escalated,
73}
74
75/// Risk level assessment for security monitoring
76#[derive(Debug, Clone, Serialize, Deserialize, PartialOrd, PartialEq, Eq, Ord, Hash)]
77pub enum RiskLevel {
78    Low,
79    Medium,
80    High,
81    Critical,
82}
83
84/// Data classification for regulatory compliance
85#[derive(Debug, Clone, Serialize, Deserialize)]
86pub enum DataClassification {
87    Public,
88    Internal,
89    Confidential,
90    Restricted,
91    HealthcareData,
92    FinancialData,
93    PersonalData,
94}
95
96/// Compliance framework tags
97#[derive(Debug, Clone, Serialize, Deserialize, Hash, PartialEq, Eq, PartialOrd, Ord)]
98pub enum ComplianceTag {
99    SOX,        // Sarbanes-Oxley
100    GDPR,       // General Data Protection Regulation
101    HIPAA,      // Health Insurance Portability and Accountability Act
102    PciDss,     // Payment Card Industry Data Security Standard
103    ISO27001,   // Information Security Management
104    NIST,       // National Institute of Standards and Technology
105    COBIT,      // Control Objectives for Information and Related Technologies
106    ITIL,       // Information Technology Infrastructure Library
107}
108
109/// Search index for efficient audit queries
110pub struct AuditSearchIndex {
111    by_user: BTreeMap<String, Vec<usize>>,
112    by_resource: BTreeMap<String, Vec<usize>>,
113    by_event_type: BTreeMap<AuditEventType, Vec<usize>>,
114    by_timestamp: BTreeMap<DateTime<Utc>, Vec<usize>>,
115    by_risk_level: BTreeMap<RiskLevel, Vec<usize>>,
116    by_compliance_tag: BTreeMap<ComplianceTag, Vec<usize>>,
117    by_ip_address: BTreeMap<String, Vec<usize>>,
118}
119
120/// Cryptographic integrity chain for tamper detection
121pub struct IntegrityChain {
122    chain_hash: String,
123    entry_count: usize,
124    last_verification: DateTime<Utc>,
125}
126
127/// Retention policy for audit data lifecycle
128#[derive(Debug, Clone, Serialize, Deserialize)]
129pub struct RetentionPolicy {
130    pub default_retention_days: u32,
131    pub by_event_type: HashMap<AuditEventType, u32>,
132    pub by_compliance_tag: HashMap<ComplianceTag, u32>,
133    pub archive_after_days: u32,
134    pub auto_delete_after_days: Option<u32>,
135}
136
137/// Compliance settings for different regulatory requirements
138#[derive(Debug, Clone, Serialize, Deserialize)]
139pub struct ComplianceSettings {
140    pub enabled_frameworks: HashSet<ComplianceTag>,
141    pub minimum_retention_days: u32,
142    pub require_integrity_verification: bool,
143    pub real_time_monitoring: bool,
144    pub automatic_reporting: bool,
145    pub data_anonymization_after_days: Option<u32>,
146}
147
148/// Alert rule for suspicious activity detection
149#[derive(Debug, Clone, Serialize, Deserialize)]
150pub struct AuditAlertRule {
151    pub rule_id: String,
152    pub name: String,
153    pub description: String,
154    pub event_types: HashSet<AuditEventType>,
155    pub conditions: Vec<AlertCondition>,
156    pub severity: AlertSeverity,
157    pub enabled: bool,
158    pub cooldown_minutes: u32,
159}
160
161/// Condition for audit alerts
162#[derive(Debug, Clone, Serialize, Deserialize)]
163pub struct AlertCondition {
164    pub field: String,
165    pub operator: AlertOperator,
166    pub value: String,
167    pub time_window_minutes: Option<u32>,
168}
169
170/// Alert operators
171#[derive(Debug, Clone, Serialize, Deserialize)]
172pub enum AlertOperator {
173    Equals,
174    NotEquals,
175    Contains,
176    FrequencyExceeds,
177    PatternMatches,
178    RiskLevelAbove,
179}
180
181/// Alert severity levels
182#[derive(Debug, Clone, Serialize, Deserialize)]
183pub enum AlertSeverity {
184    Info,
185    Low,
186    Medium,
187    High,
188    Critical,
189}
190
191/// Search criteria for audit queries
192#[derive(Debug, Clone)]
193pub struct AuditSearchCriteria {
194    pub user_id: Option<String>,
195    pub event_types: Option<HashSet<AuditEventType>>,
196    pub resources: Option<HashSet<String>>,
197    pub start_time: Option<DateTime<Utc>>,
198    pub end_time: Option<DateTime<Utc>>,
199    pub risk_levels: Option<HashSet<RiskLevel>>,
200    pub compliance_tags: Option<HashSet<ComplianceTag>>,
201    pub ip_addresses: Option<HashSet<String>>,
202    pub outcomes: Option<HashSet<AuditOutcome>>,
203    pub text_search: Option<String>,
204}
205
206/// Compliance report for regulatory requirements
207#[derive(Debug, Clone, Serialize, Deserialize)]
208pub struct ComplianceReport {
209    pub report_id: String,
210    pub framework: ComplianceTag,
211    pub generated_at: DateTime<Utc>,
212    pub period_start: DateTime<Utc>,
213    pub period_end: DateTime<Utc>,
214    pub total_events: usize,
215    pub by_event_type: HashMap<AuditEventType, usize>,
216    pub security_violations: usize,
217    pub policy_violations: usize,
218    pub failed_authentications: usize,
219    pub privileged_operations: usize,
220    pub data_access_events: usize,
221    pub integrity_status: IntegrityStatus,
222    pub risk_summary: RiskSummary,
223    pub recommendations: Vec<String>,
224}
225
226/// Integrity verification status
227#[derive(Debug, Clone, Serialize, Deserialize)]
228pub struct IntegrityStatus {
229    pub chain_verified: bool,
230    pub tamper_detected: bool,
231    pub last_verification: DateTime<Utc>,
232    pub total_entries: usize,
233    pub verification_errors: Vec<String>,
234}
235
236/// Risk assessment summary
237#[derive(Debug, Clone, Serialize, Deserialize)]
238pub struct RiskSummary {
239    pub by_level: HashMap<RiskLevel, usize>,
240    pub trending_up: bool,
241    pub high_risk_users: Vec<String>,
242    pub suspicious_patterns: Vec<String>,
243}
244
245impl AuditManager {
246    /// Create a new audit manager with default settings
247    pub fn new() -> Self {
248        Self {
249            audit_entries: Vec::new(),
250            search_index: AuditSearchIndex::new(),
251            integrity_chain: IntegrityChain::new(),
252            retention_policy: RetentionPolicy::default(),
253            compliance_settings: ComplianceSettings::default(),
254            alert_rules: Vec::new(),
255        }
256    }
257
258    /// Create audit manager with specific compliance requirements
259    pub fn with_compliance(frameworks: HashSet<ComplianceTag>) -> Self {
260        let mut audit_manager = Self::new();
261        audit_manager.compliance_settings.enabled_frameworks = frameworks;
262        audit_manager.initialize_compliance_rules();
263        audit_manager
264    }
265
266    /// Log an audit event with comprehensive tracking
267    pub fn log_audit_event(
268        &mut self,
269        event_type: AuditEventType,
270        user_id: String,
271        action: String,
272        resource: String,
273        outcome: AuditOutcome,
274        metadata: Option<HashMap<String, String>>,
275    ) -> Result<String> {
276        let entry_id = Uuid::new_v4().to_string();
277        let timestamp = Utc::now();
278        
279        // Determine risk level and compliance tags
280        let risk_level = self.assess_risk_level(&event_type, &outcome, &metadata);
281        let compliance_tags = self.determine_compliance_tags(&event_type, &resource);
282        let data_classification = self.classify_data(&resource, &metadata);
283
284        // Calculate integrity hash
285        let previous_hash = self.integrity_chain.get_current_hash();
286        let integrity_hash = self.calculate_integrity_hash(&entry_id, &timestamp, &previous_hash);
287
288        let entry = AuditTrailEntry {
289            entry_id: entry_id.clone(),
290            event_type: event_type.clone(),
291            user_id: user_id.clone(),
292            session_id: None,
293            action,
294            resource: resource.clone(),
295            resource_id: None,
296            timestamp,
297            ip_address: None,
298            user_agent: None,
299            outcome,
300            risk_level,
301            metadata: metadata.unwrap_or_default(),
302            compliance_tags,
303            data_classification,
304            integrity_hash: integrity_hash.clone(),
305            previous_hash,
306            correlation_id: None,
307            geographic_location: None,
308            duration_ms: None,
309            error_details: None,
310        };
311
312        // Add to audit log
313        let index = self.audit_entries.len();
314        self.audit_entries.push(entry.clone());
315
316        // Update search index
317        self.search_index.add_entry(index, &entry);
318
319        // Update integrity chain
320        self.integrity_chain.update(integrity_hash, index + 1);
321
322        // Check alert rules
323        self.check_alert_rules(&entry);
324
325        // Apply retention policy if needed
326        if self.audit_entries.len().is_multiple_of(1000) {
327            self.apply_retention_policy();
328        }
329
330        Ok(entry_id)
331    }
332
333    /// Log authentication event with enhanced details
334    pub fn log_authentication_event(
335        &mut self,
336        user_id: String,
337        session_id: Option<String>,
338        ip_address: Option<String>,
339        user_agent: Option<String>,
340        success: bool,
341        failure_reason: Option<String>,
342    ) -> Result<String> {
343        let mut metadata = HashMap::new();
344        if let Some(reason) = &failure_reason {
345            metadata.insert("failure_reason".to_string(), reason.clone());
346        }
347        if let Some(agent) = &user_agent {
348            metadata.insert("user_agent".to_string(), agent.clone());
349        }
350
351        let outcome = if success {
352            AuditOutcome::Success
353        } else {
354            AuditOutcome::Failure
355        };
356
357        let entry_id = self.log_audit_event(
358            AuditEventType::Authentication,
359            user_id.clone(),
360            if success { "login_success".to_string() } else { "login_failure".to_string() },
361            "authentication_system".to_string(),
362            outcome,
363            Some(metadata),
364        )?;
365
366        // Update the entry with authentication-specific details
367        if let Some(entry) = self.audit_entries.last_mut() {
368            entry.session_id = session_id;
369            entry.ip_address = ip_address;
370            entry.user_agent = user_agent;
371            entry.error_details = failure_reason;
372        }
373
374        Ok(entry_id)
375    }
376
377    /// Log data access event with privacy compliance
378    pub fn log_data_access_event(
379        &mut self,
380        user_id: String,
381        resource: String,
382        resource_id: Option<String>,
383        operation: String,
384        data_classification: DataClassification,
385        success: bool,
386    ) -> Result<String> {
387        let mut metadata = HashMap::new();
388        metadata.insert("operation".to_string(), operation.clone());
389        metadata.insert("data_classification".to_string(), format!("{data_classification:?}"));
390
391        let outcome = if success {
392            AuditOutcome::Success
393        } else {
394            AuditOutcome::Failure
395        };
396
397        let entry_id = self.log_audit_event(
398            AuditEventType::DataAccess,
399            user_id,
400            operation,
401            resource,
402            outcome,
403            Some(metadata),
404        )?;
405
406        // Update with data-specific details
407        if let Some(entry) = self.audit_entries.last_mut() {
408            entry.resource_id = resource_id;
409            entry.data_classification = data_classification;
410        }
411
412        Ok(entry_id)
413    }
414
415    /// Search audit entries with flexible criteria
416    pub fn search_audit_entries(
417        &self,
418        criteria: &AuditSearchCriteria,
419        limit: Option<usize>,
420    ) -> Vec<&AuditTrailEntry> {
421        let mut results = Vec::new();
422        let limit = limit.unwrap_or(1000);
423
424        for entry in &self.audit_entries {
425            if self.matches_criteria(entry, criteria) {
426                results.push(entry);
427                if results.len() >= limit {
428                    break;
429                }
430            }
431        }
432
433        // Sort by timestamp descending (most recent first)
434        results.sort_by(|a, b| b.timestamp.cmp(&a.timestamp));
435        results
436    }
437
438    /// Generate compliance report for specific framework
439    pub fn generate_compliance_report(
440        &self,
441        framework: ComplianceTag,
442        start_time: DateTime<Utc>,
443        end_time: DateTime<Utc>,
444    ) -> Result<ComplianceReport> {
445        let report_id = Uuid::new_v4().to_string();
446        let generated_at = Utc::now();
447
448        // Filter entries for the time period and framework
449        let relevant_entries: Vec<_> = self.audit_entries
450            .iter()
451            .filter(|entry| {
452                entry.timestamp >= start_time 
453                && entry.timestamp <= end_time
454                && entry.compliance_tags.contains(&framework)
455            })
456            .collect();
457
458        let total_events = relevant_entries.len();
459
460        // Count by event type
461        let mut by_event_type = HashMap::new();
462        for entry in &relevant_entries {
463            *by_event_type.entry(entry.event_type.clone()).or_insert(0) += 1;
464        }
465
466        // Count specific compliance metrics
467        let security_violations = relevant_entries.iter()
468            .filter(|e| e.event_type == AuditEventType::SecurityViolation)
469            .count();
470
471        let policy_violations = relevant_entries.iter()
472            .filter(|e| e.event_type == AuditEventType::PolicyViolation)
473            .count();
474
475        let failed_authentications = relevant_entries.iter()
476            .filter(|e| e.event_type == AuditEventType::Authentication && 
477                     matches!(e.outcome, AuditOutcome::Failure))
478            .count();
479
480        let privileged_operations = relevant_entries.iter()
481            .filter(|e| e.event_type == AuditEventType::PrivilegedOperation)
482            .count();
483
484        let data_access_events = relevant_entries.iter()
485            .filter(|e| matches!(e.event_type, AuditEventType::DataAccess | AuditEventType::DataModification))
486            .count();
487
488        // Verify integrity
489        let integrity_status = self.verify_integrity();
490
491        // Generate risk summary
492        let risk_summary = self.generate_risk_summary(&relevant_entries);
493
494        // Generate recommendations based on findings
495        let recommendations = self.generate_compliance_recommendations(&framework, &relevant_entries);
496
497        Ok(ComplianceReport {
498            report_id,
499            framework,
500            generated_at,
501            period_start: start_time,
502            period_end: end_time,
503            total_events,
504            by_event_type,
505            security_violations,
506            policy_violations,
507            failed_authentications,
508            privileged_operations,
509            data_access_events,
510            integrity_status,
511            risk_summary,
512            recommendations,
513        })
514    }
515
516    /// Verify integrity of audit trail using cryptographic hashes
517    pub fn verify_integrity(&self) -> IntegrityStatus {
518        let mut verification_errors = Vec::new();
519        let mut tamper_detected = false;
520        let total_entries = self.audit_entries.len();
521
522        // Verify each entry's hash
523        let mut previous_hash: Option<String> = None;
524        for (index, entry) in self.audit_entries.iter().enumerate() {
525            let expected_hash = self.calculate_integrity_hash(&entry.entry_id, &entry.timestamp, &previous_hash);
526            
527            if entry.integrity_hash != expected_hash {
528                tamper_detected = true;
529                verification_errors.push(format!("Hash mismatch at entry {}: {}", index, entry.entry_id));
530            }
531
532            if entry.previous_hash != previous_hash {
533                tamper_detected = true;
534                verification_errors.push(format!("Chain break at entry {}: {}", index, entry.entry_id));
535            }
536
537            previous_hash = Some(entry.integrity_hash.clone());
538        }
539
540        IntegrityStatus {
541            chain_verified: !tamper_detected,
542            tamper_detected,
543            last_verification: Utc::now(),
544            total_entries,
545            verification_errors,
546        }
547    }
548
549    /// Get audit statistics for monitoring dashboard
550    pub fn get_audit_statistics(&self, last_hours: u32) -> HashMap<String, serde_json::Value> {
551        let since = Utc::now() - Duration::hours(last_hours as i64);
552        let recent_entries: Vec<_> = self.audit_entries
553            .iter()
554            .filter(|e| e.timestamp >= since)
555            .collect();
556
557        let mut stats = HashMap::new();
558
559        stats.insert("total_entries".to_string(), serde_json::Value::Number(self.audit_entries.len().into()));
560        stats.insert("recent_entries".to_string(), serde_json::Value::Number(recent_entries.len().into()));
561
562        // Count by event type
563        let mut by_event_type = HashMap::new();
564        for entry in &recent_entries {
565            *by_event_type.entry(format!("{:?}", entry.event_type)).or_insert(0) += 1;
566        }
567        stats.insert("by_event_type".to_string(), serde_json::to_value(by_event_type).unwrap_or_default());
568
569        // Count by risk level
570        let mut by_risk_level = HashMap::new();
571        for entry in &recent_entries {
572            *by_risk_level.entry(format!("{:?}", entry.risk_level)).or_insert(0) += 1;
573        }
574        stats.insert("by_risk_level".to_string(), serde_json::to_value(by_risk_level).unwrap_or_default());
575
576        // Count by outcome
577        let mut by_outcome = HashMap::new();
578        for entry in &recent_entries {
579            *by_outcome.entry(format!("{:?}", entry.outcome)).or_insert(0) += 1;
580        }
581        stats.insert("by_outcome".to_string(), serde_json::to_value(by_outcome).unwrap_or_default());
582
583        // Integrity status
584        let integrity = self.verify_integrity();
585        stats.insert("integrity_verified".to_string(), serde_json::Value::Bool(integrity.chain_verified));
586        stats.insert("tamper_detected".to_string(), serde_json::Value::Bool(integrity.tamper_detected));
587
588        stats
589    }
590
591    // Private helper methods
592
593    fn assess_risk_level(
594        &self,
595        event_type: &AuditEventType,
596        outcome: &AuditOutcome,
597        _metadata: &Option<HashMap<String, String>>,
598    ) -> RiskLevel {
599        match event_type {
600            AuditEventType::SecurityViolation | AuditEventType::PolicyViolation => RiskLevel::Critical,
601            AuditEventType::PrivilegedOperation => RiskLevel::High,
602            AuditEventType::Authentication if matches!(outcome, AuditOutcome::Failure) => RiskLevel::Medium,
603            AuditEventType::DataExport => RiskLevel::Medium,
604            AuditEventType::ConfigurationChange => RiskLevel::Medium,
605            _ => RiskLevel::Low,
606        }
607    }
608
609    fn determine_compliance_tags(&self, event_type: &AuditEventType, resource: &str) -> HashSet<ComplianceTag> {
610        let mut tags = HashSet::new();
611
612        // Add tags based on event type
613        match event_type {
614            AuditEventType::Authentication | AuditEventType::Authorization => {
615                tags.insert(ComplianceTag::SOX);
616                tags.insert(ComplianceTag::ISO27001);
617            }
618            AuditEventType::DataAccess | AuditEventType::DataModification => {
619                tags.insert(ComplianceTag::GDPR);
620                if resource.contains("payment") || resource.contains("card") {
621                    tags.insert(ComplianceTag::PciDss);
622                }
623                if resource.contains("health") || resource.contains("medical") {
624                    tags.insert(ComplianceTag::HIPAA);
625                }
626            }
627            AuditEventType::ConfigurationChange | AuditEventType::PrivilegedOperation => {
628                tags.insert(ComplianceTag::SOX);
629                tags.insert(ComplianceTag::NIST);
630            }
631            _ => {
632                tags.insert(ComplianceTag::ISO27001);
633            }
634        }
635
636        // Filter by enabled frameworks
637        tags.retain(|tag| self.compliance_settings.enabled_frameworks.contains(tag));
638        tags
639    }
640
641    fn classify_data(&self, resource: &str, _metadata: &Option<HashMap<String, String>>) -> DataClassification {
642        if resource.contains("health") || resource.contains("medical") || resource.contains("patient") {
643            DataClassification::HealthcareData
644        } else if resource.contains("payment") || resource.contains("financial") || resource.contains("card") {
645            DataClassification::FinancialData
646        } else if resource.contains("personal") || resource.contains("pii") {
647            DataClassification::PersonalData
648        } else if resource.contains("confidential") || resource.contains("secret") {
649            DataClassification::Confidential
650        } else if resource.contains("restricted") || resource.contains("classified") {
651            DataClassification::Restricted
652        } else if resource.contains("internal") {
653            DataClassification::Internal
654        } else {
655            DataClassification::Public
656        }
657    }
658
659    fn calculate_integrity_hash(&self, entry_id: &str, timestamp: &DateTime<Utc>, previous_hash: &Option<String>) -> String {
660        let mut hasher = Sha256::new();
661        hasher.update(entry_id.as_bytes());
662        hasher.update(timestamp.to_rfc3339().as_bytes());
663        if let Some(prev) = previous_hash {
664            hasher.update(prev.as_bytes());
665        }
666        format!("{:x}", hasher.finalize())
667    }
668
669    fn check_alert_rules(&self, entry: &AuditTrailEntry) {
670        // In a real implementation, this would trigger alerts based on rules
671        // For now, we'll just log high-risk events
672        if entry.risk_level == RiskLevel::Critical || entry.risk_level == RiskLevel::High {
673            eprintln!("AUDIT ALERT: High-risk event detected: {:?} by user {} at {}", 
674                     entry.event_type, entry.user_id, entry.timestamp);
675        }
676    }
677
678    fn apply_retention_policy(&mut self) {
679        let now = Utc::now();
680        let retention_duration = Duration::days(self.retention_policy.default_retention_days as i64);
681        let cutoff_time = now - retention_duration;
682
683        // In a real implementation, this would archive or delete old entries
684        // For now, we'll just identify entries that would be affected
685        let old_entries = self.audit_entries
686            .iter()
687            .filter(|e| e.timestamp < cutoff_time)
688            .count();
689
690        if old_entries > 0 {
691            eprintln!("RETENTION: {old_entries} entries eligible for archival");
692        }
693    }
694
695    fn matches_criteria(&self, entry: &AuditTrailEntry, criteria: &AuditSearchCriteria) -> bool {
696        if let Some(user_id) = &criteria.user_id {
697            if entry.user_id != *user_id {
698                return false;
699            }
700        }
701
702        if let Some(event_types) = &criteria.event_types {
703            if !event_types.contains(&entry.event_type) {
704                return false;
705            }
706        }
707
708        if let Some(resources) = &criteria.resources {
709            if !resources.contains(&entry.resource) {
710                return false;
711            }
712        }
713
714        if let Some(start_time) = criteria.start_time {
715            if entry.timestamp < start_time {
716                return false;
717            }
718        }
719
720        if let Some(end_time) = criteria.end_time {
721            if entry.timestamp > end_time {
722                return false;
723            }
724        }
725
726        if let Some(risk_levels) = &criteria.risk_levels {
727            if !risk_levels.contains(&entry.risk_level) {
728                return false;
729            }
730        }
731
732        if let Some(compliance_tags) = &criteria.compliance_tags {
733            if !compliance_tags.iter().any(|tag| entry.compliance_tags.contains(tag)) {
734                return false;
735            }
736        }
737
738        if let Some(ip_addresses) = &criteria.ip_addresses {
739            if let Some(ip) = &entry.ip_address {
740                if !ip_addresses.contains(ip) {
741                    return false;
742                }
743            } else {
744                return false;
745            }
746        }
747
748        true
749    }
750
751    fn generate_risk_summary(&self, entries: &[&AuditTrailEntry]) -> RiskSummary {
752        let mut by_level = HashMap::new();
753        let mut user_risk_counts = HashMap::new();
754
755        for entry in entries {
756            *by_level.entry(entry.risk_level.clone()).or_insert(0) += 1;
757            
758            if entry.risk_level == RiskLevel::High || entry.risk_level == RiskLevel::Critical {
759                *user_risk_counts.entry(entry.user_id.clone()).or_insert(0) += 1;
760            }
761        }
762
763        let high_risk_users: Vec<String> = user_risk_counts
764            .into_iter()
765            .filter(|(_, count)| *count > 5)
766            .map(|(user, _)| user)
767            .collect();
768
769        let suspicious_patterns = vec![
770            "Multiple failed authentications detected".to_string(),
771            "Unusual after-hours access patterns".to_string(),
772            "High-volume data access events".to_string(),
773        ];
774
775        RiskSummary {
776            by_level,
777            trending_up: false, // Would calculate based on historical data
778            high_risk_users,
779            suspicious_patterns,
780        }
781    }
782
783    fn generate_compliance_recommendations(&self, framework: &ComplianceTag, _entries: &[&AuditTrailEntry]) -> Vec<String> {
784        let mut recommendations = Vec::new();
785
786        match framework {
787            ComplianceTag::SOX => {
788                recommendations.push("Implement stronger segregation of duties for financial operations".to_string());
789                recommendations.push("Enhance monitoring of privileged account activities".to_string());
790            }
791            ComplianceTag::GDPR => {
792                recommendations.push("Implement data minimization principles for personal data access".to_string());
793                recommendations.push("Enhance consent tracking for data processing activities".to_string());
794            }
795            ComplianceTag::HIPAA => {
796                recommendations.push("Strengthen access controls for healthcare data".to_string());
797                recommendations.push("Implement minimum necessary access principles".to_string());
798            }
799            ComplianceTag::PciDss => {
800                recommendations.push("Enhance monitoring of payment card data access".to_string());
801                recommendations.push("Implement stronger encryption for card data transmission".to_string());
802            }
803            _ => {
804                recommendations.push("Review security policies and access controls".to_string());
805            }
806        }
807
808        recommendations
809    }
810
811    fn initialize_compliance_rules(&mut self) {
812        // Initialize default alert rules for compliance frameworks
813        let enabled_frameworks: Vec<_> = self.compliance_settings.enabled_frameworks.iter().cloned().collect();
814        for framework in enabled_frameworks {
815            match framework {
816                ComplianceTag::SOX => self.add_sox_rules(),
817                ComplianceTag::GDPR => self.add_gdpr_rules(),
818                ComplianceTag::HIPAA => self.add_hipaa_rules(),
819                ComplianceTag::PciDss => self.add_pci_rules(),
820                _ => {}
821            }
822        }
823    }
824
825    fn add_sox_rules(&mut self) {
826        let rule = AuditAlertRule {
827            rule_id: "SOX_001".to_string(),
828            name: "Financial System Access Alert".to_string(),
829            description: "Alert on financial system access outside business hours".to_string(),
830            event_types: [AuditEventType::DataAccess, AuditEventType::PrivilegedOperation].into_iter().collect(),
831            conditions: vec![
832                AlertCondition {
833                    field: "resource".to_string(),
834                    operator: AlertOperator::Contains,
835                    value: "financial".to_string(),
836                    time_window_minutes: None,
837                }
838            ],
839            severity: AlertSeverity::High,
840            enabled: true,
841            cooldown_minutes: 60,
842        };
843        self.alert_rules.push(rule);
844    }
845
846    fn add_gdpr_rules(&mut self) {
847        let rule = AuditAlertRule {
848            rule_id: "GDPR_001".to_string(),
849            name: "Personal Data Access Alert".to_string(),
850            description: "Alert on personal data access and modifications".to_string(),
851            event_types: [AuditEventType::DataAccess, AuditEventType::DataModification, AuditEventType::DataExport].into_iter().collect(),
852            conditions: vec![
853                AlertCondition {
854                    field: "data_classification".to_string(),
855                    operator: AlertOperator::Equals,
856                    value: "PersonalData".to_string(),
857                    time_window_minutes: None,
858                }
859            ],
860            severity: AlertSeverity::Medium,
861            enabled: true,
862            cooldown_minutes: 30,
863        };
864        self.alert_rules.push(rule);
865    }
866
867    fn add_hipaa_rules(&mut self) {
868        let rule = AuditAlertRule {
869            rule_id: "HIPAA_001".to_string(),
870            name: "Healthcare Data Alert".to_string(),
871            description: "Alert on healthcare data access violations".to_string(),
872            event_types: [AuditEventType::DataAccess, AuditEventType::SecurityViolation].into_iter().collect(),
873            conditions: vec![
874                AlertCondition {
875                    field: "data_classification".to_string(),
876                    operator: AlertOperator::Equals,
877                    value: "HealthcareData".to_string(),
878                    time_window_minutes: None,
879                }
880            ],
881            severity: AlertSeverity::Critical,
882            enabled: true,
883            cooldown_minutes: 15,
884        };
885        self.alert_rules.push(rule);
886    }
887
888    fn add_pci_rules(&mut self) {
889        let rule = AuditAlertRule {
890            rule_id: "PCI_001".to_string(),
891            name: "Payment Card Data Alert".to_string(),
892            description: "Alert on payment card data access and processing".to_string(),
893            event_types: [AuditEventType::DataAccess, AuditEventType::DataModification, AuditEventType::DataExport].into_iter().collect(),
894            conditions: vec![
895                AlertCondition {
896                    field: "data_classification".to_string(),
897                    operator: AlertOperator::Equals,
898                    value: "FinancialData".to_string(),
899                    time_window_minutes: None,
900                }
901            ],
902            severity: AlertSeverity::Critical,
903            enabled: true,
904            cooldown_minutes: 10,
905        };
906        self.alert_rules.push(rule);
907    }
908}
909
910impl AuditSearchIndex {
911    fn new() -> Self {
912        Self {
913            by_user: BTreeMap::new(),
914            by_resource: BTreeMap::new(),
915            by_event_type: BTreeMap::new(),
916            by_timestamp: BTreeMap::new(),
917            by_risk_level: BTreeMap::new(),
918            by_compliance_tag: BTreeMap::new(),
919            by_ip_address: BTreeMap::new(),
920        }
921    }
922
923    fn add_entry(&mut self, index: usize, entry: &AuditTrailEntry) {
924        self.by_user.entry(entry.user_id.clone())
925            .or_default()
926            .push(index);
927
928        self.by_resource.entry(entry.resource.clone())
929            .or_default()
930            .push(index);
931
932        self.by_event_type.entry(entry.event_type.clone())
933            .or_default()
934            .push(index);
935
936        self.by_timestamp.entry(entry.timestamp)
937            .or_default()
938            .push(index);
939
940        self.by_risk_level.entry(entry.risk_level.clone())
941            .or_default()
942            .push(index);
943
944        for tag in &entry.compliance_tags {
945            self.by_compliance_tag.entry(tag.clone())
946                .or_default()
947                .push(index);
948        }
949
950        if let Some(ip) = &entry.ip_address {
951            self.by_ip_address.entry(ip.clone())
952                .or_default()
953                .push(index);
954        }
955    }
956}
957
958impl IntegrityChain {
959    fn new() -> Self {
960        Self {
961            chain_hash: "genesis".to_string(),
962            entry_count: 0,
963            last_verification: Utc::now(),
964        }
965    }
966
967    fn update(&mut self, new_hash: String, count: usize) {
968        self.chain_hash = new_hash;
969        self.entry_count = count;
970        self.last_verification = Utc::now();
971    }
972
973    fn get_current_hash(&self) -> Option<String> {
974        if self.entry_count > 0 {
975            Some(self.chain_hash.clone())
976        } else {
977            None
978        }
979    }
980}
981
982impl Default for RetentionPolicy {
983    fn default() -> Self {
984        let mut by_event_type = HashMap::new();
985        by_event_type.insert(AuditEventType::SecurityViolation, 2555); // 7 years
986        by_event_type.insert(AuditEventType::Authentication, 365);      // 1 year
987        by_event_type.insert(AuditEventType::DataAccess, 1095);         // 3 years
988
989        let mut by_compliance_tag = HashMap::new();
990        by_compliance_tag.insert(ComplianceTag::SOX, 2555);    // 7 years for SOX
991        by_compliance_tag.insert(ComplianceTag::HIPAA, 2190);  // 6 years for HIPAA
992        by_compliance_tag.insert(ComplianceTag::GDPR, 1095);   // 3 years for GDPR
993
994        Self {
995            default_retention_days: 365,
996            by_event_type,
997            by_compliance_tag,
998            archive_after_days: 180,
999            auto_delete_after_days: None,
1000        }
1001    }
1002}
1003
1004impl Default for ComplianceSettings {
1005    fn default() -> Self {
1006        Self {
1007            enabled_frameworks: [ComplianceTag::SOX, ComplianceTag::GDPR, ComplianceTag::ISO27001].into_iter().collect(),
1008            minimum_retention_days: 365,
1009            require_integrity_verification: true,
1010            real_time_monitoring: true,
1011            automatic_reporting: false,
1012            data_anonymization_after_days: Some(1095),
1013        }
1014    }
1015}
1016
1017impl Default for AuditManager {
1018    fn default() -> Self {
1019        Self::new()
1020    }
1021}
1022
1023#[cfg(test)]
1024mod tests {
1025    use super::*;
1026
1027    #[test]
1028    fn test_audit_manager_creation() {
1029        let audit_manager = AuditManager::new();
1030        assert_eq!(audit_manager.audit_entries.len(), 0);
1031        assert!(audit_manager.compliance_settings.enabled_frameworks.len() > 0);
1032    }
1033
1034    #[test]
1035    fn test_audit_event_logging() {
1036        let mut audit_manager = AuditManager::new();
1037        let entry_id = audit_manager.log_audit_event(
1038            AuditEventType::Authentication,
1039            "user123".to_string(),
1040            "login".to_string(),
1041            "system".to_string(),
1042            AuditOutcome::Success,
1043            None,
1044        ).unwrap();
1045
1046        assert!(!entry_id.is_empty());
1047        assert_eq!(audit_manager.audit_entries.len(), 1);
1048        assert_eq!(audit_manager.audit_entries[0].user_id, "user123");
1049        assert_eq!(audit_manager.audit_entries[0].event_type, AuditEventType::Authentication);
1050    }
1051
1052    #[test]
1053    fn test_integrity_verification() {
1054        let mut audit_manager = AuditManager::new();
1055        
1056        // Add some entries
1057        for i in 0..5 {
1058            audit_manager.log_audit_event(
1059                AuditEventType::DataAccess,
1060                format!("user{}", i),
1061                "read".to_string(),
1062                "database".to_string(),
1063                AuditOutcome::Success,
1064                None,
1065            ).unwrap();
1066        }
1067
1068        let integrity_status = audit_manager.verify_integrity();
1069        assert!(integrity_status.chain_verified);
1070        assert!(!integrity_status.tamper_detected);
1071        assert_eq!(integrity_status.total_entries, 5);
1072        assert!(integrity_status.verification_errors.is_empty());
1073    }
1074
1075    #[test]
1076    fn test_compliance_report_generation() {
1077        let mut audit_manager = AuditManager::new();
1078        let start_time = Utc::now() - Duration::hours(1);
1079        let end_time = Utc::now();
1080
1081        // Add some test events
1082        audit_manager.log_audit_event(
1083            AuditEventType::DataAccess,
1084            "user123".to_string(),
1085            "read_personal_data".to_string(),
1086            "customer_database".to_string(),
1087            AuditOutcome::Success,
1088            None,
1089        ).unwrap();
1090
1091        let report = audit_manager.generate_compliance_report(
1092            ComplianceTag::GDPR,
1093            start_time,
1094            end_time,
1095        ).unwrap();
1096
1097        assert!(!report.report_id.is_empty());
1098        assert_eq!(report.framework, ComplianceTag::GDPR);
1099        assert!(report.total_events > 0);
1100        assert!(!report.recommendations.is_empty());
1101    }
1102
1103    #[test]
1104    fn test_audit_search() {
1105        let mut audit_manager = AuditManager::new();
1106
1107        // Add test entries
1108        audit_manager.log_audit_event(
1109            AuditEventType::Authentication,
1110            "user1".to_string(),
1111            "login".to_string(),
1112            "system".to_string(),
1113            AuditOutcome::Success,
1114            None,
1115        ).unwrap();
1116
1117        audit_manager.log_audit_event(
1118            AuditEventType::DataAccess,
1119            "user2".to_string(),
1120            "read".to_string(),
1121            "database".to_string(),
1122            AuditOutcome::Success,
1123            None,
1124        ).unwrap();
1125
1126        let criteria = AuditSearchCriteria {
1127            user_id: Some("user1".to_string()),
1128            event_types: None,
1129            resources: None,
1130            start_time: None,
1131            end_time: None,
1132            risk_levels: None,
1133            compliance_tags: None,
1134            ip_addresses: None,
1135            outcomes: None,
1136            text_search: None,
1137        };
1138
1139        let results = audit_manager.search_audit_entries(&criteria, None);
1140        assert_eq!(results.len(), 1);
1141        assert_eq!(results[0].user_id, "user1");
1142    }
1143}