[PATCH proxmox-backup v2 09/27] sync: add helper to check encryption key acls and load key

Christian Ebner
2026-04-10T16:54:37Z

Introduces a common helper function to be used when loading an
encryption key in sync job for either push or pull direction.

For given user, access to the provided key by id is checked and the
key config containing the secret loaded from the file by means of the
config.

Signed-off-by: Christian Ebner <c.ebner@proxmox.com>
---
src/server/sync.rs | 29 ++++++++++++++++++++++++++++-
1 file changed, 28 insertions(+), 1 deletion(-)

diff --git a/src/server/sync.rs b/src/server/sync.rs
index aedf4a271..9c070cd9c 100644
--- a/src/server/sync.rs
+++ b/src/server/sync.rs
@@ -21,12 +21,14 @@ use proxmox_router::HttpError;
use pbs_api_types::{
Authid, BackupDir, BackupGroup, BackupNamespace, CryptMode, GroupListItem, SnapshotListItem,
SyncDirection, SyncJobConfig, VerifyState, CLIENT_LOG_BLOB_NAME, MANIFEST_BLOB_NAME,
- MAX_NAMESPACE_DEPTH, PRIV_DATASTORE_BACKUP, PRIV_DATASTORE_READ,
+ MAX_NAMESPACE_DEPTH, PRIV_DATASTORE_BACKUP, PRIV_DATASTORE_READ, PRIV_SYS_MODIFY,
};
use pbs_client::{BackupReader, BackupRepository, HttpClient, RemoteChunkReader};
+use pbs_config::CachedUserInfo;
use pbs_datastore::data_blob::DataBlob;
use pbs_datastore::read_chunk::AsyncReadChunk;
use pbs_datastore::{BackupManifest, DataStore, ListNamespacesRecursive, LocalChunkReader};
+use pbs_tools::crypt_config::CryptConfig;

use crate::backup::ListAccessibleBackupGroups;
use crate::server::jobstate::Job;
@@ -791,3 +793,28 @@ pub(super) fn exclude_not_verified_or_encrypted(

false
}
+
+/// Helper to check user having access to the given encryption key and loading
+/// the it using the passphrase from the config.
+pub(crate) fn check_privs_and_load_key_config(
+ key_id: &str,
+ user: &Authid,
+ fail_on_archived: bool,
+) -> Result<Option<Arc<CryptConfig>>, Error> {
+ let user_info = CachedUserInfo::new()?;
+ user_info.check_privs(
+ user,
+ &["system", "encryption-keys", key_id],
+ PRIV_SYS_MODIFY,
+ true,
+ )?;
+
+ let key_config = pbs_config::encryption_keys::load_key_config(key_id, fail_on_archived)?;
+ // pass empty passphrase to get raw key material of unprotected key
+ let (enc_key, _created, fingerprint) = key_config.decrypt(&|| Ok(Vec::new()))?;
+
+ info!("Loaded encryption key '{key_id}' with fingerprint '{fingerprint}'");
+
+ let crypt_config = Arc::new(CryptConfig::new(enc_key)?);
+ Ok(Some(crypt_config))
+}
--
2.47.3