From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from firstgate.proxmox.com (firstgate.proxmox.com [212.224.123.68]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits)) (No client certificate requested) by lists.proxmox.com (Postfix) with ESMTPS id 18C536918A for ; Thu, 12 Nov 2020 11:31:19 +0100 (CET) Received: from firstgate.proxmox.com (localhost [127.0.0.1]) by firstgate.proxmox.com (Proxmox) with ESMTP id 0FB0DD80C for ; Thu, 12 Nov 2020 11:30:49 +0100 (CET) Received: from proxmox-new.maurer-it.com (proxmox-new.maurer-it.com [212.186.127.180]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits)) (No client certificate requested) by firstgate.proxmox.com (Proxmox) with ESMTPS id 75399D802 for ; Thu, 12 Nov 2020 11:30:48 +0100 (CET) Received: from proxmox-new.maurer-it.com (localhost.localdomain [127.0.0.1]) by proxmox-new.maurer-it.com (Proxmox) with ESMTP id 3E2B842155 for ; Thu, 12 Nov 2020 11:30:48 +0100 (CET) From: =?UTF-8?q?Fabian=20Gr=C3=BCnbichler?= To: pbs-devel@lists.proxmox.com Date: Thu, 12 Nov 2020 11:30:32 +0100 Message-Id: <20201112103034.159849-4-f.gruenbichler@proxmox.com> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20201112103034.159849-1-f.gruenbichler@proxmox.com> References: <20201112103034.159849-1-f.gruenbichler@proxmox.com> MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-SPAM-LEVEL: Spam detection results: 0 AWL 0.023 Adjusted score from AWL reputation of From: address KAM_DMARC_STATUS 0.01 Test Rule for DKIM or SPF Failure with Strict Alignment RCVD_IN_DNSWL_MED -2.3 Sender listed at https://www.dnswl.org/, medium trust SPF_HELO_NONE 0.001 SPF: HELO does not publish an SPF Record SPF_PASS -0.001 SPF: sender matches SPF record URIBL_BLOCKED 0.001 ADMINISTRATOR NOTICE: The query to URIBL was blocked. See http://wiki.apache.org/spamassassin/DnsBlocklists#dnsbl-block for more information. [datastore.rs, mod.rs] Subject: [pbs-devel] [PATCH proxmox-backup 3/5] api: filter snapshot counts X-BeenThere: pbs-devel@lists.proxmox.com X-Mailman-Version: 2.1.29 Precedence: list List-Id: Proxmox Backup Server development discussion List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Thu, 12 Nov 2020 10:31:19 -0000 unprivileged users should only see the counts related to their part of the datastore. while we're at it, switch to a list groups, filter groups, count snapshots approach (like list_snapshots) to speedup calls to this endpoint when many unprivileged users share a datastore. Signed-off-by: Fabian Grünbichler --- src/api2/admin/datastore.rs | 93 +++++++++++++++++++------------------ src/api2/types/mod.rs | 2 +- 2 files changed, 48 insertions(+), 47 deletions(-) diff --git a/src/api2/admin/datastore.rs b/src/api2/admin/datastore.rs index 857fb903..6d9de4e4 100644 --- a/src/api2/admin/datastore.rs +++ b/src/api2/admin/datastore.rs @@ -472,51 +472,40 @@ pub fn list_snapshots ( }) } -fn get_snapshots_count(store: &DataStore) -> Result { +fn get_snapshots_count(store: &DataStore, filter_owner: Option<&Authid>) -> Result { let base_path = store.base_path(); - let backup_list = BackupInfo::list_backups(&base_path)?; - let mut groups = HashSet::new(); - - let mut result = Counts { - ct: None, - host: None, - vm: None, - other: None, - }; - - for info in backup_list { - let group = info.backup_dir.group(); - - let id = group.backup_id(); - let backup_type = group.backup_type(); - - let mut new_id = false; - - if groups.insert(format!("{}-{}", &backup_type, &id)) { - new_id = true; - } + let groups = BackupInfo::list_backup_groups(&base_path)?; - let mut counts = match backup_type { - "ct" => result.ct.take().unwrap_or(Default::default()), - "host" => result.host.take().unwrap_or(Default::default()), - "vm" => result.vm.take().unwrap_or(Default::default()), - _ => result.other.take().unwrap_or(Default::default()), - }; + groups.iter() + .filter(|group| { + let owner = match store.get_owner(&group) { + Ok(owner) => owner, + Err(err) => { + eprintln!("Failed to get owner of group '{}' - {}", group, err); + return false; + }, + }; - counts.snapshots += 1; - if new_id { - counts.groups +=1; - } + match filter_owner { + Some(filter) => check_backup_owner(&owner, filter).is_ok(), + None => true, + } + }) + .try_fold(Counts::default(), |mut counts, group| { + let snapshot_count = group.list_backups(&base_path)?.len() as u64; + + let type_count = match group.backup_type() { + "ct" => counts.ct.get_or_insert(Default::default()), + "vm" => counts.vm.get_or_insert(Default::default()), + "host" => counts.host.get_or_insert(Default::default()), + _ => counts.other.get_or_insert(Default::default()), + }; - match backup_type { - "ct" => result.ct = Some(counts), - "host" => result.host = Some(counts), - "vm" => result.vm = Some(counts), - _ => result.other = Some(counts), - } - } + type_count.groups += 1; + type_count.snapshots += snapshot_count; - Ok(result) + Ok(counts) + }) } #[api( @@ -546,15 +535,27 @@ pub fn status( store: String, verbose: bool, _info: &ApiMethod, - _rpcenv: &mut dyn RpcEnvironment, + rpcenv: &mut dyn RpcEnvironment, ) -> Result { let datastore = DataStore::lookup_datastore(&store)?; let storage = crate::tools::disks::disk_usage(&datastore.base_path())?; - let (counts, gc_status) = match verbose { - true => { - (Some(get_snapshots_count(&datastore)?), Some(datastore.last_gc_status())) - }, - false => (None, None), + let (counts, gc_status) = if verbose { + let auth_id: Authid = rpcenv.get_auth_id().unwrap().parse()?; + let user_info = CachedUserInfo::new()?; + + let store_privs = user_info.lookup_privs(&auth_id, &["datastore", &store]); + let filter_owner = if store_privs & PRIV_DATASTORE_AUDIT != 0 { + None + } else { + Some(&auth_id) + }; + + let counts = Some(get_snapshots_count(&datastore, filter_owner)?); + let gc_status = Some(datastore.last_gc_status()); + + (counts, gc_status) + } else { + (None, None) }; Ok(DataStoreStatus { diff --git a/src/api2/types/mod.rs b/src/api2/types/mod.rs index 44cfef94..d7d5a8af 100644 --- a/src/api2/types/mod.rs +++ b/src/api2/types/mod.rs @@ -692,7 +692,7 @@ pub struct TypeCounts { }, }, )] -#[derive(Serialize, Deserialize)] +#[derive(Serialize, Deserialize, Default)] /// Counts of groups/snapshots per BackupType. pub struct Counts { /// The counts for CT backups -- 2.20.1