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]>
This commit is contained in:
co-authored by
Lucio Franco
parent
2378581850
commit
773e4e1749
@@ -11,6 +11,7 @@ use std::fmt;
|
||||
pub struct ServerTlsConfig {
|
||||
identity: Option<Identity>,
|
||||
client_ca_root: Option<Certificate>,
|
||||
client_auth_optional: bool,
|
||||
}
|
||||
|
||||
#[cfg(feature = "tls")]
|
||||
@@ -27,6 +28,7 @@ impl ServerTlsConfig {
|
||||
ServerTlsConfig {
|
||||
identity: None,
|
||||
client_ca_root: None,
|
||||
client_auth_optional: false,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -46,7 +48,24 @@ impl ServerTlsConfig {
|
||||
}
|
||||
}
|
||||
|
||||
/// Sets whether client certificate verification is optional.
|
||||
///
|
||||
/// This option has effect only if CA certificate is set.
|
||||
///
|
||||
/// # Default
|
||||
/// By default, this option is set to `false`.
|
||||
pub fn client_auth_optional(self, optional: bool) -> Self {
|
||||
ServerTlsConfig {
|
||||
client_auth_optional: optional,
|
||||
..self
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn tls_acceptor(&self) -> Result<TlsAcceptor, crate::Error> {
|
||||
TlsAcceptor::new(self.identity.clone().unwrap(), self.client_ca_root.clone())
|
||||
TlsAcceptor::new(
|
||||
self.identity.clone().unwrap(),
|
||||
self.client_ca_root.clone(),
|
||||
self.client_auth_optional,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -118,12 +118,20 @@ impl TlsAcceptor {
|
||||
pub(crate) fn new(
|
||||
identity: Identity,
|
||||
client_ca_root: Option<Certificate>,
|
||||
client_auth_optional: bool,
|
||||
) -> Result<Self, crate::Error> {
|
||||
let builder = ServerConfig::builder().with_safe_defaults();
|
||||
|
||||
let builder = match client_ca_root {
|
||||
None => builder.with_no_client_auth(),
|
||||
Some(cert) => {
|
||||
let builder = match (client_ca_root, client_auth_optional) {
|
||||
(None, _) => builder.with_no_client_auth(),
|
||||
(Some(cert), true) => {
|
||||
use tokio_rustls::rustls::server::AllowAnyAnonymousOrAuthenticatedClient;
|
||||
let mut roots = RootCertStore::empty();
|
||||
rustls_keys::add_certs_from_pem(std::io::Cursor::new(&cert.pem[..]), &mut roots)?;
|
||||
builder
|
||||
.with_client_cert_verifier(AllowAnyAnonymousOrAuthenticatedClient::new(roots))
|
||||
}
|
||||
(Some(cert), false) => {
|
||||
use tokio_rustls::rustls::server::AllowAnyAuthenticatedClient;
|
||||
let mut roots = RootCertStore::empty();
|
||||
rustls_keys::add_certs_from_pem(std::io::Cursor::new(&cert.pem[..]), &mut roots)?;
|
||||
|
||||
Reference in New Issue
Block a user