use JSON;
use MIME::Base64;
-use PVE::Exception qw(raise raise_perm_exc);
+use PVE::Exception qw(raise raise_perm_exc raise_param_exc);
use PVE::SafeSyslog;
use PVE::RPCEnvironment;
use PVE::Cluster qw(cfs_read_file);
-use PVE::Corosync;
+use PVE::DataCenterConfig;
use PVE::RESTHandler;
use PVE::AccessControl;
use PVE::JSONSchema qw(get_standard_option);
use PVE::API2::Group;
use PVE::API2::Role;
use PVE::API2::ACL;
+use PVE::Auth::Plugin;
use PVE::OTP;
use PVE::Tools;
user => 'world'
},
protected => 1, # else we can't access shadow files
+ allowtoken => 0, # we don't want tokens to create tickets
description => "Create or verify authentication ticket.",
parameters => {
additionalProperties => 0,
$res->{cap} = &$compute_api_permission($rpcenv, $username)
if !defined($res->{NeedTFA});
- if (PVE::Corosync::check_conf_exists(1)) {
- if ($rpcenv->check($username, '/', ['Sys.Audit'], 1)) {
- eval {
- my $conf = cfs_read_file('corosync.conf');
- my $totem = PVE::Corosync::totem_config($conf);
- if ($totem->{cluster_name}) {
- $res->{clustername} = $totem->{cluster_name};
- }
- };
- warn "$@\n" if $@;
- }
+ my $clinfo = PVE::Cluster::get_clinfo();
+ if ($clinfo->{cluster}->{name} && $rpcenv->check($username, '/', ['Sys.Audit'], 1)) {
+ $res->{clustername} = $clinfo->{cluster}->{name};
}
PVE::Cluster::log_msg('info', 'root@pam', "successful auth for user '$username'");
],
},
protected => 1, # else we can't access shadow files
+ allowtoken => 0, # we don't want tokens to change the regular user password
description => "Change user password.",
parameters => {
additionalProperties => 0,
my $dc = cfs_read_file('datacenter.cfg');
my $u2f = $dc->{u2f};
die "u2f not configured in datacenter.cfg\n" if !$u2f;
- $u2f = PVE::JSONSchema::parse_property_string($PVE::Cluster::u2f_format, $u2f);
return $u2f;
}
],
},
protected => 1, # else we can't access shadow files
+ allowtoken => 0, # we don't want tokens to change the regular user's TFA settings
description => "Change user u2f authentication.",
parameters => {
additionalProperties => 0,
optional => 1,
description => 'When adding TOTP, the shared secret value.',
type => 'string',
- # This is what pve-common's PVE::OTP::oath_verify_otp accepts.
- # Should we move this to pve-common's JSONSchema as a named format?
- pattern => qr/[A-Z2-7=]{16}|[A-Fa-f0-9]{40}/,
+ format => 'pve-tfa-secret',
},
config => {
optional => 1,
# Regular users need to confirm their password to change u2f settings.
if ($authuser ne 'root@pam') {
- raise_param_exc('password' => 'password is required to modify u2f data')
+ raise_param_exc({ 'password' => 'password is required to modify u2f data' })
if !defined($password);
my $domain_cfg = cfs_read_file('domains.cfg');
my $cfg = $domain_cfg->{ids}->{$realm};
- die "auth domain '$realm' does not exists\n" if !$cfg;
+ die "auth domain '$realm' does not exist\n" if !$cfg;
my $plugin = PVE::Auth::Plugin->lookup($cfg->{type});
$plugin->authenticate_user($cfg, $realm, $ruid, $password);
}
return $challenge;
}
} elsif ($action eq 'confirm') {
- raise_param_exc('response' => "confirm action requires the 'response' parameter to be set")
+ raise_param_exc({ 'response' => "confirm action requires the 'response' parameter to be set" })
if !defined($response);
my ($type, $u2fdata) = PVE::AccessControl::user_get_tfa($userid, $realm);
method => 'POST',
permissions => { user => 'all' },
protected => 1, # else we can't access shadow files
+ allowtoken => 0, # we don't want tokens to access TFA information
description => 'Finish a u2f challenge.',
parameters => {
additionalProperties => 0,
}
}});
+__PACKAGE__->register_method({
+ name => 'permissions',
+ path => 'permissions',
+ method => 'GET',
+ description => 'Retrieve effective permissions of given user/token.',
+ permissions => {
+ description => "Each user/token is allowed to dump their own permissions. A user can dump the permissions of another user if they have 'Sys.Audit' permission on /access.",
+ user => 'all',
+ },
+ parameters => {
+ additionalProperties => 0,
+ properties => {
+ userid => {
+ type => 'string',
+ description => "User ID or full API token ID",
+ pattern => $PVE::AccessControl::userid_or_token_regex,
+ optional => 1,
+ },
+ path => get_standard_option('acl-path', {
+ description => "Only dump this specific path, not the whole tree.",
+ optional => 1,
+ }),
+ },
+ },
+ returns => {
+ type => 'object',
+ description => 'Map of "path" => (Map of "privilege" => "propagate boolean").',
+ },
+ code => sub {
+ my ($param) = @_;
+
+ my $rpcenv = PVE::RPCEnvironment::get();
+
+ my $userid = $param->{userid};
+ if (defined($userid)) {
+ $rpcenv->check($rpcenv->get_user(), '/access', ['Sys.Audit']);
+ } else {
+ $userid = $rpcenv->get_user();
+ }
+
+ my $res;
+
+ if (my $path = $param->{path}) {
+ my $perms = $rpcenv->permissions($userid, $path);
+ if ($perms) {
+ $res = { $path => $perms };
+ } else {
+ $res = {};
+ }
+ } else {
+ $res = $rpcenv->get_effective_permissions($userid);
+ }
+
+ return $res;
+ }});
+
1;