From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from gate001.proxmox.com (gate001.proxmox.com [IPv6:2a0f:8001:1:32::40]) by lore.proxmox.com (Postfix) with ESMTPS id 8251B1FF0EA for ; Thu, 13 Aug 2026 19:10:36 +0200 (CEST) Received: from gate001.proxmox.com (localhost.localdomain [127.0.0.1]) by gate001.proxmox.com (Proxmox) with ESMTP id 3228621A16; Thu, 13 Aug 2026 19:10:35 +0200 (CEST) From: Christian Ebner To: pbs-devel@lists.proxmox.com Subject: [PATCH proxmox 01/28] pbs-api-types: add append only permission and role Date: Thu, 13 Aug 2026 19:09:35 +0200 Message-ID: <20260813171002.809441-2-c.ebner@proxmox.com> X-Mailer: git-send-email 2.47.3 In-Reply-To: <20260813171002.809441-1-c.ebner@proxmox.com> References: <20260813171002.809441-1-c.ebner@proxmox.com> MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Bm-Milter-Handled: 55990f41-d878-4baa-be0a-ee34c49e34d2 X-Bm-Transport-Timestamp: 1786641012799 X-SPAM-LEVEL: Spam detection results: 0 AWL 0.225 Adjusted score from AWL reputation of From: address DMARC_MISSING 0.1 Missing DMARC policy KAM_DMARC_STATUS 0.01 Test Rule for DKIM or SPF Failure with Strict Alignment (newer systems) RCVD_IN_DNSWL_MED -2.3 Sender listed at https://www.dnswl.org/, medium trust RDNS_NONE 1.274 Delivered to internal network by a host with no rDNS SPF_HELO_NONE 0.001 SPF: HELO does not publish an SPF Record SPF_PASS -0.001 SPF: sender matches SPF record Message-ID-Hash: DJ3NWVS36BBQDVUEHTOWU4UJ6TB3U6AZ X-Message-ID-Hash: DJ3NWVS36BBQDVUEHTOWU4UJ6TB3U6AZ X-MailFrom: c.ebner@proxmox.com X-Mailman-Rule-Misses: dmarc-mitigation; no-senders; approved; loop; banned-address; emergency; member-moderation; nonmember-moderation; administrivia; implicit-dest; max-recipients; max-size; news-moderation; no-subject; digests; suspicious-header X-Mailman-Version: 3.3.10 Precedence: list List-Id: Proxmox Backup Server development discussion List-Help: List-Owner: List-Post: List-Subscribe: List-Unsubscribe: While allowing to perform backups like Datastore.Backup, the new Datastore.Append allows further to create new namespaces, but does not allow to list, restore or otherwise modify datastore contents, not even if owned. The role is intended to allow user configuration for immutable backup and sync jobs and to be set on the user/token with target datastore ACL path. Signed-off-by: Christian Ebner --- pbs-api-types/src/acl.rs | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/pbs-api-types/src/acl.rs b/pbs-api-types/src/acl.rs index 691af305..9055dfab 100644 --- a/pbs-api-types/src/acl.rs +++ b/pbs-api-types/src/acl.rs @@ -42,6 +42,9 @@ constnamedbitmap! { /// Allows verifying a datastore PRIV_DATASTORE_VERIFY("Datastore.Verify"); + /// Datastore.Append allows to create new snapshots or namespaces, + /// but also requires backup ownership + PRIV_DATASTORE_APPEND("Datastore.Append"); /// Datastore.Backup allows Datastore.Read|Verify and creating new snapshots, /// but also requires backup ownership PRIV_DATASTORE_BACKUP("Datastore.Backup"); @@ -126,6 +129,13 @@ pub const ROLE_DATASTORE_READER: u64 = 0 | PRIV_DATASTORE_VERIFY | PRIV_DATASTORE_READ; +#[rustfmt::skip] +#[allow(clippy::identity_op)] +/// Datastore.Append can only add backups and namespaces, but not +/// list, restore or prune backups and cannot delete namespaces. +pub const ROLE_DATASTORE_APPEND: u64 = 0 + | PRIV_DATASTORE_APPEND; + #[rustfmt::skip] #[allow(clippy::identity_op)] /// Datastore.Backup can do backup and restore, but no prune. @@ -241,6 +251,8 @@ pub enum Role { Audit = ROLE_AUDIT, /// Disable Access NoAccess = ROLE_NO_ACCESS, + /// Datastore Append (append new backups and create namespaces) + DatastoreAppend = ROLE_DATASTORE_APPEND, /// Datastore Administrator DatastoreAdmin = ROLE_DATASTORE_ADMIN, /// Datastore Reader (inspect datastore content and do restores) -- 2.47.3