]> git.proxmox.com Git - pve-container.git/commitdiff
network permissions: implement checks
authorFabian Grünbichler <f.gruenbichler@proxmox.com>
Fri, 9 Jun 2023 07:51:41 +0000 (09:51 +0200)
committerThomas Lamprecht <t.lamprecht@proxmox.com>
Fri, 9 Jun 2023 08:08:23 +0000 (10:08 +0200)
when creating a new container
when restoring a backup
when cloning a container
and obviously, when changing the nics of an existing container

Signed-off-by: Fabian Grünbichler <f.gruenbichler@proxmox.com>
 [ T: add $opt in override param check ]
Signed-off-by: Thomas Lamprecht <t.lamprecht@proxmox.com>
src/PVE/API2/LXC.pm
src/PVE/LXC.pm
src/PVE/LXC/Create.pm

index 2d679970b43bc6e20b1bb75f4e8de50988924f0e..28d14dea992dd9536f901f81a1e5a712e0b2b9fd 100644 (file)
@@ -388,6 +388,14 @@ __PACKAGE__->register_method({
                        print "recovering backed-up configuration from '$archive'\n";
                        ($orig_conf, $orig_mp_param) = PVE::LXC::Create::recover_config($storage_cfg, $archive, $vmid);
 
+                       for my $opt (keys %$orig_conf) {
+                           # early check before disks are created
+                           # the "real" check is in later on when actually merging the configs
+                           if ($opt =~ /^net\d+$/ && !defined($param->{$opt})) {
+                               PVE::LXC::check_bridge_access($rpcenv, $authuser, $orig_conf->{$opt});
+                           }
+                       }
+
                        $was_template = delete $orig_conf->{template};
 
                        # When we're root call 'restore_configuration' with restricted=0,
@@ -1532,7 +1540,7 @@ __PACKAGE__->register_method({
        description => "You need 'VM.Clone' permissions on /vms/{vmid}, " .
            "and 'VM.Allocate' permissions " .
            "on /vms/{newid} (or on the VM pool /pool/{pool}). You also need " .
-           "'Datastore.AllocateSpace' on any used storage.",
+           "'Datastore.AllocateSpace' on any used storage, and 'SDN.Use' on any bridge.",
        check =>
        [ 'and',
          ['perm', '/vms/{vmid}', [ 'VM.Clone' ]],
@@ -1724,6 +1732,8 @@ __PACKAGE__->register_method({
                    my $net = PVE::LXC::Config->parse_lxc_network($value);
                    $net->{hwaddr} = PVE::Tools::random_ether_addr($dc->{mac_prefix});
                    $newconf->{$opt} = PVE::LXC::Config->print_lxc_network($net);
+
+                   PVE::LXC::check_bridge_access($rpcenv, $authuser, $newconf->{$opt});
                } else {
                    # copy everything else
                    $newconf->{$opt} = $value;
index 92c1b60544460eb1dd98c8c72bf957e7ef586b6b..9642f2e508eb0895a5f8f1ccf9565cfab246cba2 100644 (file)
@@ -18,7 +18,7 @@ use PVE::AccessControl;
 use PVE::CGroup;
 use PVE::CpuSet;
 use PVE::Exception qw(raise_perm_exc);
-use PVE::GuestHelpers qw(safe_string_ne safe_num_ne safe_boolean_ne);
+use PVE::GuestHelpers qw(check_vnet_access safe_string_ne safe_num_ne safe_boolean_ne);
 use PVE::INotify;
 use PVE::JSONSchema qw(get_standard_option);
 use PVE::Network;
@@ -1317,6 +1317,7 @@ sub check_ct_modify_config_perm {
        } elsif ($opt =~ m/^net\d+$/ || $opt eq 'nameserver' ||
                 $opt eq 'searchdomain' || $opt eq 'hostname') {
            $rpcenv->check_vm_perm($authuser, $vmid, $pool, ['VM.Config.Network']);
+           PVE::LXC::check_bridge_access($rpcenv, $authuser, $newconf->{$opt});
        } elsif ($opt eq 'features') {
            raise_perm_exc("changing feature flags for privileged container is only allowed for root\@pam")
                if !$unprivileged;
@@ -1383,6 +1384,20 @@ sub check_ct_modify_config_perm {
     return 1;
 }
 
+sub check_bridge_access {
+    my ($rpcenv, $authuser, $raw) = @_;
+
+    return 1 if $authuser eq 'root@pam';
+
+    my $net = PVE::LXC::Config->parse_lxc_network($raw);
+    my $bridge = $net->{bridge};
+    my $tag = $net->{tag};
+    my $trunks = $net->{trunks};
+    check_vnet_access($rpcenv, $authuser, $bridge, $tag, $trunks);
+
+    return 1;
+};
+
 sub umount_all {
     my ($vmid, $storage_cfg, $conf, $noerr) = @_;
 
index b2e3d00a0d24248197177aff09282b26d5da8ec8..981f92d5a78686407aa24c9abbce01359034e603 100644 (file)
@@ -325,6 +325,7 @@ sub sanitize_and_merge_config {
     my ($conf, $oldconf, $restricted, $unique) = @_;
 
     my $rpcenv = PVE::RPCEnvironment::get();
+    my $authuser = $rpcenv->get_user();
 
     foreach my $key (keys %$oldconf) {
        next if $key eq 'digest' || $key eq 'rootfs' || $key eq 'snapshots' || $key eq 'unprivileged' || $key eq 'parent';
@@ -354,6 +355,10 @@ sub sanitize_and_merge_config {
            next;
        }
 
+       if ($key =~ /^net\d+$/ && !defined($conf->{$key})) {
+           PVE::LXC::check_bridge_access($rpcenv, $authuser, $oldconf->{$key});
+       }
+
        if ($unique && $key =~ /^net\d+$/) {
            my $net = PVE::LXC::Config->parse_lxc_network($oldconf->{$key});
            my $dc = PVE::Cluster::cfs_read_file('datacenter.cfg');