the-bastion/bin/plugin/open/selfMFASetupTOTP
2022-07-01 10:21:19 +02:00

114 lines
3.5 KiB
Perl
Executable file

#! /usr/bin/env perl
# vim: set filetype=perl ts=4 sw=4 sts=4 et:
use common::sense;
use File::Basename;
use lib dirname(__FILE__) . '/../../../lib/perl';
use OVH::Result;
use OVH::Bastion;
use OVH::Bastion::Plugin qw( :DEFAULT help );
my $remainingOptions = OVH::Bastion::Plugin::begin(
argv => \@ARGV,
header => "setup TOTP for your account",
options => {
'no-confirm' => \my $noConfirm,
},
helptext => <<'EOF'
Setup an additional credential (TOTP) to access your account
Usage: --osh SCRIPT_NAME [--no-confirm]
--no-confirm Bypass the confirmation step for TOTP enrollment phase
EOF
);
my $fnret;
my @command;
if (OVH::Bastion::config('accountMFAPolicy')->value eq 'disabled') {
osh_exit('ERR_DISABLED_BY_POLICY',
"Sorry, Multi-Factor Authentication has been disabled by policy on this bastion");
}
if ($ENV{'OSH_IN_INTERACTIVE_SESSION'}) {
osh_exit('ERR_PRECONDITIONS_FAILED',
"For security reasons, this plugin can't be used in interactive mode.\nTo ensure you're the owner of the account, please call it the regular way (i.e. --osh $scriptName)"
);
}
# do the TOTP enrollment
my $TOTPProvider = OVH::Bastion::config("TOTPProvider")->value;
if ($TOTPProvider eq 'none') {
# unconfigured: as we don't know which provider we have, just error out
osh_exit(
R(
'ERR_CONFIGURATION_ERROR',
msg => "No TOTP provider has been enabled, please check with your sysadmin if this is unexpected"
)
);
}
elsif ($TOTPProvider eq 'google-authenticator') {
# first, check if the google-authenticator we have supports --issuer, if not, just omit it, it's not a deal-breaker
$fnret = OVH::Bastion::execute(cmd => ['google-authenticator', '-h'], must_succeed => 1);
$fnret or osh_exit($fnret);
my @additional_params;
if (grep { /--issuer/ } @{$fnret->value->{'stdout'}}) {
push @additional_params, "--issuer=" . OVH::Bastion::config('bastionName')->value;
}
if ($noConfirm && grep { /--no-confirm/ } @{$fnret->value->{'stdout'}}) {
push @additional_params, "--no-confirm";
}
@command = (
'script',
'-q',
'-c',
"google-authenticator -f -t -Q UTF8 -r 3 -R 15 -w 2 -D "
. join(" ", @additional_params)
. " -l $self -s $HOME/"
. OVH::Bastion::TOTP_GAUTH_FILENAME,
'/dev/null'
);
{
local $ENV{'SHELL'} = '/bin/sh';
$fnret = OVH::Bastion::execute(
cmd => \@command,
noisy_stderr => 1,
noisy_stdout => 1,
expects_stdin => 1,
is_binary => 1,
must_succeed => 1
);
}
if (!$fnret) {
osh_exit('ERR_TOTP_SETUP_FAILED', msg => "Couldn't setup TOTP for your account, try again!");
}
chmod 0400, $HOME . '/' . OVH::Bastion::TOTP_GAUTH_FILENAME;
}
elsif ($TOTPProvider eq 'duo') {
# nothing to do locally, appart from marking the user as TOTP-active, which is done after this block.
}
else {
# unknown provider, this shouldn't happen
osh_exit(
R(
'ERR_CONFIGURATION_ERROR',
msg => "An unknown TOTP provider has been provided, please check with your sysadmin."
)
);
}
# it worked, add the account to the proper system group
@command = qw{ sudo -n -u root -- /usr/bin/env perl -T };
push @command, $OVH::Bastion::BASEPATH . '/bin/helper/osh-selfMFASetupTOTP';
push @command, '--account', $self;
osh_exit(OVH::Bastion::helper(cmd => \@command));