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
8pub 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#[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#[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#[derive(Debug, Clone, Serialize, Deserialize)]
66pub enum AuditOutcome {
67 Success,
68 Failure,
69 Partial,
70 Warning,
71 Blocked,
72 Escalated,
73}
74
75#[derive(Debug, Clone, Serialize, Deserialize, PartialOrd, PartialEq, Eq, Ord, Hash)]
77pub enum RiskLevel {
78 Low,
79 Medium,
80 High,
81 Critical,
82}
83
84#[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#[derive(Debug, Clone, Serialize, Deserialize, Hash, PartialEq, Eq, PartialOrd, Ord)]
98pub enum ComplianceTag {
99 SOX, GDPR, HIPAA, PciDss, ISO27001, NIST, COBIT, ITIL, }
108
109pub 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
120pub struct IntegrityChain {
122 chain_hash: String,
123 entry_count: usize,
124 last_verification: DateTime<Utc>,
125}
126
127#[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#[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#[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#[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#[derive(Debug, Clone, Serialize, Deserialize)]
172pub enum AlertOperator {
173 Equals,
174 NotEquals,
175 Contains,
176 FrequencyExceeds,
177 PatternMatches,
178 RiskLevelAbove,
179}
180
181#[derive(Debug, Clone, Serialize, Deserialize)]
183pub enum AlertSeverity {
184 Info,
185 Low,
186 Medium,
187 High,
188 Critical,
189}
190
191#[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#[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#[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#[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 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 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 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 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 let previous_hash = self.integrity_chain.get_current_hash();
286 let integrity_hash = self.calculate_integrity_hash(&entry_id, ×tamp, &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 let index = self.audit_entries.len();
314 self.audit_entries.push(entry.clone());
315
316 self.search_index.add_entry(index, &entry);
318
319 self.integrity_chain.update(integrity_hash, index + 1);
321
322 self.check_alert_rules(&entry);
324
325 if self.audit_entries.len().is_multiple_of(1000) {
327 self.apply_retention_policy();
328 }
329
330 Ok(entry_id)
331 }
332
333 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 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 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 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 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 results.sort_by(|a, b| b.timestamp.cmp(&a.timestamp));
435 results
436 }
437
438 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 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 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 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 let integrity_status = self.verify_integrity();
490
491 let risk_summary = self.generate_risk_summary(&relevant_entries);
493
494 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 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 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 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 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 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 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 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 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 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 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 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 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, 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 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); by_event_type.insert(AuditEventType::Authentication, 365); by_event_type.insert(AuditEventType::DataAccess, 1095); let mut by_compliance_tag = HashMap::new();
990 by_compliance_tag.insert(ComplianceTag::SOX, 2555); by_compliance_tag.insert(ComplianceTag::HIPAA, 2190); by_compliance_tag.insert(ComplianceTag::GDPR, 1095); 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 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 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 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}