acme-api: adapt to tracing infrastructure

Signed-off-by: Wolfgang Bumiller <w.bumiller@proxmox.com>
This commit is contained in:
Wolfgang Bumiller 2024-07-11 12:59:33 +02:00
parent 2fd7b13fbe
commit cbc30882e7
3 changed files with 62 additions and 77 deletions

View File

@ -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",
] ]

View File

@ -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,
); );
} }
} }

View File

@ -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(()),