diff --git a/Cargo.lock b/Cargo.lock index db8d25551..ff585c618 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -8077,6 +8077,7 @@ dependencies = [ "orb-endpoints", "orb-info", "orb-messages 0.0.0 (git+https://github.com/worldcoin/orb-messages?rev=af472fadb57ce55ac63f8f94bd2a0608e62405c7)", + "orb-security-utils", "orb-telemetry", "orb-update-agent-dbus", "portpicker", @@ -8324,6 +8325,7 @@ dependencies = [ "orb-dogd", "orb-info", "orb-secure-storage-ca", + "orb-security-utils", "orb-telemetry", "p256 0.13.2", "portpicker", @@ -8875,6 +8877,7 @@ dependencies = [ "orb-attest-dbus", "orb-build-info", "orb-info", + "orb-security-utils", "rand 0.8.5", "reqwest 0.12.24", "serde", diff --git a/attest/src/client.rs b/attest/src/client.rs index c85b514b2..a6f3ff3f4 100644 --- a/attest/src/client.rs +++ b/attest/src/client.rs @@ -25,7 +25,7 @@ pub enum Error { pub fn client() -> &'static Client { static CLIENT: OnceLock = OnceLock::new(); CLIENT.get_or_init(|| { - let builder = orb_security_utils::reqwest::http_client_builder() + let builder = orb_security_utils::reqwest::client_builder() .timeout(std::time::Duration::from_secs(60)) .user_agent(USER_AGENT); #[cfg(test)] diff --git a/clippy.toml b/clippy.toml new file mode 100644 index 000000000..977c911aa --- /dev/null +++ b/clippy.toml @@ -0,0 +1,6 @@ +disallowed-methods = [ + { path = "reqwest::Client::builder", reason = "use orb_security_utils::reqwest::client_builder() instead" }, + { path = "reqwest::Client::new", reason = "use orb_security_utils::reqwest::client_builder().build() instead" }, + { path = "reqwest::blocking::Client::builder", allow-invalid = true, reason = "use orb_security_utils::reqwest::blocking::client_builder() instead" }, + { path = "reqwest::blocking::Client::new", allow-invalid = true, reason = "use orb_security_utils::reqwest::blocking::client_builder().build() instead" }, +] diff --git a/experiments/artificer/src/downloader/mod.rs b/experiments/artificer/src/downloader/mod.rs index 6b257b3fc..625836425 100644 --- a/experiments/artificer/src/downloader/mod.rs +++ b/experiments/artificer/src/downloader/mod.rs @@ -1,4 +1,5 @@ //! Download functionality for various sources of artifacts. +#![allow(clippy::disallowed_methods)] use color_eyre::{eyre::WrapErr, Result}; use octocrab::Octocrab; diff --git a/experiments/orb-blob/blob-cli/src/main.rs b/experiments/orb-blob/blob-cli/src/main.rs index 33d61ca2f..3f4c2e377 100644 --- a/experiments/orb-blob/blob-cli/src/main.rs +++ b/experiments/orb-blob/blob-cli/src/main.rs @@ -1,3 +1,5 @@ +// Allow regular reqwest builder without HTTPS enforsement +#![allow(clippy::disallowed_methods)] mod http_handler; use color_eyre::eyre::{Context, Result}; use http_handler::{download, info, upload}; diff --git a/experiments/orb-blob/p2p/src/bootstrap.rs b/experiments/orb-blob/p2p/src/bootstrap.rs index 02e9f6f46..17488a8b4 100644 --- a/experiments/orb-blob/p2p/src/bootstrap.rs +++ b/experiments/orb-blob/p2p/src/bootstrap.rs @@ -1,3 +1,5 @@ +// Allow regular reqwest builder without HTTPS enforsement +#![allow(clippy::disallowed_methods)] use std::collections::BTreeSet; use std::time::Duration; diff --git a/experiments/orb-blob/tests/blob_create.rs b/experiments/orb-blob/tests/blob_create.rs index ea9d2f8a8..57b95d03e 100644 --- a/experiments/orb-blob/tests/blob_create.rs +++ b/experiments/orb-blob/tests/blob_create.rs @@ -1,3 +1,5 @@ +// Allow regular reqwest builder without HTTPS enforsement +#![allow(clippy::disallowed_methods)] use async_tempfile::TempFile; use fixture::Fixture; use iroh_blobs::{store::fs::FsStore, Hash}; diff --git a/experiments/orb-blob/tests/blob_delete.rs b/experiments/orb-blob/tests/blob_delete.rs index 0bd4f6e70..11b5e4e3a 100644 --- a/experiments/orb-blob/tests/blob_delete.rs +++ b/experiments/orb-blob/tests/blob_delete.rs @@ -1,3 +1,4 @@ +#![allow(clippy::disallowed_methods)] use async_tempfile::TempFile; use fixture::Fixture; use iroh_blobs::{ diff --git a/experiments/orb-blob/tests/e2e_node_share.rs b/experiments/orb-blob/tests/e2e_node_share.rs index cbde6e262..ad58de13b 100644 --- a/experiments/orb-blob/tests/e2e_node_share.rs +++ b/experiments/orb-blob/tests/e2e_node_share.rs @@ -1,3 +1,5 @@ +// Allow regular reqwest builder without HTTPS enforsement +#![allow(clippy::disallowed_methods)] use async_tempfile::TempFile; use fixture::Fixture; use iroh::{NodeAddr, SecretKey}; diff --git a/orb-backend-status/Cargo.toml b/orb-backend-status/Cargo.toml index c4b55ecea..c282e1c6d 100644 --- a/orb-backend-status/Cargo.toml +++ b/orb-backend-status/Cargo.toml @@ -32,6 +32,7 @@ orb-info = { workspace = true, features = [ "orb-token", ] } orb-dogd.workspace = true +orb-security-utils = { workspace = true, features = ["reqwest"] } orb-telemetry = { workspace = true, features = ["otel", "zbus-tracing"] } orb-update-agent-dbus.workspace = true reqwest = { workspace = true, features = ["json"] } @@ -57,6 +58,7 @@ zbus = { workspace = true, default-features = false, features = ["tokio"] } zenorb.workspace = true [dev-dependencies] +orb-security-utils = { workspace = true, features = ["reqwest", "allow-http"] } dbus-launch.workspace = true eyre.workspace = true portpicker = "0.1.1" diff --git a/orb-backend-status/src/backend/client.rs b/orb-backend-status/src/backend/client.rs index fcbdf517f..1034b9d62 100644 --- a/orb-backend-status/src/backend/client.rs +++ b/orb-backend-status/src/backend/client.rs @@ -71,7 +71,7 @@ impl StatusClient { .retry_bounds(min_req_retry_interval, max_req_retry_interval) .build_with_max_retries(3); - let reqwest_client = reqwest::Client::builder() + let reqwest_client = orb_security_utils::reqwest::client_builder() .timeout(req_timeout) .user_agent("orb-backend-status") .build() diff --git a/orb-connd/Cargo.toml b/orb-connd/Cargo.toml index 22b6cd33e..fe3f90c34 100644 --- a/orb-connd/Cargo.toml +++ b/orb-connd/Cargo.toml @@ -31,6 +31,7 @@ num-traits.workspace = true oes.workspace = true orb-backend-status-dbus.workspace = true orb-build-info.workspace = true +orb-security-utils = { workspace = true, features = ["reqwest"] } orb-connd-dbus.workspace = true orb-dogd.workspace = true orb-info = { workspace = true, features = ["orb-os-release", "async"] } diff --git a/orb-connd/nm_cfg/20-defaults.conf b/orb-connd/nm_cfg/20-defaults.conf index c6e0d61c3..1836bc7b1 100644 --- a/orb-connd/nm_cfg/20-defaults.conf +++ b/orb-connd/nm_cfg/20-defaults.conf @@ -21,6 +21,6 @@ ipv6.route-metric=500 [connectivity] enabled=true -uri=http://connectivity-check.worldcoin.org +uri=https://connectivity-check.worldcoin.org interval=300 response= diff --git a/orb-connd/src/conn_http_check.rs b/orb-connd/src/conn_http_check.rs index 7aa1f59dd..7dbec3b5e 100644 --- a/orb-connd/src/conn_http_check.rs +++ b/orb-connd/src/conn_http_check.rs @@ -17,9 +17,9 @@ impl ConnHttpCheck { /// iface will default to default route if `None` is passed as arg pub async fn run(connectivity_uri: &str, iface: Option<&str>) -> Result { let client = if let Some(iface) = iface { - reqwest::Client::builder().interface(iface) + orb_security_utils::reqwest::client_builder().interface(iface) } else { - reqwest::Client::builder() + orb_security_utils::reqwest::client_builder() } .timeout(Duration::from_secs(5)) .build()?; diff --git a/se050-reprovision/src/remote_api.rs b/se050-reprovision/src/remote_api.rs index e591a1a90..139020436 100644 --- a/se050-reprovision/src/remote_api.rs +++ b/se050-reprovision/src/remote_api.rs @@ -41,7 +41,7 @@ where } pub fn default_reqwest_client(self) -> Result>> { - let client = orb_security_utils::reqwest::http_client_builder() + let client = orb_security_utils::reqwest::client_builder() .user_agent(USER_AGENT) .build() .wrap_err("failed to create http client")?; diff --git a/se050-reprovision/tests/harness.rs b/se050-reprovision/tests/harness.rs index 2553f1d00..614a6b444 100644 --- a/se050-reprovision/tests/harness.rs +++ b/se050-reprovision/tests/harness.rs @@ -15,6 +15,8 @@ pub struct Harness { } impl HarnessBuilder { + // local_backend uses http://localhost — plain reqwest client is intentional here. + #[allow(clippy::disallowed_methods)] pub fn build(self) -> (Harness, orb_se050_reprovision::Config) where S: hb::IsComplete, diff --git a/security-utils/Cargo.toml b/security-utils/Cargo.toml index 5c1ac98ac..a906d4b14 100644 --- a/security-utils/Cargo.toml +++ b/security-utils/Cargo.toml @@ -13,6 +13,9 @@ rust-version.workspace = true [features] blocking = ["reqwest/blocking"] reqwest = ["dep:reqwest"] +# Disables https_only enforcement. Only intended for use in dev-dependencies +# of crates that spin up local HTTP test servers. +allow-http = [] [dependencies] eyre = "0.6" diff --git a/security-utils/src/reqwest.rs b/security-utils/src/reqwest.rs index 9d613376a..43f5a63ae 100644 --- a/security-utils/src/reqwest.rs +++ b/security-utils/src/reqwest.rs @@ -151,9 +151,9 @@ macro_rules! helper { ($builder:expr, $certs:expr) => {{ let certs = $certs; $builder - .min_tls_version(reqwest::tls::Version::TLS_1_2) + .min_tls_version(reqwest::tls::Version::TLS_1_3) .tls_built_in_root_certs(false) - .https_only(true) + .https_only(!cfg!(feature = "allow-http")) .add_root_certificate(certs.aws_root_ca1.clone()) .add_root_certificate(certs.aws_root_ca2.clone()) .add_root_certificate(certs.aws_root_ca3.clone()) @@ -167,7 +167,8 @@ macro_rules! helper { }}; } -pub fn http_client_builder() -> ClientBuilder { +#[allow(clippy::disallowed_methods)] +pub fn client_builder() -> ClientBuilder { let certs = get_certs(); helper!(Client::builder(), certs) } @@ -178,7 +179,8 @@ pub mod blocking { use super::get_certs; - pub fn http_client_builder() -> ClientBuilder { + #[allow(clippy::disallowed_methods)] + pub fn client_builder() -> ClientBuilder { let certs = get_certs(); helper!(Client::builder(), certs) } diff --git a/speed-test/Cargo.toml b/speed-test/Cargo.toml index 90b00ec09..c9b019d77 100644 --- a/speed-test/Cargo.toml +++ b/speed-test/Cargo.toml @@ -25,6 +25,7 @@ color-eyre.workspace = true flate2.workspace = true orb-attest-dbus.path = "../attest/dbus" orb-build-info.workspace = true +orb-security-utils = { workspace = true, features = ["reqwest"] } orb-info.path = "../orb-info" rand.workspace = true reqwest = { workspace = true, features = ["multipart", "stream", "json"] } diff --git a/speed-test/src/lib.rs b/speed-test/src/lib.rs index a0f1f7fc8..9dbdf3aaa 100644 --- a/speed-test/src/lib.rs +++ b/speed-test/src/lib.rs @@ -94,7 +94,9 @@ struct PackageRequest<'a> { pub async fn run_speed_test(test_size_bytes: usize) -> Result { let timeout = Duration::from_secs(CLOUDFLARE_TIMEOUT_SECS); - let client = reqwest::Client::builder().timeout(timeout).build()?; + let client = orb_security_utils::reqwest::client_builder() + .timeout(timeout) + .build()?; let upload_result = probe_upload(&client, test_size_bytes, timeout).await?; let download_result = probe_download(&client, test_size_bytes, timeout).await?; @@ -333,7 +335,7 @@ async fn request_presigned_url( id_commitment: "mock_id_commitment", }; - let client = reqwest::Client::builder() + let client = orb_security_utils::reqwest::client_builder() .timeout(Duration::from_secs(PCP_TIMEOUT_SECS)) .build()?; @@ -380,7 +382,7 @@ async fn upload_to_presigned_url( form = form.part("file", file_part); - let client = reqwest::Client::builder() + let client = orb_security_utils::reqwest::client_builder() .timeout(Duration::from_secs(PCP_TIMEOUT_SECS)) .build()?; diff --git a/update-agent-loader/src/download.rs b/update-agent-loader/src/download.rs index 963ba7dd7..32fdd8062 100644 --- a/update-agent-loader/src/download.rs +++ b/update-agent-loader/src/download.rs @@ -74,6 +74,8 @@ pub fn download( } /// Creates an HTTP client with security settings similar to the update-agent +// update-agent-loader intentionally uses system certs rather than pinned CAs. +#[allow(clippy::disallowed_methods)] fn create_client() -> Result { // Compile-time assertion to ensure allow_http feature isn't enabled in release mode #[cfg(all(feature = "allow_http", not(debug_assertions)))] @@ -81,6 +83,8 @@ fn create_client() -> Result { let builder = Client::builder() .tls_built_in_root_certs(true) + .min_tls_version(reqwest::tls::Version::TLS_1_3) + .redirect(reqwest::redirect::Policy::none()) .user_agent(concat!( env!("CARGO_PKG_NAME"), "/", diff --git a/update-agent/src/client.rs b/update-agent/src/client.rs index 78f48b3ba..2fd2aa070 100644 --- a/update-agent/src/client.rs +++ b/update-agent/src/client.rs @@ -20,6 +20,8 @@ pub fn normal() -> Result<&'static Client, Error> { INSTANCE.get_or_try_init(initialize) } +// update-agent intentionally uses system certs rather than pinned CAs — see comment below. +#[allow(clippy::disallowed_methods)] fn initialize() -> Result { // We explicitly do not pin certificates and default to using the system's // root CAs in the update-agent.