From dc57e6fe51023b915638a56225ce14609a1985e6 Mon Sep 17 00:00:00 2001 From: Orne Brocaar Date: Tue, 23 Jul 2024 13:56:21 +0100 Subject: [PATCH] Update rustls to 0.23. --- Cargo.lock | 153 +++++++++++++--------- chirpstack/Cargo.toml | 13 +- chirpstack/src/gateway/backend/mqtt.rs | 2 +- chirpstack/src/helpers/mod.rs | 1 + chirpstack/src/helpers/tls.rs | 34 ----- chirpstack/src/helpers/tls22.rs | 88 +++++++++++++ chirpstack/src/integration/gcp_pub_sub.rs | 11 +- chirpstack/src/integration/mqtt.rs | 2 +- 8 files changed, 197 insertions(+), 107 deletions(-) create mode 100644 chirpstack/src/helpers/tls22.rs diff --git a/Cargo.lock b/Cargo.lock index 41172e39..4b9ee677 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -680,7 +680,7 @@ dependencies = [ "rustc-hash", "shlex", "syn 2.0.58", - "which 4.4.2", + "which", ] [[package]] @@ -854,7 +854,7 @@ dependencies = [ "rsa", "rumqttc", "rust-embed", - "rustls 0.22.3", + "rustls 0.23.7", "rustls-native-certs 0.7.0", "rustls-pemfile 2.1.2", "serde", @@ -1816,18 +1816,21 @@ dependencies = [ [[package]] name = "gcp_auth" -version = "0.11.1" +version = "0.12.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e155fdc0640589cc660d00e7ed7aa608479e20187b9ea352a77dd4443dd2d856" +checksum = "536c79e79dde296a800738474691e97031769bed9b54e6dd0401b169d35d693d" dependencies = [ "async-trait", "base64 0.22.0", + "bytes", "chrono", "home", - "hyper 0.14.28", - "hyper-rustls 0.25.0", + "http 1.1.0", + "http-body-util", + "hyper 1.4.1", + "hyper-rustls 0.27.2", + "hyper-util", "ring", - "rustls 0.22.3", "rustls-pemfile 2.1.2", "serde", "serde_json", @@ -1836,7 +1839,6 @@ dependencies = [ "tracing", "tracing-futures", "url", - "which 6.0.1", ] [[package]] @@ -1938,6 +1940,25 @@ dependencies = [ "tracing", ] +[[package]] +name = "h2" +version = "0.4.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fa82e28a107a8cc405f0839610bdc9b15f1e25ec7d696aa5cf173edbcb1486ab" +dependencies = [ + "atomic-waker", + "bytes", + "fnv", + "futures-core", + "futures-sink", + "http 1.1.0", + "indexmap 2.2.6", + "slab", + "tokio", + "tokio-util", + "tracing", +] + [[package]] name = "handlebars" version = "6.0.0" @@ -2167,7 +2188,7 @@ dependencies = [ "futures-channel", "futures-core", "futures-util", - "h2", + "h2 0.3.26", "http 0.2.12", "http-body 0.4.6", "httparse", @@ -2183,13 +2204,14 @@ dependencies = [ [[package]] name = "hyper" -version = "1.2.0" +version = "1.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "186548d73ac615b32a73aafe38fb4f56c0d340e110e5a200bcadbaf2e199263a" +checksum = "50dfd22e0e76d0f662d429a5f80fcaf3855009297eab6a0a9f8543834744ba05" dependencies = [ "bytes", "futures-channel", "futures-util", + "h2 0.4.5", "http 1.1.0", "http-body 1.0.0", "httparse", @@ -2200,22 +2222,6 @@ dependencies = [ "want", ] -[[package]] -name = "hyper-rustls" -version = "0.25.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "399c78f9338483cb7e630c8474b07268983c6bd5acee012e4211f9f7bb21b070" -dependencies = [ - "futures-util", - "http 0.2.12", - "hyper 0.14.28", - "rustls 0.22.3", - "rustls-native-certs 0.7.0", - "rustls-pki-types", - "tokio", - "tokio-rustls", -] - [[package]] name = "hyper-rustls" version = "0.26.0" @@ -2224,12 +2230,30 @@ checksum = "a0bea761b46ae2b24eb4aef630d8d1c398157b6fc29e6350ecf090a0b70c952c" dependencies = [ "futures-util", "http 1.1.0", - "hyper 1.2.0", + "hyper 1.4.1", "hyper-util", "rustls 0.22.3", "rustls-pki-types", "tokio", - "tokio-rustls", + "tokio-rustls 0.25.0", + "tower-service", +] + +[[package]] +name = "hyper-rustls" +version = "0.27.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5ee4be2c948921a1a5320b629c4193916ed787a7f7f293fd3f7f5a6c9de74155" +dependencies = [ + "futures-util", + "http 1.1.0", + "hyper 1.4.1", + "hyper-util", + "rustls 0.23.7", + "rustls-native-certs 0.7.0", + "rustls-pki-types", + "tokio", + "tokio-rustls 0.26.0", "tower-service", ] @@ -2247,16 +2271,16 @@ dependencies = [ [[package]] name = "hyper-util" -version = "0.1.3" +version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ca38ef113da30126bbff9cd1705f9273e15d45498615d138b0c20279ac7a76aa" +checksum = "3ab92f4f49ee4fb4f997c784b7a2e0fa70050211e0b6a287f898c3c9785ca956" dependencies = [ "bytes", "futures-channel", "futures-util", "http 1.1.0", "http-body 1.0.0", - "hyper 1.2.0", + "hyper 1.4.1", "pin-project-lite", "socket2 0.5.6", "tokio", @@ -3566,7 +3590,7 @@ dependencies = [ "sha1_smol", "socket2 0.5.6", "tokio", - "tokio-rustls", + "tokio-rustls 0.25.0", "tokio-util", "url", ] @@ -3639,7 +3663,7 @@ dependencies = [ "http 1.1.0", "http-body 1.0.0", "http-body-util", - "hyper 1.2.0", + "hyper 1.4.1", "hyper-rustls 0.26.0", "hyper-util", "ipnet", @@ -3658,7 +3682,7 @@ dependencies = [ "serde_urlencoded", "sync_wrapper", "tokio", - "tokio-rustls", + "tokio-rustls 0.25.0", "tower-service", "url", "wasm-bindgen", @@ -3777,7 +3801,7 @@ dependencies = [ "rustls-webpki 0.102.2", "thiserror", "tokio", - "tokio-rustls", + "tokio-rustls 0.25.0", "url", ] @@ -3898,6 +3922,21 @@ dependencies = [ "zeroize", ] +[[package]] +name = "rustls" +version = "0.23.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ebbbdb961df0ad3f2652da8f3fdc4b36122f568f968f45ad3316f26c025c677b" +dependencies = [ + "log", + "once_cell", + "ring", + "rustls-pki-types", + "rustls-webpki 0.102.2", + "subtle", + "zeroize", +] + [[package]] name = "rustls-connector" version = "0.18.5" @@ -4652,16 +4691,15 @@ dependencies = [ [[package]] name = "tokio-postgres-rustls" -version = "0.11.1" +version = "0.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0ea13f22eda7127c827983bdaf0d7fff9df21c8817bab02815ac277a21143677" +checksum = "04fb792ccd6bbcd4bba408eb8a292f70fc4a3589e5d793626f45190e6454b6ab" dependencies = [ - "futures", "ring", - "rustls 0.22.3", + "rustls 0.23.7", "tokio", "tokio-postgres", - "tokio-rustls", + "tokio-rustls 0.26.0", "x509-certificate", ] @@ -4690,6 +4728,17 @@ dependencies = [ "tokio", ] +[[package]] +name = "tokio-rustls" +version = "0.26.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0c7bc40d0e5a97695bb96e27995cd3a08538541b0a846f65bba7a359f36700d4" +dependencies = [ + "rustls 0.23.7", + "rustls-pki-types", + "tokio", +] + [[package]] name = "tokio-stream" version = "0.1.15" @@ -4771,7 +4820,7 @@ dependencies = [ "axum", "base64 0.21.7", "bytes", - "h2", + "h2 0.3.26", "http 0.2.12", "http-body 0.4.6", "hyper 0.14.28", @@ -5139,7 +5188,7 @@ dependencies = [ "serde_json", "serde_urlencoded", "tokio", - "tokio-rustls", + "tokio-rustls 0.25.0", "tokio-util", "tower-service", "tracing", @@ -5254,18 +5303,6 @@ dependencies = [ "rustix 0.38.32", ] -[[package]] -name = "which" -version = "6.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8211e4f58a2b2805adfbefbc07bab82958fc91e3836339b1ab7ae32465dce0d7" -dependencies = [ - "either", - "home", - "rustix 0.38.32", - "winsafe", -] - [[package]] name = "whoami" version = "1.5.1" @@ -5477,12 +5514,6 @@ dependencies = [ "windows-sys 0.48.0", ] -[[package]] -name = "winsafe" -version = "0.0.19" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d135d17ab770252ad95e9a872d365cf3090e3be864a34ab46f48555993efc904" - [[package]] name = "x509-certificate" version = "0.23.1" diff --git a/chirpstack/Cargo.toml b/chirpstack/Cargo.toml index 78fcfa7f..cd5a641e 100644 --- a/chirpstack/Cargo.toml +++ b/chirpstack/Cargo.toml @@ -39,9 +39,9 @@ "async-connection-wrapper", ] } tokio-postgres = "0.7" - tokio-postgres-rustls = "0.11" + tokio-postgres-rustls = "0.12" bigdecimal = "0.4" - redis = { version = "0.25.2", features = ["tls-rustls", "tokio-rustls-comp"] } + redis = { version = "0.25", features = ["tls-rustls", "tokio-rustls-comp"] } deadpool-redis = { version = "0.15", features = ["cluster"] } # Logging @@ -78,7 +78,7 @@ sha2 = "0.10" urlencoding = "2.1" geohash = "0.13" - gcp_auth = "0.11" + gcp_auth = "0.12" lapin = "2.3" tokio-executor-trait = "2.1" tokio-reactor-trait = "1.1" @@ -117,7 +117,12 @@ pbkdf2 = { version = "0.12", features = ["simple"] } rand_core = { version = "0.6", features = ["std"] } jsonwebtoken = "9.2" - rustls = "0.22" + rustls = { version = "0.23", default-features = false, features = [ + "logging", + "std", + "tls12", + "ring", + ] } rustls-native-certs = "0.7" rustls-pemfile = "2.1" pem = "3.0" diff --git a/chirpstack/src/gateway/backend/mqtt.rs b/chirpstack/src/gateway/backend/mqtt.rs index b217d9d0..a3b964ef 100644 --- a/chirpstack/src/gateway/backend/mqtt.rs +++ b/chirpstack/src/gateway/backend/mqtt.rs @@ -23,7 +23,7 @@ use tracing::{error, info, trace}; use super::GatewayBackend; use crate::config::GatewayBackendMqtt; -use crate::helpers::tls::{get_root_certs, load_cert, load_key}; +use crate::helpers::tls22::{get_root_certs, load_cert, load_key}; use crate::monitoring::prometheus; use crate::{downlink, uplink}; use lrwn::region::CommonName; diff --git a/chirpstack/src/helpers/mod.rs b/chirpstack/src/helpers/mod.rs index d51b29b0..bcbb3d63 100644 --- a/chirpstack/src/helpers/mod.rs +++ b/chirpstack/src/helpers/mod.rs @@ -1,2 +1,3 @@ pub mod errors; pub mod tls; +pub mod tls22; // rustls 0.22 diff --git a/chirpstack/src/helpers/tls.rs b/chirpstack/src/helpers/tls.rs index e8e17c4a..e92a1415 100644 --- a/chirpstack/src/helpers/tls.rs +++ b/chirpstack/src/helpers/tls.rs @@ -2,8 +2,6 @@ use std::fs::File; use std::io::BufReader; use anyhow::{Context, Result}; -use rustls::pki_types::{CertificateDer, PrivateKeyDer}; -use tokio::fs; // Return root certificates, optionally with the provided ca_file appended. pub fn get_root_certs(ca_file: Option) -> Result { @@ -24,38 +22,6 @@ pub fn get_root_certs(ca_file: Option) -> Result Ok(roots) } -pub async fn load_cert(cert_file: &str) -> Result>> { - let cert_s = fs::read_to_string(cert_file) - .await - .context("Read TLS certificate")?; - let mut cert_b = cert_s.as_bytes(); - let certs = rustls_pemfile::certs(&mut cert_b); - let mut out = Vec::new(); - for cert in certs { - out.push(cert?.into_owned()); - } - Ok(out) -} - -pub async fn load_key(key_file: &str) -> Result> { - let key_s = fs::read_to_string(key_file) - .await - .context("Read private key")?; - let key_s = private_key_to_pkcs8(&key_s)?; - let mut key_b = key_s.as_bytes(); - let mut keys = rustls_pemfile::pkcs8_private_keys(&mut key_b); - if let Some(key) = keys.next() { - match key { - Ok(v) => return Ok(PrivateKeyDer::Pkcs8(v.clone_key())), - Err(e) => { - return Err(anyhow!("Error parsing private key, error: {}", e)); - } - } - } - - Err(anyhow!("No private key found")) -} - pub fn private_key_to_pkcs8(pem: &str) -> Result { if pem.contains("RSA PRIVATE KEY") { use rsa::{ diff --git a/chirpstack/src/helpers/tls22.rs b/chirpstack/src/helpers/tls22.rs new file mode 100644 index 00000000..be42a2e6 --- /dev/null +++ b/chirpstack/src/helpers/tls22.rs @@ -0,0 +1,88 @@ +use std::fs::File; +use std::io::BufReader; + +use anyhow::{Context, Result}; +use rumqttc::tokio_rustls::rustls::{ + self, + pki_types::{CertificateDer, PrivateKeyDer}, +}; +use tokio::fs; + +// Return root certificates, optionally with the provided ca_file appended. +pub fn get_root_certs(ca_file: Option) -> Result { + let mut roots = rustls::RootCertStore::empty(); + for cert in rustls_native_certs::load_native_certs()? { + roots.add(cert)?; + } + + if let Some(ca_file) = &ca_file { + let f = File::open(ca_file).context("Open CA certificate")?; + let mut reader = BufReader::new(f); + let certs = rustls_pemfile::certs(&mut reader); + for cert in certs.flatten() { + roots.add(cert)?; + } + } + + Ok(roots) +} + +pub async fn load_cert(cert_file: &str) -> Result>> { + let cert_s = fs::read_to_string(cert_file) + .await + .context("Read TLS certificate")?; + let mut cert_b = cert_s.as_bytes(); + let certs = rustls_pemfile::certs(&mut cert_b); + let mut out = Vec::new(); + for cert in certs { + out.push(cert?.into_owned()); + } + Ok(out) +} + +pub async fn load_key(key_file: &str) -> Result> { + let key_s = fs::read_to_string(key_file) + .await + .context("Read private key")?; + let key_s = private_key_to_pkcs8(&key_s)?; + let mut key_b = key_s.as_bytes(); + let mut keys = rustls_pemfile::pkcs8_private_keys(&mut key_b); + if let Some(key) = keys.next() { + match key { + Ok(v) => return Ok(PrivateKeyDer::Pkcs8(v.clone_key())), + Err(e) => { + return Err(anyhow!("Error parsing private key, error: {}", e)); + } + } + } + + Err(anyhow!("No private key found")) +} + +pub fn private_key_to_pkcs8(pem: &str) -> Result { + if pem.contains("RSA PRIVATE KEY") { + use rsa::{ + pkcs1::DecodeRsaPrivateKey, + pkcs8::{EncodePrivateKey, LineEnding}, + RsaPrivateKey, + }; + + let pkey = RsaPrivateKey::from_pkcs1_pem(pem).context("Read RSA PKCS#1")?; + let pkcs8_pem = pkey.to_pkcs8_pem(LineEnding::default())?; + Ok(pkcs8_pem.as_str().to_owned()) + } else if pem.contains("EC PRIVATE KEY") { + use elliptic_curve::{ + pkcs8::{EncodePrivateKey, LineEnding}, + SecretKey, + }; + + // We assume it is a P256 based secret-key, which is the most popular curve. + // Attempting to decode it as P256 is still better than just failing to read it. + let pkey: SecretKey = + SecretKey::from_sec1_pem(pem).context("Read EC SEC1")?; + let pkcs8_pem = pkey.to_pkcs8_pem(LineEnding::default())?; + Ok(pkcs8_pem.as_str().to_owned()) + } else { + Ok(pem.to_string()) + } +} diff --git a/chirpstack/src/integration/gcp_pub_sub.rs b/chirpstack/src/integration/gcp_pub_sub.rs index 555762e9..1a31bc4a 100644 --- a/chirpstack/src/integration/gcp_pub_sub.rs +++ b/chirpstack/src/integration/gcp_pub_sub.rs @@ -4,7 +4,7 @@ use std::time::Duration; use anyhow::{Context, Result}; use async_trait::async_trait; use base64::{engine::general_purpose, Engine as _}; -use gcp_auth::{AuthenticationManager, CustomServiceAccount}; +use gcp_auth::{CustomServiceAccount, TokenProvider}; use prost::Message; use reqwest::header::{HeaderMap, AUTHORIZATION, CONTENT_TYPE}; use reqwest::Client; @@ -20,7 +20,7 @@ pub struct Integration { json: bool, project_id: String, topic_name: String, - auth_manager: gcp_auth::AuthenticationManager, + service_account: gcp_auth::CustomServiceAccount, timeout: Duration, } @@ -46,7 +46,6 @@ impl Integration { pub async fn new(conf: &GcpPubSubConfiguration) -> Result { trace!("Initializing GCP Pub-Sub integration"); let service_account = CustomServiceAccount::from_json(&conf.credentials_file)?; - let auth_manager = AuthenticationManager::try_from(service_account)?; Ok(Integration { json: match Encoding::try_from(conf.encoding) @@ -57,7 +56,7 @@ impl Integration { }, project_id: conf.project_id.clone(), topic_name: conf.topic_name.clone(), - auth_manager, + service_account, timeout: Duration::from_secs(5), }) } @@ -89,8 +88,8 @@ impl Integration { let pl = serde_json::to_string(&pl)?; let token = self - .auth_manager - .get_token(&["https://www.googleapis.com/auth/pubsub"]) + .service_account + .token(&["https://www.googleapis.com/auth/pubsub"]) .await .context("Get GCP bearer token")?; diff --git a/chirpstack/src/integration/mqtt.rs b/chirpstack/src/integration/mqtt.rs index 03b9d972..3cc8a576 100644 --- a/chirpstack/src/integration/mqtt.rs +++ b/chirpstack/src/integration/mqtt.rs @@ -19,7 +19,7 @@ use tracing::{error, info, trace, warn}; use super::Integration as IntegrationTrait; use crate::config::MqttIntegration as Config; -use crate::helpers::tls::{get_root_certs, load_cert, load_key}; +use crate::helpers::tls22::{get_root_certs, load_cert, load_key}; use chirpstack_api::integration; pub struct Integration<'a> {