From fd8f35d3515b90816f1a3876aeaec9c565043bac Mon Sep 17 00:00:00 2001 From: Alec Embke Date: Mon, 29 Apr 2024 19:20:54 -0700 Subject: [PATCH] 9.0.2 (#242) * feat: support rustls/ring backend --------- Co-authored-by: Lucas Kent --- .circleci/config.yml | 19 + CHANGELOG.md | 4 + Cargo.toml | 19 +- README.md | 3 +- bin/benchmark/src/_fred.rs | 14 +- bin/benchmark/src/main.rs | 26 +- examples/tls.rs | 17 +- src/error.rs | 29 +- src/lib.rs | 15 +- src/protocol/cluster.rs | 336 +++++++++++++----- src/protocol/connection.rs | 46 +-- src/protocol/mod.rs | 6 +- src/protocol/tls.rs | 40 ++- src/protocol/types.rs | 78 +++- src/router/sentinel.rs | 6 +- src/types/config.rs | 97 ++++- src/utils.rs | 33 +- .../runners/bash/cluster-rustls-ring.sh | 19 + .../runners/compose/cluster-rustls-ring.yml | 30 ++ tests/integration/utils.rs | 99 ++++-- tests/runners/cluster-rustls-ring.sh | 4 + 21 files changed, 702 insertions(+), 238 deletions(-) create mode 100755 tests/docker/runners/bash/cluster-rustls-ring.sh create mode 100644 tests/docker/runners/compose/cluster-rustls-ring.yml create mode 100755 tests/runners/cluster-rustls-ring.sh diff --git a/.circleci/config.yml b/.circleci/config.yml index 82a9b453..aac03bf0 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -95,6 +95,14 @@ commands: name: Run cluster tests with rustls features command: source tests/environ && tests/scripts/tls-creds.sh && tests/runners/cluster-rustls.sh - save-cargo-deps-cache + test_rustls_cluster_ring: + steps: + - checkout + - restore-cargo-deps-cache + - run: + name: Run cluster tests with rustls/ring features + command: source tests/environ && tests/scripts/tls-creds.sh && tests/runners/cluster-rustls-ring.sh + - save-cargo-deps-cache test_default_nil_types_features: steps: - checkout @@ -199,6 +207,16 @@ jobs: FRED_CI_TLS: true steps: - test_rustls_cluster + test-cluster-rustls-ring-features-7_2: + machine: + image: ubuntu-2204:2022.10.2 + docker_layer_caching: true + resource_class: medium + environment: + REDIS_VERSION: 7.2.4 + FRED_CI_TLS: true + steps: + - test_rustls_cluster_ring test-sentinel-7_2: machine: image: ubuntu-2204:2022.10.2 @@ -265,5 +283,6 @@ workflows: - test-misc - test-cluster-tls-features-7_2 - test-cluster-rustls-features-7_2 + - test-cluster-rustls-ring-features-7_2 - clippy-lint - check-all-interface-features \ No newline at end of file diff --git a/CHANGELOG.md b/CHANGELOG.md index 8c0cfcf6..8ea165c8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,7 @@ +## 9.0.2 + +* Add `enable-rustls-ring` feature flag + ## 9.0.1 * Fix `partial-tracing` imports diff --git a/Cargo.toml b/Cargo.toml index ebd7148c..f329aa77 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "fred" -version = "9.0.1" +version = "9.0.2" authors = ["Alec Embke "] edition = "2021" description = "An async Redis client built on Tokio." @@ -36,14 +36,14 @@ semver = "1.0" socket2 = "0.5" urlencoding = "2.1" crossbeam-queue = "0.3" -rustls = { version = "0.23", optional = true } +rustls = { version = "0.23", optional = true, default-features = false } native-tls = { version = "0.2", optional = true } tokio-native-tls = { version = "0.3", optional = true } tracing = { version = "0.1", optional = true } tracing-futures = { version = "0.2", optional = true } nom = { version = "7.1", optional = true } serde_json = { version = "1", optional = true } -tokio-rustls = { version = "0.26", optional = true } +tokio-rustls = { version = "0.26", optional = true, default-features = false } rustls-native-certs = { version = "0.7", optional = true } trust-dns-resolver = { version = "0.23", optional = true } async-trait = { version = "0.1" } @@ -122,7 +122,18 @@ subscriber-client = ["i-pubsub"] metrics = [] mocks = [] dns = ["trust-dns-resolver", "trust-dns-resolver/tokio"] -enable-rustls = ["rustls", "tokio-rustls", "rustls-native-certs"] +# Enables rustls with the rustls/aws_lc_rs crypto backend +enable-rustls = [ + "rustls", "tokio-rustls", "rustls-native-certs", + "rustls/std", "tokio-rustls/logging", "tokio-rustls/tls12", + "tokio-rustls/aws_lc_rs" +] +# Enables rustls with the rustls/ring backend +enable-rustls-ring = [ + "rustls", "tokio-rustls", "rustls-native-certs", + "rustls/std", "tokio-rustls/logging", "tokio-rustls/tls12", + "tokio-rustls/ring" +] enable-native-tls = ["native-tls", "tokio-native-tls"] vendored-openssl = ["enable-native-tls", "native-tls/vendored"] full-tracing = ["partial-tracing"] diff --git a/README.md b/README.md index 7932e01e..aa250c5f 100644 --- a/README.md +++ b/README.md @@ -68,7 +68,8 @@ See the [examples](https://github.com/aembke/fred.rs/tree/main/examples) for mor |---------------------------|---------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------| | `transactions` | x | Enable a [Transaction](https://redis.io/docs/interact/transactions/) interface. | | `enable-native-tls` | | Enable TLS support via [native-tls](https://crates.io/crates/native-tls). | -| `enable-rustls` | | Enable TLS support via [rustls](https://crates.io/crates/rustls). | +| `enable-rustls` | | Enable TLS support via [rustls](https://crates.io/crates/rustls) with the default crypto backend features. | +| `enable-rustls-ring` | | Enable TLS support via [rustls](https://crates.io/crates/rustls) and the ring crypto backend. | | `vendored-openssl` | | Enable the `native-tls/vendored` feature. | | `metrics` | | Enable the metrics interface to track overall latency, network latency, and request/response sizes. | | `full-tracing` | | Enable full [tracing](./src/trace/README.md) support. This can emit a lot of data. | diff --git a/bin/benchmark/src/_fred.rs b/bin/benchmark/src/_fred.rs index 41abddf1..ffc607ed 100644 --- a/bin/benchmark/src/_fred.rs +++ b/bin/benchmark/src/_fred.rs @@ -8,7 +8,11 @@ use std::{ }; use tokio::task::JoinHandle; -#[cfg(any(feature = "enable-rustls", feature = "enable-native-tls"))] +#[cfg(any( + feature = "enable-rustls", + feature = "enable-native-tls", + feature = "enabled-rustls-ring" +))] use fred::types::{TlsConfig, TlsConnector, TlsHostMapping}; use futures::TryStreamExt; @@ -45,7 +49,11 @@ pub async fn init(argv: &Arc) -> Result { }, username, password: argv.auth.clone().or(password), - #[cfg(any(feature = "enable-native-tls", feature = "enable-rustls"))] + #[cfg(any( + feature = "enable-native-tls", + feature = "enable-rustls", + feature = "enable-rustls-ring" + ))] tls: default_tls_config(), #[cfg(any(feature = "stdout-tracing", feature = "partial-tracing", feature = "full-tracing"))] tracing: TracingConfig::new(argv.tracing), @@ -114,7 +122,7 @@ pub async fn run(argv: Arc, counter: Arc, bar: Option, - pub host: String, - pub port: u16, + pub tracing: bool, + pub count: usize, + pub tasks: usize, + pub unix: Option, + pub host: String, + pub port: u16, pub pipeline: bool, - pub pool: usize, - pub quiet: bool, - pub auth: Option, + pub pool: usize, + pub quiet: bool, + pub auth: Option, } fn parse_argv() -> Arc { diff --git a/examples/tls.rs b/examples/tls.rs index c27cd953..ce99c2f3 100644 --- a/examples/tls.rs +++ b/examples/tls.rs @@ -3,7 +3,11 @@ use fred::prelude::*; -#[cfg(any(feature = "enable-native-tls", feature = "enable-rustls"))] +#[cfg(any( + feature = "enable-native-tls", + feature = "enable-rustls", + feature = "enable-rustls-ring" +))] use fred::types::TlsConnector; #[cfg(feature = "enable-native-tls")] @@ -20,7 +24,10 @@ fn create_tls_config() -> TlsConnector { .into() } -#[cfg(all(feature = "enable-rustls", not(feature = "enable-native-tls")))] +#[cfg(all( + any(feature = "enable-rustls", feature = "enable-rustls-ring"), + not(feature = "enable-native-tls") +))] fn create_tls_config() -> TlsConnector { use fred::rustls::{ClientConfig, RootCertStore}; @@ -34,7 +41,11 @@ fn create_tls_config() -> TlsConnector { #[tokio::main] async fn main() -> Result<(), RedisError> { let config = RedisConfig { - #[cfg(any(feature = "enable-rustls", feature = "enable-native-tls"))] + #[cfg(any( + feature = "enable-rustls", + feature = "enable-native-tls", + feature = "enable-rustls-ring" + ))] tls: Some(create_tls_config().into()), ..RedisConfig::default() }; diff --git a/src/error.rs b/src/error.rs index fc67eb3f..adf551af 100644 --- a/src/error.rs +++ b/src/error.rs @@ -38,8 +38,19 @@ pub enum RedisErrorKind { /// A protocol error such as an invalid or unexpected frame from the server. Protocol, /// A TLS error. - #[cfg(any(feature = "enable-native-tls", feature = "enable-rustls"))] - #[cfg_attr(docsrs, doc(cfg(any(feature = "enable-native-tls", feature = "enable-rustls"))))] + #[cfg(any( + feature = "enable-native-tls", + feature = "enable-rustls", + feature = "enable-rustls-ring" + ))] + #[cfg_attr( + docsrs, + doc(cfg(any( + feature = "enable-native-tls", + feature = "enable-rustls", + feature = "enable-rustls-ring" + ))) + )] Tls, /// An error indicating the request was canceled. Canceled, @@ -78,7 +89,11 @@ impl RedisErrorKind { RedisErrorKind::Canceled => "Canceled", RedisErrorKind::Cluster => "Cluster Error", RedisErrorKind::Timeout => "Timeout Error", - #[cfg(any(feature = "enable-native-tls", feature = "enable-rustls"))] + #[cfg(any( + feature = "enable-native-tls", + feature = "enable-rustls", + feature = "enable-rustls-ring" + ))] RedisErrorKind::Tls => "TLS Error", RedisErrorKind::Config => "Config Error", RedisErrorKind::Parse => "Parse Error", @@ -275,8 +290,8 @@ impl From for RedisError { } #[doc(hidden)] -#[cfg(feature = "enable-rustls")] -#[cfg_attr(docsrs, doc(cfg(feature = "enable-rustls")))] +#[cfg(any(feature = "enable-rustls", feature = "enable-rustls-ring"))] +#[cfg_attr(docsrs, doc(cfg(any(feature = "enable-rustls", feature = "enable-rustls-ring"))))] impl From for RedisError { fn from(e: rustls::pki_types::InvalidDnsNameError) -> Self { RedisError::new(RedisErrorKind::Tls, format!("{:?}", e)) @@ -284,8 +299,8 @@ impl From for RedisError { } #[doc(hidden)] -#[cfg(feature = "enable-rustls")] -#[cfg_attr(docsrs, doc(cfg(feature = "enable-rustls")))] +#[cfg(any(feature = "enable-rustls", feature = "enable-rustls-ring"))] +#[cfg_attr(docsrs, doc(cfg(any(feature = "enable-rustls", feature = "enable-rustls-ring"))))] impl From for RedisError { fn from(e: rustls::Error) -> Self { RedisError::new(RedisErrorKind::Tls, format!("{:?}", e)) diff --git a/src/lib.rs b/src/lib.rs index 2c78517d..869fb470 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -160,7 +160,18 @@ pub mod prelude { }, }; - #[cfg(any(feature = "enable-native-tls", feature = "enable-rustls"))] - #[cfg_attr(docsrs, doc(cfg(any(feature = "enable-rustls", feature = "enable-native-tls"))))] + #[cfg(any( + feature = "enable-native-tls", + feature = "enable-rustls", + feature = "enable-rustls-ring" + ))] + #[cfg_attr( + docsrs, + doc(cfg(any( + feature = "enable-rustls", + feature = "enable-native-tls", + feature = "enable-rustls-ring" + ))) + )] pub use crate::types::{TlsConfig, TlsConnector}; } diff --git a/src/protocol/cluster.rs b/src/protocol/cluster.rs index 66129c6e..cf4fce55 100644 --- a/src/protocol/cluster.rs +++ b/src/protocol/cluster.rs @@ -8,7 +8,11 @@ use crate::{ use bytes_utils::Str; use std::{collections::HashMap, net::IpAddr, str::FromStr, sync::Arc}; -#[cfg(any(feature = "enable-native-tls", feature = "enable-rustls"))] +#[cfg(any( + feature = "enable-native-tls", + feature = "enable-rustls", + feature = "enable-rustls-ring" +))] use crate::protocol::tls::TlsHostMapping; fn parse_as_u16(value: RedisValue) -> Result { @@ -135,7 +139,11 @@ fn parse_cluster_slot_replica_nodes(slot_range: Vec, default_host: & Some(Server { host, port, - #[cfg(any(feature = "enable-native-tls", feature = "enable-rustls"))] + #[cfg(any( + feature = "enable-native-tls", + feature = "enable-rustls", + feature = "enable-rustls-ring" + ))] tls_server_name: None, }) }) @@ -176,7 +184,11 @@ fn parse_cluster_slot_nodes(mut slot_range: Vec, default_host: &Str) primary: Server { host, port, - #[cfg(any(feature = "enable-native-tls", feature = "enable-rustls"))] + #[cfg(any( + feature = "enable-native-tls", + feature = "enable-rustls", + feature = "enable-rustls-ring" + ))] tls_server_name: None, }, #[cfg(feature = "replicas")] @@ -198,7 +210,11 @@ pub fn parse_cluster_slots(frame: RedisValue, default_host: &Str) -> Result, ranges: &mut [SlotRange], default_host: &Str) { let policy = match inner.config.tls { Some(ref config) => &config.hostnames, @@ -228,7 +248,11 @@ pub fn modify_cluster_slot_hostnames(inner: &Arc, ranges: &mut replace_tls_server_names(policy, ranges, default_host); } -#[cfg(not(any(feature = "enable-rustls", feature = "enable-native-tls")))] +#[cfg(not(any( + feature = "enable-rustls", + feature = "enable-native-tls", + feature = "enable-rustls-ring" +)))] pub fn modify_cluster_slot_hostnames(inner: &Arc, _: &mut Vec, _: &Str) { _trace!(inner, "Skip modifying TLS hostnames.") } @@ -236,15 +260,27 @@ pub fn modify_cluster_slot_hostnames(inner: &Arc, _: &mut Vec< #[cfg(test)] mod tests { use super::*; - #[cfg(any(feature = "enable-native-tls", feature = "enable-rustls"))] + #[cfg(any( + feature = "enable-native-tls", + feature = "enable-rustls", + feature = "enable-rustls-ring" + ))] use crate::protocol::tls::{HostMapping, TlsHostMapping}; use crate::protocol::types::SlotRange; - #[cfg(any(feature = "enable-native-tls", feature = "enable-rustls"))] + #[cfg(any( + feature = "enable-native-tls", + feature = "enable-rustls", + feature = "enable-rustls-ring" + ))] #[derive(Debug)] struct FakeHostMapper; - #[cfg(any(feature = "enable-native-tls", feature = "enable-rustls"))] + #[cfg(any( + feature = "enable-native-tls", + feature = "enable-rustls", + feature = "enable-rustls-ring" + ))] impl HostMapping for FakeHostMapper { fn map(&self, _: &IpAddr, _: &str) -> Option { Some("foobarbaz".into()) @@ -352,7 +388,11 @@ mod tests { } #[test] - #[cfg(any(feature = "enable-native-tls", feature = "enable-rustls"))] + #[cfg(any( + feature = "enable-native-tls", + feature = "enable-rustls", + feature = "enable-rustls-ring" + ))] fn should_modify_cluster_slot_hostnames_default_host_without_metadata() { let policy = TlsHostMapping::DefaultHost; let fake_data = fake_cluster_slots_without_metadata(); @@ -372,7 +412,11 @@ mod tests { } #[test] - #[cfg(any(feature = "enable-native-tls", feature = "enable-rustls"))] + #[cfg(any( + feature = "enable-native-tls", + feature = "enable-rustls", + feature = "enable-rustls-ring" + ))] fn should_not_modify_cluster_slot_hostnames_default_host_with_metadata() { let policy = TlsHostMapping::DefaultHost; let fake_data = fake_cluster_slots_with_metadata(); @@ -393,7 +437,11 @@ mod tests { } #[test] - #[cfg(any(feature = "enable-native-tls", feature = "enable-rustls"))] + #[cfg(any( + feature = "enable-native-tls", + feature = "enable-rustls", + feature = "enable-rustls-ring" + ))] fn should_modify_cluster_slot_hostnames_custom() { let policy = TlsHostMapping::Custom(Arc::new(FakeHostMapper)); let fake_data = fake_cluster_slots_without_metadata(); @@ -419,56 +467,80 @@ mod tests { let actual = parse_cluster_slots(input, &Str::from("bad-host")).expect("Failed to parse input"); let expected = vec![ SlotRange { - start: 0, - end: 5460, - primary: Server { + start: 0, + end: 5460, + primary: Server { host: "host-1.redis.example.com".into(), port: 30001, - #[cfg(any(feature = "enable-native-tls", feature = "enable-rustls"))] + #[cfg(any( + feature = "enable-native-tls", + feature = "enable-rustls", + feature = "enable-rustls-ring" + ))] tls_server_name: None, }, - id: "09dbe9720cda62f7865eabc5fd8857c5d2678366".into(), + id: "09dbe9720cda62f7865eabc5fd8857c5d2678366".into(), #[cfg(feature = "replicas")] - replicas: vec![Server { + replicas: vec![Server { host: "host-2.redis.example.com".into(), port: 30004, - #[cfg(any(feature = "enable-native-tls", feature = "enable-rustls"))] + #[cfg(any( + feature = "enable-native-tls", + feature = "enable-rustls", + feature = "enable-rustls-ring" + ))] tls_server_name: None, }], }, SlotRange { - start: 5461, - end: 10922, - primary: Server { + start: 5461, + end: 10922, + primary: Server { host: "host-3.redis.example.com".into(), port: 30002, - #[cfg(any(feature = "enable-native-tls", feature = "enable-rustls"))] + #[cfg(any( + feature = "enable-native-tls", + feature = "enable-rustls", + feature = "enable-rustls-ring" + ))] tls_server_name: None, }, - id: "c9d93d9f2c0c524ff34cc11838c2003d8c29e013".into(), + id: "c9d93d9f2c0c524ff34cc11838c2003d8c29e013".into(), #[cfg(feature = "replicas")] - replicas: vec![Server { + replicas: vec![Server { host: "host-4.redis.example.com".into(), port: 30005, - #[cfg(any(feature = "enable-native-tls", feature = "enable-rustls"))] + #[cfg(any( + feature = "enable-native-tls", + feature = "enable-rustls", + feature = "enable-rustls-ring" + ))] tls_server_name: None, }], }, SlotRange { - start: 10923, - end: 16383, - primary: Server { + start: 10923, + end: 16383, + primary: Server { host: "host-5.redis.example.com".into(), port: 30003, - #[cfg(any(feature = "enable-native-tls", feature = "enable-rustls"))] + #[cfg(any( + feature = "enable-native-tls", + feature = "enable-rustls", + feature = "enable-rustls-ring" + ))] tls_server_name: None, }, - id: "044ec91f325b7595e76dbcb18cc688b6a5b434a1".into(), + id: "044ec91f325b7595e76dbcb18cc688b6a5b434a1".into(), #[cfg(feature = "replicas")] - replicas: vec![Server { + replicas: vec![Server { host: "host-6.redis.example.com".into(), port: 30006, - #[cfg(any(feature = "enable-native-tls", feature = "enable-rustls"))] + #[cfg(any( + feature = "enable-native-tls", + feature = "enable-rustls", + feature = "enable-rustls-ring" + ))] tls_server_name: None, }], }, @@ -483,56 +555,80 @@ mod tests { let actual = parse_cluster_slots(input, &Str::from("bad-host")).expect("Failed to parse input"); let expected = vec![ SlotRange { - start: 0, - end: 5460, - primary: Server { + start: 0, + end: 5460, + primary: Server { host: "127.0.0.1".into(), port: 30001, - #[cfg(any(feature = "enable-native-tls", feature = "enable-rustls"))] + #[cfg(any( + feature = "enable-native-tls", + feature = "enable-rustls", + feature = "enable-rustls-ring" + ))] tls_server_name: None, }, - id: "09dbe9720cda62f7865eabc5fd8857c5d2678366".into(), + id: "09dbe9720cda62f7865eabc5fd8857c5d2678366".into(), #[cfg(feature = "replicas")] - replicas: vec![Server { + replicas: vec![Server { host: "127.0.0.1".into(), port: 30004, - #[cfg(any(feature = "enable-native-tls", feature = "enable-rustls"))] + #[cfg(any( + feature = "enable-native-tls", + feature = "enable-rustls", + feature = "enable-rustls-ring" + ))] tls_server_name: None, }], }, SlotRange { - start: 5461, - end: 10922, - primary: Server { + start: 5461, + end: 10922, + primary: Server { host: "127.0.0.1".into(), port: 30002, - #[cfg(any(feature = "enable-native-tls", feature = "enable-rustls"))] + #[cfg(any( + feature = "enable-native-tls", + feature = "enable-rustls", + feature = "enable-rustls-ring" + ))] tls_server_name: None, }, - id: "c9d93d9f2c0c524ff34cc11838c2003d8c29e013".into(), + id: "c9d93d9f2c0c524ff34cc11838c2003d8c29e013".into(), #[cfg(feature = "replicas")] - replicas: vec![Server { + replicas: vec![Server { host: "127.0.0.1".into(), port: 30005, - #[cfg(any(feature = "enable-native-tls", feature = "enable-rustls"))] + #[cfg(any( + feature = "enable-native-tls", + feature = "enable-rustls", + feature = "enable-rustls-ring" + ))] tls_server_name: None, }], }, SlotRange { - start: 10923, - end: 16383, - primary: Server { + start: 10923, + end: 16383, + primary: Server { host: "127.0.0.1".into(), port: 30003, - #[cfg(any(feature = "enable-native-tls", feature = "enable-rustls"))] + #[cfg(any( + feature = "enable-native-tls", + feature = "enable-rustls", + feature = "enable-rustls-ring" + ))] tls_server_name: None, }, - id: "044ec91f325b7595e76dbcb18cc688b6a5b434a1".into(), + id: "044ec91f325b7595e76dbcb18cc688b6a5b434a1".into(), #[cfg(feature = "replicas")] - replicas: vec![Server { + replicas: vec![Server { host: "127.0.0.1".into(), port: 30006, - #[cfg(any(feature = "enable-native-tls", feature = "enable-rustls"))] + #[cfg(any( + feature = "enable-native-tls", + feature = "enable-rustls", + feature = "enable-rustls-ring" + ))] tls_server_name: None, }], }, @@ -595,56 +691,80 @@ mod tests { let actual = parse_cluster_slots(input, &Str::from("bad-host")).expect("Failed to parse input"); let expected = vec![ SlotRange { - start: 0, - end: 5460, - primary: Server { + start: 0, + end: 5460, + primary: Server { host: "127.0.0.1".into(), port: 30001, - #[cfg(any(feature = "enable-native-tls", feature = "enable-rustls"))] + #[cfg(any( + feature = "enable-native-tls", + feature = "enable-rustls", + feature = "enable-rustls-ring" + ))] tls_server_name: None, }, - id: "09dbe9720cda62f7865eabc5fd8857c5d2678366".into(), + id: "09dbe9720cda62f7865eabc5fd8857c5d2678366".into(), #[cfg(feature = "replicas")] - replicas: vec![Server { + replicas: vec![Server { host: "127.0.0.1".into(), port: 30004, - #[cfg(any(feature = "enable-native-tls", feature = "enable-rustls"))] + #[cfg(any( + feature = "enable-native-tls", + feature = "enable-rustls", + feature = "enable-rustls-ring" + ))] tls_server_name: None, }], }, SlotRange { - start: 5461, - end: 10922, - primary: Server { + start: 5461, + end: 10922, + primary: Server { host: "127.0.0.1".into(), port: 30002, - #[cfg(any(feature = "enable-native-tls", feature = "enable-rustls"))] + #[cfg(any( + feature = "enable-native-tls", + feature = "enable-rustls", + feature = "enable-rustls-ring" + ))] tls_server_name: None, }, - id: "c9d93d9f2c0c524ff34cc11838c2003d8c29e013".into(), + id: "c9d93d9f2c0c524ff34cc11838c2003d8c29e013".into(), #[cfg(feature = "replicas")] - replicas: vec![Server { + replicas: vec![Server { host: "127.0.0.1".into(), port: 30005, - #[cfg(any(feature = "enable-native-tls", feature = "enable-rustls"))] + #[cfg(any( + feature = "enable-native-tls", + feature = "enable-rustls", + feature = "enable-rustls-ring" + ))] tls_server_name: None, }], }, SlotRange { - start: 10923, - end: 16383, - primary: Server { + start: 10923, + end: 16383, + primary: Server { host: "127.0.0.1".into(), port: 30003, - #[cfg(any(feature = "enable-native-tls", feature = "enable-rustls"))] + #[cfg(any( + feature = "enable-native-tls", + feature = "enable-rustls", + feature = "enable-rustls-ring" + ))] tls_server_name: None, }, - id: "044ec91f325b7595e76dbcb18cc688b6a5b434a1".into(), + id: "044ec91f325b7595e76dbcb18cc688b6a5b434a1".into(), #[cfg(feature = "replicas")] - replicas: vec![Server { + replicas: vec![Server { host: "127.0.0.1".into(), port: 30006, - #[cfg(any(feature = "enable-native-tls", feature = "enable-rustls"))] + #[cfg(any( + feature = "enable-native-tls", + feature = "enable-rustls", + feature = "enable-rustls-ring" + ))] tls_server_name: None, }], }, @@ -707,56 +827,80 @@ mod tests { let actual = parse_cluster_slots(input, &Str::from("fake-host")).expect("Failed to parse input"); let expected = vec![ SlotRange { - start: 0, - end: 5460, - primary: Server { + start: 0, + end: 5460, + primary: Server { host: "fake-host".into(), port: 30001, - #[cfg(any(feature = "enable-native-tls", feature = "enable-rustls"))] + #[cfg(any( + feature = "enable-native-tls", + feature = "enable-rustls", + feature = "enable-rustls-ring" + ))] tls_server_name: None, }, - id: "09dbe9720cda62f7865eabc5fd8857c5d2678366".into(), + id: "09dbe9720cda62f7865eabc5fd8857c5d2678366".into(), #[cfg(feature = "replicas")] - replicas: vec![Server { + replicas: vec![Server { host: "fake-host".into(), port: 30004, - #[cfg(any(feature = "enable-native-tls", feature = "enable-rustls"))] + #[cfg(any( + feature = "enable-native-tls", + feature = "enable-rustls", + feature = "enable-rustls-ring" + ))] tls_server_name: None, }], }, SlotRange { - start: 5461, - end: 10922, - primary: Server { + start: 5461, + end: 10922, + primary: Server { host: "fake-host".into(), port: 30002, - #[cfg(any(feature = "enable-native-tls", feature = "enable-rustls"))] + #[cfg(any( + feature = "enable-native-tls", + feature = "enable-rustls", + feature = "enable-rustls-ring" + ))] tls_server_name: None, }, - id: "c9d93d9f2c0c524ff34cc11838c2003d8c29e013".into(), + id: "c9d93d9f2c0c524ff34cc11838c2003d8c29e013".into(), #[cfg(feature = "replicas")] - replicas: vec![Server { + replicas: vec![Server { host: "fake-host".into(), port: 30005, - #[cfg(any(feature = "enable-native-tls", feature = "enable-rustls"))] + #[cfg(any( + feature = "enable-native-tls", + feature = "enable-rustls", + feature = "enable-rustls-ring" + ))] tls_server_name: None, }], }, SlotRange { - start: 10923, - end: 16383, - primary: Server { + start: 10923, + end: 16383, + primary: Server { host: "fake-host".into(), port: 30003, - #[cfg(any(feature = "enable-native-tls", feature = "enable-rustls"))] + #[cfg(any( + feature = "enable-native-tls", + feature = "enable-rustls", + feature = "enable-rustls-ring" + ))] tls_server_name: None, }, - id: "044ec91f325b7595e76dbcb18cc688b6a5b434a1".into(), + id: "044ec91f325b7595e76dbcb18cc688b6a5b434a1".into(), #[cfg(feature = "replicas")] - replicas: vec![Server { + replicas: vec![Server { host: "fake-host".into(), port: 30006, - #[cfg(any(feature = "enable-native-tls", feature = "enable-rustls"))] + #[cfg(any( + feature = "enable-native-tls", + feature = "enable-rustls", + feature = "enable-rustls-ring" + ))] tls_server_name: None, }], }, diff --git a/src/protocol/connection.rs b/src/protocol/connection.rs index 568fb486..2bcd267e 100644 --- a/src/protocol/connection.rs +++ b/src/protocol/connection.rs @@ -34,7 +34,11 @@ use tokio_util::codec::Framed; #[cfg(feature = "unix-sockets")] use crate::prelude::ServerConfig; -#[cfg(any(feature = "enable-native-tls", feature = "enable-rustls"))] +#[cfg(any( + feature = "enable-native-tls", + feature = "enable-rustls", + feature = "enable-rustls-ring" +))] use crate::protocol::tls::TlsConnector; #[cfg(feature = "replicas")] use crate::{ @@ -44,7 +48,7 @@ use crate::{ #[cfg(feature = "unix-sockets")] use std::path::Path; use std::sync::atomic::AtomicBool; -#[cfg(feature = "enable-rustls")] +#[cfg(any(feature = "enable-rustls", feature = "enable-rustls-ring"))] use std::{convert::TryInto, ops::Deref}; #[cfg(feature = "unix-sockets")] use tokio::net::UnixStream; @@ -52,7 +56,7 @@ use tokio::net::UnixStream; use tokio::sync::oneshot::channel as oneshot_channel; #[cfg(feature = "enable-native-tls")] use tokio_native_tls::TlsStream as NativeTlsStream; -#[cfg(feature = "enable-rustls")] +#[cfg(any(feature = "enable-rustls", feature = "enable-rustls-ring"))] use tokio_rustls::client::TlsStream as RustlsStream; /// The contents of a simplestring OK response. @@ -162,7 +166,7 @@ pub enum ConnectionKind { Tcp(Framed), #[cfg(feature = "unix-sockets")] Unix(Framed), - #[cfg(feature = "enable-rustls")] + #[cfg(any(feature = "enable-rustls", feature = "enable-rustls-ring"))] Rustls(Framed, RedisCodec>), #[cfg(feature = "enable-native-tls")] NativeTls(Framed, RedisCodec>), @@ -181,7 +185,7 @@ impl ConnectionKind { let (sink, stream) = conn.split(); (SplitSinkKind::Unix(sink), SplitStreamKind::Unix(stream)) }, - #[cfg(feature = "enable-rustls")] + #[cfg(any(feature = "enable-rustls", feature = "enable-rustls-ring"))] ConnectionKind::Rustls(conn) => { let (sink, stream) = conn.split(); (SplitSinkKind::Rustls(sink), SplitStreamKind::Rustls(stream)) @@ -203,7 +207,7 @@ impl Stream for ConnectionKind { ConnectionKind::Tcp(ref mut conn) => Pin::new(conn).poll_next(cx), #[cfg(feature = "unix-sockets")] ConnectionKind::Unix(ref mut conn) => Pin::new(conn).poll_next(cx), - #[cfg(feature = "enable-rustls")] + #[cfg(any(feature = "enable-rustls", feature = "enable-rustls-ring"))] ConnectionKind::Rustls(ref mut conn) => Pin::new(conn).poll_next(cx), #[cfg(feature = "enable-native-tls")] ConnectionKind::NativeTls(ref mut conn) => Pin::new(conn).poll_next(cx), @@ -215,7 +219,7 @@ impl Stream for ConnectionKind { ConnectionKind::Tcp(ref conn) => conn.size_hint(), #[cfg(feature = "unix-sockets")] ConnectionKind::Unix(ref conn) => conn.size_hint(), - #[cfg(feature = "enable-rustls")] + #[cfg(any(feature = "enable-rustls", feature = "enable-rustls-ring"))] ConnectionKind::Rustls(ref conn) => conn.size_hint(), #[cfg(feature = "enable-native-tls")] ConnectionKind::NativeTls(ref conn) => conn.size_hint(), @@ -231,7 +235,7 @@ impl Sink for ConnectionKind { ConnectionKind::Tcp(ref mut conn) => Pin::new(conn).poll_ready(cx), #[cfg(feature = "unix-sockets")] ConnectionKind::Unix(ref mut conn) => Pin::new(conn).poll_ready(cx), - #[cfg(feature = "enable-rustls")] + #[cfg(any(feature = "enable-rustls", feature = "enable-rustls-ring"))] ConnectionKind::Rustls(ref mut conn) => Pin::new(conn).poll_ready(cx), #[cfg(feature = "enable-native-tls")] ConnectionKind::NativeTls(ref mut conn) => Pin::new(conn).poll_ready(cx), @@ -243,7 +247,7 @@ impl Sink for ConnectionKind { ConnectionKind::Tcp(ref mut conn) => Pin::new(conn).start_send(item), #[cfg(feature = "unix-sockets")] ConnectionKind::Unix(ref mut conn) => Pin::new(conn).start_send(item), - #[cfg(feature = "enable-rustls")] + #[cfg(any(feature = "enable-rustls", feature = "enable-rustls-ring"))] ConnectionKind::Rustls(ref mut conn) => Pin::new(conn).start_send(item), #[cfg(feature = "enable-native-tls")] ConnectionKind::NativeTls(ref mut conn) => Pin::new(conn).start_send(item), @@ -255,7 +259,7 @@ impl Sink for ConnectionKind { ConnectionKind::Tcp(ref mut conn) => Pin::new(conn).poll_flush(cx).map_err(|e| e), #[cfg(feature = "unix-sockets")] ConnectionKind::Unix(ref mut conn) => Pin::new(conn).poll_flush(cx).map_err(|e| e), - #[cfg(feature = "enable-rustls")] + #[cfg(any(feature = "enable-rustls", feature = "enable-rustls-ring"))] ConnectionKind::Rustls(ref mut conn) => Pin::new(conn).poll_flush(cx).map_err(|e| e), #[cfg(feature = "enable-native-tls")] ConnectionKind::NativeTls(ref mut conn) => Pin::new(conn).poll_flush(cx).map_err(|e| e), @@ -267,7 +271,7 @@ impl Sink for ConnectionKind { ConnectionKind::Tcp(ref mut conn) => Pin::new(conn).poll_close(cx).map_err(|e| e), #[cfg(feature = "unix-sockets")] ConnectionKind::Unix(ref mut conn) => Pin::new(conn).poll_close(cx).map_err(|e| e), - #[cfg(feature = "enable-rustls")] + #[cfg(any(feature = "enable-rustls", feature = "enable-rustls-ring"))] ConnectionKind::Rustls(ref mut conn) => Pin::new(conn).poll_close(cx).map_err(|e| e), #[cfg(feature = "enable-native-tls")] ConnectionKind::NativeTls(ref mut conn) => Pin::new(conn).poll_close(cx).map_err(|e| e), @@ -279,7 +283,7 @@ pub enum SplitStreamKind { Tcp(SplitRedisStream), #[cfg(feature = "unix-sockets")] Unix(SplitRedisStream), - #[cfg(feature = "enable-rustls")] + #[cfg(any(feature = "enable-rustls", feature = "enable-rustls-ring"))] Rustls(SplitRedisStream>), #[cfg(feature = "enable-native-tls")] NativeTls(SplitRedisStream>), @@ -293,7 +297,7 @@ impl Stream for SplitStreamKind { SplitStreamKind::Tcp(ref mut conn) => Pin::new(conn).poll_next(cx), #[cfg(feature = "unix-sockets")] SplitStreamKind::Unix(ref mut conn) => Pin::new(conn).poll_next(cx), - #[cfg(feature = "enable-rustls")] + #[cfg(any(feature = "enable-rustls", feature = "enable-rustls-ring"))] SplitStreamKind::Rustls(ref mut conn) => Pin::new(conn).poll_next(cx), #[cfg(feature = "enable-native-tls")] SplitStreamKind::NativeTls(ref mut conn) => Pin::new(conn).poll_next(cx), @@ -305,7 +309,7 @@ impl Stream for SplitStreamKind { SplitStreamKind::Tcp(ref conn) => conn.size_hint(), #[cfg(feature = "unix-sockets")] SplitStreamKind::Unix(ref conn) => conn.size_hint(), - #[cfg(feature = "enable-rustls")] + #[cfg(any(feature = "enable-rustls", feature = "enable-rustls-ring"))] SplitStreamKind::Rustls(ref conn) => conn.size_hint(), #[cfg(feature = "enable-native-tls")] SplitStreamKind::NativeTls(ref conn) => conn.size_hint(), @@ -317,7 +321,7 @@ pub enum SplitSinkKind { Tcp(SplitRedisSink), #[cfg(feature = "unix-sockets")] Unix(SplitRedisSink), - #[cfg(feature = "enable-rustls")] + #[cfg(any(feature = "enable-rustls", feature = "enable-rustls-ring"))] Rustls(SplitRedisSink>), #[cfg(feature = "enable-native-tls")] NativeTls(SplitRedisSink>), @@ -331,7 +335,7 @@ impl Sink for SplitSinkKind { SplitSinkKind::Tcp(ref mut conn) => Pin::new(conn).poll_ready(cx), #[cfg(feature = "unix-sockets")] SplitSinkKind::Unix(ref mut conn) => Pin::new(conn).poll_ready(cx), - #[cfg(feature = "enable-rustls")] + #[cfg(any(feature = "enable-rustls", feature = "enable-rustls-ring"))] SplitSinkKind::Rustls(ref mut conn) => Pin::new(conn).poll_ready(cx), #[cfg(feature = "enable-native-tls")] SplitSinkKind::NativeTls(ref mut conn) => Pin::new(conn).poll_ready(cx), @@ -343,7 +347,7 @@ impl Sink for SplitSinkKind { SplitSinkKind::Tcp(ref mut conn) => Pin::new(conn).start_send(item), #[cfg(feature = "unix-sockets")] SplitSinkKind::Unix(ref mut conn) => Pin::new(conn).start_send(item), - #[cfg(feature = "enable-rustls")] + #[cfg(any(feature = "enable-rustls", feature = "enable-rustls-ring"))] SplitSinkKind::Rustls(ref mut conn) => Pin::new(conn).start_send(item), #[cfg(feature = "enable-native-tls")] SplitSinkKind::NativeTls(ref mut conn) => Pin::new(conn).start_send(item), @@ -355,7 +359,7 @@ impl Sink for SplitSinkKind { SplitSinkKind::Tcp(ref mut conn) => Pin::new(conn).poll_flush(cx).map_err(|e| e), #[cfg(feature = "unix-sockets")] SplitSinkKind::Unix(ref mut conn) => Pin::new(conn).poll_flush(cx).map_err(|e| e), - #[cfg(feature = "enable-rustls")] + #[cfg(any(feature = "enable-rustls", feature = "enable-rustls-ring"))] SplitSinkKind::Rustls(ref mut conn) => Pin::new(conn).poll_flush(cx).map_err(|e| e), #[cfg(feature = "enable-native-tls")] SplitSinkKind::NativeTls(ref mut conn) => Pin::new(conn).poll_flush(cx).map_err(|e| e), @@ -367,7 +371,7 @@ impl Sink for SplitSinkKind { SplitSinkKind::Tcp(ref mut conn) => Pin::new(conn).poll_close(cx).map_err(|e| e), #[cfg(feature = "unix-sockets")] SplitSinkKind::Unix(ref mut conn) => Pin::new(conn).poll_close(cx).map_err(|e| e), - #[cfg(feature = "enable-rustls")] + #[cfg(any(feature = "enable-rustls", feature = "enable-rustls-ring"))] SplitSinkKind::Rustls(ref mut conn) => Pin::new(conn).poll_close(cx).map_err(|e| e), #[cfg(feature = "enable-native-tls")] SplitSinkKind::NativeTls(ref mut conn) => Pin::new(conn).poll_close(cx).map_err(|e| e), @@ -527,7 +531,7 @@ impl RedisTransport { RedisTransport::new_tcp(inner, server).await } - #[cfg(feature = "enable-rustls")] + #[cfg(any(feature = "enable-rustls", feature = "enable-rustls-ring"))] #[allow(unreachable_patterns)] pub async fn new_rustls(inner: &Arc, server: &Server) -> Result { use rustls::pki_types::ServerName; @@ -569,7 +573,7 @@ impl RedisTransport { }) } - #[cfg(not(feature = "enable-rustls"))] + #[cfg(not(any(feature = "enable-rustls", feature = "enable-rustls-ring")))] pub async fn new_rustls(inner: &Arc, server: &Server) -> Result { RedisTransport::new_tcp(inner, server).await } diff --git a/src/protocol/mod.rs b/src/protocol/mod.rs index 6364794b..09d8bc0f 100644 --- a/src/protocol/mod.rs +++ b/src/protocol/mod.rs @@ -7,7 +7,11 @@ pub mod debug; pub mod hashers; pub mod responders; /// TLS configuration types. -#[cfg(any(feature = "enable-rustls", feature = "enable-native-tls"))] +#[cfg(any( + feature = "enable-rustls", + feature = "enable-native-tls", + feature = "enable-rustls-ring" +))] pub mod tls; pub mod types; pub mod utils; diff --git a/src/protocol/tls.rs b/src/protocol/tls.rs index b0936cff..16cdbf9f 100644 --- a/src/protocol/tls.rs +++ b/src/protocol/tls.rs @@ -12,14 +12,13 @@ use crate::error::RedisErrorKind; use std::convert::{TryFrom, TryInto}; #[cfg(feature = "enable-native-tls")] use tokio_native_tls::native_tls::{ - TlsConnector as NativeTlsConnector, - TlsConnectorBuilder as NativeTlsConnectorBuilder, + TlsConnector as NativeTlsConnector, TlsConnectorBuilder as NativeTlsConnectorBuilder, }; #[cfg(feature = "enable-native-tls")] use tokio_native_tls::TlsConnector as TokioNativeTlsConnector; -#[cfg(feature = "enable-rustls")] +#[cfg(any(feature = "enable-rustls", feature = "enable-rustls-ring"))] use tokio_rustls::rustls::{ClientConfig as RustlsClientConfig, RootCertStore}; -#[cfg(feature = "enable-rustls")] +#[cfg(any(feature = "enable-rustls", feature = "enable-rustls-ring"))] use tokio_rustls::TlsConnector as RustlsConnector; /// A trait used for mapping IP addresses to hostnames when processing the `CLUSTER SLOTS` response. @@ -120,8 +119,8 @@ pub enum TlsConnector { #[cfg(feature = "enable-native-tls")] #[cfg_attr(docsrs, doc(cfg(feature = "enable-native-tls")))] Native(TokioNativeTlsConnector), - #[cfg(feature = "enable-rustls")] - #[cfg_attr(docsrs, doc(cfg(feature = "enable-rustls")))] + #[cfg(any(feature = "enable-rustls", feature = "enable-rustls-ring"))] + #[cfg_attr(docsrs, doc(cfg(any(feature = "enable-rustls", feature = "enable-rustls-ring"))))] Rustls(RustlsConnector), } @@ -136,12 +135,15 @@ impl Eq for TlsConnector {} impl Debug for TlsConnector { fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { f.debug_struct("TlsConnector") - .field("kind", match self { - #[cfg(feature = "enable-native-tls")] - TlsConnector::Native(_) => &"Native", - #[cfg(feature = "enable-rustls")] - TlsConnector::Rustls(_) => &"Rustls", - }) + .field( + "kind", + match self { + #[cfg(feature = "enable-native-tls")] + TlsConnector::Native(_) => &"Native", + #[cfg(any(feature = "enable-rustls", feature = "enable-rustls-ring"))] + TlsConnector::Rustls(_) => &"Rustls", + }, + ) .finish() } } @@ -156,8 +158,8 @@ impl TlsConnector { } /// Create a default TLS connector with the `rustls` module with safe defaults and system certs via [rustls-native-certs](https://github.com/rustls/rustls-native-certs). - #[cfg(feature = "enable-rustls")] - #[cfg_attr(docsrs, doc(cfg(feature = "enable-rustls")))] + #[cfg(any(feature = "enable-rustls", feature = "enable-rustls-ring"))] + #[cfg_attr(docsrs, doc(cfg(any(feature = "enable-rustls", feature = "enable-rustls-ring"))))] pub fn default_rustls() -> Result { let system_certs = rustls_native_certs::load_native_certs()?; let mut cert_store = RootCertStore::empty(); @@ -204,16 +206,16 @@ impl From for TlsConnector { } } -#[cfg(feature = "enable-rustls")] -#[cfg_attr(docsrs, doc(cfg(feature = "enable-rustls")))] +#[cfg(any(feature = "enable-rustls", feature = "enable-rustls-ring"))] +#[cfg_attr(docsrs, doc(cfg(any(feature = "enable-rustls", feature = "enable-rustls-ring"))))] impl From for TlsConnector { fn from(config: RustlsClientConfig) -> Self { TlsConnector::Rustls(RustlsConnector::from(Arc::new(config))) } } -#[cfg(feature = "enable-rustls")] -#[cfg_attr(docsrs, doc(cfg(feature = "enable-rustls")))] +#[cfg(any(feature = "enable-rustls", feature = "enable-rustls-ring"))] +#[cfg_attr(docsrs, doc(cfg(any(feature = "enable-rustls", feature = "enable-rustls-ring"))))] impl From for TlsConnector { fn from(connector: RustlsConnector) -> Self { TlsConnector::Rustls(connector) @@ -225,7 +227,7 @@ mod tests { use super::*; #[test] - #[cfg(feature = "enable-rustls")] + #[cfg(any(feature = "enable-rustls", feature = "enable-rustls-ring"))] fn should_create_default_rustls() { let _ = TlsConnector::default_rustls().unwrap(); } diff --git a/src/protocol/types.rs b/src/protocol/types.rs index b4692e80..43079397 100644 --- a/src/protocol/types.rs +++ b/src/protocol/types.rs @@ -22,7 +22,11 @@ use std::{ }; use tokio::sync::mpsc::UnboundedSender; -#[cfg(any(feature = "enable-rustls", feature = "enable-native-tls"))] +#[cfg(any( + feature = "enable-rustls", + feature = "enable-native-tls", + feature = "enable-rustls-ring" +))] use std::{net::IpAddr, str::FromStr}; /// Any kind of RESP frame. @@ -69,15 +73,37 @@ pub struct Server { /// The port for the server. pub port: u16, /// The server name used during the TLS handshake. - #[cfg(any(feature = "enable-rustls", feature = "enable-native-tls"))] - #[cfg_attr(docsrs, doc(cfg(any(feature = "enable-rustls", feature = "enable-native-tls"))))] + #[cfg(any( + feature = "enable-rustls", + feature = "enable-native-tls", + feature = "enable-rustls-ring" + ))] + #[cfg_attr( + docsrs, + doc(cfg(any( + feature = "enable-rustls", + feature = "enable-native-tls", + feature = "enable-rustls-ring" + ))) + )] pub tls_server_name: Option, } impl Server { /// Create a new `Server` from parts with a TLS server name. - #[cfg(any(feature = "enable-rustls", feature = "enable-native-tls"))] - #[cfg_attr(docsrs, doc(cfg(any(feature = "enable-rustls", feature = "enable-native-tls"))))] + #[cfg(any( + feature = "enable-rustls", + feature = "enable-native-tls", + feature = "enable-rustls-ring" + ))] + #[cfg_attr( + docsrs, + doc(cfg(any( + feature = "enable-rustls", + feature = "enable-native-tls", + feature = "enable-rustls-ring" + ))) + )] pub fn new_with_tls>(host: S, port: u16, tls_server_name: Option) -> Self { Server { host: host.into(), @@ -91,12 +117,20 @@ impl Server { Server { host: host.into(), port, - #[cfg(any(feature = "enable-rustls", feature = "enable-native-tls"))] + #[cfg(any( + feature = "enable-rustls", + feature = "enable-native-tls", + feature = "enable-rustls-ring" + ))] tls_server_name: None, } } - #[cfg(any(feature = "enable-rustls", feature = "enable-native-tls"))] + #[cfg(any( + feature = "enable-rustls", + feature = "enable-native-tls", + feature = "enable-rustls-ring" + ))] pub(crate) fn set_tls_server_name(&mut self, policy: &TlsHostMapping, default_host: &str) { if *policy == TlsHostMapping::None { return; @@ -119,7 +153,11 @@ impl Server { Some(Server { host: parts[0].into(), port, - #[cfg(any(feature = "enable-rustls", feature = "enable-native-tls"))] + #[cfg(any( + feature = "enable-rustls", + feature = "enable-native-tls", + feature = "enable-rustls-ring" + ))] tls_server_name: None, }) } else { @@ -142,7 +180,11 @@ impl Server { Server { host, port, - #[cfg(any(feature = "enable-rustls", feature = "enable-native-tls"))] + #[cfg(any( + feature = "enable-rustls", + feature = "enable-native-tls", + feature = "enable-rustls-ring" + ))] tls_server_name: None, } }) @@ -156,7 +198,11 @@ impl From<&std::path::Path> for Server { Server { host: utils::path_to_string(value).into(), port: 0, - #[cfg(any(feature = "enable-rustls", feature = "enable-native-tls"))] + #[cfg(any( + feature = "enable-rustls", + feature = "enable-native-tls", + feature = "enable-rustls-ring" + ))] tls_server_name: None, } } @@ -183,7 +229,11 @@ impl From<(String, u16)> for Server { Server { host: host.into(), port, - #[cfg(any(feature = "enable-native-tls", feature = "enable-rustls"))] + #[cfg(any( + feature = "enable-native-tls", + feature = "enable-rustls", + feature = "enable-rustls-ring" + ))] tls_server_name: None, } } @@ -194,7 +244,11 @@ impl From<(&str, u16)> for Server { Server { host: host.into(), port, - #[cfg(any(feature = "enable-native-tls", feature = "enable-rustls"))] + #[cfg(any( + feature = "enable-native-tls", + feature = "enable-rustls", + feature = "enable-rustls-ring" + ))] tls_server_name: None, } } diff --git a/src/router/sentinel.rs b/src/router/sentinel.rs index c0bf7c40..d47ee05a 100644 --- a/src/router/sentinel.rs +++ b/src/router/sentinel.rs @@ -217,7 +217,11 @@ async fn discover_primary_node( Server { host, port, - #[cfg(any(feature = "enable-rustls", feature = "enable-native-tls"))] + #[cfg(any( + feature = "enable-rustls", + feature = "enable-native-tls", + feature = "enable-rustls-ring" + ))] tls_server_name: None, } }; diff --git a/src/types/config.rs b/src/types/config.rs index 98b1b116..d5dc4958 100644 --- a/src/types/config.rs +++ b/src/types/config.rs @@ -12,8 +12,19 @@ use std::path::PathBuf; #[cfg(feature = "mocks")] use std::sync::Arc; -#[cfg(any(feature = "enable-rustls", feature = "enable-native-tls"))] -#[cfg_attr(docsrs, doc(cfg(any(feature = "enable-rustls", feature = "enable-native-tls"))))] +#[cfg(any( + feature = "enable-rustls", + feature = "enable-native-tls", + feature = "enable-rustls-ring" +))] +#[cfg_attr( + docsrs, + doc(cfg(any( + feature = "enable-rustls", + feature = "enable-native-tls", + feature = "enable-rustls-ring" + ))) +)] pub use crate::protocol::tls::{HostMapping, TlsConfig, TlsConnector, TlsHostMapping}; #[cfg(feature = "replicas")] @@ -624,8 +635,19 @@ pub struct RedisConfig { /// TLS configuration options. /// /// Default: `None` - #[cfg(any(feature = "enable-native-tls", feature = "enable-rustls"))] - #[cfg_attr(docsrs, doc(cfg(any(feature = "enable-native-tls", feature = "enable-rustls"))))] + #[cfg(any( + feature = "enable-native-tls", + feature = "enable-rustls", + feature = "enable-rustls-ring" + ))] + #[cfg_attr( + docsrs, + doc(cfg(any( + feature = "enable-native-tls", + feature = "enable-rustls", + feature = "enable-rustls-ring" + ))) + )] pub tls: Option, /// Tracing configuration options. #[cfg(feature = "partial-tracing")] @@ -663,7 +685,11 @@ impl Default for RedisConfig { server: ServerConfig::default(), version: RespVersion::RESP2, database: None, - #[cfg(any(feature = "enable-native-tls", feature = "enable-rustls"))] + #[cfg(any( + feature = "enable-native-tls", + feature = "enable-rustls", + feature = "enable-rustls-ring" + ))] tls: None, #[cfg(feature = "partial-tracing")] tracing: TracingConfig::default(), @@ -675,13 +701,21 @@ impl Default for RedisConfig { impl RedisConfig { /// Whether the client uses TLS. - #[cfg(any(feature = "enable-native-tls", feature = "enable-rustls"))] + #[cfg(any( + feature = "enable-native-tls", + feature = "enable-rustls", + feature = "enable-rustls-ring" + ))] pub fn uses_tls(&self) -> bool { self.tls.is_some() } /// Whether the client uses TLS. - #[cfg(not(any(feature = "enable-native-tls", feature = "enable-rustls")))] + #[cfg(not(any( + feature = "enable-native-tls", + feature = "enable-rustls", + feature = "enable-rustls-ring" + )))] pub fn uses_tls(&self) -> bool { false } @@ -703,7 +737,7 @@ impl RedisConfig { } /// Whether the client uses a `rustls` connector. - #[cfg(feature = "enable-rustls")] + #[cfg(any(feature = "enable-rustls", feature = "enable-rustls-ring"))] pub fn uses_rustls(&self) -> bool { self .tls @@ -713,7 +747,7 @@ impl RedisConfig { } /// Whether the client uses a `rustls` connector. - #[cfg(not(feature = "enable-rustls"))] + #[cfg(not(any(feature = "enable-rustls", feature = "enable-rustls-ring")))] pub fn uses_rustls(&self) -> bool { false } @@ -816,7 +850,11 @@ impl RedisConfig { username, password, database, - #[cfg(any(feature = "enable-native-tls", feature = "enable-rustls"))] + #[cfg(any( + feature = "enable-native-tls", + feature = "enable-rustls", + feature = "enable-rustls-ring" + ))] tls: utils::tls_config_from_url(_tls)?, ..RedisConfig::default() }) @@ -856,7 +894,11 @@ impl RedisConfig { server, username, password, - #[cfg(any(feature = "enable-native-tls", feature = "enable-rustls"))] + #[cfg(any( + feature = "enable-native-tls", + feature = "enable-rustls", + feature = "enable-rustls-ring" + ))] tls: utils::tls_config_from_url(_tls)?, ..RedisConfig::default() }) @@ -916,7 +958,11 @@ impl RedisConfig { username, password, database, - #[cfg(any(feature = "enable-native-tls", feature = "enable-rustls"))] + #[cfg(any( + feature = "enable-native-tls", + feature = "enable-rustls", + feature = "enable-rustls-ring" + ))] tls: utils::tls_config_from_url(_tls)?, ..RedisConfig::default() }) @@ -1162,8 +1208,19 @@ pub struct SentinelConfig { /// See the `tls` examples on Github for more information. /// /// Default: `None` - #[cfg(any(feature = "enable-native-tls", feature = "enable-rustls"))] - #[cfg_attr(docsrs, doc(cfg(any(feature = "enable-native-tls", feature = "enable-rustls"))))] + #[cfg(any( + feature = "enable-native-tls", + feature = "enable-rustls", + feature = "enable-rustls-ring" + ))] + #[cfg_attr( + docsrs, + doc(cfg(any( + feature = "enable-native-tls", + feature = "enable-rustls", + feature = "enable-rustls-ring" + ))) + )] pub tls: Option, /// Whether to enable tracing for this client. /// @@ -1181,7 +1238,11 @@ impl Default for SentinelConfig { port: 26379, username: None, password: None, - #[cfg(any(feature = "enable-native-tls", feature = "enable-rustls"))] + #[cfg(any( + feature = "enable-native-tls", + feature = "enable-rustls", + feature = "enable-rustls-ring" + ))] tls: None, #[cfg(feature = "partial-tracing")] tracing: TracingConfig::default(), @@ -1203,7 +1264,11 @@ impl From for RedisConfig { username: config.username, password: config.password, version: RespVersion::RESP2, - #[cfg(any(feature = "enable-native-tls", feature = "enable-rustls"))] + #[cfg(any( + feature = "enable-native-tls", + feature = "enable-rustls", + feature = "enable-rustls-ring" + ))] tls: config.tls, #[cfg(feature = "partial-tracing")] tracing: config.tracing, diff --git a/src/utils.rs b/src/utils.rs index 19430ed7..a50c0fb8 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -40,7 +40,11 @@ use tokio::{ use url::Url; use urlencoding::decode as percent_decode; -#[cfg(any(feature = "enable-native-tls", feature = "enable-rustls"))] +#[cfg(any( + feature = "enable-native-tls", + feature = "enable-rustls", + feature = "enable-rustls-ring" +))] use crate::protocol::tls::{TlsConfig, TlsConnector}; #[cfg(any(feature = "full-tracing", feature = "partial-tracing"))] use crate::trace; @@ -659,15 +663,26 @@ pub fn is_maybe_array_map(arr: &[RedisValue]) -> bool { } } -#[cfg(any(feature = "enable-native-tls", feature = "enable-rustls"))] +#[cfg(any( + feature = "enable-native-tls", + feature = "enable-rustls", + feature = "enable-rustls-ring" +))] pub fn check_tls_features() {} -#[cfg(not(any(feature = "enable-native-tls", feature = "enable-rustls")))] +#[cfg(not(any( + feature = "enable-native-tls", + feature = "enable-rustls", + feature = "enable-rustls-ring" +)))] pub fn check_tls_features() { warn!("TLS features are not enabled, but a TLS feature may have been used."); } -#[cfg(all(feature = "enable-native-tls", not(feature = "enable-rustls")))] +#[cfg(all( + feature = "enable-native-tls", + not(any(feature = "enable-rustls", feature = "enable-rustls-ring")) +))] pub fn tls_config_from_url(tls: bool) -> Result, RedisError> { if tls { TlsConnector::default_native_tls().map(|c| Some(c.into())) @@ -676,7 +691,10 @@ pub fn tls_config_from_url(tls: bool) -> Result, RedisError> { } } -#[cfg(all(feature = "enable-rustls", not(feature = "enable-native-tls")))] +#[cfg(all( + any(feature = "enable-rustls", feature = "enable-rustls-ring"), + not(feature = "enable-native-tls") +))] pub fn tls_config_from_url(tls: bool) -> Result, RedisError> { if tls { TlsConnector::default_rustls().map(|c| Some(c.into())) @@ -685,7 +703,10 @@ pub fn tls_config_from_url(tls: bool) -> Result, RedisError> { } } -#[cfg(all(feature = "enable-rustls", feature = "enable-native-tls"))] +#[cfg(all( + feature = "enable-native-tls", + any(feature = "enable-rustls", feature = "enable-rustls-ring") +))] pub fn tls_config_from_url(tls: bool) -> Result, RedisError> { // default to native-tls when both are enabled if tls { diff --git a/tests/docker/runners/bash/cluster-rustls-ring.sh b/tests/docker/runners/bash/cluster-rustls-ring.sh new file mode 100755 index 00000000..2575daf4 --- /dev/null +++ b/tests/docker/runners/bash/cluster-rustls-ring.sh @@ -0,0 +1,19 @@ +#!/bin/bash + +declare -a arr=("REDIS_VERSION" "REDIS_USERNAME" "REDIS_PASSWORD", "FRED_TEST_TLS_CREDS") + +for env in "${arr[@]}" +do + if [ -z "$env" ]; then + echo "$env must be set. Run `source tests/environ` if needed." + exit 1 + fi +done + +FEATURES="enable-rustls-ring transactions i-all network-logs debug-ids" + +if [ -z "$FRED_CI_NEXTEST" ]; then + FRED_CI_TLS=true cargo test --release --lib --tests --features "$FEATURES" -- --test-threads=1 "$@" +else + FRED_CI_TLS=true cargo nextest run --release --lib --tests --features "$FEATURES" --test-threads=1 "$@" +fi \ No newline at end of file diff --git a/tests/docker/runners/compose/cluster-rustls-ring.yml b/tests/docker/runners/compose/cluster-rustls-ring.yml new file mode 100644 index 00000000..635238a8 --- /dev/null +++ b/tests/docker/runners/compose/cluster-rustls-ring.yml @@ -0,0 +1,30 @@ +version: '2' + +services: + cluster-rustls-ring-tests: + depends_on: + - redis-cluster-tls-6 + container_name: "cluster-rustls-ring-tests" + build: + context: ../../../ + dockerfile: tests/docker/runners/images/base.dockerfile + args: + REDIS_VERSION: "${REDIS_VERSION}" + networks: + - fred-tests + privileged: true + command: + - "/project/tests/docker/runners/bash/cluster-rustls-ring.sh" + - "${TEST_ARGV}" + environment: + RUST_LOG: "${RUST_LOG}" + CIRCLECI_TESTS: "${CIRCLECI_TESTS}" + REDIS_VERSION: "${REDIS_VERSION}" + FRED_REDIS_CLUSTER_TLS_HOST: "${FRED_REDIS_CLUSTER_TLS_HOST}" + FRED_REDIS_CLUSTER_TLS_PORT: "${FRED_REDIS_CLUSTER_TLS_PORT}" + REDIS_USERNAME: "${REDIS_USERNAME}" + REDIS_PASSWORD: "${REDIS_PASSWORD}" + FRED_TEST_TLS_CREDS: "/project/tests/tmp/creds" + volumes: + - "../../..:/project" + - "~/.cargo/registry:/usr/local/cargo/registry" \ No newline at end of file diff --git a/tests/integration/utils.rs b/tests/integration/utils.rs index 1025a94c..403292db 100644 --- a/tests/integration/utils.rs +++ b/tests/integration/utils.rs @@ -9,13 +9,7 @@ use fred::{ error::RedisError, interfaces::*, types::{ - Builder, - ConnectionConfig, - PerformanceConfig, - ReconnectPolicy, - RedisConfig, - Server, - ServerConfig, + Builder, ConnectionConfig, PerformanceConfig, ReconnectPolicy, RedisConfig, Server, ServerConfig, UnresponsiveConfig, }, }; @@ -25,15 +19,17 @@ use std::{convert::TryInto, default::Default, env, fmt, fmt::Formatter, fs, futu const RECONNECT_DELAY: u32 = 1000; use fred::types::ClusterDiscoveryPolicy; -#[cfg(any(feature = "enable-rustls", feature = "enable-native-tls"))] +#[cfg(any( + feature = "enable-rustls", + feature = "enable-native-tls", + feature = "enable-rustls-ring" +))] use fred::types::{TlsConfig, TlsConnector, TlsHostMapping}; #[cfg(feature = "enable-native-tls")] use tokio_native_tls::native_tls::{ - Certificate as NativeTlsCertificate, - Identity, - TlsConnector as NativeTlsConnector, + Certificate as NativeTlsCertificate, Identity, TlsConnector as NativeTlsConnector, }; -#[cfg(feature = "enable-rustls")] +#[cfg(any(feature = "enable-rustls", feature = "enable-rustls-ring"))] use tokio_rustls::rustls::{ClientConfig, ConfigBuilder, RootCertStore, WantsVerifier}; pub fn read_env_var(name: &str) -> Option { @@ -104,7 +100,11 @@ pub fn read_redis_centralized_host() -> (String, u16) { (host, port) } -#[cfg(not(any(feature = "enable-native-tls", feature = "enable-rustls")))] +#[cfg(not(any( + feature = "enable-native-tls", + feature = "enable-rustls", + feature = "enable-rustls-ring" +)))] pub fn read_redis_cluster_host() -> (String, u16) { let host = read_env_var("FRED_REDIS_CLUSTER_HOST").unwrap_or("redis-cluster-1".into()); let port = read_env_var("FRED_REDIS_CLUSTER_PORT") @@ -114,7 +114,11 @@ pub fn read_redis_cluster_host() -> (String, u16) { (host, port) } -#[cfg(any(feature = "enable-native-tls", feature = "enable-rustls"))] +#[cfg(any( + feature = "enable-native-tls", + feature = "enable-rustls", + feature = "enable-rustls-ring" +))] pub fn read_redis_cluster_host() -> (String, u16) { let host = read_env_var("FRED_REDIS_CLUSTER_TLS_HOST").unwrap_or("redis-cluster-tls-1".into()); let port = read_env_var("FRED_REDIS_CLUSTER_TLS_PORT") @@ -160,18 +164,26 @@ pub fn read_sentinel_server() -> (String, u16) { (host, port) } -#[cfg(any(feature = "enable-rustls", feature = "enable-native-tls"))] +#[cfg(any( + feature = "enable-rustls", + feature = "enable-native-tls", + feature = "enable-rustls-ring" +))] #[allow(dead_code)] struct TlsCreds { - root_cert_der: Vec, - root_cert_pem: Vec, + root_cert_der: Vec, + root_cert_pem: Vec, client_cert_der: Vec, client_cert_pem: Vec, - client_key_der: Vec, - client_key_pem: Vec, + client_key_der: Vec, + client_key_pem: Vec, } -#[cfg(any(feature = "enable-rustls", feature = "enable-native-tls"))] +#[cfg(any( + feature = "enable-rustls", + feature = "enable-native-tls", + feature = "enable-rustls-ring" +))] fn check_file_contents(value: &Vec, msg: &str) { if value.is_empty() { panic!("Invalid empty TLS file: {}", msg); @@ -180,7 +192,11 @@ fn check_file_contents(value: &Vec, msg: &str) { /// Read the (root cert.pem, root cert.der, client cert.pem, client cert.der, client key.pem, client key.der) tuple /// from the test/tmp/creds directory. -#[cfg(any(feature = "enable-native-tls", feature = "enable-rustls"))] +#[cfg(any( + feature = "enable-native-tls", + feature = "enable-rustls", + feature = "enable-rustls-ring" +))] fn read_tls_creds() -> TlsCreds { let creds_path = read_env_var("FRED_TEST_TLS_CREDS").expect("Failed to read TLS path from env"); let root_cert_pem_path = format!("{}/ca.pem", creds_path); @@ -214,7 +230,7 @@ fn read_tls_creds() -> TlsCreds { } } -#[cfg(feature = "enable-rustls")] +#[cfg(any(feature = "enable-rustls", feature = "enable-rustls-ring"))] fn create_rustls_config() -> TlsConnector { use rustls::pki_types::PrivatePkcs8KeyDer; @@ -268,7 +284,7 @@ fn create_server_config(cluster: bool) -> ServerConfig { if cluster { let (host, port) = read_redis_cluster_host(); ServerConfig::Clustered { - hosts: vec![Server::new(host, port)], + hosts: vec![Server::new(host, port)], policy: ClusterDiscoveryPolicy::default(), } } else { @@ -297,18 +313,28 @@ fn create_normal_redis_config(cluster: bool, pipeline: bool, resp3: bool) -> (Re (config, perf) } -#[cfg(not(any(feature = "enable-rustls", feature = "enable-native-tls")))] +#[cfg(not(any( + feature = "enable-rustls", + feature = "enable-native-tls", + feature = "enable-rustls-ring" +)))] fn create_redis_config(cluster: bool, pipeline: bool, resp3: bool) -> (RedisConfig, PerformanceConfig) { create_normal_redis_config(cluster, pipeline, resp3) } -#[cfg(all(feature = "enable-rustls", feature = "enable-native-tls"))] +#[cfg(all( + feature = "enable-native-tls", + any(feature = "enable-rustls", feature = "enable-rustls-ring") +))] fn create_redis_config(cluster: bool, pipeline: bool, resp3: bool) -> (RedisConfig, PerformanceConfig) { // if both are enabled then don't use either since all the tests assume one or the other create_normal_redis_config(cluster, pipeline, resp3) } -#[cfg(all(feature = "enable-rustls", not(feature = "enable-native-tls")))] +#[cfg(all( + any(feature = "enable-rustls", feature = "enable-rustls-ring"), + not(feature = "enable-native-tls") +))] fn create_redis_config(cluster: bool, pipeline: bool, resp3: bool) -> (RedisConfig, PerformanceConfig) { if !read_ci_tls_env() { return create_normal_redis_config(cluster, pipeline, resp3); @@ -336,7 +362,10 @@ fn create_redis_config(cluster: bool, pipeline: bool, resp3: bool) -> (RedisConf (config, perf) } -#[cfg(all(feature = "enable-native-tls", not(feature = "enable-rustls")))] +#[cfg(all( + feature = "enable-native-tls", + not(any(feature = "enable-rustls", feature = "enable-rustls-ring")) +))] fn create_redis_config(cluster: bool, pipeline: bool, resp3: bool) -> (RedisConfig, PerformanceConfig) { if !read_ci_tls_env() { return create_normal_redis_config(cluster, pipeline, resp3); @@ -383,12 +412,12 @@ where fail_fast: read_fail_fast_env(), version: if resp3 { RespVersion::RESP3 } else { RespVersion::RESP2 }, server: ServerConfig::Sentinel { - hosts: vec![read_sentinel_server().into()], - service_name: "redis-sentinel-main".into(), + hosts: vec![read_sentinel_server().into()], + service_name: "redis-sentinel-main".into(), #[cfg(feature = "sentinel-auth")] - username: None, + username: None, #[cfg(feature = "sentinel-auth")] - password: Some(read_sentinel_password()), + password: Some(read_sentinel_password()), }, password: Some(read_redis_password()), ..Default::default() @@ -420,7 +449,7 @@ where connection.max_redirections = 10; connection.unresponsive = UnresponsiveConfig { max_timeout: Some(Duration::from_secs(10)), - interval: Duration::from_millis(400), + interval: Duration::from_millis(400), }; config.fail_fast = fail_fast; @@ -450,7 +479,7 @@ where connection.max_command_attempts = cmd_attempts; connection.unresponsive = UnresponsiveConfig { max_timeout: Some(Duration::from_secs(10)), - interval: Duration::from_millis(400), + interval: Duration::from_millis(400), }; config.fail_fast = fail_fast; @@ -467,7 +496,7 @@ where macro_rules! centralized_test_panic( ($module:tt, $name:tt) => { - #[cfg(not(any(feature = "enable-rustls", feature = "enable-native-tls")))] + #[cfg(not(any(feature = "enable-rustls", feature = "enable-native-tls", feature = "enable-rustls-ring")))] mod $name { mod resp2 { #[tokio::test(flavor = "multi_thread")] @@ -578,7 +607,7 @@ macro_rules! cluster_test_panic( macro_rules! centralized_test( ($module:tt, $name:tt) => { - #[cfg(not(any(feature = "enable-rustls", feature = "enable-native-tls")))] + #[cfg(not(any(feature = "enable-rustls", feature = "enable-native-tls", feature = "enable-rustls-ring")))] mod $name { mod resp2 { #[tokio::test(flavor = "multi_thread")] diff --git a/tests/runners/cluster-rustls-ring.sh b/tests/runners/cluster-rustls-ring.sh new file mode 100755 index 00000000..c98e605f --- /dev/null +++ b/tests/runners/cluster-rustls-ring.sh @@ -0,0 +1,4 @@ +#!/bin/bash + +TEST_ARGV="$1" docker-compose -f tests/docker/compose/cluster-tls.yml \ + -f tests/docker/runners/compose/cluster-rustls-ring.yml run -u $(id -u ${USER}):$(id -g ${USER}) --rm cluster-rustls-ring-tests \ No newline at end of file