]> git.proxmox.com Git - proxmox-backup.git/blobdiff - src/api2/node/certificates.rs
update to first proxmox crate split
[proxmox-backup.git] / src / api2 / node / certificates.rs
index edc6e5366675fb11035c5987a56b13b1dbc97ec7..4d26b29f6eb7ebd60cd89a2c46408cb74c38efe5 100644 (file)
@@ -7,18 +7,19 @@ use openssl::pkey::PKey;
 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))
@@ -175,12 +176,13 @@ pub fn get_info() -> Result<Vec<CertificateInfo>, Error> {
             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,
@@ -200,10 +202,9 @@ pub fn get_info() -> Result<Vec<CertificateInfo>, Error> {
     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))?;
@@ -223,7 +224,8 @@ pub fn upload_custom_certificate(
 
     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()
 }
@@ -233,7 +235,8 @@ pub fn upload_custom_certificate(
         properties: {
             node: { schema: NODE_SCHEMA },
             restart: {
-                description: "Restart proxmox-backup-proxy",
+                description: "UI compatibility parameter, ignored",
+                type: Boolean,
                 optional: true,
                 default: false,
             },
@@ -245,7 +248,7 @@ pub fn upload_custom_certificate(
     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)
@@ -263,10 +266,7 @@ pub fn delete_custom_certificate(restart: bool) -> Result<(), Error> {
     }
 
     crate::config::update_self_signed_cert(true)?;
-
-    if restart {
-        crate::config::reload_proxy()?;
-    }
+    crate::server::reload_proxy_certificate().await?;
 
     Ok(())
 }
@@ -304,7 +304,7 @@ async fn order_certificate(
     };
 
     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);
     }
 
@@ -312,11 +312,11 @@ async fn order_certificate(
 
     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
@@ -328,7 +328,7 @@ async fn order_certificate(
         .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 {
@@ -336,11 +336,11 @@ async fn order_certificate(
         };
 
         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 =
@@ -348,7 +348,7 @@ async fn order_certificate(
                 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?;
@@ -359,17 +359,18 @@ async fn order_certificate(
             .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;
@@ -382,7 +383,7 @@ async fn order_certificate(
 
         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()
@@ -397,7 +398,7 @@ async fn order_certificate(
                 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()
@@ -406,18 +407,18 @@ async fn order_certificate(
                 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
@@ -439,10 +440,10 @@ async fn request_validation(
     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 {
@@ -451,7 +452,7 @@ async fn request_validation(
         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(()),
@@ -516,7 +517,7 @@ pub fn renew_acme_cert(force: bool, rpcenv: &mut dyn RpcEnvironment) -> Result<S
 /// 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))
 }
 
@@ -531,11 +532,12 @@ fn spawn_certificate_worker(
 
     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(())
     })
@@ -559,7 +561,7 @@ pub fn revoke_acme_cert(rpcenv: &mut dyn RpcEnvironment) -> Result<String, Error
 
     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",
@@ -567,12 +569,12 @@ pub fn revoke_acme_cert(rpcenv: &mut dyn RpcEnvironment) -> Result<String, Error
         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(())
         },
     )