#! /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));