use tracing::info;
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum IsolationTier {
EnvProxy,
#[cfg(all(target_os = "linux", feature = "netns"))]
NetNamespace,
}
#[cfg(all(target_os = "linux", feature = "netns"))]
fn has_cap_net_admin() -> bool {
let Ok(status) = std::fs::read_to_string("/proc/self/status") else {
return false;
};
for line in status.lines() {
if let Some(hex) = line.strip_prefix("CapEff:\t") {
let Ok(caps) = u64::from_str_radix(hex.trim(), 16) else {
return false;
};
return caps & (1 << 12) != 0;
}
}
false
}
pub fn detect_and_log() -> IsolationTier {
#[cfg(all(target_os = "linux", feature = "netns"))]
{
if has_cap_net_admin() {
info!("proxy: network namespace isolation (linux/netns)");
return IsolationTier::NetNamespace;
}
info!("proxy: env var mode (netns unavailable: missing CAP_NET_ADMIN)");
return IsolationTier::EnvProxy;
}
#[cfg(not(all(target_os = "linux", feature = "netns")))]
{
#[cfg(target_os = "linux")]
info!("proxy: env var mode (netns feature not compiled)");
#[cfg(not(target_os = "linux"))]
info!("proxy: env var mode (not linux)");
IsolationTier::EnvProxy
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn detect_returns_valid_tier() {
let tier = detect_and_log();
#[cfg(not(all(target_os = "linux", feature = "netns")))]
assert_eq!(tier, IsolationTier::EnvProxy);
let _ = tier; }
}