Skip to content

Commit

Permalink
Updating rustls dependencies & adjusting for new types/patterns (#204)
Browse files Browse the repository at this point in the history
  • Loading branch information
slawlor authored Feb 17, 2024
1 parent 295d9a8 commit 9a73feb
Show file tree
Hide file tree
Showing 7 changed files with 61 additions and 35 deletions.
2 changes: 1 addition & 1 deletion ractor/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "ractor"
version = "0.9.5"
version = "0.9.6"
authors = ["Sean Lawlor", "Evan Au", "Dillon George"]
description = "A actor framework for Rust"
documentation = "https://docs.rs/ractor"
Expand Down
4 changes: 2 additions & 2 deletions ractor_cluster/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "ractor_cluster"
version = "0.9.5"
version = "0.9.6"
authors = ["Sean Lawlor", "Evan Au", "Dillon George"]
description = "Distributed cluster environment of Ractor actors"
documentation = "https://docs.rs/ractor"
Expand Down Expand Up @@ -29,7 +29,7 @@ ractor_cluster_derive = { version = "0.9.0", path = "../ractor_cluster_derive" }
rand = "0.8"
sha2 = "0.10"
tokio = { version = "1", features = ["rt", "time", "sync", "macros", "net", "io-util", "tracing"]}
tokio-rustls = { version = "0.24" }
tokio-rustls = { version = "0.25" }
tracing = "0.1"

[dev-dependencies]
Expand Down
5 changes: 3 additions & 2 deletions ractor_cluster/src/node/client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ use std::fmt::Display;

use ractor::{ActorRef, MessagingErr};
use tokio::net::{TcpStream, ToSocketAddrs};
use tokio_rustls::rustls::pki_types::ServerName;

/// A client connection error. Possible issues are Socket connection
/// problems or failure to talk to the [super::NodeServer]
Expand Down Expand Up @@ -90,15 +91,15 @@ where
/// * `node_server` - The [super::NodeServer] which will own this new connection session
/// * `address` - The network address to send the connection to. Must implement [ToSocketAddrs]
/// * `encryption_settings` - The [tokio_rustls::TlsConnector] which is configured to encrypt the socket
/// * `domain` - The server name we're connecting to ([tokio_rustls::rustls::ServerName])
/// * `domain` - The server name we're connecting to ([ServerName])
///
/// Returns: [Ok(())] if the connection was successful and the [super::NodeSession] was started. Handshake will continue
/// automatically. Results in a [Err(ClientConnectError)] if any part of the process failed to initiate
pub async fn connect_enc<T>(
node_server: &ActorRef<super::NodeServerMessage>,
address: T,
encryption_settings: tokio_rustls::TlsConnector,
domain: tokio_rustls::rustls::ServerName,
domain: ServerName<'static>,
) -> Result<(), ClientConnectErr>
where
T: ToSocketAddrs,
Expand Down
2 changes: 1 addition & 1 deletion ractor_cluster_derive/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "ractor_cluster_derive"
version = "0.9.5"
version = "0.9.6"
authors = ["Sean Lawlor <[email protected]>"]
description = "Derives for ractor_cluster"
license = "MIT"
Expand Down
4 changes: 2 additions & 2 deletions ractor_cluster_integration_tests/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,8 @@ clap = { version = "4", features = ["derive"] }
ractor = { path = "../ractor" }
ractor_cluster = { path = "../ractor_cluster" }
rand = "0.8"
tokio-rustls = { version = "0.24" }
rustls-pemfile = "1.0"
tokio-rustls = { version = "0.25" }
rustls-pemfile = "2.1"
rustyrepl = { version = "0.2", features = ["async"] }
tokio = { version = "1", features = ["rt", "time", "sync", "macros", "rt-multi-thread", "signal", "tracing"] }
tracing = "0.1"
Expand Down
3 changes: 2 additions & 1 deletion ractor_cluster_integration_tests/envs/encryption.env
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
A_TEST="encryption 8199"
B_TEST="encryption 8198 8199 node-a"
B_TEST="encryption 8198 8199 node-a"
C_TEST="nan"
76 changes: 50 additions & 26 deletions ractor_cluster_integration_tests/src/tests/encryption.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,14 +10,14 @@
use std::convert::TryFrom;
use std::fs::File;
use std::io::{self, BufReader};
use std::path::{Path, PathBuf};
use std::path::PathBuf;
use std::sync::Arc;

use clap::Args;
use ractor::concurrency::{sleep, Duration, Instant};
use ractor::Actor;
use rustls_pemfile::{certs, rsa_private_keys};
use tokio_rustls::rustls::{Certificate, OwnedTrustAnchor, PrivateKey};
use tokio_rustls::rustls::pki_types::{CertificateDer, PrivateKeyDer, ServerName, TrustAnchor};
use tokio_rustls::{TlsAcceptor, TlsConnector};

const AUTH_TIME_ALLOWANCE_MS: u128 = 1500;
Expand All @@ -33,16 +33,35 @@ pub struct EncryptionConfig {
client_host: Option<String>,
}

fn load_certs(path: &Path) -> io::Result<Vec<Certificate>> {
certs(&mut BufReader::new(File::open(path)?))
.map_err(|_| io::Error::new(io::ErrorKind::InvalidInput, "invalid cert"))
.map(|mut certs| certs.drain(..).map(Certificate).collect())
fn load_certs(path_str: &'static str) -> io::Result<Vec<CertificateDer>> {
let path = PathBuf::from(path_str);
let certs: Vec<_> = certs(&mut BufReader::new(File::open(path)?))
.filter_map(|cert| if let Ok(c) = cert { Some(c) } else { None })
.collect();

if certs.is_empty() {
Err(io::Error::new(io::ErrorKind::InvalidData, "invalid cert"))
} else {
Ok(certs)
}
}

fn load_keys(path: &Path) -> io::Result<Vec<PrivateKey>> {
rsa_private_keys(&mut BufReader::new(File::open(path)?))
.map_err(|_| io::Error::new(io::ErrorKind::InvalidInput, "invalid key"))
.map(|mut keys| keys.drain(..).map(PrivateKey).collect())
fn load_keys(path_str: &'static str) -> io::Result<Vec<PrivateKeyDer>> {
let path = PathBuf::from(path_str);
let keys: Vec<PrivateKeyDer> = rsa_private_keys(&mut BufReader::new(File::open(path)?))
.filter_map(|key| {
if let Ok(k) = key {
Some(k.into())
} else {
None
}
})
.collect();
if keys.is_empty() {
Err(io::Error::new(io::ErrorKind::InvalidData, "invalid key"))
} else {
Ok(keys)
}
}

pub async fn test(config: EncryptionConfig) -> i32 {
Expand All @@ -53,13 +72,12 @@ pub async fn test(config: EncryptionConfig) -> i32 {
// Example `rustls` command: cargo run --bin tlsserver-mio -- --certs test-ca/rsa/end.fullchain --key test-ca/rsa/end.rsa -p 8443 echo
//
// combined with source code: https://github.com/tokio-rs/tls/blob/357bc562483dcf04c1f8d08bd1a831b144bf7d4c/tokio-rustls/examples/server/src/main.rs
let cert_path = PathBuf::from("test-ca/rsa/end.fullchain");
let key_path = PathBuf::from("test-ca/rsa/end.rsa");
let certs = load_certs(&cert_path).expect("Failed to load encryption certificates");
let mut keys = load_keys(&key_path).expect("Failed to load encryption keys");
let cert_path = "test-ca/rsa/end.fullchain";
let key_path = "test-ca/rsa/end.rsa";
let certs = load_certs(cert_path).expect("Failed to load encryption certificates");
let mut keys = load_keys(key_path).expect("Failed to load encryption keys");

let server_config = tokio_rustls::rustls::ServerConfig::builder()
.with_safe_defaults()
.with_no_client_auth()
.with_single_cert(certs, keys.remove(0))
.expect("Failed to build server configuration");
Expand All @@ -69,33 +87,39 @@ pub async fn test(config: EncryptionConfig) -> i32 {

let ca_path = PathBuf::from("test-ca/rsa/ca.cert");
let mut ca_pem = BufReader::new(File::open(ca_path).expect("Failed to load CA certificate"));
let ca_certs = rustls_pemfile::certs(&mut ca_pem).expect("Failed to parse CA certificate");
let ca_certs = rustls_pemfile::certs(&mut ca_pem).filter_map(|cert| {
if let Ok(c) = cert {
Some(c)
} else {
None
}
});

let mut root_cert_store = tokio_rustls::rustls::RootCertStore::empty();
let trust_anchors = ca_certs.iter().map(|cert| {
let trust_anchors = ca_certs.map(|cert| {
let ta =
webpki::TrustAnchor::try_from_cert_der(&cert[..]).expect("Failed to build TrustAnchor");
tracing::warn!(
"CA Cert SUB={}",
String::from_utf8(ta.subject.to_vec()).unwrap_or("n/a".to_string())
);
OwnedTrustAnchor::from_subject_spki_name_constraints(
ta.subject,
ta.spki,
ta.name_constraints,
)
TrustAnchor {
subject: ta.subject.into(),
name_constraints: ta.name_constraints.map(|a| a.into()),
subject_public_key_info: ta.spki.into(),
}
.to_owned()
});
root_cert_store.add_trust_anchors(trust_anchors);
root_cert_store.extend(trust_anchors);
// root_cert_store.add_trust_anchors(trust_anchors);
let client_config = tokio_rustls::rustls::ClientConfig::builder()
.with_safe_defaults()
.with_root_certificates(root_cert_store)
.with_no_client_auth();
let connector = TlsConnector::from(Arc::new(client_config));

// NOTE: It's `testserver.com` because that's what's generated by the rustls team. Eventually we should re-generate
// our own certs but this is just a temporary hack for the test
let domain = tokio_rustls::rustls::ServerName::try_from("testserver.com")
.expect("Invalid DNS name `node-a`");
let domain = ServerName::try_from("testserver.com").expect("Invalid DNS name `node-a`");

// ================== Server Creation ================== //

Expand Down

0 comments on commit 9a73feb

Please sign in to comment.