1use crate::error::{CleanroomError, Result};
64use serde::{Deserialize, Serialize};
65use std::collections::HashMap;
66use std::time::Duration;
67
68#[derive(Debug, Clone, Default, Serialize, Deserialize)]
70pub struct Policy {
71 pub security: SecurityPolicy,
73 pub resources: ResourcePolicy,
75 pub execution: ExecutionPolicy,
77 pub compliance: CompliancePolicy,
79}
80
81#[derive(Debug, Clone, Serialize, Deserialize)]
83pub struct SecurityPolicy {
84 pub enable_network_isolation: bool,
86 pub enable_filesystem_isolation: bool,
88 pub enable_process_isolation: bool,
90 pub allowed_ports: Vec<u16>,
92 pub blocked_addresses: Vec<String>,
94 pub enable_data_redaction: bool,
96 pub redaction_patterns: Vec<String>,
98 pub enable_audit_logging: bool,
100 pub security_level: SecurityLevel,
102}
103
104#[derive(Debug, Clone, Serialize, Deserialize)]
106pub struct ResourcePolicy {
107 pub max_cpu_usage_percent: f64,
109 pub max_memory_usage_bytes: u64,
111 pub max_disk_usage_bytes: u64,
113 pub max_network_bandwidth_bytes_per_sec: u64,
115 pub max_container_count: u32,
117 pub max_test_execution_time: Duration,
119 pub enable_resource_monitoring: bool,
121 pub resource_cleanup_timeout: Duration,
123}
124
125#[derive(Debug, Clone, Serialize, Deserialize)]
127pub struct ExecutionPolicy {
128 pub enable_deterministic_execution: bool,
130 pub deterministic_seed: Option<u64>,
132 pub enable_parallel_execution: bool,
134 pub max_parallel_tasks: u32,
136 pub enable_test_isolation: bool,
138 pub test_timeout: Duration,
140 pub enable_retry_on_failure: bool,
142 pub max_retry_attempts: u32,
144 pub retry_delay: Duration,
146}
147
148#[derive(Debug, Clone, Serialize, Deserialize)]
150pub struct CompliancePolicy {
151 pub enable_compliance_reporting: bool,
153 pub compliance_standards: Vec<ComplianceStandard>,
155 pub enable_audit_trails: bool,
157 pub audit_retention_period: Duration,
159 pub enable_policy_validation: bool,
161 pub policy_validation_rules: Vec<PolicyValidationRule>,
163}
164
165#[derive(Debug, Clone, Copy, PartialEq, Serialize, Deserialize)]
167pub enum SecurityLevel {
168 Low,
170 Medium,
172 High,
174 Maximum,
176 Standard,
178 Locked,
180}
181
182#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
184pub enum AuditLevel {
185 Debug,
187 Info,
189 Warn,
191 Error,
193}
194
195#[derive(Debug, Clone, Serialize, Deserialize)]
197pub enum ComplianceStandard {
198 Soc2,
200 Iso27001,
202 PciDss,
204 Hipaa,
206 Gdpr,
208 Custom(String),
210}
211
212#[derive(Debug, Clone, Serialize, Deserialize)]
214pub struct PolicyValidationRule {
215 pub name: String,
217 pub description: String,
219 pub condition: String,
221 pub action: PolicyValidationAction,
223 pub severity: PolicyValidationSeverity,
225}
226
227#[derive(Debug, Clone, Serialize, Deserialize)]
229pub enum PolicyValidationAction {
230 Allow,
232 Deny,
234 Warn,
236 RequireApproval,
238}
239
240#[derive(Debug, Clone, Serialize, Deserialize)]
242pub enum PolicyValidationSeverity {
243 Low,
245 Medium,
247 High,
249 Critical,
251}
252
253impl SecurityPolicy {
254 pub fn new() -> Self {
256 Self::default()
257 }
258
259 pub fn with_security_level(security_level: SecurityLevel) -> Self {
261 let mut policy = Self {
262 security_level,
263 ..Default::default()
264 };
265
266 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 }
278 SecurityLevel::High | SecurityLevel::Maximum | SecurityLevel::Locked => {
279 }
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 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, max_disk_usage_bytes: 10 * 1024 * 1024 * 1024, max_network_bandwidth_bytes_per_sec: 100 * 1024 * 1024, max_container_count: 10,
322 max_test_execution_time: Duration::from_secs(300), enable_resource_monitoring: true,
324 resource_cleanup_timeout: Duration::from_secs(30),
325 }
326 }
327}
328
329impl ExecutionPolicy {
330 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 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), enable_policy_validation: true,
367 policy_validation_rules: vec![],
368 }
369 }
370}
371
372impl Policy {
373 pub fn new() -> Self {
375 Self::default()
376 }
377
378 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 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 pub fn locked() -> Self {
401 Self::with_security_level(SecurityLevel::Locked)
402 }
403
404 pub fn high_security() -> Self {
406 Self::with_security_level(SecurityLevel::High)
407 }
408
409 pub fn standard() -> Self {
411 Self::with_security_level(SecurityLevel::Standard)
412 }
413
414 pub fn low_security() -> Self {
416 Self::with_security_level(SecurityLevel::Low)
417 }
418
419 pub fn with_network_disabled(mut self) -> Self {
421 self.security.enable_network_isolation = true;
422 self
423 }
424
425 pub fn with_network_isolation(mut self, enable: bool) -> Self {
427 self.security.enable_network_isolation = enable;
428 self
429 }
430
431 pub fn allows_network(&self) -> bool {
433 !self.security.enable_network_isolation
434 }
435
436 pub fn validate(&self) -> Result<()> {
438 if self.security.allowed_ports.is_empty() {
440 return Err(CleanroomError::policy_violation_error(
441 "No allowed ports configured",
442 ));
443 }
444
445 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 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 pub fn is_operation_allowed(
484 &self,
485 _operation: &str,
486 context: &HashMap<String, String>,
487 ) -> Result<bool> {
488 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 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 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 pub fn to_env(&self) -> HashMap<String, String> {
530 let mut env = HashMap::new();
531
532 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 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 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 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}