tape: implement change-passphrase for tape encryption keys

This commit is contained in:
Dietmar Maurer 2021-01-20 08:25:42 +01:00
parent e5b6c93323
commit 301b8aa0a5
2 changed files with 130 additions and 1 deletions

View File

@ -30,6 +30,7 @@ use crate::{
TapeKeyMetadata,
},
backup::{
KeyConfig,
Kdf,
Fingerprint,
},
@ -68,6 +69,83 @@ pub fn list_keys(
Ok(list)
}
#[api(
input: {
properties: {
kdf: {
type: Kdf,
optional: true,
},
fingerprint: {
schema: TAPE_ENCRYPTION_KEY_FINGERPRINT_SCHEMA,
},
password: {
description: "The current password.",
min_length: 5,
},
"new-password": {
description: "The new password.",
min_length: 5,
},
hint: {
schema: PASSWORD_HINT_SCHEMA,
},
digest: {
optional: true,
schema: PROXMOX_CONFIG_DIGEST_SCHEMA,
},
},
},
)]
/// Change the encryption key's password (and password hint).
pub fn change_passphrase(
kdf: Option<Kdf>,
password: String,
new_password: String,
hint: String,
fingerprint: Fingerprint,
digest: Option<String>,
_rpcenv: &mut dyn RpcEnvironment
) -> Result<(), Error> {
let kdf = kdf.unwrap_or_default();
if let Kdf::None = kdf {
bail!("Please specify a key derivation funktion (none is not allowed here).");
}
let _lock = open_file_locked(
TAPE_KEYS_LOCKFILE,
std::time::Duration::new(10, 0),
true,
)?;
let (mut config_map, expected_digest) = load_key_configs()?;
if let Some(ref digest) = digest {
let digest = proxmox::tools::hex_to_digest(digest)?;
crate::tools::detect_modified_configuration_file(&digest, &expected_digest)?;
}
let key_config = match config_map.get(&fingerprint) {
Some(key_config) => key_config,
None => bail!("tape encryption key '{}' does not exist.", fingerprint),
};
let (key, created, fingerprint) = key_config.decrypt(&|| Ok(password.as_bytes().to_vec()))?;
let mut new_key_config = KeyConfig::with_key(&key, new_password.as_bytes(), kdf)?;
new_key_config.created = created; // keep original value
new_key_config.fingerprint = Some(fingerprint.clone());
new_key_config.hint = Some(hint);
config_map.insert(fingerprint, new_key_config);
save_key_configs(config_map)?;
Ok(())
}
#[api(
protected: true,
input: {
@ -165,7 +243,7 @@ pub fn delete_key(
const ITEM_ROUTER: Router = Router::new()
//.get(&API_METHOD_READ_KEY_METADATA)
//.put(&API_METHOD_UPDATE_KEY_METADATA)
.put(&API_METHOD_CHANGE_PASSPHRASE)
.delete(&API_METHOD_DELETE_KEY);
pub const ROUTER: Router = Router::new()

View File

@ -17,6 +17,8 @@ use proxmox_backup::{
self,
types::{
DRIVE_NAME_SCHEMA,
TAPE_ENCRYPTION_KEY_FINGERPRINT_SCHEMA,
PASSWORD_HINT_SCHEMA,
},
},
backup::Kdf,
@ -31,6 +33,12 @@ pub fn encryption_key_commands() -> CommandLineInterface {
"create",
CliCommand::new(&API_METHOD_CREATE_KEY)
)
.insert(
"change-passphrase",
CliCommand::new(&API_METHOD_CHANGE_PASSPHRASE)
.arg_param(&["fingerprint"])
.completion_cb("fingerprint", complete_key_fingerprint)
)
.insert(
"restore",
CliCommand::new(&API_METHOD_RESTORE_KEY)
@ -46,6 +54,49 @@ pub fn encryption_key_commands() -> CommandLineInterface {
cmd_def.into()
}
#[api(
input: {
properties: {
kdf: {
type: Kdf,
optional: true,
},
fingerprint: {
schema: TAPE_ENCRYPTION_KEY_FINGERPRINT_SCHEMA,
},
hint: {
schema: PASSWORD_HINT_SCHEMA,
optional: true,
},
},
},
)]
/// Change the encryption key's password.
fn change_passphrase(
mut param: Value,
rpcenv: &mut dyn RpcEnvironment,
) -> Result<(), Error> {
if !tty::stdin_isatty() {
bail!("unable to change passphrase - no tty");
}
let password = tty::read_password("Current Tape Encryption Key Password: ")?;
let new_password = tty::read_and_verify_password("New Tape Encryption Key Password: ")?;
param["password"] = String::from_utf8(password)?.into();
param["new-password"] = String::from_utf8(new_password)?.into();
let info = &api2::config::tape_encryption_keys::API_METHOD_CHANGE_PASSPHRASE;
match info.handler {
ApiHandler::Sync(handler) => (handler)(param, info, rpcenv)?,
_ => unreachable!(),
};
Ok(())
}
#[api(
input: {
properties: {