move more api types for the client

Signed-off-by: Wolfgang Bumiller <w.bumiller@proxmox.com>
This commit is contained in:
Wolfgang Bumiller
2021-07-09 14:26:42 +02:00
parent ba0ccc5991
commit ea584a7510
10 changed files with 319 additions and 305 deletions

View File

@ -7,19 +7,14 @@
//! encryption](https://en.wikipedia.org/wiki/Authenticated_encryption)
//! for a short introduction.
use std::fmt;
use std::fmt::Display;
use std::io::Write;
use anyhow::{Error};
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;
use pbs_tools::format::{as_fingerprint, bytes_as_fingerprint};
pub use pbs_api_types::{CryptMode, Fingerprint};
// openssl::sha::sha256(b"Proxmox Backup Encryption Key Fingerprint")
/// This constant is used to compute fingerprints.
@ -29,53 +24,6 @@ const FINGERPRINT_INPUT: [u8; 32] = [
97, 64, 127, 19, 76, 114, 93, 223,
48, 153, 45, 37, 236, 69, 237, 38,
];
#[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,
}
#[derive(Debug, Eq, PartialEq, Hash, Clone, Deserialize, Serialize)]
#[serde(transparent)]
/// 32-byte fingerprint, usually calculated with SHA256.
pub struct Fingerprint {
#[serde(with = "bytes_as_fingerprint")]
bytes: [u8; 32],
}
impl Fingerprint {
pub fn new(bytes: [u8; 32]) -> Self {
Self { bytes }
}
pub fn bytes(&self) -> &[u8; 32] {
&self.bytes
}
}
/// Display as short key ID
impl Display for Fingerprint {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{}", as_fingerprint(&self.bytes[0..8]))
}
}
impl std::str::FromStr for Fingerprint {
type Err = Error;
fn from_str(s: &str) -> Result<Self, Error> {
let mut tmp = s.to_string();
tmp.retain(|c| c != ':');
let bytes = proxmox::tools::hex_to_digest(&tmp)?;
Ok(Fingerprint::new(bytes))
}
}
/// Encryption Configuration with secret key
///

View File

@ -197,6 +197,7 @@ pub mod key_derivation;
pub mod manifest;
pub mod prune;
pub mod read_chunk;
pub mod store_progress;
pub mod task;
pub mod dynamic_index;
@ -216,3 +217,4 @@ pub use key_derivation::{
};
pub use key_derivation::{Kdf, KeyConfig, KeyDerivationConfig, KeyInfo};
pub use manifest::BackupManifest;
pub use store_progress::StoreProgress;

View File

@ -85,21 +85,26 @@ pub enum ArchiveType {
Blob,
}
impl ArchiveType {
pub fn from_path(archive_name: impl AsRef<Path>) -> Result<Self, Error> {
let archive_name = archive_name.as_ref();
let archive_type = match archive_name.extension().and_then(|ext| ext.to_str()) {
Some("didx") => ArchiveType::DynamicIndex,
Some("fidx") => ArchiveType::FixedIndex,
Some("blob") => ArchiveType::Blob,
_ => bail!("unknown archive type: {:?}", archive_name),
};
Ok(archive_type)
}
}
//#[deprecated(note = "use ArchivType::from_path instead")] later...
pub fn archive_type<P: AsRef<Path>>(
archive_name: P,
) -> Result<ArchiveType, Error> {
let archive_name = archive_name.as_ref();
let archive_type = match archive_name.extension().and_then(|ext| ext.to_str()) {
Some("didx") => ArchiveType::DynamicIndex,
Some("fidx") => ArchiveType::FixedIndex,
Some("blob") => ArchiveType::Blob,
_ => bail!("unknown archive type: {:?}", archive_name),
};
Ok(archive_type)
ArchiveType::from_path(archive_name)
}
impl BackupManifest {
pub fn new(snapshot: BackupDir) -> Self {
@ -114,7 +119,7 @@ impl BackupManifest {
}
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 = ArchiveType::from_path(&filename)?; // check type
self.files.push(FileInfo { filename, size, csum, crypt_mode });
Ok(())
}

View File

@ -0,0 +1,79 @@
#[derive(Debug, Default)]
/// Tracker for progress of operations iterating over `Datastore` contents.
pub struct StoreProgress {
/// Completed groups
pub done_groups: u64,
/// Total groups
pub total_groups: u64,
/// Completed snapshots within current group
pub done_snapshots: u64,
/// Total snapshots in current group
pub group_snapshots: u64,
}
impl StoreProgress {
pub fn new(total_groups: u64) -> Self {
StoreProgress {
total_groups,
.. Default::default()
}
}
/// Calculates an interpolated relative progress based on current counters.
pub fn percentage(&self) -> f64 {
let per_groups = (self.done_groups as f64) / (self.total_groups as f64);
if self.group_snapshots == 0 {
per_groups
} else {
let per_snapshots = (self.done_snapshots as f64) / (self.group_snapshots as f64);
per_groups + (1.0 / self.total_groups as f64) * per_snapshots
}
}
}
impl std::fmt::Display for StoreProgress {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
let current_group = if self.done_groups < self.total_groups {
self.done_groups + 1
} else {
self.done_groups
};
if self.group_snapshots == 0 {
write!(
f,
"{:.2}% ({}/{} groups)",
self.percentage() * 100.0,
self.done_groups,
self.total_groups,
)
} else if self.total_groups == 1 {
write!(
f,
"{:.2}% ({}/{} snapshots)",
self.percentage() * 100.0,
self.done_snapshots,
self.group_snapshots,
)
} else if self.done_snapshots == self.group_snapshots {
write!(
f,
"{:.2}% ({}/{} groups)",
self.percentage() * 100.0,
current_group,
self.total_groups,
)
} else {
write!(
f,
"{:.2}% ({}/{} groups, {}/{} snapshots in group #{})",
self.percentage() * 100.0,
self.done_groups,
self.total_groups,
self.done_snapshots,
self.group_snapshots,
current_group,
)
}
}
}