all lists on lists.proxmox.com
 help / color / mirror / Atom feed
From: "Fabian Grünbichler" <f.gruenbichler@proxmox.com>
To: Proxmox VE development discussion <pve-devel@lists.proxmox.com>
Subject: Re: [pve-devel] [RFC qemu-server 4/4] api: use common helper for checking root privileges
Date: Mon, 10 Jan 2022 14:45:08 +0100	[thread overview]
Message-ID: <1641820993.tq6zsgq6uk.astroid@nora.none> (raw)
In-Reply-To: <20220105152215.1307583-5-o.bektas@proxmox.com>

this patch mixes a lot of "check for 'root@pam' as short cut" with 
"check for 'root@pam' for stuff limited to 'root@pam'". as per the 
discussion in the cover letter - if we make Sys.Root imply all other 
privileges like 'root@pam' currently does, then all the short cut 
instances can just remain as is..

On January 5, 2022 4:22 pm, Oguz Bektas wrote:
> to allow API users with the 'Sys.Root' permission to call these
> endpoints.
> 
> Signed-off-by: Oguz Bektas <o.bektas@proxmox.com>
> ---
>  PVE/API2/Qemu.pm | 74 ++++++++++++++++++++++++++++++++----------------
>  1 file changed, 49 insertions(+), 25 deletions(-)
> 
> diff --git a/PVE/API2/Qemu.pm b/PVE/API2/Qemu.pm
> index 6992f6f..e846a1e 100644
> --- a/PVE/API2/Qemu.pm
> +++ b/PVE/API2/Qemu.pm
> @@ -352,7 +352,7 @@ my $cloudinitoptions = {
>  my $check_vm_create_serial_perm = sub {
>      my ($rpcenv, $authuser, $vmid, $pool, $param) = @_;
>  
> -    return 1 if $authuser eq 'root@pam';
> +    return 1 if PVE::Tools::check_for_root("/vms/$vmid");
>  
>      foreach my $opt (keys %{$param}) {
>  	next if $opt !~ m/^serial\d+$/;
> @@ -370,7 +370,7 @@ my $check_vm_create_serial_perm = sub {
>  my $check_vm_create_usb_perm = sub {
>      my ($rpcenv, $authuser, $vmid, $pool, $param) = @_;
>  
> -    return 1 if $authuser eq 'root@pam';
> +    return 1 if PVE::Tools::check_for_root("/vms/$vmid");
>  
>      foreach my $opt (keys %{$param}) {
>  	next if $opt !~ m/^usb\d+$/;
> @@ -388,7 +388,7 @@ my $check_vm_create_usb_perm = sub {
>  my $check_vm_modify_config_perm = sub {
>      my ($rpcenv, $authuser, $vmid, $pool, $key_list) = @_;
>  
> -    return 1 if $authuser eq 'root@pam';
> +    return 1 if PVE::Tools::check_for_root("/vms/$vmid");
>  
>      foreach my $opt (@$key_list) {
>  	# some checks (e.g., disk, serial port, usb) need to be done somewhere
> @@ -1105,6 +1105,8 @@ my $update_vm_api  = sub {
>  
>      my $background_delay = extract_param($param, 'background_delay');
>  
> +    my $is_root = PVE::Tools::check_for_root("/vms/$vmid");
> +
>      if (defined(my $cipassword = $param->{cipassword})) {
>  	# Same logic as in cloud-init (but with the regex fixed...)
>  	$param->{cipassword} = PVE::Tools::encrypt_pw($cipassword)
> @@ -1119,7 +1121,7 @@ my $update_vm_api  = sub {
>  
>      my $skiplock = extract_param($param, 'skiplock');
>      raise_param_exc({ skiplock => "Only root may use this option." })
> -	if $skiplock && $authuser ne 'root@pam';
> +	if $skiplock && !$is_root;
>  
>      my $delete_str = extract_param($param, 'delete');
>  
> @@ -1340,7 +1342,7 @@ my $update_vm_api  = sub {
>  		} elsif ($opt =~ m/^serial\d+$/) {
>  		    if ($val eq 'socket') {
>  			$rpcenv->check_vm_perm($authuser, $vmid, undef, ['VM.Config.HWType']);
> -		    } elsif ($authuser ne 'root@pam') {
> +		    } elsif (!$is_root) {
>  			die "only root can delete '$opt' config for real devices\n";
>  		    }
>  		    PVE::QemuConfig->add_to_pending_delete($conf, $opt, $force);
> @@ -1348,7 +1350,7 @@ my $update_vm_api  = sub {
>  		} elsif ($opt =~ m/^usb\d+$/) {
>  		    if ($val =~ m/spice/) {
>  			$rpcenv->check_vm_perm($authuser, $vmid, undef, ['VM.Config.HWType']);
> -		    } elsif ($authuser ne 'root@pam') {
> +		    } elsif (!$is_root) {
>  			die "only root can delete '$opt' config for real devices\n";
>  		    }
>  		    PVE::QemuConfig->add_to_pending_delete($conf, $opt, $force);
> @@ -1392,14 +1394,14 @@ my $update_vm_api  = sub {
>  		} elsif ($opt =~ m/^serial\d+/) {
>  		    if ((!defined($conf->{$opt}) || $conf->{$opt} eq 'socket') && $param->{$opt} eq 'socket') {
>  			$rpcenv->check_vm_perm($authuser, $vmid, undef, ['VM.Config.HWType']);
> -		    } elsif ($authuser ne 'root@pam') {
> +		    } elsif (!$is_root) {
>  			die "only root can modify '$opt' config for real devices\n";
>  		    }
>  		    $conf->{pending}->{$opt} = $param->{$opt};
>  		} elsif ($opt =~ m/^usb\d+/) {
>  		    if ((!defined($conf->{$opt}) || $conf->{$opt} =~ m/spice/) && $param->{$opt} =~ m/spice/) {
>  			$rpcenv->check_vm_perm($authuser, $vmid, undef, ['VM.Config.HWType']);
> -		    } elsif ($authuser ne 'root@pam') {
> +		    } elsif (!$is_root) {
>  			die "only root can modify '$opt' config for real devices\n";
>  		    }
>  		    $conf->{pending}->{$opt} = $param->{$opt};
> @@ -1644,9 +1646,11 @@ __PACKAGE__->register_method({
>  	my $authuser = $rpcenv->get_user();
>  	my $vmid = $param->{vmid};
>  
> +	my $is_root = PVE::Tools::check_for_root("/vms/$vmid");
> +
>  	my $skiplock = $param->{skiplock};
>  	raise_param_exc({ skiplock => "Only root may use this option." })
> -	    if $skiplock && $authuser ne 'root@pam';
> +	    if $skiplock && !$is_root;
>  
>  	my $early_checks = sub {
>  	    # test if VM exists
> @@ -2291,10 +2295,12 @@ __PACKAGE__->register_method({
>  	my $machine = extract_param($param, 'machine');
>  	my $force_cpu = extract_param($param, 'force-cpu');
>  
> +	my $is_root = PVE::Tools::check_for_root("/vms/$vmid");
> +
>  	my $get_root_param = sub {
>  	    my $value = extract_param($param, $_[0]);
>  	    raise_param_exc({ "$_[0]" => "Only root may use this option." })
> -		if $value && $authuser ne 'root@pam';
> +		if $value && !$is_root;
>  	    return $value;
>  	};
>  
> @@ -2436,17 +2442,19 @@ __PACKAGE__->register_method({
>  	my $node = extract_param($param, 'node');
>  	my $vmid = extract_param($param, 'vmid');
>  
> +	my $is_root = PVE::Tools::check_for_root("/vms/$vmid");
> +
>  	my $skiplock = extract_param($param, 'skiplock');
>  	raise_param_exc({ skiplock => "Only root may use this option." })
> -	    if $skiplock && $authuser ne 'root@pam';
> +	    if $skiplock && !$is_root;
>  
>  	my $keepActive = extract_param($param, 'keepActive');
>  	raise_param_exc({ keepActive => "Only root may use this option." })
> -	    if $keepActive && $authuser ne 'root@pam';
> +	    if $keepActive && !$is_root;
>  
>  	my $migratedfrom = extract_param($param, 'migratedfrom');
>  	raise_param_exc({ migratedfrom => "Only root may use this option." })
> -	    if $migratedfrom && $authuser ne 'root@pam';
> +	    if $migratedfrom && !$is_root;
>  
>  
>  	my $storecfg = PVE::Storage::config();
> @@ -2513,9 +2521,11 @@ __PACKAGE__->register_method({
>  
>  	my $vmid = extract_param($param, 'vmid');
>  
> +	my $is_root = PVE::Tools::check_for_root("/vms/$vmid");
> +
>  	my $skiplock = extract_param($param, 'skiplock');
>  	raise_param_exc({ skiplock => "Only root may use this option." })
> -	    if $skiplock && $authuser ne 'root@pam';
> +	    if $skiplock && !$is_root;
>  
>  	die "VM $vmid not running\n" if !PVE::QemuServer::check_running($vmid);
>  
> @@ -2580,13 +2590,15 @@ __PACKAGE__->register_method({
>  	my $node = extract_param($param, 'node');
>  	my $vmid = extract_param($param, 'vmid');
>  
> +	my $is_root = PVE::Tools::check_for_root("/vms/$vmid");
> +
>  	my $skiplock = extract_param($param, 'skiplock');
>  	raise_param_exc({ skiplock => "Only root may use this option." })
> -	    if $skiplock && $authuser ne 'root@pam';
> +	    if $skiplock && !$is_root;
>  
>  	my $keepActive = extract_param($param, 'keepActive');
>  	raise_param_exc({ keepActive => "Only root may use this option." })
> -	    if $keepActive && $authuser ne 'root@pam';
> +	    if $keepActive && !$is_root;
>  
>  	my $storecfg = PVE::Storage::config();
>  
> @@ -2735,13 +2747,15 @@ __PACKAGE__->register_method({
>  	my $node = extract_param($param, 'node');
>  	my $vmid = extract_param($param, 'vmid');
>  
> +	my $is_root = PVE::Tools::check_for_root("/vms/$vmid");
> +
>  	my $todisk = extract_param($param, 'todisk') // 0;
>  
>  	my $statestorage = extract_param($param, 'statestorage');
>  
>  	my $skiplock = extract_param($param, 'skiplock');
>  	raise_param_exc({ skiplock => "Only root may use this option." })
> -	    if $skiplock && $authuser ne 'root@pam';
> +	    if $skiplock && !$is_root;
>  
>  	die "VM $vmid not running\n" if !PVE::QemuServer::check_running($vmid);
>  
> @@ -2811,13 +2825,15 @@ __PACKAGE__->register_method({
>  
>  	my $vmid = extract_param($param, 'vmid');
>  
> +	my $is_root = PVE::Tools::check_for_root("/vms/$vmid");
> +
>  	my $skiplock = extract_param($param, 'skiplock');
>  	raise_param_exc({ skiplock => "Only root may use this option." })
> -	    if $skiplock && $authuser ne 'root@pam';
> +	    if $skiplock && !$is_root;
>  
>  	my $nocheck = extract_param($param, 'nocheck');
>  	raise_param_exc({ nocheck => "Only root may use this option." })
> -	    if $nocheck && $authuser ne 'root@pam';
> +	    if $nocheck && !$is_root;
>  
>  	my $to_disk_suspended;
>  	eval {
> @@ -2883,9 +2899,11 @@ __PACKAGE__->register_method({
>  
>  	my $vmid = extract_param($param, 'vmid');
>  
> +	my $is_root = PVE::Tools::check_for_root("/vms/$vmid");
> +
>  	my $skiplock = extract_param($param, 'skiplock');
>  	raise_param_exc({ skiplock => "Only root may use this option." })
> -	    if $skiplock && $authuser ne 'root@pam';
> +	    if $skiplock && !$is_root;
>  
>  	PVE::QemuServer::vm_sendkey($vmid, $skiplock, $param->{key});
>  
> @@ -3392,6 +3410,8 @@ __PACKAGE__->register_method({
>  
>  	my $storecfg = PVE::Storage::config();
>  
> +	my $is_root = PVE::Tools::check_for_root("/vms/$vmid");
> +
>  	my $move_updatefn =  sub {
>  	    my $conf = PVE::QemuConfig->load_config($vmid);
>  	    PVE::QemuConfig->check_lock($conf);
> @@ -3671,7 +3691,7 @@ __PACKAGE__->register_method({
>  	    raise_param_exc({ 'target-vmid' => $msg, 'storage' => $msg });
>  	} elsif ($target_vmid) {
>  	    $rpcenv->check_vm_perm($authuser, $target_vmid, undef, ['VM.Config.Disk'])
> -		if $authuser ne 'root@pam';
> +		if !$is_root;
>  
>  	    raise_param_exc({ 'target-vmid' => "must be different than source VMID to reassign disk" })
>  		if $vmid eq $target_vmid;
> @@ -3910,15 +3930,17 @@ __PACKAGE__->register_method({
>  
>  	my $vmid = extract_param($param, 'vmid');
>  
> +	my $is_root = PVE::Tools::check_for_root("/vms/$vmid");
> +
>  	raise_param_exc({ force => "Only root may use this option." })
> -	    if $param->{force} && $authuser ne 'root@pam';
> +	    if $param->{force} && !$is_root;
>  
>  	raise_param_exc({ migration_type => "Only root may use this option." })
> -	    if $param->{migration_type} && $authuser ne 'root@pam';
> +	    if $param->{migration_type} && !$is_root;
>  
>  	# allow root only until better network permissions are available
>  	raise_param_exc({ migration_network => "Only root may use this option." })
> -	    if $param->{migration_network} && $authuser ne 'root@pam';
> +	    if $param->{migration_network} && !$is_root;
>  
>  	# test if VM exists
>  	my $conf = PVE::QemuConfig->load_config($vmid);
> @@ -4099,8 +4121,10 @@ __PACKAGE__->register_method({
>  	my $sizestr = extract_param($param, 'size');
>  
>  	my $skiplock = extract_param($param, 'skiplock');
> +	my $is_root = PVE::Tools::check_for_root("/vms/$vmid");
> +
>          raise_param_exc({ skiplock => "Only root may use this option." })
> -            if $skiplock && $authuser ne 'root@pam';
> +            if $skiplock && !$is_root;
>  
>          my $storecfg = PVE::Storage::config();
>  
> -- 
> 2.30.2
> 
> 
> 
> _______________________________________________
> pve-devel mailing list
> pve-devel@lists.proxmox.com
> https://lists.proxmox.com/cgi-bin/mailman/listinfo/pve-devel
> 
> 
> 




  reply	other threads:[~2022-01-10 13:45 UTC|newest]

Thread overview: 8+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2022-01-05 15:22 [pve-devel] [RFC access-control common container qemu-server 0/4] #2582: Sys.Root privilege Oguz Bektas
2022-01-05 15:22 ` [pve-devel] [RFC access-control 1/4] add " Oguz Bektas
2022-01-05 15:22 ` [pve-devel] [RFC common 2/4] tools: add 'check_for_root' helper Oguz Bektas
2022-01-10 13:45   ` Fabian Grünbichler
2022-01-05 15:22 ` [pve-devel] [PATCH container 3/4] fix #2582: api: use common helper for checking root privileges Oguz Bektas
2022-01-05 15:22 ` [pve-devel] [RFC qemu-server 4/4] " Oguz Bektas
2022-01-10 13:45   ` Fabian Grünbichler [this message]
2022-01-10 13:45 ` [pve-devel] [RFC access-control common container qemu-server 0/4] #2582: Sys.Root privilege Fabian Grünbichler

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=1641820993.tq6zsgq6uk.astroid@nora.none \
    --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.
Service provided by Proxmox Server Solutions GmbH | Privacy | Legal