TLS guardrails (insecure http refusal, custom CAs) and deployment guide

This commit is contained in:
George Coles
2026-09-15 07:10:32 -04:00
parent ec98275613
commit 67112c2af3
12 changed files with 349 additions and 8 deletions
+55 -3
View File
@@ -31,6 +31,8 @@ pub struct RelayOptions {
pub url: Option<String>,
pub registry: Option<String>,
pub ma_key: Option<String>,
pub ca_cert: Option<String>,
pub allow_insecure: bool,
pub max_hops: usize,
}
@@ -42,6 +44,8 @@ impl Default for RelayOptions {
url: None,
registry: None,
ma_key: None,
ca_cert: None,
allow_insecure: false,
max_hops: 3,
}
}
@@ -84,6 +88,23 @@ impl Relay {
if !options.peers.is_empty() && options.url.is_none() {
return Err(anyhow!("--url is required when --peer is set"));
}
if !options.allow_insecure {
let mut urls = options.peers.clone();
if let Some(registry) = &options.registry {
urls.push(registry.clone());
}
let insecure = crate::net::insecure_http_urls(urls);
if !insecure.is_empty() {
return Err(anyhow!(
"refusing plain http endpoints (use https, configure --ca-cert, or set --allow-insecure for private networks): {}",
insecure.join(", ")
));
}
}
let client = crate::net::build_client(
options.ca_cert.as_deref().map(std::path::Path::new),
Duration::from_secs(5),
)?;
let relay = Arc::new(Self {
inner: Mutex::new(Inner {
members: HashMap::new(),
@@ -93,9 +114,7 @@ impl Relay {
}),
options,
registry,
client: reqwest::Client::builder()
.timeout(Duration::from_secs(5))
.build()?,
client,
notify: Notify::new(),
});
if let Some(watcher) = &relay.registry {
@@ -520,3 +539,36 @@ fn backpressure(status: StatusCode, missed: u64) -> Response {
)
.into_response()
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn refuses_plain_http_peers_off_loopback() {
let options = RelayOptions {
peers: vec!["http://10.0.0.1:7700".to_string()],
url: Some("http://10.0.0.1:7700".to_string()),
..Default::default()
};
assert!(Relay::new(options).is_err());
let options = RelayOptions {
peers: vec!["http://10.0.0.1:7700".to_string()],
url: Some("http://10.0.0.1:7700".to_string()),
allow_insecure: true,
..Default::default()
};
assert!(Relay::new(options).is_ok());
}
#[test]
fn loopback_peers_need_no_opt_in() {
let options = RelayOptions {
peers: vec!["http://127.0.0.1:7701".to_string()],
url: Some("http://127.0.0.1:7700".to_string()),
..Default::default()
};
assert!(Relay::new(options).is_ok());
}
}