mirror of
https://github.com/ovh/the-bastion.git
synced 2025-01-09 08:47:50 +08:00
2c2f723bbb
To avoid having e.g. a group creation interrupted in the middle just because the caller killed their ssh connection while we're still working
128 lines
4.6 KiB
Perl
Executable file
128 lines
4.6 KiB
Perl
Executable file
#! /usr/bin/perl -T
|
|
# vim: set filetype=perl ts=4 sw=4 sts=4 et:
|
|
# NEEDGROUP osh-selfAddPersonalAccess
|
|
# SUDOERS %osh-selfAddPersonalAccess ALL=(allowkeeper) NOPASSWD:/usr/bin/env perl -T /opt/bastion/bin/helper/osh-accountModifyPersonalAccess --target self --action add *
|
|
# FILEMODE 0750
|
|
# FILEOWN 0 allowkeeper
|
|
#
|
|
# NEEDGROUP osh-accountAddPersonalAccess
|
|
# SUDOERS %osh-accountAddPersonalAccess ALL=(allowkeeper) NOPASSWD:/usr/bin/env perl -T /opt/bastion/bin/helper/osh-accountModifyPersonalAccess --target any --action add *
|
|
# FILEMODE 0750
|
|
# FILEOWN 0 allowkeeper
|
|
#
|
|
# NEEDGROUP osh-selfDelPersonalAccess
|
|
# SUDOERS %osh-selfDelPersonalAccess ALL=(allowkeeper) NOPASSWD:/usr/bin/env perl -T /opt/bastion/bin/helper/osh-accountModifyPersonalAccess --target self --action del *
|
|
# FILEMODE 0750
|
|
# FILEOWN 0 allowkeeper
|
|
#
|
|
# NEEDGROUP osh-accountDelPersonalAccess
|
|
# SUDOERS %osh-accountDelPersonalAccess ALL=(allowkeeper) NOPASSWD:/usr/bin/env perl -T /opt/bastion/bin/helper/osh-accountModifyPersonalAccess --target any --action del *
|
|
# FILEMODE 0750
|
|
# FILEOWN 0 allowkeeper
|
|
|
|
#>HEADER
|
|
use common::sense;
|
|
use Getopt::Long;
|
|
|
|
use File::Basename;
|
|
use lib dirname(__FILE__) . '/../../lib/perl';
|
|
use OVH::Bastion;
|
|
local $| = 1;
|
|
|
|
#
|
|
# Globals
|
|
#
|
|
$SIG{'HUP'} = 'IGNORE'; # continue even when attached terminal is closed (we're called with setsid on supported systems anyway)
|
|
$SIG{'PIPE'} = 'IGNORE'; # continue even if osh_info gets a SIGPIPE because there's no longer a terminal
|
|
$ENV{'PATH'} = '/sbin:/bin:/usr/sbin:/usr/bin:/usr/local/sbin:/usr/local/bin:/usr/pkg/bin';
|
|
my ($self) = $ENV{'SUDO_USER'} =~ m{^([a-zA-Z0-9._-]+)$};
|
|
if (not defined $self) {
|
|
if ($< == 0) {
|
|
$self = 'root';
|
|
}
|
|
else {
|
|
HEXIT('ERR_SUDO_NEEDED', msg => 'This command must be run under sudo');
|
|
}
|
|
}
|
|
|
|
# Fetch command options
|
|
my $fnret;
|
|
my ($result, @optwarns);
|
|
my ($account, $ip, $user, $port, $action, $ttl, $forceKey, $forcePassword, $target, $comment);
|
|
eval {
|
|
local $SIG{__WARN__} = sub { push @optwarns, shift };
|
|
$result = GetOptions(
|
|
"account=s" => sub { $account //= $_[1] },
|
|
"ip=s" => sub { $ip //= $_[1] },
|
|
"user=s" => sub { $user //= $_[1] },
|
|
"port=i" => sub { $port //= $_[1] },
|
|
"action=s" => sub { $action //= $_[1] },
|
|
"ttl=i" => sub { $ttl //= $_[1] },
|
|
"force-key=s" => sub { $forceKey //= $_[1] },
|
|
"force-password=s" => sub { $forcePassword //= $_[1] },
|
|
"target=s" => sub { $target //= $_[1] },
|
|
"comment=s" => sub { $comment //= $_[1] },
|
|
);
|
|
};
|
|
if ($@) { die $@ }
|
|
|
|
if (!$result) {
|
|
local $" = ", ";
|
|
HEXIT('ERR_BAD_OPTIONS', msg => "Error parsing options: @optwarns");
|
|
}
|
|
|
|
if (not $action or not $ip or not $account or not $target) {
|
|
HEXIT('ERR_MISSING_PARAMETER', msg => "Missing argument 'action' or 'ip' or 'account' or 'target'");
|
|
}
|
|
|
|
#<HEADER
|
|
|
|
not defined $account and $account = $self;
|
|
|
|
#>RIGHTSCHECK
|
|
if ($target eq 'self' && $self ne $account) {
|
|
HEXIT('ERR_SECURITY_VIOLATION', msg => "Attempted to modify another account while you're only allowed to do it on yourself");
|
|
}
|
|
|
|
#<RIGHTSCHECK
|
|
|
|
#>PARAMS:ACTION
|
|
if (not grep { $action eq $_ } qw{ add del }) {
|
|
return R('ERR_INVALID_PARAMETER', msg => "expected 'add' or 'del' as an action");
|
|
}
|
|
|
|
#<PARAMS:ACTION
|
|
|
|
#>CODE
|
|
my $machine = $ip;
|
|
$port and $machine .= ":$port";
|
|
$user and $machine = $user . '@' . $machine;
|
|
|
|
# access_modify validates all its parameters, don't do it ourselves here for clarity
|
|
$fnret = OVH::Bastion::access_modify(
|
|
way => 'personal',
|
|
account => $account,
|
|
action => $action,
|
|
user => $user,
|
|
ip => $ip,
|
|
port => $port,
|
|
ttl => $ttl,
|
|
forceKey => $forceKey,
|
|
forcePassword => $forcePassword,
|
|
comment => $comment,
|
|
);
|
|
if ($fnret->err eq 'OK') {
|
|
my $ttlmsg = $ttl ? ' (expires in ' . OVH::Bastion::duration2human(seconds => $ttl)->value->{'human'} . ')' : '';
|
|
HEXIT(
|
|
'OK',
|
|
value => {action => $action, account => $account, ip => $ip, user => $user, port => $port, ttl => $ttl, comment => $comment},
|
|
msg => $action eq 'add' ? "Access to $machine was added to account $account$ttlmsg" : "Access to $machine was removed from account $account$ttlmsg"
|
|
);
|
|
}
|
|
elsif ($fnret->err eq 'OK_NO_CHANGE') {
|
|
HEXIT('OK_NO_CHANGE',
|
|
msg => $action eq 'add'
|
|
? "Access to $machine was already granted to account $account, nothing done"
|
|
: "Access to $machine was not granted to account $account, nothing done");
|
|
}
|
|
HEXIT($fnret);
|