We need to display the bridge is the user have a permission
on any vlan on the bridge.

to avoid to check permissions on 4096 vlans for each bridge
(could be slow with a lot of bridges),
we first list vlans where acls are defined.

(4000 check took 60ms on 10year xeon server, should be enough
for any network where the total number of vlans is limited)

Signed-off-by: Alexandre Derumier <aderum...@odiso.com>
---
 PVE/API2/Network.pm | 20 +++++++++++++++++++-
 1 file changed, 19 insertions(+), 1 deletion(-)

diff --git a/PVE/API2/Network.pm b/PVE/API2/Network.pm
index ba3b3e0e..39f17d14 100644
--- a/PVE/API2/Network.pm
+++ b/PVE/API2/Network.pm
@@ -240,17 +240,35 @@ __PACKAGE__->register_method({
 
        if (my $tfilter = $param->{type}) {
            my $vnets;
+           my $bridges_vlans_acl = {};
            #check access for local bridges
            my $can_access_vnet = sub {
+               my $bridge = $_[0];
                return 1 if $authuser eq 'root@pam';
                return 1 if $rpcenv->check_any($authuser, "/sdn/zones/local", 
['SDN.Audit', 'SDN.Allocate'], 1);
-               return 1 if $rpcenv->check_any($authuser, "/sdn/vnets/$_[0]", 
['SDN.Audit', 'SDN.Allocate'], 1);
+               return 1 if $rpcenv->check($authuser, "/sdn/vnets/$bridge", 
['SDN.Audit'], 1);
+               my $bridge_vlan = $bridges_vlans_acl->{$bridge};
+               for my $tag (sort keys %$bridge_vlan) {
+                   return 1 if $rpcenv->check($authuser, 
"/sdn/vnets/$bridge.$tag", ['SDN.Audit'], 1);
+               }
            };
 
            if ($have_sdn && $param->{type} eq 'any_bridge') {
                $vnets = PVE::Network::SDN::get_local_vnets(); # returns 
already access-filtered
            }
 
+           #find all vlans where we have specific acls
+           if ($tfilter =~ /^any(_local)?_bridge$/) {
+               my $cfg = $rpcenv->{user_cfg};
+               my $vnets_acl_root = 
$cfg->{acl_root}->{children}->{sdn}->{children}->{vnets};
+               PVE::AccessControl::iterate_acl_tree("/", $vnets_acl_root, sub {
+                   my ($path, $node) = @_;
+                   if ($path =~ /\/(.*)\.(\d+)$/) {
+                       $bridges_vlans_acl->{$1}->{$2} = 1;
+                   }
+               });
+           }
+
            for my $k (sort keys $ifaces->%*) {
                my $type = $ifaces->{$k}->{type};
                my $match = $tfilter eq $type || ($tfilter =~ 
/^any(_local)?_bridge$/ && ($type eq 'bridge' || $type eq 'OVSBridge'));
-- 
2.30.2


_______________________________________________
pve-devel mailing list
pve-devel@lists.proxmox.com
https://lists.proxmox.com/cgi-bin/mailman/listinfo/pve-devel

Reply via email to