[pbs-devel] [PATCH proxmox-backup] proxmox-tape: api: restore_key-code moved to tape-encryption-keys

Markus Frank m.frank at proxmox.com
Wed Apr 13 11:30:04 CEST 2022


The restore_key api-endpoint is tape/drive/{drive}/restore-key.
Since I cannot set the url parameter for the drivename to null or
undefined, when restoring by exported-key, I moved the 
added restore_key-api-code to 
"create_key aka POST api2/json/config/tape-encryption-keys" and
added an ApiHandler call in the cli's "restore_key" to call
"create_key" in the api.

Signed-off-by: Markus Frank <m.frank at proxmox.com>
---
 src/api2/config/tape_encryption_keys.rs | 39 ++++++++++++++++---
 src/api2/tape/drive.rs                  | 51 +++++++------------------
 src/bin/proxmox_tape/encryption_key.rs  | 19 ++++++---
 3 files changed, 61 insertions(+), 48 deletions(-)

diff --git a/src/api2/config/tape_encryption_keys.rs b/src/api2/config/tape_encryption_keys.rs
index 3e9a60d1..ac0e8355 100644
--- a/src/api2/config/tape_encryption_keys.rs
+++ b/src/api2/config/tape_encryption_keys.rs
@@ -174,6 +174,14 @@ pub fn change_passphrase(
             },
             hint: {
                 schema: PASSWORD_HINT_SCHEMA,
+                optional: true,
+            },
+            key: {
+                description: "A previously exported paperkey in JSON format.",
+                type: String,
+                min_length: 300,
+                max_length: 600,
+                optional: true,
             },
         },
     },
@@ -188,7 +196,8 @@ pub fn change_passphrase(
 pub fn create_key(
     kdf: Option<Kdf>,
     password: String,
-    hint: String,
+    hint: Option<String>,
+    key: Option<String>,
     _rpcenv: &mut dyn RpcEnvironment
 ) -> Result<Fingerprint, Error> {
 
@@ -197,13 +206,33 @@ pub fn create_key(
     if let Kdf::None = kdf {
         param_bail!("kdf", format_err!("Please specify a key derivation function (none is not allowed here)."));
     }
+    if hint.is_none() && key.is_none() {
+        param_bail!(
+            "hint",
+            format_err!("Please specify either a hint or a key")
+        );
+    }
 
-    let (key, mut key_config) = KeyConfig::new(password.as_bytes(), kdf)?;
-    key_config.hint = Some(hint);
+    let (key_decrypt, mut key_config, fingerprint) = match key {
+        Some(key) => {
+            let key_config: KeyConfig =
+                serde_json::from_str(&key).map_err(|err| format_err!("<errmsg>: {}", err))?;
+            let password_fn = || Ok(password.as_bytes().to_vec());
+            let (key_decrypt, _created, fingerprint) = key_config.decrypt(&password_fn)?;
+            (key_decrypt, key_config, fingerprint)
+        }
+        None => {
+            let (key_decrypt, key_config) = KeyConfig::new(password.as_bytes(), kdf)?;
+            let fingerprint = key_config.fingerprint.clone().unwrap();
+            (key_decrypt, key_config, fingerprint)
+        }
+    };
 
-    let fingerprint = key_config.fingerprint.clone().unwrap();
+    if hint.is_some() {
+        key_config.hint = hint;
+    }
 
-    insert_key(key, key_config, false)?;
+    insert_key(key_decrypt, key_config, false)?;
 
     Ok(fingerprint)
 }
diff --git a/src/api2/tape/drive.rs b/src/api2/tape/drive.rs
index 70aaf761..c08d650e 100644
--- a/src/api2/tape/drive.rs
+++ b/src/api2/tape/drive.rs
@@ -23,7 +23,6 @@ use pbs_api_types::{
 
 use pbs_api_types::{PRIV_TAPE_AUDIT, PRIV_TAPE_READ, PRIV_TAPE_WRITE};
 
-use pbs_config::key_config::KeyConfig;
 use pbs_config::tape_encryption_keys::insert_key;
 use pbs_config::CachedUserInfo;
 use pbs_tape::{
@@ -610,18 +609,10 @@ fn write_media_label(
             drive: {
                 schema: DRIVE_NAME_SCHEMA,
                 //description: "Restore the key from this drive the (encrypted) key was saved on.",
-                optional: true,
             },
             password: {
                 description: "The password the key was encrypted with.",
             },
-            key: {
-                description: "Restore the key from this JSON string. Clashes with drive.",
-                type: String,
-                min_length: 300,
-                max_length: 600,
-                optional: true,
-            },
         },
     },
     access: {
@@ -630,40 +621,26 @@ fn write_media_label(
 )]
 /// Try to restore a tape encryption key
 pub async fn restore_key(
-    drive: Option<String>,
+    drive: String,
     password: String,
-    key: Option<String>,
 ) -> Result<(), Error> {
-    if drive.is_some() && key.is_some() {
-        bail!("cannot have both 'drive' and 'key' parameter set!");
-    } else if !drive.is_some() && !key.is_some() {
-        bail!("one of either 'drive' or 'key' parameter must be set!");
-    }
 
-    if let Some(drive) = drive {
-        run_drive_blocking_task(drive.clone(), "restore key".to_string(), move |config| {
-            let mut drive = open_drive(&config, &drive)?;
+    run_drive_blocking_task(drive.clone(), "restore key".to_string(), move |config| {
+        let mut drive = open_drive(&config, &drive)?;
 
-            let (_media_id, key_config) = drive.read_label()?;
+        let (_media_id, key_config) = drive.read_label()?;
 
-            if let Some(key_config) = key_config {
-                let password_fn = || Ok(password.as_bytes().to_vec());
-                let (key, ..) = key_config.decrypt(&password_fn)?;
-                insert_key(key, key_config, true)?;
-            } else {
-                bail!("media does not contain any encryption key configuration");
-            }
+        if let Some(key_config) = key_config {
+            let password_fn = || Ok(password.as_bytes().to_vec());
+            let (key, ..) = key_config.decrypt(&password_fn)?;
+            insert_key(key, key_config, true)?;
+        } else {
+            bail!("media does not contain any encryption key configuration");
+        }
 
-            Ok(())
-        })
-        .await?;
-    } else if let Some(key) = key {
-        let key_config: KeyConfig =
-            serde_json::from_str(&key).map_err(|err| format_err!("<errmsg>: {}", err))?;
-        let password_fn = || Ok(password.as_bytes().to_vec());
-        let (key, ..) = key_config.decrypt(&password_fn)?;
-        insert_key(key, key_config, false)?;
-    }
+        Ok(())
+    })
+    .await?;
 
     Ok(())
 }
diff --git a/src/bin/proxmox_tape/encryption_key.rs b/src/bin/proxmox_tape/encryption_key.rs
index d2f33475..c7350a45 100644
--- a/src/bin/proxmox_tape/encryption_key.rs
+++ b/src/bin/proxmox_tape/encryption_key.rs
@@ -247,12 +247,19 @@ async fn restore_key(
 
     let password = tty::read_password("Tape Encryption Key Password: ")?;
     param["password"] = String::from_utf8(password)?.into();
-
-    let info = &api2::tape::drive::API_METHOD_RESTORE_KEY;
-    match info.handler {
-        ApiHandler::Async(handler) => (handler)(param, info, rpcenv).await?,
-        _ => unreachable!(),
-    };
+    if drive_passed {
+        let info = &api2::tape::drive::API_METHOD_RESTORE_KEY;
+        match info.handler {
+            ApiHandler::Async(handler) => (handler)(param, info, rpcenv).await?,
+            _ => unreachable!(),
+        };
+    } else {
+        let info = &api2::config::tape_encryption_keys::API_METHOD_CREATE_KEY;
+        match info.handler {
+            ApiHandler::Sync(handler) => (handler)(param, info, rpcenv)?,
+            _ => unreachable!(),
+        };
+    }
 
     Ok(())
 }
-- 
2.30.2






More information about the pbs-devel mailing list