forked from proxmox-mirrors/proxmox-backup
acme: partially fix #6372: scale certificate renewal checks by lifetime
Start renewing a certificate once 2/3 of its total lifetime have passed, instead of the hardcoded 30 days. This stays consistent with many certificates, which are valid for 90 days. The update service runs daily, impose a 3 day minimum remaining lifetime to still be able to handle transient failures for certificate renewals. Signed-off-by: Manuel Federanko <m.federanko@proxmox.com> Fixes: https://bugzilla.proxmox.com/show_bug.cgi?id=6372 Link: https://lore.proxmox.com/20260421144645.275884-1-m.federanko@proxmox.com
This commit is contained in:
parent
9ebd57f889
commit
29bd6b89ca
@ -306,16 +306,33 @@ pub fn new_acme_cert(force: bool, rpcenv: &mut dyn RpcEnvironment) -> Result<Str
|
||||
/// parameter is set).
|
||||
pub fn renew_acme_cert(force: bool, rpcenv: &mut dyn RpcEnvironment) -> Result<String, Error> {
|
||||
if !cert_expires_soon()? && !force {
|
||||
bail!("Certificate does not expire within the next 30 days and 'force' is not set.")
|
||||
let lead = cert_renew_lead_time()? / (24 * 60 * 60);
|
||||
bail!("Certificate does not expire within the next {lead} days and 'force' is not set.")
|
||||
}
|
||||
|
||||
spawn_certificate_worker("acme-renew-cert", force, rpcenv)
|
||||
}
|
||||
|
||||
/// When to start checking for new certs.
|
||||
pub fn cert_renew_lead_time() -> Result<i64, Error> {
|
||||
let cert = pem_to_cert_info(get_certificate_pem()?.as_bytes())?;
|
||||
if let (Some(notafter), Some(notbefore)) =
|
||||
(cert.not_after_unix().ok(), cert.not_before_unix().ok())
|
||||
{
|
||||
// gets usually checked every day by the daily-update service,
|
||||
// start checking at least 3 days before expiry
|
||||
let lifetime = notafter - notbefore;
|
||||
let lead = std::cmp::max(lifetime / 3, 3 * 24 * 60 * 60);
|
||||
Ok(lead)
|
||||
} else {
|
||||
Ok(30 * 24 * 60 * 60)
|
||||
}
|
||||
}
|
||||
|
||||
/// Check whether the current certificate expires within the next 30 days.
|
||||
pub fn cert_expires_soon() -> Result<bool, Error> {
|
||||
let cert = pem_to_cert_info(get_certificate_pem()?.as_bytes())?;
|
||||
cert.is_expired_after_epoch(proxmox_time::epoch_i64() + 30 * 24 * 60 * 60)
|
||||
cert.is_expired_after_epoch(proxmox_time::epoch_i64() + cert_renew_lead_time()?)
|
||||
.map_err(|err| format_err!("Failed to check certificate expiration date: {}", err))
|
||||
}
|
||||
|
||||
|
||||
@ -75,7 +75,8 @@ async fn check_acme_certificates(rpcenv: &mut dyn RpcEnvironment) -> Result<(),
|
||||
}
|
||||
|
||||
if !api2::node::certificates::cert_expires_soon()? {
|
||||
log::info!("Certificate does not expire within the next 30 days, not renewing.");
|
||||
let lead = api2::node::certificates::cert_renew_lead_time()? / (24 * 60 * 60);
|
||||
log::info!("Certificate does not expire within the next {lead} days, not renewing.");
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
|
||||
@ -415,7 +415,8 @@ pub fn plugin_cli() -> CommandLineInterface {
|
||||
async fn order_acme_cert(param: Value, rpcenv: &mut dyn RpcEnvironment) -> Result<(), Error> {
|
||||
if !param["force"].as_bool().unwrap_or(false) && !api2::node::certificates::cert_expires_soon()?
|
||||
{
|
||||
println!("Certificate does not expire within the next 30 days, not renewing.");
|
||||
let lead = api2::node::certificates::cert_renew_lead_time()? / (24 * 60 * 60);
|
||||
println!("Certificate does not expire within the next {lead} days, not renewing.");
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
|
||||
Loading…
Reference in New Issue
Block a user