Skip to content

Commit

Permalink
Support TLS connection with optional tonic feature tls and `tls-roo…
Browse files Browse the repository at this point in the history
…ts` (#15)

Co-authored-by: David Li <[email protected]>
  • Loading branch information
jrb0001 and davidli2010 authored Jan 5, 2021
1 parent ba2eedd commit 553bffc
Show file tree
Hide file tree
Showing 3 changed files with 78 additions and 4 deletions.
4 changes: 4 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,10 @@ homepage = "https://github.com/etcdv3/etcd-client"
documentation = "https://docs.rs/etcd-client/"
keywords = ["etcd", "v3", "api", "client", "async"]

[features]
tls = ["tonic/tls"]
tls-roots = ["tls", "tonic/tls-roots"]

[dependencies]
tonic = "0.3"
prost = "0.6"
Expand Down
76 changes: 72 additions & 4 deletions src/client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,11 +31,14 @@ use crate::rpc::maintenance::{
HashResponse, MaintenanceClient, MoveLeaderResponse, SnapshotStreaming, StatusResponse,
};
use crate::rpc::watch::{WatchClient, WatchOptions, WatchStream, Watcher};
#[cfg(feature = "tls")]
use crate::TlsOptions;
use tonic::metadata::{Ascii, MetadataValue};
use tonic::transport::Channel;
use tonic::Interceptor;

const HTTP_PREFIX: &str = "http://";
const HTTPS_PREFIX: &str = "https://";

/// Asynchronous `etcd` client using v3 API.
#[derive(Clone)]
Expand All @@ -61,10 +64,59 @@ impl Client {
for e in endpoints.as_ref() {
let e = e.as_ref();
let channel = if e.starts_with(HTTP_PREFIX) {
#[cfg(feature = "tls")]
if let Some(ref connect_options) = options {
if let Some(_) = connect_options.tls {
return Err(Error::InvalidArgs(String::from(
"TLS options are only supported with HTTPS URLs",
)));
}
}

Channel::builder(e.parse()?)
} else if e.starts_with(HTTPS_PREFIX) {
#[cfg(not(feature = "tls"))]
return Err(Error::InvalidArgs(String::from(
"HTTPS URLs are only supported with the feature \"tls\"",
)));

#[cfg(feature = "tls")]
{
let tls = if let Some(ref connect_options) = options {
connect_options.tls.clone()
} else {
None
}
.unwrap_or_else(TlsOptions::new);

Channel::builder(e.parse()?).tls_config(tls)?
}
} else {
let e = HTTP_PREFIX.to_owned() + e;
Channel::builder(e.parse()?)
#[cfg(feature = "tls")]
{
let tls = if let Some(ref connect_options) = options {
connect_options.tls.clone()
} else {
None
};

match tls {
Some(tls) => {
let e = HTTPS_PREFIX.to_owned() + e;
Channel::builder(e.parse()?).tls_config(tls)?
}
None => {
let e = HTTP_PREFIX.to_owned() + e;
Channel::builder(e.parse()?)
}
}
}

#[cfg(not(feature = "tls"))]
{
let e = HTTP_PREFIX.to_owned() + e;
Channel::builder(e.parse()?)
}
};
eps.push(channel);
}
Expand Down Expand Up @@ -423,7 +475,7 @@ impl Client {
let mut eps = Vec::new();
for e in urls.as_ref() {
let e = e.as_ref();
let url = if e.starts_with(HTTP_PREFIX) {
let url = if e.starts_with(HTTP_PREFIX) || e.starts_with(HTTPS_PREFIX) {
e.to_string()
} else {
HTTP_PREFIX.to_owned() + e
Expand Down Expand Up @@ -516,6 +568,8 @@ impl Client {
pub struct ConnectOptions {
/// user is a pair values of name and password
user: Option<(String, String)>,
#[cfg(feature = "tls")]
tls: Option<TlsOptions>,
}

impl ConnectOptions {
Expand All @@ -526,10 +580,24 @@ impl ConnectOptions {
self
}

/// Sets TLS options.
///
/// Notes that this function have to work with `HTTPS` URLs.
#[cfg(feature = "tls")]
#[inline]
pub fn with_tls(mut self, tls: TlsOptions) -> Self {
self.tls = Some(tls);
self
}

/// Creates a `ConnectOptions`.
#[inline]
pub const fn new() -> Self {
ConnectOptions { user: None }
ConnectOptions {
user: None,
#[cfg(feature = "tls")]
tls: None,
}
}
}

Expand Down
2 changes: 2 additions & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -41,3 +41,5 @@ pub use crate::rpc::watch::{
Event, EventType, WatchFilterType, WatchOptions, WatchResponse, WatchStream, Watcher,
};
pub use crate::rpc::{KeyValue, ResponseHeader};
#[cfg(feature = "tls")]
pub use tonic::transport::{Certificate, ClientTlsConfig as TlsOptions, Identity};

0 comments on commit 553bffc

Please sign in to comment.