From: Manuel Federanko <m.federanko@proxmox.com>
To: pbs-devel@lists.proxmox.com, pdm-devel@lists.proxmox.com
Subject: [PATCH proxmox 3/7] acme: allow specifying the certificate that is replaced by an order
Date: Thu, 25 Jun 2026 16:13:33 +0200 [thread overview]
Message-ID: <20260625141337.181684-4-m.federanko@proxmox.com> (raw)
In-Reply-To: <20260625141337.181684-1-m.federanko@proxmox.com>
There isn't a foolproof way of determining if the id should be sent
along yet. If the request fails try again without the ari id.
Signed-off-by: Manuel Federanko <m.federanko@proxmox.com>
---
proxmox-acme-api/src/certificate_helpers.rs | 27 ++++++++++++++++++---
proxmox-acme/src/async_client.rs | 18 +++++++++++---
proxmox-acme/src/order.rs | 13 ++++++++++
3 files changed, 51 insertions(+), 7 deletions(-)
diff --git a/proxmox-acme-api/src/certificate_helpers.rs b/proxmox-acme-api/src/certificate_helpers.rs
index 7dc06c2d..5d35f86a 100644
--- a/proxmox-acme-api/src/certificate_helpers.rs
+++ b/proxmox-acme-api/src/certificate_helpers.rs
@@ -65,6 +65,7 @@ pub async fn order_certificate(
worker: Arc<WorkerTask>,
acme_config: &AcmeConfig,
domains: &[AcmeDomain],
+ replaces_certificate_id: Option<&str>,
) -> Result<Option<OrderedCertificate>, Error> {
use proxmox_acme::authorization::Status;
use proxmox_acme::order::Identifier;
@@ -88,10 +89,30 @@ pub async fn order_certificate(
let (plugins, _) = super::plugin_config::plugin_config()?;
info!("Placing ACME order");
-
let order = acme
- .new_order(domains.iter().map(|d| d.domain.to_ascii_lowercase()))
- .await?;
+ .new_order(
+ domains.iter().map(|d| d.domain.to_ascii_lowercase()),
+ replaces_certificate_id,
+ )
+ .await;
+ // there isn't really a nice way to know if a specific certificate
+ // is issued by the acme server, retry without specifying the id
+ // on failures
+ let order = match order {
+ Ok(o) => o,
+ Err(e) => if replaces_certificate_id.is_some() {
+ info!("Failed to place order, retrying without ARI id: {}", e);
+ acme
+ .new_order(
+ domains.iter().map(|d| d.domain.to_ascii_lowercase()),
+ None,
+ )
+ .await?
+ } else {
+ Err(e)?
+ },
+
+ };
info!("Order URL: {}", order.location);
diff --git a/proxmox-acme/src/async_client.rs b/proxmox-acme/src/async_client.rs
index c133a54e..7738346e 100644
--- a/proxmox-acme/src/async_client.rs
+++ b/proxmox-acme/src/async_client.rs
@@ -172,15 +172,25 @@ impl AcmeClient {
///
/// Please remember to persist the order somewhere (ideally along with the account data) in
/// order to finish & query it later on.
- pub async fn new_order<I>(&mut self, domains: I) -> Result<Order, anyhow::Error>
+ pub async fn new_order<I>(
+ &mut self,
+ domains: I,
+ replaces_certificate_id: Option<&str>,
+ ) -> Result<Order, anyhow::Error>
where
I: IntoIterator<Item = String>,
{
let account = Self::need_account(&self.account)?;
- let order = domains
- .into_iter()
- .fold(OrderData::new(), |order, domain| order.domain(domain));
+ let order = {
+ let mut order = domains
+ .into_iter()
+ .fold(OrderData::new(), |order, domain| order.domain(domain));
+ if let Some(replaces_certificate_id) = replaces_certificate_id {
+ order = order.replaces(replaces_certificate_id);
+ }
+ order
+ };
let mut retry = retry();
loop {
diff --git a/proxmox-acme/src/order.rs b/proxmox-acme/src/order.rs
index d75fbde1..36ee5fe1 100644
--- a/proxmox-acme/src/order.rs
+++ b/proxmox-acme/src/order.rs
@@ -81,6 +81,10 @@ pub struct OrderData {
/// List of identifiers to order for the certificate.
pub identifiers: Vec<Identifier>,
+ /// Reference to the certificate being replaced
+ #[serde(skip_serializing_if = "Option::is_none")]
+ pub replaces: Option<String>,
+
/// An RFC3339 formatted time string. It is up to the user to choose a dev dependency for this
/// shit.
#[serde(skip_serializing_if = "Option::is_none")]
@@ -120,6 +124,15 @@ impl OrderData {
self.identifiers.push(Identifier::Dns(domain));
self
}
+
+ /// Builder-style method to specify which certificate this order replaces.
+ pub fn replaces<K>(mut self, ari_id: K) -> Self
+ where
+ K: ToString,
+ {
+ self.replaces = Some(ari_id.to_string());
+ self
+ }
}
/// Represents an order for a new certificate. This combines the order's own location (URL) with
--
2.47.3
next prev parent reply other threads:[~2026-06-25 14:14 UTC|newest]
Thread overview: 8+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-06-25 14:13 [PATCH proxmox{,-backup,-datacenter-manager} 0/7] acme: fix #6372 implement basic ARI support Manuel Federanko
2026-06-25 14:13 ` [PATCH proxmox 1/7] acme: client: add methods to fetch renewal information Manuel Federanko
2026-06-25 14:13 ` [PATCH proxmox 2/7] acme: add retry-after header to " Manuel Federanko
2026-06-25 14:13 ` Manuel Federanko [this message]
2026-06-25 14:13 ` [PATCH proxmox 4/7] acme: cert: add dedicated ari_id field to the certificate info Manuel Federanko
2026-06-25 14:13 ` [PATCH proxmox-backup 5/7] acme: add ari_id to cert info Manuel Federanko
2026-06-25 14:13 ` [PATCH proxmox-backup 6/7] acme: fix #6372 implement ARI renewal information fetching Manuel Federanko
2026-06-25 14:13 ` [PATCH proxmox-datacenter-manager 7/7] acme: fix #6372 use ARI for renewal if available Manuel Federanko
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20260625141337.181684-4-m.federanko@proxmox.com \
--to=m.federanko@proxmox.com \
--cc=pbs-devel@lists.proxmox.com \
--cc=pdm-devel@lists.proxmox.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox