diff --git a/rpxy-acme/src/dir_cache.rs b/rpxy-acme/src/dir_cache.rs
index 2f613d8..33504fa 100644
--- a/rpxy-acme/src/dir_cache.rs
+++ b/rpxy-acme/src/dir_cache.rs
@@ -15,14 +15,14 @@ enum FileType {
Cert,
}
-#[derive(Debug)]
+#[derive(Debug, PartialEq, Eq)]
pub struct DirCache {
- account_dir: PathBuf,
- cert_dir: PathBuf,
+ pub(super) account_dir: PathBuf,
+ pub(super) cert_dir: PathBuf,
}
impl DirCache {
- pub fn new
(dir: P, server_name: impl AsRef) -> Self
+ pub fn new(dir: P, server_name: &str) -> Self
where
P: AsRef,
{
diff --git a/rpxy-acme/src/targets.rs b/rpxy-acme/src/targets.rs
index 08c4685..74e6262 100644
--- a/rpxy-acme/src/targets.rs
+++ b/rpxy-acme/src/targets.rs
@@ -1,32 +1,28 @@
-use crate::dir_cache::DirCache;
use crate::{
constants::{ACME_DIR_URL, ACME_REGISTRY_PATH},
+ dir_cache::DirCache,
error::RpxyAcmeError,
log::*,
};
use rustc_hash::FxHashMap as HashMap;
-use rustls_acme::AcmeConfig;
-use std::{fmt::Debug, path::PathBuf, sync::Arc};
+// use rustls_acme::AcmeConfig;
+use std::path::PathBuf;
use url::Url;
#[derive(Debug)]
/// ACME settings
-pub struct AcmeContexts
-where
- EC: Debug + 'static,
- EA: Debug + 'static,
-{
+pub struct AcmeContexts {
/// ACME directory url
acme_dir_url: Url,
/// ACME registry directory
acme_registry_dir: PathBuf,
/// ACME contacts
contacts: Vec,
- /// ACME config
- inner: HashMap>>,
+ /// ACME directly cache information
+ inner: HashMap,
}
-impl AcmeContexts {
+impl AcmeContexts {
/// Create a new instance. Note that for each domain, a new AcmeConfig is created.
/// This means that for each domain, a distinct operation will be dispatched and separated certificates will be generated.
pub fn try_new(
@@ -35,6 +31,9 @@ impl AcmeContexts {
contacts: &[String],
domains: &[String],
) -> Result {
+ // Install aws_lc_rs as default crypto provider for rustls
+ let _ = rustls::crypto::CryptoProvider::install_default(rustls::crypto::aws_lc_rs::default_provider());
+
let acme_registry_dir = acme_registry_dir
.map(|v| v.to_ascii_lowercase())
.map_or_else(|| PathBuf::from(ACME_REGISTRY_PATH), PathBuf::from);
@@ -46,25 +45,33 @@ impl AcmeContexts {
.as_deref()
.map_or_else(|| Url::parse(ACME_DIR_URL), Url::parse)?;
let contacts = contacts.iter().map(|email| format!("mailto:{email}")).collect::>();
- let rustls_client_config = rustls::ClientConfig::builder()
- .dangerous() // The `Verifier` we're using is actually safe
- .with_custom_certificate_verifier(std::sync::Arc::new(rustls_platform_verifier::Verifier::new()))
- .with_no_client_auth();
- let rustls_client_config = Arc::new(rustls_client_config);
+ // let rustls_client_config = rustls::ClientConfig::builder()
+ // .dangerous() // The `Verifier` we're using is actually safe
+ // .with_custom_certificate_verifier(std::sync::Arc::new(rustls_platform_verifier::Verifier::new()))
+ // .with_no_client_auth();
+ // let rustls_client_config = Arc::new(rustls_client_config);
let inner = domains
.iter()
.map(|domain| {
- let dir_cache = DirCache::new(&acme_registry_dir, domain);
- let config = AcmeConfig::new([domain])
- .contact(&contacts)
- .cache(dir_cache)
- .directory(acme_dir_url.as_str())
- .client_tls_config(rustls_client_config.clone());
- let config = Box::new(config);
- (domain.to_ascii_lowercase(), config)
+ let domain = domain.to_ascii_lowercase();
+ let dir_cache = DirCache::new(&acme_registry_dir, &domain);
+ (domain, dir_cache)
})
.collect::>();
+ // let inner = domains
+ // .iter()
+ // .map(|domain| {
+ // let dir_cache = DirCache::new(&acme_registry_dir, domain);
+ // let config = AcmeConfig::new([domain])
+ // .contact(&contacts)
+ // .cache(dir_cache)
+ // .directory(acme_dir_url.as_str())
+ // .client_tls_config(rustls_client_config.clone());
+ // let config = Box::new(config);
+ // (domain.to_ascii_lowercase(), config)
+ // })
+ // .collect::>();
Ok(Self {
acme_dir_url,
@@ -77,6 +84,8 @@ impl AcmeContexts {
#[cfg(test)]
mod tests {
+ use crate::constants::ACME_ACCOUNT_SUBDIR;
+
use super::*;
#[test]
@@ -84,13 +93,30 @@ mod tests {
let acme_dir_url = "https://acme.example.com/directory";
let acme_registry_dir = "/tmp/acme";
let contacts = vec!["test@example.com".to_string()];
- let acme_contexts: AcmeContexts = AcmeContexts::try_new(
+ let acme_contexts: AcmeContexts = AcmeContexts::try_new(
Some(acme_dir_url),
Some(acme_registry_dir),
&contacts,
&["example.com".to_string(), "example.org".to_string()],
)
.unwrap();
- println!("{:#?}", acme_contexts);
+ assert_eq!(acme_contexts.inner.len(), 2);
+ assert_eq!(acme_contexts.contacts, vec!["mailto:test@example.com".to_string()]);
+ assert_eq!(acme_contexts.acme_dir_url.as_str(), acme_dir_url);
+ assert_eq!(acme_contexts.acme_registry_dir, PathBuf::from(acme_registry_dir));
+ assert_eq!(
+ acme_contexts.inner["example.com"],
+ DirCache {
+ account_dir: PathBuf::from(acme_registry_dir).join(ACME_ACCOUNT_SUBDIR),
+ cert_dir: PathBuf::from(acme_registry_dir).join("example.com"),
+ }
+ );
+ assert_eq!(
+ acme_contexts.inner["example.org"],
+ DirCache {
+ account_dir: PathBuf::from(acme_registry_dir).join(ACME_ACCOUNT_SUBDIR),
+ cert_dir: PathBuf::from(acme_registry_dir).join("example.org"),
+ }
+ );
}
}
diff --git a/rpxy-bin/src/config/parse.rs b/rpxy-bin/src/config/parse.rs
index 741cc7a..3dd6599 100644
--- a/rpxy-bin/src/config/parse.rs
+++ b/rpxy-bin/src/config/parse.rs
@@ -7,7 +7,7 @@ use rpxy_lib::{AppConfig, AppConfigList, ProxyConfig};
use rustc_hash::FxHashMap as HashMap;
#[cfg(feature = "acme")]
-use rpxy_acme::{ACME_DIR_URL, ACME_REGISTRY_PATH};
+use rpxy_acme::{AcmeContexts, ACME_DIR_URL, ACME_REGISTRY_PATH};
/// Parsed options
pub struct Opts {
@@ -160,27 +160,37 @@ pub async fn build_cert_manager(
/// Build acme manager and dummy cert and key as initial states if not exists
/// TODO: CURRENTLY NOT IMPLEMENTED, UNDER DESIGNING
pub async fn build_acme_manager(config: &ConfigToml) -> Result<(), anyhow::Error> {
- // let acme_option = config.experimental.as_ref().and_then(|v| v.acme.clone());
- // if acme_option.is_none() {
- // return Ok(());
- // }
- // let acme_option = acme_option.unwrap();
- // let mut acme_targets = AcmeTargets::try_new(
- // acme_option.email.as_ref(),
- // acme_option.dir_url.as_deref(),
- // acme_option.registry_path.as_deref(),
- // )
- // .map_err(|e| anyhow!("Invalid acme configuration: {e}"))?;
+ let acme_option = config.experimental.as_ref().and_then(|v| v.acme.clone());
+ if acme_option.is_none() {
+ return Ok(());
+ }
+ let acme_option = acme_option.unwrap();
+
+ let domains = config
+ .apps
+ .as_ref()
+ .unwrap()
+ .0
+ .values()
+ .filter_map(|app| {
+ //
+ if let Some(tls) = app.tls.as_ref() {
+ if let Some(true) = tls.acme {
+ return Some(app.server_name.as_ref().unwrap().to_owned());
+ }
+ }
+ None
+ })
+ .collect::>();
+
+ let acme_contexts = AcmeContexts::try_new(
+ acme_option.dir_url.as_deref(),
+ acme_option.registry_path.as_deref(),
+ &[acme_option.email],
+ domains.as_slice(),
+ )?;
- // let apps = config.apps.as_ref().unwrap();
- // for app in apps.0.values() {
- // if let Some(tls) = app.tls.as_ref() {
- // if tls.acme.unwrap_or(false) {
- // acme_targets.add_target(app.server_name.as_ref().unwrap())?;
- // }
- // }
- // }
// TODO: remove later
- // println!("ACME targets: {:#?}", acme_targets);
+ println!("ACME contexts: {:#?}", acme_contexts);
Ok(())
}