proxmox-backup/src/api2/config/tape_encryption_keys.rs
2021-01-18 13:38:22 +01:00

167 lines
3.8 KiB
Rust

use anyhow::{bail, Error};
use serde_json::Value;
use proxmox::{
api::{
api,
ApiMethod,
Router,
RpcEnvironment,
},
tools::fs::open_file_locked,
};
use crate::{
config::{
tape_encryption_keys::{
TAPE_KEYS_LOCKFILE,
EncryptionKeyInfo,
load_keys,
save_keys,
},
},
api2::types::{
TAPE_ENCRYPTION_KEY_FINGERPRINT_SCHEMA,
PROXMOX_CONFIG_DIGEST_SCHEMA,
TapeKeyMetadata,
},
backup::Fingerprint,
tools::format::as_fingerprint,
};
#[api(
protected: true,
input: {
properties: {},
},
returns: {
description: "The list of tape encryption keys (with config digest).",
type: Array,
items: { type: TapeKeyMetadata },
},
)]
/// List existing keys
pub fn list_keys(
_param: Value,
_info: &ApiMethod,
mut rpcenv: &mut dyn RpcEnvironment,
) -> Result<Vec<TapeKeyMetadata>, Error> {
let (key_map, digest) = load_keys()?;
let mut list = Vec::new();
for (_fingerprint, item) in key_map {
list.push(TapeKeyMetadata {
hint: item.hint,
fingerprint: as_fingerprint(item.fingerprint.bytes()),
});
}
rpcenv["digest"] = proxmox::tools::digest_to_hex(&digest).into();
Ok(list)
}
#[api(
protected: true,
input: {
properties: {
password: {
description: "A secret password.",
min_length: 5,
},
hint: {
description: "Password restore hint",
min_length: 1,
},
},
},
)]
/// Create a new encryption key
pub fn create_key(
password: String,
hint: String,
_rpcenv: &mut dyn RpcEnvironment
) -> Result<Fingerprint, Error> {
let key = openssl::sha::sha256(password.as_bytes()); // fixme: better KDF ??
let item = EncryptionKeyInfo::new(&key, hint);
let _lock = open_file_locked(
TAPE_KEYS_LOCKFILE,
std::time::Duration::new(10, 0),
true,
)?;
let (mut key_map, _) = load_keys()?;
let fingerprint = item.fingerprint.clone();
if let Some(_) = key_map.get(&fingerprint) {
bail!("encryption key '{}' already exists.", fingerprint);
}
key_map.insert(fingerprint.clone(), item);
save_keys(key_map)?;
Ok(fingerprint)
}
#[api(
protected: true,
input: {
properties: {
fingerprint: {
schema: TAPE_ENCRYPTION_KEY_FINGERPRINT_SCHEMA,
},
digest: {
optional: true,
schema: PROXMOX_CONFIG_DIGEST_SCHEMA,
},
},
},
)]
/// Remove a encryption key from the database
///
/// Please note that you can no longer access tapes using this key.
pub fn delete_key(
fingerprint: Fingerprint,
digest: Option<String>,
_rpcenv: &mut dyn RpcEnvironment,
) -> Result<(), Error> {
let _lock = open_file_locked(
TAPE_KEYS_LOCKFILE,
std::time::Duration::new(10, 0),
true,
)?;
let (mut key_map, expected_digest) = load_keys()?;
if let Some(ref digest) = digest {
let digest = proxmox::tools::hex_to_digest(digest)?;
crate::tools::detect_modified_configuration_file(&digest, &expected_digest)?;
}
match key_map.get(&fingerprint) {
Some(_) => { key_map.remove(&fingerprint); },
None => bail!("tape encryption key '{}' does not exist.", fingerprint),
}
save_keys(key_map)?;
Ok(())
}
const ITEM_ROUTER: Router = Router::new()
//.get(&API_METHOD_READ_KEY_METADATA)
//.put(&API_METHOD_UPDATE_KEY_METADATA)
.delete(&API_METHOD_DELETE_KEY);
pub const ROUTER: Router = Router::new()
.get(&API_METHOD_LIST_KEYS)
.post(&API_METHOD_CREATE_KEY)
.match_all("fingerprint", &ITEM_ROUTER);