diff --git a/bin/plugin/open/batch b/bin/plugin/open/batch index 342ee78..0ae6bcb 100755 --- a/bin/plugin/open/batch +++ b/bin/plugin/open/batch @@ -57,7 +57,12 @@ while (my $line = ) { $line =~ s/ --json[a-z-]*//g; my @cmd = ($ENV{'SHELL'}, '-c', "--osh $line --json"); osh_info "--- launching command: $line"; - $fnret = OVH::Bastion::helper(cmd => \@cmd); + do { + # notify that we're under batch mode, hence if plugin requires MFA, + # we'll require --proactive-mfa, see comment in lib/perl/OVH/Bastion.pm + local $ENV{'OSH_BATCH'} = 1; + $fnret = OVH::Bastion::helper(cmd => \@cmd); + }; if (!$fnret) { osh_warn "--- command failed!"; } diff --git a/lib/perl/OVH/Bastion.pm b/lib/perl/OVH/Bastion.pm index e8fe8b5..6143561 100644 --- a/lib/perl/OVH/Bastion.pm +++ b/lib/perl/OVH/Bastion.pm @@ -1006,6 +1006,14 @@ sub do_pamtester { return R('ERR_MISSING_PARAMETER', msg => "Missing mandatory arguments 'sysself' or 'self'"); } + # if we're being called as part of the batch plugin, OSH_BATCH will be set and it means + # we can't grab the term, so pam can't set raw mode to avoid local echo, and it could end + # up having passwords typed by the user displayed on screen. In that case, refuse to do it, + # and return an error to our caller. + if ($ENV{'OSH_BATCH'}) { + return R('KO_MFA_TERM_NOT_RAW', msg => "MFA is required for this action, but we're running under batch mode, please use --proactive-mfa"); + } + # use system() instead of OVH::Bastion::execute() because we need it to grab the term my $pamtries = 3; while (1) { @@ -1017,11 +1025,11 @@ sub do_pamtester { $pamsysret = system('pamtester', 'sshd', $sysself, 'authenticate'); } if ($pamsysret < 0) { - return R('KO_MFA_FAILED', msg => "MFA is required for this host, but this bastion is missing the `pamtester' tool, aborting"); + return R('KO_MFA_FAILED', msg => "MFA is required for this action, but this bastion is missing the `pamtester' tool, aborting"); } elsif ($pamsysret != 0) { if (--$pamtries <= 0) { - return R('KO_MFA_FAILED', msg => "Sorry, but Multi-Factor Authentication failed, I can't connect you to this host"); + return R('KO_MFA_FAILED', msg => "Sorry, but Multi-Factor Authentication failed, couldn't complete the requested action"); } next; } diff --git a/tests/functional/tests.d/340-selfaccesses.sh b/tests/functional/tests.d/340-selfaccesses.sh index aa9e497..94783a7 100644 --- a/tests/functional/tests.d/340-selfaccesses.sh +++ b/tests/functional/tests.d/340-selfaccesses.sh @@ -79,7 +79,7 @@ testsuite_selfaccesses() # batch plugin - script one "printf \"%b\\n\" \"info\\naccountInfo --account $account0\\nselfListEgressKeys\" | $a1 --osh batch" + script batch_one "printf \"%b\\n\" \"info\\naccountInfo --account $account0\\nselfListEgressKeys\" | $a1 --osh batch" retvalshouldbe 0 json .command batch .error_code OK json '.value[0].result.error_code' OK '.value[0].command' info '.value[0].result.value.account' "$account1" diff --git a/tests/functional/tests.d/370-mfa.sh b/tests/functional/tests.d/370-mfa.sh index ea9382d..9e31c8a 100644 --- a/tests/functional/tests.d/370-mfa.sh +++ b/tests/functional/tests.d/370-mfa.sh @@ -66,6 +66,48 @@ testsuite_mfa() json .command groupList .error_code OK_EMPTY fi + # batch trying to start a plugin that requires mfa => should get an error + + if [ "${capabilities[pamtester]}" = 1 ]; then + + success batch_set_mfa $r0 "echo '{\\\"mfa_required\\\":\\\"any\\\"}' \> $opt_remote_etc_bastion/plugin.info.conf \; chmod o+r $opt_remote_etc_bastion/plugin.info.conf" + + if [ "${capabilities[mfa]}" = 1 ] || [ "${capabilities[mfa-password]}" = 1 ]; then + script batch_try_mfa "echo 'set timeout 30; \ + spawn $a4 --osh batch; \ + expect \":\" { sleep 0.2; send \"$a4_password\\n\"; }; \ + expect \"waiting for input\" { sleep 0.2; send \"info\\n\"; }; \ + expect \"failed\" { sleep 0.2; send \"quit\\n\"; }; \ + expect eof; \ + lassign [wait] pid spawnid value value; \ + exit \$value' | expect -f -" + retvalshouldbe 0 + contain "launching command: info" + contain "entering MFA phase" + contain "please use --proactive-mfa" + nocontain "Your alias to connect" + json .command batch .error_code OK '.value[0].command' info '.value[0].result.error_code' KO_MFA_FAILED + else + script batch_try_mfa "echo 'set timeout 30; \ + spawn $a4 --osh batch; \ + expect \"waiting for input\" { sleep 0.2; send \"info\\n\"; }; \ + expect \"failed\" { sleep 0.2; send \"quit\\n\"; }; \ + expect eof; \ + lassign [wait] pid spawnid value value; \ + exit \$value' | expect -f -" + retvalshouldbe 0 + contain "launching command: info" + contain "entering MFA phase" + contain "please use --proactive-mfa" + nocontain "Your alias to connect" + json .command batch .error_code OK '.value[0].command' info '.value[0].result.error_code' KO_MFA_FAILED + fi + + success batch_unset_mfa $r0 "rm -f $opt_remote_etc_bastion/plugin.info.conf" + fi + + # /batch + if [ "${capabilities[pamtester]}" = 1 ]; then grant groupCreate