feat: add 2 configurable knobs to (self|account)AddPersonalAccess

widest_v4_prefix (maximum allowed prefix to add in a single ACL),
and self_remote_user_only (only allow ACLs where the remote user
is the same than the bastion account name)
This commit is contained in:
Stéphane Lesimple 2023-05-31 13:06:15 +00:00 committed by Stéphane Lesimple
parent 482eddb10c
commit cf405badfb
4 changed files with 130 additions and 17 deletions

View file

@ -85,18 +85,38 @@ my $machine = $ip;
$port and $machine .= ":$port";
$user and $machine = $user . '@' . $machine;
my $plugin = ($target eq 'self' ? 'self' : 'account') . 'AddPersonalAccess';
# check plugin config for (self|account)AddPersonalAccess
my $widestV4Prefix;
if ($action eq 'add') {
$fnret = OVH::Bastion::plugin_config(plugin => $plugin);
$fnret or HEXIT($fnret);
if ($fnret->value && $fnret->value->{'self_remote_user_only'}) {
if (!$user || $user ne $account) {
HEXIT('ERR_INVALID_PARAMETER',
msg => "This bastion policy forces the remote user of personal accesses to match\n"
. "the account name: you may retry with --user $account");
}
}
$widestV4Prefix = $fnret->value->{'widest_v4_prefix'};
}
# access_modify validates all its parameters, don't do it ourselves here for clarity
$fnret = OVH::Bastion::access_modify(
way => 'personal',
account => $account,
action => $action,
user => $user,
ip => $ip,
port => $port,
ttl => $ttl,
forceKey => $forceKey,
forcePassword => $forcePassword,
comment => $comment,
way => 'personal',
account => $account,
action => $action,
user => $user,
ip => $ip,
port => $port,
ttl => $ttl,
forceKey => $forceKey,
forcePassword => $forcePassword,
comment => $comment,
widestV4Prefix => $widestV4Prefix,
);
if ($fnret->err eq 'OK') {
my $ttlmsg = $ttl ? ' (expires in ' . OVH::Bastion::duration2human(seconds => $ttl)->value->{'human'} . ')' : '';

View file

@ -102,6 +102,39 @@ if ($forceKey && $forcePassword) {
osh_exit 'ERR_INCOMPATIBLE_PARAMETERS', "Can't use --force-key and --force-password at the same time";
}
# check plugin config
if ($pluginConfig && $pluginConfig->{'self_remote_user_only'}) {
if (!$user || $user ne $account) {
osh_exit('ERR_INVALID_PARAMETER',
msg => "This bastion policy forces the remote user of personal accesses to match\n"
. "the account name: you may retry with --user $account");
}
}
# if no comment is specified, but we're adding the server by hostname,
# use it to craft a comment
if (!$comment && $host ne $ip) {
$comment = "hostname=$host";
}
# use dryrun to validate all parameters
$fnret = OVH::Bastion::access_modify(
dryrun => 1,
sudo => 0,
way => 'personal',
account => $account,
action => 'add',
user => $user,
ip => $ip,
port => $port,
ttl => $ttl,
forceKey => $forceKey,
forcePassword => $forcePassword,
comment => $comment,
widestV4Prefix => ($pluginConfig ? $pluginConfig->{'widest_v4_prefix'} : undef),
);
$fnret or osh_exit($fnret);
osh_info "Can't verify whether $account\'s personal key has been installed to the remote server, "
. "as you don't have access to their private keys, adding the access blindly";

View file

@ -90,6 +90,39 @@ if ($forceKey && $forcePassword) {
osh_exit 'ERR_INCOMPATIBLE_PARAMETERS', "Can't use --force-key and --force-password at the same time";
}
# check plugin config
if ($pluginConfig && $pluginConfig->{'self_remote_user_only'}) {
if (!$user || $user ne $self) {
osh_exit('ERR_INVALID_PARAMETER',
msg => "This bastion policy forces the remote user of personal accesses to match\n"
. "the account name: you may retry with --user $self");
}
}
# if no comment is specified, but we're adding the server by hostname,
# use it to craft a comment
if (!$comment && $host ne $ip) {
$comment = "hostname=$host";
}
# use dryrun to validate all parameters
$fnret = OVH::Bastion::access_modify(
dryrun => 1,
sudo => 0,
way => 'personal',
account => $self,
action => 'add',
user => $user,
ip => $ip,
port => $port,
ttl => $ttl,
forceKey => $forceKey,
forcePassword => $forcePassword,
comment => $comment,
widestV4Prefix => ($pluginConfig ? $pluginConfig->{'widest_v4_prefix'} : undef),
);
$fnret or osh_exit($fnret);
if (not $force) {
$fnret = OVH::Bastion::ssh_test_access_way(
account => $self,
@ -100,7 +133,6 @@ if (not $force) {
forcePassword => $forcePassword
);
if ($fnret->is_ok and $fnret->err ne 'OK') {
# we have something to say, say it
osh_info $fnret->msg;
}
@ -113,12 +145,6 @@ else {
osh_info "Forcing add as asked, we didn't test the SSH connection, maybe it won't work!";
}
# if no comment is specified, but we're adding the server by hostname,
# use it to craft a comment
if (!$comment && $host ne $ip) {
$comment = "hostname=$host";
}
my @command = qw{ sudo -n -u allowkeeper -- /usr/bin/env perl -T };
push @command, $OVH::Bastion::BASEPATH . '/bin/helper/osh-accountModifyPersonalAccess';
push @command, '--target', 'self';

View file

@ -121,6 +121,40 @@ testsuite_selfaccesses()
contain "already"
json .command selfAddPersonalAccess .error_code OK_NO_CHANGE .value null
# test selfAddPersonalAccess config items
success selfAddPersonalAccess_setconfig1 $r0 "echo '\{\\\"self_remote_user_only\\\":true\,\\\"widest_v4_prefix\\\":30\}' \> $opt_remote_etc_bastion/plugin.selfAddPersonalAccess.conf \; chmod o+r $opt_remote_etc_bastion/plugin.selfAddPersonalAccess.conf"
plgfail selfAddPersonalAccess_self_remote_user_only $a0 --osh selfAddPersonalAccess --host 127.0.0.9 --user notme --port-any
json .error_code ERR_INVALID_PARAMETER
contain "you may retry"
plgfail selfAddPersonalAccess_too_wide $a0 --osh selfAddPersonalAccess --host 127.0.0.0/8 --user $account0 --port-any
json .error_code ERR_INVALID_PARAMETER
contain "IPv4 is /30 by this"
success selfAddPersonalAccess_constraints_ok $a0 --osh selfAddPersonalAccess --host 127.0.0.9 --user $account0 --port-any --ttl 1 --force
success selfAddPersonalAccess_delconfig $r0 "rm -f $opt_remote_etc_bastion/plugin.selfAddPersonalAccess.conf"
# same with accountAddPersonalAccess
grant accountAddPersonalAccess
success accountAddPersonalAccess_setconfig1 $r0 "echo '\{\\\"self_remote_user_only\\\":true\,\\\"widest_v4_prefix\\\":30\}' \> $opt_remote_etc_bastion/plugin.accountAddPersonalAccess.conf \; chmod o+r $opt_remote_etc_bastion/plugin.accountAddPersonalAccess.conf"
plgfail accountAddPersonalAccess_self_remote_user_only $a0 --osh accountAddPersonalAccess --host 127.0.0.9 --user notme --port-any --account $account1
json .error_code ERR_INVALID_PARAMETER
contain "you may retry"
plgfail accountAddPersonalAccess_too_wide $a0 --osh accountAddPersonalAccess --host 127.0.0.0/8 --user $account1 --port-any --account $account1
json .error_code ERR_INVALID_PARAMETER
contain "IPv4 is /30 by this"
success accountAddPersonalAccess_constaints_ok $a0 --osh accountAddPersonalAccess --host 127.0.0.9 --user $account1 --port-any --ttl 1 --account $account1
success accountAddPersonalAccess_delconfig $r0 "rm -f $opt_remote_etc_bastion/plugin.accountAddPersonalAccess.conf"
revoke accountAddPersonalAccess
# /test (self|account)AddPersonalAccess config items
success withttl $a0 -osh selfAddPersonalAccess -h 127.0.0.4 -u $shellaccount -p 22 --force --ttl 0d0h0m3s
json .command selfAddPersonalAccess .error_code OK .value.ip 127.0.0.4 .value.user $shellaccount .value.port 22 .value.ttl 3