introduce a CryptMode enum
This also replaces the recently introduced --encryption parameter on the client with a --crypt-mode parameter. This can be "none", "encrypt" or "sign-only". Note that this introduces various changes in the API types which previously did not take the above distinction into account properly: Both `BackupContent` and the manifest's `FileInfo`: lose `encryption: Option<bool>` gain `crypt_mode: Option<CryptMode>` Within the backup manifest itself, the "crypt-mode" property will always be set. Signed-off-by: Wolfgang Bumiller <w.bumiller@proxmox.com>
This commit is contained in:
parent
56b814e378
commit
f28d9088ed
@ -52,14 +52,14 @@ fn read_backup_index(store: &DataStore, backup_dir: &BackupDir) -> Result<Vec<Ba
|
|||||||
for item in manifest.files() {
|
for item in manifest.files() {
|
||||||
result.push(BackupContent {
|
result.push(BackupContent {
|
||||||
filename: item.filename.clone(),
|
filename: item.filename.clone(),
|
||||||
encrypted: item.encrypted,
|
crypt_mode: Some(item.crypt_mode),
|
||||||
size: Some(item.size),
|
size: Some(item.size),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
result.push(BackupContent {
|
result.push(BackupContent {
|
||||||
filename: MANIFEST_BLOB_NAME.to_string(),
|
filename: MANIFEST_BLOB_NAME.to_string(),
|
||||||
encrypted: Some(false),
|
crypt_mode: None,
|
||||||
size: Some(index_size),
|
size: Some(index_size),
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -79,7 +79,11 @@ fn get_all_snapshot_files(
|
|||||||
|
|
||||||
for file in &info.files {
|
for file in &info.files {
|
||||||
if file_set.contains(file) { continue; }
|
if file_set.contains(file) { continue; }
|
||||||
files.push(BackupContent { filename: file.to_string(), size: None, encrypted: None });
|
files.push(BackupContent {
|
||||||
|
filename: file.to_string(),
|
||||||
|
size: None,
|
||||||
|
crypt_mode: None,
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(files)
|
Ok(files)
|
||||||
@ -350,7 +354,15 @@ pub fn list_snapshots (
|
|||||||
},
|
},
|
||||||
Err(err) => {
|
Err(err) => {
|
||||||
eprintln!("error during snapshot file listing: '{}'", err);
|
eprintln!("error during snapshot file listing: '{}'", err);
|
||||||
info.files.iter().map(|x| BackupContent { filename: x.to_string(), size: None, encrypted: None }).collect()
|
info
|
||||||
|
.files
|
||||||
|
.iter()
|
||||||
|
.map(|x| BackupContent {
|
||||||
|
filename: x.to_string(),
|
||||||
|
size: None,
|
||||||
|
crypt_mode: None,
|
||||||
|
})
|
||||||
|
.collect()
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -902,7 +914,7 @@ fn download_file_decoded(
|
|||||||
|
|
||||||
let files = read_backup_index(&datastore, &backup_dir)?;
|
let files = read_backup_index(&datastore, &backup_dir)?;
|
||||||
for file in files {
|
for file in files {
|
||||||
if file.filename == file_name && file.encrypted == Some(true) {
|
if file.filename == file_name && file.crypt_mode == Some(CryptMode::Encrypt) {
|
||||||
bail!("cannot decode '{}' - is encrypted", file_name);
|
bail!("cannot decode '{}' - is encrypted", file_name);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -5,6 +5,8 @@ use proxmox::api::{api, schema::*};
|
|||||||
use proxmox::const_regex;
|
use proxmox::const_regex;
|
||||||
use proxmox::{IPRE, IPV4RE, IPV6RE, IPV4OCTET, IPV6H16, IPV6LS32};
|
use proxmox::{IPRE, IPV4RE, IPV6RE, IPV4OCTET, IPV6H16, IPV6LS32};
|
||||||
|
|
||||||
|
use crate::backup::CryptMode;
|
||||||
|
|
||||||
// File names: may not contain slashes, may not start with "."
|
// File names: may not contain slashes, may not start with "."
|
||||||
pub const FILENAME_FORMAT: ApiStringFormat = ApiStringFormat::VerifyFn(|name| {
|
pub const FILENAME_FORMAT: ApiStringFormat = ApiStringFormat::VerifyFn(|name| {
|
||||||
if name.starts_with('.') {
|
if name.starts_with('.') {
|
||||||
@ -496,6 +498,10 @@ pub const PRUNE_SCHEMA_KEEP_YEARLY: Schema = IntegerSchema::new(
|
|||||||
"filename": {
|
"filename": {
|
||||||
schema: BACKUP_ARCHIVE_NAME_SCHEMA,
|
schema: BACKUP_ARCHIVE_NAME_SCHEMA,
|
||||||
},
|
},
|
||||||
|
"crypt-mode": {
|
||||||
|
type: CryptMode,
|
||||||
|
optional: true,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
)]
|
)]
|
||||||
#[derive(Serialize, Deserialize)]
|
#[derive(Serialize, Deserialize)]
|
||||||
@ -503,9 +509,9 @@ pub const PRUNE_SCHEMA_KEEP_YEARLY: Schema = IntegerSchema::new(
|
|||||||
/// Basic information about archive files inside a backup snapshot.
|
/// Basic information about archive files inside a backup snapshot.
|
||||||
pub struct BackupContent {
|
pub struct BackupContent {
|
||||||
pub filename: String,
|
pub filename: String,
|
||||||
/// Info if file is encrypted (or empty if we do not have that info)
|
/// Info if file is encrypted, signed, or neither.
|
||||||
#[serde(skip_serializing_if="Option::is_none")]
|
#[serde(skip_serializing_if="Option::is_none")]
|
||||||
pub encrypted: Option<bool>,
|
pub crypt_mode: Option<CryptMode>,
|
||||||
/// Archive size (from backup manifest).
|
/// Archive size (from backup manifest).
|
||||||
#[serde(skip_serializing_if="Option::is_none")]
|
#[serde(skip_serializing_if="Option::is_none")]
|
||||||
pub size: Option<u64>,
|
pub size: Option<u64>,
|
||||||
|
@ -6,12 +6,40 @@
|
|||||||
//! See the Wikipedia Artikel for [Authenticated
|
//! See the Wikipedia Artikel for [Authenticated
|
||||||
//! encryption](https://en.wikipedia.org/wiki/Authenticated_encryption)
|
//! encryption](https://en.wikipedia.org/wiki/Authenticated_encryption)
|
||||||
//! for a short introduction.
|
//! for a short introduction.
|
||||||
use anyhow::{bail, Error};
|
|
||||||
use openssl::pkcs5::pbkdf2_hmac;
|
|
||||||
use openssl::hash::MessageDigest;
|
|
||||||
use openssl::symm::{decrypt_aead, Cipher, Crypter, Mode};
|
|
||||||
use std::io::Write;
|
use std::io::Write;
|
||||||
|
|
||||||
|
use anyhow::{bail, Error};
|
||||||
use chrono::{Local, TimeZone, DateTime};
|
use chrono::{Local, TimeZone, DateTime};
|
||||||
|
use openssl::hash::MessageDigest;
|
||||||
|
use openssl::pkcs5::pbkdf2_hmac;
|
||||||
|
use openssl::symm::{decrypt_aead, Cipher, Crypter, Mode};
|
||||||
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
|
use proxmox::api::api;
|
||||||
|
|
||||||
|
#[api(default: "encrypt")]
|
||||||
|
#[derive(Copy, Clone, Debug, Eq, PartialEq, Deserialize, Serialize)]
|
||||||
|
#[serde(rename_all = "kebab-case")]
|
||||||
|
/// Defines whether data is encrypted (using an AEAD cipher), only signed, or neither.
|
||||||
|
pub enum CryptMode {
|
||||||
|
/// Don't encrypt.
|
||||||
|
None,
|
||||||
|
/// Encrypt.
|
||||||
|
Encrypt,
|
||||||
|
/// Only sign.
|
||||||
|
SignOnly,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl CryptMode {
|
||||||
|
/// Maps values other than `None` to `SignOnly`.
|
||||||
|
pub fn sign_only(self) -> Self {
|
||||||
|
match self {
|
||||||
|
CryptMode::None => CryptMode::None,
|
||||||
|
_ => CryptMode::SignOnly,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Encryption Configuration with secret key
|
/// Encryption Configuration with secret key
|
||||||
///
|
///
|
||||||
@ -26,7 +54,6 @@ pub struct CryptConfig {
|
|||||||
id_pkey: openssl::pkey::PKey<openssl::pkey::Private>,
|
id_pkey: openssl::pkey::PKey<openssl::pkey::Private>,
|
||||||
// The private key used by the cipher.
|
// The private key used by the cipher.
|
||||||
enc_key: [u8; 32],
|
enc_key: [u8; 32],
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl CryptConfig {
|
impl CryptConfig {
|
||||||
|
@ -4,14 +4,14 @@ use std::path::Path;
|
|||||||
|
|
||||||
use serde_json::{json, Value};
|
use serde_json::{json, Value};
|
||||||
|
|
||||||
use crate::backup::BackupDir;
|
use crate::backup::{BackupDir, CryptMode};
|
||||||
|
|
||||||
pub const MANIFEST_BLOB_NAME: &str = "index.json.blob";
|
pub const MANIFEST_BLOB_NAME: &str = "index.json.blob";
|
||||||
pub const CLIENT_LOG_BLOB_NAME: &str = "client.log.blob";
|
pub const CLIENT_LOG_BLOB_NAME: &str = "client.log.blob";
|
||||||
|
|
||||||
pub struct FileInfo {
|
pub struct FileInfo {
|
||||||
pub filename: String,
|
pub filename: String,
|
||||||
pub encrypted: Option<bool>,
|
pub crypt_mode: CryptMode,
|
||||||
pub size: u64,
|
pub size: u64,
|
||||||
pub csum: [u8; 32],
|
pub csum: [u8; 32],
|
||||||
}
|
}
|
||||||
@ -49,9 +49,9 @@ impl BackupManifest {
|
|||||||
Self { files: Vec::new(), snapshot }
|
Self { files: Vec::new(), snapshot }
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn add_file(&mut self, filename: String, size: u64, csum: [u8; 32], encrypted: Option<bool>) -> Result<(), Error> {
|
pub fn add_file(&mut self, filename: String, size: u64, csum: [u8; 32], crypt_mode: CryptMode) -> Result<(), Error> {
|
||||||
let _archive_type = archive_type(&filename)?; // check type
|
let _archive_type = archive_type(&filename)?; // check type
|
||||||
self.files.push(FileInfo { filename, size, csum, encrypted });
|
self.files.push(FileInfo { filename, size, csum, crypt_mode });
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -91,18 +91,12 @@ impl BackupManifest {
|
|||||||
"backup-time": self.snapshot.backup_time().timestamp(),
|
"backup-time": self.snapshot.backup_time().timestamp(),
|
||||||
"files": self.files.iter()
|
"files": self.files.iter()
|
||||||
.fold(Vec::new(), |mut acc, info| {
|
.fold(Vec::new(), |mut acc, info| {
|
||||||
let mut value = json!({
|
acc.push(json!({
|
||||||
"filename": info.filename,
|
"filename": info.filename,
|
||||||
"encrypted": info.encrypted,
|
"crypt-mode": info.crypt_mode,
|
||||||
"size": info.size,
|
"size": info.size,
|
||||||
"csum": proxmox::tools::digest_to_hex(&info.csum),
|
"csum": proxmox::tools::digest_to_hex(&info.csum),
|
||||||
});
|
}));
|
||||||
|
|
||||||
if let Some(encrypted) = info.encrypted {
|
|
||||||
value["encrypted"] = encrypted.into();
|
|
||||||
}
|
|
||||||
|
|
||||||
acc.push(value);
|
|
||||||
acc
|
acc
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
@ -142,8 +136,8 @@ impl TryFrom<Value> for BackupManifest {
|
|||||||
let csum = required_string_property(item, "csum")?;
|
let csum = required_string_property(item, "csum")?;
|
||||||
let csum = proxmox::tools::hex_to_digest(csum)?;
|
let csum = proxmox::tools::hex_to_digest(csum)?;
|
||||||
let size = required_integer_property(item, "size")? as u64;
|
let size = required_integer_property(item, "size")? as u64;
|
||||||
let encrypted = item["encrypted"].as_bool();
|
let crypt_mode: CryptMode = serde_json::from_value(item["crypt-mode"].clone())?;
|
||||||
manifest.add_file(filename, size, csum, encrypted)?;
|
manifest.add_file(filename, size, csum, crypt_mode)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
if manifest.files().is_empty() {
|
if manifest.files().is_empty() {
|
||||||
|
@ -35,11 +35,12 @@ use proxmox_backup::backup::{
|
|||||||
BackupGroup,
|
BackupGroup,
|
||||||
BackupManifest,
|
BackupManifest,
|
||||||
BufferedDynamicReader,
|
BufferedDynamicReader,
|
||||||
|
CATALOG_NAME,
|
||||||
CatalogReader,
|
CatalogReader,
|
||||||
CatalogWriter,
|
CatalogWriter,
|
||||||
CATALOG_NAME,
|
|
||||||
ChunkStream,
|
ChunkStream,
|
||||||
CryptConfig,
|
CryptConfig,
|
||||||
|
CryptMode,
|
||||||
DataBlob,
|
DataBlob,
|
||||||
DynamicIndexReader,
|
DynamicIndexReader,
|
||||||
FixedChunkStream,
|
FixedChunkStream,
|
||||||
@ -664,34 +665,41 @@ fn spawn_catalog_upload(
|
|||||||
Ok((catalog, catalog_result_rx))
|
Ok((catalog, catalog_result_rx))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn keyfile_parameters(param: &Value) -> Result<Option<PathBuf>, Error> {
|
fn keyfile_parameters(param: &Value) -> Result<(Option<PathBuf>, CryptMode), Error> {
|
||||||
Ok(match (param.get("keyfile"), param.get("encryption")) {
|
let keyfile = match param.get("keyfile") {
|
||||||
|
Some(Value::String(keyfile)) => Some(keyfile),
|
||||||
|
Some(_) => bail!("bad --keyfile parameter type"),
|
||||||
|
None => None,
|
||||||
|
};
|
||||||
|
|
||||||
|
let crypt_mode: Option<CryptMode> = match param.get("crypt-mode") {
|
||||||
|
Some(mode) => Some(serde_json::from_value(mode.clone())?),
|
||||||
|
None => None,
|
||||||
|
};
|
||||||
|
|
||||||
|
Ok(match (keyfile, crypt_mode) {
|
||||||
// no parameters:
|
// no parameters:
|
||||||
(None, None) => key::optional_default_key_path()?,
|
(None, None) => (key::optional_default_key_path()?, CryptMode::Encrypt),
|
||||||
|
|
||||||
// just --encryption=false
|
// just --crypt-mode=none
|
||||||
(None, Some(Value::Bool(false))) => None,
|
(None, Some(CryptMode::None)) => (None, CryptMode::None),
|
||||||
|
|
||||||
// just --encryption=true
|
// just --crypt-mode other than none
|
||||||
(None, Some(Value::Bool(true))) => match key::optional_default_key_path()? {
|
(None, Some(crypt_mode)) => match key::optional_default_key_path()? {
|
||||||
None => bail!("--encryption=false without --keyfile and no default key file available"),
|
None => bail!("--crypt-mode without --keyfile and no default key file available"),
|
||||||
Some(path) => Some(path),
|
Some(path) => (Some(path), crypt_mode),
|
||||||
}
|
}
|
||||||
|
|
||||||
// just --keyfile
|
// just --keyfile
|
||||||
(Some(Value::String(keyfile)), None) => Some(PathBuf::from(keyfile)),
|
(Some(keyfile), None) => (Some(PathBuf::from(keyfile)), CryptMode::Encrypt),
|
||||||
|
|
||||||
// --keyfile and --encryption=false
|
// --keyfile and --crypt-mode=none
|
||||||
(Some(Value::String(_)), Some(Value::Bool(false))) => {
|
(Some(_), Some(CryptMode::None)) => {
|
||||||
bail!("--keyfile and --encryption=false are mutually exclusive");
|
bail!("--keyfile and --crypt-mode=none are mutually exclusive");
|
||||||
}
|
}
|
||||||
|
|
||||||
// --keyfile and --encryption=true
|
// --keyfile and --crypt-mode other than none
|
||||||
(Some(Value::String(keyfile)), Some(Value::Bool(true))) => Some(PathBuf::from(keyfile)),
|
(Some(keyfile), Some(crypt_mode)) => (Some(PathBuf::from(keyfile)), crypt_mode),
|
||||||
|
|
||||||
// wrong value types:
|
|
||||||
(Some(_), _) => bail!("bad --keyfile parameter"),
|
|
||||||
(_, Some(_)) => bail!("bad --encryption parameter"),
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -794,7 +802,7 @@ async fn create_backup(
|
|||||||
verify_chunk_size(size)?;
|
verify_chunk_size(size)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
let keyfile = keyfile_parameters(¶m)?;
|
let (keyfile, crypt_mode) = keyfile_parameters(¶m)?;
|
||||||
|
|
||||||
let backup_id = param["backup-id"].as_str().unwrap_or(&proxmox::tools::nodename());
|
let backup_id = param["backup-id"].as_str().unwrap_or(&proxmox::tools::nodename());
|
||||||
|
|
||||||
@ -912,8 +920,6 @@ async fn create_backup(
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
let is_encrypted = Some(crypt_config.is_some());
|
|
||||||
|
|
||||||
let client = BackupWriter::start(
|
let client = BackupWriter::start(
|
||||||
client,
|
client,
|
||||||
crypt_config.clone(),
|
crypt_config.clone(),
|
||||||
@ -941,16 +947,16 @@ async fn create_backup(
|
|||||||
BackupSpecificationType::CONFIG => {
|
BackupSpecificationType::CONFIG => {
|
||||||
println!("Upload config file '{}' to '{:?}' as {}", filename, repo, target);
|
println!("Upload config file '{}' to '{:?}' as {}", filename, repo, target);
|
||||||
let stats = client
|
let stats = client
|
||||||
.upload_blob_from_file(&filename, &target, true, Some(true))
|
.upload_blob_from_file(&filename, &target, true, crypt_mode)
|
||||||
.await?;
|
.await?;
|
||||||
manifest.add_file(target, stats.size, stats.csum, is_encrypted)?;
|
manifest.add_file(target, stats.size, stats.csum, crypt_mode)?;
|
||||||
}
|
}
|
||||||
BackupSpecificationType::LOGFILE => { // fixme: remove - not needed anymore ?
|
BackupSpecificationType::LOGFILE => { // fixme: remove - not needed anymore ?
|
||||||
println!("Upload log file '{}' to '{:?}' as {}", filename, repo, target);
|
println!("Upload log file '{}' to '{:?}' as {}", filename, repo, target);
|
||||||
let stats = client
|
let stats = client
|
||||||
.upload_blob_from_file(&filename, &target, true, Some(true))
|
.upload_blob_from_file(&filename, &target, true, crypt_mode)
|
||||||
.await?;
|
.await?;
|
||||||
manifest.add_file(target, stats.size, stats.csum, is_encrypted)?;
|
manifest.add_file(target, stats.size, stats.csum, crypt_mode)?;
|
||||||
}
|
}
|
||||||
BackupSpecificationType::PXAR => {
|
BackupSpecificationType::PXAR => {
|
||||||
// start catalog upload on first use
|
// start catalog upload on first use
|
||||||
@ -976,7 +982,7 @@ async fn create_backup(
|
|||||||
pattern_list.clone(),
|
pattern_list.clone(),
|
||||||
entries_max as usize,
|
entries_max as usize,
|
||||||
).await?;
|
).await?;
|
||||||
manifest.add_file(target, stats.size, stats.csum, is_encrypted)?;
|
manifest.add_file(target, stats.size, stats.csum, crypt_mode)?;
|
||||||
catalog.lock().unwrap().end_directory()?;
|
catalog.lock().unwrap().end_directory()?;
|
||||||
}
|
}
|
||||||
BackupSpecificationType::IMAGE => {
|
BackupSpecificationType::IMAGE => {
|
||||||
@ -990,7 +996,7 @@ async fn create_backup(
|
|||||||
chunk_size_opt,
|
chunk_size_opt,
|
||||||
verbose,
|
verbose,
|
||||||
).await?;
|
).await?;
|
||||||
manifest.add_file(target, stats.size, stats.csum, is_encrypted)?;
|
manifest.add_file(target, stats.size, stats.csum, crypt_mode)?;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1007,7 +1013,7 @@ async fn create_backup(
|
|||||||
|
|
||||||
if let Some(catalog_result_rx) = catalog_result_tx {
|
if let Some(catalog_result_rx) = catalog_result_tx {
|
||||||
let stats = catalog_result_rx.await??;
|
let stats = catalog_result_rx.await??;
|
||||||
manifest.add_file(CATALOG_NAME.to_owned(), stats.size, stats.csum, is_encrypted)?;
|
manifest.add_file(CATALOG_NAME.to_owned(), stats.size, stats.csum, crypt_mode)?;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1015,9 +1021,9 @@ async fn create_backup(
|
|||||||
let target = "rsa-encrypted.key";
|
let target = "rsa-encrypted.key";
|
||||||
println!("Upload RSA encoded key to '{:?}' as {}", repo, target);
|
println!("Upload RSA encoded key to '{:?}' as {}", repo, target);
|
||||||
let stats = client
|
let stats = client
|
||||||
.upload_blob_from_data(rsa_encrypted_key, target, false, None)
|
.upload_blob_from_data(rsa_encrypted_key, target, false, CryptMode::None)
|
||||||
.await?;
|
.await?;
|
||||||
manifest.add_file(format!("{}.blob", target), stats.size, stats.csum, is_encrypted)?;
|
manifest.add_file(format!("{}.blob", target), stats.size, stats.csum, crypt_mode)?;
|
||||||
|
|
||||||
// openssl rsautl -decrypt -inkey master-private.pem -in rsa-encrypted.key -out t
|
// openssl rsautl -decrypt -inkey master-private.pem -in rsa-encrypted.key -out t
|
||||||
/*
|
/*
|
||||||
@ -1035,7 +1041,7 @@ async fn create_backup(
|
|||||||
println!("Upload index.json to '{:?}'", repo);
|
println!("Upload index.json to '{:?}'", repo);
|
||||||
let manifest = serde_json::to_string_pretty(&manifest)?.into();
|
let manifest = serde_json::to_string_pretty(&manifest)?.into();
|
||||||
client
|
client
|
||||||
.upload_blob_from_data(manifest, MANIFEST_BLOB_NAME, true, Some(true))
|
.upload_blob_from_data(manifest, MANIFEST_BLOB_NAME, true, crypt_mode.sign_only())
|
||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
client.finish().await?;
|
client.finish().await?;
|
||||||
@ -1193,7 +1199,7 @@ async fn restore(param: Value) -> Result<Value, Error> {
|
|||||||
let target = tools::required_string_param(¶m, "target")?;
|
let target = tools::required_string_param(¶m, "target")?;
|
||||||
let target = if target == "-" { None } else { Some(target) };
|
let target = if target == "-" { None } else { Some(target) };
|
||||||
|
|
||||||
let keyfile = keyfile_parameters(¶m)?;
|
let (keyfile, _crypt_mode) = keyfile_parameters(¶m)?;
|
||||||
|
|
||||||
let crypt_config = match keyfile {
|
let crypt_config = match keyfile {
|
||||||
None => None,
|
None => None,
|
||||||
@ -1341,7 +1347,7 @@ async fn upload_log(param: Value) -> Result<Value, Error> {
|
|||||||
|
|
||||||
let mut client = connect(repo.host(), repo.user())?;
|
let mut client = connect(repo.host(), repo.user())?;
|
||||||
|
|
||||||
let keyfile = keyfile_parameters(¶m)?;
|
let (keyfile, crypt_mode) = keyfile_parameters(¶m)?;
|
||||||
|
|
||||||
let crypt_config = match keyfile {
|
let crypt_config = match keyfile {
|
||||||
None => None,
|
None => None,
|
||||||
@ -1354,7 +1360,19 @@ async fn upload_log(param: Value) -> Result<Value, Error> {
|
|||||||
|
|
||||||
let data = file_get_contents(logfile)?;
|
let data = file_get_contents(logfile)?;
|
||||||
|
|
||||||
let blob = DataBlob::encode(&data, crypt_config.as_ref().map(Arc::as_ref), true)?;
|
let blob = match crypt_mode {
|
||||||
|
CryptMode::None => DataBlob::encode(&data, None, true)?,
|
||||||
|
CryptMode::Encrypt => {
|
||||||
|
DataBlob::encode(&data, crypt_config.as_ref().map(Arc::as_ref), true)?
|
||||||
|
}
|
||||||
|
CryptMode::SignOnly => DataBlob::create_signed(
|
||||||
|
&data,
|
||||||
|
crypt_config
|
||||||
|
.ok_or_else(|| format_err!("cannot sign without crypt config"))?
|
||||||
|
.as_ref(),
|
||||||
|
true,
|
||||||
|
)?,
|
||||||
|
};
|
||||||
|
|
||||||
let raw_data = blob.into_inner();
|
let raw_data = blob.into_inner();
|
||||||
|
|
||||||
|
@ -3,7 +3,7 @@ use std::os::unix::fs::OpenOptionsExt;
|
|||||||
use std::sync::atomic::{AtomicUsize, Ordering};
|
use std::sync::atomic::{AtomicUsize, Ordering};
|
||||||
use std::sync::{Arc, Mutex};
|
use std::sync::{Arc, Mutex};
|
||||||
|
|
||||||
use anyhow::{format_err, Error};
|
use anyhow::{bail, format_err, Error};
|
||||||
use chrono::{DateTime, Utc};
|
use chrono::{DateTime, Utc};
|
||||||
use futures::*;
|
use futures::*;
|
||||||
use futures::stream::Stream;
|
use futures::stream::Stream;
|
||||||
@ -163,21 +163,17 @@ impl BackupWriter {
|
|||||||
data: Vec<u8>,
|
data: Vec<u8>,
|
||||||
file_name: &str,
|
file_name: &str,
|
||||||
compress: bool,
|
compress: bool,
|
||||||
crypt_or_sign: Option<bool>,
|
crypt_mode: CryptMode,
|
||||||
) -> Result<BackupStats, Error> {
|
) -> Result<BackupStats, Error> {
|
||||||
|
let blob = match (crypt_mode, &self.crypt_config) {
|
||||||
let blob = if let Some(ref crypt_config) = self.crypt_config {
|
(CryptMode::None, _) => DataBlob::encode(&data, None, compress)?,
|
||||||
if let Some(encrypt) = crypt_or_sign {
|
(_, None) => bail!("requested encryption/signing without a crypt config"),
|
||||||
if encrypt {
|
(CryptMode::Encrypt, Some(crypt_config)) => {
|
||||||
DataBlob::encode(&data, Some(crypt_config), compress)?
|
DataBlob::encode(&data, Some(crypt_config), compress)?
|
||||||
} else {
|
}
|
||||||
|
(CryptMode::SignOnly, Some(crypt_config)) => {
|
||||||
DataBlob::create_signed(&data, crypt_config, compress)?
|
DataBlob::create_signed(&data, crypt_config, compress)?
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
DataBlob::encode(&data, None, compress)?
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
DataBlob::encode(&data, None, compress)?
|
|
||||||
};
|
};
|
||||||
|
|
||||||
let raw_data = blob.into_inner();
|
let raw_data = blob.into_inner();
|
||||||
@ -194,7 +190,7 @@ impl BackupWriter {
|
|||||||
src_path: P,
|
src_path: P,
|
||||||
file_name: &str,
|
file_name: &str,
|
||||||
compress: bool,
|
compress: bool,
|
||||||
crypt_or_sign: Option<bool>,
|
crypt_mode: CryptMode,
|
||||||
) -> Result<BackupStats, Error> {
|
) -> Result<BackupStats, Error> {
|
||||||
|
|
||||||
let src_path = src_path.as_ref();
|
let src_path = src_path.as_ref();
|
||||||
@ -209,7 +205,7 @@ impl BackupWriter {
|
|||||||
.await
|
.await
|
||||||
.map_err(|err| format_err!("unable to read file {:?} - {}", src_path, err))?;
|
.map_err(|err| format_err!("unable to read file {:?} - {}", src_path, err))?;
|
||||||
|
|
||||||
self.upload_blob_from_data(contents, file_name, compress, crypt_or_sign).await
|
self.upload_blob_from_data(contents, file_name, compress, crypt_mode).await
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn upload_stream(
|
pub async fn upload_stream(
|
||||||
|
Loading…
Reference in New Issue
Block a user