v0.25.1
This commit is contained in:
1 parent
87e571c170
commit
fa7abc9e53
308 files changed
+49746
-50237
No files matched your search
@@ -0,0 +1,82 @@
|
||||
impl App {
|
||||
/// Re-read configured public certificate/key files and publish a new
|
||||
/// immutable TLS/routing snapshot without changing desired configuration
|
||||
/// or its SQLite revision. Existing connections continue on their current
|
||||
/// TLS session; new H1/H2/H3 handshakes use the refreshed certificates.
|
||||
pub async fn reload_certificates(self: &Arc<Self>) -> Result<u64, ApiError> {
|
||||
self.reload_certificate_snapshot(None).await
|
||||
}
|
||||
|
||||
/// Reload an externally managed/manual certificate by id. The immutable TLS
|
||||
/// resolver is rebuilt as one validated snapshot, so the requested pair is
|
||||
/// re-read atomically with the other configured pairs while desired
|
||||
/// configuration and its revision remain unchanged.
|
||||
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));
|
||||
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)
|
||||
}
|
||||
|
||||
}
|
||||
Reference in new issue
Block a user