[PATCH proxmox-backup v2 11/27] api: config: check sync owner has access to en-/decryption keys

Christian Ebner
2026-04-10T16:55:18Z

So a sync job can not be configured with a non existing or non
accessible key for given sync owner/local-user.

Key access is checked by loading the key from the keyfile.

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

diff --git a/src/api2/config/sync.rs b/src/api2/config/sync.rs
index 67fa3182c..51be7e208 100644
--- a/src/api2/config/sync.rs
+++ b/src/api2/config/sync.rs
@@ -62,6 +62,16 @@ fn is_correct_owner(auth_id: &Authid, job: &SyncJobConfig) -> bool {
}
}

+// Check access and test key loading works as expected for sync job owner/user.
+fn sync_user_can_access_optional_key(key_id: Option<&str>, owner: &Authid) -> Result<(), Error> {
+ if let Some(key_id) = key_id {
+ if crate::server::sync::check_privs_and_load_key_config(key_id, owner, false).is_err() {
+ bail!("no such key or cannot access key '{key_id}'");
+ }
+ }
+ Ok(())
+}
+
/// checks whether user can run the corresponding sync job, depending on sync direction
///
/// namespace creation/deletion ACL and backup group ownership checks happen in the pull/push code
@@ -251,6 +261,19 @@ pub fn create_sync_job(
}
}

+ let owner = config
+ .owner
+ .as_ref()
+ .unwrap_or_else(|| Authid::root_auth_id());
+
+ if sync_direction == SyncDirection::Push {
+ sync_user_can_access_optional_key(config.active_encryption_key.as_deref(), owner)?;
+ } else {
+ for key in config.associated_key.as_deref().unwrap_or(&[]) {
+ sync_user_can_access_optional_key(Some(key), owner)?;
+ }
+ }
+
let (mut section_config, _digest) = sync::config()?;

if section_config.sections.contains_key(&config.id) {
--
2.47.3