#! /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 );
use OVH::Bastion::Plugin::groupSetRole;
use OVH::Bastion::Plugin::ACL;

my $remainingOptions = OVH::Bastion::Plugin::begin(
    argv               => \@ARGV,
    header             => "add access to one server of a group to an account",
    userAllowWildcards => 1,
    options            => {
        "group=s"    => \my $group,
        "protocol=s" => \my $protocol,
        "account=s"  => \my $account,
        "ttl=s"      => \my $ttl,
        "comment=s"  => \my $comment,
        # undocumented/compatibility:
        "user-any" => \my $userAny,
        "port-any" => \my $portAny,
        "scpup"    => \my $scpUp,
        "scpdown"  => \my $scpDown,
        "sftp"     => \my $sftp,
    },
    helptext => <<'EOF',
Add a specific group server access to an account

Usage: --osh SCRIPT_NAME --group GROUP --account ACCOUNT [OPTIONS]

  --account ACCOUNT        Name of the other bastion account to add access to, they'll be given access to the GROUP key
  --group GROUP            Group to add the guest access to, note that this group should already have access
                             to the USER/HOST/PORT tuple you'll specify with the options below.
  --host HOST|IP|SUBNET    Host(s) to add access to, either a HOST which will be resolved to an IP immediately,
                             or an IP, or a whole subnet using the PREFIX/SIZE notation
  --user USER|PATTERN|*    Specify which remote user should be allowed to connect as.
                             Globbing characters '*' and '?' are supported, so you can specify a pattern
                             that will be matched against the actual remote user name.
                             To allow any user, use '--user *' (you might need to escape '*' from your shell)
  --port PORT|*            Remote port allowed to connect to
                             To allow any port, use '--port *' (you might need to escape '*' from your shell)
  --protocol PROTO         Specify that a special protocol should be allowed for this HOST:PORT tuple, note that you
                              must not specify --user in that case. However, for this protocol to be usable under a given
                              remote user, access to the USER@HOST:PORT tuple must also be allowed.
                              PROTO must be one of:
                              scpupload    allow SCP upload, you--bastion-->server
                              scpdownload  allow SCP download, you<--bastion--server
                              sftp         allow usage of the SFTP subsystem, through the bastion
                              rsync        allow usage of rsync, through the bastion
  --ttl SECONDS|DURATION  Specify a number of seconds after which the access will automatically expire
  --comment '"ANY TEXT"'  Add a comment alongside this access. Quote it twice as shown if you're under a shell.
                            If omitted, we'll use the closest preexisting group access' comment as seen in groupListServers

This command adds, to an existing bastion account, access to the egress keys of a group,
but only to accessing one or several given servers, instead of all the servers of this group.

If you want to add complete access to an account to all the present and future servers
of the group, using the group key, please use ``groupAddMember`` instead.

If you want to add access to an account to a group server but using his personal bastion
key instead of the group key, please use ``accountAddPersonalAccess`` instead (his public key
must be on the remote server).

This command is the opposite of ``groupDelGuestAccess``.
EOF
);

my $fnret;

if (not $ip and $host) {
    osh_exit 'ERR_INVALID_HOST',
      "Specified host ($host) didn't resolve correctly, fix your DNS or specify the IP instead";
}

$fnret = OVH::Bastion::Plugin::ACL::check(
    user     => $user,
    userAny  => $userAny,
    port     => $port,
    portAny  => $portAny,
    scpUp    => $scpUp,
    scpDown  => $scpDown,
    sftp     => $sftp,
    protocol => $protocol,
);
if (!$fnret) {
    help();
    osh_exit($fnret);
}
$user = $fnret->value->{'user'};
$port = $fnret->value->{'port'};

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

# act() will also call preconditions() which will check all the params
$fnret = OVH::Bastion::Plugin::groupSetRole::act(
    account        => $account,
    group          => $group,
    action         => 'add',
    type           => 'guest',
    user           => $user,
    port           => $port,
    host           => ($ip || $host),
    ttl            => $ttl,
    comment        => $comment,
    sudo           => 0,
    silentoverride => 0,
    self           => $self,
    scriptName     => $scriptName,
    savedArgs      => $savedArgs
);
help() if not $fnret;
osh_exit($fnret);
