#! /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  => "modify the PIV policy of an account",
    options => {
        "account=s" => \my $account,
        "policy=s"  => \my $policy,
        "ttl=s"     => \my $ttl,
    },
    helptext => <<'EOF',
Modify the PIV policy for the ingress keys of an account

Usage: --osh SCRIPT_NAME --account ACCOUNT --policy <default|enforce|never|grace --ttl SECONDS|DURATION>

  --account ACCOUNT       Bastion account to work on
  --policy  POLICY        Changes the PIV policy of account. See below for a description of available policies.
  --ttl SECONDS|DURATION  For the ``grace`` policy, amount of time after which the account will automatically revert
                            to its previous policy (amount of seconds, or duration string such as "4d12h15m").

Possible POLICY values:
-----------------------

default
   No specific policy is defined for this account, the default bastion policy applies (see the :ref:`ingressRequirePIV` global option).

enforce
   Only verified PIV keys can be added as ingress SSH keys for this account. Note that setting the policy to ``enforce`` also immediately
   disables any non-PIV keys from the account's ingress keys. If no valid PIV key is found, this in effect disables all the keys of said
   account, preventing connection. The disabled keys are still kept so that setting back the policy to ``default`` or ``never`` does restore
   the non-PIV keys.

never
   Regardless of the global configuration of the bastion (see the :ref:`ingressRequirePIV` global option), this account will never be required
   to use only PIV keys. This can be needed for a non-human account if PIV is enabled bastion-wide.

grace
   enables temporary deactivation of PIV enforcement on this account. This is only meaningful when the policy is already set to ``enforce``
   for this account, or if the global :ref:`ingressRequirePIV` option is set to true. This policy requires the use of the ``--ttl`` option to
   specify how much time the policy will be relaxed for this account before going back to its previous policy automatically. This can be
   useful when people forget their PIV-enabled hardware token and you don't want to send them back home.
EOF
);

my $fnret;

if (!$account) {
    help();
    osh_exit 'ERR_MISSING_PARAMETER', "Missing mandatory parameter 'account'";
}

$fnret = OVH::Bastion::is_bastion_account_valid_and_existing(account => $account, localOnly => 1);
$fnret or osh_exit $fnret;
$account = $fnret->value->{'account'};

if (not grep { $policy eq $_ } qw{ default enforce never grace }) {
    help();
    osh_exit 'ERR_INVALID_PARAMETER', "Expected either 'none,' enforce', 'never' or 'grace' as a parameter to --policy";
}

if ($policy eq 'grace' && !defined $ttl) {
    help();
    osh_exit 'ERR_MISSING_PARAMETER', "The use of 'grace' requires to specify the --ttl parameter as well";
}

if (defined $ttl) {
    $fnret = OVH::Bastion::is_valid_ttl(ttl => $ttl);
    $fnret or osh_exit $fnret;
    $ttl = $fnret->value->{'seconds'};
}

my @command;

osh_info "Changing account configuration...";

@command = qw{ sudo -n -u allowkeeper -- /usr/bin/env perl -T };
push @command, $OVH::Bastion::BASEPATH . '/bin/helper/osh-accountPIV';
push @command, '--step',    '1';
push @command, '--account', $account;
push @command, '--policy',  $policy;
push @command, '--ttl',     $ttl if defined $ttl;

$fnret = OVH::Bastion::helper(cmd => \@command);
$fnret or osh_exit $fnret;
osh_info $fnret->msg;

osh_info "Applying change to keys...";

@command = qw{ sudo -n -u };
push @command, $account;
push @command, qw{ -- /usr/bin/env perl -T };
push @command, $OVH::Bastion::BASEPATH . '/bin/helper/osh-accountPIV';
push @command, '--step',    '2';
push @command, '--account', $account;
push @command, '--policy',  $policy;
push @command, '--ttl',     $ttl if defined $ttl;

$fnret = OVH::Bastion::helper(cmd => \@command);
osh_exit $fnret;
