diff --git a/ci/Cargo.lock.min b/ci/Cargo.lock.min index 5c6416a..549b2ca 100644 --- a/ci/Cargo.lock.min +++ b/ci/Cargo.lock.min @@ -148,7 +148,7 @@ dependencies = [ "tokio-util", "tower-service", "url", - "winapi", + "winapi 0.3.9", ] [[package]] @@ -252,6 +252,16 @@ version = "0.8.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "06ea2b9bc92be3c2baa9334a323ebca2d6f074ff852cd1d7b11064035cd3868f" +[[package]] +name = "crypt32-sys" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e34988f7e069e0b2f3bfc064295161e489b2d4e04a2e4248fb94360cdf00b4ec" +dependencies = [ + "winapi 0.2.8", + "winapi-build", +] + [[package]] name = "darling" version = "0.20.0" @@ -657,7 +667,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c07c315e106bd6f83f026a20ddaeef2706782e490db1dcdd37caad38a0e895b3" dependencies = [ "scopeguard", - "winapi", + "winapi 0.3.9", ] [[package]] @@ -668,7 +678,7 @@ checksum = "01b1af8d6d068ba9de1c39c6ff0d879aed20f74873d4d3929a4535000bb07886" dependencies = [ "libc", "match_cfg", - "winapi", + "winapi 0.3.9", ] [[package]] @@ -749,7 +759,7 @@ dependencies = [ "pin-project-lite", "tokio", "tower-service", - "winapi", + "winapi 0.3.9", ] [[package]] @@ -835,7 +845,7 @@ dependencies = [ "core-foundation-sys", "js-sys", "wasm-bindgen", - "winapi", + "winapi 0.3.9", ] [[package]] @@ -884,7 +894,7 @@ checksum = "723519edce41262b05d4143ceb95050e4c614f483e78e9fd9e39a8275a84ad98" dependencies = [ "socket2 0.4.0", "widestring", - "winapi", + "winapi 0.3.9", "winreg 0.7.0", ] @@ -926,11 +936,27 @@ dependencies = [ "wasm-bindgen", ] +[[package]] +name = "kernel32-sys" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ad1ca084b49bfd975182288e1a5f1d27ea34ff2d6ae084ae5e66e1652427eada" +dependencies = [ + "winapi 0.2.8", + "winapi-build", +] + [[package]] name = "lazy_static" -version = "1.0.0" +version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c8f31047daa365f19be14b47c29df4f7c3b581832407daabe6ae77397619237d" +checksum = "4f9e1e434b35b61b6422b19998d5c219f6b4a90aae841583444b44077adb953b" + +[[package]] +name = "lazy_static" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fb497c35d362b6a331cfd94956a07fc2c78a4604cdbee844a81170386b996dd3" [[package]] name = "lenient_semver" @@ -1112,6 +1138,8 @@ dependencies = [ "paste", "pin-project-lite", "pretty_env_logger", + "rustls-native-certs", + "rustls-pemfile", "serde", "serde_bytes", "serde_json", @@ -1127,7 +1155,6 @@ dependencies = [ "tokio-rustls 0.26.0", "url", "uuid", - "webpki-roots", ] [[package]] @@ -1682,9 +1709,9 @@ dependencies = [ [[package]] name = "rustls-native-certs" -version = "0.7.0" +version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f1fb85efa936c42c6d5fc28d2629bb51e4b2f4b8a5211e297d599cc5a093792" +checksum = "a88d6d420651b496bdd98684116959239430022a115c1240e6c3993be0b15fba" dependencies = [ "openssl-probe", "rustls-pemfile", @@ -1695,19 +1722,19 @@ dependencies = [ [[package]] name = "rustls-pemfile" -version = "2.0.0" +version = "2.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "35e4980fa29e4c4b212ffb3db068a564cbf560e51d3944b7c88bd8bf5bec64f4" +checksum = "29993a25686778eb88d4189742cd713c9bce943bc54251a33509dc63cbacf73d" dependencies = [ - "base64 0.21.7", + "base64 0.22.0", "rustls-pki-types", ] [[package]] name = "rustls-pki-types" -version = "1.2.0" +version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0a716eb65e3158e90e17cd93d855216e27bde02745ab842f2cab4a39dba1bacf" +checksum = "048a63e5b3ac996d78d402940b5fa47973d2d080c6c6fffa1d0f19c4445310b7" [[package]] name = "rustls-webpki" @@ -1737,12 +1764,15 @@ dependencies = [ [[package]] name = "schannel" -version = "0.1.15" +version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f2f6abf258d99c3c1c5c2131d99d064e94b7b3dd5f416483057f308fea253339" +checksum = "4183ac471f97fe3e84803e81e40eba6612db22354095321a84000f495845bb09" dependencies = [ - "lazy_static", - "winapi", + "crypt32-sys", + "kernel32-sys", + "lazy_static 0.2.0", + "secur32-sys", + "winapi 0.2.8", ] [[package]] @@ -1751,6 +1781,16 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd" +[[package]] +name = "secur32-sys" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f412dfa83308d893101dd59c10d6fda8283465976c28c287c5c855bf8d216bc" +dependencies = [ + "winapi 0.2.8", + "winapi-build", +] + [[package]] name = "security-framework" version = "2.11.0" @@ -1924,7 +1964,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9e3dfc207c526015c632472a77be09cf1b6e46866581aecae5cc38fb4235dea2" dependencies = [ "libc", - "winapi", + "winapi 0.3.9", ] [[package]] @@ -2394,9 +2434,9 @@ checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" [[package]] name = "wasm-bindgen" -version = "0.2.82" +version = "0.2.81" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fc7652e3f6c4706c8d9cd54832c4a4ccb9b5336e2c3bd154d5cccfbf1c1f5f7d" +checksum = "7c53b543413a17a202f4be280a7e5c62a1c69345f5de525ee64f8cfdbc954994" dependencies = [ "cfg-if 1.0.0", "wasm-bindgen-macro", @@ -2404,13 +2444,13 @@ dependencies = [ [[package]] name = "wasm-bindgen-backend" -version = "0.2.82" +version = "0.2.81" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "662cd44805586bd52971b9586b1df85cdbbd9112e4ef4d8f41559c334dc6ac3f" +checksum = "5491a68ab4500fa6b4d726bd67408630c3dbe9c4fe7bda16d5c82a1fd8c7340a" dependencies = [ "bumpalo", + "lazy_static 1.0.2", "log", - "once_cell", "proc-macro2", "quote", "syn 1.0.67", @@ -2431,9 +2471,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro" -version = "0.2.82" +version = "0.2.81" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b260f13d3012071dfb1512849c033b1925038373aea48ced3012c09df952c602" +checksum = "c441e177922bc58f1e12c022624b6216378e5febc2f0533e41ba443d505b80aa" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -2441,9 +2481,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.82" +version = "0.2.81" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5be8e654bdd9b79216c2929ab90721aa82faf65c48cdf08bdc4e7f51357b80da" +checksum = "7d94ac45fcf608c1f45ef53e748d35660f168490c10b23704c7779ab8f5c3048" dependencies = [ "proc-macro2", "quote", @@ -2454,9 +2494,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-shared" -version = "0.2.82" +version = "0.2.81" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6598dd0bd3c7d51095ff6531a5b23e02acdc81804e30d8f07afb77b7215a140a" +checksum = "6a89911bd99e5f3659ec4acf9c4d93b0a90fe4a2a11f15328472058edc5261be" [[package]] name = "web-sys" @@ -2493,6 +2533,12 @@ version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "15be6395051be4e41efeee975b7561b8c602ba30204bfa35fefa0f85582075b6" +[[package]] +name = "winapi" +version = "0.2.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "167dc9d6949a9b857f3451275e911c3f44255842c1f7a76f33c55103a909087a" + [[package]] name = "winapi" version = "0.3.9" @@ -2503,6 +2549,12 @@ dependencies = [ "winapi-x86_64-pc-windows-gnu", ] +[[package]] +name = "winapi-build" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2d315eee3b34aca4797b2da6b13ed88266e6d612562a0c46390af8299fc699bc" + [[package]] name = "winapi-i686-pc-windows-gnu" version = "0.4.0" @@ -2515,7 +2567,7 @@ version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4ccfbf554c6ad11084fb7517daca16cfdcaccbdadba4fc336f032a8b12c2ad80" dependencies = [ - "winapi", + "winapi 0.3.9", ] [[package]] @@ -2705,7 +2757,7 @@ version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0120db82e8a1e0b9fb3345a539c478767c0048d842860994d96113d5b667bd69" dependencies = [ - "winapi", + "winapi 0.3.9", ] [[package]] diff --git a/ci/Cargo.lock.msrv b/ci/Cargo.lock.msrv index b874e45..9c24c61 100644 --- a/ci/Cargo.lock.msrv +++ b/ci/Cargo.lock.msrv @@ -179,9 +179,9 @@ dependencies = [ [[package]] name = "cc" -version = "1.1.5" +version = "1.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "324c74f2155653c90b04f25b2a47a8a631360cb908f92a772695f430c7e31052" +checksum = "2aba8f4e9906c7ce3c73463f62a7f0c65183ada1a2d47e397cc8810827f9694f" [[package]] name = "cfg-if" @@ -742,7 +742,7 @@ dependencies = [ "http", "hyper", "hyper-util", - "rustls 0.23.11", + "rustls 0.23.12", "rustls-native-certs", "rustls-pki-types", "tokio", @@ -1022,13 +1022,14 @@ dependencies = [ [[package]] name = "mio" -version = "0.8.11" +version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a4a650543ca06a924e8b371db273b2756685faae30f8487da1b56505a8f78b0c" +checksum = "4569e456d394deccd22ce1c1913e6ea0e54519f577285001215d33557431afe4" dependencies = [ + "hermit-abi", "libc", "wasi", - "windows-sys 0.48.0", + "windows-sys 0.52.0", ] [[package]] @@ -1084,6 +1085,8 @@ dependencies = [ "paste", "pin-project-lite", "pretty_env_logger", + "rustls-native-certs", + "rustls-pemfile", "serde", "serde_bytes", "serde_json", @@ -1099,7 +1102,6 @@ dependencies = [ "tokio-rustls 0.26.0", "url", "uuid", - "webpki-roots", ] [[package]] @@ -1165,9 +1167,9 @@ dependencies = [ [[package]] name = "object" -version = "0.36.1" +version = "0.36.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "081b846d1d56ddfc18fdf1a922e4f6e07a11768ea1b92dec44e42b72712ccfce" +checksum = "3f203fa8daa7bb185f760ae12bd8e097f63d17041dcdcaf675ac54cdf863170e" dependencies = [ "memchr", ] @@ -1377,7 +1379,7 @@ dependencies = [ "quinn-proto", "quinn-udp", "rustc-hash", - "rustls 0.23.11", + "rustls 0.23.12", "thiserror", "tokio", "tracing", @@ -1393,7 +1395,7 @@ dependencies = [ "rand", "ring", "rustc-hash", - "rustls 0.23.11", + "rustls 0.23.12", "slab", "thiserror", "tinyvec", @@ -1402,14 +1404,13 @@ dependencies = [ [[package]] name = "quinn-udp" -version = "0.5.2" +version = "0.5.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9096629c45860fc7fb143e125eb826b5e721e10be3263160c7d60ca832cf8c46" +checksum = "8bffec3605b73c6f1754535084a85229fa8a30f86014e6c81aeec4abb68b0285" dependencies = [ "libc", "once_cell", "socket2", - "tracing", "windows-sys 0.52.0", ] @@ -1534,7 +1535,7 @@ dependencies = [ "percent-encoding", "pin-project-lite", "quinn", - "rustls 0.23.11", + "rustls 0.23.12", "rustls-native-certs", "rustls-pemfile", "rustls-pki-types", @@ -1606,9 +1607,9 @@ dependencies = [ [[package]] name = "rustls" -version = "0.23.11" +version = "0.23.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4828ea528154ae444e5a642dbb7d5623354030dc9822b83fd9bb79683c7399d0" +checksum = "c58f8c84392efc0a126acce10fa59ff7b3d2ac06ab451a33f2741989b806b044" dependencies = [ "once_cell", "ring", @@ -1649,9 +1650,9 @@ checksum = "976295e77ce332211c0d24d92c0e83e50f5c5f046d11082cea19f3df13a3562d" [[package]] name = "rustls-webpki" -version = "0.102.5" +version = "0.102.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f9a6fccd794a42c2c105b513a2f62bc3fd8f3ba57a4593677ceb0bd035164d78" +checksum = "8e6b52d4fda176fd835fdc55a835d4a89b8499cad995885a21149d5ad62f852e" dependencies = [ "ring", "rustls-pki-types", @@ -1909,9 +1910,9 @@ checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292" [[package]] name = "syn" -version = "2.0.71" +version = "2.0.72" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b146dcf730474b4bcd16c311627b31ede9ab149045db4d6088b3becaea046462" +checksum = "dc4b9b9bf2add8093d3f2c0204471e951b2285580335de42f9d2534f3ae7a8af" dependencies = [ "proc-macro2", "quote", @@ -1974,9 +1975,9 @@ dependencies = [ [[package]] name = "testcontainers" -version = "0.20.0" +version = "0.20.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cb74bff469141dfded423ce9b8aa47430bfd9058e8d8ddac4a7c0966da0025bb" +checksum = "725cbe485aafddfd8b2d01665937c95498d894c07fabd9c4e06a53c7da4ccc56" dependencies = [ "async-trait", "bollard", @@ -2078,28 +2079,27 @@ checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" [[package]] name = "tokio" -version = "1.38.1" +version = "1.39.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eb2caba9f80616f438e09748d5acda951967e1ea58508ef53d9c6402485a46df" +checksum = "d040ac2b29ab03b09d4129c2f5bbd012a3ac2f79d38ff506a4bf8dd34b0eac8a" dependencies = [ "backtrace", "bytes", "libc", "mio", - "num_cpus", "parking_lot", "pin-project-lite", "signal-hook-registry", "socket2", "tokio-macros", - "windows-sys 0.48.0", + "windows-sys 0.52.0", ] [[package]] name = "tokio-macros" -version = "2.3.0" +version = "2.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f5ae998a069d4b5aba8ee9dad856af7d520c3699e6159b185c2acd48155d39a" +checksum = "693d596312e88961bc67d7f1f97af8a70227d9f90c31bba5806eec004978d752" dependencies = [ "proc-macro2", "quote", @@ -2123,7 +2123,7 @@ version = "0.26.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0c7bc40d0e5a97695bb96e27995cd3a08538541b0a846f65bba7a359f36700d4" dependencies = [ - "rustls 0.23.11", + "rustls 0.23.12", "rustls-pki-types", "tokio", ] @@ -2372,9 +2372,9 @@ dependencies = [ [[package]] name = "wide" -version = "0.7.25" +version = "0.7.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2caba658a80831539b30698ae9862a72db6697dfdd7151e46920f5f2755c3ce2" +checksum = "901e8597c777fa042e9e245bd56c0dc4418c5db3f845b6ff94fbac732c6a0692" dependencies = [ "bytemuck", "safe_arch", diff --git a/lib/Cargo.toml b/lib/Cargo.toml index 8e5e627..2c8e111 100644 --- a/lib/Cargo.toml +++ b/lib/Cargo.toml @@ -37,13 +37,14 @@ nav-types = { version = "0.5.2", optional = true } neo4rs-macros = { version = "0.3.0", path = "../macros" } paste = "1.0.0" pin-project-lite = "0.2.9" +rustls-native-certs = "0.7.1" +rustls-pemfile = "2.1.2" serde = { version = "1.0.185", features = ["derive"] } # TODO: eliminate derive serde_json = { version = "1.0.0", optional = true } thiserror = "1.0.7" time = { version = "0.3.22", optional = true } tokio = { version = "1.5.0", features = ["full"] } url = "2.0.0" -webpki-roots = "0.26.0" [dependencies.chrono] version = "0.4.35" diff --git a/lib/src/auth/mod.rs b/lib/src/auth/mod.rs new file mode 100644 index 0000000..f8a36bc --- /dev/null +++ b/lib/src/auth/mod.rs @@ -0,0 +1,14 @@ +use std::path::{Path, PathBuf}; + +#[derive(Debug, Clone)] +pub struct ClientCertificate { + pub(crate) cert_file: PathBuf, +} + +impl ClientCertificate { + pub fn new(path: impl AsRef) -> Self { + ClientCertificate { + cert_file: path.as_ref().to_path_buf(), + } + } +} diff --git a/lib/src/config.rs b/lib/src/config.rs index 592a6f5..f154f4b 100644 --- a/lib/src/config.rs +++ b/lib/src/config.rs @@ -1,4 +1,6 @@ +use crate::auth::ClientCertificate; use crate::errors::{Error, Result}; +use std::path::Path; use std::{ops::Deref, sync::Arc}; const DEFAULT_DATABASE: &str = "neo4j"; @@ -58,6 +60,7 @@ pub struct Config { pub(crate) max_connections: usize, pub(crate) db: Database, pub(crate) fetch_size: usize, + pub(crate) client_certificate: Option, } impl Config { @@ -77,6 +80,7 @@ pub struct ConfigBuilder { db: Database, fetch_size: usize, max_connections: usize, + client_certificate: Option, } impl ConfigBuilder { @@ -128,6 +132,11 @@ impl ConfigBuilder { self } + pub fn with_client_certificate(mut self, client_cert: impl AsRef) -> Self { + self.client_certificate = Some(ClientCertificate::new(client_cert)); + self + } + pub fn build(self) -> Result { if let (Some(uri), Some(user), Some(password)) = (self.uri, self.user, self.password) { Ok(Config { @@ -137,6 +146,7 @@ impl ConfigBuilder { fetch_size: self.fetch_size, max_connections: self.max_connections, db: self.db, + client_certificate: self.client_certificate, }) } else { Err(Error::InvalidConfig) @@ -153,6 +163,7 @@ impl Default for ConfigBuilder { db: DEFAULT_DATABASE.into(), max_connections: DEFAULT_MAX_CONNECTIONS, fetch_size: DEFAULT_FETCH_SIZE, + client_certificate: None, } } } @@ -178,6 +189,7 @@ mod tests { assert_eq!(&*config.db, "some_db"); assert_eq!(config.fetch_size, 10); assert_eq!(config.max_connections, 5); + assert!(config.client_certificate.is_none()); } #[test] @@ -194,6 +206,7 @@ mod tests { assert_eq!(&*config.db, "neo4j"); assert_eq!(config.fetch_size, 200); assert_eq!(config.max_connections, 16); + assert!(config.client_certificate.is_none()); } #[test] diff --git a/lib/src/connection.rs b/lib/src/connection.rs index 821d1a1..04f87bb 100644 --- a/lib/src/connection.rs +++ b/lib/src/connection.rs @@ -1,3 +1,4 @@ +use crate::auth::ClientCertificate; #[cfg(feature = "unstable-bolt-protocol-impl-v2")] use crate::bolt::{ExpectedResponse, Message, MessageResponse}; use crate::{ @@ -6,12 +7,16 @@ use crate::{ version::Version, }; use bytes::{Bytes, BytesMut}; +use log::warn; +use std::fs::File; +use std::io::BufReader; use std::{mem, sync::Arc}; use stream::ConnectionStream; use tokio::{ io::{AsyncReadExt, AsyncWriteExt, BufStream}, net::TcpStream, }; +use tokio_rustls::client::TlsStream; use tokio_rustls::{ rustls::{ pki_types::{IpAddr, Ipv4Addr, Ipv6Addr, ServerName}, @@ -39,7 +44,20 @@ impl Connection { match info.encryption { Encryption::No => Self::new_unencrypted(stream, &info.user, &info.password).await, - Encryption::Tls => Self::new_tls(stream, &info.host, &info.user, &info.password).await, + Encryption::Tls => { + if let Some(certificate) = info.client_certificate.as_ref() { + Self::new_tls_with_certificate( + stream, + &info.host, + &info.user, + &info.password, + certificate, + ) + .await + } else { + Self::new_tls(stream, &info.host, &info.user, &info.password).await + } + } } } @@ -53,9 +71,48 @@ impl Connection { user: &str, password: &str, ) -> Result { + let root_cert_store = Self::build_cert_store(); + let stream = Self::build_stream(stream, host, root_cert_store).await?; + + Self::init(user, password, stream).await + } + + async fn new_tls_with_certificate>( + stream: TcpStream, + host: &Host, + user: &str, + password: &str, + certificate: &ClientCertificate, + ) -> Result { + let mut root_cert_store = Self::build_cert_store(); + + let cert_file = File::open(certificate.cert_file.as_os_str())?; + let mut reader = BufReader::new(cert_file); + let certs = rustls_pemfile::certs(&mut reader).flatten(); + root_cert_store.add_parsable_certificates(certs); + + let stream = Self::build_stream(stream, host, root_cert_store).await?; + Self::init(user, password, stream).await + } + + fn build_cert_store() -> RootCertStore { let mut root_cert_store = RootCertStore::empty(); - root_cert_store.extend(webpki_roots::TLS_SERVER_ROOTS.iter().map(ToOwned::to_owned)); + match rustls_native_certs::load_native_certs() { + Ok(certs) => { + root_cert_store.add_parsable_certificates(certs); + } + Err(e) => { + warn!("Failed to load native certificates: {e}"); + } + } + root_cert_store + } + async fn build_stream>( + stream: TcpStream, + host: &Host, + root_cert_store: RootCertStore, + ) -> Result, Error> { let config = ClientConfig::builder() .with_root_certificates(root_cert_store) .with_no_client_auth(); @@ -71,8 +128,7 @@ impl Connection { }; let stream = connector.connect(domain, stream).await?; - - Self::init(user, password, stream).await + Ok(stream) } async fn init( @@ -212,6 +268,7 @@ pub(crate) struct ConnectionInfo { host: Host>, port: u16, encryption: Encryption, + client_certificate: Option, } enum Encryption { @@ -220,7 +277,12 @@ enum Encryption { } impl ConnectionInfo { - pub(crate) fn new(uri: &str, user: &str, password: &str) -> Result { + pub(crate) fn new( + uri: &str, + user: &str, + password: &str, + client_certificate: Option<&ClientCertificate>, + ) -> Result { let url = NeoUrl::parse(uri)?; let port = url.port(); let host = url.host(); @@ -242,6 +304,14 @@ impl ConnectionInfo { )); Encryption::Tls } + "neo4j+ssc" => { + log::warn!(concat!( + "This driver does not yet implement client-side routing. ", + "It is possible that operations against a cluster (such as Aura) will fail." + )); + Encryption::Tls + } + "bolt+ssc" => Encryption::Tls, otherwise => return Err(Error::UnsupportedScheme(otherwise.to_owned())), }; @@ -255,6 +325,7 @@ impl ConnectionInfo { }, port, encryption, + client_certificate: client_certificate.cloned(), }) } } diff --git a/lib/src/lib.rs b/lib/src/lib.rs index f7f45fb..0b2243d 100644 --- a/lib/src/lib.rs +++ b/lib/src/lib.rs @@ -421,6 +421,7 @@ //! ``` //! //! +mod auth; #[cfg(feature = "unstable-bolt-protocol-impl-v2")] pub mod bolt; mod config; @@ -441,6 +442,7 @@ mod txn; mod types; mod version; +pub use crate::auth::ClientCertificate; pub use crate::config::{Config, ConfigBuilder, Database}; pub use crate::errors::*; pub use crate::graph::{query, Graph}; diff --git a/lib/src/pool.rs b/lib/src/pool.rs index 3985762..c91a9f7 100644 --- a/lib/src/pool.rs +++ b/lib/src/pool.rs @@ -1,3 +1,4 @@ +use crate::auth::ClientCertificate; use crate::{ config::Config, connection::{Connection, ConnectionInfo}, @@ -14,8 +15,13 @@ pub struct ConnectionManager { } impl ConnectionManager { - pub fn new(uri: &str, user: &str, password: &str) -> Result { - let info = ConnectionInfo::new(uri, user, password)?; + pub fn new( + uri: &str, + user: &str, + password: &str, + client_certificate: Option<&ClientCertificate>, + ) -> Result { + let info = ConnectionInfo::new(uri, user, password, client_certificate)?; Ok(ConnectionManager { info }) } } @@ -35,7 +41,12 @@ impl Manager for ConnectionManager { } pub async fn create_pool(config: &Config) -> Result { - let mgr = ConnectionManager::new(&config.uri, &config.user, &config.password)?; + let mgr = ConnectionManager::new( + &config.uri, + &config.user, + &config.password, + config.client_certificate.as_ref(), + )?; info!( "creating connection pool with max size {}", config.max_connections