Commit 612ec0a5 authored by Dietmar Maurer's avatar Dietmar Maurer

implement new check attribute for permissions.

We use a simple prefix notation to express complex expressions.
parent e0993680
......@@ -291,8 +291,7 @@ __PACKAGE__->register_method({
method => 'GET',
description => "Get datacenter options.",
permissions => {
path => '/',
privs => [ 'Sys.Audit' ],
check => ['perm', '/', [ 'Sys.Audit' ]],
},
parameters => {
additionalProperties => 0,
......@@ -313,8 +312,7 @@ __PACKAGE__->register_method({
method => 'PUT',
description => "Set datacenter options.",
permissions => {
path => '/',
privs => [ 'Sys.Modify' ],
check => ['perm', '/', [ 'Sys.Modify' ]],
},
protected => 1,
parameters => {
......
......@@ -19,8 +19,7 @@ __PACKAGE__->register_method({
method => 'GET',
description => "Directory index.",
permissions => {
path => '/',
privs => [ 'Sys.Audit' ],
check => ['perm', '/', [ 'Sys.Audit' ]],
},
parameters => {
additionalProperties => 0,
......@@ -90,8 +89,7 @@ __PACKAGE__->register_method({
description => "Read cluster configuartion (cluster.conf). If you have any uncommitted changes in cluster.conf.new that content is returned instead.",
protected => 1,
permissions => {
path => '/',
privs => [ 'Sys.Audit' ],
check => ['perm', '/', [ 'Sys.Audit' ]],
},
parameters => {
additionalProperties => 0,
......@@ -120,8 +118,7 @@ __PACKAGE__->register_method({
description => "Get pending changes (unified diff between cluster.conf and cluster.conf.new",
protected => 1,
permissions => {
path => '/',
privs => [ 'Sys.Audit' ],
check => ['perm', '/', [ 'Sys.Audit' ]],
},
parameters => {
additionalProperties => 0,
......@@ -143,8 +140,7 @@ __PACKAGE__->register_method({
description => "Revert pending changes (remove cluster.conf.new)",
protected => 1,
permissions => {
path => '/',
privs => [ 'Sys.Modify' ],
check => ['perm', '/', [ 'Sys.Modify' ]],
},
parameters => {
additionalProperties => 0,
......@@ -168,8 +164,7 @@ __PACKAGE__->register_method({
description => "Commit cluster configuartion. Pending changes from cluster.conf.new are written to cluster.conf. This triggers a CMan reload on all nodes.",
protected => 1,
permissions => {
path => '/',
privs => [ 'Sys.Modify' ],
check => ['perm', '/', [ 'Sys.Modify' ]],
},
parameters => {
additionalProperties => 0,
......@@ -227,8 +222,7 @@ __PACKAGE__->register_method({
description => "List resource groups.",
protected => 1,
permissions => {
path => '/',
privs => [ 'Sys.Audit' ],
check => ['perm', '/', [ 'Sys.Audit' ]],
},
parameters => {
additionalProperties => 0,
......@@ -270,8 +264,7 @@ __PACKAGE__->register_method({
description => "Create a new resource groups.",
protected => 1,
permissions => {
path => '/',
privs => [ 'Sys.Modify' ],
check => ['perm', '/', [ 'Sys.Modify' ]],
},
parameters => {
additionalProperties => 0,
......@@ -318,8 +311,7 @@ __PACKAGE__->register_method({
description => "Update resource groups settings.",
protected => 1,
permissions => {
path => '/',
privs => [ 'Sys.Modify' ],
check => ['perm', '/', [ 'Sys.Modify' ]],
},
parameters => {
additionalProperties => 0,
......@@ -373,8 +365,7 @@ __PACKAGE__->register_method({
description => "List resource groups.",
protected => 1,
permissions => {
path => '/',
privs => [ 'Sys.Audit' ],
check => ['perm', '/', [ 'Sys.Audit' ]],
},
parameters => {
additionalProperties => 0,
......@@ -422,8 +413,7 @@ __PACKAGE__->register_method({
description => "Delete resource group.",
protected => 1,
permissions => {
path => '/',
privs => [ 'Sys.Modify' ],
check => ['perm', '/', [ 'Sys.Modify' ]],
},
parameters => {
additionalProperties => 0,
......
......@@ -135,8 +135,7 @@ __PACKAGE__->register_method({
path => '',
method => 'POST',
permissions => {
path => '/nodes/{node}',
privs => [ 'Sys.Modify' ],
check => ['perm', '/nodes/{node}', [ 'Sys.Modify' ]],
},
description => "Create network device configuration",
protected => 1,
......@@ -181,8 +180,7 @@ __PACKAGE__->register_method({
path => '{iface}',
method => 'PUT',
permissions => {
path => '/nodes/{node}',
privs => [ 'Sys.Modify' ],
check => ['perm', '/nodes/{node}', [ 'Sys.Modify' ]],
},
description => "Update network device configuration",
protected => 1,
......@@ -239,8 +237,7 @@ __PACKAGE__->register_method({
path => '{iface}',
method => 'GET',
permissions => {
path => '/nodes/{node}',
privs => [ 'Sys.Audit' ],
check => ['perm', '/nodes/{node}', [ 'Sys.Audit' ]],
},
description => "Read network device configuration",
proxyto => 'node',
......@@ -278,8 +275,7 @@ __PACKAGE__->register_method({
path => '{iface}',
method => 'DELETE',
permissions => {
path => '/nodes/{node}',
privs => [ 'Sys.Modify' ],
check => ['perm', '/nodes/{node}', [ 'Sys.Modify' ]],
},
description => "Delete network device configuration",
protected => 1,
......
......@@ -147,8 +147,7 @@ __PACKAGE__->register_method({
name => 'beancounters_failcnt',
path => 'ubcfailcnt',
permissions => {
path => '/nodes/{node}',
privs => [ 'Sys.Audit' ],
check => ['perm', '/nodes/{node}', [ 'Sys.Audit' ]],
},
method => 'GET',
proxyto => 'node',
......@@ -189,8 +188,7 @@ __PACKAGE__->register_method({
path => 'network_changes',
method => 'GET',
permissions => {
path => '/nodes/{node}',
privs => [ 'Sys.Audit' ],
check => ['perm', '/nodes/{node}', [ 'Sys.Audit' ]],
},
description => "Get network configuration changes (diff) since last boot.",
proxyto => 'node',
......@@ -214,8 +212,7 @@ __PACKAGE__->register_method({
path => 'network_changes',
method => 'DELETE',
permissions => {
path => '/nodes/{node}',
privs => [ 'Sys.Modify' ],
check => ['perm', '/nodes/{node}', [ 'Sys.Modify' ]],
},
protected => 1,
description => "Revert network configuration changes.",
......@@ -240,8 +237,7 @@ __PACKAGE__->register_method({
path => 'status',
method => 'GET',
permissions => {
path => '/nodes/{node}',
privs => [ 'Sys.Audit' ],
check => ['perm', '/nodes/{node}', [ 'Sys.Audit' ]],
},
description => "Read node status",
proxyto => 'node',
......@@ -313,8 +309,7 @@ __PACKAGE__->register_method({
path => 'status',
method => 'POST',
permissions => {
path => '/nodes/{node}',
privs => [ 'Sys.PowerMgmt' ],
check => ['perm', '/nodes/{node}', [ 'Sys.PowerMgmt' ]],
},
protected => 1,
description => "Reboot or shutdown a node.",
......@@ -350,8 +345,7 @@ __PACKAGE__->register_method({
method => 'GET',
protected => 1, # fixme: can we avoid that?
permissions => {
path => '/nodes/{node}',
privs => [ 'Sys.Audit' ],
check => ['perm', '/nodes/{node}', [ 'Sys.Audit' ]],
},
description => "Read node RRD statistics (returns PNG)",
parameters => {
......@@ -396,8 +390,7 @@ __PACKAGE__->register_method({
method => 'GET',
protected => 1, # fixme: can we avoid that?
permissions => {
path => '/nodes/{node}',
privs => [ 'Sys.Audit' ],
check => ['perm', '/nodes/{node}', [ 'Sys.Audit' ]],
},
description => "Read node RRD statistics",
parameters => {
......@@ -438,8 +431,7 @@ __PACKAGE__->register_method({
description => "Read system log",
proxyto => 'node',
permissions => {
path => '/nodes/{node}',
privs => [ 'Sys.Syslog' ],
check => ['perm', '/nodes/{node}', [ 'Sys.Syslog' ]],
},
protected => 1,
parameters => {
......@@ -496,8 +488,7 @@ __PACKAGE__->register_method ({
method => 'POST',
protected => 1,
permissions => {
path => '/nodes/{node}',
privs => [ 'Sys.Console' ],
check => ['perm', '/nodes/{node}', [ 'Sys.Console' ]],
},
description => "Creates a VNC Shell proxy.",
parameters => {
......@@ -586,8 +577,7 @@ __PACKAGE__->register_method({
path => 'dns',
method => 'GET',
permissions => {
path => '/nodes/{node}',
privs => [ 'Sys.Audit' ],
check => ['perm', '/nodes/{node}', [ 'Sys.Audit' ]],
},
description => "Read DNS settings.",
proxyto => 'node',
......@@ -677,9 +667,8 @@ __PACKAGE__->register_method({
path => 'time',
method => 'GET',
permissions => {
path => '/nodes/{node}',
privs => [ 'Sys.Audit' ],
},
check => ['perm', '/nodes/{node}', [ 'Sys.Audit' ]],
},
description => "Read server time and time zone settings.",
proxyto => 'node',
parameters => {
......@@ -753,8 +742,7 @@ __PACKAGE__->register_method ({
path => 'upload',
method => 'POST',
permissions => {
path => '/storage/{storage}',
privs => [ 'Datastore.AllocateSpace' ],
check => ['perm', '/storage/{storage}', [ 'Datastore.AllocateSpace' ]],
},
description => "Upload content.",
parameters => {
......
......@@ -446,8 +446,7 @@ __PACKAGE__->register_method({
method => 'GET',
protected => 1, # fixme: can we avoid that?
permissions => {
path => '/vms/{vmid}',
privs => [ 'VM.Audit' ],
check => ['perm', '/vms/{vmid}', [ 'VM.Audit' ]],
},
description => "Read VM RRD statistics (returns PNG)",
parameters => {
......@@ -493,8 +492,7 @@ __PACKAGE__->register_method({
method => 'GET',
protected => 1, # fixme: can we avoid that?
permissions => {
path => '/vms/{vmid}',
privs => [ 'VM.Audit' ],
check => ['perm', '/vms/{vmid}', [ 'VM.Audit' ]],
},
description => "Read VM RRD statistics",
parameters => {
......@@ -536,8 +534,7 @@ __PACKAGE__->register_method({
protected => 1,
proxyto => 'node',
permissions => {
path => '/vms/{vmid}',
privs => [ 'VM.Audit' ],
check => ['perm', '/vms/{vmid}', [ 'VM.Audit' ]],
},
description => "Read init log.",
parameters => {
......@@ -714,8 +711,7 @@ __PACKAGE__->register_method ({
method => 'POST',
protected => 1,
permissions => {
path => '/vms/{vmid}',
privs => [ 'VM.Console' ],
check => ['perm', '/vms/{vmid}', [ 'VM.Console' ]],
},
description => "Creates a TCP VNC proxy connections.",
parameters => {
......
......@@ -153,8 +153,7 @@ __PACKAGE__->register_method ({
path => '',
method => 'GET',
permissions => {
path => '/nodes/{node}',
privs => [ 'Sys.Audit' ],
check => ['perm', '/nodes/{node}', [ 'Sys.Audit' ]],
},
description => "Service list.",
proxyto => 'node',
......@@ -231,8 +230,7 @@ __PACKAGE__->register_method ({
path => '{service}/state',
method => 'GET',
permissions => {
path => '/nodes/{node}',
privs => [ 'Sys.Audit' ],
check => ['perm', '/nodes/{node}', [ 'Sys.Audit' ]],
},
description => "Read service properties",
proxyto => 'node',
......
......@@ -271,6 +271,64 @@ sub proxy_handler {
return OK;
}
sub exec_perm_check {
my ($rpcenv, $check, $username, $param, $noerr) = @_;
my $test = shift @$check;
die "no permission test specified" if !$test;
if ($test eq 'and') {
while (my $subcheck = shift @$check) {
exec_perm_check($rpcenv, $subcheck, $username, $param);
}
return 1;
} elsif ($test eq 'or') {
while (my $subcheck = shift @$check) {
return 1 if exec_perm_check($rpcenv, $subcheck, $username, $param, 1);
}
return 0 if $noerr;
raise_perm_exc();
} elsif ($test eq 'perm') {
my ($tmplpath, $privs, %options) = @$check;
my $any = $options{any};
die "missing parameters" if !($tmplpath && $privs);
my $path = PVE::Tools::template_replace($tmplpath, $param);
if ($any) {
return $rpcenv->check_any($username, $path, $privs, $noerr);
} else {
return $rpcenv->check($username, $path, $privs, $noerr);
}
} elsif ($test eq 'userid-group') {
my $userid = $param->{userid};
return if !$rpcenv->check_user_exist($userid, $noerr);
my ($privs, %options) = @$check;
if (!$rpcenv->check_any($username, "/access", $privs, 1)) {
my $groups = $rpcenv->filter_groups($username, $privs, 1);
my $allowed_users = $rpcenv->group_member_join([keys %$groups]);
if (!$allowed_users->{$userid}) {
return 0 if $noerr;
raise_perm_exc();
}
}
return 1;
} elsif ($test eq 'userid-param') {
my $userid = $param->{userid};
return if !$rpcenv->check_user_exist($userid, $noerr);
my ($subtest) = @$check;
die "missing parameters" if !$subtest;
if ($subtest eq 'self') {
syslog("info", "TESTASQAS");
return 1 if $username eq 'userid';
return 0 if $noerr;
raise_perm_exc();
} else {
die "unknown userid-param test";
}
} else {
die "unknown permission test";
}
};
my $check_permissions = sub {
my ($rpcenv, $perm, $username, $param) = @_;
......@@ -284,14 +342,7 @@ my $check_permissions = sub {
return 1 if $perm->{user} && $perm->{user} eq 'all';
return 1 if $perm->{user} && $perm->{user} eq 'arg' &&
($username eq $param->{username} || $username eq $param->{userid});
if ($perm->{path} && $perm->{privs}) {
my $path = PVE::Tools::template_replace($perm->{path}, $param);
$rpcenv->check($username, $path, $perm->{privs});
return 1;
}
return exec_perm_check($rpcenv, $perm->{check}, $username, $param) if $perm->{check};
raise_perm_exc();
};
......
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