From 4f1911ecefd138d7732b24c3dc4bc71ec06862ac Mon Sep 17 00:00:00 2001 From: Robsdedude Date: Tue, 16 Apr 2024 08:44:47 +0200 Subject: [PATCH 1/2] Bump dependencies --- CHANGELOG.md | 12 ++++++++-- neo4j/Cargo.toml | 6 ++--- neo4j/src/driver/config.rs | 34 +++++++++++++++++++++++++++ neo4j/src/driver/io/bolt/handshake.rs | 23 +++++++++++++++++- testkit/Dockerfile | 3 +++ testkit_backend/Cargo.toml | 1 + testkit_backend/src/main.rs | 3 +++ 7 files changed, 76 insertions(+), 6 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index a5092d2..316eab9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,6 +11,13 @@ - Add `Driver::is_encrypted()`. - Introduce `neo4j::driver::Conifg::with_keep_alive()` and `without_keep_alive()`. +**👏 Improvements** + - ⚠️ ️️Bump `chrono-tz` from `0.8` to `0.9` (types of this crate are exposed through the driver's API. + - ⚠️ ️️Bump `rustls` from `0.22` to `0.23`: + - types of this crate are exposed through the driver's API + - other breaking changes (e.g., new build requirements). + See [rustls' changelog](https://github.com/rustls/rustls/releases/tag/v%2F0.23.0) for more details. + **🔧 Fixes** - Fix `Transaction::rolblack()` failing if a result stream failed before. - Fix errors during transaction `BEGIN` not being properly propagated. @@ -29,7 +36,7 @@ **👏 Improvements** - Impl `FromStr` for `neo4j::driver::ConnectionConfig` (besides `TryFrom<&str>`). - - **🧹Clean-up** +**🧹Clean-up** - ⚠️ Update dependencies. Among others `rustls`. To accommodate this change, the `rustls_dangerous_configuration` feature was removed. @@ -48,6 +55,7 @@ **📚 Docs** - Much more documentation. -## 0.0.1 +## 0.0.1 +*** Initial release diff --git a/neo4j/Cargo.toml b/neo4j/Cargo.toml index 83222db..e875abd 100644 --- a/neo4j/Cargo.toml +++ b/neo4j/Cargo.toml @@ -29,15 +29,15 @@ _internal_public_api = [ [dependencies] atomic_refcell = "0.1.13" chrono = "0.4.37" -chrono-tz = "0.8.6" +chrono-tz = "0.9.0" duplicate = "1.0.0" enum_dispatch = "0.3.13" -itertools = "0.11.0" +itertools = "0.12.1" log = "0.4.21" mockall_double = "0.3.1" parking_lot = "0.12.1" rand = "0.8.5" -rustls = "0.22.3" +rustls = "0.23.4" rustls-native-certs = "0.7.0" rustls-pemfile = "2.1.2" rustls-pki-types = "1.4.1" diff --git a/neo4j/src/driver/config.rs b/neo4j/src/driver/config.rs index f37a642..7378410 100644 --- a/neo4j/src/driver/config.rs +++ b/neo4j/src/driver/config.rs @@ -135,6 +135,15 @@ pub enum KeepAliveConfig { /// .unwrap() /// .with_routing_context(routing_context); /// ``` +/// +/// ## TLS +/// The driver utilizes [`rustls`] for TLS concerns. +/// Make sure to have a look at the requirements, for building and using it. +/// In particular: +/// * Consider the +/// [platform support](https://docs.rs/rustls/latest/rustls/index.html#platform-support) +/// * Make sure a crypto provider is installed (e.g., by calling +/// [`rustls::crypto::CryptoProvider::install_default()`] when starting the process). #[derive(Debug)] pub struct ConnectionConfig { pub(crate) address: Address, @@ -634,6 +643,8 @@ impl ConnectionConfig { /// certificate store. /// /// Returns an error if the system's root CA certificate store could not be loaded. + /// + /// To use TLS, see the notes about [TLS requirements](Self#tls). #[allow(clippy::result_large_err)] pub fn with_encryption_trust_default_cas(mut self) -> StdResult { self.tls_config = Some(match tls_helper::secure_tls_config() { @@ -652,6 +663,8 @@ impl ConnectionConfig { /// loaded from the given file(s). /// /// Returns an error if loading the root CA certificates failed. + /// + /// To use TLS, see the notes about [TLS requirements](Self#tls). #[allow(clippy::result_large_err)] pub fn with_encryption_trust_custom_cas>( self, @@ -675,6 +688,8 @@ impl ConnectionConfig { /// /// **⚠️ WARNING**: /// This is not secure and should only be used for testing purposes. + /// + /// To use TLS, see the notes about [TLS requirements](Self#tls). pub fn with_encryption_trust_any_certificate(mut self) -> Self { self.tls_config = Some(tls_helper::self_signed_tls_config()); self @@ -693,6 +708,8 @@ impl ConnectionConfig { /// # use rustls_pki_types::{TrustAnchor, Der}; /// /// # fn get_custom_client_config() -> ClientConfig { + /// # // Fails if a provider is already installed. That's fine, too. + /// # let _ = rustls::crypto::aws_lc_rs::default_provider().install_default(); /// # ClientConfig::builder().with_root_certificates( /// # RootCertStore { /// # roots: vec![ @@ -710,6 +727,8 @@ impl ConnectionConfig { /// let config = ConnectionConfig::new(("localhost", 7687).into()) /// .with_encryption_custom_tls_config(client_config); /// ``` + /// + /// To use TLS, see the notes about [TLS requirements](Self#tls). pub fn with_encryption_custom_tls_config(mut self, tls_config: ClientConfig) -> Self { self.tls_config = Some(tls_config); self @@ -933,7 +952,13 @@ mod mockable { OnceLock::new(); pub fn secure_tls_config() -> StdResult { + // Fails if a provider is already installed. That's fine, too. + let _ = rustls::crypto::aws_lc_rs::default_provider().install_default(); + let root_store = SYSTEM_CERTIFICATES.get_or_init(|| { + // Fails if a provider is already installed. That's fine, too. + let _ = rustls::crypto::aws_lc_rs::default_provider().install_default(); + let mut root_store = RootCertStore::empty(); // root_store.add_trust_anchors(webpki_roots::TLS_SERVER_ROOTS.iter().map(|ta| { // rustls::OwnedTrustAnchor::from_subject_spki_name_constraints( @@ -957,6 +982,9 @@ mod mockable { pub fn custom_ca_tls_config<'a, 'b>( paths: &'a [&'b Path], ) -> StdResult { + // Fails if a provider is already installed. That's fine, too. + let _ = rustls::crypto::aws_lc_rs::default_provider().install_default(); + let mut root_store = RootCertStore::empty(); for path in paths { let file = File::open(path) @@ -976,6 +1004,9 @@ mod mockable { } pub fn self_signed_tls_config() -> ClientConfig { + // Fails if a provider is already installed. That's fine, too. + let _ = rustls::crypto::aws_lc_rs::default_provider().install_default(); + let root_store = RootCertStore::empty(); let mut config = ClientConfig::builder() .with_root_certificates(root_store) @@ -1095,6 +1126,9 @@ mod tests { } fn get_test_client_config() -> ClientConfig { + // Fails if a provider is already installed. That's fine, too. + let _ = rustls::crypto::aws_lc_rs::default_provider().install_default(); + let root_store = RootCertStore::empty(); ClientConfig::builder() .with_root_certificates(root_store) diff --git a/neo4j/src/driver/io/bolt/handshake.rs b/neo4j/src/driver/io/bolt/handshake.rs index d7445bb..d068e73 100644 --- a/neo4j/src/driver/io/bolt/handshake.rs +++ b/neo4j/src/driver/io/bolt/handshake.rs @@ -226,7 +226,12 @@ pub(crate) fn open( )?; socket_debug!(local_port, "S: {:02X?}", negotiated_version); - let version = decode_version_offer(&negotiated_version)?; + let version = wrap_socket_killing( + &mut socket_provider, + &raw_socket, + local_port, + decode_version_offer(&negotiated_version), + )?; Ok(Bolt::new( version, @@ -304,6 +309,22 @@ where })) } +fn wrap_socket_killing( + socket_provider: &mut S, + stream: &S::RW, + local_port: u16, + res: Result, +) -> Result { + match res { + Ok(res) => Ok(res), + Err(err) => { + socket_debug!(local_port, " closing socket because {}", &err); + let _ = socket_provider.shutdown(stream, Shutdown::Both); + Err(err) + } + } +} + fn wrap_socket_write( socket_provider: &mut S, stream: &S::RW, diff --git a/testkit/Dockerfile b/testkit/Dockerfile index ff26590..d8f1a98 100644 --- a/testkit/Dockerfile +++ b/testkit/Dockerfile @@ -3,6 +3,9 @@ FROM rust:1.73-buster ENV DEBIAN_FRONTEND noninteractive RUN apt-get update && \ apt-get install -y locales && \ + # needed for aws-lc (transitive dependency of rustls) + # https://aws.github.io/aws-lc-rs/requirements/linux.html + apt-get install -y cmake gcc g++ libclang1 && \ apt-get clean && rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/* && \ localedef -i en_US -c -f UTF-8 -A /usr/share/locale/locale.alias en_US.UTF-8 \ && rm -rf /var/lib/apt/lists/* diff --git a/testkit_backend/Cargo.toml b/testkit_backend/Cargo.toml index a6262f8..0148a13 100644 --- a/testkit_backend/Cargo.toml +++ b/testkit_backend/Cargo.toml @@ -20,3 +20,4 @@ serde = { version = "1.0.197", features = ["derive"] } serde_json = "1.0.115" snowflaked = "1.0.3" thiserror = "1.0.58" +rustls = { version = "0.23.4", features = ["ring"] } diff --git a/testkit_backend/src/main.rs b/testkit_backend/src/main.rs index d5b4fc3..ba7cf81 100644 --- a/testkit_backend/src/main.rs +++ b/testkit_backend/src/main.rs @@ -20,6 +20,9 @@ mod testkit_backend; use testkit_backend::start_server; fn main() { + rustls::crypto::ring::default_provider() + .install_default() + .expect("failed to initialize aws_lc_rs"); logging::init(); start_server() } From ae9285e6a5df704af2596ca7868b555fd84bb86d Mon Sep 17 00:00:00 2001 From: Robsdedude Date: Fri, 3 May 2024 11:29:56 +0200 Subject: [PATCH 2/2] Improve error message when failing to load timezone id Bumping new version of `chrono-tz` does no longer mention the time zone's name in the error message when loading it fails. Therefore, the driver now makes sure the time zone name is included in the BrokenRecord's message. --- neo4j/src/driver/io/bolt/bolt4x4/translator.rs | 2 +- neo4j/src/driver/io/bolt/bolt5x0/translator.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/neo4j/src/driver/io/bolt/bolt4x4/translator.rs b/neo4j/src/driver/io/bolt/bolt4x4/translator.rs index f66f4c2..79563ad 100644 --- a/neo4j/src/driver/io/bolt/bolt4x4/translator.rs +++ b/neo4j/src/driver/io/bolt/bolt4x4/translator.rs @@ -268,7 +268,7 @@ impl BoltStructTranslator for Bolt4x4StructTranslator { Ok(tz) => tz, Err(e) => { return failed_struct(format!( - "failed to load DateTimeZoneId time zone: {e}" + "failed to load DateTimeZoneId time zone \"{tz_id}\": {e}" )); } }; diff --git a/neo4j/src/driver/io/bolt/bolt5x0/translator.rs b/neo4j/src/driver/io/bolt/bolt5x0/translator.rs index 761a28d..d218855 100644 --- a/neo4j/src/driver/io/bolt/bolt5x0/translator.rs +++ b/neo4j/src/driver/io/bolt/bolt5x0/translator.rs @@ -494,7 +494,7 @@ impl BoltStructTranslator for Bolt5x0StructTranslator { Ok(tz) => tz, Err(e) => { return failed_struct(format!( - "failed to load DateTimeZoneId time zone: {e}" + "failed to load DateTimeZoneId time zone \"{tz_id}\": {e}" )); } };