Periodically refresh certs for all domains
This commit is contained in:
parent
5b26396106
commit
06cda77772
@ -1,4 +1,5 @@
|
||||
use std::path::{Path, PathBuf};
|
||||
use std::str::FromStr;
|
||||
use std::{fs, io, sync};
|
||||
|
||||
use crate::error::{MapUnexpected, ToUnexpected};
|
||||
@ -37,10 +38,14 @@ pub enum SetError {
|
||||
Unexpected(#[from] error::Unexpected),
|
||||
}
|
||||
|
||||
/// Used in the return from all_domains from Store.
|
||||
pub type AllDomainsResult<T> = Result<T, error::Unexpected>;
|
||||
|
||||
#[mockall::automock]
|
||||
pub trait Store {
|
||||
fn get(&self, domain: &domain::Name) -> Result<Config, GetError>;
|
||||
fn set(&self, domain: &domain::Name, config: &Config) -> Result<(), SetError>;
|
||||
fn all_domains(&self) -> AllDomainsResult<Vec<AllDomainsResult<domain::Name>>>;
|
||||
}
|
||||
|
||||
pub trait BoxedStore: Store + Send + Sync + Clone {}
|
||||
@ -89,6 +94,22 @@ impl Store for sync::Arc<FSStore> {
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn all_domains(&self) -> AllDomainsResult<Vec<AllDomainsResult<domain::Name>>> {
|
||||
Ok(fs::read_dir(&self.dir_path)
|
||||
.map_unexpected()?
|
||||
.map(
|
||||
|dir_entry_res: io::Result<fs::DirEntry>| -> AllDomainsResult<domain::Name> {
|
||||
let domain = dir_entry_res.map_unexpected()?.file_name();
|
||||
let domain = domain.to_str().ok_or_else(|| {
|
||||
error::Unexpected::from("couldn't convert os string to &str")
|
||||
})?;
|
||||
|
||||
Ok(domain::Name::from_str(domain).map_unexpected()?)
|
||||
},
|
||||
)
|
||||
.collect())
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
|
@ -115,6 +115,8 @@ impl From<config::SetError> for SyncWithConfigError {
|
||||
|
||||
pub type GetAcmeHttp01ChallengeKeyError = acme::manager::GetHttp01ChallengeKeyError;
|
||||
|
||||
pub type AllDomainsResult<T> = config::AllDomainsResult<T>;
|
||||
|
||||
#[mockall::automock(
|
||||
type Origin=origin::MockOrigin;
|
||||
type SyncWithConfigFuture=future::Ready<Result<(), SyncWithConfigError>>;
|
||||
@ -153,6 +155,8 @@ pub trait Manager {
|
||||
&self,
|
||||
token: &str,
|
||||
) -> Result<String, GetAcmeHttp01ChallengeKeyError>;
|
||||
|
||||
fn all_domains(&self) -> AllDomainsResult<Vec<AllDomainsResult<domain::Name>>>;
|
||||
}
|
||||
|
||||
pub trait BoxedManager: Manager + Send + Sync + Clone {}
|
||||
@ -283,4 +287,8 @@ where
|
||||
|
||||
Err(GetAcmeHttp01ChallengeKeyError::NotFound)
|
||||
}
|
||||
|
||||
fn all_domains(&self) -> AllDomainsResult<Vec<AllDomainsResult<domain::Name>>> {
|
||||
self.domain_config_store.all_domains()
|
||||
}
|
||||
}
|
||||
|
39
src/main.rs
39
src/main.rs
@ -158,7 +158,7 @@ fn main() {
|
||||
});
|
||||
|
||||
let service = domiply::service::new(
|
||||
manager,
|
||||
manager.clone(),
|
||||
config.domain_checker_target_a,
|
||||
config.passphrase,
|
||||
config.http_domain.clone(),
|
||||
@ -181,6 +181,7 @@ fn main() {
|
||||
|
||||
wait_group.push({
|
||||
let http_domain = config.http_domain.clone();
|
||||
let canceller = canceller.clone();
|
||||
|
||||
tokio_runtime.spawn(async move {
|
||||
let addr = config.http_listen_addr;
|
||||
@ -205,9 +206,20 @@ fn main() {
|
||||
// if there's an acme manager then it means that https is enabled, and we should ensure that
|
||||
// the http domain for domiply itself has a valid certificate.
|
||||
if let Some(domain_acme_manager) = domain_acme_manager {
|
||||
let manager = manager.clone();
|
||||
let canceller = canceller.clone();
|
||||
let http_domain = config.http_domain.clone();
|
||||
|
||||
// Periodically refresh all domain certs
|
||||
wait_group.push(tokio_runtime.spawn(async move {
|
||||
let mut interval = time::interval(time::Duration::from_secs(60 * 60));
|
||||
|
||||
loop {
|
||||
select! {
|
||||
_ = interval.tick() => (),
|
||||
_ = canceller.cancelled() => return,
|
||||
}
|
||||
|
||||
_ = domain_acme_manager
|
||||
.sync_domain(http_domain.clone())
|
||||
.await
|
||||
@ -217,6 +229,31 @@ fn main() {
|
||||
http_domain.as_str()
|
||||
)
|
||||
});
|
||||
|
||||
let domains_iter = manager.all_domains();
|
||||
|
||||
if let Err(err) = domains_iter {
|
||||
println!("Got error calling all_domains: {err}");
|
||||
continue;
|
||||
}
|
||||
|
||||
for domain in domains_iter.unwrap().into_iter() {
|
||||
match domain {
|
||||
Ok(domain) => {
|
||||
let _ = domain_acme_manager
|
||||
.sync_domain(domain.clone())
|
||||
.await
|
||||
.inspect_err(|err| {
|
||||
println!(
|
||||
"Error while getting cert for {}: {err}",
|
||||
domain.as_str(),
|
||||
)
|
||||
});
|
||||
}
|
||||
Err(err) => println!("Error iterating through domains: {err}"),
|
||||
};
|
||||
}
|
||||
}
|
||||
}));
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user