Skip to content

Commit 773e4e1

Browse files
dufkanLucioFranco
andauthored
feat(tls): add an option for optional TLS client authentication (#1163)
* feat(tls): add an option for optional TLS client authentication Previously there were only two options for client authentication – either no authentication or mandatory authentication. With this change, a server can allow for optional authentication with a given root CA certificate and enforce client authentication on a per-request basis. Refs: #687 * Update tonic/src/transport/server/tls.rs --------- Co-authored-by: Lucio Franco <[email protected]>
1 parent 2378581 commit 773e4e1

File tree

2 files changed

+31
-4
lines changed

2 files changed

+31
-4
lines changed

tonic/src/transport/server/tls.rs

+20-1
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ use std::fmt;
1111
pub struct ServerTlsConfig {
1212
identity: Option<Identity>,
1313
client_ca_root: Option<Certificate>,
14+
client_auth_optional: bool,
1415
}
1516

1617
#[cfg(feature = "tls")]
@@ -27,6 +28,7 @@ impl ServerTlsConfig {
2728
ServerTlsConfig {
2829
identity: None,
2930
client_ca_root: None,
31+
client_auth_optional: false,
3032
}
3133
}
3234

@@ -46,7 +48,24 @@ impl ServerTlsConfig {
4648
}
4749
}
4850

51+
/// Sets whether client certificate verification is optional.
52+
///
53+
/// This option has effect only if CA certificate is set.
54+
///
55+
/// # Default
56+
/// By default, this option is set to `false`.
57+
pub fn client_auth_optional(self, optional: bool) -> Self {
58+
ServerTlsConfig {
59+
client_auth_optional: optional,
60+
..self
61+
}
62+
}
63+
4964
pub(crate) fn tls_acceptor(&self) -> Result<TlsAcceptor, crate::Error> {
50-
TlsAcceptor::new(self.identity.clone().unwrap(), self.client_ca_root.clone())
65+
TlsAcceptor::new(
66+
self.identity.clone().unwrap(),
67+
self.client_ca_root.clone(),
68+
self.client_auth_optional,
69+
)
5170
}
5271
}

tonic/src/transport/service/tls.rs

+11-3
Original file line numberDiff line numberDiff line change
@@ -118,12 +118,20 @@ impl TlsAcceptor {
118118
pub(crate) fn new(
119119
identity: Identity,
120120
client_ca_root: Option<Certificate>,
121+
client_auth_optional: bool,
121122
) -> Result<Self, crate::Error> {
122123
let builder = ServerConfig::builder().with_safe_defaults();
123124

124-
let builder = match client_ca_root {
125-
None => builder.with_no_client_auth(),
126-
Some(cert) => {
125+
let builder = match (client_ca_root, client_auth_optional) {
126+
(None, _) => builder.with_no_client_auth(),
127+
(Some(cert), true) => {
128+
use tokio_rustls::rustls::server::AllowAnyAnonymousOrAuthenticatedClient;
129+
let mut roots = RootCertStore::empty();
130+
rustls_keys::add_certs_from_pem(std::io::Cursor::new(&cert.pem[..]), &mut roots)?;
131+
builder
132+
.with_client_cert_verifier(AllowAnyAnonymousOrAuthenticatedClient::new(roots))
133+
}
134+
(Some(cert), false) => {
127135
use tokio_rustls::rustls::server::AllowAnyAuthenticatedClient;
128136
let mut roots = RootCertStore::empty();
129137
rustls_keys::add_certs_from_pem(std::io::Cursor::new(&cert.pem[..]), &mut roots)?;

0 commit comments

Comments
 (0)