5
0
mirror of git://git.proxmox.com/git/proxmox-backup-qemu.git synced 2025-08-26 01:49:21 +03:00

api: add master key support

this is a breaking change/API extension.

Signed-off-by: Fabian Grünbichler <f.gruenbichler@proxmox.com>
This commit is contained in:
Fabian Grünbichler
2021-02-08 14:08:32 +01:00
committed by Thomas Lamprecht
parent 58f4a111bd
commit d8aa155c6c
4 changed files with 56 additions and 9 deletions

View File

@ -176,6 +176,7 @@ ProxmoxBackupHandle *proxmox_backup_new(const char *repo,
const char *password,
const char *keyfile,
const char *key_password,
const char *master_keyfile,
bool compress,
bool encrypt,
const char *fingerprint,

View File

@ -8,9 +8,11 @@ use futures::future::{Future, Either, FutureExt};
use tokio::runtime::Runtime;
use proxmox_backup::tools::runtime::get_runtime_with_builder;
use proxmox_backup::backup::{CryptConfig, CryptMode, BackupDir, BackupManifest, load_and_decrypt_key};
use proxmox_backup::backup::{CryptConfig, CryptMode, BackupDir, BackupManifest, KeyConfig, load_and_decrypt_key, rsa_encrypt_key_config};
use proxmox_backup::client::{HttpClient, HttpClientOptions, BackupWriter};
use proxmox::tools::fs::file_get_contents;
use super::BackupSetup;
use crate::capi_types::*;
use crate::registry::Registry;
@ -22,6 +24,7 @@ pub(crate) struct BackupTask {
compress: bool,
crypt_mode: CryptMode,
crypt_config: Option<Arc<CryptConfig>>,
rsa_encrypted_key: Option<Vec<u8>>,
writer: OnceCell<Arc<BackupWriter>>,
last_manifest: OnceCell<Arc<BackupManifest>>,
manifest: Arc<Mutex<BackupManifest>>,
@ -44,16 +47,28 @@ impl BackupTask {
runtime: Arc<Runtime>
) -> Result<Self, Error> {
let crypt_config = match setup.keyfile {
None => None,
let (crypt_config, rsa_encrypted_key) = match setup.keyfile {
None => (None, None),
Some(ref path) => {
let (key, _, _) = load_and_decrypt_key(path, & || {
let (key, created, _) = load_and_decrypt_key(path, & || {
match setup.key_password {
Some(ref key_password) => Ok(key_password.as_bytes().to_vec()),
None => bail!("no key_password specified"),
}
})?;
Some(Arc::new(CryptConfig::new(key)?))
let rsa_encrypted_key = match setup.master_keyfile {
Some(ref master_keyfile) => {
let pem = file_get_contents(master_keyfile)?;
let rsa = openssl::rsa::Rsa::public_key_from_pem(&pem)?;
let mut key_config = KeyConfig::without_password(key)?;
key_config.created = created; // keep original value
Some(rsa_encrypt_key_config(rsa, &key_config)?)
},
None => None,
};
(Some(Arc::new(CryptConfig::new(key)?)), rsa_encrypted_key)
}
};
@ -65,10 +80,21 @@ impl BackupTask {
let registry = Arc::new(Mutex::new(Registry::<ImageUploadInfo>::new()));
let known_chunks = Arc::new(Mutex::new(HashSet::new()));
Ok(Self { runtime, setup, compress, crypt_mode, crypt_config, abort,
registry, manifest, known_chunks,
writer: OnceCell::new(), last_manifest: OnceCell::new(),
aborted: OnceCell::new() })
Ok(Self {
runtime,
setup,
compress,
crypt_mode,
crypt_config,
rsa_encrypted_key,
abort,
registry,
manifest,
known_chunks,
writer: OnceCell::new(),
last_manifest: OnceCell::new(),
aborted: OnceCell::new()
})
}
pub fn new(setup: BackupSetup, compress: bool, crypt_mode: CryptMode) -> Result<Self, Error> {
@ -258,6 +284,7 @@ impl BackupTask {
let command_future = finish_backup(
self.need_writer()?,
self.crypt_config.clone(),
self.rsa_encrypted_key.clone(),
Arc::clone(&self.manifest),
);

View File

@ -438,8 +438,18 @@ pub(crate) async fn write_data(
pub(crate) async fn finish_backup(
client: Arc<BackupWriter>,
crypt_config: Option<Arc<CryptConfig>>,
rsa_encrypted_key: Option<Vec<u8>>,
manifest: Arc<Mutex<BackupManifest>>,
) -> Result<c_int, Error> {
if let Some(rsa_encrypted_key) = rsa_encrypted_key {
let target = ENCRYPTED_KEY_BLOB_NAME;
let options = UploadOptions { compress: false, encrypt: false, ..UploadOptions::default() };
let stats = client
.upload_blob_from_data(rsa_encrypted_key, target, options)
.await?;
manifest.lock().unwrap().add_file(target.to_string(), stats.size, stats.csum, CryptMode::Encrypt)?;
};
let manifest = {
let guard = manifest.lock().unwrap();

View File

@ -137,6 +137,7 @@ pub(crate) struct BackupSetup {
pub password: String,
pub keyfile: Option<std::path::PathBuf>,
pub key_password: Option<String>,
pub master_keyfile: Option<std::path::PathBuf>,
pub fingerprint: Option<String>,
}
@ -208,6 +209,7 @@ pub extern "C" fn proxmox_backup_new(
password: *const c_char,
keyfile: *const c_char,
key_password: *const c_char,
master_keyfile: *const c_char,
compress: bool,
encrypt: bool,
fingerprint: *const c_char,
@ -227,6 +229,11 @@ pub extern "C" fn proxmox_backup_new(
let keyfile = tools::utf8_c_string(keyfile)?.map(std::path::PathBuf::from);
let key_password = tools::utf8_c_string(key_password)?;
let fingerprint = tools::utf8_c_string(fingerprint)?;
let master_keyfile = tools::utf8_c_string(master_keyfile)?.map(std::path::PathBuf::from);
if master_keyfile.is_some() && keyfile.is_none() {
return Err(format_err!("can't use master keyfile without keyfile"));
}
let crypt_mode = if keyfile.is_some() {
if encrypt { CryptMode::Encrypt } else { CryptMode::SignOnly }
@ -246,6 +253,7 @@ pub extern "C" fn proxmox_backup_new(
backup_time: backup_time as i64,
keyfile,
key_password,
master_keyfile,
fingerprint,
};
@ -720,6 +728,7 @@ pub extern "C" fn proxmox_restore_new(
backup_time,
keyfile,
key_password,
master_keyfile: None,
fingerprint,
};