]> git.proxmox.com Git - proxmox-backup.git/commitdiff
api: list datastore: avoid iterating over NS for priv check, use AclTree
authorThomas Lamprecht <t.lamprecht@proxmox.com>
Sat, 4 Jun 2022 12:57:30 +0000 (14:57 +0200)
committerThomas Lamprecht <t.lamprecht@proxmox.com>
Sat, 4 Jun 2022 13:34:42 +0000 (15:34 +0200)
Make the assumption that if a user has any privilege that would make
an NS and (parts) of its content visible they also should be able to
know about the datastore and very basic errors on lookup (path
existence and maintenance mode) even if that NS doesn't even exists
(yet), as they could, e.g., make or view a backup and find out
anyway.

This avoids iterating over parts of the whole datastore folder tree
on disk, doing a priv check on each, swapping IO to virtual in memory
checks on info we got available already anyway, is always a good idea
after all

Signed-off-by: Thomas Lamprecht <t.lamprecht@proxmox.com>
src/api2/admin/datastore.rs

index ca2dc8dba8a79c632af66285f460a614e92084a9..ca958988f5d3a4b69396d944bf8aa6081f52b9b9 100644 (file)
@@ -64,7 +64,7 @@ use crate::api2::backup::optional_ns_param;
 use crate::api2::node::rrd::create_value_from_rrd;
 use crate::backup::{
     can_access_any_namespace, check_ns_privs_full, verify_all_backups, verify_backup_dir,
-    verify_backup_group, verify_filter, ListAccessibleBackupGroups,
+    verify_backup_group, verify_filter, ListAccessibleBackupGroups, NS_PRIVS_OK,
 };
 
 use crate::server::jobstate::Job;
@@ -1188,16 +1188,15 @@ pub fn get_datastore_list(
     let mut list = Vec::new();
 
     for (store, (_, data)) in &config.sections {
-        let user_privs = user_info.lookup_privs(&auth_id, &["datastore", store]);
+        let acl_path = &["datastore", store];
+        let user_privs = user_info.lookup_privs(&auth_id, acl_path);
         let allowed = (user_privs & (PRIV_DATASTORE_AUDIT | PRIV_DATASTORE_BACKUP)) != 0;
 
         let mut allow_id = false;
         if !allowed {
-            if let Ok(datastore) = DataStore::lookup_datastore(store, Some(Operation::Read)) {
-                allow_id = can_access_any_namespace(datastore, &auth_id, &user_info);
+            if let Ok(any_privs) = user_info.any_privs_below(&auth_id, acl_path, NS_PRIVS_OK) {
+                allow_id = any_privs;
             }
-            // FIXME: check for any ACL on the datastore below in the error case, otherwise offline
-            // datastore will disappear for users that can only access a specific namespace
         }
 
         if allowed || allow_id {