mirror of
https://git.proxmox.com/git/proxmox
synced 2025-07-22 20:50:03 +00:00
acme-api: adapt to tracing infrastructure
Signed-off-by: Wolfgang Bumiller <w.bumiller@proxmox.com>
This commit is contained in:
parent
2fd7b13fbe
commit
cbc30882e7
@ -10,59 +10,62 @@ description = "ACME API implementation"
|
|||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
anyhow.workspace = true
|
anyhow.workspace = true
|
||||||
serde = { workspace = true, features = ["derive"] }
|
|
||||||
serde_json = { workspace = true }
|
|
||||||
base64 = { workspace = true, optional = true }
|
base64 = { workspace = true, optional = true }
|
||||||
tokio = { workspace = true, optional = true, features = ["fs"] }
|
|
||||||
hyper = { workspace = true, optional = true }
|
|
||||||
futures = { workspace = true, optional = true }
|
futures = { workspace = true, optional = true }
|
||||||
|
hex = { workspace = true, optional = true }
|
||||||
http = { workspace = true, optional = true }
|
http = { workspace = true, optional = true }
|
||||||
|
hyper = { workspace = true, optional = true }
|
||||||
|
lazy_static = { workspace = true, optional = true }
|
||||||
log = { workspace = true, optional = true }
|
log = { workspace = true, optional = true }
|
||||||
nix = { workspace = true, optional = true }
|
nix = { workspace = true, optional = true }
|
||||||
hex = { workspace = true, optional = true }
|
serde = { workspace = true, features = ["derive"] }
|
||||||
lazy_static = { workspace = true, optional = true }
|
serde_json = { workspace = true }
|
||||||
|
tokio = { workspace = true, optional = true, features = ["fs"] }
|
||||||
|
|
||||||
|
foreign-types = { workspace = true, optional = true }
|
||||||
libc = { workspace = true, optional = true }
|
libc = { workspace = true, optional = true }
|
||||||
openssl = { workspace = true, optional = true }
|
openssl = { workspace = true, optional = true }
|
||||||
foreign-types = { workspace = true, optional = true }
|
|
||||||
|
|
||||||
|
|
||||||
proxmox-serde.workspace = true
|
|
||||||
proxmox-section-config = { workspace = true, optional = true }
|
|
||||||
proxmox-rest-server = { workspace = true, optional = true }
|
|
||||||
proxmox-router = { workspace = true, optional = true }
|
|
||||||
proxmox-sys = { workspace = true, optional = true }
|
|
||||||
proxmox-schema = { workspace = true, features = ["api-macro", "api-types"] }
|
|
||||||
proxmox-uuid = { workspace = true, optional = true }
|
|
||||||
proxmox-time = { workspace = true, optional = true }
|
|
||||||
proxmox-acme = { workspace = true, features = ["api-types"] }
|
proxmox-acme = { workspace = true, features = ["api-types"] }
|
||||||
proxmox-config-digest = { workspace = true, optional = true }
|
proxmox-config-digest = { workspace = true, optional = true }
|
||||||
|
proxmox-log = { workspace = true, optional = true }
|
||||||
proxmox-product-config = { workspace = true, optional = true }
|
proxmox-product-config = { workspace = true, optional = true }
|
||||||
|
proxmox-rest-server = { workspace = true, optional = true }
|
||||||
|
proxmox-router = { workspace = true, optional = true }
|
||||||
|
proxmox-schema = { workspace = true, features = ["api-macro", "api-types"] }
|
||||||
|
proxmox-section-config = { workspace = true, optional = true }
|
||||||
|
proxmox-serde.workspace = true
|
||||||
|
proxmox-sys = { workspace = true, optional = true }
|
||||||
|
proxmox-time = { workspace = true, optional = true }
|
||||||
|
proxmox-uuid = { workspace = true, optional = true }
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
default = []
|
default = []
|
||||||
impl = [
|
impl = [
|
||||||
"dep:proxmox-uuid",
|
"dep:base64",
|
||||||
"dep:proxmox-time",
|
"dep:foreign-types",
|
||||||
"dep:proxmox-config-digest",
|
|
||||||
"proxmox-config-digest?/openssl",
|
|
||||||
"dep:proxmox-product-config",
|
|
||||||
"proxmox-acme/impl",
|
|
||||||
"proxmox-acme/async-client",
|
|
||||||
"dep:proxmox-section-config",
|
|
||||||
"dep:hex",
|
|
||||||
"dep:lazy_static",
|
|
||||||
"dep:log",
|
|
||||||
"dep:nix",
|
|
||||||
"dep:tokio",
|
|
||||||
"dep:futures",
|
"dep:futures",
|
||||||
|
"dep:hex",
|
||||||
"dep:http",
|
"dep:http",
|
||||||
"dep:hyper",
|
"dep:hyper",
|
||||||
"dep:proxmox-sys",
|
"dep:lazy_static",
|
||||||
|
"dep:libc",
|
||||||
|
"dep:log",
|
||||||
|
"dep:nix",
|
||||||
|
"dep:openssl",
|
||||||
|
"dep:tokio",
|
||||||
|
|
||||||
|
"dep:proxmox-config-digest",
|
||||||
|
"dep:proxmox-log",
|
||||||
|
"dep:proxmox-product-config",
|
||||||
"dep:proxmox-rest-server",
|
"dep:proxmox-rest-server",
|
||||||
"dep:proxmox-router",
|
"dep:proxmox-router",
|
||||||
"dep:base64",
|
"dep:proxmox-section-config",
|
||||||
"dep:libc",
|
"dep:proxmox-sys",
|
||||||
"dep:openssl",
|
"dep:proxmox-time",
|
||||||
"dep:foreign-types",
|
"dep:proxmox-uuid",
|
||||||
|
|
||||||
|
"proxmox-acme/async-client",
|
||||||
|
"proxmox-acme/impl",
|
||||||
|
"proxmox-config-digest?/openssl",
|
||||||
]
|
]
|
||||||
|
@ -7,9 +7,7 @@ use serde_json::json;
|
|||||||
|
|
||||||
use proxmox_acme::async_client::AcmeClient;
|
use proxmox_acme::async_client::AcmeClient;
|
||||||
use proxmox_acme::types::AccountData as AcmeAccountData;
|
use proxmox_acme::types::AccountData as AcmeAccountData;
|
||||||
|
use proxmox_log::warn;
|
||||||
use proxmox_rest_server::WorkerTask;
|
|
||||||
use proxmox_sys::task_warn;
|
|
||||||
|
|
||||||
use crate::account_config::AccountData;
|
use crate::account_config::AccountData;
|
||||||
use crate::config::DEFAULT_ACME_DIRECTORY_ENTRY;
|
use crate::config::DEFAULT_ACME_DIRECTORY_ENTRY;
|
||||||
@ -75,11 +73,7 @@ pub async fn register_account(
|
|||||||
Ok(account.location)
|
Ok(account.location)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn deactivate_account(
|
pub async fn deactivate_account(name: &AcmeAccountName, force: bool) -> Result<(), Error> {
|
||||||
worker: &WorkerTask,
|
|
||||||
name: &AcmeAccountName,
|
|
||||||
force: bool,
|
|
||||||
) -> Result<(), Error> {
|
|
||||||
let mut account_data = super::account_config::load_account_config(name).await?;
|
let mut account_data = super::account_config::load_account_config(name).await?;
|
||||||
let mut client = account_data.client();
|
let mut client = account_data.client();
|
||||||
|
|
||||||
@ -93,11 +87,9 @@ pub async fn deactivate_account(
|
|||||||
}
|
}
|
||||||
Err(err) if !force => return Err(err),
|
Err(err) if !force => return Err(err),
|
||||||
Err(err) => {
|
Err(err) => {
|
||||||
task_warn!(
|
warn!(
|
||||||
worker,
|
|
||||||
"error deactivating account {}, proceedeing anyway - {}",
|
"error deactivating account {}, proceedeing anyway - {}",
|
||||||
name,
|
name, err,
|
||||||
err,
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -10,8 +10,8 @@ use openssl::rsa::Rsa;
|
|||||||
use openssl::x509::{X509Builder, X509};
|
use openssl::x509::{X509Builder, X509};
|
||||||
|
|
||||||
use proxmox_acme::async_client::AcmeClient;
|
use proxmox_acme::async_client::AcmeClient;
|
||||||
|
use proxmox_log::{info, warn};
|
||||||
use proxmox_rest_server::WorkerTask;
|
use proxmox_rest_server::WorkerTask;
|
||||||
use proxmox_sys::{task_log, task_warn};
|
|
||||||
|
|
||||||
use crate::types::{AcmeConfig, AcmeDomain};
|
use crate::types::{AcmeConfig, AcmeDomain};
|
||||||
use crate::CertificateInfo;
|
use crate::CertificateInfo;
|
||||||
@ -47,10 +47,7 @@ pub async fn order_certificate(
|
|||||||
};
|
};
|
||||||
|
|
||||||
if domains.is_empty() {
|
if domains.is_empty() {
|
||||||
task_log!(
|
info!("No domains configured to be ordered from an ACME server.");
|
||||||
worker,
|
|
||||||
"No domains configured to be ordered from an ACME server."
|
|
||||||
);
|
|
||||||
return Ok(None);
|
return Ok(None);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -60,13 +57,13 @@ pub async fn order_certificate(
|
|||||||
|
|
||||||
let (plugins, _) = super::plugin_config::plugin_config()?;
|
let (plugins, _) = super::plugin_config::plugin_config()?;
|
||||||
|
|
||||||
task_log!(worker, "Placing ACME order");
|
info!("Placing ACME order");
|
||||||
|
|
||||||
let order = acme
|
let order = acme
|
||||||
.new_order(domains.iter().map(|d| d.domain.to_ascii_lowercase()))
|
.new_order(domains.iter().map(|d| d.domain.to_ascii_lowercase()))
|
||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
task_log!(worker, "Order URL: {}", order.location);
|
info!("Order URL: {}", order.location);
|
||||||
|
|
||||||
let identifiers: Vec<String> = order
|
let identifiers: Vec<String> = order
|
||||||
.data
|
.data
|
||||||
@ -78,7 +75,7 @@ pub async fn order_certificate(
|
|||||||
.collect();
|
.collect();
|
||||||
|
|
||||||
for auth_url in &order.data.authorizations {
|
for auth_url in &order.data.authorizations {
|
||||||
task_log!(worker, "Getting authorization details from '{}'", auth_url);
|
info!("Getting authorization details from '{}'", auth_url);
|
||||||
let mut auth = acme.get_authorization(auth_url).await?;
|
let mut auth = acme.get_authorization(auth_url).await?;
|
||||||
|
|
||||||
let domain = match &mut auth.identifier {
|
let domain = match &mut auth.identifier {
|
||||||
@ -86,11 +83,11 @@ pub async fn order_certificate(
|
|||||||
};
|
};
|
||||||
|
|
||||||
if auth.status == Status::Valid {
|
if auth.status == Status::Valid {
|
||||||
task_log!(worker, "{} is already validated!", domain);
|
info!("{} is already validated!", domain);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
task_log!(worker, "The validation for {} is pending", domain);
|
info!("The validation for {} is pending", domain);
|
||||||
let domain_config: &AcmeDomain = get_domain_config(&domain)?;
|
let domain_config: &AcmeDomain = get_domain_config(&domain)?;
|
||||||
let plugin_id = domain_config.plugin.as_deref().unwrap_or("standalone");
|
let plugin_id = domain_config.plugin.as_deref().unwrap_or("standalone");
|
||||||
let mut plugin_cfg =
|
let mut plugin_cfg =
|
||||||
@ -98,31 +95,28 @@ pub async fn order_certificate(
|
|||||||
format_err!("plugin '{}' for domain '{}' not found!", plugin_id, domain)
|
format_err!("plugin '{}' for domain '{}' not found!", plugin_id, domain)
|
||||||
})?;
|
})?;
|
||||||
|
|
||||||
task_log!(worker, "Setting up validation plugin");
|
info!("Setting up validation plugin");
|
||||||
let validation_url = plugin_cfg
|
let validation_url = plugin_cfg
|
||||||
.setup(&mut acme, &auth, domain_config, Arc::clone(&worker))
|
.setup(&mut acme, &auth, domain_config, Arc::clone(&worker))
|
||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
let result = request_validation(&worker, &mut acme, auth_url, validation_url).await;
|
let result = request_validation(&mut acme, auth_url, validation_url).await;
|
||||||
|
|
||||||
if let Err(err) = plugin_cfg
|
if let Err(err) = plugin_cfg
|
||||||
.teardown(&mut acme, &auth, domain_config, Arc::clone(&worker))
|
.teardown(&mut acme, &auth, domain_config, Arc::clone(&worker))
|
||||||
.await
|
.await
|
||||||
{
|
{
|
||||||
task_warn!(
|
warn!(
|
||||||
worker,
|
|
||||||
"Failed to teardown plugin '{}' for domain '{}' - {}",
|
"Failed to teardown plugin '{}' for domain '{}' - {}",
|
||||||
plugin_id,
|
plugin_id, domain, err
|
||||||
domain,
|
|
||||||
err
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
result?;
|
result?;
|
||||||
}
|
}
|
||||||
|
|
||||||
task_log!(worker, "All domains validated");
|
info!("All domains validated");
|
||||||
task_log!(worker, "Creating CSR");
|
info!("Creating CSR");
|
||||||
|
|
||||||
let csr = proxmox_acme::util::Csr::generate(&identifiers, &Default::default())?;
|
let csr = proxmox_acme::util::Csr::generate(&identifiers, &Default::default())?;
|
||||||
let mut finalize_error_cnt = 0u8;
|
let mut finalize_error_cnt = 0u8;
|
||||||
@ -135,7 +129,7 @@ pub async fn order_certificate(
|
|||||||
|
|
||||||
match order.status {
|
match order.status {
|
||||||
Status::Pending => {
|
Status::Pending => {
|
||||||
task_log!(worker, "still pending, trying to finalize anyway");
|
info!("still pending, trying to finalize anyway");
|
||||||
let finalize = order
|
let finalize = order
|
||||||
.finalize
|
.finalize
|
||||||
.as_deref()
|
.as_deref()
|
||||||
@ -150,7 +144,7 @@ pub async fn order_certificate(
|
|||||||
tokio::time::sleep(Duration::from_secs(5)).await;
|
tokio::time::sleep(Duration::from_secs(5)).await;
|
||||||
}
|
}
|
||||||
Status::Ready => {
|
Status::Ready => {
|
||||||
task_log!(worker, "order is ready, finalizing");
|
info!("order is ready, finalizing");
|
||||||
let finalize = order
|
let finalize = order
|
||||||
.finalize
|
.finalize
|
||||||
.as_deref()
|
.as_deref()
|
||||||
@ -159,18 +153,18 @@ pub async fn order_certificate(
|
|||||||
tokio::time::sleep(Duration::from_secs(5)).await;
|
tokio::time::sleep(Duration::from_secs(5)).await;
|
||||||
}
|
}
|
||||||
Status::Processing => {
|
Status::Processing => {
|
||||||
task_log!(worker, "still processing, trying again in 30 seconds");
|
info!("still processing, trying again in 30 seconds");
|
||||||
tokio::time::sleep(Duration::from_secs(30)).await;
|
tokio::time::sleep(Duration::from_secs(30)).await;
|
||||||
}
|
}
|
||||||
Status::Valid => {
|
Status::Valid => {
|
||||||
task_log!(worker, "valid");
|
info!("valid");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
other => bail!("order status: {:?}", other),
|
other => bail!("order status: {:?}", other),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
task_log!(worker, "Downloading certificate");
|
info!("Downloading certificate");
|
||||||
let certificate = acme
|
let certificate = acme
|
||||||
.get_certificate(
|
.get_certificate(
|
||||||
order
|
order
|
||||||
@ -187,15 +181,14 @@ pub async fn order_certificate(
|
|||||||
}
|
}
|
||||||
|
|
||||||
async fn request_validation(
|
async fn request_validation(
|
||||||
worker: &WorkerTask,
|
|
||||||
acme: &mut AcmeClient,
|
acme: &mut AcmeClient,
|
||||||
auth_url: &str,
|
auth_url: &str,
|
||||||
validation_url: &str,
|
validation_url: &str,
|
||||||
) -> Result<(), Error> {
|
) -> Result<(), Error> {
|
||||||
task_log!(worker, "Triggering validation");
|
info!("Triggering validation");
|
||||||
acme.request_challenge_validation(validation_url).await?;
|
acme.request_challenge_validation(validation_url).await?;
|
||||||
|
|
||||||
task_log!(worker, "Sleeping for 5 seconds");
|
info!("Sleeping for 5 seconds");
|
||||||
tokio::time::sleep(Duration::from_secs(5)).await;
|
tokio::time::sleep(Duration::from_secs(5)).await;
|
||||||
|
|
||||||
loop {
|
loop {
|
||||||
@ -204,10 +197,7 @@ async fn request_validation(
|
|||||||
let auth = acme.get_authorization(auth_url).await?;
|
let auth = acme.get_authorization(auth_url).await?;
|
||||||
match auth.status {
|
match auth.status {
|
||||||
Status::Pending => {
|
Status::Pending => {
|
||||||
task_log!(
|
info!("Status is still 'pending', trying again in 10 seconds");
|
||||||
worker,
|
|
||||||
"Status is still 'pending', trying again in 10 seconds"
|
|
||||||
);
|
|
||||||
tokio::time::sleep(Duration::from_secs(10)).await;
|
tokio::time::sleep(Duration::from_secs(10)).await;
|
||||||
}
|
}
|
||||||
Status::Valid => return Ok(()),
|
Status::Valid => return Ok(()),
|
||||||
|
Loading…
Reference in New Issue
Block a user