From: "Fabian Grünbichler" <f.gruenbichler@proxmox.com>
To: pve-devel@lists.proxmox.com
Subject: [pve-devel] [PATCH container] network permissions: implement checks
Date: Fri, 9 Jun 2023 09:51:41 +0200 [thread overview]
Message-ID: <20230609075141.667259-1-f.gruenbichler@proxmox.com> (raw)
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>
---
src/PVE/API2/LXC.pm | 12 +++++++++++-
src/PVE/LXC.pm | 17 ++++++++++++++++-
src/PVE/LXC/Create.pm | 5 +++++
3 files changed, 32 insertions(+), 2 deletions(-)
diff --git a/src/PVE/API2/LXC.pm b/src/PVE/API2/LXC.pm
index 2d67997..ed68390 100644
--- a/src/PVE/API2/LXC.pm
+++ b/src/PVE/API2/LXC.pm
@@ -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+$/ && !$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;
diff --git a/src/PVE/LXC.pm b/src/PVE/LXC.pm
index 92c1b60..9642f2e 100644
--- a/src/PVE/LXC.pm
+++ b/src/PVE/LXC.pm
@@ -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) = @_;
diff --git a/src/PVE/LXC/Create.pm b/src/PVE/LXC/Create.pm
index b2e3d00..981f92d 100644
--- a/src/PVE/LXC/Create.pm
+++ b/src/PVE/LXC/Create.pm
@@ -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');
--
2.39.2
next reply other threads:[~2023-06-09 7:51 UTC|newest]
Thread overview: 2+ messages / expand[flat|nested] mbox.gz Atom feed top
2023-06-09 7:51 Fabian Grünbichler [this message]
2023-06-09 8:22 ` [pve-devel] applied: " Thomas Lamprecht
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20230609075141.667259-1-f.gruenbichler@proxmox.com \
--to=f.gruenbichler@proxmox.com \
--cc=pve-devel@lists.proxmox.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.