Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Update dependencies (rustls and axum-server) #5

Closed
wants to merge 7 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 8 additions & 8 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -12,33 +12,33 @@ categories = ["asynchronous", "cryptography", "network-programming"]

[dependencies]
futures = "0.3.21"
rcgen = "0.11"
rcgen = "0.12"
serde_json = "1.0.81"
serde = { version = "1.0.137", features = ["derive"] }
ring = { version = "0.16.20", features = ["std"] }
ring = { version = "0.17", features = ["std"] }
base64 = "0.21.0"
log = "0.4.17"
webpki-roots = "0.25.2"
webpki-roots = "0.26"
pem = "2.0"
thiserror = "1.0.31"
x509-parser = "0.15"
chrono = { version = "0.4.24", default-features = false, features = ["clock"] }
url = "2.2.2"
async-trait = "0.1.53"
rustls = "0.21"
rustls = "0.23"

tokio = { version = "1.20.1", default-features = false }
tokio-rustls = { version = "0.24" }
reqwest = { version = "0.11.19", default-features = false, features = ["rustls-tls"] }
tokio-rustls = { version = "0.26" }
reqwest = { version = "0.12.5", default-features = false, features = ["rustls-tls"] }

# Axum
axum-server = { version = "0.5", features = ["tls-rustls"], optional = true }
axum-server = { version = "0.7", features = ["tls-rustls"], optional = true }

[dev-dependencies]
simple_logger = "4.1"
structopt = "0.3.26"
clap = { version = "4", features = ["derive"] }
axum = "0.6"
axum = "0.7"
tokio = { version="1.19.2", features = ["full"] }
tokio-stream = { version="0.1.9", features = ["net"] }
tokio-util = { version="0.7.3", features = ["compat"] }
Expand Down
4 changes: 4 additions & 0 deletions examples/high_level.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
use clap::Parser;
use rustls::crypto;
use std::net::Ipv6Addr;
use std::path::PathBuf;
use tokio::io::AsyncWriteExt;
Expand Down Expand Up @@ -33,6 +34,9 @@ struct Args {
#[tokio::main]
async fn main() {
simple_logger::init_with_level(log::Level::Info).unwrap();

crypto::ring::default_provider().install_default().unwrap();

let args = Args::parse();

let tcp_listener = tokio::net::TcpListener::bind((Ipv6Addr::UNSPECIFIED, args.port))
Expand Down
6 changes: 6 additions & 0 deletions examples/high_level_warp.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
use clap::Parser;
use rustls::crypto;
use std::net::Ipv6Addr;
use std::path::PathBuf;
use tokio_rustls_acme::caches::DirCache;
Expand Down Expand Up @@ -32,6 +33,11 @@ struct Args {
#[tokio::main]
async fn main() {
simple_logger::init_with_level(log::Level::Info).unwrap();

crypto::aws_lc_rs::default_provider()
.install_default()
.unwrap();

let args = Args::parse();

let tcp_listener = tokio::net::TcpListener::bind((Ipv6Addr::UNSPECIFIED, args.port))
Expand Down
6 changes: 4 additions & 2 deletions examples/low_level.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use clap::Parser;
use rustls::ServerConfig;
use rustls::{crypto, ServerConfig};
use std::net::Ipv6Addr;
use std::path::PathBuf;
use std::sync::Arc;
Expand Down Expand Up @@ -34,6 +34,9 @@ struct Args {
#[tokio::main]
async fn main() {
simple_logger::init_with_level(log::Level::Info).unwrap();

crypto::ring::default_provider().install_default().unwrap();

let args = Args::parse();

let mut state = AcmeConfig::new(args.domains)
Expand All @@ -42,7 +45,6 @@ async fn main() {
.directory_lets_encrypt(args.prod)
.state();
let rustls_config = ServerConfig::builder()
.with_safe_defaults()
.with_no_client_auth()
.with_cert_resolver(state.resolver());
let acceptor = state.acceptor();
Expand Down
6 changes: 4 additions & 2 deletions examples/low_level_axum.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use axum::{routing::get, Router};
use clap::Parser;
use rustls::ServerConfig;
use rustls::{crypto, ServerConfig};
use std::net::{Ipv6Addr, SocketAddr};
use std::path::PathBuf;
use std::sync::Arc;
Expand Down Expand Up @@ -34,6 +34,9 @@ struct Args {
#[tokio::main]
async fn main() {
simple_logger::init_with_level(log::Level::Info).unwrap();

crypto::ring::default_provider().install_default().unwrap();

let args = Args::parse();

let mut state = AcmeConfig::new(args.domains)
Expand All @@ -42,7 +45,6 @@ async fn main() {
.directory_lets_encrypt(args.prod)
.state();
let rustls_config = ServerConfig::builder()
.with_safe_defaults()
.with_no_client_auth()
.with_cert_resolver(state.resolver());
let acceptor = state.axum_acceptor(Arc::new(rustls_config));
Expand Down
1 change: 0 additions & 1 deletion src/acceptor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@ pub struct AcmeAcceptor {
impl AcmeAcceptor {
pub(crate) fn new(resolver: Arc<ResolvesServerCertAcme>) -> Self {
let mut config = ServerConfig::builder()
.with_safe_defaults()
.with_no_client_auth()
.with_cert_resolver(resolver);
config.alpn_protocols.push(ACME_TLS_ALPN_NAME.to_vec());
Expand Down
22 changes: 15 additions & 7 deletions src/acme.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,15 @@ use crate::https_helper::{https, HttpsRequestError, Method, Response};
use crate::jose::{key_authorization_sha256, sign, JoseError};
use base64::engine::general_purpose::URL_SAFE_NO_PAD;
use base64::Engine;
use rcgen::{Certificate, CustomExtension, RcgenError, PKCS_ECDSA_P256_SHA256};
use rcgen::{Certificate, CustomExtension, PKCS_ECDSA_P256_SHA256};
use ring::error::{KeyRejected, Unspecified};
use ring::rand::SystemRandom;
use ring::signature::{EcdsaKeyPair, EcdsaSigningAlgorithm, ECDSA_P256_SHA256_FIXED_SIGNING};
use rustls::sign::{any_ecdsa_type, CertifiedKey};
use rustls::{ClientConfig, PrivateKey};
use rustls::{crypto::ring::sign::any_ecdsa_type, sign::CertifiedKey};
use rustls::{
pki_types::{PrivateKeyDer, PrivatePkcs8KeyDer},
ClientConfig,
};
use serde::{Deserialize, Serialize};
use serde_json::json;
use thiserror::Error;
Expand Down Expand Up @@ -57,7 +60,8 @@ impl Account {
S: AsRef<str> + 'a,
I: IntoIterator<Item = &'a S>,
{
let key_pair = EcdsaKeyPair::from_pkcs8(ALG, key_pair)?;
let rng = SystemRandom::new();
let key_pair = EcdsaKeyPair::from_pkcs8(ALG, key_pair, &rng)?;
let contact: Vec<&'a str> = contact.into_iter().map(AsRef::<str>::as_ref).collect();
let payload = json!({
"termsOfServiceAgreed": true,
Expand Down Expand Up @@ -178,8 +182,12 @@ impl Account {
params.alg = &PKCS_ECDSA_P256_SHA256;
params.custom_extensions = vec![CustomExtension::new_acme_identifier(key_auth.as_ref())];
let cert = Certificate::from_params(params)?;
let pk = any_ecdsa_type(&PrivateKey(cert.serialize_private_key_der())).unwrap();
let certified_key = CertifiedKey::new(vec![rustls::Certificate(cert.serialize_der()?)], pk);
let pk_bytes = cert.serialize_private_key_der();
let pk_der: PrivatePkcs8KeyDer = pk_bytes.into();
let pk_der: PrivateKeyDer = pk_der.into();
let pk = any_ecdsa_type(&pk_der).unwrap();
let cert_bytes = cert.serialize_der()?;
let certified_key = CertifiedKey::new(vec![cert_bytes.into()], pk);
Ok((challenge, certified_key))
}
}
Expand Down Expand Up @@ -285,7 +293,7 @@ pub enum AcmeError {
#[error("io error: {0}")]
Io(#[from] std::io::Error),
#[error("certificate generation error: {0}")]
Rcgen(#[from] RcgenError),
Rcgen(#[from] rcgen::Error),
#[error("JOSE error: {0}")]
Jose(#[from] JoseError),
#[error("JSON error: {0}")]
Expand Down
1 change: 1 addition & 0 deletions src/caches/test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ use std::sync::Arc;
/// # use tokio_rustls_acme::{AcmeConfig};
/// # use tokio_rustls_acme::caches::{DirCache, TestCache};
/// # let test_environment = true;
/// rustls::crypto::ring::default_provider().install_default().unwrap();
/// let mut config = AcmeConfig::new(["example.com"])
/// .cache(DirCache::new("./cache"));
/// if test_environment {
Expand Down
19 changes: 11 additions & 8 deletions src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ impl AcmeConfig<Infallible, Infallible> {
/// ```rust
/// # use tokio_rustls_acme::AcmeConfig;
/// use tokio_rustls_acme::caches::DirCache;
/// rustls::crypto::ring::default_provider().install_default().unwrap();
/// let config = AcmeConfig::new(["example.com"]).cache(DirCache::new("./rustls_acme_cache"));
/// ```
///
Expand All @@ -43,23 +44,25 @@ impl AcmeConfig<Infallible, Infallible> {
/// ```rust
/// # use tokio_rustls_acme::AcmeConfig;
/// use tokio_rustls_acme::caches::NoCache;
/// rustls::crypto::ring::default_provider().install_default().unwrap();
/// # type EC = std::io::Error;
/// # type EA = EC;
/// let config: AcmeConfig<EC, EA> = AcmeConfig::new(["example.com"]).cache(NoCache::new());
/// ```
///
pub fn new(domains: impl IntoIterator<Item = impl AsRef<str>>) -> Self {
let mut root_store = RootCertStore::empty();
root_store.add_trust_anchors(TLS_SERVER_ROOTS.iter().map(|ta| {
rustls::OwnedTrustAnchor::from_subject_spki_name_constraints(
ta.subject,
ta.spki,
ta.name_constraints,
)
}));
root_store.extend(
TLS_SERVER_ROOTS
.iter()
.map(|ta| rustls::pki_types::TrustAnchor {
subject: ta.subject.clone(),
subject_public_key_info: ta.subject_public_key_info.clone(),
name_constraints: ta.name_constraints.clone(),
}),
);
let client_config = Arc::new(
ClientConfig::builder()
.with_safe_defaults()
.with_root_certificates(root_store)
.with_no_client_auth(),
);
Expand Down
9 changes: 4 additions & 5 deletions src/https_helper.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
use rustls::client::InvalidDnsNameError;
use rustls::ClientConfig;
use std::sync::Arc;
use rustls::{pki_types::InvalidDnsNameError, ClientConfig};
use thiserror::Error;
use std::sync::Arc;

pub use reqwest::{Request, Response};

Expand Down Expand Up @@ -29,9 +28,8 @@ pub(crate) async fn https(
body: Option<String>,
) -> Result<Response, HttpsRequestError> {
let method: reqwest::Method = method.into();
let client_config: ClientConfig = client_config.as_ref().clone();
let client = reqwest::ClientBuilder::new()
.use_preconfigured_tls(client_config)
.use_preconfigured_tls(Arc::clone(client_config))
.build()?;
let mut request = client.request(method, url.as_ref());
if let Some(body) = body {
Expand Down Expand Up @@ -70,3 +68,4 @@ pub enum HttpsRequestError {
#[error("could not determine host from url")]
UndefinedHost,
}

1 change: 0 additions & 1 deletion src/incoming.rs
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,6 @@ impl<
alpn_protocols: Vec<Vec<u8>>,
) -> Self {
let mut config = ServerConfig::builder()
.with_safe_defaults()
.with_no_client_auth()
.with_cert_resolver(state.resolver());
config.alpn_protocols = alpn_protocols;
Expand Down
22 changes: 22 additions & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -131,3 +131,25 @@ pub use config::*;
pub use incoming::*;
pub use resolver::*;
pub use state::*;

#[cfg(test)]
mod test {
use rustls::{crypto, ClientConfig, RootCertStore};
use std::any::Any;

#[test]
fn downcast_client_config() {
crypto::ring::default_provider().install_default().unwrap();

let mut root_store = RootCertStore::empty();
let mut tls = Some(
ClientConfig::builder()
.with_root_certificates(root_store)
.with_no_client_auth(),
);

if let None = (&mut tls as &mut dyn Any).downcast_mut::<Option<rustls::ClientConfig>>() {
panic!("could not downcast client config");
}
}
}
2 changes: 2 additions & 0 deletions src/resolver.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,12 @@ use std::collections::BTreeMap;
use std::sync::Arc;
use std::sync::Mutex;

#[derive(Debug)]
pub struct ResolvesServerCertAcme {
inner: Mutex<Inner>,
}

#[derive(Debug)]
struct Inner {
cert: Option<Arc<CertifiedKey>>,
auth_keys: BTreeMap<String, Arc<CertifiedKey>>,
Expand Down
23 changes: 12 additions & 11 deletions src/state.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,10 @@ use crate::{AcmeConfig, Incoming, ResolvesServerCertAcme};
use chrono::{DateTime, TimeZone, Utc};
use futures::future::try_join_all;
use futures::{ready, FutureExt, Stream};
use rcgen::{CertificateParams, DistinguishedName, RcgenError, PKCS_ECDSA_P256_SHA256};
use rustls::sign::{any_ecdsa_type, CertifiedKey};
use rustls::Certificate as RustlsCertificate;
use rustls::PrivateKey;
use rcgen::{CertificateParams, DistinguishedName, PKCS_ECDSA_P256_SHA256};
use rustls::pki_types::CertificateDer as RustlsCertificate;
use rustls::pki_types::{PrivateKeyDer, PrivatePkcs8KeyDer};
use rustls::{crypto::ring::sign::any_ecdsa_type, sign::CertifiedKey};
use std::convert::Infallible;
use std::fmt::Debug;
use std::future::Future;
Expand Down Expand Up @@ -74,7 +74,7 @@ pub enum OrderError {
#[error("acme error: {0}")]
Acme(#[from] AcmeError),
#[error("certificate generation error: {0}")]
Rcgen(#[from] RcgenError),
Rcgen(#[from] rcgen::Error),
#[error("bad order object: {0:?}")]
BadOrder(Order),
#[error("bad auth object: {0:?}")]
Expand Down Expand Up @@ -159,15 +159,16 @@ impl<EC: 'static + Debug, EA: 'static + Debug> AcmeState<EC, EA> {
if pems.len() < 2 {
return Err(CertParseError::TooFewPem(pems.len()));
}
let pk = match any_ecdsa_type(&PrivateKey(pems.remove(0).into_contents())) {
let pk_bytes = pems.remove(0).into_contents();
let pk_der: PrivatePkcs8KeyDer = pk_bytes.into();
let pk: PrivateKeyDer = pk_der.into();
let pk = match any_ecdsa_type(&pk) {
Ok(pk) => pk,
Err(_) => return Err(CertParseError::InvalidPrivateKey),
};
let cert_chain: Vec<RustlsCertificate> = pems
.into_iter()
.map(|p| RustlsCertificate(p.into_contents()))
.collect();
let validity = match parse_x509_certificate(cert_chain[0].0.as_slice()) {
let cert_chain: Vec<RustlsCertificate> =
pems.into_iter().map(|p| p.into_contents().into()).collect();
let validity = match parse_x509_certificate(cert_chain[0].as_ref()) {
Ok((_, cert)) => {
let validity = cert.validity();
[validity.not_before, validity.not_after]
Expand Down