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//!     tracing::error!(error = %e, "Policy validation failed");
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}