1use std::collections::{HashMap, HashSet};
50use std::fmt;
51use std::sync::atomic::{AtomicU64, Ordering};
52use std::sync::RwLock;
53use std::time::{Duration, Instant, SystemTime};
54
55use crate::KernelId;
56
57#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Default)]
63pub enum EncryptionAlgorithm {
64 #[default]
66 Aes256Gcm,
67 Aes128Gcm,
69 ChaCha20Poly1305,
71 XChaCha20Poly1305,
73}
74
75impl fmt::Display for EncryptionAlgorithm {
76 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
77 match self {
78 Self::Aes256Gcm => write!(f, "AES-256-GCM"),
79 Self::Aes128Gcm => write!(f, "AES-128-GCM"),
80 Self::ChaCha20Poly1305 => write!(f, "ChaCha20-Poly1305"),
81 Self::XChaCha20Poly1305 => write!(f, "XChaCha20-Poly1305"),
82 }
83 }
84}
85
86#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
88pub enum KeyDerivation {
89 #[default]
91 HkdfSha256,
92 HkdfSha384,
94 Argon2id,
96 Pbkdf2Sha256,
98}
99
100#[derive(Debug, Clone)]
102pub struct EncryptionConfig {
103 pub algorithm: EncryptionAlgorithm,
105 pub key_derivation: KeyDerivation,
107 pub key_rotation_interval: Duration,
109 pub encrypt_control_blocks: bool,
111 pub encrypt_message_queues: bool,
113 pub encrypt_kernel_state: bool,
115 pub aad_prefix: Option<Vec<u8>>,
117}
118
119impl Default for EncryptionConfig {
120 fn default() -> Self {
121 Self {
122 algorithm: EncryptionAlgorithm::default(),
123 key_derivation: KeyDerivation::default(),
124 key_rotation_interval: Duration::from_secs(3600), encrypt_control_blocks: true,
126 encrypt_message_queues: true,
127 encrypt_kernel_state: true,
128 aad_prefix: None,
129 }
130 }
131}
132
133impl EncryptionConfig {
134 pub fn new() -> Self {
136 Self::default()
137 }
138
139 pub fn with_algorithm(mut self, algorithm: EncryptionAlgorithm) -> Self {
141 self.algorithm = algorithm;
142 self
143 }
144
145 pub fn with_key_derivation(mut self, kdf: KeyDerivation) -> Self {
147 self.key_derivation = kdf;
148 self
149 }
150
151 pub fn with_key_rotation_interval(mut self, interval: Duration) -> Self {
153 self.key_rotation_interval = interval;
154 self
155 }
156
157 pub fn with_control_block_encryption(mut self, enabled: bool) -> Self {
159 self.encrypt_control_blocks = enabled;
160 self
161 }
162
163 pub fn with_message_queue_encryption(mut self, enabled: bool) -> Self {
165 self.encrypt_message_queues = enabled;
166 self
167 }
168
169 pub fn with_kernel_state_encryption(mut self, enabled: bool) -> Self {
171 self.encrypt_kernel_state = enabled;
172 self
173 }
174
175 pub fn with_aad_prefix(mut self, prefix: Vec<u8>) -> Self {
177 self.aad_prefix = Some(prefix);
178 self
179 }
180}
181
182#[derive(Clone)]
184pub struct EncryptionKey {
185 pub key_id: u64,
187 key_material: Vec<u8>,
189 pub created_at: Instant,
191 pub expires_at: Option<Instant>,
193 pub algorithm: EncryptionAlgorithm,
195}
196
197impl EncryptionKey {
198 pub fn new(key_id: u64, algorithm: EncryptionAlgorithm) -> Self {
200 let key_size = match algorithm {
202 EncryptionAlgorithm::Aes256Gcm
203 | EncryptionAlgorithm::ChaCha20Poly1305
204 | EncryptionAlgorithm::XChaCha20Poly1305 => 32,
205 EncryptionAlgorithm::Aes128Gcm => 16,
206 };
207
208 let key_material: Vec<u8> = (0..key_size)
209 .map(|i| ((key_id as u8).wrapping_add(i as u8)).wrapping_mul(17))
210 .collect();
211
212 Self {
213 key_id,
214 key_material,
215 created_at: Instant::now(),
216 expires_at: None,
217 algorithm,
218 }
219 }
220
221 pub fn is_expired(&self) -> bool {
223 self.expires_at
224 .map(|exp| Instant::now() > exp)
225 .unwrap_or(false)
226 }
227
228 pub fn key_size(&self) -> usize {
230 self.key_material.len()
231 }
232}
233
234impl fmt::Debug for EncryptionKey {
235 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
236 f.debug_struct("EncryptionKey")
237 .field("key_id", &self.key_id)
238 .field("algorithm", &self.algorithm)
239 .field("key_size", &self.key_material.len())
240 .field("created_at", &self.created_at)
241 .field("expires_at", &self.expires_at)
242 .finish()
243 }
244}
245
246#[derive(Debug, Clone)]
248pub struct EncryptedRegion {
249 pub region_id: u64,
251 pub ciphertext: Vec<u8>,
253 pub nonce: Vec<u8>,
255 pub key_id: u64,
257 pub plaintext_size: usize,
259 pub algorithm: EncryptionAlgorithm,
261 pub encrypted_at: Instant,
263}
264
265#[derive(Debug, Clone, Default)]
267pub struct EncryptionStats {
268 pub bytes_encrypted: u64,
270 pub bytes_decrypted: u64,
272 pub encrypt_ops: u64,
274 pub decrypt_ops: u64,
276 pub key_rotations: u64,
278 pub avg_encrypt_time_us: f64,
280 pub avg_decrypt_time_us: f64,
282}
283
284pub struct MemoryEncryption {
286 config: EncryptionConfig,
288 active_key: RwLock<EncryptionKey>,
290 previous_keys: RwLock<HashMap<u64, EncryptionKey>>,
292 next_key_id: AtomicU64,
294 region_counter: AtomicU64,
296 stats: RwLock<EncryptionStats>,
298 last_rotation: RwLock<Instant>,
300}
301
302impl MemoryEncryption {
303 pub fn new(config: EncryptionConfig) -> Self {
305 let key_id = 1;
306 let active_key = EncryptionKey::new(key_id, config.algorithm);
307
308 Self {
309 config,
310 active_key: RwLock::new(active_key),
311 previous_keys: RwLock::new(HashMap::new()),
312 next_key_id: AtomicU64::new(2),
313 region_counter: AtomicU64::new(1),
314 stats: RwLock::new(EncryptionStats::default()),
315 last_rotation: RwLock::new(Instant::now()),
316 }
317 }
318
319 pub fn encrypt_region(&self, plaintext: &[u8]) -> EncryptedRegion {
321 let start = Instant::now();
322
323 let key = self.active_key.read().unwrap();
324 let region_id = self.region_counter.fetch_add(1, Ordering::Relaxed);
325
326 let nonce_size = match self.config.algorithm {
328 EncryptionAlgorithm::Aes256Gcm | EncryptionAlgorithm::Aes128Gcm => 12,
329 EncryptionAlgorithm::ChaCha20Poly1305 => 12,
330 EncryptionAlgorithm::XChaCha20Poly1305 => 24,
331 };
332 let nonce: Vec<u8> = (0..nonce_size)
333 .map(|i| ((region_id as u8).wrapping_add(i as u8)).wrapping_mul(23))
334 .collect();
335
336 let mut ciphertext = plaintext.to_vec();
339 for (i, byte) in ciphertext.iter_mut().enumerate() {
340 *byte ^= key.key_material[i % key.key_material.len()];
341 *byte ^= nonce[i % nonce.len()];
342 }
343
344 let tag: Vec<u8> = (0..16)
346 .map(|i| {
347 ciphertext.get(i).copied().unwrap_or(0)
348 ^ key.key_material[i % key.key_material.len()]
349 })
350 .collect();
351 ciphertext.extend(tag);
352
353 let elapsed = start.elapsed();
354
355 {
357 let mut stats = self.stats.write().unwrap();
358 stats.bytes_encrypted += plaintext.len() as u64;
359 stats.encrypt_ops += 1;
360 let total_time = stats.avg_encrypt_time_us * (stats.encrypt_ops - 1) as f64;
361 stats.avg_encrypt_time_us =
362 (total_time + elapsed.as_micros() as f64) / stats.encrypt_ops as f64;
363 }
364
365 EncryptedRegion {
366 region_id,
367 ciphertext,
368 nonce,
369 key_id: key.key_id,
370 plaintext_size: plaintext.len(),
371 algorithm: self.config.algorithm,
372 encrypted_at: Instant::now(),
373 }
374 }
375
376 pub fn decrypt_region(&self, region: &EncryptedRegion) -> Result<Vec<u8>, String> {
378 let start = Instant::now();
379
380 let key = if region.key_id == self.active_key.read().unwrap().key_id {
382 self.active_key.read().unwrap().clone()
383 } else {
384 self.previous_keys
385 .read()
386 .unwrap()
387 .get(®ion.key_id)
388 .cloned()
389 .ok_or_else(|| format!("Key {} not found", region.key_id))?
390 };
391
392 if region.ciphertext.len() < 16 {
394 return Err("Ciphertext too short".to_string());
395 }
396 let (ciphertext, _tag) = region.ciphertext.split_at(region.ciphertext.len() - 16);
397
398 let mut plaintext = ciphertext.to_vec();
400 for (i, byte) in plaintext.iter_mut().enumerate() {
401 *byte ^= region.nonce[i % region.nonce.len()];
402 *byte ^= key.key_material[i % key.key_material.len()];
403 }
404
405 let elapsed = start.elapsed();
406
407 {
409 let mut stats = self.stats.write().unwrap();
410 stats.bytes_decrypted += plaintext.len() as u64;
411 stats.decrypt_ops += 1;
412 let total_time = stats.avg_decrypt_time_us * (stats.decrypt_ops - 1) as f64;
413 stats.avg_decrypt_time_us =
414 (total_time + elapsed.as_micros() as f64) / stats.decrypt_ops as f64;
415 }
416
417 Ok(plaintext)
418 }
419
420 pub fn rotate_keys(&self) {
422 let mut active = self.active_key.write().unwrap();
423 let mut previous = self.previous_keys.write().unwrap();
424
425 let old_key = active.clone();
427 previous.insert(old_key.key_id, old_key);
428
429 let new_key_id = self.next_key_id.fetch_add(1, Ordering::Relaxed);
431 *active = EncryptionKey::new(new_key_id, self.config.algorithm);
432
433 *self.last_rotation.write().unwrap() = Instant::now();
435
436 self.stats.write().unwrap().key_rotations += 1;
438
439 while previous.len() > 10 {
441 if let Some(oldest_id) = previous.keys().min().copied() {
442 previous.remove(&oldest_id);
443 }
444 }
445 }
446
447 pub fn needs_rotation(&self) -> bool {
449 let last = *self.last_rotation.read().unwrap();
450 last.elapsed() >= self.config.key_rotation_interval
451 }
452
453 pub fn stats(&self) -> EncryptionStats {
455 self.stats.read().unwrap().clone()
456 }
457
458 pub fn current_key_id(&self) -> u64 {
460 self.active_key.read().unwrap().key_id
461 }
462
463 pub fn config(&self) -> &EncryptionConfig {
465 &self.config
466 }
467}
468
469impl fmt::Debug for MemoryEncryption {
470 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
471 f.debug_struct("MemoryEncryption")
472 .field("config", &self.config)
473 .field("current_key_id", &self.current_key_id())
474 .field("stats", &self.stats())
475 .finish()
476 }
477}
478
479#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
485pub enum AccessLevel {
486 Deny,
488 ReadOnly,
490 #[default]
492 ReadWrite,
493 Full,
495}
496
497#[derive(Debug, Clone)]
499pub struct ResourceLimits {
500 pub max_memory_bytes: u64,
502 pub max_execution_time: Duration,
504 pub max_messages_per_sec: u32,
506 pub max_k2k_connections: u32,
508 pub max_checkpoint_size: u64,
510 pub max_queue_depth: u32,
512}
513
514impl Default for ResourceLimits {
515 fn default() -> Self {
516 Self {
517 max_memory_bytes: 1024 * 1024 * 1024, max_execution_time: Duration::from_secs(60),
519 max_messages_per_sec: 10000,
520 max_k2k_connections: 100,
521 max_checkpoint_size: 100 * 1024 * 1024, max_queue_depth: 4096,
523 }
524 }
525}
526
527impl ResourceLimits {
528 pub fn new() -> Self {
530 Self::default()
531 }
532
533 pub fn with_max_memory(mut self, bytes: u64) -> Self {
535 self.max_memory_bytes = bytes;
536 self
537 }
538
539 pub fn with_max_execution_time(mut self, duration: Duration) -> Self {
541 self.max_execution_time = duration;
542 self
543 }
544
545 pub fn with_max_messages_per_sec(mut self, count: u32) -> Self {
547 self.max_messages_per_sec = count;
548 self
549 }
550
551 pub fn with_max_k2k_connections(mut self, count: u32) -> Self {
553 self.max_k2k_connections = count;
554 self
555 }
556
557 pub fn restrictive() -> Self {
559 Self {
560 max_memory_bytes: 256 * 1024 * 1024, max_execution_time: Duration::from_secs(10),
562 max_messages_per_sec: 1000,
563 max_k2k_connections: 10,
564 max_checkpoint_size: 10 * 1024 * 1024, max_queue_depth: 256,
566 }
567 }
568
569 pub fn permissive() -> Self {
571 Self {
572 max_memory_bytes: 8 * 1024 * 1024 * 1024, max_execution_time: Duration::from_secs(3600),
574 max_messages_per_sec: 1_000_000,
575 max_k2k_connections: 1000,
576 max_checkpoint_size: 1024 * 1024 * 1024, max_queue_depth: 65536,
578 }
579 }
580}
581
582#[derive(Debug, Clone)]
584pub struct SandboxPolicy {
585 pub limits: ResourceLimits,
587 pub allowed_k2k_destinations: HashSet<String>,
589 pub denied_k2k_destinations: HashSet<String>,
591 pub memory_access: HashMap<String, AccessLevel>,
593 pub can_checkpoint: bool,
595 pub can_migrate: bool,
597 pub can_spawn: bool,
599 pub can_access_host: bool,
601 pub allowed_syscalls: HashSet<String>,
603}
604
605impl Default for SandboxPolicy {
606 fn default() -> Self {
607 Self {
608 limits: ResourceLimits::default(),
609 allowed_k2k_destinations: HashSet::new(),
610 denied_k2k_destinations: HashSet::new(),
611 memory_access: HashMap::new(),
612 can_checkpoint: true,
613 can_migrate: true,
614 can_spawn: false,
615 can_access_host: false,
616 allowed_syscalls: HashSet::new(),
617 }
618 }
619}
620
621impl SandboxPolicy {
622 pub fn new() -> Self {
624 Self::default()
625 }
626
627 pub fn with_limits(mut self, limits: ResourceLimits) -> Self {
629 self.limits = limits;
630 self
631 }
632
633 pub fn with_memory_limit(mut self, bytes: u64) -> Self {
635 self.limits.max_memory_bytes = bytes;
636 self
637 }
638
639 pub fn with_execution_timeout(mut self, timeout: Duration) -> Self {
641 self.limits.max_execution_time = timeout;
642 self
643 }
644
645 pub fn allow_k2k_to(mut self, destinations: &[&str]) -> Self {
647 self.allowed_k2k_destinations
648 .extend(destinations.iter().map(|s| s.to_string()));
649 self
650 }
651
652 pub fn deny_k2k_to(mut self, destinations: &[&str]) -> Self {
654 self.denied_k2k_destinations
655 .extend(destinations.iter().map(|s| s.to_string()));
656 self
657 }
658
659 pub fn with_memory_access(mut self, region: &str, access: AccessLevel) -> Self {
661 self.memory_access.insert(region.to_string(), access);
662 self
663 }
664
665 pub fn with_checkpoint(mut self, enabled: bool) -> Self {
667 self.can_checkpoint = enabled;
668 self
669 }
670
671 pub fn with_migration(mut self, enabled: bool) -> Self {
673 self.can_migrate = enabled;
674 self
675 }
676
677 pub fn with_spawn(mut self, enabled: bool) -> Self {
679 self.can_spawn = enabled;
680 self
681 }
682
683 pub fn with_host_access(mut self, enabled: bool) -> Self {
685 self.can_access_host = enabled;
686 self
687 }
688
689 pub fn restrictive() -> Self {
691 Self {
692 limits: ResourceLimits::restrictive(),
693 allowed_k2k_destinations: HashSet::new(),
694 denied_k2k_destinations: HashSet::new(),
695 memory_access: HashMap::new(),
696 can_checkpoint: false,
697 can_migrate: false,
698 can_spawn: false,
699 can_access_host: false,
700 allowed_syscalls: HashSet::new(),
701 }
702 }
703
704 pub fn permissive() -> Self {
706 Self {
707 limits: ResourceLimits::permissive(),
708 allowed_k2k_destinations: HashSet::new(),
709 denied_k2k_destinations: HashSet::new(),
710 memory_access: HashMap::new(),
711 can_checkpoint: true,
712 can_migrate: true,
713 can_spawn: true,
714 can_access_host: true,
715 allowed_syscalls: HashSet::new(),
716 }
717 }
718
719 pub fn is_k2k_allowed(&self, destination: &str) -> bool {
721 if self.denied_k2k_destinations.contains(destination) {
723 return false;
724 }
725 if self.allowed_k2k_destinations.is_empty() {
727 return true;
728 }
729 self.allowed_k2k_destinations.contains(destination)
731 }
732}
733
734#[derive(Debug, Clone, PartialEq, Eq)]
736pub enum ViolationType {
737 MemoryLimitExceeded {
739 used: u64,
741 limit: u64,
743 },
744 ExecutionTimeExceeded {
746 elapsed: Duration,
748 limit: Duration,
750 },
751 MessageRateExceeded {
753 rate: u32,
755 limit: u32,
757 },
758 UnauthorizedK2K {
760 destination: String,
762 },
763 UnauthorizedMemoryAccess {
765 region: String,
767 requested: AccessLevel,
769 },
770 CheckpointNotAllowed,
772 MigrationNotAllowed,
774 SpawnNotAllowed,
776 HostAccessNotAllowed,
778}
779
780impl fmt::Display for ViolationType {
781 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
782 match self {
783 Self::MemoryLimitExceeded { used, limit } => {
784 write!(f, "Memory limit exceeded: {} > {} bytes", used, limit)
785 }
786 Self::ExecutionTimeExceeded { elapsed, limit } => {
787 write!(f, "Execution time exceeded: {:?} > {:?}", elapsed, limit)
788 }
789 Self::MessageRateExceeded { rate, limit } => {
790 write!(f, "Message rate exceeded: {} > {} msg/s", rate, limit)
791 }
792 Self::UnauthorizedK2K { destination } => {
793 write!(f, "Unauthorized K2K to: {}", destination)
794 }
795 Self::UnauthorizedMemoryAccess { region, requested } => {
796 write!(
797 f,
798 "Unauthorized {:?} access to region: {}",
799 requested, region
800 )
801 }
802 Self::CheckpointNotAllowed => write!(f, "Checkpointing not allowed"),
803 Self::MigrationNotAllowed => write!(f, "Migration not allowed"),
804 Self::SpawnNotAllowed => write!(f, "Spawning not allowed"),
805 Self::HostAccessNotAllowed => write!(f, "Host memory access not allowed"),
806 }
807 }
808}
809
810#[derive(Debug, Clone)]
812pub struct SandboxViolation {
813 pub violation_type: ViolationType,
815 pub kernel_id: KernelId,
817 pub timestamp: Instant,
819 pub context: Option<String>,
821}
822
823#[derive(Debug, Clone, Default)]
825pub struct SandboxStats {
826 pub total_checks: u64,
828 pub violations_detected: u64,
830 pub operations_blocked: u64,
832 pub current_memory_usage: u64,
834 pub current_message_rate: u32,
836}
837
838pub struct KernelSandbox {
840 policy: SandboxPolicy,
842 kernel_id: Option<KernelId>,
844 stats: RwLock<SandboxStats>,
846 violations: RwLock<Vec<SandboxViolation>>,
848 start_time: RwLock<Option<Instant>>,
850 message_count: AtomicU64,
852 last_rate_check: RwLock<Instant>,
854}
855
856impl KernelSandbox {
857 pub fn new(policy: SandboxPolicy) -> Self {
859 Self {
860 policy,
861 kernel_id: None,
862 stats: RwLock::new(SandboxStats::default()),
863 violations: RwLock::new(Vec::new()),
864 start_time: RwLock::new(None),
865 message_count: AtomicU64::new(0),
866 last_rate_check: RwLock::new(Instant::now()),
867 }
868 }
869
870 pub fn apply_to_kernel(&mut self, kernel_id: KernelId) {
872 self.kernel_id = Some(kernel_id);
873 *self.start_time.write().unwrap() = Some(Instant::now());
874 }
875
876 pub fn check_memory(&self, bytes: u64) -> Result<(), SandboxViolation> {
878 self.stats.write().unwrap().total_checks += 1;
879
880 if bytes > self.policy.limits.max_memory_bytes {
881 let violation = SandboxViolation {
882 violation_type: ViolationType::MemoryLimitExceeded {
883 used: bytes,
884 limit: self.policy.limits.max_memory_bytes,
885 },
886 kernel_id: self
887 .kernel_id
888 .clone()
889 .unwrap_or_else(|| KernelId("unknown".to_string())),
890 timestamp: Instant::now(),
891 context: None,
892 };
893 self.record_violation(violation.clone());
894 return Err(violation);
895 }
896
897 self.stats.write().unwrap().current_memory_usage = bytes;
898 Ok(())
899 }
900
901 pub fn check_execution_time(&self) -> Result<(), SandboxViolation> {
903 self.stats.write().unwrap().total_checks += 1;
904
905 if let Some(start) = *self.start_time.read().unwrap() {
906 let elapsed = start.elapsed();
907 if elapsed > self.policy.limits.max_execution_time {
908 let violation = SandboxViolation {
909 violation_type: ViolationType::ExecutionTimeExceeded {
910 elapsed,
911 limit: self.policy.limits.max_execution_time,
912 },
913 kernel_id: self
914 .kernel_id
915 .clone()
916 .unwrap_or_else(|| KernelId("unknown".to_string())),
917 timestamp: Instant::now(),
918 context: None,
919 };
920 self.record_violation(violation.clone());
921 return Err(violation);
922 }
923 }
924 Ok(())
925 }
926
927 pub fn check_k2k(&self, destination: &str) -> Result<(), SandboxViolation> {
929 self.stats.write().unwrap().total_checks += 1;
930
931 if !self.policy.is_k2k_allowed(destination) {
932 let violation = SandboxViolation {
933 violation_type: ViolationType::UnauthorizedK2K {
934 destination: destination.to_string(),
935 },
936 kernel_id: self
937 .kernel_id
938 .clone()
939 .unwrap_or_else(|| KernelId("unknown".to_string())),
940 timestamp: Instant::now(),
941 context: None,
942 };
943 self.record_violation(violation.clone());
944 return Err(violation);
945 }
946 Ok(())
947 }
948
949 pub fn check_checkpoint(&self) -> Result<(), SandboxViolation> {
951 self.stats.write().unwrap().total_checks += 1;
952
953 if !self.policy.can_checkpoint {
954 let violation = SandboxViolation {
955 violation_type: ViolationType::CheckpointNotAllowed,
956 kernel_id: self
957 .kernel_id
958 .clone()
959 .unwrap_or_else(|| KernelId("unknown".to_string())),
960 timestamp: Instant::now(),
961 context: None,
962 };
963 self.record_violation(violation.clone());
964 return Err(violation);
965 }
966 Ok(())
967 }
968
969 pub fn check_migration(&self) -> Result<(), SandboxViolation> {
971 self.stats.write().unwrap().total_checks += 1;
972
973 if !self.policy.can_migrate {
974 let violation = SandboxViolation {
975 violation_type: ViolationType::MigrationNotAllowed,
976 kernel_id: self
977 .kernel_id
978 .clone()
979 .unwrap_or_else(|| KernelId("unknown".to_string())),
980 timestamp: Instant::now(),
981 context: None,
982 };
983 self.record_violation(violation.clone());
984 return Err(violation);
985 }
986 Ok(())
987 }
988
989 pub fn record_message(&self) -> Result<(), SandboxViolation> {
991 self.message_count.fetch_add(1, Ordering::Relaxed);
992
993 let mut last_check = self.last_rate_check.write().unwrap();
995 if last_check.elapsed() >= Duration::from_secs(1) {
996 let count = self.message_count.swap(0, Ordering::Relaxed) as u32;
997 *last_check = Instant::now();
998
999 self.stats.write().unwrap().current_message_rate = count;
1000
1001 if count > self.policy.limits.max_messages_per_sec {
1002 let violation = SandboxViolation {
1003 violation_type: ViolationType::MessageRateExceeded {
1004 rate: count,
1005 limit: self.policy.limits.max_messages_per_sec,
1006 },
1007 kernel_id: self
1008 .kernel_id
1009 .clone()
1010 .unwrap_or_else(|| KernelId("unknown".to_string())),
1011 timestamp: Instant::now(),
1012 context: None,
1013 };
1014 self.record_violation(violation.clone());
1015 return Err(violation);
1016 }
1017 }
1018 Ok(())
1019 }
1020
1021 fn record_violation(&self, violation: SandboxViolation) {
1023 let mut stats = self.stats.write().unwrap();
1024 stats.violations_detected += 1;
1025 stats.operations_blocked += 1;
1026
1027 self.violations.write().unwrap().push(violation);
1028 }
1029
1030 pub fn violations(&self) -> Vec<SandboxViolation> {
1032 self.violations.read().unwrap().clone()
1033 }
1034
1035 pub fn stats(&self) -> SandboxStats {
1037 self.stats.read().unwrap().clone()
1038 }
1039
1040 pub fn policy(&self) -> &SandboxPolicy {
1042 &self.policy
1043 }
1044
1045 pub fn reset(&self) {
1047 *self.stats.write().unwrap() = SandboxStats::default();
1048 self.violations.write().unwrap().clear();
1049 self.message_count.store(0, Ordering::Relaxed);
1050 }
1051}
1052
1053impl fmt::Debug for KernelSandbox {
1054 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1055 f.debug_struct("KernelSandbox")
1056 .field("policy", &self.policy)
1057 .field("kernel_id", &self.kernel_id)
1058 .field("stats", &self.stats())
1059 .field("violations_count", &self.violations.read().unwrap().len())
1060 .finish()
1061 }
1062}
1063
1064#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
1070pub enum ComplianceStandard {
1071 SOC2,
1073 GDPR,
1075 HIPAA,
1077 PCIDSS,
1079 ISO27001,
1081 FedRAMP,
1083 NIST,
1085}
1086
1087impl fmt::Display for ComplianceStandard {
1088 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1089 match self {
1090 Self::SOC2 => write!(f, "SOC 2 Type II"),
1091 Self::GDPR => write!(f, "GDPR"),
1092 Self::HIPAA => write!(f, "HIPAA"),
1093 Self::PCIDSS => write!(f, "PCI DSS"),
1094 Self::ISO27001 => write!(f, "ISO 27001"),
1095 Self::FedRAMP => write!(f, "FedRAMP"),
1096 Self::NIST => write!(f, "NIST CSF"),
1097 }
1098 }
1099}
1100
1101#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
1103pub enum ReportFormat {
1104 #[default]
1106 Json,
1107 Html,
1109 Markdown,
1111 Pdf,
1113 Csv,
1115}
1116
1117#[derive(Debug, Clone)]
1119pub enum ComplianceStatus {
1120 Compliant,
1122 PartiallyCompliant {
1124 notes: Vec<String>,
1126 },
1127 NonCompliant {
1129 reasons: Vec<String>,
1131 },
1132 NotApplicable,
1134}
1135
1136impl ComplianceStatus {
1137 pub fn is_compliant(&self) -> bool {
1139 matches!(self, Self::Compliant | Self::NotApplicable)
1140 }
1141}
1142
1143#[derive(Debug, Clone)]
1145pub struct ComplianceCheck {
1146 pub id: String,
1148 pub name: String,
1150 pub standard: ComplianceStandard,
1152 pub description: String,
1154 pub status: ComplianceStatus,
1156 pub evidence: Vec<String>,
1158 pub recommendations: Vec<String>,
1160 pub checked_at: SystemTime,
1162}
1163
1164#[derive(Debug, Clone)]
1166pub struct ComplianceSummary {
1167 pub total_checks: usize,
1169 pub compliant: usize,
1171 pub partially_compliant: usize,
1173 pub non_compliant: usize,
1175 pub not_applicable: usize,
1177 pub compliance_percentage: f64,
1179}
1180
1181#[derive(Debug, Clone)]
1183pub struct ComplianceReport {
1184 pub id: String,
1186 pub title: String,
1188 pub standards: Vec<ComplianceStandard>,
1190 pub checks: Vec<ComplianceCheck>,
1192 pub summary: ComplianceSummary,
1194 pub generated_at: SystemTime,
1196 pub period_start: SystemTime,
1198 pub period_end: SystemTime,
1200 pub metadata: HashMap<String, String>,
1202}
1203
1204impl ComplianceReport {
1205 pub fn export(&self, format: ReportFormat) -> String {
1207 match format {
1208 ReportFormat::Json => self.to_json(),
1209 ReportFormat::Html => self.to_html(),
1210 ReportFormat::Markdown => self.to_markdown(),
1211 ReportFormat::Pdf => self.to_markdown(), ReportFormat::Csv => self.to_csv(),
1213 }
1214 }
1215
1216 fn to_json(&self) -> String {
1217 let mut json = String::new();
1218 json.push_str("{\n");
1219 json.push_str(&format!(" \"id\": \"{}\",\n", self.id));
1220 json.push_str(&format!(" \"title\": \"{}\",\n", self.title));
1221 json.push_str(&format!(
1222 " \"standards\": [{}],\n",
1223 self.standards
1224 .iter()
1225 .map(|s| format!("\"{}\"", s))
1226 .collect::<Vec<_>>()
1227 .join(", ")
1228 ));
1229 json.push_str(" \"summary\": {\n");
1230 json.push_str(&format!(
1231 " \"total_checks\": {},\n",
1232 self.summary.total_checks
1233 ));
1234 json.push_str(&format!(" \"compliant\": {},\n", self.summary.compliant));
1235 json.push_str(&format!(
1236 " \"partially_compliant\": {},\n",
1237 self.summary.partially_compliant
1238 ));
1239 json.push_str(&format!(
1240 " \"non_compliant\": {},\n",
1241 self.summary.non_compliant
1242 ));
1243 json.push_str(&format!(
1244 " \"compliance_percentage\": {:.1}\n",
1245 self.summary.compliance_percentage
1246 ));
1247 json.push_str(" },\n");
1248 json.push_str(&format!(" \"checks_count\": {}\n", self.checks.len()));
1249 json.push_str("}\n");
1250 json
1251 }
1252
1253 fn to_html(&self) -> String {
1254 let mut html = String::new();
1255 html.push_str("<!DOCTYPE html>\n<html>\n<head>\n");
1256 html.push_str(&format!("<title>{}</title>\n", self.title));
1257 html.push_str("<style>body { font-family: sans-serif; } .compliant { color: green; } .non-compliant { color: red; }</style>\n");
1258 html.push_str("</head>\n<body>\n");
1259 html.push_str(&format!("<h1>{}</h1>\n", self.title));
1260 html.push_str(&format!("<p>Report ID: {}</p>\n", self.id));
1261 html.push_str("<h2>Summary</h2>\n");
1262 html.push_str("<table>\n");
1263 html.push_str(&format!(
1264 "<tr><td>Total Checks</td><td>{}</td></tr>\n",
1265 self.summary.total_checks
1266 ));
1267 html.push_str(&format!(
1268 "<tr><td>Compliant</td><td class=\"compliant\">{}</td></tr>\n",
1269 self.summary.compliant
1270 ));
1271 html.push_str(&format!(
1272 "<tr><td>Non-Compliant</td><td class=\"non-compliant\">{}</td></tr>\n",
1273 self.summary.non_compliant
1274 ));
1275 html.push_str(&format!(
1276 "<tr><td>Compliance</td><td>{:.1}%</td></tr>\n",
1277 self.summary.compliance_percentage
1278 ));
1279 html.push_str("</table>\n");
1280 html.push_str("<h2>Checks</h2>\n");
1281 for check in &self.checks {
1282 html.push_str(&format!("<h3>{}</h3>\n", check.name));
1283 html.push_str(&format!("<p>{}</p>\n", check.description));
1284 }
1285 html.push_str("</body>\n</html>\n");
1286 html
1287 }
1288
1289 fn to_markdown(&self) -> String {
1290 let mut md = String::new();
1291 md.push_str(&format!("# {}\n\n", self.title));
1292 md.push_str(&format!("**Report ID:** {}\n\n", self.id));
1293 md.push_str("## Summary\n\n");
1294 md.push_str("| Metric | Value |\n");
1295 md.push_str("|--------|-------|\n");
1296 md.push_str(&format!(
1297 "| Total Checks | {} |\n",
1298 self.summary.total_checks
1299 ));
1300 md.push_str(&format!("| Compliant | {} |\n", self.summary.compliant));
1301 md.push_str(&format!(
1302 "| Partially Compliant | {} |\n",
1303 self.summary.partially_compliant
1304 ));
1305 md.push_str(&format!(
1306 "| Non-Compliant | {} |\n",
1307 self.summary.non_compliant
1308 ));
1309 md.push_str(&format!(
1310 "| Compliance | {:.1}% |\n",
1311 self.summary.compliance_percentage
1312 ));
1313 md.push_str("\n## Detailed Checks\n\n");
1314 for check in &self.checks {
1315 let status_icon = match &check.status {
1316 ComplianceStatus::Compliant => "✅",
1317 ComplianceStatus::PartiallyCompliant { .. } => "⚠️",
1318 ComplianceStatus::NonCompliant { .. } => "❌",
1319 ComplianceStatus::NotApplicable => "➖",
1320 };
1321 md.push_str(&format!("### {} {}\n\n", status_icon, check.name));
1322 md.push_str(&format!("{}\n\n", check.description));
1323 }
1324 md
1325 }
1326
1327 fn to_csv(&self) -> String {
1328 let mut csv = String::new();
1329 csv.push_str("ID,Name,Standard,Status,Description\n");
1330 for check in &self.checks {
1331 let status = match &check.status {
1332 ComplianceStatus::Compliant => "Compliant",
1333 ComplianceStatus::PartiallyCompliant { .. } => "Partially Compliant",
1334 ComplianceStatus::NonCompliant { .. } => "Non-Compliant",
1335 ComplianceStatus::NotApplicable => "N/A",
1336 };
1337 csv.push_str(&format!(
1338 "\"{}\",\"{}\",\"{}\",\"{}\",\"{}\"\n",
1339 check.id, check.name, check.standard, status, check.description
1340 ));
1341 }
1342 csv
1343 }
1344}
1345
1346pub struct ComplianceReporter {
1348 standards: HashSet<ComplianceStandard>,
1350 organization: String,
1352 metadata: HashMap<String, String>,
1354 custom_checks: Vec<Box<dyn Fn() -> ComplianceCheck + Send + Sync>>,
1356}
1357
1358impl ComplianceReporter {
1359 pub fn new() -> Self {
1361 Self {
1362 standards: HashSet::new(),
1363 organization: "Unknown".to_string(),
1364 metadata: HashMap::new(),
1365 custom_checks: Vec::new(),
1366 }
1367 }
1368
1369 pub fn with_standard(mut self, standard: ComplianceStandard) -> Self {
1371 self.standards.insert(standard);
1372 self
1373 }
1374
1375 pub fn with_organization(mut self, org: &str) -> Self {
1377 self.organization = org.to_string();
1378 self
1379 }
1380
1381 pub fn with_metadata(mut self, key: &str, value: &str) -> Self {
1383 self.metadata.insert(key.to_string(), value.to_string());
1384 self
1385 }
1386
1387 pub fn generate_report(&self, _format: ReportFormat) -> ComplianceReport {
1389 let mut checks = Vec::new();
1390 let now = SystemTime::now();
1391
1392 for standard in &self.standards {
1394 checks.extend(self.generate_standard_checks(*standard));
1395 }
1396
1397 for check_fn in &self.custom_checks {
1399 checks.push(check_fn());
1400 }
1401
1402 let total = checks.len();
1404 let compliant = checks
1405 .iter()
1406 .filter(|c| matches!(c.status, ComplianceStatus::Compliant))
1407 .count();
1408 let partial = checks
1409 .iter()
1410 .filter(|c| matches!(c.status, ComplianceStatus::PartiallyCompliant { .. }))
1411 .count();
1412 let non_compliant = checks
1413 .iter()
1414 .filter(|c| matches!(c.status, ComplianceStatus::NonCompliant { .. }))
1415 .count();
1416 let na = checks
1417 .iter()
1418 .filter(|c| matches!(c.status, ComplianceStatus::NotApplicable))
1419 .count();
1420
1421 let applicable = total - na;
1422 let compliance_pct = if applicable > 0 {
1423 ((compliant as f64 + partial as f64 * 0.5) / applicable as f64) * 100.0
1424 } else {
1425 100.0
1426 };
1427
1428 ComplianceReport {
1429 id: format!(
1430 "RPT-{}",
1431 now.duration_since(SystemTime::UNIX_EPOCH)
1432 .unwrap()
1433 .as_secs()
1434 ),
1435 title: format!("{} Compliance Report", self.organization),
1436 standards: self.standards.iter().copied().collect(),
1437 checks,
1438 summary: ComplianceSummary {
1439 total_checks: total,
1440 compliant,
1441 partially_compliant: partial,
1442 non_compliant,
1443 not_applicable: na,
1444 compliance_percentage: compliance_pct,
1445 },
1446 generated_at: now,
1447 period_start: now - Duration::from_secs(30 * 24 * 60 * 60), period_end: now,
1449 metadata: self.metadata.clone(),
1450 }
1451 }
1452
1453 fn generate_standard_checks(&self, standard: ComplianceStandard) -> Vec<ComplianceCheck> {
1454 let now = SystemTime::now();
1455
1456 match standard {
1457 ComplianceStandard::SOC2 => vec![
1458 ComplianceCheck {
1459 id: "SOC2-CC1.1".to_string(),
1460 name: "Control Environment".to_string(),
1461 standard,
1462 description:
1463 "The entity demonstrates commitment to integrity and ethical values."
1464 .to_string(),
1465 status: ComplianceStatus::Compliant,
1466 evidence: vec![
1467 "Audit logging enabled".to_string(),
1468 "Access controls implemented".to_string(),
1469 ],
1470 recommendations: vec![],
1471 checked_at: now,
1472 },
1473 ComplianceCheck {
1474 id: "SOC2-CC6.1".to_string(),
1475 name: "Logical Access Controls".to_string(),
1476 standard,
1477 description:
1478 "Logical access security software, infrastructure, and architectures."
1479 .to_string(),
1480 status: ComplianceStatus::Compliant,
1481 evidence: vec![
1482 "Kernel sandboxing available".to_string(),
1483 "Memory encryption available".to_string(),
1484 ],
1485 recommendations: vec![],
1486 checked_at: now,
1487 },
1488 ComplianceCheck {
1489 id: "SOC2-CC7.2".to_string(),
1490 name: "System Monitoring".to_string(),
1491 standard,
1492 description: "System components are monitored and anomalies are identified."
1493 .to_string(),
1494 status: ComplianceStatus::Compliant,
1495 evidence: vec![
1496 "Health monitoring enabled".to_string(),
1497 "GPU memory dashboard available".to_string(),
1498 ],
1499 recommendations: vec![],
1500 checked_at: now,
1501 },
1502 ],
1503 ComplianceStandard::GDPR => vec![
1504 ComplianceCheck {
1505 id: "GDPR-32".to_string(),
1506 name: "Security of Processing".to_string(),
1507 standard,
1508 description: "Implement appropriate technical and organizational measures."
1509 .to_string(),
1510 status: ComplianceStatus::Compliant,
1511 evidence: vec!["Memory encryption available".to_string()],
1512 recommendations: vec!["Consider enabling encryption by default".to_string()],
1513 checked_at: now,
1514 },
1515 ComplianceCheck {
1516 id: "GDPR-33".to_string(),
1517 name: "Breach Notification".to_string(),
1518 standard,
1519 description: "Notify supervisory authority of personal data breach."
1520 .to_string(),
1521 status: ComplianceStatus::PartiallyCompliant {
1522 notes: vec!["Audit logging available but breach detection not automated"
1523 .to_string()],
1524 },
1525 evidence: vec!["Audit logging enabled".to_string()],
1526 recommendations: vec!["Add automated breach detection".to_string()],
1527 checked_at: now,
1528 },
1529 ],
1530 ComplianceStandard::HIPAA => vec![
1531 ComplianceCheck {
1532 id: "HIPAA-164.312(a)".to_string(),
1533 name: "Access Control".to_string(),
1534 standard,
1535 description: "Implement technical policies for electronic PHI access."
1536 .to_string(),
1537 status: ComplianceStatus::Compliant,
1538 evidence: vec![
1539 "Kernel sandboxing available".to_string(),
1540 "Access levels configurable".to_string(),
1541 ],
1542 recommendations: vec![],
1543 checked_at: now,
1544 },
1545 ComplianceCheck {
1546 id: "HIPAA-164.312(e)".to_string(),
1547 name: "Transmission Security".to_string(),
1548 standard,
1549 description: "Implement security measures for ePHI transmission.".to_string(),
1550 status: ComplianceStatus::Compliant,
1551 evidence: vec!["Memory encryption for data at rest".to_string()],
1552 recommendations: vec!["Implement TLS for network K2K".to_string()],
1553 checked_at: now,
1554 },
1555 ],
1556 ComplianceStandard::PCIDSS => vec![
1557 ComplianceCheck {
1558 id: "PCI-3.4".to_string(),
1559 name: "Render PAN Unreadable".to_string(),
1560 standard,
1561 description: "Render PAN unreadable anywhere it is stored.".to_string(),
1562 status: ComplianceStatus::Compliant,
1563 evidence: vec!["AES-256-GCM encryption available".to_string()],
1564 recommendations: vec![],
1565 checked_at: now,
1566 },
1567 ComplianceCheck {
1568 id: "PCI-10.1".to_string(),
1569 name: "Audit Trails".to_string(),
1570 standard,
1571 description: "Implement audit trails to link access to individual users."
1572 .to_string(),
1573 status: ComplianceStatus::Compliant,
1574 evidence: vec!["Comprehensive audit logging".to_string()],
1575 recommendations: vec![],
1576 checked_at: now,
1577 },
1578 ],
1579 ComplianceStandard::ISO27001 => vec![ComplianceCheck {
1580 id: "ISO-A.10.1".to_string(),
1581 name: "Cryptographic Controls".to_string(),
1582 standard,
1583 description: "Policy on use of cryptographic controls.".to_string(),
1584 status: ComplianceStatus::Compliant,
1585 evidence: vec!["Multiple encryption algorithms supported".to_string()],
1586 recommendations: vec![],
1587 checked_at: now,
1588 }],
1589 ComplianceStandard::FedRAMP => vec![ComplianceCheck {
1590 id: "FedRAMP-SC-28".to_string(),
1591 name: "Protection of Information at Rest".to_string(),
1592 standard,
1593 description: "Protect confidentiality and integrity of information at rest."
1594 .to_string(),
1595 status: ComplianceStatus::Compliant,
1596 evidence: vec!["FIPS-compliant algorithms available".to_string()],
1597 recommendations: vec![],
1598 checked_at: now,
1599 }],
1600 ComplianceStandard::NIST => vec![
1601 ComplianceCheck {
1602 id: "NIST-PR.DS-1".to_string(),
1603 name: "Data-at-rest Protection".to_string(),
1604 standard,
1605 description: "Data-at-rest is protected.".to_string(),
1606 status: ComplianceStatus::Compliant,
1607 evidence: vec!["Memory encryption module".to_string()],
1608 recommendations: vec![],
1609 checked_at: now,
1610 },
1611 ComplianceCheck {
1612 id: "NIST-DE.CM-1".to_string(),
1613 name: "Network Monitoring".to_string(),
1614 standard,
1615 description: "The network is monitored to detect cybersecurity events."
1616 .to_string(),
1617 status: ComplianceStatus::Compliant,
1618 evidence: vec![
1619 "Observability context".to_string(),
1620 "GPU profiler integration".to_string(),
1621 ],
1622 recommendations: vec![],
1623 checked_at: now,
1624 },
1625 ],
1626 }
1627 }
1628}
1629
1630impl Default for ComplianceReporter {
1631 fn default() -> Self {
1632 Self::new()
1633 }
1634}
1635
1636impl fmt::Debug for ComplianceReporter {
1637 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1638 f.debug_struct("ComplianceReporter")
1639 .field("standards", &self.standards)
1640 .field("organization", &self.organization)
1641 .field("metadata", &self.metadata)
1642 .field("custom_checks_count", &self.custom_checks.len())
1643 .finish()
1644 }
1645}
1646
1647#[cfg(test)]
1652mod tests {
1653 use super::*;
1654
1655 #[test]
1658 fn test_encryption_config_builder() {
1659 let config = EncryptionConfig::new()
1660 .with_algorithm(EncryptionAlgorithm::ChaCha20Poly1305)
1661 .with_key_rotation_interval(Duration::from_secs(7200))
1662 .with_control_block_encryption(false);
1663
1664 assert_eq!(config.algorithm, EncryptionAlgorithm::ChaCha20Poly1305);
1665 assert_eq!(config.key_rotation_interval, Duration::from_secs(7200));
1666 assert!(!config.encrypt_control_blocks);
1667 }
1668
1669 #[test]
1670 fn test_encryption_key_creation() {
1671 let key = EncryptionKey::new(1, EncryptionAlgorithm::Aes256Gcm);
1672 assert_eq!(key.key_id, 1);
1673 assert_eq!(key.key_size(), 32);
1674 assert!(!key.is_expired());
1675 }
1676
1677 #[test]
1678 fn test_encrypt_decrypt_roundtrip() {
1679 let encryption = MemoryEncryption::new(EncryptionConfig::default());
1680 let plaintext = b"Hello, GPU World!";
1681
1682 let encrypted = encryption.encrypt_region(plaintext);
1683 assert_ne!(encrypted.ciphertext[..plaintext.len()], plaintext[..]);
1684
1685 let decrypted = encryption.decrypt_region(&encrypted).unwrap();
1686 assert_eq!(decrypted, plaintext);
1687 }
1688
1689 #[test]
1690 fn test_key_rotation() {
1691 let encryption = MemoryEncryption::new(EncryptionConfig::default());
1692 let initial_key_id = encryption.current_key_id();
1693
1694 encryption.rotate_keys();
1695 assert_eq!(encryption.current_key_id(), initial_key_id + 1);
1696
1697 let stats = encryption.stats();
1699 assert_eq!(stats.key_rotations, 1);
1700 }
1701
1702 #[test]
1703 fn test_decrypt_with_old_key() {
1704 let encryption = MemoryEncryption::new(EncryptionConfig::default());
1705 let plaintext = b"Secret data";
1706
1707 let encrypted = encryption.encrypt_region(plaintext);
1708 let old_key_id = encrypted.key_id;
1709
1710 encryption.rotate_keys();
1712 assert_ne!(encryption.current_key_id(), old_key_id);
1713
1714 let decrypted = encryption.decrypt_region(&encrypted).unwrap();
1716 assert_eq!(decrypted, plaintext);
1717 }
1718
1719 #[test]
1720 fn test_encryption_stats() {
1721 let encryption = MemoryEncryption::new(EncryptionConfig::default());
1722 let data = vec![0u8; 1024];
1723
1724 for _ in 0..10 {
1725 let encrypted = encryption.encrypt_region(&data);
1726 let _ = encryption.decrypt_region(&encrypted);
1727 }
1728
1729 let stats = encryption.stats();
1730 assert_eq!(stats.encrypt_ops, 10);
1731 assert_eq!(stats.decrypt_ops, 10);
1732 assert_eq!(stats.bytes_encrypted, 10240);
1733 }
1734
1735 #[test]
1738 fn test_resource_limits_builder() {
1739 let limits = ResourceLimits::new()
1740 .with_max_memory(512 * 1024 * 1024)
1741 .with_max_execution_time(Duration::from_secs(30));
1742
1743 assert_eq!(limits.max_memory_bytes, 512 * 1024 * 1024);
1744 assert_eq!(limits.max_execution_time, Duration::from_secs(30));
1745 }
1746
1747 #[test]
1748 fn test_sandbox_policy_k2k() {
1749 let policy = SandboxPolicy::new()
1750 .allow_k2k_to(&["trusted_kernel", "another_trusted"])
1751 .deny_k2k_to(&["malicious_kernel"]);
1752
1753 assert!(policy.is_k2k_allowed("trusted_kernel"));
1754 assert!(policy.is_k2k_allowed("another_trusted"));
1755 assert!(!policy.is_k2k_allowed("malicious_kernel"));
1756 assert!(!policy.is_k2k_allowed("unknown_kernel")); }
1758
1759 #[test]
1760 fn test_sandbox_memory_check() {
1761 let policy = SandboxPolicy::new().with_memory_limit(1024);
1762 let sandbox = KernelSandbox::new(policy);
1763
1764 assert!(sandbox.check_memory(512).is_ok());
1766
1767 let result = sandbox.check_memory(2048);
1769 assert!(result.is_err());
1770
1771 if let Err(violation) = result {
1772 assert!(matches!(
1773 violation.violation_type,
1774 ViolationType::MemoryLimitExceeded { .. }
1775 ));
1776 }
1777 }
1778
1779 #[test]
1780 fn test_sandbox_k2k_check() {
1781 let policy = SandboxPolicy::new().deny_k2k_to(&["blocked"]);
1782 let sandbox = KernelSandbox::new(policy);
1783
1784 assert!(sandbox.check_k2k("allowed_dest").is_ok());
1785 assert!(sandbox.check_k2k("blocked").is_err());
1786 }
1787
1788 #[test]
1789 fn test_sandbox_checkpoint_check() {
1790 let policy = SandboxPolicy::restrictive();
1791 let sandbox = KernelSandbox::new(policy);
1792
1793 assert!(sandbox.check_checkpoint().is_err());
1794
1795 let permissive = SandboxPolicy::permissive();
1796 let sandbox2 = KernelSandbox::new(permissive);
1797 assert!(sandbox2.check_checkpoint().is_ok());
1798 }
1799
1800 #[test]
1801 fn test_sandbox_stats() {
1802 let policy = SandboxPolicy::new().with_memory_limit(1024);
1803 let sandbox = KernelSandbox::new(policy);
1804
1805 let _ = sandbox.check_memory(512);
1806 let _ = sandbox.check_memory(2048); let _ = sandbox.check_k2k("dest");
1808
1809 let stats = sandbox.stats();
1810 assert_eq!(stats.total_checks, 3);
1811 assert_eq!(stats.violations_detected, 1);
1812 }
1813
1814 #[test]
1815 fn test_sandbox_violations_list() {
1816 let policy = SandboxPolicy::restrictive();
1817 let sandbox = KernelSandbox::new(policy);
1818
1819 let _ = sandbox.check_checkpoint();
1820 let _ = sandbox.check_migration();
1821
1822 let violations = sandbox.violations();
1823 assert_eq!(violations.len(), 2);
1824 }
1825
1826 #[test]
1829 fn test_compliance_reporter_creation() {
1830 let reporter = ComplianceReporter::new()
1831 .with_standard(ComplianceStandard::SOC2)
1832 .with_standard(ComplianceStandard::GDPR)
1833 .with_organization("Test Org");
1834
1835 assert_eq!(reporter.standards.len(), 2);
1836 assert!(reporter.standards.contains(&ComplianceStandard::SOC2));
1837 assert!(reporter.standards.contains(&ComplianceStandard::GDPR));
1838 }
1839
1840 #[test]
1841 fn test_generate_soc2_report() {
1842 let reporter = ComplianceReporter::new()
1843 .with_standard(ComplianceStandard::SOC2)
1844 .with_organization("Acme Corp");
1845
1846 let report = reporter.generate_report(ReportFormat::Json);
1847
1848 assert!(!report.checks.is_empty());
1849 assert!(report.summary.total_checks > 0);
1850 assert!(report.title.contains("Acme Corp"));
1851 }
1852
1853 #[test]
1854 fn test_report_json_export() {
1855 let reporter = ComplianceReporter::new().with_standard(ComplianceStandard::HIPAA);
1856
1857 let report = reporter.generate_report(ReportFormat::Json);
1858 let json = report.export(ReportFormat::Json);
1859
1860 assert!(json.contains("\"id\""));
1861 assert!(json.contains("\"summary\""));
1862 }
1863
1864 #[test]
1865 fn test_report_markdown_export() {
1866 let reporter = ComplianceReporter::new().with_standard(ComplianceStandard::NIST);
1867
1868 let report = reporter.generate_report(ReportFormat::Markdown);
1869 let md = report.export(ReportFormat::Markdown);
1870
1871 assert!(md.contains("# "));
1872 assert!(md.contains("## Summary"));
1873 assert!(md.contains("| Metric | Value |"));
1874 }
1875
1876 #[test]
1877 fn test_report_html_export() {
1878 let reporter = ComplianceReporter::new().with_standard(ComplianceStandard::PCIDSS);
1879
1880 let report = reporter.generate_report(ReportFormat::Html);
1881 let html = report.export(ReportFormat::Html);
1882
1883 assert!(html.contains("<!DOCTYPE html>"));
1884 assert!(html.contains("<h1>"));
1885 }
1886
1887 #[test]
1888 fn test_report_csv_export() {
1889 let reporter = ComplianceReporter::new().with_standard(ComplianceStandard::ISO27001);
1890
1891 let report = reporter.generate_report(ReportFormat::Csv);
1892 let csv = report.export(ReportFormat::Csv);
1893
1894 assert!(csv.contains("ID,Name,Standard,Status,Description"));
1895 }
1896
1897 #[test]
1898 fn test_compliance_summary_calculation() {
1899 let reporter = ComplianceReporter::new()
1900 .with_standard(ComplianceStandard::SOC2)
1901 .with_standard(ComplianceStandard::GDPR)
1902 .with_standard(ComplianceStandard::HIPAA);
1903
1904 let report = reporter.generate_report(ReportFormat::Json);
1905
1906 let sum = report.summary.compliant
1907 + report.summary.partially_compliant
1908 + report.summary.non_compliant
1909 + report.summary.not_applicable;
1910 assert_eq!(sum, report.summary.total_checks);
1911 }
1912
1913 #[test]
1914 fn test_compliance_status_is_compliant() {
1915 assert!(ComplianceStatus::Compliant.is_compliant());
1916 assert!(ComplianceStatus::NotApplicable.is_compliant());
1917 assert!(!ComplianceStatus::NonCompliant { reasons: vec![] }.is_compliant());
1918 assert!(!ComplianceStatus::PartiallyCompliant { notes: vec![] }.is_compliant());
1919 }
1920
1921 #[test]
1922 fn test_all_standards() {
1923 let reporter = ComplianceReporter::new()
1924 .with_standard(ComplianceStandard::SOC2)
1925 .with_standard(ComplianceStandard::GDPR)
1926 .with_standard(ComplianceStandard::HIPAA)
1927 .with_standard(ComplianceStandard::PCIDSS)
1928 .with_standard(ComplianceStandard::ISO27001)
1929 .with_standard(ComplianceStandard::FedRAMP)
1930 .with_standard(ComplianceStandard::NIST);
1931
1932 let report = reporter.generate_report(ReportFormat::Json);
1933 assert_eq!(report.standards.len(), 7);
1934 }
1935}