refactor: remove proxy admin endpoint (#13687)

## Summary
- delete the network proxy admin server and its runtime listener/task
plumbing
- remove the admin endpoint config, runtime, requirement, protocol,
schema, and debug-surface fields
- update proxy docs to reflect the remaining HTTP and SOCKS listeners
only
This commit is contained in:
viyatb-oai
2026-03-05 22:03:16 -08:00
committed by GitHub
parent f9ce403b5a
commit 6a79ed5920
24 changed files with 30 additions and 476 deletions

View File

@@ -1,181 +0,0 @@
use crate::config::NetworkMode;
use crate::responses::json_response;
use crate::responses::text_response;
use crate::state::NetworkProxyState;
use anyhow::Context;
use anyhow::Result;
use rama_core::rt::Executor;
use rama_core::service::service_fn;
use rama_http::Body;
use rama_http::Request;
use rama_http::Response;
use rama_http::StatusCode;
use rama_http_backend::server::HttpServer;
use rama_tcp::server::TcpListener;
use serde::Deserialize;
use serde::Serialize;
use std::convert::Infallible;
use std::net::SocketAddr;
use std::net::TcpListener as StdTcpListener;
use std::sync::Arc;
use tracing::error;
use tracing::info;
pub async fn run_admin_api(state: Arc<NetworkProxyState>, addr: SocketAddr) -> Result<()> {
// Debug-only admin API (health/config/patterns/blocked + mode/reload). Policy is config-driven
// and constraint-enforced; this endpoint should not become a second policy/approval plane.
let listener = TcpListener::build()
.bind(addr)
.await
// See `http_proxy.rs` for details on why we wrap `BoxError` before converting to anyhow.
.map_err(rama_core::error::OpaqueError::from)
.map_err(anyhow::Error::from)
.with_context(|| format!("bind admin API: {addr}"))?;
run_admin_api_with_listener(state, listener).await
}
pub async fn run_admin_api_with_std_listener(
state: Arc<NetworkProxyState>,
listener: StdTcpListener,
) -> Result<()> {
let listener =
TcpListener::try_from(listener).context("convert std listener to admin API listener")?;
run_admin_api_with_listener(state, listener).await
}
async fn run_admin_api_with_listener(
state: Arc<NetworkProxyState>,
listener: TcpListener,
) -> Result<()> {
let addr = listener
.local_addr()
.context("read admin API listener local addr")?;
let server_state = state.clone();
let server = HttpServer::auto(Executor::new()).service(service_fn(move |req| {
let state = server_state.clone();
async move { handle_admin_request(state, req).await }
}));
info!("admin API listening on {addr}");
listener.serve(server).await;
Ok(())
}
async fn handle_admin_request(
state: Arc<NetworkProxyState>,
req: Request,
) -> Result<Response, Infallible> {
const MODE_BODY_LIMIT: usize = 8 * 1024;
let method = req.method().clone();
let path = req.uri().path().to_string();
let response = match (method.as_str(), path.as_str()) {
("GET", "/health") => Response::new(Body::from("ok")),
("GET", "/config") => match state.current_cfg().await {
Ok(cfg) => json_response(&cfg),
Err(err) => {
error!("failed to load config: {err}");
text_response(StatusCode::INTERNAL_SERVER_ERROR, "error")
}
},
("GET", "/patterns") => match state.current_patterns().await {
Ok((allow, deny)) => json_response(&PatternsResponse {
allowed: allow,
denied: deny,
}),
Err(err) => {
error!("failed to load patterns: {err}");
text_response(StatusCode::INTERNAL_SERVER_ERROR, "error")
}
},
("GET", "/blocked") => match state.blocked_snapshot().await {
Ok(blocked) => json_response(&BlockedResponse { blocked }),
Err(err) => {
error!("failed to read blocked queue: {err}");
text_response(StatusCode::INTERNAL_SERVER_ERROR, "error")
}
},
("POST", "/mode") => {
let mut body = req.into_body();
let mut buf: Vec<u8> = Vec::new();
loop {
let chunk = match body.chunk().await {
Ok(chunk) => chunk,
Err(err) => {
error!("failed to read mode body: {err}");
return Ok(text_response(StatusCode::BAD_REQUEST, "invalid body"));
}
};
let Some(chunk) = chunk else {
break;
};
if buf.len().saturating_add(chunk.len()) > MODE_BODY_LIMIT {
return Ok(text_response(
StatusCode::PAYLOAD_TOO_LARGE,
"body too large",
));
}
buf.extend_from_slice(&chunk);
}
if buf.is_empty() {
return Ok(text_response(StatusCode::BAD_REQUEST, "missing body"));
}
let update: ModeUpdate = match serde_json::from_slice(&buf) {
Ok(update) => update,
Err(err) => {
error!("failed to parse mode update: {err}");
return Ok(text_response(StatusCode::BAD_REQUEST, "invalid json"));
}
};
match state.set_network_mode(update.mode).await {
Ok(()) => json_response(&ModeUpdateResponse {
status: "ok",
mode: update.mode,
}),
Err(err) => {
error!("mode update failed: {err}");
text_response(StatusCode::INTERNAL_SERVER_ERROR, "mode update failed")
}
}
}
("POST", "/reload") => match state.force_reload().await {
Ok(()) => json_response(&ReloadResponse { status: "reloaded" }),
Err(err) => {
error!("reload failed: {err}");
text_response(StatusCode::INTERNAL_SERVER_ERROR, "reload failed")
}
},
_ => text_response(StatusCode::NOT_FOUND, "not found"),
};
Ok(response)
}
#[derive(Deserialize)]
struct ModeUpdate {
mode: NetworkMode,
}
#[derive(Debug, Serialize)]
struct PatternsResponse {
allowed: Vec<String>,
denied: Vec<String>,
}
#[derive(Debug, Serialize)]
struct BlockedResponse<T> {
blocked: T,
}
#[derive(Debug, Serialize)]
struct ModeUpdateResponse {
status: &'static str,
mode: NetworkMode,
}
#[derive(Debug, Serialize)]
struct ReloadResponse {
status: &'static str,
}

View File

@@ -23,8 +23,6 @@ pub struct NetworkProxySettings {
pub enabled: bool,
#[serde(default = "default_proxy_url")]
pub proxy_url: String,
#[serde(default = "default_admin_url")]
pub admin_url: String,
pub enable_socks5: bool,
#[serde(default = "default_socks_url")]
pub socks_url: String,
@@ -33,8 +31,6 @@ pub struct NetworkProxySettings {
#[serde(default)]
pub dangerously_allow_non_loopback_proxy: bool,
#[serde(default)]
pub dangerously_allow_non_loopback_admin: bool,
#[serde(default)]
pub dangerously_allow_all_unix_sockets: bool,
#[serde(default)]
pub mode: NetworkMode,
@@ -54,13 +50,11 @@ impl Default for NetworkProxySettings {
Self {
enabled: false,
proxy_url: default_proxy_url(),
admin_url: default_admin_url(),
enable_socks5: true,
socks_url: default_socks_url(),
enable_socks5_udp: true,
allow_upstream_proxy: true,
dangerously_allow_non_loopback_proxy: false,
dangerously_allow_non_loopback_admin: false,
dangerously_allow_all_unix_sockets: false,
mode: NetworkMode::default(),
allowed_domains: Vec::new(),
@@ -98,16 +92,17 @@ fn default_proxy_url() -> String {
"http://127.0.0.1:3128".to_string()
}
fn default_admin_url() -> String {
"http://127.0.0.1:8080".to_string()
}
fn default_socks_url() -> String {
"http://127.0.0.1:8081".to_string()
}
/// Clamp non-loopback bind addresses to loopback unless explicitly allowed.
fn clamp_non_loopback(addr: SocketAddr, allow_non_loopback: bool, name: &str) -> SocketAddr {
fn clamp_non_loopback(
addr: SocketAddr,
allow_non_loopback: bool,
name: &str,
override_setting_name: &str,
) -> SocketAddr {
if addr.ip().is_loopback() {
return addr;
}
@@ -118,7 +113,7 @@ fn clamp_non_loopback(addr: SocketAddr, allow_non_loopback: bool, name: &str) ->
}
warn!(
"{name} requested non-loopback bind ({addr}); clamping to 127.0.0.1:{port} (set dangerously_allow_non_loopback_proxy or dangerously_allow_non_loopback_admin to override)",
"{name} requested non-loopback bind ({addr}); clamping to 127.0.0.1:{port} (set {override_setting_name} to override)",
port = addr.port()
);
SocketAddr::from(([127, 0, 0, 1], addr.port()))
@@ -127,30 +122,26 @@ fn clamp_non_loopback(addr: SocketAddr, allow_non_loopback: bool, name: &str) ->
pub(crate) fn clamp_bind_addrs(
http_addr: SocketAddr,
socks_addr: SocketAddr,
admin_addr: SocketAddr,
cfg: &NetworkProxySettings,
) -> (SocketAddr, SocketAddr, SocketAddr) {
) -> (SocketAddr, SocketAddr) {
let http_addr = clamp_non_loopback(
http_addr,
cfg.dangerously_allow_non_loopback_proxy,
"HTTP proxy",
"dangerously_allow_non_loopback_proxy",
);
let socks_addr = clamp_non_loopback(
socks_addr,
cfg.dangerously_allow_non_loopback_proxy,
"SOCKS5 proxy",
);
let admin_addr = clamp_non_loopback(
admin_addr,
cfg.dangerously_allow_non_loopback_admin,
"admin API",
"dangerously_allow_non_loopback_proxy",
);
if cfg.allow_unix_sockets.is_empty() && !cfg.dangerously_allow_all_unix_sockets {
return (http_addr, socks_addr, admin_addr);
return (http_addr, socks_addr);
}
// `x-unix-socket` is intentionally a local escape hatch. If the proxy (or admin API) is
// reachable from outside the machine, it can become a remote bridge into local daemons
// `x-unix-socket` is intentionally a local escape hatch. If the proxy is reachable from
// outside the machine, it can become a remote bridge into local daemons
// (e.g. docker.sock). To avoid footguns, enforce loopback binding whenever unix sockets
// are enabled.
if cfg.dangerously_allow_non_loopback_proxy && !http_addr.ip().is_loopback() {
@@ -163,22 +154,15 @@ pub(crate) fn clamp_bind_addrs(
"unix socket proxying is enabled; ignoring dangerously_allow_non_loopback_proxy and clamping SOCKS5 proxy to loopback"
);
}
if cfg.dangerously_allow_non_loopback_admin && !admin_addr.ip().is_loopback() {
warn!(
"unix socket proxying is enabled; ignoring dangerously_allow_non_loopback_admin and clamping admin API to loopback"
);
}
(
SocketAddr::from(([127, 0, 0, 1], http_addr.port())),
SocketAddr::from(([127, 0, 0, 1], socks_addr.port())),
SocketAddr::from(([127, 0, 0, 1], admin_addr.port())),
)
}
pub struct RuntimeConfig {
pub http_addr: SocketAddr,
pub socks_addr: SocketAddr,
pub admin_addr: SocketAddr,
}
#[derive(Debug, Clone, PartialEq, Eq)]
@@ -228,15 +212,11 @@ pub fn resolve_runtime(cfg: &NetworkProxyConfig) -> Result<RuntimeConfig> {
.with_context(|| format!("invalid network.proxy_url: {}", cfg.network.proxy_url))?;
let socks_addr = resolve_addr(&cfg.network.socks_url, 8081)
.with_context(|| format!("invalid network.socks_url: {}", cfg.network.socks_url))?;
let admin_addr = resolve_addr(&cfg.network.admin_url, 8080)
.with_context(|| format!("invalid network.admin_url: {}", cfg.network.admin_url))?;
let (http_addr, socks_addr, admin_addr) =
clamp_bind_addrs(http_addr, socks_addr, admin_addr, &cfg.network);
let (http_addr, socks_addr) = clamp_bind_addrs(http_addr, socks_addr, &cfg.network);
Ok(RuntimeConfig {
http_addr,
socks_addr,
admin_addr,
})
}
@@ -384,13 +364,11 @@ mod tests {
NetworkProxySettings {
enabled: false,
proxy_url: "http://127.0.0.1:3128".to_string(),
admin_url: "http://127.0.0.1:8080".to_string(),
enable_socks5: true,
socks_url: "http://127.0.0.1:8081".to_string(),
enable_socks5_udp: true,
allow_upstream_proxy: true,
dangerously_allow_non_loopback_proxy: false,
dangerously_allow_non_loopback_admin: false,
dangerously_allow_all_unix_sockets: false,
mode: NetworkMode::Full,
allowed_domains: Vec::new(),
@@ -545,59 +523,47 @@ mod tests {
fn clamp_bind_addrs_allows_non_loopback_when_enabled() {
let cfg = NetworkProxySettings {
dangerously_allow_non_loopback_proxy: true,
dangerously_allow_non_loopback_admin: true,
..Default::default()
};
let http_addr = "0.0.0.0:3128".parse::<SocketAddr>().unwrap();
let socks_addr = "0.0.0.0:8081".parse::<SocketAddr>().unwrap();
let admin_addr = "0.0.0.0:8080".parse::<SocketAddr>().unwrap();
let (http_addr, socks_addr, admin_addr) =
clamp_bind_addrs(http_addr, socks_addr, admin_addr, &cfg);
let (http_addr, socks_addr) = clamp_bind_addrs(http_addr, socks_addr, &cfg);
assert_eq!(http_addr, "0.0.0.0:3128".parse::<SocketAddr>().unwrap());
assert_eq!(socks_addr, "0.0.0.0:8081".parse::<SocketAddr>().unwrap());
assert_eq!(admin_addr, "0.0.0.0:8080".parse::<SocketAddr>().unwrap());
}
#[test]
fn clamp_bind_addrs_forces_loopback_when_unix_sockets_enabled() {
let cfg = NetworkProxySettings {
dangerously_allow_non_loopback_proxy: true,
dangerously_allow_non_loopback_admin: true,
allow_unix_sockets: vec!["/tmp/docker.sock".to_string()],
..Default::default()
};
let http_addr = "0.0.0.0:3128".parse::<SocketAddr>().unwrap();
let socks_addr = "0.0.0.0:8081".parse::<SocketAddr>().unwrap();
let admin_addr = "0.0.0.0:8080".parse::<SocketAddr>().unwrap();
let (http_addr, socks_addr, admin_addr) =
clamp_bind_addrs(http_addr, socks_addr, admin_addr, &cfg);
let (http_addr, socks_addr) = clamp_bind_addrs(http_addr, socks_addr, &cfg);
assert_eq!(http_addr, "127.0.0.1:3128".parse::<SocketAddr>().unwrap());
assert_eq!(socks_addr, "127.0.0.1:8081".parse::<SocketAddr>().unwrap());
assert_eq!(admin_addr, "127.0.0.1:8080".parse::<SocketAddr>().unwrap());
}
#[test]
fn clamp_bind_addrs_forces_loopback_when_all_unix_sockets_enabled() {
let cfg = NetworkProxySettings {
dangerously_allow_non_loopback_proxy: true,
dangerously_allow_non_loopback_admin: true,
dangerously_allow_all_unix_sockets: true,
..Default::default()
};
let http_addr = "0.0.0.0:3128".parse::<SocketAddr>().unwrap();
let socks_addr = "0.0.0.0:8081".parse::<SocketAddr>().unwrap();
let admin_addr = "0.0.0.0:8080".parse::<SocketAddr>().unwrap();
let (http_addr, socks_addr, admin_addr) =
clamp_bind_addrs(http_addr, socks_addr, admin_addr, &cfg);
let (http_addr, socks_addr) = clamp_bind_addrs(http_addr, socks_addr, &cfg);
assert_eq!(http_addr, "127.0.0.1:3128".parse::<SocketAddr>().unwrap());
assert_eq!(socks_addr, "127.0.0.1:8081".parse::<SocketAddr>().unwrap());
assert_eq!(admin_addr, "127.0.0.1:8080".parse::<SocketAddr>().unwrap());
}
#[test]

View File

@@ -1,6 +1,5 @@
#![deny(clippy::print_stdout, clippy::print_stderr)]
mod admin;
mod certs;
mod config;
mod http_proxy;

View File

@@ -1,4 +1,3 @@
use crate::admin;
use crate::config;
use crate::http_proxy;
use crate::network_policy::NetworkPolicyDecider;
@@ -26,15 +25,13 @@ pub struct Args {}
struct ReservedListeners {
http: Mutex<Option<StdTcpListener>>,
socks: Mutex<Option<StdTcpListener>>,
admin: Mutex<Option<StdTcpListener>>,
}
impl ReservedListeners {
fn new(http: StdTcpListener, socks: Option<StdTcpListener>, admin: StdTcpListener) -> Self {
fn new(http: StdTcpListener, socks: Option<StdTcpListener>) -> Self {
Self {
http: Mutex::new(Some(http)),
socks: Mutex::new(socks),
admin: Mutex::new(Some(admin)),
}
}
@@ -53,14 +50,6 @@ impl ReservedListeners {
.unwrap_or_else(std::sync::PoisonError::into_inner);
guard.take()
}
fn take_admin(&self) -> Option<StdTcpListener> {
let mut guard = self
.admin
.lock()
.unwrap_or_else(std::sync::PoisonError::into_inner);
guard.take()
}
}
#[derive(Clone)]
@@ -68,7 +57,6 @@ pub struct NetworkProxyBuilder {
state: Option<Arc<NetworkProxyState>>,
http_addr: Option<SocketAddr>,
socks_addr: Option<SocketAddr>,
admin_addr: Option<SocketAddr>,
managed_by_codex: bool,
policy_decider: Option<Arc<dyn NetworkPolicyDecider>>,
blocked_request_observer: Option<Arc<dyn BlockedRequestObserver>>,
@@ -80,7 +68,6 @@ impl Default for NetworkProxyBuilder {
state: None,
http_addr: None,
socks_addr: None,
admin_addr: None,
managed_by_codex: true,
policy_decider: None,
blocked_request_observer: None,
@@ -104,11 +91,6 @@ impl NetworkProxyBuilder {
self
}
pub fn admin_addr(mut self, addr: SocketAddr) -> Self {
self.admin_addr = Some(addr);
self
}
pub fn managed_by_codex(mut self, managed_by_codex: bool) -> Self {
self.managed_by_codex = managed_by_codex;
self
@@ -153,10 +135,10 @@ impl NetworkProxyBuilder {
.set_blocked_request_observer(self.blocked_request_observer.clone())
.await;
let current_cfg = state.current_cfg().await?;
let (requested_http_addr, requested_socks_addr, requested_admin_addr, reserved_listeners) =
let (requested_http_addr, requested_socks_addr, reserved_listeners) =
if self.managed_by_codex {
let runtime = config::resolve_runtime(&current_cfg)?;
let (http_listener, socks_listener, admin_listener) =
let (http_listener, socks_listener) =
reserve_loopback_ephemeral_listeners(current_cfg.network.enable_socks5)
.context("reserve managed loopback proxy listeners")?;
let http_addr = http_listener
@@ -169,17 +151,12 @@ impl NetworkProxyBuilder {
} else {
runtime.socks_addr
};
let admin_addr = admin_listener
.local_addr()
.context("failed to read reserved admin API address")?;
(
http_addr,
socks_addr,
admin_addr,
Some(Arc::new(ReservedListeners::new(
http_listener,
socks_listener,
admin_listener,
))),
)
} else {
@@ -187,16 +164,14 @@ impl NetworkProxyBuilder {
(
self.http_addr.unwrap_or(runtime.http_addr),
self.socks_addr.unwrap_or(runtime.socks_addr),
self.admin_addr.unwrap_or(runtime.admin_addr),
None,
)
};
// Reapply bind clamping for caller overrides so unix-socket proxying stays loopback-only.
let (http_addr, socks_addr, admin_addr) = config::clamp_bind_addrs(
let (http_addr, socks_addr) = config::clamp_bind_addrs(
requested_http_addr,
requested_socks_addr,
requested_admin_addr,
&current_cfg.network,
);
@@ -210,7 +185,6 @@ impl NetworkProxyBuilder {
dangerously_allow_all_unix_sockets: current_cfg
.network
.dangerously_allow_all_unix_sockets,
admin_addr,
reserved_listeners,
policy_decider: self.policy_decider,
})
@@ -219,7 +193,7 @@ impl NetworkProxyBuilder {
fn reserve_loopback_ephemeral_listeners(
reserve_socks_listener: bool,
) -> Result<(StdTcpListener, Option<StdTcpListener>, StdTcpListener)> {
) -> Result<(StdTcpListener, Option<StdTcpListener>)> {
let http_listener =
reserve_loopback_ephemeral_listener().context("reserve HTTP proxy listener")?;
let socks_listener = if reserve_socks_listener {
@@ -227,9 +201,7 @@ fn reserve_loopback_ephemeral_listeners(
} else {
None
};
let admin_listener =
reserve_loopback_ephemeral_listener().context("reserve admin API listener")?;
Ok((http_listener, socks_listener, admin_listener))
Ok((http_listener, socks_listener))
}
fn reserve_loopback_ephemeral_listener() -> Result<StdTcpListener> {
@@ -246,7 +218,6 @@ pub struct NetworkProxy {
allow_local_binding: bool,
allow_unix_sockets: Vec<String>,
dangerously_allow_all_unix_sockets: bool,
admin_addr: SocketAddr,
reserved_listeners: Option<Arc<ReservedListeners>>,
policy_decider: Option<Arc<dyn NetworkPolicyDecider>>,
}
@@ -258,7 +229,6 @@ impl std::fmt::Debug for NetworkProxy {
f.debug_struct("NetworkProxy")
.field("http_addr", &self.http_addr)
.field("socks_addr", &self.socks_addr)
.field("admin_addr", &self.admin_addr)
.finish_non_exhaustive()
}
}
@@ -268,7 +238,6 @@ impl PartialEq for NetworkProxy {
self.http_addr == other.http_addr
&& self.socks_addr == other.socks_addr
&& self.allow_local_binding == other.allow_local_binding
&& self.admin_addr == other.admin_addr
}
}
@@ -421,10 +390,6 @@ impl NetworkProxy {
self.socks_addr
}
pub fn admin_addr(&self) -> SocketAddr {
self.admin_addr
}
pub async fn add_allowed_domain(&self, host: &str) -> Result<()> {
self.state.add_allowed_domain(host).await
}
@@ -475,7 +440,6 @@ impl NetworkProxy {
let reserved_listeners = self.reserved_listeners.as_ref();
let http_listener = reserved_listeners.and_then(|listeners| listeners.take_http());
let socks_listener = reserved_listeners.and_then(|listeners| listeners.take_socks());
let admin_listener = reserved_listeners.and_then(|listeners| listeners.take_admin());
let http_state = self.state.clone();
let http_decider = self.policy_decider.clone();
@@ -520,21 +484,10 @@ impl NetworkProxy {
} else {
None
};
let admin_state = self.state.clone();
let admin_addr = self.admin_addr;
let admin_task = tokio::spawn(async move {
match admin_listener {
Some(listener) => {
admin::run_admin_api_with_std_listener(admin_state, listener).await
}
None => admin::run_admin_api(admin_state, admin_addr).await,
}
});
Ok(NetworkProxyHandle {
http_task: Some(http_task),
socks_task,
admin_task: Some(admin_task),
completed: false,
})
}
@@ -543,7 +496,6 @@ impl NetworkProxy {
pub struct NetworkProxyHandle {
http_task: Option<JoinHandle<Result<()>>>,
socks_task: Option<JoinHandle<Result<()>>>,
admin_task: Option<JoinHandle<Result<()>>>,
completed: bool,
}
@@ -552,24 +504,20 @@ impl NetworkProxyHandle {
Self {
http_task: Some(tokio::spawn(async { Ok(()) })),
socks_task: None,
admin_task: Some(tokio::spawn(async { Ok(()) })),
completed: true,
}
}
pub async fn wait(mut self) -> Result<()> {
let http_task = self.http_task.take().context("missing http proxy task")?;
let admin_task = self.admin_task.take().context("missing admin proxy task")?;
let socks_task = self.socks_task.take();
let http_result = http_task.await;
let admin_result = admin_task.await;
let socks_result = match socks_task {
Some(task) => Some(task.await),
None => None,
};
self.completed = true;
http_result??;
admin_result??;
if let Some(socks_result) = socks_result {
socks_result??;
}
@@ -577,12 +525,7 @@ impl NetworkProxyHandle {
}
pub async fn shutdown(mut self) -> Result<()> {
abort_tasks(
self.http_task.take(),
self.socks_task.take(),
self.admin_task.take(),
)
.await;
abort_tasks(self.http_task.take(), self.socks_task.take()).await;
self.completed = true;
Ok(())
}
@@ -598,11 +541,9 @@ async fn abort_task(task: Option<JoinHandle<Result<()>>>) {
async fn abort_tasks(
http_task: Option<JoinHandle<Result<()>>>,
socks_task: Option<JoinHandle<Result<()>>>,
admin_task: Option<JoinHandle<Result<()>>>,
) {
abort_task(http_task).await;
abort_task(socks_task).await;
abort_task(admin_task).await;
}
impl Drop for NetworkProxyHandle {
@@ -612,9 +553,8 @@ impl Drop for NetworkProxyHandle {
}
let http_task = self.http_task.take();
let socks_task = self.socks_task.take();
let admin_task = self.admin_task.take();
tokio::spawn(async move {
abort_tasks(http_task, socks_task, admin_task).await;
abort_tasks(http_task, socks_task).await;
});
}
}
@@ -648,10 +588,8 @@ mod tests {
assert!(proxy.http_addr.ip().is_loopback());
assert!(proxy.socks_addr.ip().is_loopback());
assert!(proxy.admin_addr.ip().is_loopback());
assert_ne!(proxy.http_addr.port(), 0);
assert_ne!(proxy.socks_addr.port(), 0);
assert_ne!(proxy.admin_addr.port(), 0);
}
#[tokio::test]
@@ -659,7 +597,6 @@ mod tests {
let settings = NetworkProxySettings {
proxy_url: "http://127.0.0.1:43128".to_string(),
socks_url: "http://127.0.0.1:48081".to_string(),
admin_url: "http://127.0.0.1:48080".to_string(),
..NetworkProxySettings::default()
};
let state = Arc::new(network_proxy_state_for_policy(settings));
@@ -678,10 +615,6 @@ mod tests {
proxy.socks_addr,
"127.0.0.1:48081".parse::<SocketAddr>().unwrap()
);
assert_eq!(
proxy.admin_addr,
"127.0.0.1:48080".parse::<SocketAddr>().unwrap()
);
}
#[tokio::test]
@@ -706,7 +639,6 @@ mod tests {
};
assert!(proxy.http_addr.ip().is_loopback());
assert!(proxy.admin_addr.ip().is_loopback());
assert_eq!(
proxy.socks_addr,
"127.0.0.1:43129".parse::<SocketAddr>().unwrap()

View File

@@ -1251,42 +1251,6 @@ mod tests {
assert!(validate_policy_against_constraints(&config, &constraints).is_err());
}
#[test]
fn validate_policy_against_constraints_disallows_non_loopback_admin_without_managed_opt_in() {
let constraints = NetworkProxyConstraints {
dangerously_allow_non_loopback_admin: Some(false),
..NetworkProxyConstraints::default()
};
let config = NetworkProxyConfig {
network: NetworkProxySettings {
enabled: true,
dangerously_allow_non_loopback_admin: true,
..NetworkProxySettings::default()
},
};
assert!(validate_policy_against_constraints(&config, &constraints).is_err());
}
#[test]
fn validate_policy_against_constraints_allows_non_loopback_admin_with_managed_opt_in() {
let constraints = NetworkProxyConstraints {
dangerously_allow_non_loopback_admin: Some(true),
..NetworkProxyConstraints::default()
};
let config = NetworkProxyConfig {
network: NetworkProxySettings {
enabled: true,
dangerously_allow_non_loopback_admin: true,
..NetworkProxySettings::default()
},
};
assert!(validate_policy_against_constraints(&config, &constraints).is_ok());
}
#[test]
fn validate_policy_against_constraints_disallows_allow_all_unix_sockets_without_managed_opt_in()
{

View File

@@ -21,7 +21,6 @@ pub struct NetworkProxyConstraints {
pub mode: Option<NetworkMode>,
pub allow_upstream_proxy: Option<bool>,
pub dangerously_allow_non_loopback_proxy: Option<bool>,
pub dangerously_allow_non_loopback_admin: Option<bool>,
pub dangerously_allow_all_unix_sockets: Option<bool>,
pub allowed_domains: Option<Vec<String>>,
pub denied_domains: Option<Vec<String>>,
@@ -41,7 +40,6 @@ pub struct PartialNetworkConfig {
pub mode: Option<NetworkMode>,
pub allow_upstream_proxy: Option<bool>,
pub dangerously_allow_non_loopback_proxy: Option<bool>,
pub dangerously_allow_non_loopback_admin: Option<bool>,
pub dangerously_allow_all_unix_sockets: Option<bool>,
#[serde(default)]
pub allowed_domains: Option<Vec<String>>,
@@ -149,25 +147,6 @@ pub fn validate_policy_against_constraints(
},
)?;
let allow_non_loopback_admin = constraints.dangerously_allow_non_loopback_admin;
validate(
config.network.dangerously_allow_non_loopback_admin,
move |candidate| match allow_non_loopback_admin {
Some(true) | None => Ok(()),
Some(false) => {
if *candidate {
Err(invalid_value(
"network.dangerously_allow_non_loopback_admin",
"true",
"false (disabled by managed config)",
))
} else {
Ok(())
}
}
},
)?;
let allow_non_loopback_proxy = constraints.dangerously_allow_non_loopback_proxy;
validate(
config.network.dangerously_allow_non_loopback_proxy,