From 85060500f3a8f91ed47c632e07896c9e5567629a Mon Sep 17 00:00:00 2001 From: James Nugent Date: Fri, 15 Nov 2019 14:30:42 +0200 Subject: [PATCH] fix(transport): Remove support for OpenSSL (#141) BREAKING CHANGE: Remove support for OpenSSL within the transport. --- .github/workflows/CI.yml | 33 +--- README.md | 3 +- tonic-examples/Cargo.toml | 2 +- tonic-interop/Cargo.toml | 7 +- tonic-interop/src/bin/client.rs | 34 +--- tonic-interop/src/bin/server.rs | 26 +-- tonic-interop/test.sh | 9 +- tonic/Cargo.toml | 12 +- tonic/src/lib.rs | 18 +-- tonic/src/transport/endpoint.rs | 67 ++------ tonic/src/transport/mod.rs | 9 +- tonic/src/transport/server.rs | 68 ++------ tonic/src/transport/service/tls.rs | 248 ++++------------------------- tonic/src/transport/tls.rs | 11 -- 14 files changed, 82 insertions(+), 465 deletions(-) diff --git a/.github/workflows/CI.yml b/.github/workflows/CI.yml index 5804e1a60..707cfa9f0 100644 --- a/.github/workflows/CI.yml +++ b/.github/workflows/CI.yml @@ -74,12 +74,12 @@ jobs: - name: Run tests run: cargo test --all --all-features - interop-unix: - name: Interop Tests (Rustls & OpenSSL) + interop: + name: Interop Tests runs-on: ${{ matrix.os }} strategy: matrix: - os: [ubuntu-latest, macOS-latest] + os: [ubuntu-latest, macOS-latest, windows-latest] rust: [stable] env: @@ -98,30 +98,3 @@ jobs: - name: Run interop tests with Rustls run: ./tonic-interop/test.sh --use_tls tls_rustls shell: bash - - name: Run interop tests with OpenSSL - run: ./tonic-interop/test.sh --use_tls tls_openssl - shell: bash - - interop-windows: - name: Interop Tests (Rustls) (Windows) - runs-on: windows-latest - strategy: - matrix: - rust: [stable] - - env: - RUSTFLAGS: "-D warnings" - - steps: - - uses: hecrj/setup-rust-action@master - with: - rust-version: ${{ matrix.rust }} - - name: Install rustfmt - run: rustup component add rustfmt - - uses: actions/checkout@master - - name: Run interop tests - run: ./tonic-interop/test.sh - shell: bash - - name: Run interop tests with Rustls - run: ./tonic-interop/test.sh --use_tls tls_rustls - shell: bash diff --git a/README.md b/README.md index 8f0d94a4c..b0bffd4eb 100644 --- a/README.md +++ b/README.md @@ -25,7 +25,7 @@ contains the tools to build clients and servers from [`protobuf`] definitions. - Bi-directional streaming - High performance async io - Interoperability -- TLS backed via either [`openssl`] or [`rustls`] +- TLS backed by [`rustls`] - Load balancing - Custom metadata - Authentication @@ -97,7 +97,6 @@ terms or conditions. [`prost`]: https://github.com/danburkert/prost [`protobuf`]: https://developers.google.com/protocol-buffers [`rustls`]: https://github.com/ctz/rustls -[`openssl`]: https://www.openssl.org/ [`tonic-examples`]: https://github.com/hyperium/tonic/tree/master/tonic-examples [`tonic-interop`]: https://github.com/hyperium/tonic/tree/master/tonic-interop [Examples]: https://github.com/hyperium/tonic/tree/master/tonic-examples diff --git a/tonic-examples/Cargo.toml b/tonic-examples/Cargo.toml index 807829e18..43955c1d7 100644 --- a/tonic-examples/Cargo.toml +++ b/tonic-examples/Cargo.toml @@ -67,7 +67,7 @@ name = "gcp-client" path = "src/gcp/client.rs" [dependencies] -tonic = { path = "../tonic", features = ["rustls"] } +tonic = { path = "../tonic", features = ["tls"] } bytes = "0.4" prost = "0.5" diff --git a/tonic-interop/Cargo.toml b/tonic-interop/Cargo.toml index 2d6ef9189..e82bf2c85 100644 --- a/tonic-interop/Cargo.toml +++ b/tonic-interop/Cargo.toml @@ -6,11 +6,6 @@ edition = "2018" publish = false license = "MIT" -[features] -default = ["tonic"] -tls_openssl = ["tonic", "tonic/tls", "tonic/openssl"] -tls_rustls = ["tonic", "tonic/tls", "tonic/rustls"] - [[bin]] name = "client" path = "src/bin/client.rs" @@ -21,7 +16,7 @@ path = "src/bin/server.rs" [dependencies] tokio = "=0.2.0-alpha.6" -tonic = { path = "../tonic", optional = true } +tonic = { path = "../tonic", features = ["tls"] } prost = "0.5" prost-derive = "0.5" bytes = "0.4" diff --git a/tonic-interop/src/bin/client.rs b/tonic-interop/src/bin/client.rs index 3572d32c5..2142310c9 100644 --- a/tonic-interop/src/bin/client.rs +++ b/tonic-interop/src/bin/client.rs @@ -1,7 +1,6 @@ use std::time::Duration; use structopt::{clap::arg_enum, StructOpt}; use tonic::transport::Endpoint; -#[cfg(any(feature = "tls_rustls", feature = "tls_openssl"))] use tonic::transport::{Certificate, ClientTlsConfig}; use tonic_interop::client; @@ -33,32 +32,13 @@ async fn main() -> Result<(), Box> { .concurrency_limit(30); if matches.use_tls { - #[cfg(not(any(feature = "tls_rustls", feature = "tls_openssl")))] - { - panic!("No TLS library feature selected"); - } - - #[cfg(feature = "tls_rustls")] - { - let pem = tokio::fs::read("tonic-interop/data/ca.pem").await?; - let ca = Certificate::from_pem(pem); - endpoint = endpoint.tls_config( - ClientTlsConfig::with_rustls() - .ca_certificate(ca) - .domain_name("foo.test.google.fr"), - ); - } - - #[cfg(feature = "tls_openssl")] - { - let pem = tokio::fs::read("tonic-interop/data/ca.pem").await?; - let ca = Certificate::from_pem(pem); - endpoint = endpoint.tls_config( - ClientTlsConfig::with_openssl() - .ca_certificate(ca) - .domain_name("foo.test.google.fr"), - ); - } + let pem = tokio::fs::read("tonic-interop/data/ca.pem").await?; + let ca = Certificate::from_pem(pem); + endpoint = endpoint.tls_config( + ClientTlsConfig::with_rustls() + .ca_certificate(ca) + .domain_name("foo.test.google.fr"), + ); } let channel = endpoint.connect().await?; diff --git a/tonic-interop/src/bin/server.rs b/tonic-interop/src/bin/server.rs index 427e91985..1d60a8ff8 100644 --- a/tonic-interop/src/bin/server.rs +++ b/tonic-interop/src/bin/server.rs @@ -3,7 +3,6 @@ use structopt::StructOpt; use tonic::body::BoxBody; use tonic::client::GrpcService; use tonic::transport::Server; -#[cfg(any(feature = "tls_rustls", feature = "tls_openssl"))] use tonic::transport::{Identity, ServerTlsConfig}; use tonic_interop::{server, MergeTrailers}; @@ -50,28 +49,11 @@ async fn main() -> std::result::Result<(), Box> { }); if matches.use_tls { - #[cfg(not(any(feature = "tls_rustls", feature = "tls_openssl")))] - { - panic!("No TLS library feature selected"); - } - - #[cfg(feature = "tls_rustls")] - { - let cert = tokio::fs::read("tonic-interop/data/server1.pem").await?; - let key = tokio::fs::read("tonic-interop/data/server1.key").await?; - let identity = Identity::from_pem(cert, key); - - builder = builder.tls_config(ServerTlsConfig::with_rustls().identity(identity)); - } - - #[cfg(feature = "tls_openssl")] - { - let cert = tokio::fs::read("tonic-interop/data/server1.pem").await?; - let key = tokio::fs::read("tonic-interop/data/server1.key").await?; - let identity = Identity::from_pem(cert, key); + let cert = tokio::fs::read("tonic-interop/data/server1.pem").await?; + let key = tokio::fs::read("tonic-interop/data/server1.key").await?; + let identity = Identity::from_pem(cert, key); - builder = builder.tls_config(ServerTlsConfig::with_openssl().identity(identity)); - } + builder = builder.tls_config(ServerTlsConfig::with_rustls().identity(identity)); } let test_service = server::TestServiceServer::new(server::TestService::default()); diff --git a/tonic-interop/test.sh b/tonic-interop/test.sh index b9499c72c..559749295 100755 --- a/tonic-interop/test.sh +++ b/tonic-interop/test.sh @@ -15,15 +15,8 @@ case "$OSTYPE" in esac ARG="${1:-""}" -TLS_PROVIDER="${2:-""}" -if [[ -n "${TLS_PROVIDER}" ]] ; then - FEATURES="--features ${TLS_PROVIDER}" -else - FEATURES= -fi - -(cd tonic-interop && cargo build --bins ${FEATURES}) +(cd tonic-interop && cargo build --bins) SERVER="tonic-interop/bin/server_${OS}_amd64${EXT}" diff --git a/tonic/Cargo.toml b/tonic/Cargo.toml index 514cc72bd..e65606ac1 100644 --- a/tonic/Cargo.toml +++ b/tonic/Cargo.toml @@ -32,11 +32,8 @@ transport = [ "tower-balance", "tower-load", ] -openssl = ["openssl1", "tokio-openssl", "tls"] -rustls = ["tokio-rustls", "tls"] -openssl-roots = ["openssl-probe"] -rustls-roots = ["rustls-native-certs"] -tls = [] +tls = ["tokio-rustls"] +tls-roots = ["rustls-native-certs"] [[bench]] name = "bench_main" @@ -72,11 +69,6 @@ tower-make = "=0.3.0-alpha.2a" tower-balance = { version = "=0.3.0-alpha.2", optional = true } tower-load = { version = "=0.3.0-alpha.2", optional = true } -# openssl -tokio-openssl = { version = "=0.4.0-alpha.6", optional = true } -openssl1 = { package = "openssl", version = "0.10", optional = true } -openssl-probe = { version = "0.1", optional = true } - # rustls tokio-rustls = { version = "=0.12.0-alpha.5", optional = true } rustls-native-certs = { version = "0.1", optional = true } diff --git a/tonic/src/lib.rs b/tonic/src/lib.rs index 6bbd5d9cc..5851feb2b 100644 --- a/tonic/src/lib.rs +++ b/tonic/src/lib.rs @@ -20,16 +20,11 @@ //! implementation based on [`hyper`], [`tower`] and [`tokio`]. Enabled by default. //! - `codegen`: Enables all the required exports and optional dependencies required //! for [`tonic-build`]. Enabled by default. -//! - `openssl`: Enables the `openssl` based tls options for the `transport` feature`. Not +//! - `tls`: Enables the `ruslts` based TLS options for the `transport` feature`. Not //! enabled by default. -//! - `openssl-roots`: Adds system trust roots to `openssl`-based gRPC clients using the -//! `openssl-probe` crate. Not enabled by default. `openssl` must be enabled to use -//! `openssl-roots`. -//! - `rustls`: Enables the `ruslts` based tls options for the `transport` feature`. Not -//! enabled by default. -//! - `rustls-roots`: Adds system trust roots to `rustls`-based gRPC clients using the -//! `rustls-native-certs` crate. Not enabled by default. `rustls` must be enabled to use -//! `rustls-roots`. +//! - `tls-roots`: Adds system trust roots to `rustls`-based gRPC clients using the +//! `rustls-native-certs` crate. Not enabled by default. `tls` must be enabled to use +//! `tls-roots`. //! - `prost`: Enables the [`prost`] based gRPC [`Codec`] implementation. //! //! # Structure @@ -48,8 +43,8 @@ //! and [`Server`]. These implementations are built on top of [`tokio`], [`hyper`] and [`tower`]. //! It also provides many of the features that the core gRPC libraries provide such as load balancing, //! tls, timeouts, and many more. This implementation can also be used as a reference implementation -//! to build even more feature rich clients and servers. This module also provides the ability to choose -//! between [`rustls`] and [`openssl`] for the tls backend. +//! to build even more feature rich clients and servers. This module also provides the ability to +//! enable TLS using [`rustls`], via the `tls` feature flag. //! //! [gRPC]: https://grpc.io //! [`tonic`]: https://github.com/hyperium/tonic @@ -63,7 +58,6 @@ //! [`Channel`]: transport/struct.Channel.html //! [`Server`]: transport/struct.Server.html //! [`rustls`]: https://docs.rs/rustls -//! [`openssl`]: https://www.openssl.org //! [`client`]: client/index.html //! [`transport`]: transport/index.html diff --git a/tonic/src/transport/endpoint.rs b/tonic/src/transport/endpoint.rs index a79cc2481..0a4f32dcc 100644 --- a/tonic/src/transport/endpoint.rs +++ b/tonic/src/transport/endpoint.rs @@ -2,7 +2,7 @@ use super::channel::Channel; #[cfg(feature = "tls")] use super::{ service::TlsConnector, - tls::{Certificate, Identity, TlsProvider}, + tls::{Certificate, Identity}, }; use bytes::Bytes; use http::uri::{InvalidUriBytes, Uri}; @@ -223,13 +223,9 @@ impl fmt::Debug for Endpoint { #[cfg(feature = "tls")] #[derive(Clone)] pub struct ClientTlsConfig { - provider: TlsProvider, domain: Option, cert: Option, identity: Option, - #[cfg(feature = "openssl")] - openssl_raw: Option, - #[cfg(feature = "rustls")] rustls_raw: Option, } @@ -237,7 +233,6 @@ pub struct ClientTlsConfig { impl fmt::Debug for ClientTlsConfig { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { f.debug_struct("ClientTlsConfig") - .field("provider", &self.provider) .field("domain", &self.domain) .field("cert", &self.cert) .field("identity", &self.identity) @@ -247,35 +242,19 @@ impl fmt::Debug for ClientTlsConfig { #[cfg(feature = "tls")] impl ClientTlsConfig { - /// Creates a new `ClientTlsConfig` using OpenSSL. - #[cfg(feature = "openssl")] - pub fn with_openssl() -> Self { - Self::new(TlsProvider::OpenSsl) - } - /// Creates a new `ClientTlsConfig` using Rustls. - #[cfg(feature = "rustls")] pub fn with_rustls() -> Self { - Self::new(TlsProvider::Rustls) - } - - fn new(provider: TlsProvider) -> Self { ClientTlsConfig { - provider, domain: None, cert: None, identity: None, - #[cfg(feature = "openssl")] - openssl_raw: None, - #[cfg(feature = "rustls")] rustls_raw: None, } } /// Sets the domain name against which to verify the server's TLS certificate. /// - /// This has no effect if `rustls_client_config` or `openssl_connector` is used to configure - /// Rustls or OpenSSL respectively. + /// This has no effect if `rustls_client_config` is used to configure Rustls. pub fn domain_name(self, domain_name: impl Into) -> Self { ClientTlsConfig { domain: Some(domain_name.into()), @@ -285,8 +264,7 @@ impl ClientTlsConfig { /// Sets the CA Certificate against which to verify the server's TLS certificate. /// - /// This has no effect if `rustls_client_config` or `openssl_connector` is used to configure - /// Rustls or OpenSSL respectively. + /// This has no effect if `rustls_client_config` is used to configure Rustls. pub fn ca_certificate(self, ca_certificate: Certificate) -> Self { ClientTlsConfig { cert: Some(ca_certificate), @@ -296,8 +274,7 @@ impl ClientTlsConfig { /// Sets the client identity to present to the server. /// - /// This has no effect if `rustls_client_config` or `openssl_connector` is used to configure - /// Rustls or OpenSSL respectively. + /// This has no effect if `rustls_client_config` is used to configure Rustls. pub fn identity(self, identity: Identity) -> Self { ClientTlsConfig { identity: Some(identity), @@ -305,21 +282,9 @@ impl ClientTlsConfig { } } - /// Use options specified by the given `SslConnector` to configure TLS. - /// - /// This overrides all other TLS options set via other means. - #[cfg(feature = "openssl")] - pub fn openssl_connector(self, connector: openssl1::ssl::SslConnector) -> Self { - ClientTlsConfig { - openssl_raw: Some(connector), - ..self - } - } - /// Use options specified by the given `ClientConfig` to configure TLS. /// /// This overrides all other TLS options set via other means. - #[cfg(feature = "rustls")] pub fn rustls_client_config(self, config: tokio_rustls::rustls::ClientConfig) -> Self { ClientTlsConfig { rustls_raw: Some(config), @@ -332,25 +297,11 @@ impl ClientTlsConfig { None => uri.to_string(), Some(domain) => domain.clone(), }; - match self.provider { - #[cfg(feature = "openssl")] - TlsProvider::OpenSsl => match &self.openssl_raw { - None => TlsConnector::new_with_openssl_cert( - self.cert.clone(), - self.identity.clone(), - domain, - ), - Some(r) => TlsConnector::new_with_openssl_raw(r.clone(), domain), - }, - #[cfg(feature = "rustls")] - TlsProvider::Rustls => match &self.rustls_raw { - None => TlsConnector::new_with_rustls_cert( - self.cert.clone(), - self.identity.clone(), - domain, - ), - Some(c) => TlsConnector::new_with_rustls_raw(c.clone(), domain), - }, + match &self.rustls_raw { + None => { + TlsConnector::new_with_rustls_cert(self.cert.clone(), self.identity.clone(), domain) + } + Some(c) => TlsConnector::new_with_rustls_raw(c.clone(), domain), } } } diff --git a/tonic/src/transport/mod.rs b/tonic/src/transport/mod.rs index 718faf515..64fa72909 100644 --- a/tonic/src/transport/mod.rs +++ b/tonic/src/transport/mod.rs @@ -1,13 +1,13 @@ //! Batteries included server and client. //! //! This module provides a set of batteries included, fully featured and -//! fast set of HTTP/2 server and client's. These components each provide either an -//! `openssl` or `rustls` tls backend when the respective feature flags are enabled. -//!They also provide may configurable knobs that can be used to tune how they work. +//! fast set of HTTP/2 server and client's. These components each provide a or +//! `rustls` tls backend when the respective feature flag is enabled, and +//! provides builders to configure transport behavior. //! //! # Features //! -//! - TLS support via either [OpenSSL] or [rustls]. +//! - TLS support via [rustls]. //! - Load balancing //! - Timeouts //! - Concurrency Limits @@ -89,7 +89,6 @@ //! # } //! ``` //! -//! [OpenSSL]: https://www.openssl.org/ //! [rustls]: https://docs.rs/rustls/0.16.0/rustls/ pub mod channel; diff --git a/tonic/src/transport/server.rs b/tonic/src/transport/server.rs index c86ea3da4..9c87c14bf 100644 --- a/tonic/src/transport/server.rs +++ b/tonic/src/transport/server.rs @@ -2,11 +2,7 @@ use super::service::{layer_fn, BoxedIo, Or, Routes, ServiceBuilderExt}; #[cfg(feature = "tls")] -use super::{ - service::TlsAcceptor, - tls::{Identity, TlsProvider}, - Certificate, -}; +use super::{service::TlsAcceptor, tls::Identity, Certificate}; use crate::body::BoxBody; use futures_core::Stream; use futures_util::{future, ready, try_future::MapErr, TryFutureExt, TryStreamExt}; @@ -332,48 +328,25 @@ impl fmt::Debug for Server { #[cfg(feature = "tls")] #[derive(Clone)] pub struct ServerTlsConfig { - provider: TlsProvider, identity: Option, client_ca_root: Option, - #[cfg(feature = "openssl")] - openssl_raw: Option, - #[cfg(feature = "rustls")] rustls_raw: Option, } #[cfg(feature = "tls")] impl fmt::Debug for ServerTlsConfig { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - f.debug_struct("ServerTlsConfig") - .field("provider", &self.provider) - .finish() + f.debug_struct("ServerTlsConfig").finish() } } #[cfg(feature = "tls")] impl ServerTlsConfig { - /// Creates a new `ServerTlsConfig` using OpenSSL. - #[cfg(feature = "openssl")] - pub fn with_openssl() -> Self { - Self::new(TlsProvider::OpenSsl) - } - - /// Creates a new `ServerTlsConfig` using Rustls. - #[cfg(feature = "rustls")] + /// Creates a new `ServerTlsConfig`. pub fn with_rustls() -> Self { - Self::new(TlsProvider::Rustls) - } - - /// Creates a new `ServerTlsConfig` backed by the specified provider. Enable the `openssl` or - /// `rustls` features of the `tonic` crate to use OpenSSL or Rustls respectively. - fn new(provider: TlsProvider) -> Self { ServerTlsConfig { - provider, identity: None, client_ca_root: None, - #[cfg(feature = "openssl")] - openssl_raw: None, - #[cfg(feature = "rustls")] rustls_raw: None, } } @@ -394,21 +367,9 @@ impl ServerTlsConfig { } } - /// Use options specified by the given `SslAcceptor` to configure TLS. - /// - /// This overrides all other TLS options set via other means. - #[cfg(feature = "openssl")] - pub fn openssl_connector(self, acceptor: openssl1::ssl::SslAcceptor) -> Self { - ServerTlsConfig { - openssl_raw: Some(acceptor), - ..self - } - } - /// Use options specified by the given `ServerConfig` to configure TLS. /// /// This overrides all other TLS options set via other means. - #[cfg(feature = "rustls")] pub fn rustls_server_config( &mut self, config: tokio_rustls::rustls::ServerConfig, @@ -418,23 +379,12 @@ impl ServerTlsConfig { } fn tls_acceptor(&self) -> Result { - match self.provider { - #[cfg(feature = "openssl")] - TlsProvider::OpenSsl => match &self.openssl_raw { - None => TlsAcceptor::new_with_openssl_identity( - self.identity.clone().unwrap(), - self.client_ca_root.clone(), - ), - Some(acceptor) => TlsAcceptor::new_with_openssl_raw(acceptor.clone()), - }, - #[cfg(feature = "rustls")] - TlsProvider::Rustls => match &self.rustls_raw { - None => TlsAcceptor::new_with_rustls_identity( - self.identity.clone().unwrap(), - self.client_ca_root.clone(), - ), - Some(config) => TlsAcceptor::new_with_rustls_raw(config.clone()), - }, + match &self.rustls_raw { + None => TlsAcceptor::new_with_rustls_identity( + self.identity.clone().unwrap(), + self.client_ca_root.clone(), + ), + Some(config) => TlsAcceptor::new_with_rustls_raw(config.clone()), } } } diff --git a/tonic/src/transport/service/tls.rs b/tonic/src/transport/service/tls.rs index 7a9b2d114..c619a4433 100644 --- a/tonic/src/transport/service/tls.rs +++ b/tonic/src/transport/service/tls.rs @@ -1,29 +1,18 @@ use super::io::BoxedIo; use crate::transport::{Certificate, Identity}; -#[cfg(feature = "openssl")] -use openssl1::{ - pkey::PKey, - ssl::{select_next_proto, AlpnError, SslAcceptor, SslConnector, SslMethod, SslVerifyMode}, - x509::{store::X509StoreBuilder, X509}, -}; -#[cfg(feature = "openssl-roots")] -use openssl_probe; -#[cfg(feature = "rustls-roots")] +#[cfg(feature = "tls-roots")] use rustls_native_certs; use std::{fmt, sync::Arc}; use tokio::net::TcpStream; -#[cfg(feature = "rustls")] +#[cfg(feature = "tls")] use tokio_rustls::{ rustls::{ClientConfig, NoClientAuth, ServerConfig, Session}, webpki::DNSNameRef, TlsAcceptor as RustlsAcceptor, TlsConnector as RustlsConnector, }; -/// h2 alpn in wire format for openssl. -#[cfg(feature = "openssl")] -const ALPN_H2_WIRE: &[u8] = b"\x02h2"; /// h2 alpn in plain format for rustls. -#[cfg(feature = "rustls")] +#[cfg(feature = "tls")] const ALPN_H2: &str = "h2"; #[derive(Debug, Clone)] @@ -37,77 +26,20 @@ pub(crate) struct Cert { enum TlsError { #[allow(dead_code)] H2NotNegotiated, - #[cfg(feature = "rustls")] + #[cfg(feature = "tls")] CertificateParseError, - #[cfg(feature = "rustls")] + #[cfg(feature = "tls")] PrivateKeyParseError, - #[cfg(feature = "openssl-roots")] - TrustAnchorsConfigurationError(openssl1::error::ErrorStack), } #[derive(Clone)] pub(crate) struct TlsConnector { - inner: Connector, + config: Arc, domain: Arc, } -#[derive(Clone)] -enum Connector { - #[cfg(feature = "openssl")] - Openssl(SslConnector), - #[cfg(feature = "rustls")] - Rustls(Arc), -} - impl TlsConnector { - #[cfg(feature = "openssl")] - pub(crate) fn new_with_openssl_cert( - cert: Option, - identity: Option, - domain: String, - ) -> Result { - let mut config = SslConnector::builder(SslMethod::tls())?; - config.set_alpn_protos(ALPN_H2_WIRE)?; - - #[cfg(feature = "openssl-roots")] - { - openssl_probe::init_ssl_cert_env_vars(); - match config.cert_store_mut().set_default_paths() { - Ok(()) => (), - Err(e) => return Err(Box::new(TlsError::TrustAnchorsConfigurationError(e))), - }; - } - - if let Some(cert) = cert { - let ca = X509::from_pem(&cert.pem[..])?; - config.cert_store_mut().add_cert(ca)?; - } - - if let Some(identity) = identity { - let key = PKey::private_key_from_pem(&identity.key[..])?; - let cert = X509::from_pem(&identity.cert.pem[..])?; - config.set_certificate(&cert)?; - config.set_private_key(&key)?; - } - - Ok(Self { - inner: Connector::Openssl(config.build()), - domain: Arc::new(domain), - }) - } - - #[cfg(feature = "openssl")] - pub(crate) fn new_with_openssl_raw( - ssl_connector: openssl1::ssl::SslConnector, - domain: String, - ) -> Result { - Ok(Self { - inner: Connector::Openssl(ssl_connector), - domain: Arc::new(domain), - }) - } - - #[cfg(feature = "rustls")] + #[cfg(feature = "tls")] pub(crate) fn new_with_rustls_cert( ca_cert: Option, identity: Option, @@ -121,7 +53,7 @@ impl TlsConnector { config.set_single_client_cert(client_cert, client_key); } - #[cfg(feature = "rustls-roots")] + #[cfg(feature = "tls-roots")] { config.root_store = rustls_native_certs::load_native_certs()?; } @@ -132,58 +64,38 @@ impl TlsConnector { } Ok(Self { - inner: Connector::Rustls(Arc::new(config)), + config: Arc::new(config), domain: Arc::new(domain), }) } - #[cfg(feature = "rustls")] + #[cfg(feature = "tls")] pub(crate) fn new_with_rustls_raw( config: tokio_rustls::rustls::ClientConfig, domain: String, ) -> Result { Ok(Self { - inner: Connector::Rustls(Arc::new(config)), + config: Arc::new(config), domain: Arc::new(domain), }) } pub(crate) async fn connect(&self, io: TcpStream) -> Result { - let tls_io = match &self.inner { - #[cfg(feature = "openssl")] - Connector::Openssl(connector) => { - let config = connector.configure()?; - let tls = tokio_openssl::connect(config, &self.domain, io).await?; - - match tls.ssl().selected_alpn_protocol() { - Some(b) if b == b"h2" => tracing::trace!("HTTP/2 succesfully negotiated."), - _ => return Err(TlsError::H2NotNegotiated.into()), - }; - - BoxedIo::new(tls) - } - #[cfg(feature = "rustls")] - Connector::Rustls(config) => { - let dns = DNSNameRef::try_from_ascii_str(self.domain.as_str()) - .unwrap() - .to_owned(); - - let io = RustlsConnector::from(config.clone()) - .connect(dns.as_ref(), io) - .await?; + let tls_io = { + let dns = DNSNameRef::try_from_ascii_str(self.domain.as_str())?.to_owned(); - let (_, session) = io.get_ref(); + let io = RustlsConnector::from(self.config.clone()) + .connect(dns.as_ref(), io) + .await?; - match session.get_alpn_protocol() { - Some(b) if b == b"h2" => (), - _ => return Err(TlsError::H2NotNegotiated.into()), - }; + let (_, session) = io.get_ref(); - BoxedIo::new(io) - } + match session.get_alpn_protocol() { + Some(b) if b == b"h2" => (), + _ => return Err(TlsError::H2NotNegotiated.into()), + }; - #[allow(unreachable_patterns)] - _ => unreachable!("Reached a tls config point with neither feature enabled!"), + BoxedIo::new(io) }; Ok(tls_io) @@ -192,79 +104,17 @@ impl TlsConnector { impl fmt::Debug for TlsConnector { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - f.debug_struct("TlsConnector") - .field( - "inner", - match &self.inner { - #[cfg(feature = "openssl")] - Connector::Openssl(_) => &"Openssl", - #[cfg(feature = "rustls")] - Connector::Rustls(_) => &"Rustls", - - #[allow(unreachable_patterns)] - _ => &"None", - }, - ) - .finish() + f.debug_struct("TlsConnector").finish() } } #[derive(Clone)] pub(crate) struct TlsAcceptor { - inner: Acceptor, -} - -#[derive(Clone)] -enum Acceptor { - #[cfg(feature = "openssl")] - Openssl(SslAcceptor), - #[cfg(feature = "rustls")] - Rustls(Arc), + inner: Arc, } impl TlsAcceptor { - #[cfg(feature = "openssl")] - pub(crate) fn new_with_openssl_identity( - identity: Identity, - client_ca_root: Option, - ) -> Result { - let key = PKey::private_key_from_pem(&identity.key[..])?; - let cert = X509::from_pem(&identity.cert.pem[..])?; - - let mut config = SslAcceptor::mozilla_modern(SslMethod::tls())?; - - config.set_private_key(&key)?; - config.set_certificate(&cert)?; - config.set_alpn_protos(ALPN_H2_WIRE)?; - config.set_alpn_select_callback(|_ssl, alpn| { - select_next_proto(ALPN_H2_WIRE, alpn).ok_or(AlpnError::NOACK) - }); - - if let Some(cert) = client_ca_root { - let ca_cert = X509::from_pem(&cert.pem[..])?; - let mut store = X509StoreBuilder::new()?; - store.add_cert(ca_cert.clone())?; - - config.add_client_ca(&ca_cert)?; - config.set_verify_cert_store(store.build())?; - config.set_verify(SslVerifyMode::PEER | SslVerifyMode::FAIL_IF_NO_PEER_CERT); - } - - Ok(Self { - inner: Acceptor::Openssl(config.build()), - }) - } - - #[cfg(feature = "openssl")] - pub(crate) fn new_with_openssl_raw( - acceptor: openssl1::ssl::SslAcceptor, - ) -> Result { - Ok(Self { - inner: Acceptor::Openssl(acceptor), - }) - } - - #[cfg(feature = "rustls")] + #[cfg(feature = "tls")] pub(crate) fn new_with_rustls_identity( identity: Identity, client_ca_root: Option, @@ -291,36 +141,24 @@ impl TlsAcceptor { config.set_protocols(&[Vec::from(&ALPN_H2[..])]); Ok(Self { - inner: Acceptor::Rustls(Arc::new(config)), + inner: Arc::new(config), }) } - #[cfg(feature = "rustls")] + #[cfg(feature = "tls")] pub(crate) fn new_with_rustls_raw( config: tokio_rustls::rustls::ServerConfig, ) -> Result { Ok(Self { - inner: Acceptor::Rustls(Arc::new(config)), + inner: Arc::new(config), }) } pub(crate) async fn connect(&self, io: TcpStream) -> Result { - let io = match &self.inner { - #[cfg(feature = "openssl")] - Acceptor::Openssl(acceptor) => { - let tls = tokio_openssl::accept(&acceptor, io).await?; - BoxedIo::new(tls) - } - - #[cfg(feature = "rustls")] - Acceptor::Rustls(config) => { - let acceptor = RustlsAcceptor::from(config.clone()); - let tls = acceptor.accept(io).await?; - BoxedIo::new(tls) - } - - #[allow(unreachable_patterns)] - _ => unreachable!("Reached a tls config point with neither feature enabled!"), + let io = { + let acceptor = RustlsAcceptor::from(self.inner.clone()); + let tls = acceptor.accept(io).await?; + BoxedIo::new(tls) }; Ok(io) @@ -329,19 +167,7 @@ impl TlsAcceptor { impl fmt::Debug for TlsAcceptor { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - f.debug_struct("TlsAcceptor") - .field( - "inner", - match &self.inner { - #[cfg(feature = "openssl")] - Acceptor::Openssl(_) => &"Openssl", - #[cfg(feature = "rustls")] - Acceptor::Rustls(_) => &"Rustls", - #[allow(unreachable_patterns)] - _ => &"None", - }, - ) - .finish() + f.debug_struct("TlsAcceptor").finish() } } @@ -349,24 +175,18 @@ impl fmt::Display for TlsError { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { match self { TlsError::H2NotNegotiated => write!(f, "HTTP/2 was not negotiated."), - #[cfg(feature = "rustls")] TlsError::CertificateParseError => write!(f, "Error parsing TLS certificate."), - #[cfg(feature = "rustls")] TlsError::PrivateKeyParseError => write!( f, "Error parsing TLS private key - no RSA or PKCS8-encoded keys found." ), - #[cfg(feature = "openssl-roots")] - TlsError::TrustAnchorsConfigurationError(stack) => { - f.write_fmt(format_args!("Error adding trust anchors - {}", stack)) - } } } } impl std::error::Error for TlsError {} -#[cfg(feature = "rustls")] +#[cfg(feature = "tls")] mod rustls_keys { use tokio_rustls::rustls::{internal::pemfile, Certificate, PrivateKey}; diff --git a/tonic/src/transport/tls.rs b/tonic/src/transport/tls.rs index 33c8fec6b..f8fb9916d 100644 --- a/tonic/src/transport/tls.rs +++ b/tonic/src/transport/tls.rs @@ -1,14 +1,3 @@ -/// Selects a library to provide TLS. -#[derive(Clone, Debug)] -pub(crate) enum TlsProvider { - /// Use OpenSSL for TLS. - #[cfg(feature = "openssl")] - OpenSsl, - /// Use OpenSSL for TLS. - #[cfg(feature = "rustls")] - Rustls, -} - /// Represents a X509 certificate. #[derive(Debug, Clone)] pub struct Certificate {