//! Docker sandbox (container isolation) use crate::security::traits::Sandbox; use std::process::Command; /// Docker sandbox backend #[derive(Debug, Clone)] pub struct DockerSandbox { image: String, } impl Default for DockerSandbox { fn default() -> Self { Self { image: "alpine:latest".to_string(), } } } impl DockerSandbox { pub fn new() -> std::io::Result { if Self::is_installed() { Ok(Self::default()) } else { Err(std::io::Error::new( std::io::ErrorKind::NotFound, "Docker not found", )) } } pub fn with_image(image: String) -> std::io::Result { if Self::is_installed() { Ok(Self { image }) } else { Err(std::io::Error::new( std::io::ErrorKind::NotFound, "Docker not found", )) } } pub fn probe() -> std::io::Result { Self::new() } fn is_installed() -> bool { Command::new("docker") .arg("--version") .output() .map(|o| o.status.success()) .unwrap_or(false) } } impl Sandbox for DockerSandbox { fn wrap_command(&self, cmd: &mut Command) -> std::io::Result<()> { let program = cmd.get_program().to_string_lossy().to_string(); let args: Vec = cmd .get_args() .map(|s| s.to_string_lossy().to_string()) .collect(); let mut docker_cmd = Command::new("docker"); docker_cmd.args([ "run", "--rm", "--memory", "512m", "--cpus", "1.0", "--network", "none", ]); docker_cmd.arg(&self.image); docker_cmd.arg(&program); docker_cmd.args(&args); *cmd = docker_cmd; Ok(()) } fn is_available(&self) -> bool { Self::is_installed() } fn name(&self) -> &str { "docker" } fn description(&self) -> &str { "Docker container isolation (requires docker)" } } #[cfg(test)] mod tests { use super::*; #[test] fn docker_sandbox_name() { let sandbox = DockerSandbox::default(); assert_eq!(sandbox.name(), "docker"); } #[test] fn docker_sandbox_default_image() { let sandbox = DockerSandbox::default(); assert_eq!(sandbox.image, "alpine:latest"); } #[test] fn docker_with_custom_image() { let result = DockerSandbox::with_image("ubuntu:latest".to_string()); match result { Ok(sandbox) => assert_eq!(sandbox.image, "ubuntu:latest"), Err(_) => assert!(!DockerSandbox::is_installed()), } } }