use openssl::x509::X509;
use serde::{Deserialize, Serialize};
-use proxmox::api::router::SubdirMap;
-use proxmox::api::{api, Permission, Router, RpcEnvironment};
-use proxmox::list_subdirs_api_method;
+use proxmox_router::SubdirMap;
+use proxmox_router::{Permission, Router, RpcEnvironment};
+use proxmox_router::list_subdirs_api_method;
+use proxmox_schema::api;
+
+use pbs_api_types::{NODE_SCHEMA, PRIV_SYS_MODIFY};
+use pbs_buildcfg::configdir;
+use pbs_tools::{task_log, task_warn, cert};
use crate::acme::AcmeClient;
-use crate::api2::types::Authid;
-use crate::api2::types::NODE_SCHEMA;
-use crate::config::acl::PRIV_SYS_MODIFY;
-use crate::config::acme::AcmeDomain;
+use crate::api2::types::AcmeDomain;
use crate::config::node::NodeConfig;
-use crate::server::WorkerTask;
-use crate::tools::cert;
+use proxmox_rest_server::WorkerTask;
pub const ROUTER: Router = Router::new()
.get(&list_subdirs_api_method!(SUBDIRS))
node: { schema: NODE_SCHEMA },
certificates: { description: "PEM encoded certificate (chain)." },
key: { description: "PEM encoded private key." },
+ // FIXME: widget-toolkit should have an option to disable using these 2 parameters...
restart: {
- description: "Restart proxmox-backup-proxy",
+ description: "UI compatibility parameter, ignored",
+ type: Boolean,
optional: true,
default: false,
},
- // FIXME: widget-toolkit should have an option to disable using this parameter...
force: {
description: "Force replacement of existing files.",
type: Boolean,
protected: true,
)]
/// Upload a custom certificate.
-pub fn upload_custom_certificate(
+pub async fn upload_custom_certificate(
certificates: String,
key: String,
- restart: bool,
) -> Result<Vec<CertificateInfo>, Error> {
let certificates = X509::stack_from_pem(certificates.as_bytes())
.map_err(|err| format_err!("failed to decode certificate chain: {}", err))?;
let key = key.private_key_to_pem_pkcs8()?;
- crate::config::set_proxy_certificate(&certificates, &key, restart)?;
+ crate::config::set_proxy_certificate(&certificates, &key)?;
+ crate::server::reload_proxy_certificate().await?;
get_info()
}
properties: {
node: { schema: NODE_SCHEMA },
restart: {
- description: "Restart proxmox-backup-proxy",
+ description: "UI compatibility parameter, ignored",
+ type: Boolean,
optional: true,
default: false,
},
protected: true,
)]
/// Delete the current certificate and regenerate a self signed one.
-pub fn delete_custom_certificate(restart: bool) -> Result<(), Error> {
+pub async fn delete_custom_certificate() -> Result<(), Error> {
let cert_path = configdir!("/proxy.pem");
// Here we fail since if this fails nothing else breaks anyway
std::fs::remove_file(&cert_path)
}
crate::config::update_self_signed_cert(true)?;
-
- if restart {
- crate::config::reload_proxy()?;
- }
+ crate::server::reload_proxy_certificate().await?;
Ok(())
}
};
if domains.is_empty() {
- worker.log("No domains configured to be ordered from an ACME server.");
+ task_log!(worker, "No domains configured to be ordered from an ACME server.");
return Ok(None);
}
let mut acme = node_config.acme_client().await?;
- worker.log("Placing ACME order");
+ task_log!(worker, "Placing ACME order");
let order = acme
.new_order(domains.iter().map(|d| d.domain.to_ascii_lowercase()))
.await?;
- worker.log(format!("Order URL: {}", order.location));
+ task_log!(worker, "Order URL: {}", order.location);
let identifiers: Vec<String> = order
.data
.collect();
for auth_url in &order.data.authorizations {
- worker.log(format!("Getting authorization details from '{}'", auth_url));
+ task_log!(worker, "Getting authorization details from '{}'", auth_url);
let mut auth = acme.get_authorization(&auth_url).await?;
let domain = match &mut auth.identifier {
};
if auth.status == Status::Valid {
- worker.log(format!("{} is already validated!", domain));
+ task_log!(worker, "{} is already validated!", domain);
continue;
}
- worker.log(format!("The validation for {} is pending", domain));
+ task_log!(worker, "The validation for {} is pending", domain);
let domain_config: &AcmeDomain = get_domain_config(&domain)?;
let plugin_id = domain_config.plugin.as_deref().unwrap_or("standalone");
let mut plugin_cfg =
format_err!("plugin '{}' for domain '{}' not found!", plugin_id, domain)
})?;
- worker.log("Setting up validation plugin");
+ task_log!(worker, "Setting up validation plugin");
let validation_url = plugin_cfg
.setup(&mut acme, &auth, domain_config, Arc::clone(&worker))
.await?;
.teardown(&mut acme, &auth, domain_config, Arc::clone(&worker))
.await
{
- worker.warn(format!(
+ task_warn!(
+ worker,
"Failed to teardown plugin '{}' for domain '{}' - {}",
plugin_id, domain, err
- ));
+ );
}
let _: () = result?;
}
- worker.log("All domains validated");
- worker.log("Creating CSR");
+ task_log!(worker, "All domains validated");
+ task_log!(worker, "Creating CSR");
let csr = proxmox_acme_rs::util::Csr::generate(&identifiers, &Default::default())?;
let mut finalize_error_cnt = 0u8;
match order.status {
Status::Pending => {
- worker.log("still pending, trying to finalize anyway");
+ task_log!(worker, "still pending, trying to finalize anyway");
let finalize = order
.finalize
.as_deref()
tokio::time::sleep(Duration::from_secs(5)).await;
}
Status::Ready => {
- worker.log("order is ready, finalizing");
+ task_log!(worker, "order is ready, finalizing");
let finalize = order
.finalize
.as_deref()
tokio::time::sleep(Duration::from_secs(5)).await;
}
Status::Processing => {
- worker.log("still processing, trying again in 30 seconds");
+ task_log!(worker, "still processing, trying again in 30 seconds");
tokio::time::sleep(Duration::from_secs(30)).await;
}
Status::Valid => {
- worker.log("valid");
+ task_log!(worker, "valid");
break;
}
other => bail!("order status: {:?}", other),
}
}
- worker.log("Downloading certificate");
+ task_log!(worker, "Downloading certificate");
let certificate = acme
.get_certificate(
order
auth_url: &str,
validation_url: &str,
) -> Result<(), Error> {
- worker.log("Triggering validation");
+ task_log!(worker, "Triggering validation");
acme.request_challenge_validation(&validation_url).await?;
- worker.log("Sleeping for 5 seconds");
+ task_log!(worker, "Sleeping for 5 seconds");
tokio::time::sleep(Duration::from_secs(5)).await;
loop {
let auth = acme.get_authorization(&auth_url).await?;
match auth.status {
Status::Pending => {
- worker.log("Status is still 'pending', trying again in 10 seconds");
+ task_log!(worker, "Status is still 'pending', trying again in 10 seconds");
tokio::time::sleep(Duration::from_secs(10)).await;
}
Status::Valid => return Ok(()),
/// 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::tools::time::epoch_i64() + 30 * 24 * 60 * 60)
+ cert.is_expired_after_epoch(proxmox_time::epoch_i64() + 30 * 24 * 60 * 60)
.map_err(|err| format_err!("Failed to check certificate expiration date: {}", err))
}
let (node_config, _digest) = crate::config::node::config()?;
- let auth_id: Authid = rpcenv.get_auth_id().unwrap().parse()?;
+ let auth_id = rpcenv.get_auth_id().unwrap();
WorkerTask::spawn(name, None, auth_id, true, move |worker| async move {
if let Some(cert) = order_certificate(worker, &node_config).await? {
- crate::config::set_proxy_certificate(&cert.certificate, &cert.private_key_pem, true)?;
+ crate::config::set_proxy_certificate(&cert.certificate, &cert.private_key_pem)?;
+ crate::server::reload_proxy_certificate().await?;
}
Ok(())
})
let cert_pem = get_certificate_pem()?;
- let auth_id: Authid = rpcenv.get_auth_id().unwrap().parse()?;
+ let auth_id = rpcenv.get_auth_id().unwrap();
WorkerTask::spawn(
"acme-revoke-cert",
auth_id,
true,
move |worker| async move {
- worker.log("Loading ACME account");
+ task_log!(worker, "Loading ACME account");
let mut acme = node_config.acme_client().await?;
- worker.log("Revoking old certificate");
+ task_log!(worker, "Revoking old certificate");
acme.revoke_certificate(cert_pem.as_bytes(), None).await?;
- worker.log("Deleting certificate and regenerating a self-signed one");
- delete_custom_certificate(true)?;
+ task_log!(worker, "Deleting certificate and regenerating a self-signed one");
+ delete_custom_certificate().await?;
Ok(())
},
)