api: check Sys.Audit permissions when setting a custom CPU model

Explicitly allows changing other properties than the cputype, even if
the currently set cputype is not accessible by the user. This way, an
administrator can assign a custom CPU type to a VM for a less privileged
user without breaking edit functionality for them.

Signed-off-by: Stefan Reiter <s.reiter@proxmox.com>
This commit is contained in:
Stefan Reiter 2020-05-04 12:58:38 +02:00 committed by Thomas Lamprecht
parent 690748632b
commit 6e72f90bbb

View File

@ -21,6 +21,7 @@ use PVE::GuestHelpers;
use PVE::QemuConfig; use PVE::QemuConfig;
use PVE::QemuServer; use PVE::QemuServer;
use PVE::QemuServer::Drive; use PVE::QemuServer::Drive;
use PVE::QemuServer::CPUConfig;
use PVE::QemuServer::Monitor qw(mon_cmd); use PVE::QemuServer::Monitor qw(mon_cmd);
use PVE::QemuMigrate; use PVE::QemuMigrate;
use PVE::RPCEnvironment; use PVE::RPCEnvironment;
@ -236,6 +237,26 @@ my $create_disks = sub {
return $vollist; return $vollist;
}; };
my $check_cpu_model_access = sub {
my ($rpcenv, $authuser, $new, $existing) = @_;
return if !defined($new->{cpu});
my $cpu = PVE::JSONSchema::check_format('pve-vm-cpu-conf', $new->{cpu});
return if !$cpu || !$cpu->{cputype}; # always allow default
my $cputype = $cpu->{cputype};
if ($existing && $existing->{cpu}) {
# changing only other settings doesn't require permissions for CPU model
my $existingCpu = PVE::JSONSchema::check_format('pve-vm-cpu-conf', $existing->{cpu});
return if $existingCpu->{cputype} eq $cputype;
}
if (PVE::QemuServer::CPUConfig::is_custom_model($cputype)) {
$rpcenv->check($authuser, "/nodes", ['Sys.Audit']);
}
};
my $cpuoptions = { my $cpuoptions = {
'cores' => 1, 'cores' => 1,
'cpu' => 1, 'cpu' => 1,
@ -543,6 +564,8 @@ __PACKAGE__->register_method({
&$check_vm_modify_config_perm($rpcenv, $authuser, $vmid, $pool, [ keys %$param]); &$check_vm_modify_config_perm($rpcenv, $authuser, $vmid, $pool, [ keys %$param]);
&$check_cpu_model_access($rpcenv, $authuser, $param);
foreach my $opt (keys %$param) { foreach my $opt (keys %$param) {
if (PVE::QemuServer::is_valid_drivename($opt)) { if (PVE::QemuServer::is_valid_drivename($opt)) {
my $drive = PVE::QemuServer::parse_drive($opt, $param->{$opt}); my $drive = PVE::QemuServer::parse_drive($opt, $param->{$opt});
@ -1122,6 +1145,8 @@ my $update_vm_api = sub {
die "checksum missmatch (file change by other user?)\n" die "checksum missmatch (file change by other user?)\n"
if $digest && $digest ne $conf->{digest}; if $digest && $digest ne $conf->{digest};
&$check_cpu_model_access($rpcenv, $authuser, $param, $conf);
# FIXME: 'suspended' lock should probabyl be a state or "weak" lock?! # FIXME: 'suspended' lock should probabyl be a state or "weak" lock?!
if (scalar(@delete) && grep { $_ eq 'vmstate'} @delete) { if (scalar(@delete) && grep { $_ eq 'vmstate'} @delete) {
if (defined($conf->{lock}) && $conf->{lock} eq 'suspended') { if (defined($conf->{lock}) && $conf->{lock} eq 'suspended') {