Commit e61ef871 authored by Dietmar Maurer's avatar Dietmar Maurer

add permissions for openvz create/update

parent b865665a
...@@ -5,13 +5,13 @@ use warnings; ...@@ -5,13 +5,13 @@ use warnings;
use File::Basename; use File::Basename;
use File::Path; use File::Path;
use POSIX qw (LONG_MAX); use POSIX qw (LONG_MAX);
use Cwd 'abs_path';
use PVE::SafeSyslog; use PVE::SafeSyslog;
use PVE::Tools qw(extract_param run_command); use PVE::Tools qw(extract_param run_command);
use PVE::Exception qw(raise raise_param_exc); use PVE::Exception qw(raise raise_param_exc);
use PVE::INotify; use PVE::INotify;
use PVE::Cluster qw(cfs_lock_file cfs_read_file); use PVE::Cluster qw(cfs_lock_file cfs_read_file cfs_write_file);
use PVE::AccessControl;
use PVE::Storage; use PVE::Storage;
use PVE::RESTHandler; use PVE::RESTHandler;
use PVE::RPCEnvironment; use PVE::RPCEnvironment;
...@@ -59,6 +59,30 @@ CPUUNITS="1000" ...@@ -59,6 +59,30 @@ CPUUNITS="1000"
CPUS="1" CPUS="1"
__EOD __EOD
my $check_ct_modify_config_perm = sub {
my ($rpcenv, $authuser, $vmid, $pool, $key_list) = @_;
return 1 if $authuser ne 'root@pam';
foreach my $opt (@$key_list) {
if ($opt eq 'cpus' || $opt eq 'cpuunits' || $opt eq 'cpulimit') {
$rpcenv->check_vm_perm($authuser, $vmid, $pool, ['VM.Config.CPU']);
} elsif ($opt eq 'disk' || $opt eq 'quotatime' || $opt eq 'quotaugidlimit') {
$rpcenv->check_vm_perm($authuser, $vmid, $pool, ['VM.Config.Disk']);
} elsif ($opt eq 'memory' || $opt eq 'swap') {
$rpcenv->check_vm_perm($authuser, $vmid, $pool, ['VM.Config.Memory']);
} elsif ($opt eq 'netif' || $opt eq 'ip_address' || $opt eq 'nameserver' ||
$opt eq 'searchdomain' || $opt eq 'hostname') {
$rpcenv->check_vm_perm($authuser, $vmid, $pool, ['VM.Config.Network']);
} else {
$rpcenv->check_vm_perm($authuser, $vmid, $pool, ['VM.Config.Options']);
}
}
return 1;
};
__PACKAGE__->register_method({ __PACKAGE__->register_method({
name => 'vmlist', name => 'vmlist',
path => '', path => '',
...@@ -198,6 +222,13 @@ __PACKAGE__->register_method({ ...@@ -198,6 +222,13 @@ __PACKAGE__->register_method({
path => '', path => '',
method => 'POST', method => 'POST',
description => "Create or restore a container.", description => "Create or restore a container.",
permissions => {
description => "You need 'VM.Allocate' permissions on /vms/{vmid} or on the VM pool /pool/{pool}, and 'Datastore.AllocateSpace' on the storage.",
check => [ 'or',
[ 'perm', '/vms/{vmid}', ['VM.Allocate']],
[ 'perm', '/pool/{pool}', ['VM.Allocate'], require_param => 'pool'],
],
},
protected => 1, protected => 1,
proxyto => 'node', proxyto => 'node',
parameters => { parameters => {
...@@ -230,6 +261,11 @@ __PACKAGE__->register_method({ ...@@ -230,6 +261,11 @@ __PACKAGE__->register_method({
type => 'boolean', type => 'boolean',
description => "Mark this as restore task.", description => "Mark this as restore task.",
}, },
pool => {
optional => 1,
type => 'string', format => 'pve-poolid',
description => "Add the VM to the specified pool.",
},
}), }),
}, },
returns => { returns => {
...@@ -240,7 +276,7 @@ __PACKAGE__->register_method({ ...@@ -240,7 +276,7 @@ __PACKAGE__->register_method({
my $rpcenv = PVE::RPCEnvironment::get(); my $rpcenv = PVE::RPCEnvironment::get();
my $user = $rpcenv->get_user(); my $authuser = $rpcenv->get_user();
my $node = extract_param($param, 'node'); my $node = extract_param($param, 'node');
...@@ -250,6 +286,8 @@ __PACKAGE__->register_method({ ...@@ -250,6 +286,8 @@ __PACKAGE__->register_method({
my $storage = extract_param($param, 'storage') || 'local'; my $storage = extract_param($param, 'storage') || 'local';
my $pool = extract_param($param, 'pool');
my $storage_cfg = cfs_read_file("storage.cfg"); my $storage_cfg = cfs_read_file("storage.cfg");
my $scfg = PVE::Storage::storage_check_node($storage_cfg, $storage, $node); my $scfg = PVE::Storage::storage_check_node($storage_cfg, $storage, $node);
...@@ -259,10 +297,28 @@ __PACKAGE__->register_method({ ...@@ -259,10 +297,28 @@ __PACKAGE__->register_method({
my $private = PVE::Storage::get_private_dir($storage_cfg, $storage, $vmid); my $private = PVE::Storage::get_private_dir($storage_cfg, $storage, $vmid);
if (defined($pool)) {
$rpcenv->check_pool_exist($pool);
$rpcenv->check_perm_modify($authuser, "/pool/$pool");
}
$rpcenv->check($authuser, "/storage/$storage", ['Datastore.AllocateSpace']);
&$check_ct_modify_config_perm($rpcenv, $authuser, $vmid, $pool, [ keys %$param]);
PVE::Storage::activate_storage($storage_cfg, $storage); PVE::Storage::activate_storage($storage_cfg, $storage);
my $conf = PVE::OpenVZ::parse_ovz_config("/tmp/openvz/$vmid.conf", $pve_base_ovz_config); my $conf = PVE::OpenVZ::parse_ovz_config("/tmp/openvz/$vmid.conf", $pve_base_ovz_config);
my $addVMtoPoolFn = sub {
my $usercfg = cfs_read_file("user.cfg");
if (my $data = $usercfg->{pools}->{$pool}) {
$data->{vms}->{$vmid} = 1;
$usercfg->{vms}->{$vmid} = $pool;
cfs_write_file("user.cfg", $usercfg);
}
};
my $code = sub { my $code = sub {
my $basecfg_fn = PVE::OpenVZ::config_file($vmid); my $basecfg_fn = PVE::OpenVZ::config_file($vmid);
...@@ -284,14 +340,7 @@ __PACKAGE__->register_method({ ...@@ -284,14 +340,7 @@ __PACKAGE__->register_method({
if !$param->{restore}; if !$param->{restore};
$archive = '-'; $archive = '-';
} else { } else {
if (PVE::Storage::parse_volume_id($ostemplate, 1)) { $archive = $rpcenv->check_volume_access($authuser, $storage_cfg, $vmid, $ostemplate);
$archive = PVE::Storage::path($storage_cfg, $ostemplate);
} else {
raise_param_exc({ archive => "Only root can pass arbitrary paths." })
if $user ne 'root@pam';
$archive = abs_path($ostemplate);
}
die "can't find file '$archive'\n" if ! -f $archive; die "can't find file '$archive'\n" if ! -f $archive;
} }
...@@ -346,15 +395,25 @@ __PACKAGE__->register_method({ ...@@ -346,15 +395,25 @@ __PACKAGE__->register_method({
PVE::OpenVZ::set_rootpasswd($private, $password) PVE::OpenVZ::set_rootpasswd($private, $password)
if defined($password); if defined($password);
} }
PVE::AccessControl::lock_user_config($addVMtoPoolFn, "can't add VM to pool") if $pool;
}; };
return $rpcenv->fork_worker($param->{restore} ? 'vzrestore' : 'vzcreate', return $rpcenv->fork_worker($param->{restore} ? 'vzrestore' : 'vzcreate',
$vmid, $user, $realcmd); $vmid, $authuser, $realcmd);
}; };
return PVE::OpenVZ::lock_container($vmid, $code); return PVE::OpenVZ::lock_container($vmid, $code);
}}); }});
my $vm_config_perm_list = [
'VM.Config.Disk',
'VM.Config.CPU',
'VM.Config.Memory',
'VM.Config.Network',
'VM.Config.Options',
];
__PACKAGE__->register_method({ __PACKAGE__->register_method({
name => 'update_vm', name => 'update_vm',
path => '{vmid}/config', path => '{vmid}/config',
...@@ -362,6 +421,9 @@ __PACKAGE__->register_method({ ...@@ -362,6 +421,9 @@ __PACKAGE__->register_method({
protected => 1, protected => 1,
proxyto => 'node', proxyto => 'node',
description => "Set virtual machine options.", description => "Set virtual machine options.",
permissions => {
check => ['perm', '/vms/{vmid}', $vm_config_perm_list, any => 1],
},
parameters => { parameters => {
additionalProperties => 0, additionalProperties => 0,
properties => PVE::OpenVZ::json_config_properties( properties => PVE::OpenVZ::json_config_properties(
...@@ -382,7 +444,7 @@ __PACKAGE__->register_method({ ...@@ -382,7 +444,7 @@ __PACKAGE__->register_method({
my $rpcenv = PVE::RPCEnvironment::get(); my $rpcenv = PVE::RPCEnvironment::get();
my $user = $rpcenv->get_user(); my $authuser = $rpcenv->get_user();
my $node = extract_param($param, 'node'); my $node = extract_param($param, 'node');
...@@ -392,6 +454,8 @@ __PACKAGE__->register_method({ ...@@ -392,6 +454,8 @@ __PACKAGE__->register_method({
die "no options specified\n" if !scalar(keys %$param); die "no options specified\n" if !scalar(keys %$param);
&$check_ct_modify_config_perm($rpcenv, $authuser, $vmid, undef, [keys %$param]);
my $code = sub { my $code = sub {
my $conf = PVE::OpenVZ::load_config($vmid); my $conf = PVE::OpenVZ::load_config($vmid);
...@@ -404,7 +468,7 @@ __PACKAGE__->register_method({ ...@@ -404,7 +468,7 @@ __PACKAGE__->register_method({
my $cmd = ['vzctl', '--skiplock', 'set', $vmid, @$changes, '--save']; my $cmd = ['vzctl', '--skiplock', 'set', $vmid, @$changes, '--save'];
PVE::Cluster::log_msg('info', $user, "update CT $vmid: " . join(' ', @$changes)); PVE::Cluster::log_msg('info', $authuser, "update CT $vmid: " . join(' ', @$changes));
run_command($cmd); run_command($cmd);
}; };
...@@ -593,7 +657,7 @@ __PACKAGE__->register_method({ ...@@ -593,7 +657,7 @@ __PACKAGE__->register_method({
my ($param) = @_; my ($param) = @_;
my $rpcenv = PVE::RPCEnvironment::get(); my $rpcenv = PVE::RPCEnvironment::get();
my $user = $rpcenv->get_user(); my $authuser = $rpcenv->get_user();
my $vmid = $param->{vmid}; my $vmid = $param->{vmid};
...@@ -712,7 +776,7 @@ __PACKAGE__->register_method({ ...@@ -712,7 +776,7 @@ __PACKAGE__->register_method({
my $rpcenv = PVE::RPCEnvironment::get(); my $rpcenv = PVE::RPCEnvironment::get();
my $user = $rpcenv->get_user(); my $authuser = $rpcenv->get_user();
my $vmid = $param->{vmid}; my $vmid = $param->{vmid};
...@@ -725,7 +789,7 @@ __PACKAGE__->register_method({ ...@@ -725,7 +789,7 @@ __PACKAGE__->register_method({
run_command($cmd); run_command($cmd);
}; };
return $rpcenv->fork_worker('vzdestroy', $vmid, $user, $realcmd); return $rpcenv->fork_worker('vzdestroy', $vmid, $authuser, $realcmd);
}}); }});
my $sslcert; my $sslcert;
...@@ -761,14 +825,14 @@ __PACKAGE__->register_method ({ ...@@ -761,14 +825,14 @@ __PACKAGE__->register_method ({
my $rpcenv = PVE::RPCEnvironment::get(); my $rpcenv = PVE::RPCEnvironment::get();
my $user = $rpcenv->get_user(); my $authuser = $rpcenv->get_user();
my $vmid = $param->{vmid}; my $vmid = $param->{vmid};
my $node = $param->{node}; my $node = $param->{node};
my $authpath = "/vms/$vmid"; my $authpath = "/vms/$vmid";
my $ticket = PVE::AccessControl::assemble_vnc_ticket($user, $authpath); my $ticket = PVE::AccessControl::assemble_vnc_ticket($authuser, $authpath);
$sslcert = PVE::Tools::file_get_contents("/etc/pve/pve-root-ca.pem", 8192) $sslcert = PVE::Tools::file_get_contents("/etc/pve/pve-root-ca.pem", 8192)
if !$sslcert; if !$sslcert;
...@@ -804,10 +868,10 @@ __PACKAGE__->register_method ({ ...@@ -804,10 +868,10 @@ __PACKAGE__->register_method ({
return; return;
}; };
my $upid = $rpcenv->fork_worker('vncproxy', $vmid, $user, $realcmd); my $upid = $rpcenv->fork_worker('vncproxy', $vmid, $authuser, $realcmd);
return { return {
user => $user, user => $authuser,
ticket => $ticket, ticket => $ticket,
port => $port, port => $port,
upid => $upid, upid => $upid,
...@@ -963,7 +1027,7 @@ __PACKAGE__->register_method({ ...@@ -963,7 +1027,7 @@ __PACKAGE__->register_method({
my $rpcenv = PVE::RPCEnvironment::get(); my $rpcenv = PVE::RPCEnvironment::get();
my $user = $rpcenv->get_user(); my $authuser = $rpcenv->get_user();
my $node = extract_param($param, 'node'); my $node = extract_param($param, 'node');
...@@ -983,7 +1047,7 @@ __PACKAGE__->register_method({ ...@@ -983,7 +1047,7 @@ __PACKAGE__->register_method({
return; return;
}; };
return $rpcenv->fork_worker('vzstart', $vmid, $user, $realcmd); return $rpcenv->fork_worker('vzstart', $vmid, $authuser, $realcmd);
}}); }});
__PACKAGE__->register_method({ __PACKAGE__->register_method({
...@@ -1011,7 +1075,7 @@ __PACKAGE__->register_method({ ...@@ -1011,7 +1075,7 @@ __PACKAGE__->register_method({
my $rpcenv = PVE::RPCEnvironment::get(); my $rpcenv = PVE::RPCEnvironment::get();
my $user = $rpcenv->get_user(); my $authuser = $rpcenv->get_user();
my $node = extract_param($param, 'node'); my $node = extract_param($param, 'node');
...@@ -1030,7 +1094,7 @@ __PACKAGE__->register_method({ ...@@ -1030,7 +1094,7 @@ __PACKAGE__->register_method({
return; return;
}; };
my $upid = $rpcenv->fork_worker('vzstop', $vmid, $user, $realcmd); my $upid = $rpcenv->fork_worker('vzstop', $vmid, $authuser, $realcmd);
return $upid; return $upid;
}}); }});
...@@ -1073,7 +1137,7 @@ __PACKAGE__->register_method({ ...@@ -1073,7 +1137,7 @@ __PACKAGE__->register_method({
my $rpcenv = PVE::RPCEnvironment::get(); my $rpcenv = PVE::RPCEnvironment::get();
my $user = $rpcenv->get_user(); my $authuser = $rpcenv->get_user();
my $node = extract_param($param, 'node'); my $node = extract_param($param, 'node');
...@@ -1106,7 +1170,7 @@ __PACKAGE__->register_method({ ...@@ -1106,7 +1170,7 @@ __PACKAGE__->register_method({
return; return;
}; };
my $upid = $rpcenv->fork_worker('vzshutdown', $vmid, $user, $realcmd); my $upid = $rpcenv->fork_worker('vzshutdown', $vmid, $authuser, $realcmd);
return $upid; return $upid;
}}); }});
...@@ -1143,7 +1207,7 @@ __PACKAGE__->register_method({ ...@@ -1143,7 +1207,7 @@ __PACKAGE__->register_method({
my $rpcenv = PVE::RPCEnvironment::get(); my $rpcenv = PVE::RPCEnvironment::get();
my $user = $rpcenv->get_user(); my $authuser = $rpcenv->get_user();
my $target = extract_param($param, 'target'); my $target = extract_param($param, 'target');
...@@ -1175,7 +1239,7 @@ __PACKAGE__->register_method({ ...@@ -1175,7 +1239,7 @@ __PACKAGE__->register_method({
return; return;
}; };
my $upid = $rpcenv->fork_worker('vzmigrate', $vmid, $user, $realcmd); my $upid = $rpcenv->fork_worker('vzmigrate', $vmid, $authuser, $realcmd);
return $upid; return $upid;
}}); }});
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment