diff --git a/Cargo.toml b/Cargo.toml index 92331280..804cba6c 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -15,6 +15,7 @@ rumqttc = "0.23.0" serde = { version = "1.0.196", features = ["derive"] } serde_derive = "1.0.196" toml = "0.8.10" +rustls-native-certs = "0.7.0" [package.metadata.cargo-machete] ignored = ["serde"] \ No newline at end of file diff --git a/hms2mqtt/src/mqtt_config.rs b/hms2mqtt/src/mqtt_config.rs index 47f61ee6..5eccc097 100644 --- a/hms2mqtt/src/mqtt_config.rs +++ b/hms2mqtt/src/mqtt_config.rs @@ -6,4 +6,5 @@ pub struct MqttConfig { pub port: Option, pub username: Option, pub password: Option, + pub tls: Option, } diff --git a/src/bin/hms-mqtt-publish/rumqttc_wrapper.rs b/src/bin/hms-mqtt-publish/rumqttc_wrapper.rs index ea0df3f4..234448b6 100644 --- a/src/bin/hms-mqtt-publish/rumqttc_wrapper.rs +++ b/src/bin/hms-mqtt-publish/rumqttc_wrapper.rs @@ -5,7 +5,12 @@ use hms2mqtt::{ mqtt_wrapper::{self}, }; use log::warn; -use rumqttc::{Client, MqttOptions, QoS::AtMostOnce}; +use rumqttc::{ + tokio_rustls::{self, rustls::ClientConfig}, + Client, MqttOptions, + QoS::AtMostOnce, + Transport, +}; pub struct RumqttcWrapper { client: Client, @@ -58,12 +63,37 @@ impl mqtt_wrapper::MqttWrapper for RumqttcWrapper { } fn new(config: &MqttConfig, suffix: &str) -> Self { + let use_tls = config.tls.is_some_and(|tls| tls); + let mut mqttoptions = MqttOptions::new( "hms800wt2-mqtt-publisher".to_string() + suffix, &config.host, - config.port.unwrap_or(1883), + config.port.unwrap_or_else(|| { + if use_tls { + return 8883; + } + 1883 + }), ); mqttoptions.set_keep_alive(Duration::from_secs(5)); + if use_tls { + // Use rustls-native-certs to load root certificates from the operating system. + let mut roots = tokio_rustls::rustls::RootCertStore::empty(); + for cert in + rustls_native_certs::load_native_certs().expect("could not load platform certs") + { + roots + .add(&tokio_rustls::rustls::Certificate(cert.to_vec())) + .unwrap(); + } + + let client_config = ClientConfig::builder() + .with_safe_defaults() + .with_root_certificates(roots) + .with_no_client_auth(); + + mqttoptions.set_transport(Transport::tls_with_config(client_config.into())); + } //parse the mqtt authentication options if let Some((username, password)) = match (&config.username, &config.password) { diff --git a/tests/integration_tests.rs b/tests/integration_tests.rs index 2fd3fa3e..49983938 100644 --- a/tests/integration_tests.rs +++ b/tests/integration_tests.rs @@ -50,6 +50,7 @@ fn publish_one_message() { port: Some(1234), username: None, password: None, + tls: None, }, "-test", );