Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 3 additions & 2 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -36,8 +36,9 @@ jobs:
- name: clippy
run: >
cargo hack --feature-powerset
--mutually-exclusive-features tls,tls-openssl
--mutually-exclusive-features tls-roots,tls-openssl clippy
--mutually-exclusive-features tls-ring,tls-aws-lc,tls-openssl
--mutually-exclusive-features tls-native-roots,tls-openssl
--mutually-exclusive-features tls-webpki-roots,tls-openssl clippy
--all-targets
--
-D warnings
Expand Down
8 changes: 5 additions & 3 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,12 @@ documentation = "https://docs.rs/etcd-client/"
keywords = ["etcd", "v3", "api", "client", "async"]

[features]
tls = ["tonic/tls-ring"]
tls-ring = ["tonic/tls-ring"]
tls-aws-lc = ["tonic/tls-aws-lc"]
tls-openssl = ["openssl", "hyper-openssl", "hyper", "hyper-util"]
tls-openssl-vendored = ["tls-openssl", "openssl/vendored"]
tls-roots = ["tls", "tonic/tls-native-roots"]
tls-native-roots = ["tonic/tls-native-roots"]
tls-webpki-roots = ["tonic/tls-webpki-roots"]
pub-response-field = ["visible"]
build-server = ["pub-response-field"]
raw-channel = []
Expand Down Expand Up @@ -44,5 +46,5 @@ tonic-build = { version = "0.14", default-features = false }
tonic-prost-build = "0.14"

[package.metadata.docs.rs]
features = ["tls", "tls-roots"]
features = ["tls-ring", "tls-native-roots"]
rustdoc-args = ["--cfg", "docsrs"]
7 changes: 5 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -86,9 +86,12 @@ Examples can be found in [`examples`](./examples).

## Feature Flags

- `tls`: Enables the `rustls`-based TLS connection. Not enabled by default.
- `tls-roots`: Adds system trust roots to `rustls`-based TLS connection using the
- `tls-ring`: Enables the `ring` backed `rustls`-based TLS connection. Not enabled by default.
- `tls-aws-lc`: Enables the `aws-lc-rs` backed `rustls`-based TLS connection. Not enabled by default.
- `tls-native-roots`: Adds system trust roots to `rustls`-based TLS connection using the
`rustls-native-certs` crate. Not enabled by default.
- `tls-webpki-roots`: Adds Mozilla's trust roots to `rustls`-based TLS connection using the
`webpki-roots` crate. Not enabled by default.
- `pub-response-field`: Exposes structs used to create regular `etcd-client` responses including
internal protobuf representations. Useful for mocking. Not enabled by default.
- `tls-openssl`: Enables the `openssl`-based TLS connections. This would make your binary
Expand Down
38 changes: 26 additions & 12 deletions src/client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ use crate::rpc::maintenance::{
use crate::rpc::watch::{WatchClient, WatchOptions, WatchStream};
#[cfg(feature = "tls-openssl")]
use crate::OpenSslResult;
#[cfg(feature = "tls")]
#[cfg(any(feature = "tls-ring", feature = "tls-aws-lc"))]
use crate::TlsOptions;
use http::uri::Uri;
use tonic::metadata::{Ascii, MetadataValue};
Expand Down Expand Up @@ -159,7 +159,7 @@ impl Client {
fn build_endpoint(url: &str, options: &ConnectOptions) -> Result<Endpoint> {
use tonic::transport::Channel as TonicChannel;
let mut endpoint = if url.starts_with(HTTP_PREFIX) {
#[cfg(feature = "tls")]
#[cfg(any(feature = "tls-ring", feature = "tls-aws-lc"))]
if options.tls.is_some() {
return Err(Error::InvalidArgs(String::from(
"TLS options are only supported with HTTPS URLs",
Expand All @@ -168,23 +168,30 @@ impl Client {

TonicChannel::builder(url.parse()?)
} else if url.starts_with(HTTPS_PREFIX) {
#[cfg(not(any(feature = "tls", feature = "tls-openssl")))]
#[cfg(not(any(
feature = "tls-ring",
feature = "tls-aws-lc",
feature = "tls-openssl"
)))]
return Err(Error::InvalidArgs(String::from(
"HTTPS URLs are only supported with the feature \"tls\"",
)));

#[cfg(all(feature = "tls-openssl", not(feature = "tls")))]
#[cfg(all(
feature = "tls-openssl",
not(any(feature = "tls-ring", feature = "tls-aws-lc"))
))]
{
TonicChannel::builder(url.parse()?)
}

#[cfg(feature = "tls")]
#[cfg(any(feature = "tls-ring", feature = "tls-aws-lc"))]
{
let tls = options.tls.clone().unwrap_or_default();
TonicChannel::builder(url.parse()?).tls_config(tls)?
}
} else {
#[cfg(feature = "tls")]
#[cfg(any(feature = "tls-ring", feature = "tls-aws-lc"))]
{
let tls = options.tls.clone();

Expand All @@ -200,7 +207,10 @@ impl Client {
}
}

#[cfg(all(feature = "tls-openssl", not(feature = "tls")))]
#[cfg(all(
feature = "tls-openssl",
not(any(feature = "tls-ring", feature = "tls-aws-lc"))
))]
{
let pfx = if options.otls.as_ref().is_some() {
HTTPS_PREFIX
Expand All @@ -211,7 +221,11 @@ impl Client {
TonicChannel::builder(e.parse()?)
}

#[cfg(all(not(feature = "tls"), not(feature = "tls-openssl")))]
#[cfg(all(
not(feature = "tls-ring"),
not(feature = "tls-aws-lc"),
not(feature = "tls-openssl")
))]
{
let e = HTTP_PREFIX.to_owned() + url;
TonicChannel::builder(e.parse()?)
Expand Down Expand Up @@ -803,7 +817,7 @@ pub struct ConnectOptions {
connect_timeout: Option<Duration>,
/// TCP keepalive.
tcp_keepalive: Option<Duration>,
#[cfg(feature = "tls")]
#[cfg(any(feature = "tls-ring", feature = "tls-aws-lc"))]
tls: Option<TlsOptions>,
#[cfg(feature = "tls-openssl")]
otls: Option<OpenSslResult<OpenSslConnector>>,
Expand All @@ -822,8 +836,8 @@ impl ConnectOptions {
/// Sets TLS options.
///
/// Notes that this function have to work with `HTTPS` URLs.
#[cfg_attr(docsrs, doc(cfg(feature = "tls")))]
#[cfg(feature = "tls")]
#[cfg_attr(docsrs, doc(cfg(any(feature = "tls-ring", feature = "tls-aws-lc"))))]
#[cfg(any(feature = "tls-ring", feature = "tls-aws-lc"))]
#[inline]
pub fn with_tls(mut self, tls: TlsOptions) -> Self {
self.tls = Some(tls);
Expand Down Expand Up @@ -899,7 +913,7 @@ impl ConnectOptions {
timeout: None,
connect_timeout: None,
tcp_keepalive: None,
#[cfg(feature = "tls")]
#[cfg(any(feature = "tls-ring", feature = "tls-aws-lc"))]
tls: None,
#[cfg(feature = "tls-openssl")]
otls: None,
Expand Down
10 changes: 6 additions & 4 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -48,8 +48,10 @@
//!
//! # Feature Flags
//!
//! - `tls`: Enables the `rustls`-based TLS connection. Not enabled by default.
//! - `tls-roots`: Adds system trust roots to `rustls`-based TLS connection using the `rustls-native-certs` crate. Not enabled by default.
//! - `tls-ring`: Enables the `ring` backed `rustls`-based TLS connection. Not enabled by default.
//! - `tls-aws-lc`: Enables the `aws-lc-rs` backed `rustls`-based TLS connection. Not enabled by default.
//! - `tls-native-roots`: Adds system trust roots to `rustls`-based TLS connection using the `rustls-native-certs` crate. Not enabled by default.
//! - `tls-webpki-roots`: Adds Mozilla's trust roots to `rustls`-based TLS connection using the `webpki-roots` crate. Not enabled by default.
//! - `pub-response-field`: Exposes structs used to create regular `etcd-client` responses including internal protobuf representations. Useful for mocking. Not enabled by default.
//! - `tls-openssl`: Enables the `openssl`-based TLS connections. This would make your binary dynamically link to `libssl`.
//! - `tls-openssl-vendored`: Like `tls-openssl`, however compile openssl from source code and statically link to it.
Expand Down Expand Up @@ -109,8 +111,8 @@ pub use crate::rpc::watch::{
};
pub use crate::rpc::{KeyValue, ResponseHeader};

#[cfg(feature = "tls")]
#[cfg_attr(docsrs, doc(cfg(feature = "tls")))]
#[cfg(any(feature = "tls-ring", feature = "tls-aws-lc"))]
#[cfg_attr(docsrs, doc(cfg(any(feature = "tls-ring", feature = "tls-aws-lc"))))]
pub use tonic::transport::{Certificate, ClientTlsConfig as TlsOptions, Identity};

#[cfg(feature = "tls-openssl")]
Expand Down
4 changes: 2 additions & 2 deletions src/openssl_tls/transport.rs
Original file line number Diff line number Diff line change
Expand Up @@ -45,9 +45,9 @@ impl OpenSslConnector {
}
}

#[cfg(feature = "tls")]
#[cfg(any(feature = "tls-ring", feature = "tls-aws-lc"))]
compile_error!(concat!(
"**You should only enable one of `tls` and `tls-openssl`.** Reason: ",
"**You should only enable one of `tls-ring`, `tls-aws-lc` and `tls-openssl`.** Reason: ",
"For now, `tls-openssl` would take over the transport layer (sockets) to implement TLS based connection. ",
"As a result, once using with `tonic`'s internal TLS implementation (which based on `rustls`), ",
"we may create TLS tunnels over TLS tunnels or directly fail because of some sorts of misconfiguration.")
Expand Down