all lists on lists.proxmox.com
 help / color / mirror / Atom feed
* [pbs-devel] [PATCH proxmox-backup v7] fix #3854 paperkey import to proxmox-tape
@ 2022-03-24 11:49 Markus Frank
  2022-04-06 14:35 ` [pbs-devel] applied: " Thomas Lamprecht
  0 siblings, 1 reply; 3+ messages in thread
From: Markus Frank @ 2022-03-24 11:49 UTC (permalink / raw)
  To: pbs-devel

added a parameter to the cli for importing tape key via a json-parameter or
via reading a exported paperkey-file or json-file.
For this i also added a backupkey parameter to the api, but here it only
accepts json.

The cli interprets the parameter first as json-string, then json-file
and last as paperkey-file.

functionality:
proxmox-tape key paperkey [fingerprint of existing key] > paperkey.backup
proxmox-tape key restore --backupkey paperkey.backup # key from line above
proxmox-tape key restore --backupkey paperkey.json # only the json
proxmox-tape key restore --backupkey '{"kdf": {"Scrypt": ...' # json as string

for importing the key as paperkey-file it is irrelevant, if the paperkey got exported as html
or txt.

Signed-off-by: Markus Frank <m.frank@proxmox.com>
---
Comments:
 * I would disallow giving this functions both a drivename and a
 backupkey, so that there is no confusion about the behavour.

version 7:
 * moved to restore
 * added json-parameter to cli

version 6:
 * api: removed identical tuple-matching arms and returned to checking parameter-errors
 earlier and adding hint if set afterwards

version 5:
 * removed extract_text_between. I would say we can move it to a
 public function if another component does a similar text-extraction.
 * simplified text extraction

version 4:
 * ParameterError::from to param_bail!
 * when hint and paperkey-file used at the same time, old hint get overwritten
 * added text in pbs-tools with function extract_text_between

version 3:
 * ParameterError with method ParameterError::from
 * changed --paperkey_file to --paperkey-file

version 2:
 * added format_err! and ParameterError
 * changed a few "ifs" to "match"

 src/api2/tape/drive.rs                 | 65 +++++++++++++++++++-------
 src/bin/proxmox_tape/encryption_key.rs | 59 +++++++++++++++++++++--
 2 files changed, 102 insertions(+), 22 deletions(-)

diff --git a/src/api2/tape/drive.rs b/src/api2/tape/drive.rs
index 526743f6..c79688ff 100644
--- a/src/api2/tape/drive.rs
+++ b/src/api2/tape/drive.rs
@@ -10,7 +10,7 @@ use proxmox_sys::sortable;
 use proxmox_router::{
     list_subdirs_api_method, Permission, Router, RpcEnvironment, RpcEnvironmentType, SubdirMap,
 };
-use proxmox_schema::api;
+use proxmox_schema::{api, param_bail};
 use proxmox_section_config::SectionConfigData;
 use proxmox_uuid::Uuid;
 use proxmox_sys::{task_log, task_warn};
@@ -24,6 +24,8 @@ use pbs_api_types::{
 use pbs_api_types::{PRIV_TAPE_AUDIT, PRIV_TAPE_READ, PRIV_TAPE_WRITE};
 
 use pbs_config::CachedUserInfo;
+use pbs_config::key_config::KeyConfig;
+use pbs_config::tape_encryption_keys::insert_key;
 use pbs_tape::{
     BlockReadError,
     sg_tape::tape_alert_flags_critical,
@@ -607,10 +609,18 @@ fn write_media_label(
         properties: {
             drive: {
                 schema: DRIVE_NAME_SCHEMA,
+                optional: true,
             },
             password: {
                 description: "Encryption key password.",
             },
+            backupkey: {
+                description: "A previously exported paperkey in JSON format.",
+                type: String,
+                min_length: 300,
+                max_length: 600,
+                optional: true,
+            },
         },
     },
     access: {
@@ -619,29 +629,48 @@ fn write_media_label(
 )]
 /// Try to restore a tape encryption key
 pub async fn restore_key(
-    drive: String,
+    drive: Option<String>,
     password: String,
+    backupkey: Option<String>,
 ) -> Result<(), Error> {
-    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()?;
+    if (drive.is_none() && backupkey.is_none()) || (drive.is_some() && backupkey.is_some()) {
+        param_bail!(
+            "drive",
+            format_err!("Please specify either a valid drive name or a backupkey")
+        );
+    }
 
-            if let Some(key_config) = key_config {
-                let password_fn = || { Ok(password.as_bytes().to_vec()) };
-                let (key, ..) = key_config.decrypt(&password_fn)?;
-                pbs_config::tape_encryption_keys::insert_key(key, key_config, true)?;
-            } else {
-                bail!("media does not contain any encryption key configuration");
+    if let Some(drive) = 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()?;
+
+                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(backupkey) = backupkey {
+        let key_config: KeyConfig =
+                serde_json::from_str(&backupkey).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(())
 }
 
  #[api(
diff --git a/src/bin/proxmox_tape/encryption_key.rs b/src/bin/proxmox_tape/encryption_key.rs
index 71df9ffa..471a6349 100644
--- a/src/bin/proxmox_tape/encryption_key.rs
+++ b/src/bin/proxmox_tape/encryption_key.rs
@@ -1,8 +1,8 @@
-use anyhow::{bail, Error};
+use anyhow::{bail, format_err, Error};
 use serde_json::Value;
 
 use proxmox_router::{cli::*, ApiHandler, RpcEnvironment};
-use proxmox_schema::api;
+use proxmox_schema::{api, param_bail};
 use proxmox_sys::linux::tty;
 
 use pbs_api_types::{
@@ -12,6 +12,7 @@ use pbs_api_types::{
 
 use pbs_datastore::paperkey::{PaperkeyFormat, generate_paper_key};
 use pbs_config::tape_encryption_keys::{load_key_configs,complete_key_fingerprint};
+use pbs_config::key_config::KeyConfig;
 
 use proxmox_backup::api2;
 
@@ -186,6 +187,9 @@ fn change_passphrase(
     Ok(())
 }
 
+pub const BEGIN_MARKER: &str = "-----BEGIN PROXMOX BACKUP KEY-----";
+pub const END_MARKER: &str = "-----END PROXMOX BACKUP KEY-----";
+
 #[api(
     input: {
         properties: {
@@ -193,23 +197,70 @@ fn change_passphrase(
                 schema: DRIVE_NAME_SCHEMA,
                 optional: true,
             },
+            "backupkey": {
+                description: "Importing a previously exported backupkey with either an exported paperkey-file, json-string or a json-file",
+                type: String,
+                optional: true,
+            },
         },
     },
 )]
 /// Restore encryption key from tape (read password from stdin)
 async fn restore_key(
     mut param: Value,
+    backupkey: Option<String>,
     rpcenv: &mut dyn RpcEnvironment,
 ) -> Result<(), Error> {
 
     let (config, _digest) = pbs_config::drive::config()?;
-    param["drive"] = crate::extract_drive_name(&mut param, &config)?.into();
+
+    let drive = crate::extract_drive_name(&mut param, &config);
 
     if !tty::stdin_isatty() {
         bail!("no password input mechanism available");
     }
 
-    let password = tty::read_password("Tepe Encryption Key Password: ")?;
+    if (drive.is_err() && backupkey.is_none()) || (drive.is_ok() && backupkey.is_some()) {
+        param_bail!(
+            "drive",
+            format_err!("Please specify either a valid drive name or a backupkey")
+        );
+    }
+
+    if drive.is_ok() {
+        param["drive"] = drive.unwrap().into();
+    }
+
+    if let Some(backupkey) = backupkey {
+        if serde_json::from_str::<KeyConfig>(&backupkey).is_ok() {
+            // json as Parameter
+            println!("backupkey to import: {}", backupkey);
+            param["backupkey"] = backupkey.into();
+        } else {
+            println!("backupkey is not a valid json. Interpreting Parameter as a filename");
+            let data = proxmox_sys::fs::file_read_string(backupkey)?;
+            if serde_json::from_str::<KeyConfig>(&data).is_ok() {
+                // standalone json-file
+                println!("backupkey to import: {}", data);
+                param["backupkey"] = data.into();
+            } else {
+                // exported paperkey-file
+                let start = data
+                    .find(BEGIN_MARKER)
+                    .ok_or_else(|| format_err!("cannot find key start marker"))?
+                    + BEGIN_MARKER.len();
+                let data_remain = &data[start..];
+                let end = data_remain
+                    .find(END_MARKER)
+                    .ok_or_else(|| format_err!("cannot find key end marker below start marker"))?;
+                let backupkey_extract = &data_remain[..end];
+                println!("backupkey to import: {}", backupkey_extract);
+                param["backupkey"] = backupkey_extract.into();
+            }
+        }
+    }
+
+    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;
-- 
2.30.2





^ permalink raw reply	[flat|nested] 3+ messages in thread

* [pbs-devel] applied: [PATCH proxmox-backup v7] fix #3854 paperkey import to proxmox-tape
  2022-03-24 11:49 [pbs-devel] [PATCH proxmox-backup v7] fix #3854 paperkey import to proxmox-tape Markus Frank
@ 2022-04-06 14:35 ` Thomas Lamprecht
  2022-04-07  9:42   ` Markus Frank
  0 siblings, 1 reply; 3+ messages in thread
From: Thomas Lamprecht @ 2022-04-06 14:35 UTC (permalink / raw)
  To: Proxmox Backup Server development discussion, Markus Frank

On 24.03.22 12:49, Markus Frank wrote:
> added a parameter to the cli for importing tape key via a json-parameter or
> via reading a exported paperkey-file or json-file.
> For this i also added a backupkey parameter to the api, but here it only
> accepts json.
> 
> The cli interprets the parameter first as json-string, then json-file
> and last as paperkey-file.
> 
> functionality:
> proxmox-tape key paperkey [fingerprint of existing key] > paperkey.backup
> proxmox-tape key restore --backupkey paperkey.backup # key from line above
> proxmox-tape key restore --backupkey paperkey.json # only the json
> proxmox-tape key restore --backupkey '{"kdf": {"Scrypt": ...' # json as string
> 
> for importing the key as paperkey-file it is irrelevant, if the paperkey got exported as html
> or txt.
> 
> Signed-off-by: Markus Frank <m.frank@proxmox.com>
> ---

>  src/api2/tape/drive.rs                 | 65 +++++++++++++++++++-------
>  src/bin/proxmox_tape/encryption_key.rs | 59 +++++++++++++++++++++--
>  2 files changed, 102 insertions(+), 22 deletions(-)
> 
>

applied, thanks! While this was OK code-wise I made a not so small followup commit
for some semantic changes, mostly it was for splitting CLI behavior for key-string
vs. key-file again. Would appreciate if you also re-take a look to ensure I did
not botched something in progress.




^ permalink raw reply	[flat|nested] 3+ messages in thread

* Re: [pbs-devel] applied: [PATCH proxmox-backup v7] fix #3854 paperkey import to proxmox-tape
  2022-04-06 14:35 ` [pbs-devel] applied: " Thomas Lamprecht
@ 2022-04-07  9:42   ` Markus Frank
  0 siblings, 0 replies; 3+ messages in thread
From: Markus Frank @ 2022-04-07  9:42 UTC (permalink / raw)
  To: Thomas Lamprecht, Proxmox Backup Server development discussion

Thanks, nothing is missing and everything should work similar to before.

Commands I tested (valid):
proxmox-tape key restore --key '{...}'
proxmox-tape key restore --key-file paperkey.json
proxmox-tape key restore --key-file paperkey.backup # with markers
proxmox-tape key restore --drive drive1

Error:
proxmox-tape key restore --key-file paperkey.json --key '{"kdf": {...'
proxmox-tape key restore --drive drive1 --key '{"kdf": {...'
proxmox-tape key restore --drive drive1 --key-file test123
proxmox-tape key restore --drive drive1 --key-file test123 \
	--key '{"kdf": {...'

On 4/6/22 16:35, Thomas Lamprecht wrote:
> On 24.03.22 12:49, Markus Frank wrote:
>> added a parameter to the cli for importing tape key via a json-parameter or
>> via reading a exported paperkey-file or json-file.
>> For this i also added a backupkey parameter to the api, but here it only
>> accepts json.
>>
>> The cli interprets the parameter first as json-string, then json-file
>> and last as paperkey-file.
>>
>> functionality:
>> proxmox-tape key paperkey [fingerprint of existing key] > paperkey.backup
>> proxmox-tape key restore --backupkey paperkey.backup # key from line above
>> proxmox-tape key restore --backupkey paperkey.json # only the json
>> proxmox-tape key restore --backupkey '{"kdf": {"Scrypt": ...' # json as string
>>
>> for importing the key as paperkey-file it is irrelevant, if the paperkey got exported as html
>> or txt.
>>
>> Signed-off-by: Markus Frank <m.frank@proxmox.com>
>> ---
> 
>>   src/api2/tape/drive.rs                 | 65 +++++++++++++++++++-------
>>   src/bin/proxmox_tape/encryption_key.rs | 59 +++++++++++++++++++++--
>>   2 files changed, 102 insertions(+), 22 deletions(-)
>>
>>
> 
> applied, thanks! While this was OK code-wise I made a not so small followup commit
> for some semantic changes, mostly it was for splitting CLI behavior for key-string
> vs. key-file again. Would appreciate if you also re-take a look to ensure I did
> not botched something in progress.




^ permalink raw reply	[flat|nested] 3+ messages in thread

end of thread, other threads:[~2022-04-07  9:42 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2022-03-24 11:49 [pbs-devel] [PATCH proxmox-backup v7] fix #3854 paperkey import to proxmox-tape Markus Frank
2022-04-06 14:35 ` [pbs-devel] applied: " Thomas Lamprecht
2022-04-07  9:42   ` Markus Frank

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.
Service provided by Proxmox Server Solutions GmbH | Privacy | Legal