Files
RustProxy/src/runtime/certificates.rs
T

85 lines
3.0 KiB
Rust

impl App {
pub async fn reload_certificates(self: &Arc<Self>) -> Result<u64, ApiError> {
self.reload_certificate_snapshot(None).await
}
pub async fn reload_certificate(
self: &Arc<Self>,
certificate_id: &str,
) -> Result<u64, ApiError> {
if !crate::config::valid_id(certificate_id) {
return Err(ApiError(
StatusCode::NOT_FOUND,
"certificate not found".into(),
));
}
self.reload_certificate_snapshot(Some(certificate_id)).await
}
async fn reload_certificate_snapshot(
self: &Arc<Self>,
certificate_id: Option<&str>,
) -> Result<u64, ApiError> {
let _lock = self.update_lock.lock().await;
let previous = self.config.load_full();
let desired = previous.envelope.config.clone();
if let Some(certificate_id) = certificate_id {
let certificate = desired
.tls
.certificates
.iter()
.find(|certificate| certificate.id == certificate_id)
.ok_or_else(|| ApiError(StatusCode::NOT_FOUND, "certificate not found".into()))?;
if certificate.issuer.is_some() {
return Err(ApiError(
StatusCode::CONFLICT,
"managed certificates are reloaded by the renewal pipeline".into(),
));
}
}
let desired_vhost_count = desired.vhosts.len();
let observed = self.docker.snapshot().await;
let policy = self.policy.clone();
let defaults = self.startup_listeners;
let active_listeners = self.active_listeners.clone();
let revision = previous.envelope.revision;
let prepared = tokio::task::spawn_blocking(move || {
let effective = crate::docker::effective_config(desired, &observed)?;
let mut prepared = config::compile_with_active(
effective,
revision,
&policy,
defaults,
Some(&previous),
&active_listeners,
)?;
prepared
.envelope
.config
.vhosts
.truncate(desired_vhost_count);
Ok::<_, anyhow::Error>(prepared)
})
.await
.map_err(|_| {
ApiError(
StatusCode::INTERNAL_SERVER_ERROR,
"certificate reload task failed".into(),
)
})?
.map_err(|error| ApiError(StatusCode::UNPROCESSABLE_ENTITY, format!("{error:#}")))?;
self.config.store(Arc::new(prepared));
crate::acl::dynamic::config_changed();
if let Some(certificate_id) = certificate_id {
tracing::info!(
revision,
certificate_id,
"configured certificate reloaded from disk"
);
} else {
tracing::info!(revision, "configured certificates reloaded from disk");
}
Ok(revision)
}
}