public inbox for pbs-devel@lists.proxmox.com
 help / color / mirror / Atom feed
From: Dominik Csapak <d.csapak@proxmox.com>
To: Proxmox Backup Server development discussion
	<pbs-devel@lists.proxmox.com>, Markus Frank <m.frank@proxmox.com>
Subject: Re: [pbs-devel] [PATCH proxmox-backup] fix #3854 paperkey import to proxmox-tape
Date: Wed, 9 Feb 2022 14:21:32 +0100	[thread overview]
Message-ID: <035844da-48ae-c5a5-cd15-5b267d31da27@proxmox.com> (raw)
In-Reply-To: <20220208115119.74931-1-m.frank@proxmox.com>

comments inline

On 2/8/22 12:51, Markus Frank wrote:
> added a parameter to the cli for reading a old paperkeyfile to restore
> the key from it. For that i added a json parameter for the api and made
> hint optional because hint is already in the proxmox-backupkey-json.
> 
> functionality:
> proxmox-tape key paperkey [fingerprint of existing key] > paperkey.backup
> proxmox-tape key create --paperkeyfile paperkey.backup
> 
> for importing the key it is irrelevant, if the paperkey got exported as html
> or txt.
> 
> Signed-off-by: Markus Frank <m.frank@proxmox.com>
> ---
>   src/api2/config/tape_encryption_keys.rs | 41 +++++++++++++++++++------
>   src/bin/proxmox_tape/encryption_key.rs  | 28 +++++++++++++++++
>   2 files changed, 60 insertions(+), 9 deletions(-)
> 
> diff --git a/src/api2/config/tape_encryption_keys.rs b/src/api2/config/tape_encryption_keys.rs
> index 1ad99377..23de4acc 100644
> --- a/src/api2/config/tape_encryption_keys.rs
> +++ b/src/api2/config/tape_encryption_keys.rs
> @@ -145,6 +145,12 @@ pub fn change_passphrase(
>               },
>               hint: {
>                   schema: PASSWORD_HINT_SCHEMA,
> +                optional: true,
> +            },
> +            backupkey: {
> +                description: "json parameter for importing old backupkey",

since we want to import a previously exported paperkey, i'd use that
in the description instead, for example

'A previously exported paperkey in JSON format.'

> +                type: String

while having a regex here is not practical (i think), we should
somewhat limit the input a user can send here, we should at least limit
the length here.

> +                optional: true,
>               },
>           },
>       },
> @@ -159,7 +165,8 @@ pub fn change_passphrase(
>   pub fn create_key(
>       kdf: Option<Kdf>,
>       password: String,
> -    hint: String,
> +    hint: Option<String>,
> +    backupkey: Option<String>,
>       _rpcenv: &mut dyn RpcEnvironment
>   ) -> Result<Fingerprint, Error> {
>   
> @@ -169,14 +176,30 @@ pub fn create_key(
>           bail!("Please specify a key derivation function (none is not allowed here).");
>       }
>   
> -    let (key, mut key_config) = KeyConfig::new(password.as_bytes(), kdf)?;
> -    key_config.hint = Some(hint);
> -
> -    let fingerprint = key_config.fingerprint.clone().unwrap();
> -
> -    insert_key(key, key_config, false)?;
> -
> -    Ok(fingerprint)
> +    if let Some(ref backupkey) = backupkey {
> +        match serde_json::from_str::<KeyConfig>(backupkey) {
> +             Ok(key_config) => {
> +                let password_fn = || { Ok(password.as_bytes().to_vec()) };

using 'into_bytes()' here avoids copying it

> +                let (key, _created, fingerprint) = key_config.decrypt(&password_fn)?;
> +                insert_key(key, key_config, false)?;
> +                Ok(fingerprint)
> +             }
> +             Err(err) => {
> +                eprintln!("Couldn't parse data as KeyConfig - {}", err);
> +                bail!("Neither a PEM-formatted private key, nor a PBS key file.");

two things: please do use log::error (or warning) instead of 'eprintln'
and when we return an error, there is no need to print an additional error,

this whole statement can be simplified by doing:

---
let key_config: KeyConfig = serde_json::from_str(backupkey)
     .map_err(|err| format_err!("<errmsg>: {}", err))?;
...
---


> +             }
> +        }
> +    } else {
> +        if hint.is_none() {
> +            bail!("Please specify either a hint or a backupkey.");

we have a special error to bubble parameter errors to the gui
look for 'ParameterError' in proxmox-schema
(basically:

let mut err = ParameterError::new();
err.push("parameter".to_string(), Err(...))
return Err(err);

using that, the api behaves similarly to when the schema verification fails

> +        } else {
> +            let (key, mut key_config) = KeyConfig::new(password.as_bytes(), kdf)?;
> +            key_config.hint = hint;
> +            let fingerprint = key_config.fingerprint.clone().unwrap();
> +            insert_key(key, key_config, false)?;
> +            Ok(fingerprint)
> +        }
> +    }
>   }

the whole if/else could be better written as

match (hint, backupkey) {
     (_, Some(backupkey)) => { }, // handle backupkey
     (Some(hint), _) => { }, // handle hint
     (None, None) => { } // handle parameter error
}

>   
>   
> diff --git a/src/bin/proxmox_tape/encryption_key.rs b/src/bin/proxmox_tape/encryption_key.rs
> index 156295fd..1863c9bc 100644
> --- a/src/bin/proxmox_tape/encryption_key.rs
> +++ b/src/bin/proxmox_tape/encryption_key.rs
> @@ -15,6 +15,8 @@ use pbs_config::tape_encryption_keys::{load_key_configs,complete_key_fingerprint
>   
>   use proxmox_backup::api2;
>   
> +use std::fs;
> +
>   pub fn encryption_key_commands() -> CommandLineInterface {
>   
>       let cmd_def = CliCommandMap::new()
> @@ -222,6 +224,12 @@ async fn restore_key(
>                   type: String,
>                   min_length: 1,
>                   max_length: 32,
> +                optional: true,
> +            },
> +            paperkeyfile: {

nit: i'd prefer 'paperkey-file'

> +                description: "Paperkeyfile location for importing old backupkey",
> +                type: String,
> +                optional: true,
>               },
>           },
>       },
> @@ -230,12 +238,32 @@ async fn restore_key(
>   fn create_key(
>       mut param: Value,
>       rpcenv: &mut dyn RpcEnvironment,
> +    paperkeyfile: Option<String>,
>   ) -> Result<(), Error> {
>   
>       if !tty::stdin_isatty() {
>           bail!("no password input mechanism available");
>       }
>   
> +    if param["hint"].is_null() && paperkeyfile.is_none(){
> +        bail!("Please specify either a hint or a paperkeyfile.");

same as above with ParameterError

> +    }
> +
> +    // searching for PROXMOX BACKUP KEY if a paperkeyfile is defined
> +    if let Some(paperkeyfile) = paperkeyfile {
> +        let data = fs::read_to_string(paperkeyfile)?;

i'd use proxmox-sys::fs::file_read_string here
it's just a thin wrapper around read_to_string, but provides
a better error message

> +        let begin = "-----BEGIN PROXMOX BACKUP KEY-----";
> +        let start = data.find(begin);
> +        let end = data.find("-----END PROXMOX BACKUP KEY-----");
> +        if let Some(start) = start {
> +            if let Some(end) = end {
> +                let backupkey = &data[start+begin.len()..end];

i'd check here if start < end

> +                param["backupkey"]=backupkey.into();
> +                println!("backupkey to import: {}", backupkey);
> +            }
> +        }

this could be better written as:

match (start, end) {
     (Some(start), Some(end)) => {} // set the parameter
     (_, _) => {} // throw error
}

else a file with missing markers will be silently ignored..


> +    }
> +
>       let password = tty::read_and_verify_password("Tape Encryption Key Password: ")?;
>   
>       param["password"] = String::from_utf8(password)?.into();





      reply	other threads:[~2022-02-09 13:22 UTC|newest]

Thread overview: 2+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2022-02-08 11:51 Markus Frank
2022-02-09 13:21 ` Dominik Csapak [this message]

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=035844da-48ae-c5a5-cd15-5b267d31da27@proxmox.com \
    --to=d.csapak@proxmox.com \
    --cc=m.frank@proxmox.com \
    --cc=pbs-devel@lists.proxmox.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
Service provided by Proxmox Server Solutions GmbH | Privacy | Legal