Skip to main content

kz_proxy/
backend.rs

1//! Sandbox backend: selects how to force traffic through the proxy (Firecracker on Linux, Docker on macOS).
2
3use std::path::Path;
4
5use crate::enforce::{run_child_duct, Enforce};
6use crate::{ConnectionPolicy, SecretMapping, StringMapping};
7
8/// Sandbox backend for forcing traffic through the proxy. No "native" isolation; only these backends.
9#[derive(Clone, Copy, Debug, Eq, PartialEq)]
10pub enum SandboxBackend {
11    /// Run runner (proxy + child) inside a Firecracker microVM. Linux only.
12    Firecracker,
13    /// Run runner (proxy + child) inside a Docker container with --network none. macOS only.
14    Docker,
15}
16
17impl std::fmt::Display for SandboxBackend {
18    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
19        match self {
20            SandboxBackend::Firecracker => write!(f, "firecracker"),
21            SandboxBackend::Docker => write!(f, "docker"),
22        }
23    }
24}
25
26impl std::str::FromStr for SandboxBackend {
27    type Err = String;
28
29    fn from_str(s: &str) -> Result<Self, Self::Err> {
30        match s {
31            "firecracker" => Ok(SandboxBackend::Firecracker),
32            "docker" => Ok(SandboxBackend::Docker),
33            _ => Err(format!(
34                "unknown sandbox backend '{}'; use firecracker or docker",
35                s
36            )),
37        }
38    }
39}
40
41/// Enforcer that only sets proxy env and runs the child (no runner, no isolation). Used when
42/// force_traffic_through_proxy is false, or when we're already inside the runner (Docker/Firecracker).
43pub struct EnvOnlyEnforcer;
44
45impl Enforce for EnvOnlyEnforcer {
46    fn maybe_spawn_runner(
47        &self,
48        _cmd: &str,
49        _secret_mappings: &[SecretMapping],
50        _string_mappings: &[StringMapping],
51        _allow_private_connect: bool,
52        _upstream_ca: &Option<std::path::PathBuf>,
53        _connection_policies: &[ConnectionPolicy],
54    ) -> Result<Option<std::process::ExitStatus>, Box<dyn std::error::Error + Send + Sync>> {
55        Ok(None)
56    }
57
58    fn run_child(
59        &self,
60        cmd: &str,
61        proxy_url: &str,
62        env_vars_with_masked: &[(String, String)],
63        ssl_cert_file: &Path,
64        _force: bool,
65    ) -> Result<std::process::ExitStatus, Box<dyn std::error::Error + Send + Sync>> {
66        run_child_duct(cmd, proxy_url, env_vars_with_masked, ssl_cert_file)
67    }
68}
69
70/// Default backend for the current OS when force_traffic_through_proxy is true.
71#[cfg(target_os = "linux")]
72pub fn default_backend_for_os() -> SandboxBackend {
73    SandboxBackend::Firecracker
74}
75
76#[cfg(target_os = "macos")]
77pub fn default_backend_for_os() -> SandboxBackend {
78    SandboxBackend::Docker
79}
80
81#[cfg(not(any(target_os = "linux", target_os = "macos")))]
82pub fn default_backend_for_os() -> SandboxBackend {
83    // No isolation backend on this OS; callers should use env-only when force is true.
84    SandboxBackend::Firecracker
85}