Skip to content

Commit

Permalink
chore(deps): Upgrade tokio-rustls to 0.26 (#3419)
Browse files Browse the repository at this point in the history
chore(deps): Upgrade tokio-rustls to 0.26

This bumps rustls itself from 0.21 to 0.23, which comes with a few breaking API changes. Most of these are limited to types being moved or renamed, or how the certificate verifiers are constructed.

Signed-off-by: Scott Fleener <[email protected]>
Co-authored-by: Oliver Gould <[email protected]>
  • Loading branch information
sfleen and olix0r authored Dec 11, 2024
1 parent 24dc5d8 commit bb6e9b7
Show file tree
Hide file tree
Showing 14 changed files with 227 additions and 120 deletions.
52 changes: 32 additions & 20 deletions Cargo.lock
Original file line number Diff line number Diff line change
Expand Up @@ -3416,32 +3416,42 @@ dependencies = [

[[package]]
name = "rustls"
version = "0.21.12"
version = "0.23.19"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3f56a14d1f48b391359b22f731fd4bd7e43c97f3c50eee276f3aa09c94784d3e"
checksum = "934b404430bb06b3fae2cba809eb45a1ab1aecd64491213d7c3301b88393f8d1"
dependencies = [
"log",
"once_cell",
"ring",
"rustls-pki-types",
"rustls-webpki",
"sct",
"subtle",
"zeroize",
]

[[package]]
name = "rustls-pemfile"
version = "1.0.4"
version = "2.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1c74cae0a4cf6ccbbf5f359f08efdf8ee7e1dc532573bf0db71968cb56b1448c"
checksum = "dce314e5fee3f39953d46bb63bb8a46d40c2f8fb7cc5a3b6cab2bde9721d6e50"
dependencies = [
"base64 0.21.7",
"rustls-pki-types",
]

[[package]]
name = "rustls-pki-types"
version = "1.10.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "16f1201b3c9a7ee8039bcadc17b7e605e2945b27eee7631788c1bd2b0643674b"

[[package]]
name = "rustls-webpki"
version = "0.101.7"
version = "0.102.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8b6275d1ee7a1cd780b64aca7726599a1dbc893b1e64144529e55c3c2f745765"
checksum = "64ca1bc8749bd4cf37b5ce386cc146580777b4e8572c7b97baf22c83f444bee9"
dependencies = [
"ring",
"rustls-pki-types",
"untrusted",
]

Expand All @@ -3463,16 +3473,6 @@ version = "1.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49"

[[package]]
name = "sct"
version = "0.7.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "da046153aa2352493d6cb7da4b6e5c0c057d8a1d0a9aa8560baffdd945acd414"
dependencies = [
"ring",
"untrusted",
]

[[package]]
name = "semver"
version = "1.0.23"
Expand Down Expand Up @@ -3615,6 +3615,12 @@ version = "1.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3"

[[package]]
name = "subtle"
version = "2.6.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292"

[[package]]
name = "symbolic-common"
version = "12.12.3"
Expand Down Expand Up @@ -3859,9 +3865,9 @@ dependencies = [

[[package]]
name = "tokio-rustls"
version = "0.24.1"
version = "0.26.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c28327cf380ac148141087fbfb9de9d7bd4e84ab5d2c28fbc911d753de8a7081"
checksum = "5f6d0975eaace0cf0fcadee4e4aaa5da15b5c079146f2cffb67c113be122bf37"
dependencies = [
"rustls",
"tokio",
Expand Down Expand Up @@ -4483,6 +4489,12 @@ dependencies = [
"synstructure",
]

[[package]]
name = "zeroize"
version = "1.8.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ced3678a2879b30306d323f4542626697a464a97c0a07c9aebf7ebca65cd4dde"

[[package]]
name = "zerovec"
version = "0.10.4"
Expand Down
1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -98,4 +98,5 @@ lto = true

[workspace.dependencies]
linkerd2-proxy-api = "0.15.0"
tokio-rustls = { version = "0.26", default-features = false, features = ["ring", "logging"] }
# linkerd2-proxy-api = { git = "https://github.com/linkerd/linkerd2-proxy-api.git", branch = "main" }
4 changes: 2 additions & 2 deletions linkerd/app/integration/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -47,8 +47,8 @@ regex = "1"
socket2 = "0.5"
tokio = { version = "1", features = ["io-util", "net", "rt", "macros"] }
tokio-stream = { version = "0.1", features = ["sync"] }
tokio-rustls = "0.24"
rustls-pemfile = "1.0"
tokio-rustls = { workspace = true }
rustls-pemfile = "2.2"
tower = { version = "0.4", default-features = false }
tonic = { version = "0.10", features = ["transport"], default-features = false }
tracing = "0.1"
Expand Down
10 changes: 5 additions & 5 deletions linkerd/app/integration/src/client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,7 @@ use super::*;
use linkerd_app_core::proxy::http::TracingExecutor;
use parking_lot::Mutex;
use std::io;
use tokio::net::TcpStream;
use tokio::task::JoinHandle;
use tokio::{net::TcpStream, task::JoinHandle};
use tokio_rustls::rustls::{self, ClientConfig};
use tracing::info_span;

Expand All @@ -15,12 +14,13 @@ type Sender = mpsc::UnboundedSender<(Request, oneshot::Sender<Result<Response, C
#[derive(Clone)]
pub struct TlsConfig {
client_config: Arc<ClientConfig>,
name: rustls::ServerName,
name: rustls::pki_types::ServerName<'static>,
}

impl TlsConfig {
pub fn new(client_config: Arc<ClientConfig>, name: &str) -> Self {
let name = rustls::ServerName::try_from(name).expect("name must be a valid DNS name");
pub fn new(client_config: Arc<ClientConfig>, name: &'static str) -> Self {
let name =
rustls::pki_types::ServerName::try_from(name).expect("name must be a valid DNS name");
TlsConfig {
client_config,
name,
Expand Down
61 changes: 38 additions & 23 deletions linkerd/app/integration/src/identity.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ use std::{
};

use linkerd2_proxy_api::identity as pb;
use tokio_rustls::rustls;
use tokio_rustls::rustls::{self, pki_types::CertificateDer, server::WebPkiClientVerifier};
use tonic as grpc;

pub struct Identity {
Expand Down Expand Up @@ -36,7 +36,7 @@ type Certify = Box<

static TLS_VERSIONS: &[&rustls::SupportedProtocolVersion] = &[&rustls::version::TLS13];
static TLS_SUPPORTED_CIPHERSUITES: &[rustls::SupportedCipherSuite] =
&[rustls::cipher_suite::TLS13_CHACHA20_POLY1305_SHA256];
&[rustls::crypto::ring::cipher_suite::TLS13_CHACHA20_POLY1305_SHA256];

struct Certificates {
pub leaf: Vec<u8>,
Expand All @@ -50,23 +50,32 @@ impl Certificates {
{
let f = fs::File::open(p)?;
let mut r = io::BufReader::new(f);
let mut certs = rustls_pemfile::certs(&mut r)
let mut certs = rustls_pemfile::certs(&mut r);
let leaf = certs
.next()
.expect("no leaf cert in pemfile")
.map_err(|_| io::Error::new(io::ErrorKind::Other, "rustls error reading certs"))?
.as_ref()
.to_vec();
let intermediates = certs
.map(|cert| cert.map(|cert| cert.as_ref().to_vec()))
.collect::<Result<Vec<_>, _>>()
.map_err(|_| io::Error::new(io::ErrorKind::Other, "rustls error reading certs"))?;
let mut certs = certs.drain(..);
let leaf = certs.next().expect("no leaf cert in pemfile");
let intermediates = certs.collect();

Ok(Certificates {
leaf,
intermediates,
})
}

pub fn chain(&self) -> Vec<rustls::Certificate> {
pub fn chain(&self) -> Vec<rustls::pki_types::CertificateDer<'static>> {
let mut chain = Vec::with_capacity(self.intermediates.len() + 1);
chain.push(self.leaf.clone());
chain.extend(self.intermediates.clone());
chain.into_iter().map(rustls::Certificate).collect()
chain
.into_iter()
.map(rustls::pki_types::CertificateDer::from)
.collect()
}

pub fn response(&self) -> pb::CertifyResponse {
Expand All @@ -79,43 +88,49 @@ impl Certificates {
}

impl Identity {
fn load_key<P>(p: P) -> rustls::PrivateKey
fn load_key<P>(p: P) -> rustls::pki_types::PrivateKeyDer<'static>
where
P: AsRef<Path>,
{
let p8 = fs::read(&p).expect("read key");
rustls::PrivateKey(p8)
rustls::pki_types::PrivateKeyDer::try_from(p8).expect("decode key")
}

fn configs(
trust_anchors: &str,
certs: &Certificates,
key: rustls::PrivateKey,
key: rustls::pki_types::PrivateKeyDer<'static>,
) -> (Arc<rustls::ClientConfig>, Arc<rustls::ServerConfig>) {
use std::io::Cursor;
let mut roots = rustls::RootCertStore::empty();
let trust_anchors =
rustls_pemfile::certs(&mut Cursor::new(trust_anchors)).expect("error parsing pemfile");
let (added, skipped) = roots.add_parsable_certificates(&trust_anchors[..]);
let trust_anchors = rustls_pemfile::certs(&mut Cursor::new(trust_anchors))
.map(|bytes| bytes.map(CertificateDer::from))
.collect::<Result<Vec<_>, _>>()
.expect("error parsing pemfile");
let (added, skipped) = roots.add_parsable_certificates(trust_anchors);
assert_ne!(added, 0, "trust anchors must include at least one cert");
assert_eq!(skipped, 0, "no certs in pemfile should be invalid");

let client_config = rustls::ClientConfig::builder()
.with_cipher_suites(TLS_SUPPORTED_CIPHERSUITES)
.with_safe_default_kx_groups()
let mut provider = rustls::crypto::ring::default_provider();
provider.cipher_suites = TLS_SUPPORTED_CIPHERSUITES.to_vec();
let provider = Arc::new(provider);

let client_config = rustls::ClientConfig::builder_with_provider(provider.clone())
.with_protocol_versions(TLS_VERSIONS)
.expect("client config must be valid")
.with_root_certificates(roots.clone())
.with_no_client_auth();

let server_config = rustls::ServerConfig::builder()
.with_cipher_suites(TLS_SUPPORTED_CIPHERSUITES)
.with_safe_default_kx_groups()
let client_cert_verifier =
WebPkiClientVerifier::builder_with_provider(Arc::new(roots), provider.clone())
.allow_unauthenticated()
.build()
.expect("server verifier must be valid");

let server_config = rustls::ServerConfig::builder_with_provider(provider)
.with_protocol_versions(TLS_VERSIONS)
.expect("server config must be valid")
.with_client_cert_verifier(Arc::new(
rustls::server::AllowAnyAnonymousOrAuthenticatedClient::new(roots),
))
.with_client_cert_verifier(client_cert_verifier)
.with_single_cert(certs.chain(), key)
.unwrap();

Expand Down
2 changes: 1 addition & 1 deletion linkerd/app/outbound/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ futures-util = "0.3"
http-body = "0.4"
hyper = { version = "0.14", features = ["backports", "deprecated", "http1", "http2"] }
tokio = { version = "1", features = ["macros", "sync", "time"] }
tokio-rustls = "0.24"
tokio-rustls = { workspace = true }
tokio-test = "0.4"
tower-test = "0.4"

Expand Down
33 changes: 28 additions & 5 deletions linkerd/app/outbound/src/tls/logical/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ use std::{
time::Duration,
};
use tokio::sync::watch;
use tokio_rustls::rustls::pki_types::DnsName;

mod basic;

Expand Down Expand Up @@ -171,28 +172,37 @@ fn generate_client_hello(sni: &str) -> Vec<u8> {
use tokio_rustls::rustls::{
internal::msgs::{
base::Payload,
codec::{Codec, Reader},
enums::Compression,
handshake::{
ClientExtension, ClientHelloPayload, HandshakeMessagePayload, HandshakePayload,
Random, SessionId,
Random, ServerName, SessionId,
},
message::{MessagePayload, PlainMessage},
},
server::DnsName,
CipherSuite, ContentType, HandshakeType, ProtocolVersion,
};

let sni = DnsName::try_from(sni.to_string()).unwrap();
let sni = trim_hostname_trailing_dot_for_sni(&sni);

let mut server_name_bytes = vec![];
0u8.encode(&mut server_name_bytes); // encode the type first
(sni.as_ref().len() as u16).encode(&mut server_name_bytes); // then the length as u16
server_name_bytes.extend_from_slice(sni.as_ref().as_bytes()); // then the server name itself

let server_name =
ServerName::read(&mut Reader::init(&server_name_bytes)).expect("Server name is valid");

let hs_payload = HandshakeMessagePayload {
typ: HandshakeType::ClientHello,
payload: HandshakePayload::ClientHello(ClientHelloPayload {
client_version: ProtocolVersion::TLSv1_2,
random: Random::from([0; 32]),
session_id: SessionId::empty(),
session_id: SessionId::read(&mut Reader::init(&[0])).unwrap(),
cipher_suites: vec![CipherSuite::TLS_NULL_WITH_NULL_NULL],
compression_methods: vec![Compression::Null],
extensions: vec![ClientExtension::make_sni(sni.borrow())],
extensions: vec![ClientExtension::ServerName(vec![server_name])],
}),
};

Expand All @@ -202,8 +212,21 @@ fn generate_client_hello(sni: &str) -> Vec<u8> {
let message = PlainMessage {
typ: ContentType::Handshake,
version: ProtocolVersion::TLSv1_2,
payload: Payload(hs_payload_bytes),
payload: Payload::Owned(hs_payload_bytes),
};

message.into_unencrypted_opaque().encode()
}

fn trim_hostname_trailing_dot_for_sni(dns_name: &DnsName<'_>) -> DnsName<'static> {
let dns_name_str = dns_name.as_ref();

// RFC6066: "The hostname is represented as a byte string using
// ASCII encoding without a trailing dot"
if dns_name_str.ends_with('.') {
let trimmed = &dns_name_str[0..dns_name_str.len() - 1];
DnsName::try_from(trimmed).unwrap().to_owned()
} else {
dns_name.to_owned()
}
}
6 changes: 3 additions & 3 deletions linkerd/meshtls/rustls/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,11 @@ test-util = ["linkerd-tls-test-util"]
[dependencies]
futures = { version = "0.3", default-features = false }
ring = { version = "0.17", features = ["std"] }
rustls-pemfile = "1.0"
rustls-webpki = { version = "0.101.5", features = ["std"] }
rustls-pemfile = "2.2"
rustls-webpki = { version = "0.102.8", features = ["std"] }
thiserror = "2"
tokio = { version = "1", features = ["macros", "rt", "sync"] }
tokio-rustls = { version = "0.24", features = ["dangerous_configuration"] }
tokio-rustls = { workspace = true }
tracing = "0.1"

linkerd-dns-name = { path = "../../dns/name" }
Expand Down
Loading

0 comments on commit bb6e9b7

Please sign in to comment.