use Scalar::Util 'weaken';
use URI::Escape;
+use PVE::Exception qw(raise_perm_exc raise_param_exc);
use PVE::OTP;
use PVE::Ticket;
use PVE::Tools qw(run_command lock_file file_get_contents split_list safe_print);
my ($username, $realm, $tfa_response, $tfa_challenge) = @_;
my ($tfa_cfg, $realm_tfa) = user_get_tfa($username, $realm);
+ # FIXME: `$tfa_cfg` is now usually never undef - use cheap check for
+ # whether the user has *any* entries here instead whe it is available in
+ # pve-rs
if (!defined($tfa_cfg)) {
return undef;
}
$tfa_challenge = undef;
} else {
$tfa_challenge = $tfa_cfg->authentication_challenge($username);
+
+ die "missing required 2nd keys\n"
+ if $realm_tfa && !defined($tfa_challenge);
+
if (defined($tfa_response)) {
if (defined($tfa_challenge)) {
$tfa_done = 1;
my $children = $node->{children};
- foreach my $child (keys %$children) {
+ foreach my $child (sort keys %$children) {
iterate_acl_tree("$path/$child", $children->{$child}, $code);
}
}
'Sys.PowerMgmt',
'Sys.Modify', # edit/change node settings
'Sys.Incoming', # incoming storage/guest migrations
+ 'Sys.AccessNetwork', # for, e.g., downloading ISOs from any URL
],
admin => [
'Sys.Console',
sub create_roles {
- foreach my $cat (keys %$privgroups) {
+ for my $cat (keys %$privgroups) {
my $cd = $privgroups->{$cat};
- foreach my $p (@{$cd->{root}}, @{$cd->{admin}},
- @{$cd->{user}}, @{$cd->{audit}}) {
- $valid_privs->{$p} = 1;
+ # create map to easily check if a privilege is valid
+ for my $priv (@{$cd->{root}}, @{$cd->{admin}}, @{$cd->{user}}, @{$cd->{audit}}) {
+ $valid_privs->{$priv} = 1;
}
- foreach my $p (@{$cd->{admin}}, @{$cd->{user}}, @{$cd->{audit}}) {
-
- $special_roles->{"PVE${cat}Admin"}->{$p} = 1;
- $special_roles->{"PVEAdmin"}->{$p} = 1;
+ # create grouped admin roles and PVEAdmin
+ for my $priv (@{$cd->{admin}}, @{$cd->{user}}, @{$cd->{audit}}) {
+ $special_roles->{"PVE${cat}Admin"}->{$priv} = 1;
+ $special_roles->{"PVEAdmin"}->{$priv} = 1;
}
+ # create grouped user and audit roles
if (scalar(@{$cd->{user}})) {
- foreach my $p (@{$cd->{user}}, @{$cd->{audit}}) {
- $special_roles->{"PVE${cat}User"}->{$p} = 1;
+ for my $priv (@{$cd->{user}}, @{$cd->{audit}}) {
+ $special_roles->{"PVE${cat}User"}->{$priv} = 1;
}
}
- foreach my $p (@{$cd->{audit}}) {
- $special_roles->{"PVEAuditor"}->{$p} = 1;
+ for my $priv (@{$cd->{audit}}) {
+ $special_roles->{"PVEAuditor"}->{$priv} = 1;
}
}
|/nodes
|/nodes/[[:alnum:]\.\-\_]+
|/pool
- |/pool/[[:alnum:]\.\-\_]+
+ |/pool/[A-Za-z0-9\.\-_]+(?:/[A-Za-z0-9\.\-_]+){0,2}
|/sdn
+ |/sdn/controllers
+ |/sdn/controllers/[[:alnum:]\_\-]+
+ |/sdn/dns
+ |/sdn/dns/[[:alnum:]]+
+ |/sdn/ipams
+ |/sdn/ipams/[[:alnum:]]+
|/sdn/zones
|/sdn/zones/[[:alnum:]\.\-\_]+
|/sdn/zones/[[:alnum:]\.\-\_]+/[[:alnum:]\.\-\_]+
sub verify_poolname {
my ($poolname, $noerr) = @_;
- if ($poolname !~ m/^[A-Za-z0-9\.\-_]+$/) {
+ if (split("/", $poolname) > 3) {
+ die "pool name '$poolname' nested too deeply (max levels = 3)\n" if !$noerr;
+
+ return undef;
+ }
+ # also adapt check_path above if changed!
+ if ($poolname !~ m!^[A-Za-z0-9\.\-_]+(?:/[A-Za-z0-9\.\-_]+){0,2}$!) {
die "pool name '$poolname' contains invalid characters\n" if !$noerr;
return undef;
}
# make sure to add the pool (even if there are no members)
- $cfg->{pools}->{$pool} = { vms => {}, storage => {} } if !$cfg->{pools}->{$pool};
+ $cfg->{pools}->{$pool} = { vms => {}, storage => {}, pools => {} }
+ if !$cfg->{pools}->{$pool};
+
+ if ($pool =~ m!/!) {
+ my $curr = $pool;
+ while ($curr =~ m!^(.+)/[^/]+$!) {
+ # ensure nested pool info is correctly recorded
+ my $parent = $1;
+ $cfg->{pools}->{$curr}->{parent} = $parent;
+ $cfg->{pools}->{$parent} = { vms => {}, storage => {}, pools => {} }
+ if !$cfg->{pools}->{$parent};
+ $cfg->{pools}->{$parent}->{pools}->{$curr} = 1;
+ $curr = $parent;
+ }
+ }
$cfg->{pools}->{$pool}->{comment} = PVE::Tools::decode_text($comment) if $comment;
$realm_tfa = PVE::Auth::Plugin::parse_tfa_config($realm_tfa)
if $realm_tfa;
- if (!$keys) {
- return if !$realm_tfa;
- die "missing required 2nd keys\n";
- }
-
my $tfa_cfg = cfs_read_file('priv/tfa.cfg');
if (defined($keys) && $keys !~ /^x(?:!.*)$/) {
add_old_keys_to_realm_tfa($username, $tfa_cfg, $realm_tfa, $keys);
}
+
return ($tfa_cfg, $realm_tfa);
}