auth_framework/analytics/
mod.rs

1//! Analytics and monitoring for RBAC systems
2//!
3//! This module provides comprehensive analytics capabilities for monitoring
4//! and analyzing RBAC usage patterns, security compliance, and system performance.
5
6use serde::{Deserialize, Serialize};
7use std::collections::HashMap;
8use tokio::time::{Duration, Instant};
9
10pub mod compliance;
11pub mod dashboard;
12pub mod metrics;
13pub mod reports;
14
15/// Analytics configuration
16#[derive(Debug, Clone, Serialize, Deserialize)]
17pub struct AnalyticsConfig {
18    /// Enable real-time analytics
19    pub real_time_enabled: bool,
20
21    /// Data retention period
22    pub data_retention_days: u32,
23
24    /// Metrics collection interval
25    pub collection_interval: Duration,
26
27    /// Enable security compliance monitoring
28    pub compliance_monitoring: bool,
29
30    /// Enable performance monitoring
31    pub performance_monitoring: bool,
32
33    /// Maximum number of events to buffer
34    pub max_event_buffer: usize,
35}
36
37impl Default for AnalyticsConfig {
38    fn default() -> Self {
39        Self {
40            real_time_enabled: true,
41            data_retention_days: 90,
42            collection_interval: Duration::from_secs(60),
43            compliance_monitoring: true,
44            performance_monitoring: true,
45            max_event_buffer: 10000,
46        }
47    }
48}
49
50/// RBAC analytics event types
51#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
52pub enum RbacEventType {
53    /// Role assignment/revocation
54    RoleAssignment,
55    /// Permission check
56    PermissionCheck,
57    /// Role creation/modification
58    RoleManagement,
59    /// User authentication
60    Authentication,
61    /// Authorization decision
62    Authorization,
63    /// Policy violation
64    PolicyViolation,
65    /// Privilege escalation attempt
66    PrivilegeEscalation,
67    /// Access pattern anomaly
68    AccessAnomaly,
69}
70
71/// Analytics event data
72#[derive(Debug, Clone, Serialize, Deserialize)]
73pub struct AnalyticsEvent {
74    /// Unique event ID
75    pub id: String,
76
77    /// Event type
78    pub event_type: RbacEventType,
79
80    /// Timestamp
81    pub timestamp: chrono::DateTime<chrono::Utc>,
82
83    /// User ID (if applicable)
84    pub user_id: Option<String>,
85
86    /// Role ID (if applicable)
87    pub role_id: Option<String>,
88
89    /// Permission/resource (if applicable)
90    pub resource: Option<String>,
91
92    /// Action performed
93    pub action: Option<String>,
94
95    /// Result of the operation
96    pub result: EventResult,
97
98    /// Additional metadata
99    pub metadata: HashMap<String, String>,
100
101    /// Processing duration (milliseconds)
102    pub duration_ms: Option<u64>,
103
104    /// Source IP address
105    pub source_ip: Option<String>,
106
107    /// User agent
108    pub user_agent: Option<String>,
109}
110
111/// Event result types
112#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
113pub enum EventResult {
114    Success,
115    Failure,
116    Denied,
117    Error,
118}
119
120/// Role usage statistics
121#[derive(Debug, Clone, Serialize, Deserialize)]
122pub struct RoleUsageStats {
123    /// Role ID
124    pub role_id: String,
125
126    /// Role name
127    pub role_name: String,
128
129    /// Number of users assigned to this role
130    pub user_count: u32,
131
132    /// Number of permission checks for this role
133    pub permission_checks: u64,
134
135    /// Number of successful access attempts
136    pub successful_access: u64,
137
138    /// Number of denied access attempts
139    pub denied_access: u64,
140
141    /// Last time this role was used
142    pub last_used: Option<chrono::DateTime<chrono::Utc>>,
143
144    /// Average response time for permission checks (ms)
145    pub avg_response_time_ms: f64,
146
147    /// Most frequently accessed resources
148    pub top_resources: Vec<ResourceAccess>,
149}
150
151/// Resource access statistics
152#[derive(Debug, Clone, Serialize, Deserialize)]
153pub struct ResourceAccess {
154    /// Resource identifier
155    pub resource: String,
156
157    /// Number of access attempts
158    pub access_count: u64,
159
160    /// Success rate (0.0 to 1.0)
161    pub success_rate: f64,
162}
163
164/// Permission usage analytics
165#[derive(Debug, Clone, Serialize, Deserialize)]
166pub struct PermissionUsageStats {
167    /// Permission identifier
168    pub permission_id: String,
169
170    /// Number of checks for this permission
171    pub check_count: u64,
172
173    /// Success rate
174    pub success_rate: f64,
175
176    /// Roles that use this permission
177    pub used_by_roles: Vec<String>,
178
179    /// Most active users for this permission
180    pub top_users: Vec<UserActivity>,
181
182    /// Peak usage times
183    pub peak_hours: Vec<u8>, // Hours of day (0-23)
184}
185
186/// User activity statistics
187#[derive(Debug, Clone, Serialize, Deserialize)]
188pub struct UserActivity {
189    /// User ID
190    pub user_id: String,
191
192    /// Number of actions
193    pub activity_count: u64,
194
195    /// Last activity timestamp
196    pub last_activity: chrono::DateTime<chrono::Utc>,
197}
198
199/// Security compliance metrics
200#[derive(Debug, Clone, Serialize, Deserialize)]
201pub struct ComplianceMetrics {
202    /// Percentage of users with appropriate role assignments
203    pub role_assignment_compliance: f64,
204
205    /// Percentage of permissions properly scoped
206    pub permission_scoping_compliance: f64,
207
208    /// Number of orphaned permissions
209    pub orphaned_permissions: u32,
210
211    /// Number of over-privileged users
212    pub over_privileged_users: u32,
213
214    /// Number of unused roles
215    pub unused_roles: u32,
216
217    /// Average time to revoke access (hours)
218    pub avg_access_revocation_time_hours: f64,
219
220    /// Policy violations in the last period
221    pub policy_violations: u32,
222
223    /// Security incidents related to RBAC
224    pub security_incidents: u32,
225}
226
227/// Performance metrics for RBAC operations
228#[derive(Debug, Clone, Serialize, Deserialize)]
229pub struct PerformanceMetrics {
230    /// Average permission check latency (ms)
231    pub avg_permission_check_latency_ms: f64,
232
233    /// 95th percentile permission check latency (ms)
234    pub p95_permission_check_latency_ms: f64,
235
236    /// 99th percentile permission check latency (ms)
237    pub p99_permission_check_latency_ms: f64,
238
239    /// Total number of permission checks per second
240    pub permission_checks_per_second: f64,
241
242    /// Cache hit rate for permission checks
243    pub permission_cache_hit_rate: f64,
244
245    /// Error rate for RBAC operations
246    pub error_rate: f64,
247
248    /// System resource utilization
249    pub cpu_usage_percent: f64,
250
251    /// Memory usage (MB)
252    pub memory_usage_mb: u64,
253}
254
255/// Time-based analytics data
256#[derive(Debug, Clone, Serialize, Deserialize)]
257pub struct TimeSeriesData {
258    /// Timestamp
259    pub timestamp: chrono::DateTime<chrono::Utc>,
260
261    /// Metric value
262    pub value: f64,
263
264    /// Additional tags/dimensions
265    pub tags: HashMap<String, String>,
266}
267
268/// Analytics trend information
269#[derive(Debug, Clone, Serialize, Deserialize)]
270pub struct TrendAnalysis {
271    /// Metric name
272    pub metric_name: String,
273
274    /// Current value
275    pub current_value: f64,
276
277    /// Value from previous period
278    pub previous_value: f64,
279
280    /// Percentage change
281    pub change_percent: f64,
282
283    /// Trend direction
284    pub trend: TrendDirection,
285
286    /// Time series data points
287    pub data_points: Vec<TimeSeriesData>,
288}
289
290/// Trend direction
291#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
292pub enum TrendDirection {
293    Increasing,
294    Decreasing,
295    Stable,
296    Volatile,
297}
298
299/// Main analytics manager
300pub struct AnalyticsManager {
301    config: AnalyticsConfig,
302    event_buffer: Vec<AnalyticsEvent>,
303    last_collection: Instant,
304}
305
306impl AnalyticsManager {
307    /// Create new analytics manager
308    pub fn new(config: AnalyticsConfig) -> Self {
309        Self {
310            config,
311            event_buffer: Vec::new(),
312            last_collection: Instant::now(),
313        }
314    }
315
316    /// Record an analytics event
317    pub async fn record_event(&mut self, event: AnalyticsEvent) -> Result<(), AnalyticsError> {
318        if self.event_buffer.len() >= self.config.max_event_buffer {
319            self.flush_events().await?;
320        }
321
322        self.event_buffer.push(event);
323
324        if self.config.real_time_enabled {
325            // Process event immediately for real-time analytics
326            self.process_real_time_event(self.event_buffer.last().unwrap())
327                .await?;
328        }
329
330        Ok(())
331    }
332
333    /// Get role usage statistics
334    pub async fn get_role_usage_stats(
335        &self,
336        _role_id: Option<&str>,
337        _time_range: Option<TimeRange>,
338    ) -> Result<Vec<RoleUsageStats>, AnalyticsError> {
339        // Implementation would query stored analytics data
340        Ok(vec![])
341    }
342
343    /// Get permission usage statistics
344    pub async fn get_permission_usage_stats(
345        &self,
346        _permission_id: Option<&str>,
347        _time_range: Option<TimeRange>,
348    ) -> Result<Vec<PermissionUsageStats>, AnalyticsError> {
349        // Implementation would query stored analytics data
350        Ok(vec![])
351    }
352
353    /// Get compliance metrics
354    pub async fn get_compliance_metrics(
355        &self,
356        _time_range: Option<TimeRange>,
357    ) -> Result<ComplianceMetrics, AnalyticsError> {
358        // Implementation would calculate compliance metrics
359        Ok(ComplianceMetrics {
360            role_assignment_compliance: 95.5,
361            permission_scoping_compliance: 88.2,
362            orphaned_permissions: 5,
363            over_privileged_users: 12,
364            unused_roles: 3,
365            avg_access_revocation_time_hours: 2.5,
366            policy_violations: 8,
367            security_incidents: 1,
368        })
369    }
370
371    /// Get performance metrics
372    pub async fn get_performance_metrics(
373        &self,
374        _time_range: Option<TimeRange>,
375    ) -> Result<PerformanceMetrics, AnalyticsError> {
376        // Implementation would calculate performance metrics
377        Ok(PerformanceMetrics {
378            avg_permission_check_latency_ms: 15.5,
379            p95_permission_check_latency_ms: 45.2,
380            p99_permission_check_latency_ms: 125.8,
381            permission_checks_per_second: 1250.0,
382            permission_cache_hit_rate: 0.92,
383            error_rate: 0.001,
384            cpu_usage_percent: 15.5,
385            memory_usage_mb: 512,
386        })
387    }
388
389    /// Get trend analysis for a specific metric
390    pub async fn get_trend_analysis(
391        &self,
392        metric_name: &str,
393        _time_range: TimeRange,
394    ) -> Result<TrendAnalysis, AnalyticsError> {
395        // Implementation would analyze trends
396        Ok(TrendAnalysis {
397            metric_name: metric_name.to_string(),
398            current_value: 100.0,
399            previous_value: 95.0,
400            change_percent: 5.26,
401            trend: TrendDirection::Increasing,
402            data_points: vec![],
403        })
404    }
405
406    /// Generate comprehensive analytics report
407    pub async fn generate_report(
408        &self,
409        report_type: ReportType,
410        time_range: TimeRange,
411    ) -> Result<AnalyticsReport, AnalyticsError> {
412        let role_stats = self
413            .get_role_usage_stats(None, Some(time_range.clone()))
414            .await?;
415        let permission_stats = self
416            .get_permission_usage_stats(None, Some(time_range.clone()))
417            .await?;
418        let compliance_metrics = self
419            .get_compliance_metrics(Some(time_range.clone()))
420            .await?;
421        let performance_metrics = self
422            .get_performance_metrics(Some(time_range.clone()))
423            .await?;
424
425        Ok(AnalyticsReport {
426            report_type,
427            time_range,
428            generated_at: chrono::Utc::now(),
429            role_stats,
430            permission_stats,
431            compliance_metrics: compliance_metrics.clone(),
432            performance_metrics: performance_metrics.clone(),
433            summary: self.generate_report_summary(&compliance_metrics, &performance_metrics),
434        })
435    }
436
437    /// Flush buffered events
438    async fn flush_events(&mut self) -> Result<(), AnalyticsError> {
439        if self.event_buffer.is_empty() {
440            return Ok(());
441        }
442
443        // Implementation would persist events to storage
444        // For now, we'll just clear the buffer
445        self.event_buffer.clear();
446        self.last_collection = Instant::now();
447
448        Ok(())
449    }
450
451    /// Process event for real-time analytics
452    async fn process_real_time_event(&self, _event: &AnalyticsEvent) -> Result<(), AnalyticsError> {
453        // Implementation would update real-time metrics
454        Ok(())
455    }
456
457    /// Generate report summary
458    fn generate_report_summary(
459        &self,
460        compliance: &ComplianceMetrics,
461        performance: &PerformanceMetrics,
462    ) -> String {
463        format!(
464            "RBAC Analytics Summary: {}% compliance, {:.1}ms avg latency, {:.1}% error rate",
465            compliance.role_assignment_compliance,
466            performance.avg_permission_check_latency_ms,
467            performance.error_rate * 100.0
468        )
469    }
470}
471
472/// Time range for analytics queries
473#[derive(Debug, Clone, Serialize, Deserialize)]
474pub struct TimeRange {
475    pub start: chrono::DateTime<chrono::Utc>,
476    pub end: chrono::DateTime<chrono::Utc>,
477}
478
479impl TimeRange {
480    /// Create time range for the last N hours
481    pub fn last_hours(hours: u32) -> Self {
482        let end = chrono::Utc::now();
483        let start = end - chrono::Duration::hours(hours as i64);
484        Self { start, end }
485    }
486
487    /// Create time range for the last N days
488    pub fn last_days(days: u32) -> Self {
489        let end = chrono::Utc::now();
490        let start = end - chrono::Duration::days(days as i64);
491        Self { start, end }
492    }
493
494    /// Create time range for today
495    pub fn today() -> Self {
496        let now = chrono::Utc::now();
497        let start = now.date_naive().and_hms_opt(0, 0, 0).unwrap().and_utc();
498        let end = now;
499        Self { start, end }
500    }
501}
502
503/// Report types
504#[derive(Debug, Clone, Serialize, Deserialize)]
505pub enum ReportType {
506    /// Daily summary report
507    Daily,
508    /// Weekly summary report
509    Weekly,
510    /// Monthly summary report
511    Monthly,
512    /// Security compliance report
513    Compliance,
514    /// Performance analysis report
515    Performance,
516    /// Custom report with specific criteria
517    Custom(String),
518}
519
520/// Comprehensive analytics report
521#[derive(Debug, Clone, Serialize, Deserialize)]
522pub struct AnalyticsReport {
523    pub report_type: ReportType,
524    pub time_range: TimeRange,
525    pub generated_at: chrono::DateTime<chrono::Utc>,
526    pub role_stats: Vec<RoleUsageStats>,
527    pub permission_stats: Vec<PermissionUsageStats>,
528    pub compliance_metrics: ComplianceMetrics,
529    pub performance_metrics: PerformanceMetrics,
530    pub summary: String,
531}
532
533/// Analytics-related errors
534#[derive(Debug, thiserror::Error)]
535pub enum AnalyticsError {
536    #[error("Data processing error: {0}")]
537    ProcessingError(String),
538
539    #[error("Storage error: {0}")]
540    StorageError(String),
541
542    #[error("Query error: {0}")]
543    QueryError(String),
544
545    #[error("Configuration error: {0}")]
546    ConfigError(String),
547
548    #[error("IO error: {0}")]
549    IoError(#[from] std::io::Error),
550
551    #[error("Serialization error: {0}")]
552    SerializationError(#[from] serde_json::Error),
553}
554
555#[cfg(test)]
556mod tests {
557    use super::*;
558
559    #[test]
560    fn test_analytics_config_default() {
561        let config = AnalyticsConfig::default();
562        assert!(config.real_time_enabled);
563        assert_eq!(config.data_retention_days, 90);
564        assert!(config.compliance_monitoring);
565    }
566
567    #[test]
568    fn test_time_range_creation() {
569        let range = TimeRange::last_hours(24);
570        assert!(range.end > range.start);
571
572        let today = TimeRange::today();
573        assert!(today.end > today.start);
574    }
575
576    #[tokio::test]
577    async fn test_analytics_manager_creation() {
578        let config = AnalyticsConfig::default();
579        let manager = AnalyticsManager::new(config);
580        assert_eq!(manager.event_buffer.len(), 0);
581    }
582
583    #[tokio::test]
584    async fn test_record_event() {
585        let config = AnalyticsConfig::default();
586        let mut manager = AnalyticsManager::new(config);
587
588        let event = AnalyticsEvent {
589            id: "test_event_1".to_string(),
590            event_type: RbacEventType::PermissionCheck,
591            timestamp: chrono::Utc::now(),
592            user_id: Some("user123".to_string()),
593            role_id: Some("admin".to_string()),
594            resource: Some("user_data".to_string()),
595            action: Some("read".to_string()),
596            result: EventResult::Success,
597            metadata: HashMap::new(),
598            duration_ms: Some(15),
599            source_ip: Some("192.168.1.1".to_string()),
600            user_agent: Some("TestAgent/1.0".to_string()),
601        };
602
603        let result = manager.record_event(event).await;
604        assert!(result.is_ok());
605        assert_eq!(manager.event_buffer.len(), 1);
606    }
607}
608
609