Skip to main content

oxirs_gql/
zero_trust_security.rs

1//! Zero-Trust Security Architecture for GraphQL
2//!
3//! This module implements a comprehensive zero-trust security model with advanced
4//! authentication, authorization, threat detection, and continuous security monitoring.
5
6use anyhow::{anyhow, Result};
7use serde::{Deserialize, Serialize};
8use std::collections::{HashMap, HashSet, VecDeque};
9use std::net::IpAddr;
10use std::sync::Arc;
11use std::time::{Duration, SystemTime};
12use tokio::sync::{broadcast, Mutex as AsyncMutex, RwLock as AsyncRwLock};
13use tracing::{debug, info, warn};
14
15use crate::ast::{Document, OperationType};
16use crate::production::{JwtClaims, JwtConfig, JwtManager};
17
18/// Zero-trust security configuration
19#[derive(Debug, Clone)]
20pub struct ZeroTrustConfig {
21    pub enable_continuous_auth: bool,
22    pub enable_behavioral_analysis: bool,
23    pub enable_threat_detection: bool,
24    pub enable_data_loss_prevention: bool,
25    pub enable_encryption_at_rest: bool,
26    pub enable_network_segmentation: bool,
27    pub enable_device_trust: bool,
28    pub auth_token_lifetime: Duration,
29    pub session_timeout: Duration,
30    pub max_failed_attempts: usize,
31    pub rate_limiting: RateLimitConfig,
32    pub encryption_config: EncryptionConfig,
33    pub audit_config: AuditConfig,
34    pub threat_detection_config: ThreatDetectionConfig,
35    /// HMAC-SHA256 secret used to verify inbound JWT bearer tokens. When `None`,
36    /// [`ZeroTrustSecurityManager::authenticate_request`] rejects every request
37    /// (fail-closed) rather than fabricating an authenticated identity.
38    pub jwt_secret: Option<String>,
39    /// Optional expected `iss` (issuer) claim. When set, tokens whose issuer does
40    /// not match are rejected.
41    pub jwt_issuer: Option<String>,
42}
43
44impl Default for ZeroTrustConfig {
45    fn default() -> Self {
46        Self {
47            enable_continuous_auth: true,
48            enable_behavioral_analysis: true,
49            enable_threat_detection: true,
50            enable_data_loss_prevention: true,
51            enable_encryption_at_rest: true,
52            enable_network_segmentation: true,
53            enable_device_trust: true,
54            auth_token_lifetime: Duration::from_secs(3600),
55            session_timeout: Duration::from_secs(1800),
56            max_failed_attempts: 5,
57            rate_limiting: RateLimitConfig::default(),
58            encryption_config: EncryptionConfig::default(),
59            audit_config: AuditConfig::default(),
60            threat_detection_config: ThreatDetectionConfig::default(),
61            jwt_secret: None,
62            jwt_issuer: None,
63        }
64    }
65}
66
67/// Rate limiting configuration
68#[derive(Debug, Clone)]
69pub struct RateLimitConfig {
70    pub requests_per_minute: usize,
71    pub burst_capacity: usize,
72    pub sliding_window_duration: Duration,
73    pub enable_adaptive_limits: bool,
74    pub enable_ip_based_limiting: bool,
75    pub enable_user_based_limiting: bool,
76}
77
78impl Default for RateLimitConfig {
79    fn default() -> Self {
80        Self {
81            requests_per_minute: 1000,
82            burst_capacity: 100,
83            sliding_window_duration: Duration::from_secs(60),
84            enable_adaptive_limits: true,
85            enable_ip_based_limiting: true,
86            enable_user_based_limiting: true,
87        }
88    }
89}
90
91/// Encryption configuration
92#[derive(Debug, Clone)]
93pub struct EncryptionConfig {
94    pub algorithm: EncryptionAlgorithm,
95    pub key_rotation_interval: Duration,
96    pub enable_field_level_encryption: bool,
97    pub enable_query_encryption: bool,
98    pub enable_result_encryption: bool,
99    pub kms_integration: bool,
100}
101
102impl Default for EncryptionConfig {
103    fn default() -> Self {
104        Self {
105            algorithm: EncryptionAlgorithm::AES256GCM,
106            key_rotation_interval: Duration::from_secs(86400), // 24 hours
107            enable_field_level_encryption: true,
108            enable_query_encryption: true,
109            enable_result_encryption: true,
110            kms_integration: true,
111        }
112    }
113}
114
115#[derive(Debug, Clone)]
116pub enum EncryptionAlgorithm {
117    AES256GCM,
118    ChaCha20Poly1305,
119    AES256CTR,
120}
121
122/// Audit configuration
123#[derive(Debug, Clone)]
124pub struct AuditConfig {
125    pub enable_audit_logging: bool,
126    pub log_all_queries: bool,
127    pub log_authentication_events: bool,
128    pub log_authorization_events: bool,
129    pub log_data_access: bool,
130    pub log_admin_actions: bool,
131    pub retention_period: Duration,
132    pub enable_real_time_alerts: bool,
133}
134
135impl Default for AuditConfig {
136    fn default() -> Self {
137        Self {
138            enable_audit_logging: true,
139            log_all_queries: true,
140            log_authentication_events: true,
141            log_authorization_events: true,
142            log_data_access: true,
143            log_admin_actions: true,
144            retention_period: Duration::from_secs(86400 * 365), // 1 year
145            enable_real_time_alerts: true,
146        }
147    }
148}
149
150/// Threat detection configuration
151#[derive(Debug, Clone)]
152pub struct ThreatDetectionConfig {
153    pub enable_anomaly_detection: bool,
154    pub enable_pattern_matching: bool,
155    pub enable_ml_threat_detection: bool,
156    pub enable_network_analysis: bool,
157    pub threat_score_threshold: f64,
158    pub response_actions: Vec<ThreatResponseAction>,
159}
160
161impl Default for ThreatDetectionConfig {
162    fn default() -> Self {
163        Self {
164            enable_anomaly_detection: true,
165            enable_pattern_matching: true,
166            enable_ml_threat_detection: true,
167            enable_network_analysis: true,
168            threat_score_threshold: 0.7,
169            response_actions: vec![
170                ThreatResponseAction::LogEvent,
171                ThreatResponseAction::NotifyAdmin,
172                ThreatResponseAction::IncreaseMonitoring,
173            ],
174        }
175    }
176}
177
178#[derive(Debug, Clone)]
179pub enum ThreatResponseAction {
180    LogEvent,
181    NotifyAdmin,
182    BlockUser,
183    BlockIP,
184    RequireReauth,
185    IncreaseMonitoring,
186    RevokeTokens,
187    TriggerCircuitBreaker,
188}
189
190/// Security context for requests
191#[derive(Debug, Clone)]
192pub struct SecurityContext {
193    pub user_id: Option<String>,
194    pub session_id: String,
195    pub device_id: Option<String>,
196    pub ip_address: IpAddr,
197    pub user_agent: Option<String>,
198    pub auth_level: AuthenticationLevel,
199    pub permissions: HashSet<Permission>,
200    pub trust_score: f64,
201    pub session_start: SystemTime,
202    pub last_activity: SystemTime,
203    pub authentication_factors: Vec<AuthenticationFactor>,
204    pub risk_factors: Vec<RiskFactor>,
205}
206
207/// Authentication levels
208#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord)]
209pub enum AuthenticationLevel {
210    Anonymous,
211    Basic,
212    MultiFactorAuthenticated,
213    CertificateBased,
214    BiometricVerified,
215}
216
217/// Permissions in the system
218#[derive(Debug, Clone, Hash, PartialEq, Eq)]
219pub enum Permission {
220    ReadData,
221    WriteData,
222    DeleteData,
223    AdminAccess,
224    QueryIntrospection,
225    SchemaAccess,
226    MetricsAccess,
227    AuditLogAccess,
228    UserManagement,
229    SystemConfiguration,
230}
231
232/// Authentication factors
233#[derive(Debug, Clone)]
234pub enum AuthenticationFactor {
235    Password {
236        verified_at: SystemTime,
237    },
238    TwoFactorCode {
239        verified_at: SystemTime,
240    },
241    BiometricScan {
242        scan_type: BiometricType,
243        verified_at: SystemTime,
244    },
245    HardwareToken {
246        token_id: String,
247        verified_at: SystemTime,
248    },
249    CertificateAuth {
250        cert_fingerprint: String,
251        verified_at: SystemTime,
252    },
253}
254
255#[derive(Debug, Clone)]
256pub enum BiometricType {
257    Fingerprint,
258    FaceRecognition,
259    VoicePrint,
260    IrisScanning,
261}
262
263/// Risk factors for security assessment
264#[derive(Debug, Clone)]
265pub struct RiskFactor {
266    pub factor_type: RiskFactorType,
267    pub severity: RiskSeverity,
268    pub description: String,
269    pub detected_at: SystemTime,
270    pub auto_mitigated: bool,
271}
272
273#[derive(Debug, Clone)]
274pub enum RiskFactorType {
275    UnusualLocation,
276    NewDevice,
277    SuspiciousQuery,
278    HighFailureRate,
279    DataExfiltrationAttempt,
280    PrivilegeEscalation,
281    AnomalousAccess,
282    NetworkAnomaly,
283}
284
285#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Serialize, Deserialize)]
286pub enum RiskSeverity {
287    Low,
288    Medium,
289    High,
290    Critical,
291}
292
293/// Security event for audit logging
294#[derive(Debug, Clone, Serialize, Deserialize)]
295pub struct SecurityEvent {
296    pub event_id: String,
297    pub event_type: SecurityEventType,
298    pub severity: RiskSeverity,
299    pub user_id: Option<String>,
300    pub session_id: String,
301    pub ip_address: IpAddr,
302    pub timestamp: SystemTime,
303    pub description: String,
304    pub metadata: HashMap<String, String>,
305    pub threat_score: Option<f64>,
306    pub mitigated: bool,
307}
308
309#[derive(Debug, Clone, Serialize, Deserialize)]
310pub enum SecurityEventType {
311    AuthenticationAttempt,
312    AuthenticationFailure,
313    AuthenticationSuccess,
314    AuthorizationDenied,
315    SuspiciousQuery,
316    DataAccess,
317    AdminAction,
318    ThreatDetected,
319    SecurityViolation,
320    PolicyEnforcement,
321}
322
323/// Behavioral analysis data
324#[derive(Debug, Clone)]
325pub struct BehavioralProfile {
326    pub user_id: String,
327    pub typical_access_patterns: Vec<AccessPattern>,
328    pub common_query_types: HashSet<String>,
329    pub usual_access_times: Vec<TimeRange>,
330    pub typical_locations: HashSet<IpAddr>,
331    pub baseline_metrics: BaselineMetrics,
332    pub last_updated: SystemTime,
333}
334
335#[derive(Debug, Clone)]
336pub struct AccessPattern {
337    pub pattern_type: String,
338    pub frequency: f64,
339    pub typical_duration: Duration,
340    pub confidence: f64,
341}
342
343#[derive(Debug, Clone)]
344pub struct TimeRange {
345    pub start_hour: u8,
346    pub end_hour: u8,
347    pub days_of_week: HashSet<u8>,
348}
349
350#[derive(Debug, Clone)]
351pub struct BaselineMetrics {
352    pub avg_queries_per_session: f64,
353    pub avg_session_duration: Duration,
354    pub typical_query_complexity: f64,
355    pub common_field_access: HashSet<String>,
356}
357
358/// Main zero-trust security manager
359pub struct ZeroTrustSecurityManager {
360    config: ZeroTrustConfig,
361    active_sessions: Arc<AsyncRwLock<HashMap<String, SecurityContext>>>,
362    rate_limiters: Arc<AsyncRwLock<HashMap<String, RateLimiter>>>,
363    behavioral_profiles: Arc<AsyncRwLock<HashMap<String, BehavioralProfile>>>,
364    threat_detector: Arc<AsyncMutex<ThreatDetector>>,
365    audit_logger: Arc<AsyncMutex<AuditLogger>>,
366    encryption_manager: Arc<AsyncMutex<EncryptionManager>>,
367    security_event_sender: broadcast::Sender<SecurityEvent>,
368    blocked_ips: Arc<AsyncRwLock<HashSet<IpAddr>>>,
369    blocked_users: Arc<AsyncRwLock<HashSet<String>>>,
370}
371
372impl ZeroTrustSecurityManager {
373    /// Create a new zero-trust security manager
374    pub fn new(config: ZeroTrustConfig) -> (Self, broadcast::Receiver<SecurityEvent>) {
375        let (security_event_sender, security_event_receiver) = broadcast::channel(1000);
376
377        let manager = Self {
378            config: config.clone(),
379            active_sessions: Arc::new(AsyncRwLock::new(HashMap::new())),
380            rate_limiters: Arc::new(AsyncRwLock::new(HashMap::new())),
381            behavioral_profiles: Arc::new(AsyncRwLock::new(HashMap::new())),
382            threat_detector: Arc::new(AsyncMutex::new(ThreatDetector::new(
383                &config.threat_detection_config,
384            ))),
385            audit_logger: Arc::new(AsyncMutex::new(AuditLogger::new(&config.audit_config))),
386            encryption_manager: Arc::new(AsyncMutex::new(EncryptionManager::new(
387                &config.encryption_config,
388            ))),
389            security_event_sender,
390            blocked_ips: Arc::new(AsyncRwLock::new(HashSet::new())),
391            blocked_users: Arc::new(AsyncRwLock::new(HashSet::new())),
392        };
393
394        (manager, security_event_receiver)
395    }
396
397    /// Authenticate and authorize a request
398    pub async fn authenticate_request(&self, request: &SecurityRequest) -> Result<SecurityContext> {
399        info!("Authenticating request from {}", request.ip_address);
400
401        // Check if IP is blocked
402        if self.is_ip_blocked(request.ip_address).await? {
403            return Err(anyhow!("IP address blocked"));
404        }
405
406        // Check if user is blocked
407        if let Some(ref user_id) = request.user_id {
408            if self.is_user_blocked(user_id).await? {
409                return Err(anyhow!("User account blocked"));
410            }
411        }
412
413        // Rate limiting check
414        self.check_rate_limits(request).await?;
415
416        // Validate authentication token
417        let auth_info = self
418            .validate_authentication_token(&request.auth_token)
419            .await?;
420
421        // Create security context
422        let mut context = SecurityContext {
423            user_id: auth_info.user_id,
424            session_id: auth_info.session_id,
425            device_id: request.device_id.clone(),
426            ip_address: request.ip_address,
427            user_agent: request.user_agent.clone(),
428            auth_level: auth_info.auth_level,
429            permissions: auth_info.permissions,
430            trust_score: 1.0, // Will be calculated
431            session_start: auth_info.session_start,
432            last_activity: SystemTime::now(),
433            authentication_factors: auth_info.authentication_factors,
434            risk_factors: Vec::new(),
435        };
436
437        // Calculate trust score
438        context.trust_score = self.calculate_trust_score(&context, request).await?;
439
440        // Perform behavioral analysis
441        if self.config.enable_behavioral_analysis {
442            self.analyze_behavior(&mut context, request).await?;
443        }
444
445        // Threat detection
446        if self.config.enable_threat_detection {
447            self.detect_threats(&mut context, request).await?;
448        }
449
450        // Store active session
451        self.active_sessions
452            .write()
453            .await
454            .insert(context.session_id.clone(), context.clone());
455
456        // Log authentication event
457        self.log_security_event(SecurityEvent {
458            event_id: uuid::Uuid::new_v4().to_string(),
459            event_type: SecurityEventType::AuthenticationSuccess,
460            severity: RiskSeverity::Low,
461            user_id: context.user_id.clone(),
462            session_id: context.session_id.clone(),
463            ip_address: context.ip_address,
464            timestamp: SystemTime::now(),
465            description: "User authenticated successfully".to_string(),
466            metadata: HashMap::new(),
467            threat_score: Some(context.trust_score),
468            mitigated: false,
469        })
470        .await?;
471
472        Ok(context)
473    }
474
475    /// Authorize a GraphQL query
476    pub async fn authorize_query(
477        &self,
478        context: &SecurityContext,
479        query: &Document,
480    ) -> Result<AuthorizationResult> {
481        debug!("Authorizing query for user {:?}", context.user_id);
482
483        // Check session validity
484        self.validate_session(context).await?;
485
486        // Extract required permissions from query
487        let required_permissions = self.extract_query_permissions(query).await?;
488
489        // Check permissions
490        let mut missing_permissions = Vec::new();
491        for permission in &required_permissions {
492            if !context.permissions.contains(permission) {
493                missing_permissions.push(permission.clone());
494            }
495        }
496
497        if !missing_permissions.is_empty() {
498            // Log authorization denial
499            self.log_security_event(SecurityEvent {
500                event_id: uuid::Uuid::new_v4().to_string(),
501                event_type: SecurityEventType::AuthorizationDenied,
502                severity: RiskSeverity::Medium,
503                user_id: context.user_id.clone(),
504                session_id: context.session_id.clone(),
505                ip_address: context.ip_address,
506                timestamp: SystemTime::now(),
507                description: format!(
508                    "Authorization denied - missing permissions: {missing_permissions:?}"
509                ),
510                metadata: HashMap::new(),
511                threat_score: None,
512                mitigated: false,
513            })
514            .await?;
515
516            return Err(anyhow!(
517                "Insufficient permissions: {:?}",
518                missing_permissions
519            ));
520        }
521
522        // Analyze query for suspicious patterns
523        let suspicious_score = self.analyze_query_suspiciousness(query).await?;
524
525        // Apply data loss prevention
526        if self.config.enable_data_loss_prevention {
527            self.apply_data_loss_prevention(context, query).await?;
528        }
529
530        Ok(AuthorizationResult {
531            authorized: true,
532            required_permissions,
533            applied_filters: Vec::new(),
534            suspicious_score,
535            additional_monitoring: suspicious_score > 0.5,
536        })
537    }
538
539    /// Encrypt sensitive data
540    pub async fn encrypt_data(&self, data: &str, context: &SecurityContext) -> Result<String> {
541        let encryption_manager = self.encryption_manager.lock().await;
542        encryption_manager.encrypt(data, &context.session_id).await
543    }
544
545    /// Decrypt sensitive data
546    pub async fn decrypt_data(
547        &self,
548        encrypted_data: &str,
549        context: &SecurityContext,
550    ) -> Result<String> {
551        let encryption_manager = self.encryption_manager.lock().await;
552        encryption_manager
553            .decrypt(encrypted_data, &context.session_id)
554            .await
555    }
556
557    /// Check if IP is blocked
558    async fn is_ip_blocked(&self, ip: IpAddr) -> Result<bool> {
559        let blocked_ips = self.blocked_ips.read().await;
560        Ok(blocked_ips.contains(&ip))
561    }
562
563    /// Check if user is blocked
564    async fn is_user_blocked(&self, user_id: &str) -> Result<bool> {
565        let blocked_users = self.blocked_users.read().await;
566        Ok(blocked_users.contains(user_id))
567    }
568
569    /// Check rate limits
570    async fn check_rate_limits(&self, request: &SecurityRequest) -> Result<()> {
571        let key = format!("{}:{:?}", request.ip_address, request.user_id);
572
573        let mut rate_limiters = self.rate_limiters.write().await;
574        let rate_limiter = rate_limiters
575            .entry(key)
576            .or_insert_with(|| RateLimiter::new(&self.config.rate_limiting));
577
578        if !rate_limiter.allow_request().await? {
579            return Err(anyhow!("Rate limit exceeded"));
580        }
581
582        Ok(())
583    }
584
585    /// Validate an inbound JWT bearer token.
586    ///
587    /// This performs real verification (HMAC-SHA256 signature, expiry, and — when
588    /// configured — issuer). It NEVER fabricates an identity: a missing secret,
589    /// empty token, bad signature, expired token, or issuer mismatch all return
590    /// `Err`, consistent with the module's zero-trust / fail-closed contract.
591    async fn validate_authentication_token(&self, token: &str) -> Result<AuthenticationInfo> {
592        // Fail closed if authentication is not configured.
593        let secret = self.config.jwt_secret.as_ref().ok_or_else(|| {
594            anyhow!(
595                "Zero-trust authentication is not configured (jwt_secret is None); \
596                 refusing to authenticate any request"
597            )
598        })?;
599
600        // Reject empty / obviously malformed tokens up front.
601        let token = token.trim();
602        let token = token.strip_prefix("Bearer ").unwrap_or(token).trim();
603        if token.is_empty() {
604            return Err(anyhow!("Missing authentication token"));
605        }
606
607        // Verify signature + expiry via the shared HMAC-SHA256 JWT manager.
608        let jwt_config = JwtConfig {
609            secret: secret.clone(),
610            issuer: self.config.jwt_issuer.clone(),
611            ..Default::default()
612        };
613        let manager = JwtManager::new(jwt_config)?;
614        let claims = manager
615            .verify_token(token)
616            .map_err(|e| anyhow!("Token verification failed: {e}"))?;
617
618        // Enforce issuer when an expected issuer is configured.
619        if let Some(expected_iss) = &self.config.jwt_issuer {
620            match &claims.iss {
621                Some(iss) if iss == expected_iss => {}
622                _ => return Err(anyhow!("Token issuer mismatch")),
623            }
624        }
625
626        Ok(Self::authentication_info_from_claims(&claims))
627    }
628
629    /// Map verified JWT claims onto an [`AuthenticationInfo`].
630    ///
631    /// Permissions are read from a `permissions` (or `scope`) custom claim; the
632    /// authentication level is read from an `auth_level` custom claim. Absent
633    /// claims grant the minimal capability (read-only, Basic) rather than a
634    /// broad default.
635    fn authentication_info_from_claims(claims: &JwtClaims) -> AuthenticationInfo {
636        let permissions = Self::permissions_from_claims(claims);
637        let auth_level = claims
638            .custom
639            .get("auth_level")
640            .and_then(|v| v.as_str())
641            .map(Self::parse_auth_level)
642            .unwrap_or(AuthenticationLevel::Basic);
643
644        AuthenticationInfo {
645            user_id: Some(claims.sub.clone()),
646            session_id: uuid::Uuid::new_v4().to_string(),
647            auth_level,
648            permissions,
649            session_start: SystemTime::now(),
650            authentication_factors: Vec::new(),
651        }
652    }
653
654    /// Extract granted permissions from the `permissions` or `scope` claim.
655    fn permissions_from_claims(claims: &JwtClaims) -> HashSet<Permission> {
656        let mut perms = HashSet::new();
657
658        // Collect string tokens from a `permissions` array or a space-delimited
659        // `scope` string (OAuth2 convention).
660        let mut raw: Vec<String> = Vec::new();
661        if let Some(v) = claims.custom.get("permissions") {
662            if let Some(arr) = v.as_array() {
663                raw.extend(arr.iter().filter_map(|x| x.as_str().map(String::from)));
664            } else if let Some(s) = v.as_str() {
665                raw.extend(s.split_whitespace().map(String::from));
666            }
667        }
668        if let Some(scope) = claims.custom.get("scope").and_then(|v| v.as_str()) {
669            raw.extend(scope.split_whitespace().map(String::from));
670        }
671
672        for token in raw {
673            if let Some(p) = Self::parse_permission(&token) {
674                perms.insert(p);
675            }
676        }
677
678        // A verified token always grants at least read access.
679        if perms.is_empty() {
680            perms.insert(Permission::ReadData);
681        }
682        perms
683    }
684
685    /// Parse a single permission string into a [`Permission`].
686    fn parse_permission(s: &str) -> Option<Permission> {
687        match s.to_ascii_lowercase().as_str() {
688            "read" | "readdata" | "read_data" | "read:data" => Some(Permission::ReadData),
689            "write" | "writedata" | "write_data" | "write:data" => Some(Permission::WriteData),
690            "delete" | "deletedata" | "delete_data" | "delete:data" => Some(Permission::DeleteData),
691            "admin" | "adminaccess" | "admin_access" => Some(Permission::AdminAccess),
692            "introspection" | "queryintrospection" => Some(Permission::QueryIntrospection),
693            "schema" | "schemaaccess" => Some(Permission::SchemaAccess),
694            "metrics" | "metricsaccess" => Some(Permission::MetricsAccess),
695            "audit" | "auditlogaccess" => Some(Permission::AuditLogAccess),
696            "usermanagement" | "user_management" => Some(Permission::UserManagement),
697            "systemconfiguration" | "system_configuration" => Some(Permission::SystemConfiguration),
698            _ => None,
699        }
700    }
701
702    /// Parse an authentication-level string into an [`AuthenticationLevel`].
703    fn parse_auth_level(s: &str) -> AuthenticationLevel {
704        match s.to_ascii_lowercase().as_str() {
705            "mfa" | "multifactor" | "multifactorauthenticated" => {
706                AuthenticationLevel::MultiFactorAuthenticated
707            }
708            "certificate" | "certificatebased" => AuthenticationLevel::CertificateBased,
709            "biometric" | "biometricverified" => AuthenticationLevel::BiometricVerified,
710            "anonymous" => AuthenticationLevel::Anonymous,
711            _ => AuthenticationLevel::Basic,
712        }
713    }
714
715    /// Calculate trust score
716    async fn calculate_trust_score(
717        &self,
718        context: &SecurityContext,
719        _request: &SecurityRequest,
720    ) -> Result<f64> {
721        let mut score: f64 = 1.0;
722
723        // Decrease score for risk factors
724        for risk_factor in &context.risk_factors {
725            match risk_factor.severity {
726                RiskSeverity::Low => score -= 0.1,
727                RiskSeverity::Medium => score -= 0.3,
728                RiskSeverity::High => score -= 0.5,
729                RiskSeverity::Critical => score -= 0.8,
730            }
731        }
732
733        // Increase score for strong authentication
734        match context.auth_level {
735            AuthenticationLevel::Anonymous => score -= 0.5,
736            AuthenticationLevel::Basic => score -= 0.2,
737            AuthenticationLevel::MultiFactorAuthenticated => score += 0.1,
738            AuthenticationLevel::CertificateBased => score += 0.2,
739            AuthenticationLevel::BiometricVerified => score += 0.3,
740        }
741
742        Ok(score.clamp(0.0, 1.0))
743    }
744
745    /// Analyze user behavior
746    async fn analyze_behavior(
747        &self,
748        context: &mut SecurityContext,
749        _request: &SecurityRequest,
750    ) -> Result<()> {
751        if let Some(ref user_id) = context.user_id {
752            let profiles = self.behavioral_profiles.read().await;
753            if let Some(profile) = profiles.get(user_id) {
754                // Check for deviations from normal behavior
755                if self
756                    .is_unusual_access_time(profile, SystemTime::now())
757                    .await?
758                {
759                    context.risk_factors.push(RiskFactor {
760                        factor_type: RiskFactorType::AnomalousAccess,
761                        severity: RiskSeverity::Medium,
762                        description: "Access outside normal hours".to_string(),
763                        detected_at: SystemTime::now(),
764                        auto_mitigated: false,
765                    });
766                }
767
768                if self
769                    .is_unusual_location(profile, context.ip_address)
770                    .await?
771                {
772                    context.risk_factors.push(RiskFactor {
773                        factor_type: RiskFactorType::UnusualLocation,
774                        severity: RiskSeverity::High,
775                        description: "Access from unusual location".to_string(),
776                        detected_at: SystemTime::now(),
777                        auto_mitigated: false,
778                    });
779                }
780            }
781        }
782
783        Ok(())
784    }
785
786    /// Detect threats
787    async fn detect_threats(
788        &self,
789        context: &mut SecurityContext,
790        request: &SecurityRequest,
791    ) -> Result<()> {
792        let mut threat_detector = self.threat_detector.lock().await;
793        let threats = threat_detector.analyze_request(context, request).await?;
794
795        for threat in threats {
796            if threat.score > self.config.threat_detection_config.threat_score_threshold {
797                context.risk_factors.push(RiskFactor {
798                    factor_type: threat.threat_type.clone(),
799                    severity: threat.severity.clone(),
800                    description: threat.description.clone(),
801                    detected_at: SystemTime::now(),
802                    auto_mitigated: false,
803                });
804
805                // Apply response actions
806                for action in &self.config.threat_detection_config.response_actions {
807                    self.apply_threat_response(action, context, &threat).await?;
808                }
809            }
810        }
811
812        Ok(())
813    }
814
815    /// Validate session
816    async fn validate_session(&self, context: &SecurityContext) -> Result<()> {
817        let sessions = self.active_sessions.read().await;
818        if let Some(session) = sessions.get(&context.session_id) {
819            // Check session timeout
820            if session
821                .last_activity
822                .elapsed()
823                .unwrap_or(Duration::from_secs(0))
824                > self.config.session_timeout
825            {
826                return Err(anyhow!("Session expired"));
827            }
828        } else {
829            return Err(anyhow!("Invalid session"));
830        }
831
832        Ok(())
833    }
834
835    /// Extract permissions required by query
836    async fn extract_query_permissions(&self, query: &Document) -> Result<Vec<Permission>> {
837        let mut permissions = Vec::new();
838
839        // Simple permission extraction (in practice would be more sophisticated)
840        for definition in &query.definitions {
841            if let crate::ast::Definition::Operation(op) = definition {
842                match op.operation_type {
843                    OperationType::Query => permissions.push(Permission::ReadData),
844                    OperationType::Mutation => permissions.push(Permission::WriteData),
845                    OperationType::Subscription => permissions.push(Permission::ReadData),
846                }
847            }
848        }
849
850        Ok(permissions)
851    }
852
853    /// Analyze query for suspicious patterns
854    async fn analyze_query_suspiciousness(&self, _query: &Document) -> Result<f64> {
855        // Implement query analysis for suspicious patterns
856        Ok(0.0)
857    }
858
859    /// Apply data loss prevention
860    async fn apply_data_loss_prevention(
861        &self,
862        _context: &SecurityContext,
863        _query: &Document,
864    ) -> Result<()> {
865        // Implement DLP policies
866        Ok(())
867    }
868
869    /// Check if access time is unusual
870    async fn is_unusual_access_time(
871        &self,
872        _profile: &BehavioralProfile,
873        _access_time: SystemTime,
874    ) -> Result<bool> {
875        // Implement time-based anomaly detection
876        Ok(false)
877    }
878
879    /// Check if location is unusual
880    async fn is_unusual_location(&self, _profile: &BehavioralProfile, _ip: IpAddr) -> Result<bool> {
881        // Implement location-based anomaly detection
882        Ok(false)
883    }
884
885    /// Apply threat response
886    async fn apply_threat_response(
887        &self,
888        action: &ThreatResponseAction,
889        context: &SecurityContext,
890        threat: &ThreatDetection,
891    ) -> Result<()> {
892        match action {
893            ThreatResponseAction::LogEvent => {
894                self.log_security_event(SecurityEvent {
895                    event_id: uuid::Uuid::new_v4().to_string(),
896                    event_type: SecurityEventType::ThreatDetected,
897                    severity: threat.severity.clone(),
898                    user_id: context.user_id.clone(),
899                    session_id: context.session_id.clone(),
900                    ip_address: context.ip_address,
901                    timestamp: SystemTime::now(),
902                    description: threat.description.clone(),
903                    metadata: HashMap::new(),
904                    threat_score: Some(threat.score),
905                    mitigated: false,
906                })
907                .await?;
908            }
909            ThreatResponseAction::BlockIP => {
910                self.blocked_ips.write().await.insert(context.ip_address);
911            }
912            ThreatResponseAction::BlockUser => {
913                if let Some(ref user_id) = context.user_id {
914                    self.blocked_users.write().await.insert(user_id.clone());
915                }
916            }
917            _ => {
918                // Implement other response actions
919            }
920        }
921
922        Ok(())
923    }
924
925    /// Log security event
926    async fn log_security_event(&self, event: SecurityEvent) -> Result<()> {
927        let mut audit_logger = self.audit_logger.lock().await;
928        audit_logger.log_event(&event).await?;
929
930        // Send event to subscribers
931        if self.security_event_sender.send(event).is_err() {
932            warn!("No security event subscribers");
933        }
934
935        Ok(())
936    }
937}
938
939/// Security request information
940#[derive(Debug, Clone)]
941pub struct SecurityRequest {
942    pub auth_token: String,
943    pub ip_address: IpAddr,
944    pub user_agent: Option<String>,
945    pub device_id: Option<String>,
946    pub user_id: Option<String>,
947}
948
949/// Authentication information
950#[derive(Debug, Clone)]
951pub struct AuthenticationInfo {
952    pub user_id: Option<String>,
953    pub session_id: String,
954    pub auth_level: AuthenticationLevel,
955    pub permissions: HashSet<Permission>,
956    pub session_start: SystemTime,
957    pub authentication_factors: Vec<AuthenticationFactor>,
958}
959
960/// Authorization result
961#[derive(Debug, Clone)]
962pub struct AuthorizationResult {
963    pub authorized: bool,
964    pub required_permissions: Vec<Permission>,
965    pub applied_filters: Vec<String>,
966    pub suspicious_score: f64,
967    pub additional_monitoring: bool,
968}
969
970/// Threat detection result
971#[derive(Debug, Clone)]
972pub struct ThreatDetection {
973    pub threat_type: RiskFactorType,
974    pub severity: RiskSeverity,
975    pub score: f64,
976    pub description: String,
977    pub confidence: f64,
978}
979
980/// Rate limiter implementation
981#[derive(Debug)]
982pub struct RateLimiter {
983    config: RateLimitConfig,
984    requests: VecDeque<SystemTime>,
985}
986
987impl RateLimiter {
988    pub fn new(config: &RateLimitConfig) -> Self {
989        Self {
990            config: config.clone(),
991            requests: VecDeque::new(),
992        }
993    }
994
995    pub async fn allow_request(&mut self) -> Result<bool> {
996        let now = SystemTime::now();
997
998        // Clean old requests
999        while let Some(&front) = self.requests.front() {
1000            if now.duration_since(front).unwrap_or(Duration::from_secs(0))
1001                > self.config.sliding_window_duration
1002            {
1003                self.requests.pop_front();
1004            } else {
1005                break;
1006            }
1007        }
1008
1009        // Check rate limit
1010        if self.requests.len() >= self.config.requests_per_minute {
1011            return Ok(false);
1012        }
1013
1014        self.requests.push_back(now);
1015        Ok(true)
1016    }
1017}
1018
1019/// Threat detector
1020#[derive(Debug)]
1021pub struct ThreatDetector {
1022    #[allow(dead_code)]
1023    config: ThreatDetectionConfig,
1024    #[allow(dead_code)]
1025    ml_models: HashMap<String, ThreatModel>,
1026}
1027
1028impl ThreatDetector {
1029    pub fn new(config: &ThreatDetectionConfig) -> Self {
1030        Self {
1031            config: config.clone(),
1032            ml_models: HashMap::new(),
1033        }
1034    }
1035
1036    pub async fn analyze_request(
1037        &mut self,
1038        _context: &SecurityContext,
1039        _request: &SecurityRequest,
1040    ) -> Result<Vec<ThreatDetection>> {
1041        // Implement threat detection algorithms
1042        Ok(Vec::new())
1043    }
1044}
1045
1046/// ML threat detection model
1047#[derive(Debug)]
1048pub struct ThreatModel {
1049    pub model_type: String,
1050    pub accuracy: f64,
1051    pub last_trained: SystemTime,
1052}
1053
1054/// Audit logger
1055#[derive(Debug)]
1056pub struct AuditLogger {
1057    config: AuditConfig,
1058    events: VecDeque<SecurityEvent>,
1059}
1060
1061impl AuditLogger {
1062    pub fn new(config: &AuditConfig) -> Self {
1063        Self {
1064            config: config.clone(),
1065            events: VecDeque::new(),
1066        }
1067    }
1068
1069    pub async fn log_event(&mut self, event: &SecurityEvent) -> Result<()> {
1070        if self.config.enable_audit_logging {
1071            self.events.push_back(event.clone());
1072
1073            // In practice, would write to persistent storage
1074            info!("Security event logged: {:?}", event);
1075        }
1076
1077        Ok(())
1078    }
1079}
1080
1081/// Encryption manager
1082#[derive(Debug)]
1083pub struct EncryptionManager {
1084    #[allow(dead_code)]
1085    config: EncryptionConfig,
1086    #[allow(dead_code)]
1087    active_keys: HashMap<String, EncryptionKey>,
1088}
1089
1090impl EncryptionManager {
1091    pub fn new(config: &EncryptionConfig) -> Self {
1092        Self {
1093            config: config.clone(),
1094            active_keys: HashMap::new(),
1095        }
1096    }
1097
1098    pub async fn encrypt(&self, data: &str, _key_id: &str) -> Result<String> {
1099        // Implement encryption logic
1100        Ok(format!("encrypted:{data}"))
1101    }
1102
1103    pub async fn decrypt(&self, encrypted_data: &str, _key_id: &str) -> Result<String> {
1104        // Implement decryption logic
1105        if let Some(stripped) = encrypted_data.strip_prefix("encrypted:") {
1106            Ok(stripped.to_string())
1107        } else {
1108            Err(anyhow!("Invalid encrypted data format"))
1109        }
1110    }
1111}
1112
1113/// Encryption key
1114#[derive(Debug, Clone)]
1115pub struct EncryptionKey {
1116    pub key_id: String,
1117    pub algorithm: EncryptionAlgorithm,
1118    pub created_at: SystemTime,
1119    pub expires_at: Option<SystemTime>,
1120}
1121
1122#[cfg(test)]
1123mod zero_trust_auth_tests {
1124    use super::*;
1125
1126    fn manager_with_secret(secret: Option<&str>) -> ZeroTrustSecurityManager {
1127        let config = ZeroTrustConfig {
1128            jwt_secret: secret.map(String::from),
1129            ..Default::default()
1130        };
1131        let (manager, _rx) = ZeroTrustSecurityManager::new(config);
1132        manager
1133    }
1134
1135    fn sign_token(secret: &str, claims: &JwtClaims) -> String {
1136        let jwt_config = JwtConfig {
1137            secret: secret.to_string(),
1138            ..Default::default()
1139        };
1140        let manager = JwtManager::new(jwt_config).expect("valid jwt config");
1141        manager.generate_token(claims).expect("token generated")
1142    }
1143
1144    #[tokio::test]
1145    async fn regression_no_secret_rejects_every_token() {
1146        let manager = manager_with_secret(None);
1147        // Even a well-formed value must be rejected when no secret is configured.
1148        assert!(manager
1149            .validate_authentication_token("anything")
1150            .await
1151            .is_err());
1152        assert!(manager.validate_authentication_token("").await.is_err());
1153    }
1154
1155    #[tokio::test]
1156    async fn regression_empty_and_garbage_token_rejected() {
1157        let manager = manager_with_secret(Some("super-secret-key"));
1158        assert!(manager.validate_authentication_token("").await.is_err());
1159        assert!(manager
1160            .validate_authentication_token("not-a-jwt")
1161            .await
1162            .is_err());
1163        // Wrong number of segments.
1164        assert!(manager.validate_authentication_token("a.b").await.is_err());
1165    }
1166
1167    #[tokio::test]
1168    async fn regression_tampered_signature_rejected() {
1169        let secret = "super-secret-key";
1170        let manager = manager_with_secret(Some(secret));
1171        let claims = JwtClaims::new("alice".to_string(), 3600);
1172        let token = sign_token(secret, &claims);
1173        // Flip a character in the signature segment.
1174        let mut parts: Vec<String> = token.split('.').map(String::from).collect();
1175        let sig = &mut parts[2];
1176        let flipped = if sig.starts_with('A') { 'B' } else { 'A' };
1177        sig.replace_range(0..1, &flipped.to_string());
1178        let tampered = parts.join(".");
1179        assert!(manager
1180            .validate_authentication_token(&tampered)
1181            .await
1182            .is_err());
1183    }
1184
1185    #[tokio::test]
1186    async fn regression_wrong_secret_rejected() {
1187        let good = sign_token("issuer-secret", &JwtClaims::new("bob".to_string(), 3600));
1188        let manager = manager_with_secret(Some("different-secret"));
1189        assert!(manager.validate_authentication_token(&good).await.is_err());
1190    }
1191
1192    #[tokio::test]
1193    async fn regression_valid_token_maps_claims() {
1194        let secret = "super-secret-key";
1195        let manager = manager_with_secret(Some(secret));
1196        let claims = JwtClaims::new("carol".to_string(), 3600)
1197            .with_claim(
1198                "permissions".to_string(),
1199                serde_json::json!(["read", "write", "admin"]),
1200            )
1201            .with_claim("auth_level".to_string(), serde_json::json!("mfa"));
1202        let token = sign_token(secret, &claims);
1203
1204        let info = manager
1205            .validate_authentication_token(&token)
1206            .await
1207            .expect("valid token accepted");
1208        assert_eq!(info.user_id.as_deref(), Some("carol"));
1209        assert_eq!(
1210            info.auth_level,
1211            AuthenticationLevel::MultiFactorAuthenticated
1212        );
1213        assert!(info.permissions.contains(&Permission::ReadData));
1214        assert!(info.permissions.contains(&Permission::WriteData));
1215        assert!(info.permissions.contains(&Permission::AdminAccess));
1216        // A permission NOT granted must be absent.
1217        assert!(!info.permissions.contains(&Permission::DeleteData));
1218    }
1219
1220    #[tokio::test]
1221    async fn regression_issuer_mismatch_rejected() {
1222        let secret = "super-secret-key";
1223        let config = ZeroTrustConfig {
1224            jwt_secret: Some(secret.to_string()),
1225            jwt_issuer: Some("expected-issuer".to_string()),
1226            ..Default::default()
1227        };
1228        let (manager, _rx) = ZeroTrustSecurityManager::new(config);
1229
1230        // Token carries a different issuer.
1231        let mut claims = JwtClaims::new("dave".to_string(), 3600);
1232        claims.iss = Some("attacker".to_string());
1233        let token = sign_token(secret, &claims);
1234        assert!(manager.validate_authentication_token(&token).await.is_err());
1235    }
1236
1237    #[tokio::test]
1238    async fn regression_bearer_prefix_stripped() {
1239        let secret = "super-secret-key";
1240        let manager = manager_with_secret(Some(secret));
1241        let token = sign_token(secret, &JwtClaims::new("eve".to_string(), 3600));
1242        let bearer = format!("Bearer {token}");
1243        assert!(manager.validate_authentication_token(&bearer).await.is_ok());
1244    }
1245}