From 8babffed760604675f6300636587f4eccdb3b2d4 Mon Sep 17 00:00:00 2001 From: Dreaded_X Date: Sat, 20 Jun 2026 02:42:53 +0200 Subject: [PATCH] fix: No root certificates in scratch container --- Cargo.lock | 6 ++++-- automation_devices/src/air_filter.rs | 10 ++++++---- automation_devices/src/hue_bridge.rs | 3 ++- automation_devices/src/hue_group.rs | 13 ++++--------- automation_devices/src/ntfy.rs | 3 ++- automation_lib/Cargo.toml | 2 ++ automation_lib/src/lib.rs | 1 + automation_lib/src/reqwest.rs | 23 +++++++++++++++++++++++ src/web.rs | 3 ++- 9 files changed, 46 insertions(+), 18 deletions(-) create mode 100644 automation_lib/src/reqwest.rs diff --git a/Cargo.lock b/Cargo.lock index 2707f33..613dee5 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -151,12 +151,14 @@ dependencies = [ "inventory", "lua_typed", "mlua", + "reqwest", "rumqttc", "serde", "serde_json", "thiserror", "tokio", "tracing", + "webpki-root-certs", ] [[package]] @@ -2878,9 +2880,9 @@ dependencies = [ [[package]] name = "webpki-root-certs" -version = "1.0.7" +version = "1.0.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f31141ce3fc3e300ae89b78c0dd67f9708061d1d2eda54b8209346fd6be9a92c" +checksum = "0d46a5a140e6f7afeccd8eae97eff335163939eac8b929834875168b29b3d267" dependencies = [ "rustls-pki-types", ] diff --git a/automation_devices/src/air_filter.rs b/automation_devices/src/air_filter.rs index 7528f61..0c7be1a 100644 --- a/automation_devices/src/air_filter.rs +++ b/automation_devices/src/air_filter.rs @@ -1,6 +1,7 @@ use async_trait::async_trait; use automation_lib::config::InfoConfig; use automation_lib::device::{Device, LuaDeviceCreate}; +use automation_lib::reqwest::new_client; use automation_macro::{Device, LuaDeviceConfig}; use google_home::device::Name; use google_home::errors::ErrorCode; @@ -52,20 +53,21 @@ impl AirFilter { async fn set_fan_speed(&self, speed: air_filter_types::FanSpeed) -> Result<(), Error> { let message = air_filter_types::SetFanSpeed::new(speed); let url = format!("{}/state/fan", self.config.url); - let client = reqwest::Client::new(); - client.put(url).json(&message).send().await?; + new_client().put(url).json(&message).send().await?; Ok(()) } async fn get_fan_state(&self) -> Result { let url = format!("{}/state/fan", self.config.url); - Ok(reqwest::get(url).await?.json().await?) + let client = new_client(); + Ok(client.get(url).send().await?.json().await?) } async fn get_sensor_data(&self) -> Result { let url = format!("{}/state/sensor", self.config.url); - Ok(reqwest::get(url).await?.json().await?) + let client = new_client(); + Ok(client.get(url).send().await?.json().await?) } } diff --git a/automation_devices/src/hue_bridge.rs b/automation_devices/src/hue_bridge.rs index 0c548c8..d55fbc8 100644 --- a/automation_devices/src/hue_bridge.rs +++ b/automation_devices/src/hue_bridge.rs @@ -4,6 +4,7 @@ use std::net::SocketAddr; use async_trait::async_trait; use automation_lib::device::{Device, LuaDeviceCreate}; use automation_lib::lua::traits::PartialUserData; +use automation_lib::reqwest::new_client; use automation_macro::{Device, LuaDeviceConfig}; use lua_typed::Typed; use mlua::LuaSerdeExt; @@ -98,7 +99,7 @@ impl HueBridge { ); trace!(?flag, flag_id, value, "Sending request to change flag"); - let res = reqwest::Client::new() + let res = new_client() .put(url) .json(&FlagMessage { flag: value }) .send() diff --git a/automation_devices/src/hue_group.rs b/automation_devices/src/hue_group.rs index ab10b00..61635c7 100644 --- a/automation_devices/src/hue_group.rs +++ b/automation_devices/src/hue_group.rs @@ -3,6 +3,7 @@ use std::net::SocketAddr; use anyhow::Result; use async_trait::async_trait; use automation_lib::lua::traits::PartialUserData; +use automation_lib::reqwest::new_client; use automation_macro::{Device, LuaDeviceConfig}; use google_home::errors::ErrorCode; use google_home::traits::OnOff; @@ -74,7 +75,7 @@ impl OnOff for HueGroup { message::Action::on(false) }; - let res = reqwest::Client::new() + let res = new_client() .put(self.url_set_action()) .json(&message) .send() @@ -94,10 +95,7 @@ impl OnOff for HueGroup { } async fn on(&self) -> Result { - let res = reqwest::Client::new() - .get(self.url_get_state()) - .send() - .await; + let res = new_client().get(self.url_get_state()).send().await; match res { Ok(res) => { @@ -128,10 +126,7 @@ struct AllOn; impl PartialUserData for AllOn { fn add_methods>(methods: &mut M) { methods.add_async_method("all_on", async |_lua, this, ()| { - let res = reqwest::Client::new() - .get(this.url_get_state()) - .send() - .await; + let res = new_client().get(this.url_get_state()).send().await; match res { Ok(res) => { diff --git a/automation_devices/src/ntfy.rs b/automation_devices/src/ntfy.rs index d41df47..ba79096 100644 --- a/automation_devices/src/ntfy.rs +++ b/automation_devices/src/ntfy.rs @@ -4,6 +4,7 @@ use std::convert::Infallible; use async_trait::async_trait; use automation_lib::device::{Device, LuaDeviceCreate}; use automation_lib::lua::traits::PartialUserData; +use automation_lib::reqwest::new_client; use automation_macro::{Device, LuaDeviceConfig}; use lua_typed::Typed; use mlua::LuaSerdeExt; @@ -143,7 +144,7 @@ impl Ntfy { let notification = notification.finalize(&self.config.topic); // Create the request - let res = reqwest::Client::new() + let res = new_client() .post(self.config.url.clone()) .json(¬ification) .send() diff --git a/automation_lib/Cargo.toml b/automation_lib/Cargo.toml index b05bee5..df88808 100644 --- a/automation_lib/Cargo.toml +++ b/automation_lib/Cargo.toml @@ -4,6 +4,7 @@ version = "0.1.0" edition = "2024" [dependencies] +reqwest = { workspace = true } automation_macro = { workspace = true } async-trait = { workspace = true } automation_cast = { workspace = true } @@ -21,3 +22,4 @@ serde_json = { workspace = true } thiserror = { workspace = true } tokio = { workspace = true } tracing = { workspace = true } +webpki-root-certs = "1.0.8" diff --git a/automation_lib/src/lib.rs b/automation_lib/src/lib.rs index a50fabd..01fb69c 100644 --- a/automation_lib/src/lib.rs +++ b/automation_lib/src/lib.rs @@ -13,6 +13,7 @@ pub mod helpers; pub mod lua; pub mod messages; pub mod mqtt; +pub mod reqwest; type RegisterFn = fn(lua: &mlua::Lua) -> mlua::Result; type DefinitionsFn = fn() -> String; diff --git a/automation_lib/src/reqwest.rs b/automation_lib/src/reqwest.rs new file mode 100644 index 0000000..7e1af26 --- /dev/null +++ b/automation_lib/src/reqwest.rs @@ -0,0 +1,23 @@ +use reqwest::{Certificate, Client}; + +pub fn new_client() -> Client { + println!( + "{}/{}", + std::env!("CARGO_PKG_NAME"), + std::env!("CARGO_PKG_VERSION") + ); + + Client::builder() + .user_agent(format!( + "{}/{}", + std::env!("CARGO_PKG_NAME"), + std::env!("CARGO_PKG_VERSION") + )) + .tls_certs_only( + webpki_root_certs::TLS_SERVER_ROOT_CERTS + .iter() + .map(|cert| Certificate::from_der(cert).unwrap()), + ) + .build() + .expect("Client should build") +} diff --git a/src/web.rs b/src/web.rs index 85cd2f5..40f5b35 100644 --- a/src/web.rs +++ b/src/web.rs @@ -1,5 +1,6 @@ use std::result; +use automation_lib::reqwest::new_client; use axum::extract::{FromRef, FromRequestParts}; use axum::http::StatusCode; use axum::http::request::Parts; @@ -93,7 +94,7 @@ where // TODO: Do some discovery to find the correct url for this instead of assuming // TODO: I think we can also just run Authlia in front of the endpoint instead // This would then give us a header containing the logged in user info? - let mut req = reqwest::Client::new().get(format!("{}/userinfo", openid_url)); + let mut req = new_client().get(format!("{}/userinfo", openid_url)); // Add auth header to the request if it exists if let Some(auth) = parts.headers.get(axum::http::header::AUTHORIZATION) {