clnrm_core/
policy.rs

1//! Policy enforcement for cleanroom testing
2//!
3//! This module provides comprehensive policy enforcement following core team best practices:
4//! - Security boundaries and isolation controls
5//! - Resource limits and constraints enforcement
6//! - Execution policies and compliance rules
7//! - Audit trails and compliance reporting
8//!
9//! ## Security Levels
10//!
11//! Cleanroom supports multiple security levels:
12//!
13//! - **Low**: Minimal isolation for development and debugging
14//! - **Medium**: Balanced security for most testing scenarios
15//! - **High**: Enhanced security for sensitive applications
16//! - **Maximum**: Maximum security with strict isolation
17//! - **Locked**: Maximum security with additional restrictions
18//!
19//! ## Usage Examples
20//!
21//! ### Basic Policy Creation
22//!
23//! ```no_run
24//! use clnrm::{Policy, SecurityLevel};
25//!
26//! // Create policy with specific security level
27//! let policy = Policy::with_security_level(SecurityLevel::High);
28//!
29//! // Create custom policy with resource limits
30//! let policy = Policy::with_resource_limits(
31//!     80.0,  // max CPU %
32//!     1024 * 1024 * 1024,  // max memory bytes (1GB)
33//!     10 * 1024 * 1024 * 1024,  // max disk bytes (10GB)
34//! );
35//! ```
36//!
37//! ### Security Policy Configuration
38//!
39//! ```no_run
40//! use clnrm::{Policy, SecurityPolicy};
41//!
42//! let mut policy = Policy::default();
43//! policy.security.enable_network_isolation = true;
44//! policy.security.enable_filesystem_isolation = true;
45//! policy.security.allowed_ports = vec![5432, 6379]; // PostgreSQL, Redis
46//! policy.security.blocked_addresses = vec!["127.0.0.1".to_string()];
47//! ```
48//!
49//! ### Policy Validation
50//!
51//! ```no_run
52//! use clnrm::Policy;
53//!
54//! let policy = Policy::locked();
55//!
56//! // Validate policy configuration
57//! if let Err(e) = policy.validate() {
58//!     eprintln!("Policy validation failed: {}", e);
59//!     // Handle validation errors
60//! }
61//! ```
62
63use crate::error::{CleanroomError, Result};
64use serde::{Deserialize, Serialize};
65use std::collections::HashMap;
66use std::time::Duration;
67
68/// Policy configuration for cleanroom testing
69#[derive(Debug, Clone, Default, Serialize, Deserialize)]
70pub struct Policy {
71    /// Security policy
72    pub security: SecurityPolicy,
73    /// Resource policy
74    pub resources: ResourcePolicy,
75    /// Execution policy
76    pub execution: ExecutionPolicy,
77    /// Compliance policy
78    pub compliance: CompliancePolicy,
79}
80
81/// Security policy configuration
82#[derive(Debug, Clone, Serialize, Deserialize)]
83pub struct SecurityPolicy {
84    /// Enable network isolation
85    pub enable_network_isolation: bool,
86    /// Enable filesystem isolation
87    pub enable_filesystem_isolation: bool,
88    /// Enable process isolation
89    pub enable_process_isolation: bool,
90    /// Allowed network ports
91    pub allowed_ports: Vec<u16>,
92    /// Blocked network addresses
93    pub blocked_addresses: Vec<String>,
94    /// Enable sensitive data redaction
95    pub enable_data_redaction: bool,
96    /// Redaction patterns
97    pub redaction_patterns: Vec<String>,
98    /// Enable audit logging
99    pub enable_audit_logging: bool,
100    /// Security level
101    pub security_level: SecurityLevel,
102}
103
104/// Resource policy configuration
105#[derive(Debug, Clone, Serialize, Deserialize)]
106pub struct ResourcePolicy {
107    /// Maximum CPU usage percentage
108    pub max_cpu_usage_percent: f64,
109    /// Maximum memory usage bytes
110    pub max_memory_usage_bytes: u64,
111    /// Maximum disk usage bytes
112    pub max_disk_usage_bytes: u64,
113    /// Maximum network bandwidth bytes per second
114    pub max_network_bandwidth_bytes_per_sec: u64,
115    /// Maximum container count
116    pub max_container_count: u32,
117    /// Maximum test execution time
118    pub max_test_execution_time: Duration,
119    /// Enable resource monitoring
120    pub enable_resource_monitoring: bool,
121    /// Resource cleanup timeout
122    pub resource_cleanup_timeout: Duration,
123}
124
125/// Execution policy configuration
126#[derive(Debug, Clone, Serialize, Deserialize)]
127pub struct ExecutionPolicy {
128    /// Enable deterministic execution
129    pub enable_deterministic_execution: bool,
130    /// Fixed seed for deterministic runs
131    pub deterministic_seed: Option<u64>,
132    /// Enable parallel execution
133    pub enable_parallel_execution: bool,
134    /// Maximum parallel tasks
135    pub max_parallel_tasks: u32,
136    /// Enable test isolation
137    pub enable_test_isolation: bool,
138    /// Test timeout
139    pub test_timeout: Duration,
140    /// Enable retry on failure
141    pub enable_retry_on_failure: bool,
142    /// Maximum retry attempts
143    pub max_retry_attempts: u32,
144    /// Retry delay
145    pub retry_delay: Duration,
146}
147
148/// Compliance policy configuration
149#[derive(Debug, Clone, Serialize, Deserialize)]
150pub struct CompliancePolicy {
151    /// Enable compliance reporting
152    pub enable_compliance_reporting: bool,
153    /// Compliance standards
154    pub compliance_standards: Vec<ComplianceStandard>,
155    /// Enable audit trails
156    pub enable_audit_trails: bool,
157    /// Audit retention period
158    pub audit_retention_period: Duration,
159    /// Enable policy validation
160    pub enable_policy_validation: bool,
161    /// Policy validation rules
162    pub policy_validation_rules: Vec<PolicyValidationRule>,
163}
164
165/// Security level enumeration
166#[derive(Debug, Clone, Copy, PartialEq, Serialize, Deserialize)]
167pub enum SecurityLevel {
168    /// Low security level
169    Low,
170    /// Medium security level
171    Medium,
172    /// High security level
173    High,
174    /// Maximum security level
175    Maximum,
176    /// Standard security level
177    Standard,
178    /// Locked security level
179    Locked,
180}
181
182/// Audit level enumeration
183#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
184pub enum AuditLevel {
185    /// Debug audit level
186    Debug,
187    /// Info audit level
188    Info,
189    /// Warning audit level
190    Warn,
191    /// Error audit level
192    Error,
193}
194
195/// Compliance standard enumeration
196#[derive(Debug, Clone, Serialize, Deserialize)]
197pub enum ComplianceStandard {
198    /// SOC 2 compliance
199    Soc2,
200    /// ISO 27001 compliance
201    Iso27001,
202    /// PCI DSS compliance
203    PciDss,
204    /// HIPAA compliance
205    Hipaa,
206    /// GDPR compliance
207    Gdpr,
208    /// Custom compliance standard
209    Custom(String),
210}
211
212/// Policy validation rule
213#[derive(Debug, Clone, Serialize, Deserialize)]
214pub struct PolicyValidationRule {
215    /// Rule name
216    pub name: String,
217    /// Rule description
218    pub description: String,
219    /// Rule condition
220    pub condition: String,
221    /// Rule action
222    pub action: PolicyValidationAction,
223    /// Rule severity
224    pub severity: PolicyValidationSeverity,
225}
226
227/// Policy validation action
228#[derive(Debug, Clone, Serialize, Deserialize)]
229pub enum PolicyValidationAction {
230    /// Allow operation
231    Allow,
232    /// Deny operation
233    Deny,
234    /// Warn about operation
235    Warn,
236    /// Require approval
237    RequireApproval,
238}
239
240/// Policy validation severity
241#[derive(Debug, Clone, Serialize, Deserialize)]
242pub enum PolicyValidationSeverity {
243    /// Low severity
244    Low,
245    /// Medium severity
246    Medium,
247    /// High severity
248    High,
249    /// Critical severity
250    Critical,
251}
252
253impl SecurityPolicy {
254    /// Create a new security policy with default settings
255    pub fn new() -> Self {
256        Self::default()
257    }
258
259    /// Create a security policy with a specific security level
260    pub fn with_security_level(security_level: SecurityLevel) -> Self {
261        let mut policy = Self {
262            security_level,
263            ..Default::default()
264        };
265
266        // Adjust isolation settings based on security level
267        match security_level {
268            SecurityLevel::Low => {
269                policy.enable_network_isolation = false;
270                policy.enable_filesystem_isolation = false;
271                policy.enable_process_isolation = false;
272                policy.enable_data_redaction = false;
273                policy.enable_audit_logging = false;
274            }
275            SecurityLevel::Medium | SecurityLevel::Standard => {
276                // Keep default settings
277            }
278            SecurityLevel::High | SecurityLevel::Maximum | SecurityLevel::Locked => {
279                // Keep all isolation enabled (default)
280            }
281        }
282
283        policy
284    }
285}
286
287impl Default for SecurityPolicy {
288    fn default() -> Self {
289        Self {
290            enable_network_isolation: true,
291            enable_filesystem_isolation: true,
292            enable_process_isolation: true,
293            allowed_ports: vec![5432, 6379, 8080, 9090],
294            blocked_addresses: vec!["127.0.0.1".to_string()],
295            enable_data_redaction: true,
296            redaction_patterns: vec![
297                r"password\s*=\s*[^\s]+".to_string(),
298                r"token\s*=\s*[^\s]+".to_string(),
299                r"key\s*=\s*[^\s]+".to_string(),
300            ],
301            enable_audit_logging: true,
302            security_level: SecurityLevel::Standard,
303        }
304    }
305}
306
307impl ResourcePolicy {
308    /// Create a new resource policy with default settings
309    pub fn new() -> Self {
310        Self::default()
311    }
312}
313
314impl Default for ResourcePolicy {
315    fn default() -> Self {
316        Self {
317            max_cpu_usage_percent: 80.0,
318            max_memory_usage_bytes: 1024 * 1024 * 1024, // 1GB
319            max_disk_usage_bytes: 10 * 1024 * 1024 * 1024, // 10GB
320            max_network_bandwidth_bytes_per_sec: 100 * 1024 * 1024, // 100MB/s
321            max_container_count: 10,
322            max_test_execution_time: Duration::from_secs(300), // 5 minutes
323            enable_resource_monitoring: true,
324            resource_cleanup_timeout: Duration::from_secs(30),
325        }
326    }
327}
328
329impl ExecutionPolicy {
330    /// Create a new execution policy with default settings
331    pub fn new() -> Self {
332        Self::default()
333    }
334}
335
336impl Default for ExecutionPolicy {
337    fn default() -> Self {
338        Self {
339            enable_deterministic_execution: true,
340            deterministic_seed: Some(42),
341            enable_parallel_execution: true,
342            max_parallel_tasks: 4,
343            enable_test_isolation: true,
344            test_timeout: Duration::from_secs(60),
345            enable_retry_on_failure: true,
346            max_retry_attempts: 3,
347            retry_delay: Duration::from_secs(1),
348        }
349    }
350}
351
352impl CompliancePolicy {
353    /// Create a new compliance policy with default settings
354    pub fn new() -> Self {
355        Self::default()
356    }
357}
358
359impl Default for CompliancePolicy {
360    fn default() -> Self {
361        Self {
362            enable_compliance_reporting: true,
363            compliance_standards: vec![ComplianceStandard::Soc2],
364            enable_audit_trails: true,
365            audit_retention_period: Duration::from_secs(30 * 24 * 60 * 60), // 30 days
366            enable_policy_validation: true,
367            policy_validation_rules: vec![],
368        }
369    }
370}
371
372impl Policy {
373    /// Create a new policy with default values
374    pub fn new() -> Self {
375        Self::default()
376    }
377
378    /// Create a policy with custom security level
379    pub fn with_security_level(security_level: SecurityLevel) -> Self {
380        Self {
381            security: SecurityPolicy::with_security_level(security_level),
382            ..Default::default()
383        }
384    }
385
386    /// Create a policy with custom resource limits
387    pub fn with_resource_limits(
388        max_cpu_percent: f64,
389        max_memory_bytes: u64,
390        max_disk_bytes: u64,
391    ) -> Self {
392        let mut policy = Self::default();
393        policy.resources.max_cpu_usage_percent = max_cpu_percent;
394        policy.resources.max_memory_usage_bytes = max_memory_bytes;
395        policy.resources.max_disk_usage_bytes = max_disk_bytes;
396        policy
397    }
398
399    /// Create a locked-down policy with maximum security
400    pub fn locked() -> Self {
401        Self::with_security_level(SecurityLevel::Locked)
402    }
403
404    /// Create a high security policy
405    pub fn high_security() -> Self {
406        Self::with_security_level(SecurityLevel::High)
407    }
408
409    /// Create a standard security policy
410    pub fn standard() -> Self {
411        Self::with_security_level(SecurityLevel::Standard)
412    }
413
414    /// Create a low security policy
415    pub fn low_security() -> Self {
416        Self::with_security_level(SecurityLevel::Low)
417    }
418
419    /// Disable network access
420    pub fn with_network_disabled(mut self) -> Self {
421        self.security.enable_network_isolation = true;
422        self
423    }
424
425    /// Set network isolation
426    pub fn with_network_isolation(mut self, enable: bool) -> Self {
427        self.security.enable_network_isolation = enable;
428        self
429    }
430
431    /// Check if network access is allowed
432    pub fn allows_network(&self) -> bool {
433        !self.security.enable_network_isolation
434    }
435
436    /// Validate policy configuration
437    pub fn validate(&self) -> Result<()> {
438        // Validate security policy
439        if self.security.allowed_ports.is_empty() {
440            return Err(CleanroomError::policy_violation_error(
441                "No allowed ports configured",
442            ));
443        }
444
445        // Validate resource policy
446        if self.resources.max_cpu_usage_percent <= 0.0
447            || self.resources.max_cpu_usage_percent > 100.0
448        {
449            return Err(CleanroomError::policy_violation_error(
450                "Invalid CPU usage percentage",
451            ));
452        }
453
454        if self.resources.max_memory_usage_bytes == 0 {
455            return Err(CleanroomError::policy_violation_error(
456                "Invalid memory usage limit",
457            ));
458        }
459
460        if self.resources.max_disk_usage_bytes == 0 {
461            return Err(CleanroomError::policy_violation_error(
462                "Invalid disk usage limit",
463            ));
464        }
465
466        // Validate execution policy
467        if self.execution.max_parallel_tasks == 0 {
468            return Err(CleanroomError::policy_violation_error(
469                "Invalid parallel task count",
470            ));
471        }
472
473        if self.execution.max_retry_attempts == 0 {
474            return Err(CleanroomError::policy_violation_error(
475                "Invalid retry attempt count",
476            ));
477        }
478
479        Ok(())
480    }
481
482    /// Check if operation is allowed by policy
483    pub fn is_operation_allowed(
484        &self,
485        _operation: &str,
486        context: &HashMap<String, String>,
487    ) -> Result<bool> {
488        // Check security policy
489        if self.security.enable_network_isolation {
490            if let Some(port) = context.get("port") {
491                if let Ok(port_num) = port.parse::<u16>() {
492                    if !self.security.allowed_ports.contains(&port_num) {
493                        return Ok(false);
494                    }
495                }
496            }
497        }
498
499        // Check resource policy
500        if let Some(cpu_usage) = context.get("cpu_usage") {
501            if let Ok(cpu_percent) = cpu_usage.parse::<f64>() {
502                if cpu_percent > self.resources.max_cpu_usage_percent {
503                    return Ok(false);
504                }
505            }
506        }
507
508        if let Some(memory_usage) = context.get("memory_usage") {
509            if let Ok(memory_bytes) = memory_usage.parse::<u64>() {
510                if memory_bytes > self.resources.max_memory_usage_bytes {
511                    return Ok(false);
512                }
513            }
514        }
515
516        // Check execution policy
517        if let Some(parallel_tasks) = context.get("parallel_tasks") {
518            if let Ok(task_count) = parallel_tasks.parse::<u32>() {
519                if task_count > self.execution.max_parallel_tasks {
520                    return Ok(false);
521                }
522            }
523        }
524
525        Ok(true)
526    }
527
528    /// Get environment variables for policy enforcement
529    pub fn to_env(&self) -> HashMap<String, String> {
530        let mut env = HashMap::new();
531
532        // Security policy environment variables
533        env.insert(
534            "CLEANROOM_SECURITY_LEVEL".to_string(),
535            format!("{:?}", self.security.security_level),
536        );
537        env.insert(
538            "CLEANROOM_NETWORK_ISOLATION".to_string(),
539            self.security.enable_network_isolation.to_string(),
540        );
541        env.insert(
542            "CLEANROOM_FILESYSTEM_ISOLATION".to_string(),
543            self.security.enable_filesystem_isolation.to_string(),
544        );
545        env.insert(
546            "CLEANROOM_PROCESS_ISOLATION".to_string(),
547            self.security.enable_process_isolation.to_string(),
548        );
549        env.insert(
550            "CLEANROOM_ALLOWED_PORTS".to_string(),
551            self.security
552                .allowed_ports
553                .iter()
554                .map(|p| p.to_string())
555                .collect::<Vec<_>>()
556                .join(","),
557        );
558
559        // Resource policy environment variables
560        env.insert(
561            "CLEANROOM_MAX_CPU_PERCENT".to_string(),
562            self.resources.max_cpu_usage_percent.to_string(),
563        );
564        env.insert(
565            "CLEANROOM_MAX_MEMORY_BYTES".to_string(),
566            self.resources.max_memory_usage_bytes.to_string(),
567        );
568        env.insert(
569            "CLEANROOM_MAX_DISK_BYTES".to_string(),
570            self.resources.max_disk_usage_bytes.to_string(),
571        );
572        env.insert(
573            "CLEANROOM_MAX_CONTAINER_COUNT".to_string(),
574            self.resources.max_container_count.to_string(),
575        );
576
577        // Execution policy environment variables
578        env.insert(
579            "CLEANROOM_DETERMINISTIC_EXECUTION".to_string(),
580            self.execution.enable_deterministic_execution.to_string(),
581        );
582        env.insert(
583            "CLEANROOM_PARALLEL_EXECUTION".to_string(),
584            self.execution.enable_parallel_execution.to_string(),
585        );
586        env.insert(
587            "CLEANROOM_MAX_PARALLEL_TASKS".to_string(),
588            self.execution.max_parallel_tasks.to_string(),
589        );
590        env.insert(
591            "CLEANROOM_TEST_ISOLATION".to_string(),
592            self.execution.enable_test_isolation.to_string(),
593        );
594
595        env
596    }
597
598    /// Get policy summary
599    pub fn summary(&self) -> String {
600        format!(
601            "Policy Summary:\n\
602            Security Level: {:?}\n\
603            Network Isolation: {}\n\
604            Filesystem Isolation: {}\n\
605            Process Isolation: {}\n\
606            Max CPU Usage: {}%\n\
607            Max Memory Usage: {} bytes\n\
608            Max Disk Usage: {} bytes\n\
609            Max Container Count: {}\n\
610            Deterministic Execution: {}\n\
611            Parallel Execution: {}\n\
612            Max Parallel Tasks: {}\n\
613            Test Isolation: {}",
614            self.security.security_level,
615            self.security.enable_network_isolation,
616            self.security.enable_filesystem_isolation,
617            self.security.enable_process_isolation,
618            self.resources.max_cpu_usage_percent,
619            self.resources.max_memory_usage_bytes,
620            self.resources.max_disk_usage_bytes,
621            self.resources.max_container_count,
622            self.execution.enable_deterministic_execution,
623            self.execution.enable_parallel_execution,
624            self.execution.max_parallel_tasks,
625            self.execution.enable_test_isolation
626        )
627    }
628}
629
630#[cfg(test)]
631mod tests {
632    use super::*;
633
634    // Allow unwrap/expect in tests as they are expected to panic on failure
635    #[allow(
636        clippy::unwrap_used,
637        clippy::expect_used,
638        clippy::indexing_slicing,
639        clippy::panic
640    )]
641    #[test]
642    fn test_policy_creation() {
643        let policy = Policy::new();
644        assert!(policy.validate().is_ok());
645    }
646
647    #[test]
648    fn test_policy_with_security_level() {
649        let policy = Policy::with_security_level(SecurityLevel::High);
650        assert_eq!(policy.security.security_level, SecurityLevel::High);
651    }
652
653    #[test]
654    fn test_policy_with_resource_limits() {
655        let policy = Policy::with_resource_limits(50.0, 512 * 1024 * 1024, 5 * 1024 * 1024 * 1024);
656        assert_eq!(policy.resources.max_cpu_usage_percent, 50.0);
657        assert_eq!(policy.resources.max_memory_usage_bytes, 512 * 1024 * 1024);
658        assert_eq!(
659            policy.resources.max_disk_usage_bytes,
660            5 * 1024 * 1024 * 1024
661        );
662    }
663
664    #[test]
665    fn test_policy_validation() {
666        let policy = Policy::new();
667        assert!(policy.validate().is_ok());
668    }
669
670    #[test]
671    fn test_policy_operation_allowed() -> Result<()> {
672        let policy = Policy::new();
673        let mut context = HashMap::new();
674        context.insert("port".to_string(), "5432".to_string());
675        context.insert("cpu_usage".to_string(), "50.0".to_string());
676        context.insert("memory_usage".to_string(), "256000000".to_string());
677
678        assert!(policy.is_operation_allowed("test_operation", &context)?);
679        Ok(())
680    }
681
682    #[test]
683    fn test_policy_operation_denied() -> Result<()> {
684        let policy = Policy::new();
685        let mut context = HashMap::new();
686        context.insert("port".to_string(), "9999".to_string()); // Not in allowed ports
687        context.insert("cpu_usage".to_string(), "90.0".to_string()); // Exceeds limit
688
689        assert!(!policy.is_operation_allowed("test_operation", &context)?);
690        Ok(())
691    }
692
693    #[test]
694    fn test_policy_env_variables() {
695        let policy = Policy::new();
696        let env = policy.to_env();
697
698        assert!(env.contains_key("CLEANROOM_SECURITY_LEVEL"));
699        assert!(env.contains_key("CLEANROOM_NETWORK_ISOLATION"));
700        assert!(env.contains_key("CLEANROOM_MAX_CPU_PERCENT"));
701        assert!(env.contains_key("CLEANROOM_MAX_MEMORY_BYTES"));
702    }
703
704    #[test]
705    fn test_policy_summary() {
706        let policy = Policy::new();
707        let summary = policy.summary();
708
709        assert!(summary.contains("Policy Summary"));
710        assert!(summary.contains("Security Level"));
711        assert!(summary.contains("Network Isolation"));
712    }
713
714    #[test]
715    fn test_policy_default() {
716        let policy = Policy::default();
717
718        assert_eq!(policy.security.security_level, SecurityLevel::Standard);
719        assert!(policy.security.enable_network_isolation);
720        assert!(policy.security.enable_filesystem_isolation);
721        assert!(policy.security.enable_process_isolation);
722        assert!(policy.security.enable_data_redaction);
723        assert!(policy.security.enable_audit_logging);
724    }
725
726    #[test]
727    fn test_policy_new() {
728        let policy = Policy::new();
729
730        assert_eq!(policy.security.security_level, SecurityLevel::Standard);
731        assert!(policy.security.enable_network_isolation);
732        assert!(policy.security.enable_filesystem_isolation);
733        assert!(policy.security.enable_process_isolation);
734        assert!(policy.security.enable_data_redaction);
735        assert!(policy.security.enable_audit_logging);
736    }
737
738    #[test]
739    fn test_policy_serialization() -> Result<()> {
740        let policy = Policy::new();
741
742        let json = serde_json::to_string(&policy)
743            .map_err(|e| CleanroomError::internal_error(format!("Serialization failed: {}", e)))?;
744        let deserialized: Policy = serde_json::from_str(&json).map_err(|e| {
745            CleanroomError::internal_error(format!("Deserialization failed: {}", e))
746        })?;
747
748        assert_eq!(
749            policy.security.security_level,
750            deserialized.security.security_level
751        );
752        assert_eq!(
753            policy.security.enable_network_isolation,
754            deserialized.security.enable_network_isolation
755        );
756        assert_eq!(
757            policy.security.enable_filesystem_isolation,
758            deserialized.security.enable_filesystem_isolation
759        );
760        Ok(())
761    }
762
763    #[test]
764    fn test_security_policy() {
765        let security = SecurityPolicy::new();
766
767        assert_eq!(security.security_level, SecurityLevel::Standard);
768        assert!(security.enable_network_isolation);
769        assert!(security.enable_filesystem_isolation);
770        assert!(security.enable_process_isolation);
771        assert!(security.enable_data_redaction);
772        assert!(security.enable_audit_logging);
773        assert!(security.allowed_ports.contains(&5432)); // PostgreSQL
774        assert!(security.allowed_ports.contains(&6379)); // Redis
775    }
776
777    #[test]
778    fn test_security_policy_with_level() {
779        let security = SecurityPolicy::with_security_level(SecurityLevel::High);
780
781        assert_eq!(security.security_level, SecurityLevel::High);
782        assert!(security.enable_network_isolation);
783        assert!(security.enable_filesystem_isolation);
784        assert!(security.enable_process_isolation);
785        assert!(security.enable_data_redaction);
786        assert!(security.enable_audit_logging);
787    }
788
789    #[test]
790    fn test_security_level_serialization() -> Result<()> {
791        let levels = vec![
792            SecurityLevel::Low,
793            SecurityLevel::Standard,
794            SecurityLevel::High,
795            SecurityLevel::Locked,
796        ];
797
798        for level in levels {
799            let json = serde_json::to_string(&level).map_err(|e| {
800                CleanroomError::internal_error(format!("Serialization failed: {}", e))
801            })?;
802            let deserialized: SecurityLevel = serde_json::from_str(&json).map_err(|e| {
803                CleanroomError::internal_error(format!("Deserialization failed: {}", e))
804            })?;
805            assert_eq!(level, deserialized);
806        }
807        Ok(())
808    }
809
810    #[test]
811    fn test_resource_policy() {
812        let resources = ResourcePolicy::new();
813
814        assert_eq!(resources.max_cpu_usage_percent, 80.0);
815        assert_eq!(resources.max_memory_usage_bytes, 1024 * 1024 * 1024); // 1GB
816        assert_eq!(resources.max_disk_usage_bytes, 10 * 1024 * 1024 * 1024); // 10GB
817        assert_eq!(
818            resources.max_network_bandwidth_bytes_per_sec,
819            100 * 1024 * 1024
820        ); // 100MB/s
821        assert_eq!(resources.max_container_count, 10);
822        assert_eq!(resources.max_test_execution_time, Duration::from_secs(300));
823    }
824
825    #[test]
826    fn test_execution_policy() {
827        let execution = ExecutionPolicy::new();
828
829        assert!(execution.enable_deterministic_execution);
830        assert!(execution.enable_parallel_execution);
831        assert!(execution.enable_test_isolation);
832        assert!(execution.enable_retry_on_failure);
833        assert_eq!(execution.max_parallel_tasks, 4);
834        assert_eq!(execution.max_retry_attempts, 3);
835        assert_eq!(execution.test_timeout, Duration::from_secs(60));
836    }
837
838    #[test]
839    fn test_compliance_policy() {
840        let compliance = CompliancePolicy::new();
841
842        assert!(compliance.enable_compliance_reporting);
843        assert!(compliance.enable_audit_trails);
844        assert!(compliance.enable_policy_validation);
845        assert_eq!(
846            compliance.audit_retention_period,
847            Duration::from_secs(30 * 24 * 60 * 60)
848        ); // 30 days
849    }
850
851    #[test]
852    fn test_audit_level_serialization() -> Result<()> {
853        let levels = vec![
854            AuditLevel::Debug,
855            AuditLevel::Info,
856            AuditLevel::Warn,
857            AuditLevel::Error,
858        ];
859
860        for level in levels {
861            let json = serde_json::to_string(&level).map_err(|e| {
862                CleanroomError::internal_error(format!("Serialization failed: {}", e))
863            })?;
864            let deserialized: AuditLevel = serde_json::from_str(&json).map_err(|e| {
865                CleanroomError::internal_error(format!("Deserialization failed: {}", e))
866            })?;
867            assert_eq!(level, deserialized);
868        }
869        Ok(())
870    }
871
872    #[test]
873    fn test_policy_locked() {
874        let policy = Policy::locked();
875
876        assert_eq!(policy.security.security_level, SecurityLevel::Locked);
877        assert!(policy.security.enable_network_isolation);
878        assert!(policy.security.enable_filesystem_isolation);
879        assert!(policy.security.enable_process_isolation);
880        assert!(policy.security.enable_data_redaction);
881        assert!(policy.security.enable_audit_logging);
882    }
883
884    #[test]
885    fn test_policy_high_security() {
886        let policy = Policy::high_security();
887
888        assert_eq!(policy.security.security_level, SecurityLevel::High);
889        assert!(policy.security.enable_network_isolation);
890        assert!(policy.security.enable_filesystem_isolation);
891        assert!(policy.security.enable_process_isolation);
892        assert!(policy.security.enable_data_redaction);
893        assert!(policy.security.enable_audit_logging);
894    }
895
896    #[test]
897    fn test_policy_standard() {
898        let policy = Policy::standard();
899
900        assert_eq!(policy.security.security_level, SecurityLevel::Standard);
901        assert!(policy.security.enable_network_isolation);
902        assert!(policy.security.enable_filesystem_isolation);
903        assert!(policy.security.enable_process_isolation);
904        assert!(policy.security.enable_data_redaction);
905        assert!(policy.security.enable_audit_logging);
906    }
907
908    #[test]
909    fn test_policy_low_security() {
910        let policy = Policy::low_security();
911
912        assert_eq!(policy.security.security_level, SecurityLevel::Low);
913        assert!(!policy.security.enable_network_isolation);
914        assert!(!policy.security.enable_filesystem_isolation);
915        assert!(!policy.security.enable_process_isolation);
916        assert!(!policy.security.enable_data_redaction);
917        assert!(!policy.security.enable_audit_logging);
918    }
919
920    #[test]
921    fn test_policy_operation_allowed_with_valid_context() -> Result<()> {
922        let policy = Policy::new();
923        let mut context = HashMap::new();
924        context.insert("port".to_string(), "5432".to_string());
925        context.insert("cpu_usage".to_string(), "50.0".to_string());
926        context.insert("memory_usage".to_string(), "256000000".to_string());
927
928        assert!(policy.is_operation_allowed("test_operation", &context)?);
929        Ok(())
930    }
931
932    #[test]
933    fn test_policy_operation_denied_with_invalid_port() -> Result<()> {
934        let policy = Policy::new();
935        let mut context = HashMap::new();
936        context.insert("port".to_string(), "9999".to_string()); // Not in allowed ports
937        context.insert("cpu_usage".to_string(), "50.0".to_string());
938        context.insert("memory_usage".to_string(), "256000000".to_string());
939
940        assert!(!policy.is_operation_allowed("test_operation", &context)?);
941        Ok(())
942    }
943
944    #[test]
945    fn test_policy_operation_denied_with_high_cpu() -> Result<()> {
946        let policy = Policy::new();
947        let mut context = HashMap::new();
948        context.insert("port".to_string(), "5432".to_string());
949        context.insert("cpu_usage".to_string(), "90.0".to_string()); // Exceeds limit
950        context.insert("memory_usage".to_string(), "256000000".to_string());
951
952        assert!(!policy.is_operation_allowed("test_operation", &context)?);
953        Ok(())
954    }
955
956    #[test]
957    fn test_policy_operation_denied_with_high_memory() -> Result<()> {
958        let policy = Policy::new();
959        let mut context = HashMap::new();
960        context.insert("port".to_string(), "5432".to_string());
961        context.insert("cpu_usage".to_string(), "50.0".to_string());
962        context.insert("memory_usage".to_string(), "2000000000".to_string()); // Exceeds limit
963
964        assert!(!policy.is_operation_allowed("test_operation", &context)?);
965        Ok(())
966    }
967
968    #[test]
969    fn test_policy_env_variables_values() {
970        let policy = Policy::new();
971        let env = policy.to_env();
972
973        assert_eq!(
974            env.get("CLEANROOM_SECURITY_LEVEL"),
975            Some(&"Standard".to_string())
976        );
977        assert_eq!(
978            env.get("CLEANROOM_NETWORK_ISOLATION"),
979            Some(&"true".to_string())
980        );
981        assert_eq!(
982            env.get("CLEANROOM_MAX_CPU_PERCENT"),
983            Some(&"80".to_string())
984        );
985        assert_eq!(
986            env.get("CLEANROOM_MAX_MEMORY_BYTES"),
987            Some(&"1073741824".to_string())
988        );
989    }
990}