From 99dd1603b0424490ec67b2a13821107a5de29677 Mon Sep 17 00:00:00 2001 From: Dirkjan Ochtman Date: Mon, 4 Mar 2024 11:59:56 +0100 Subject: [PATCH 1/2] Simplify listener abstraction --- .../src/server.rs | 35 +---------- .../src/tls/listener.rs | 63 ++++++++++++++----- 2 files changed, 49 insertions(+), 49 deletions(-) diff --git a/rust-runtime/aws-smithy-http-server-python/src/server.rs b/rust-runtime/aws-smithy-http-server-python/src/server.rs index 84c295adf6..774e1f78b0 100644 --- a/rust-runtime/aws-smithy-http-server-python/src/server.rs +++ b/rust-runtime/aws-smithy-http-server-python/src/server.rs @@ -8,7 +8,6 @@ use std::convert::Infallible; use std::net::TcpListener as StdTcpListener; use std::ops::Deref; use std::process; -use std::sync::{mpsc, Arc}; use std::thread; use aws_smithy_http_server::{ @@ -22,7 +21,6 @@ use pyo3::{prelude::*, types::IntoPyDict}; use signal_hook::{consts::*, iterator::Signals}; use socket2::Socket; use tokio::{net::TcpListener, runtime}; -use tokio_rustls::TlsAcceptor; use tower::{util::BoxCloneService, ServiceBuilder}; use crate::{ @@ -260,8 +258,7 @@ event_loop.add_signal_handler(signal.SIGINT, let addr = addr_incoming_from_socket(raw_socket); if let Some(config) = tls { - let (acceptor, acceptor_rx) = tls_config_reloader(config); - let listener = TlsListener::new(acceptor, addr, acceptor_rx); + let listener = TlsListener::new(config, addr); let server = hyper::Server::builder(listener).serve(IntoMakeService::new(service)); @@ -271,6 +268,7 @@ event_loop.add_signal_handler(signal.SIGINT, tracing::error!(error = ?err, "server error"); } } else { + let server = hyper::Server::builder(addr).serve(IntoMakeService::new(service)); tracing::trace!("started hyper server from shared socket"); @@ -509,32 +507,3 @@ fn addr_incoming_from_socket(socket: Socket) -> AddrIncoming { AddrIncoming::from_listener(listener) .expect("unable to create `AddrIncoming` from `TcpListener`") } - -// Builds `TlsAcceptor` from given `config` and also creates a background task -// to reload certificates and returns a channel to receive new `TlsAcceptor`s. -fn tls_config_reloader(config: PyTlsConfig) -> (TlsAcceptor, mpsc::Receiver) { - let reload_dur = config.reload_duration(); - let (tx, rx) = mpsc::channel(); - let acceptor = TlsAcceptor::from(Arc::new(config.build().expect("invalid tls config"))); - - tokio::spawn(async move { - tracing::trace!(dur = ?reload_dur, "starting timer to reload tls config"); - loop { - tokio::time::sleep(reload_dur).await; - tracing::trace!("reloading tls config"); - match config.build() { - Ok(config) => { - let new_config = TlsAcceptor::from(Arc::new(config)); - // Note on expect: `tx.send` can only fail if the receiver is dropped, - // it probably a bug if that happens - tx.send(new_config).expect("could not send new tls config") - } - Err(err) => { - tracing::error!(error = ?err, "could not reload tls config because it is invalid"); - } - } - } - }); - - (acceptor, rx) -} diff --git a/rust-runtime/aws-smithy-http-server-python/src/tls/listener.rs b/rust-runtime/aws-smithy-http-server-python/src/tls/listener.rs index 9e6dbed364..4f9a037c7f 100644 --- a/rust-runtime/aws-smithy-http-server-python/src/tls/listener.rs +++ b/rust-runtime/aws-smithy-http-server-python/src/tls/listener.rs @@ -3,42 +3,44 @@ * SPDX-License-Identifier: Apache-2.0 */ +use std::io; use std::pin::Pin; -use std::sync::mpsc; +use std::sync::{mpsc, Arc}; use std::task::{Context, Poll}; use futures::{ready, Stream}; use hyper::server::accept::Accept; +use hyper::server::conn::{AddrIncoming, AddrStream}; use pin_project_lite::pin_project; -use tls_listener::{AsyncAccept, AsyncTls, Error as TlsListenerError, TlsListener}; +use tls_listener::{Error as TlsListenerError, TlsListener}; +use tokio_rustls::server::TlsStream; +use tokio_rustls::TlsAcceptor; + +use super::PyTlsConfig; pin_project! { /// A wrapper around [TlsListener] that allows changing TLS config via a channel /// and ignores incorrect connections (they cause Hyper server to shutdown otherwise). - pub struct Listener> { + pub struct Listener { #[pin] - inner: TlsListener, - new_acceptor_rx: mpsc::Receiver, + inner: TlsListener, + new_acceptor_rx: mpsc::Receiver, } } -impl> Listener { - pub fn new(tls: T, listener: A, new_acceptor_rx: mpsc::Receiver) -> Self { +impl Listener { + pub fn new(config: PyTlsConfig, addr: AddrIncoming) -> Self { + let (acceptor, new_acceptor_rx) = tls_config_reloader(config); Self { - inner: TlsListener::new(tls, listener), + inner: TlsListener::new(acceptor, addr), new_acceptor_rx, } } } -impl Accept for Listener -where - A: AsyncAccept, - A::Error: std::error::Error, - T: AsyncTls, -{ - type Conn = T::Stream; - type Error = A::Error; +impl Accept for Listener { + type Conn = TlsStream; + type Error = io::Error; fn poll_accept( mut self: Pin<&mut Self>, @@ -65,6 +67,35 @@ where } } +// Builds `TlsAcceptor` from given `config` and also creates a background task +// to reload certificates and returns a channel to receive new `TlsAcceptor`s. +fn tls_config_reloader(config: PyTlsConfig) -> (TlsAcceptor, mpsc::Receiver) { + let reload_dur = config.reload_duration(); + let (tx, rx) = mpsc::channel(); + let acceptor = TlsAcceptor::from(Arc::new(config.build().expect("invalid tls config"))); + + tokio::spawn(async move { + tracing::trace!(dur = ?reload_dur, "starting timer to reload tls config"); + loop { + tokio::time::sleep(reload_dur).await; + tracing::trace!("reloading tls config"); + match config.build() { + Ok(config) => { + let new_config = TlsAcceptor::from(Arc::new(config)); + // Note on expect: `tx.send` can only fail if the receiver is dropped, + // it probably a bug if that happens + tx.send(new_config).expect("could not send new tls config") + } + Err(err) => { + tracing::error!(error = ?err, "could not reload tls config because it is invalid"); + } + } + } + }); + + (acceptor, rx) +} + #[cfg(test)] mod tests { use std::io; From 633ffa1287e8a50956ef45f50949c73799c3f152 Mon Sep 17 00:00:00 2001 From: Dirkjan Ochtman Date: Mon, 4 Mar 2024 10:30:35 +0100 Subject: [PATCH 2/2] Upgrade to rustls 0.22 cs --- aws/rust-runtime/aws-config/Cargo.toml | 2 +- aws/rust-runtime/aws-types/Cargo.toml | 2 +- .../aws-smithy-http-server-python/Cargo.toml | 8 +-- .../src/server.rs | 15 +++-- .../aws-smithy-http-server-python/src/tls.rs | 44 ++++++++------ .../src/tls/listener.rs | 57 ++++++++++++------- rust-runtime/aws-smithy-runtime/Cargo.toml | 4 +- .../src/client/http/hyper_014.rs | 36 +++++++----- 8 files changed, 98 insertions(+), 70 deletions(-) diff --git a/aws/rust-runtime/aws-config/Cargo.toml b/aws/rust-runtime/aws-config/Cargo.toml index df656841b8..c59c8a925d 100644 --- a/aws/rust-runtime/aws-config/Cargo.toml +++ b/aws/rust-runtime/aws-config/Cargo.toml @@ -72,7 +72,7 @@ serde = { version = "1", features = ["derive"] } serde_json = "1" # used for a usage example -hyper-rustls = { version = "0.24", features = ["webpki-tokio", "http2", "http1"] } +hyper-rustls = { version = "0.25", features = ["webpki-tokio", "http2", "http1"] } aws-smithy-async = { path = "../../sdk/build/aws-sdk/sdk/aws-smithy-async", features = ["rt-tokio", "test-util"] } diff --git a/aws/rust-runtime/aws-types/Cargo.toml b/aws/rust-runtime/aws-types/Cargo.toml index 060275681c..c3a27e9c57 100644 --- a/aws/rust-runtime/aws-types/Cargo.toml +++ b/aws/rust-runtime/aws-types/Cargo.toml @@ -22,7 +22,7 @@ http = "0.2.6" # cargo does not support optional test dependencies, so to completely disable rustls # we need to add the webpki-roots feature here. # https://github.com/rust-lang/cargo/issues/1596 -hyper-rustls = { version = "0.24", optional = true, features = ["rustls-native-certs", "http2", "webpki-roots"] } +hyper-rustls = { version = "0.25", optional = true, features = ["rustls-native-certs", "http2", "webpki-roots"] } [dev-dependencies] http = "0.2.4" diff --git a/rust-runtime/aws-smithy-http-server-python/Cargo.toml b/rust-runtime/aws-smithy-http-server-python/Cargo.toml index 2f65440e33..9dfc411b68 100644 --- a/rust-runtime/aws-smithy-http-server-python/Cargo.toml +++ b/rust-runtime/aws-smithy-http-server-python/Cargo.toml @@ -22,19 +22,19 @@ bytes = "1.2" futures = "0.3" http = "0.2" hyper = { version = "0.14.26", features = ["server", "http1", "http2", "tcp", "stream"] } -tls-listener = { version = "0.7.0", features = ["rustls", "hyper-h2"] } -rustls-pemfile = "1.0.1" -tokio-rustls = "0.24.0" lambda_http = { version = "0.8.0" } num_cpus = "1.13.1" parking_lot = "0.12.1" pin-project-lite = "0.2" pyo3 = "0.18.2" pyo3-asyncio = { version = "0.18.0", features = ["tokio-runtime"] } +rustls-pemfile = "2" signal-hook = { version = "0.3.14", features = ["extended-siginfo"] } socket2 = { version = "0.5.2", features = ["all"] } thiserror = "1.0.32" +tls-listener = { version = "0.9", features = ["rustls"] } tokio = { version = "1.20.1", features = ["full"] } +tokio-rustls = "0.25" tokio-stream = "0.1" tower = { version = "0.4.13", features = ["util"] } tracing = "0.1.36" @@ -48,7 +48,7 @@ tower-test = "0.4" tokio-test = "0.4" pyo3-asyncio = { version = "0.18.0", features = ["testing", "attributes", "tokio-runtime", "unstable-streams"] } rcgen = "0.10.0" -hyper-rustls = { version = "0.24", features = ["http2"] } +hyper-rustls = { version = "0.25", features = ["http2"] } # PyO3 Asyncio tests cannot use Cargo's default testing harness because `asyncio` # wants to control the main thread. So we need to use testing harness provided by `pyo3_asyncio` diff --git a/rust-runtime/aws-smithy-http-server-python/src/server.rs b/rust-runtime/aws-smithy-http-server-python/src/server.rs index 774e1f78b0..73edf19739 100644 --- a/rust-runtime/aws-smithy-http-server-python/src/server.rs +++ b/rust-runtime/aws-smithy-http-server-python/src/server.rs @@ -255,10 +255,10 @@ event_loop.add_signal_handler(signal.SIGINT, .build() .expect("unable to start a new tokio runtime for this process"); rt.block_on(async move { - let addr = addr_incoming_from_socket(raw_socket); + let listener = tcp_listener_from_socket(raw_socket); if let Some(config) = tls { - let listener = TlsListener::new(config, addr); + let listener = TlsListener::new(config, listener); let server = hyper::Server::builder(listener).serve(IntoMakeService::new(service)); @@ -268,7 +268,8 @@ event_loop.add_signal_handler(signal.SIGINT, tracing::error!(error = ?err, "server error"); } } else { - + let addr = AddrIncoming::from_listener(listener) + .expect("unable to create `AddrIncoming` from `TcpListener`"); let server = hyper::Server::builder(addr).serve(IntoMakeService::new(service)); tracing::trace!("started hyper server from shared socket"); @@ -496,14 +497,12 @@ event_loop.add_signal_handler(signal.SIGINT, } } -fn addr_incoming_from_socket(socket: Socket) -> AddrIncoming { +fn tcp_listener_from_socket(socket: Socket) -> TcpListener { let std_listener: StdTcpListener = socket.into(); // StdTcpListener::from_std doesn't set O_NONBLOCK std_listener .set_nonblocking(true) .expect("unable to set `O_NONBLOCK=true` on `std::net::TcpListener`"); - let listener = TcpListener::from_std(std_listener) - .expect("unable to create `tokio::net::TcpListener` from `std::net::TcpListener`"); - AddrIncoming::from_listener(listener) - .expect("unable to create `AddrIncoming` from `TcpListener`") + TcpListener::from_std(std_listener) + .expect("unable to create `tokio::net::TcpListener` from `std::net::TcpListener`") } diff --git a/rust-runtime/aws-smithy-http-server-python/src/tls.rs b/rust-runtime/aws-smithy-http-server-python/src/tls.rs index c817cabaca..4a31fe4d2e 100644 --- a/rust-runtime/aws-smithy-http-server-python/src/tls.rs +++ b/rust-runtime/aws-smithy-http-server-python/src/tls.rs @@ -15,7 +15,8 @@ use std::time::Duration; use pyo3::{pyclass, pymethods}; use thiserror::Error; -use tokio_rustls::rustls::{Certificate, Error as RustTlsError, PrivateKey, ServerConfig}; +use tokio_rustls::rustls::pki_types::{CertificateDer, PrivateKeyDer}; +use tokio_rustls::rustls::{Error as RustTlsError, ServerConfig}; pub mod listener; @@ -53,7 +54,6 @@ impl PyTlsConfig { let cert_chain = self.cert_chain()?; let key_der = self.key_der()?; let mut config = ServerConfig::builder() - .with_safe_defaults() .with_no_client_auth() .with_single_cert(cert_chain, key_der)?; config.alpn_protocols = vec!["h2".into(), "http/1.1".into()]; @@ -66,18 +66,16 @@ impl PyTlsConfig { } /// Reads certificates from `cert_path`. - fn cert_chain(&self) -> Result, PyTlsConfigError> { + fn cert_chain(&self) -> Result>, PyTlsConfigError> { let file = File::open(&self.cert_path).map_err(PyTlsConfigError::CertParse)?; let mut cert_rdr = BufReader::new(file); - Ok(rustls_pemfile::certs(&mut cert_rdr) - .map_err(PyTlsConfigError::CertParse)? - .into_iter() - .map(Certificate) - .collect()) + rustls_pemfile::certs(&mut cert_rdr) + .collect::, _>>() + .map_err(PyTlsConfigError::CertParse) } /// Parses RSA or PKCS private key from `key_path`. - fn key_der(&self) -> Result { + fn key_der(&self) -> Result, PyTlsConfigError> { let mut key_vec = Vec::new(); File::open(&self.key_path) .and_then(|mut f| f.read_to_end(&mut key_vec)) @@ -86,16 +84,26 @@ impl PyTlsConfig { return Err(PyTlsConfigError::EmptyKey); } - let mut pkcs8 = rustls_pemfile::pkcs8_private_keys(&mut key_vec.as_slice()) - .map_err(PyTlsConfigError::Pkcs8Parse)?; - if !pkcs8.is_empty() { - return Ok(PrivateKey(pkcs8.remove(0))); + let mut key_slice = key_vec.as_slice(); + let mut pkcs8 = rustls_pemfile::pkcs8_private_keys(&mut key_slice); + match pkcs8.next() { + Some(Ok(key)) if !key.secret_pkcs8_der().is_empty() => { + return Ok(PrivateKeyDer::from(key).clone_key()) + } + Some(Ok(_)) => return Err(PyTlsConfigError::EmptyKey), + Some(Err(e)) => return Err(PyTlsConfigError::Pkcs8Parse(e)), + None => {} } - let mut rsa = rustls_pemfile::rsa_private_keys(&mut key_vec.as_slice()) - .map_err(PyTlsConfigError::RsaParse)?; - if !rsa.is_empty() { - return Ok(PrivateKey(rsa.remove(0))); + let mut key_slice = key_vec.as_slice(); + let mut rsa = rustls_pemfile::rsa_private_keys(&mut key_slice); + match rsa.next() { + Some(Ok(key)) if !key.secret_pkcs1_der().is_empty() => { + return Ok(PrivateKeyDer::from(key)) + } + Some(Ok(_)) => return Err(PyTlsConfigError::EmptyKey), + Some(Err(e)) => return Err(PyTlsConfigError::Pkcs8Parse(e)), + None => {} } Err(PyTlsConfigError::EmptyKey) @@ -129,7 +137,7 @@ pub enum PyTlsConfigError { Pkcs8Parse(io::Error), #[error("could not parse rsa keys")] RsaParse(io::Error), - #[error("rusttls protocol error")] + #[error("rustls protocol error")] RustTlsError(#[from] RustTlsError), } diff --git a/rust-runtime/aws-smithy-http-server-python/src/tls/listener.rs b/rust-runtime/aws-smithy-http-server-python/src/tls/listener.rs index 4f9a037c7f..363ee40cb8 100644 --- a/rust-runtime/aws-smithy-http-server-python/src/tls/listener.rs +++ b/rust-runtime/aws-smithy-http-server-python/src/tls/listener.rs @@ -10,9 +10,9 @@ use std::task::{Context, Poll}; use futures::{ready, Stream}; use hyper::server::accept::Accept; -use hyper::server::conn::{AddrIncoming, AddrStream}; use pin_project_lite::pin_project; use tls_listener::{Error as TlsListenerError, TlsListener}; +use tokio::net::{TcpListener, TcpStream}; use tokio_rustls::server::TlsStream; use tokio_rustls::TlsAcceptor; @@ -23,23 +23,23 @@ pin_project! { /// and ignores incorrect connections (they cause Hyper server to shutdown otherwise). pub struct Listener { #[pin] - inner: TlsListener, + inner: TlsListener, new_acceptor_rx: mpsc::Receiver, } } impl Listener { - pub fn new(config: PyTlsConfig, addr: AddrIncoming) -> Self { + pub fn new(config: PyTlsConfig, listener: TcpListener) -> Self { let (acceptor, new_acceptor_rx) = tls_config_reloader(config); Self { - inner: TlsListener::new(acceptor, addr), + inner: TlsListener::new(acceptor, listener), new_acceptor_rx, } } } impl Accept for Listener { - type Conn = TlsStream; + type Conn = TlsStream; type Error = io::Error; fn poll_accept( @@ -53,13 +53,22 @@ impl Accept for Listener { loop { match ready!(self.as_mut().project().inner.poll_next(cx)) { - Some(Ok(conn)) => return Poll::Ready(Some(Ok(conn))), + Some(Ok((conn, _))) => return Poll::Ready(Some(Ok(conn))), Some(Err(TlsListenerError::ListenerError(err))) => { return Poll::Ready(Some(Err(err))) } - Some(Err(TlsListenerError::TlsAcceptError(err))) => { + Some(Err(TlsListenerError::TlsAcceptError { + error, peer_addr, .. + })) => { // Don't propogate TLS handshake errors to Hyper because it causes server to shutdown - tracing::debug!(error = ?err, "tls handshake error"); + tracing::debug!(?error, ?peer_addr, "tls accept error"); + } + Some(Err(TlsListenerError::HandshakeTimeout { peer_addr, .. })) => { + // Don't propogate TLS handshake errors to Hyper because it causes server to shutdown + tracing::debug!(?peer_addr, "tls handshake timeout"); + } + Some(_) => { + tracing::debug!("unexpected tls listener error"); } None => return Poll::Ready(None), } @@ -106,14 +115,19 @@ mod tests { use std::thread; use futures::ready; - use hyper::server::conn::{AddrIncoming, AddrStream}; + use hyper::server::accept::Accept; + use hyper::server::conn::AddrIncoming; use hyper::service::{make_service_fn, service_fn}; use hyper::{Body, Client, Error, Response, Server, Uri}; use hyper_rustls::HttpsConnectorBuilder; use pin_project_lite::pin_project; use tls_listener::AsyncAccept; + use tokio::net::TcpStream; use tokio_rustls::{ - rustls::{Certificate, ClientConfig, PrivateKey, RootCertStore, ServerConfig}, + rustls::{ + pki_types::{CertificateDer, PrivatePkcs8KeyDer}, + ClientConfig, RootCertStore, ServerConfig, + }, TlsAcceptor, }; @@ -137,24 +151,26 @@ mod tests { } impl AsyncAccept for DummyListener { - type Connection = AddrStream; + type Address = SocketAddr; + type Connection = TcpStream; type Error = io::Error; fn poll_accept( self: Pin<&mut Self>, cx: &mut Context<'_>, - ) -> Poll>> { + ) -> Poll> { let this = self.project(); let conn = match ready!(this.inner.poll_accept(cx)) { Some(Ok(conn)) => conn, - Some(Err(err)) => return Poll::Ready(Some(Err(err))), - None => return Poll::Ready(None), + Some(Err(err)) => return Poll::Ready(Err(err)), + None => return Poll::Pending, }; + let remote_addr = conn.remote_addr(); match &this.mode { - DummyListenerMode::Identity => Poll::Ready(Some(Ok(conn))), + DummyListenerMode::Identity => Poll::Ready(Ok((conn.into_inner(), remote_addr))), DummyListenerMode::Fail => { - Poll::Ready(Some(Err(io::ErrorKind::ConnectionAborted.into()))) + Poll::Ready(Err(io::ErrorKind::ConnectionAborted.into())) } } } @@ -245,9 +261,9 @@ mod tests { fn client_config_with_cert(cert: &rcgen::Certificate) -> ClientConfig { let mut roots = RootCertStore::empty(); - roots.add_parsable_certificates(&[cert.serialize_der().unwrap()]); + let cert = CertificateDer::from(cert.serialize_der().unwrap()); + roots.add_parsable_certificates([cert]); ClientConfig::builder() - .with_safe_defaults() .with_root_certificates(roots) .with_no_client_auth() } @@ -266,11 +282,10 @@ mod tests { fn acceptor_from_cert(cert: &rcgen::Certificate) -> TlsAcceptor { TlsAcceptor::from(Arc::new( ServerConfig::builder() - .with_safe_defaults() .with_no_client_auth() .with_single_cert( - vec![Certificate(cert.serialize_der().unwrap())], - PrivateKey(cert.serialize_private_key_der()), + vec![CertificateDer::from(cert.serialize_der().unwrap())], + PrivatePkcs8KeyDer::from(cert.serialize_private_key_der()).into(), ) .unwrap(), )) diff --git a/rust-runtime/aws-smithy-runtime/Cargo.toml b/rust-runtime/aws-smithy-runtime/Cargo.toml index c8224745e1..98fa3ce32a 100644 --- a/rust-runtime/aws-smithy-runtime/Cargo.toml +++ b/rust-runtime/aws-smithy-runtime/Cargo.toml @@ -32,11 +32,11 @@ h2 = { version = "0.3", default-features = false, optional = true } http = { version = "0.2.8" } http-body-0-4 = { package = "http-body", version = "0.4.4" } hyper-0-14 = { package = "hyper", version = "0.14.26", default-features = false, optional = true } -hyper-rustls = { version = "0.24", features = ["rustls-native-certs", "http2"], optional = true } +hyper-rustls = { version = "0.25", features = ["rustls-native-certs", "http2"], optional = true } once_cell = "1.18.0" pin-project-lite = "0.2.7" pin-utils = "0.1.0" -rustls = { version = "0.21.8", optional = true } +rustls = { version = "0.22", optional = true } serde = { version = "1", features = ["derive"], optional = true } serde_json = { version = "1", optional = true } tokio = { version = "1.25", features = [] } diff --git a/rust-runtime/aws-smithy-runtime/src/client/http/hyper_014.rs b/rust-runtime/aws-smithy-runtime/src/client/http/hyper_014.rs index 95bcd0d182..9d1eda15d9 100644 --- a/rust-runtime/aws-smithy-runtime/src/client/http/hyper_014.rs +++ b/rust-runtime/aws-smithy-runtime/src/client/http/hyper_014.rs @@ -37,10 +37,13 @@ use tokio::io::{AsyncRead, AsyncWrite}; #[cfg(feature = "tls-rustls")] mod default_connector { + use std::sync::Arc; + use aws_smithy_async::rt::sleep::SharedAsyncSleep; use aws_smithy_runtime_api::client::http::HttpConnectorSettings; use hyper_0_14::client::HttpConnector; use hyper_rustls::HttpsConnector; + use rustls::crypto::ring::cipher_suite; // Creating a `with_native_roots` HTTP client takes 300ms on OS X. Cache this so that we // don't need to repeatedly incur that cost. @@ -50,25 +53,28 @@ mod default_connector { fn default_tls() -> HttpsConnector { use hyper_rustls::ConfigBuilderExt; + + let mut crypto_provider = rustls::crypto::ring::default_provider(); + crypto_provider.cipher_suites = vec![ + // TLS1.3 suites + cipher_suite::TLS13_AES_256_GCM_SHA384, + cipher_suite::TLS13_AES_128_GCM_SHA256, + // TLS1.2 suites + cipher_suite::TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384, + cipher_suite::TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, + cipher_suite::TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384, + cipher_suite::TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256, + cipher_suite::TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256, + ]; + hyper_rustls::HttpsConnectorBuilder::new() - .with_tls_config( - rustls::ClientConfig::builder() - .with_cipher_suites(&[ - // TLS1.3 suites - rustls::cipher_suite::TLS13_AES_256_GCM_SHA384, - rustls::cipher_suite::TLS13_AES_128_GCM_SHA256, - // TLS1.2 suites - rustls::cipher_suite::TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384, - rustls::cipher_suite::TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, - rustls::cipher_suite::TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384, - rustls::cipher_suite::TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256, - rustls::cipher_suite::TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256, - ]) - .with_safe_default_kx_groups() + .with_tls_config( + rustls::ClientConfig::builder_with_provider(Arc::new(crypto_provider)) .with_safe_default_protocol_versions() .expect("Error with the TLS configuration. Please file a bug report under https://github.com/smithy-lang/smithy-rs/issues.") .with_native_roots() - .with_no_client_auth() + .expect("Error with the TLS configuration. Please file a bug report under https://github.com/smithy-lang/smithy-rs/issues.") + .with_no_client_auth(), ) .https_or_http() .enable_http1()