From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from firstgate.proxmox.com (firstgate.proxmox.com [IPv6:2a01:7e0:0:424::9]) by lore.proxmox.com (Postfix) with ESMTPS id CB70C1FF13B for ; Wed, 03 Jun 2026 16:56:15 +0200 (CEST) Received: from firstgate.proxmox.com (localhost [127.0.0.1]) by firstgate.proxmox.com (Proxmox) with ESMTP id A13A11038C; Wed, 3 Jun 2026 16:56:15 +0200 (CEST) From: David Riley To: pve-devel@lists.proxmox.com Subject: [PATCH pve-access-control v3 1/5] fix: #7520: sdn: prune orphaned ACLs on resource deletion Date: Wed, 3 Jun 2026 16:55:19 +0200 Message-ID: <20260603145523.120075-2-d.riley@proxmox.com> X-Mailer: git-send-email 2.47.3 In-Reply-To: <20260603145523.120075-1-d.riley@proxmox.com> References: <20260603145523.120075-1-d.riley@proxmox.com> MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Bm-Milter-Handled: 55990f41-d878-4baa-be0a-ee34c49e34d2 X-Bm-Transport-Timestamp: 1780498529196 X-SPAM-LEVEL: Spam detection results: 0 AWL 0.229 Adjusted score from AWL reputation of From: address BAYES_00 -1.9 Bayes spam probability is 0 to 1% DMARC_MISSING 0.1 Missing DMARC policy KAM_DMARC_STATUS 0.01 Test Rule for DKIM or SPF Failure with Strict Alignment 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: LJVM37C3RC3R7LH36FPXJXLPRT7CGXS4 X-Message-ID-Hash: LJVM37C3RC3R7LH36FPXJXLPRT7CGXS4 X-MailFrom: d.riley@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 CC: David Riley X-Mailman-Version: 3.3.10 Precedence: list List-Id: Proxmox VE development discussion List-Help: List-Owner: List-Post: List-Subscribe: List-Unsubscribe: Add a helper routine to prune ACL entries under the '/sdn/' path when the corresponding resources are deleted. Compare the running configuration against the newly compiled state during config commit. This prevents dangling permission states and ensures configuration consistency across manual API/UI applies as well as automatic reloads during system boot. Link: https://bugzilla.proxmox.com/show_bug.cgi?id=7520 Signed-off-by: David Riley --- src/PVE/AccessControl.pm | 46 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 46 insertions(+) diff --git a/src/PVE/AccessControl.pm b/src/PVE/AccessControl.pm index 0d632b3..7581394 100644 --- a/src/PVE/AccessControl.pm +++ b/src/PVE/AccessControl.pm @@ -1974,6 +1974,52 @@ sub remove_vm_from_pool { lock_user_config($delVMfromPoolFn, "pool cleanup for VM $vmid failed"); } +sub remove_sdn_resource_access { + my ($paths) = @_; # [ ['zones', ''], ['zones', '', ''] ] + + my $delete_resource_fn = sub { + my $usercfg = cfs_read_file("user.cfg"); + my $modified = 0; + + foreach my $segments (@$paths) { + my @full_path = ('sdn', @$segments); + my $current = $usercfg->{acl_root}; + my ($parent, $last_key) = lookup_acl_node($current, \@full_path); + + if ($parent && $last_key) { + delete $parent->{children}->{$last_key}; + $modified = 1; + } + } + + if ($modified) { + cfs_write_file("user.cfg", $usercfg); + } + }; + + lock_user_config($delete_resource_fn, "SDN ACL cleanup failed"); +} + +sub lookup_acl_node { + my ($root, $path) = @_; + + my $current = $root; + my $parent = undef; + my $last_key = undef; + + foreach my $step (@$path) { + if ($current->{children} && $current->{children}->{$step}) { + $parent = $current; + $last_key = $step; + $current = $current->{children}->{$step}; + } else { + return; + } + } + + return ($parent, $last_key, $current); +} + my $USER_CONTROLLED_TFA_TYPES = { u2f => 1, oath => 1, -- 2.47.3