Skip to content

Commit

Permalink
refactor(tls-quic): moving shared code into zenoh-link-commons::tls
Browse files Browse the repository at this point in the history
Signed-off-by: gabrik <[email protected]>
  • Loading branch information
gabrik committed Apr 24, 2024
1 parent 2fdddae commit c98654f
Show file tree
Hide file tree
Showing 13 changed files with 199 additions and 274 deletions.
2 changes: 2 additions & 0 deletions io/zenoh-link-commons/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -34,9 +34,11 @@ rustls-webpki = { workspace = true }
flume = { workspace = true }
tracing = {workspace = true}
serde = { workspace = true, features = ["default"] }
secrecy = {workspace = true }
zenoh-buffers = { workspace = true }
zenoh-codec = { workspace = true }
zenoh-core = { workspace = true }
zenoh-config = { workspace = true }
zenoh-protocol = { workspace = true }
zenoh-result = { workspace = true }
zenoh-util = { workspace = true }
Expand Down
150 changes: 150 additions & 0 deletions io/zenoh-link-commons/src/tls.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,19 @@ use rustls::{
};
use webpki::ALL_VERIFICATION_ALGS;

use crate::ConfigurationInspector;
use secrecy::ExposeSecret;
use zenoh_config::Config;
use zenoh_protocol::core::endpoint;
use zenoh_result::{bail, ZResult};

use config::{
TLS_CLIENT_AUTH, TLS_CLIENT_CERTIFICATE_BASE64, TLS_CLIENT_CERTIFICATE_FILE,
TLS_CLIENT_PRIVATE_KEY_BASE64, TLS_CLIENT_PRIVATE_KEY_FILE, TLS_ROOT_CA_CERTIFICATE_BASE64,
TLS_ROOT_CA_CERTIFICATE_FILE, TLS_SERVER_CERTIFICATE_BASE64, TLS_SERVER_CERTIFICATE_FILE,
TLS_SERVER_NAME_VERIFICATION, TLS_SERVER_PRIVATE_KEY_BASE_64, TLS_SERVER_PRIVATE_KEY_FILE,
};

impl ServerCertVerifier for WebPkiVerifierAnyServerName {
/// Will verify the certificate is valid in the following ways:
/// - Signed by a trusted `RootCertStore` CA
Expand Down Expand Up @@ -85,3 +98,140 @@ impl WebPkiVerifierAnyServerName {
Self { roots }
}
}

pub mod config {
pub const TLS_ROOT_CA_CERTIFICATE_FILE: &str = "root_ca_certificate_file";
pub const TLS_ROOT_CA_CERTIFICATE_RAW: &str = "root_ca_certificate_raw";
pub const TLS_ROOT_CA_CERTIFICATE_BASE64: &str = "root_ca_certificate_base64";

pub const TLS_SERVER_PRIVATE_KEY_FILE: &str = "server_private_key_file";
pub const TLS_SERVER_PRIVATE_KEY_RAW: &str = "server_private_key_raw";
pub const TLS_SERVER_PRIVATE_KEY_BASE_64: &str = "server_private_key_base64";

pub const TLS_SERVER_CERTIFICATE_FILE: &str = "server_certificate_file";
pub const TLS_SERVER_CERTIFICATE_RAW: &str = "server_certificate_raw";
pub const TLS_SERVER_CERTIFICATE_BASE64: &str = "server_certificate_base64";

pub const TLS_CLIENT_PRIVATE_KEY_FILE: &str = "client_private_key_file";
pub const TLS_CLIENT_PRIVATE_KEY_RAW: &str = "client_private_key_raw";
pub const TLS_CLIENT_PRIVATE_KEY_BASE64: &str = "client_private_key_base64";

pub const TLS_CLIENT_CERTIFICATE_FILE: &str = "client_certificate_file";
pub const TLS_CLIENT_CERTIFICATE_RAW: &str = "client_certificate_raw";
pub const TLS_CLIENT_CERTIFICATE_BASE64: &str = "client_certificate_base64";

pub const TLS_CLIENT_AUTH: &str = "client_auth";

pub const TLS_SERVER_NAME_VERIFICATION: &str = "server_name_verification";
pub const TLS_SERVER_NAME_VERIFICATION_DEFAULT: &str = "true";
}

#[derive(Default, Clone, Copy, Debug)]
pub struct TlsConfigurator;

impl ConfigurationInspector<Config> for TlsConfigurator {
fn inspect_config(&self, config: &Config) -> ZResult<String> {
let mut ps: Vec<(&str, &str)> = vec![];

let c = config.transport().link().tls();

match (c.root_ca_certificate(), c.root_ca_certificate_base64()) {
(Some(_), Some(_)) => {
bail!("Only one between 'root_ca_certificate' and 'root_ca_certificate_base64' can be present!")
}
(Some(ca_certificate), None) => {
ps.push((TLS_ROOT_CA_CERTIFICATE_FILE, ca_certificate));
}
(None, Some(ca_certificate)) => {
ps.push((
TLS_ROOT_CA_CERTIFICATE_BASE64,
ca_certificate.expose_secret(),
));
}
_ => {}
}

match (c.server_private_key(), c.server_private_key_base64()) {
(Some(_), Some(_)) => {
bail!("Only one between 'server_private_key' and 'server_private_key_base64' can be present!")
}
(Some(server_private_key), None) => {
ps.push((TLS_SERVER_PRIVATE_KEY_FILE, server_private_key));
}
(None, Some(server_private_key)) => {
ps.push((
TLS_SERVER_PRIVATE_KEY_BASE_64,
server_private_key.expose_secret(),
));
}
_ => {}
}

match (c.server_certificate(), c.server_certificate_base64()) {
(Some(_), Some(_)) => {
bail!("Only one between 'server_certificate' and 'server_certificate_base64' can be present!")
}
(Some(server_certificate), None) => {
ps.push((TLS_SERVER_CERTIFICATE_FILE, server_certificate));
}
(None, Some(server_certificate)) => {
ps.push((
TLS_SERVER_CERTIFICATE_BASE64,
server_certificate.expose_secret(),
));
}
_ => {}
}

if let Some(client_auth) = c.client_auth() {
match client_auth {
true => ps.push((TLS_CLIENT_AUTH, "true")),
false => ps.push((TLS_CLIENT_AUTH, "false")),
};
}

match (c.client_private_key(), c.client_private_key_base64()) {
(Some(_), Some(_)) => {
bail!("Only one between 'client_private_key' and 'client_private_key_base64' can be present!")
}
(Some(client_private_key), None) => {
ps.push((TLS_CLIENT_PRIVATE_KEY_FILE, client_private_key));
}
(None, Some(client_private_key)) => {
ps.push((
TLS_CLIENT_PRIVATE_KEY_BASE64,
client_private_key.expose_secret(),
));
}
_ => {}
}

match (c.client_certificate(), c.client_certificate_base64()) {
(Some(_), Some(_)) => {
bail!("Only one between 'client_certificate' and 'client_certificate_base64' can be present!")
}
(Some(client_certificate), None) => {
ps.push((TLS_CLIENT_CERTIFICATE_FILE, client_certificate));
}
(None, Some(client_certificate)) => {
ps.push((
TLS_CLIENT_CERTIFICATE_BASE64,
client_certificate.expose_secret(),
));
}
_ => {}
}

if let Some(server_name_verification) = c.server_name_verification() {
match server_name_verification {
true => ps.push((TLS_SERVER_NAME_VERIFICATION, "true")),
false => ps.push((TLS_SERVER_NAME_VERIFICATION, "false")),
};
}

let mut s = String::new();
endpoint::Parameters::extend(ps.drain(..), &mut s);

Ok(s)
}
}
13 changes: 6 additions & 7 deletions io/zenoh-link/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,9 @@
//! [Click here for Zenoh's documentation](../zenoh/index.html)
use std::collections::HashMap;
use zenoh_config::Config;

#[cfg(any(feature = "transport_quic", feature = "transport_tls"))]
use zenoh_link_commons::tls::TlsConfigurator;
use zenoh_result::{bail, ZResult};

#[cfg(feature = "transport_tcp")]
Expand All @@ -36,16 +39,12 @@ use zenoh_link_udp::{
#[cfg(feature = "transport_tls")]
pub use zenoh_link_tls as tls;
#[cfg(feature = "transport_tls")]
use zenoh_link_tls::{
LinkManagerUnicastTls, TlsConfigurator, TlsLocatorInspector, TLS_LOCATOR_PREFIX,
};
use zenoh_link_tls::{LinkManagerUnicastTls, TlsLocatorInspector, TLS_LOCATOR_PREFIX};

#[cfg(feature = "transport_quic")]
pub use zenoh_link_quic as quic;
#[cfg(feature = "transport_quic")]
use zenoh_link_quic::{
LinkManagerUnicastQuic, QuicConfigurator, QuicLocatorInspector, QUIC_LOCATOR_PREFIX,
};
use zenoh_link_quic::{LinkManagerUnicastQuic, QuicLocatorInspector, QUIC_LOCATOR_PREFIX};

#[cfg(feature = "transport_ws")]
pub use zenoh_link_ws as ws;
Expand Down Expand Up @@ -155,7 +154,7 @@ impl LocatorInspector {
#[derive(Default)]
pub struct LinkConfigurator {
#[cfg(feature = "transport_quic")]
quic_inspector: QuicConfigurator,
quic_inspector: TlsConfigurator,
#[cfg(feature = "transport_tls")]
tls_inspector: TlsConfigurator,
#[cfg(feature = "transport_unixpipe")]
Expand Down
103 changes: 3 additions & 100 deletions io/zenoh-links/zenoh-link-quic/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,20 +18,11 @@
//!
//! [Click here for Zenoh's documentation](../zenoh/index.html)
use async_trait::async_trait;
use config::{
TLS_ROOT_CA_CERTIFICATE_BASE64, TLS_ROOT_CA_CERTIFICATE_FILE, TLS_SERVER_CERTIFICATE_BASE64,
TLS_SERVER_CERTIFICATE_FILE, TLS_SERVER_NAME_VERIFICATION, TLS_SERVER_PRIVATE_KEY_BASE64,
TLS_SERVER_PRIVATE_KEY_FILE,
};
use secrecy::ExposeSecret;

use std::net::SocketAddr;
use zenoh_config::Config;
use zenoh_core::zconfigurable;
use zenoh_link_commons::{ConfigurationInspector, LocatorInspector};
use zenoh_protocol::core::{
endpoint::{Address, Parameters},
Locator,
};
use zenoh_link_commons::LocatorInspector;
use zenoh_protocol::core::{endpoint::Address, Locator};
use zenoh_result::{bail, zerror, ZResult};

mod unicast;
Expand Down Expand Up @@ -64,77 +55,6 @@ impl LocatorInspector for QuicLocatorInspector {
}
}

#[derive(Default, Clone, Copy, Debug)]
pub struct QuicConfigurator;

impl ConfigurationInspector<Config> for QuicConfigurator {
fn inspect_config(&self, config: &Config) -> ZResult<String> {
let mut ps: Vec<(&str, &str)> = vec![];

let c = config.transport().link().tls();

match (c.root_ca_certificate(), c.root_ca_certificate_base64()) {
(Some(_), Some(_)) => {
bail!("Only one between 'root_ca_certificate' and 'root_ca_certificate_base64' can be present!")
}
(Some(ca_certificate), None) => {
ps.push((TLS_ROOT_CA_CERTIFICATE_FILE, ca_certificate));
}
(None, Some(ca_certificate)) => {
ps.push((
TLS_ROOT_CA_CERTIFICATE_BASE64,
ca_certificate.expose_secret(),
));
}
_ => {}
}

match (c.server_private_key(), c.server_private_key_base64()) {
(Some(_), Some(_)) => {
bail!("Only one between 'server_private_key' and 'server_private_key_base64' can be present!")
}
(Some(server_private_key), None) => {
ps.push((TLS_SERVER_PRIVATE_KEY_FILE, server_private_key));
}
(None, Some(server_private_key)) => {
ps.push((
TLS_SERVER_PRIVATE_KEY_BASE64,
server_private_key.expose_secret(),
));
}
_ => {}
}

match (c.server_certificate(), c.server_certificate_base64()) {
(Some(_), Some(_)) => {
bail!("Only one between 'server_certificate' and 'server_certificate_base64' can be present!")
}
(Some(server_certificate), None) => {
ps.push((TLS_SERVER_CERTIFICATE_FILE, server_certificate));
}
(None, Some(server_certificate)) => {
ps.push((
TLS_SERVER_CERTIFICATE_BASE64,
server_certificate.expose_secret(),
));
}
_ => {}
}

if let Some(server_name_verification) = c.server_name_verification() {
match server_name_verification {
true => ps.push((TLS_SERVER_NAME_VERIFICATION, "true")),
false => ps.push((TLS_SERVER_NAME_VERIFICATION, "false")),
};
}

let mut s = String::new();
Parameters::extend(ps.drain(..), &mut s);

Ok(s)
}
}

zconfigurable! {
// Default MTU (QUIC PDU) in bytes.
static ref QUIC_DEFAULT_MTU: u16 = QUIC_MAX_MTU;
Expand All @@ -148,23 +68,6 @@ zconfigurable! {
static ref QUIC_ACCEPT_THROTTLE_TIME: u64 = 100_000;
}

pub mod config {
pub const TLS_ROOT_CA_CERTIFICATE_FILE: &str = "root_ca_certificate_file";
pub const TLS_ROOT_CA_CERTIFICATE_RAW: &str = "root_ca_certificate_raw";
pub const TLS_ROOT_CA_CERTIFICATE_BASE64: &str = "root_ca_certificate_base64";

pub const TLS_SERVER_PRIVATE_KEY_FILE: &str = "server_private_key_file";
pub const TLS_SERVER_PRIVATE_KEY_RAW: &str = "server_private_key_raw";
pub const TLS_SERVER_PRIVATE_KEY_BASE64: &str = "server_private_key_base64";

pub const TLS_SERVER_CERTIFICATE_FILE: &str = "tls_server_certificate_file";
pub const TLS_SERVER_CERTIFICATE_RAW: &str = "tls_server_certificate_raw";
pub const TLS_SERVER_CERTIFICATE_BASE64: &str = "tls_server_certificate_base64";

pub const TLS_SERVER_NAME_VERIFICATION: &str = "server_name_verification";
pub const TLS_SERVER_NAME_VERIFICATION_DEFAULT: &str = "true";
}

async fn get_quic_addr(address: &Address<'_>) -> ZResult<SocketAddr> {
match tokio::net::lookup_host(address.as_str()).await?.next() {
Some(addr) => Ok(addr),
Expand Down
12 changes: 9 additions & 3 deletions io/zenoh-links/zenoh-link-quic/src/unicast.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,8 @@

use crate::base64_decode;
use crate::{
config::*, get_quic_addr, verify::WebPkiVerifierAnyServerName, ALPN_QUIC_HTTP,
QUIC_ACCEPT_THROTTLE_TIME, QUIC_DEFAULT_MTU, QUIC_LOCATOR_PREFIX,
get_quic_addr, verify::WebPkiVerifierAnyServerName, ALPN_QUIC_HTTP, QUIC_ACCEPT_THROTTLE_TIME,
QUIC_DEFAULT_MTU, QUIC_LOCATOR_PREFIX,
};
use async_trait::async_trait;
use rustls::{Certificate, PrivateKey};
Expand All @@ -29,6 +29,12 @@ use std::time::Duration;
use tokio::sync::Mutex as AsyncMutex;
use tokio_util::sync::CancellationToken;
use zenoh_core::zasynclock;
use zenoh_link_commons::tls::config::{
TLS_ROOT_CA_CERTIFICATE_BASE64, TLS_ROOT_CA_CERTIFICATE_FILE, TLS_ROOT_CA_CERTIFICATE_RAW,
TLS_SERVER_CERTIFICATE_BASE64, TLS_SERVER_CERTIFICATE_FILE, TLS_SERVER_CERTIFICATE_RAW,
TLS_SERVER_NAME_VERIFICATION, TLS_SERVER_NAME_VERIFICATION_DEFAULT,
TLS_SERVER_PRIVATE_KEY_FILE, TLS_SERVER_PRIVATE_KEY_RAW,
};
use zenoh_link_commons::{
get_ip_interface_names, LinkManagerUnicastTrait, LinkUnicast, LinkUnicastTrait,
ListenersUnicastIP, NewLinkChannelSender,
Expand Down Expand Up @@ -336,7 +342,7 @@ impl LinkManagerUnicastTrait for LinkManagerUnicastQuic {
// Private keys
let f = if let Some(value) = epconf.get(TLS_SERVER_PRIVATE_KEY_RAW) {
value.as_bytes().to_vec()
} else if let Some(b64_key) = epconf.get(TLS_SERVER_PRIVATE_KEY_BASE64) {
} else if let Some(b64_key) = epconf.get(TLS_SERVER_PRIVATE_KEY_RAW) {
base64_decode(b64_key)?
} else if let Some(value) = epconf.get(TLS_SERVER_PRIVATE_KEY_FILE) {
tokio::fs::read(value)
Expand Down
Loading

0 comments on commit c98654f

Please sign in to comment.