Skip to content

Commit 9a9832a

Browse files
gabrikMallets
andauthored
fix(771): Adding mTLS support in QUIC (#899)
* refactor(tls-quic): moving shared code into zenoh-link-commons::tls Signed-off-by: gabrik <gabriele.baldoni@gmail.com> * fix(mtls-quic): adding support for mTLS in QUIC [no ci] - broken Signed-off-by: gabrik <gabriele.baldoni@gmail.com> * fix(mtls-quic): using current release of quinn at the cost of some duplicated code Signed-off-by: gabrik <gabriele.baldoni@gmail.com> * test(quic-mlts): added tests for QUIC with mTLS, using rustls 0.22 to workaround the default CryptoProvider panic Signed-off-by: gabrik <gabriele.baldoni@gmail.com> * chore: addressing comments Signed-off-by: gabrik <gabriele.baldoni@gmail.com> * Apply suggestions from code review --------- Signed-off-by: gabrik <gabriele.baldoni@gmail.com> Co-authored-by: Luca Cominardi <luca.cominardi@gmail.com>
1 parent 2fdddae commit 9a9832a

File tree

12 files changed

+1334
-734
lines changed

12 files changed

+1334
-734
lines changed

Cargo.lock

Lines changed: 14 additions & 8 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

io/zenoh-link-commons/Cargo.toml

Lines changed: 22 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -12,35 +12,44 @@
1212
# ZettaScale Zenoh Team, <zenoh@zettascale.tech>
1313
#
1414
[package]
15-
rust-version = { workspace = true }
16-
name = "zenoh-link-commons"
17-
version = { workspace = true }
18-
repository = { workspace = true }
19-
homepage = { workspace = true }
2015
authors = { workspace = true }
21-
edition = { workspace = true }
22-
license = { workspace = true }
2316
categories = { workspace = true }
2417
description = "Internal crate for zenoh."
18+
edition = { workspace = true }
19+
homepage = { workspace = true }
20+
license = { workspace = true }
21+
name = "zenoh-link-commons"
22+
repository = { workspace = true }
23+
rust-version = { workspace = true }
24+
version = { workspace = true }
2525
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
2626

2727
[features]
2828
compression = []
2929

3030
[dependencies]
3131
async-trait = { workspace = true }
32+
base64 = { workspace = true, optional = true }
33+
flume = { workspace = true }
34+
futures = { workspace = true }
3235
rustls = { workspace = true }
3336
rustls-webpki = { workspace = true }
34-
flume = { workspace = true }
35-
tracing = {workspace = true}
3637
serde = { workspace = true, features = ["default"] }
38+
tokio = { workspace = true, features = [
39+
"fs",
40+
"io-util",
41+
"net",
42+
"sync",
43+
"time",
44+
] }
45+
tokio-util = { workspace = true, features = ["rt"] }
46+
tracing = { workspace = true }
47+
webpki-roots = { workspace = true, optional = true }
3748
zenoh-buffers = { workspace = true }
3849
zenoh-codec = { workspace = true }
50+
zenoh-config = { workspace = true }
3951
zenoh-core = { workspace = true }
4052
zenoh-protocol = { workspace = true }
4153
zenoh-result = { workspace = true }
42-
zenoh-util = { workspace = true }
4354
zenoh-runtime = { workspace = true }
44-
tokio = { workspace = true, features = ["io-util", "net", "fs", "sync", "time"] }
45-
tokio-util = { workspace = true, features = ["rt"] }
46-
futures = { workspace = true }
55+
zenoh-util = { workspace = true }

io/zenoh-links/zenoh-link-quic/Cargo.toml

Lines changed: 20 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -12,39 +12,46 @@
1212
# ZettaScale Zenoh Team, <zenoh@zettascale.tech>
1313
#
1414
[package]
15-
rust-version = { workspace = true }
16-
name = "zenoh-link-quic"
17-
version = { workspace = true }
18-
repository = { workspace = true }
19-
homepage = { workspace = true }
2015
authors = { workspace = true }
21-
edition = { workspace = true }
22-
license = { workspace = true }
2316
categories = { workspace = true }
2417
description = "Internal crate for zenoh."
18+
edition = { workspace = true }
19+
homepage = { workspace = true }
20+
license = { workspace = true }
21+
name = "zenoh-link-quic"
22+
repository = { workspace = true }
23+
rust-version = { workspace = true }
24+
version = { workspace = true }
2525
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
2626

2727
[dependencies]
2828
async-trait = { workspace = true }
2929
base64 = { workspace = true }
3030
futures = { workspace = true }
31-
tracing = {workspace = true}
3231
quinn = { workspace = true }
3332
rustls-native-certs = { workspace = true }
34-
rustls-pemfile = { workspace = true }
33+
rustls-pki-types = { workspace = true }
3534
rustls-webpki = { workspace = true }
36-
secrecy = {workspace = true }
37-
tokio = { workspace = true, features = ["io-util", "net", "fs", "sync", "time"] }
35+
secrecy = { workspace = true }
36+
tokio = { workspace = true, features = [
37+
"fs",
38+
"io-util",
39+
"net",
40+
"sync",
41+
"time",
42+
] }
3843
tokio-util = { workspace = true, features = ["rt"] }
44+
tracing = { workspace = true }
45+
webpki-roots = { workspace = true }
3946
zenoh-config = { workspace = true }
4047
zenoh-core = { workspace = true }
4148
zenoh-link-commons = { workspace = true }
4249
zenoh-protocol = { workspace = true }
4350
zenoh-result = { workspace = true }
51+
zenoh-runtime = { workspace = true }
4452
zenoh-sync = { workspace = true }
4553
zenoh-util = { workspace = true }
46-
zenoh-runtime = { workspace = true }
47-
4854
# Lock due to quinn not supporting rustls 0.22 yet
4955
rustls = { version = "0.21", features = ["dangerous_configuration", "quic"] }
5056
tokio-rustls = "0.24.1"
57+
rustls-pemfile = { version = "1" }

io/zenoh-links/zenoh-link-quic/src/lib.rs

Lines changed: 19 additions & 103 deletions
Original file line numberDiff line numberDiff line change
@@ -18,25 +18,17 @@
1818
//!
1919
//! [Click here for Zenoh's documentation](../zenoh/index.html)
2020
use async_trait::async_trait;
21-
use config::{
22-
TLS_ROOT_CA_CERTIFICATE_BASE64, TLS_ROOT_CA_CERTIFICATE_FILE, TLS_SERVER_CERTIFICATE_BASE64,
23-
TLS_SERVER_CERTIFICATE_FILE, TLS_SERVER_NAME_VERIFICATION, TLS_SERVER_PRIVATE_KEY_BASE64,
24-
TLS_SERVER_PRIVATE_KEY_FILE,
25-
};
26-
use secrecy::ExposeSecret;
27-
use std::net::SocketAddr;
28-
use zenoh_config::Config;
21+
2922
use zenoh_core::zconfigurable;
30-
use zenoh_link_commons::{ConfigurationInspector, LocatorInspector};
31-
use zenoh_protocol::core::{
32-
endpoint::{Address, Parameters},
33-
Locator,
34-
};
35-
use zenoh_result::{bail, zerror, ZResult};
23+
use zenoh_link_commons::LocatorInspector;
24+
use zenoh_protocol::core::Locator;
25+
use zenoh_result::ZResult;
3626

3727
mod unicast;
28+
mod utils;
3829
mod verify;
3930
pub use unicast::*;
31+
pub use utils::TlsConfigurator as QuicConfigurator;
4032

4133
// Default ALPN protocol
4234
pub const ALPN_QUIC_HTTP: &[&[u8]] = &[b"hq-29"];
@@ -64,77 +56,6 @@ impl LocatorInspector for QuicLocatorInspector {
6456
}
6557
}
6658

67-
#[derive(Default, Clone, Copy, Debug)]
68-
pub struct QuicConfigurator;
69-
70-
impl ConfigurationInspector<Config> for QuicConfigurator {
71-
fn inspect_config(&self, config: &Config) -> ZResult<String> {
72-
let mut ps: Vec<(&str, &str)> = vec![];
73-
74-
let c = config.transport().link().tls();
75-
76-
match (c.root_ca_certificate(), c.root_ca_certificate_base64()) {
77-
(Some(_), Some(_)) => {
78-
bail!("Only one between 'root_ca_certificate' and 'root_ca_certificate_base64' can be present!")
79-
}
80-
(Some(ca_certificate), None) => {
81-
ps.push((TLS_ROOT_CA_CERTIFICATE_FILE, ca_certificate));
82-
}
83-
(None, Some(ca_certificate)) => {
84-
ps.push((
85-
TLS_ROOT_CA_CERTIFICATE_BASE64,
86-
ca_certificate.expose_secret(),
87-
));
88-
}
89-
_ => {}
90-
}
91-
92-
match (c.server_private_key(), c.server_private_key_base64()) {
93-
(Some(_), Some(_)) => {
94-
bail!("Only one between 'server_private_key' and 'server_private_key_base64' can be present!")
95-
}
96-
(Some(server_private_key), None) => {
97-
ps.push((TLS_SERVER_PRIVATE_KEY_FILE, server_private_key));
98-
}
99-
(None, Some(server_private_key)) => {
100-
ps.push((
101-
TLS_SERVER_PRIVATE_KEY_BASE64,
102-
server_private_key.expose_secret(),
103-
));
104-
}
105-
_ => {}
106-
}
107-
108-
match (c.server_certificate(), c.server_certificate_base64()) {
109-
(Some(_), Some(_)) => {
110-
bail!("Only one between 'server_certificate' and 'server_certificate_base64' can be present!")
111-
}
112-
(Some(server_certificate), None) => {
113-
ps.push((TLS_SERVER_CERTIFICATE_FILE, server_certificate));
114-
}
115-
(None, Some(server_certificate)) => {
116-
ps.push((
117-
TLS_SERVER_CERTIFICATE_BASE64,
118-
server_certificate.expose_secret(),
119-
));
120-
}
121-
_ => {}
122-
}
123-
124-
if let Some(server_name_verification) = c.server_name_verification() {
125-
match server_name_verification {
126-
true => ps.push((TLS_SERVER_NAME_VERIFICATION, "true")),
127-
false => ps.push((TLS_SERVER_NAME_VERIFICATION, "false")),
128-
};
129-
}
130-
131-
let mut s = String::new();
132-
Parameters::extend(ps.drain(..), &mut s);
133-
134-
Ok(s)
135-
}
136-
}
137-
13859
zconfigurable! {
13960
// Default MTU (QUIC PDU) in bytes.
14061
static ref QUIC_DEFAULT_MTU: u16 = QUIC_MAX_MTU;
@@ -157,25 +78,20 @@ pub mod config {
15778
pub const TLS_SERVER_PRIVATE_KEY_RAW: &str = "server_private_key_raw";
15879
pub const TLS_SERVER_PRIVATE_KEY_BASE64: &str = "server_private_key_base64";
15980

160-
pub const TLS_SERVER_CERTIFICATE_FILE: &str = "tls_server_certificate_file";
161-
pub const TLS_SERVER_CERTIFICATE_RAW: &str = "tls_server_certificate_raw";
162-
pub const TLS_SERVER_CERTIFICATE_BASE64: &str = "tls_server_certificate_base64";
81+
pub const TLS_SERVER_CERTIFICATE_FILE: &str = "server_certificate_file";
82+
pub const TLS_SERVER_CERTIFICATE_RAW: &str = "server_certificate_raw";
83+
pub const TLS_SERVER_CERTIFICATE_BASE64: &str = "server_certificate_base64";
16384

164-
pub const TLS_SERVER_NAME_VERIFICATION: &str = "server_name_verification";
165-
pub const TLS_SERVER_NAME_VERIFICATION_DEFAULT: &str = "true";
166-
}
85+
pub const TLS_CLIENT_PRIVATE_KEY_FILE: &str = "client_private_key_file";
86+
pub const TLS_CLIENT_PRIVATE_KEY_RAW: &str = "client_private_key_raw";
87+
pub const TLS_CLIENT_PRIVATE_KEY_BASE64: &str = "client_private_key_base64";
16788

168-
async fn get_quic_addr(address: &Address<'_>) -> ZResult<SocketAddr> {
169-
match tokio::net::lookup_host(address.as_str()).await?.next() {
170-
Some(addr) => Ok(addr),
171-
None => bail!("Couldn't resolve QUIC locator address: {}", address),
172-
}
173-
}
89+
pub const TLS_CLIENT_CERTIFICATE_FILE: &str = "client_certificate_file";
90+
pub const TLS_CLIENT_CERTIFICATE_RAW: &str = "client_certificate_raw";
91+
pub const TLS_CLIENT_CERTIFICATE_BASE64: &str = "client_certificate_base64";
17492

175-
pub fn base64_decode(data: &str) -> ZResult<Vec<u8>> {
176-
use base64::engine::general_purpose;
177-
use base64::Engine;
178-
Ok(general_purpose::STANDARD
179-
.decode(data)
180-
.map_err(|e| zerror!("Unable to perform base64 decoding: {e:?}"))?)
93+
pub const TLS_CLIENT_AUTH: &str = "client_auth";
94+
95+
pub const TLS_SERVER_NAME_VERIFICATION: &str = "server_name_verification";
96+
pub const TLS_SERVER_NAME_VERIFICATION_DEFAULT: &str = "true";
18197
}

0 commit comments

Comments
 (0)