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 E7EFC62EB7 for ; Wed, 28 Oct 2020 12:37:49 +0100 (CET) Received: from firstgate.proxmox.com (localhost [127.0.0.1]) by firstgate.proxmox.com (Proxmox) with ESMTP id E4A641ED0D for ; Wed, 28 Oct 2020 12:37:19 +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 1C2FA1ED02 for ; Wed, 28 Oct 2020 12:37:19 +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 DA7C545E51 for ; Wed, 28 Oct 2020 12:37:18 +0100 (CET) From: =?UTF-8?q?Fabian=20Gr=C3=BCnbichler?= To: pbs-devel@lists.proxmox.com Date: Wed, 28 Oct 2020 12:37:11 +0100 Message-Id: <20201028113717.827644-1-f.gruenbichler@proxmox.com> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20201028113632.814586-1-f.gruenbichler@proxmox.com> References: <20201028113632.814586-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.028 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. [mod.rs, tasks.rs] Subject: [pbs-devel] [PATCH proxmox-backup 10/16] tasks: allow unpriv users to read their tokens' tasks 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: Wed, 28 Oct 2020 11:37:50 -0000 and tighten down the return schema while we're at it. Signed-off-by: Fabian Grünbichler --- src/api2/node/tasks.rs | 37 +++++++++++++++++++++++++------------ src/api2/types/mod.rs | 6 +++--- 2 files changed, 28 insertions(+), 15 deletions(-) diff --git a/src/api2/node/tasks.rs b/src/api2/node/tasks.rs index 66af6d11..555f59cd 100644 --- a/src/api2/node/tasks.rs +++ b/src/api2/node/tasks.rs @@ -14,6 +14,16 @@ use crate::server::{self, UPID, TaskState, TaskListInfoIterator}; use crate::config::acl::{PRIV_SYS_AUDIT, PRIV_SYS_MODIFY}; use crate::config::cached_user_info::CachedUserInfo; +fn check_task_access(auth_id: &Authid, upid: &UPID) -> Result<(), Error> { + let task_auth_id = &upid.auth_id; + if auth_id == task_auth_id + || (task_auth_id.is_token() && &Authid::from(task_auth_id.user().clone()) == auth_id) { + Ok(()) + } else { + let user_info = CachedUserInfo::new()?; + user_info.check_privs(auth_id, &["system", "tasks"], PRIV_SYS_AUDIT, false) + } +} #[api( input: { @@ -57,9 +67,13 @@ use crate::config::cached_user_info::CachedUserInfo; description: "Worker ID (arbitrary ASCII string)", }, user: { - type: String, + type: Userid, description: "The user who started the task.", }, + tokenid: { + schema: PROXMOX_TOKEN_NAME_SCHEMA, + optional: true, + }, status: { type: String, description: "'running' or 'stopped'", @@ -85,11 +99,7 @@ async fn get_task_status( let upid = extract_upid(¶m)?; let auth_id: Authid = rpcenv.get_auth_id().unwrap().parse()?; - - if auth_id != upid.auth_id { - let user_info = CachedUserInfo::new()?; - user_info.check_privs(&auth_id, &["system", "tasks"], PRIV_SYS_AUDIT, false)?; - } + check_task_access(&auth_id, &upid)?; let mut result = json!({ "upid": param["upid"], @@ -99,9 +109,13 @@ async fn get_task_status( "starttime": upid.starttime, "type": upid.worker_type, "id": upid.worker_id, - "user": upid.auth_id, + "user": upid.auth_id.user(), }); + if upid.auth_id.is_token() { + result["tokenid"] = Value::from(upid.auth_id.tokenname().unwrap().as_str()); + } + if crate::server::worker_is_active(&upid).await? { result["status"] = Value::from("running"); } else { @@ -163,10 +177,7 @@ async fn read_task_log( let auth_id: Authid = rpcenv.get_auth_id().unwrap().parse()?; - if auth_id != upid.auth_id { - let user_info = CachedUserInfo::new()?; - user_info.check_privs(&auth_id, &["system", "tasks"], PRIV_SYS_AUDIT, false)?; - } + check_task_access(&auth_id, &upid)?; let test_status = param["test-status"].as_bool().unwrap_or(false); @@ -326,7 +337,9 @@ pub fn list_tasks( Err(_) => return None, }; - if !list_all && info.upid.auth_id != auth_id { return None; } + if !list_all && check_task_access(&auth_id, &info.upid).is_err() { + return None; + } if let Some(needle) = &userfilter { if !info.upid.auth_id.to_string().contains(needle) { return None; } diff --git a/src/api2/types/mod.rs b/src/api2/types/mod.rs index 4084112d..acb5d6d0 100644 --- a/src/api2/types/mod.rs +++ b/src/api2/types/mod.rs @@ -627,7 +627,7 @@ pub struct StorageStatus { #[api( properties: { upid: { schema: UPID_SCHEMA }, - userid: { type: Authid }, + user: { type: Authid }, }, )] #[derive(Serialize, Deserialize)] @@ -647,7 +647,7 @@ pub struct TaskListItem { /// Worker ID (arbitrary ASCII string) pub worker_id: Option, /// The authenticated entity who started the task - pub userid: Authid, + pub user: Authid, /// The task end time (Epoch) #[serde(skip_serializing_if="Option::is_none")] pub endtime: Option, @@ -670,7 +670,7 @@ impl From for TaskListItem { starttime: info.upid.starttime, worker_type: info.upid.worker_type, worker_id: info.upid.worker_id, - userid: info.upid.auth_id, + user: info.upid.auth_id, endtime, status, } -- 2.20.1