mirror of
https://github.com/ovh/the-bastion.git
synced 2025-02-27 00:54:26 +08:00
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
103 lines
2.9 KiB
Perl
Executable file
103 lines
2.9 KiB
Perl
Executable file
#! /usr/bin/perl -T
|
|
# vim: set filetype=perl ts=4 sw=4 sts=4 et:
|
|
# NEEDGROUP osh-accountListIngressKeys
|
|
# SUDOERS %osh-accountListIngressKeys ALL=(keyreader) NOPASSWD:/usr/bin/env perl -T /opt/bastion/bin/helper/osh-accountListIngressKeys *
|
|
# FILEMODE 0750
|
|
# FILEOWN 0 keyreader
|
|
|
|
#>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, $allfiles);
|
|
eval {
|
|
local $SIG{__WARN__} = sub { push @optwarns, shift };
|
|
$result = GetOptions(
|
|
"account=s" => sub { $account //= $_[1] },
|
|
"all-files" => sub { $allfiles //= $_[1] },
|
|
);
|
|
};
|
|
if ($@) { die $@ }
|
|
|
|
if (!$result) {
|
|
local $" = ", ";
|
|
HEXIT('ERR_BAD_OPTIONS', msg => "Error parsing options: @optwarns");
|
|
}
|
|
|
|
if (!$account) {
|
|
HEXIT('ERR_MISSING_PARAMETER', msg => "Missing argument 'account'");
|
|
}
|
|
|
|
#<HEADER
|
|
|
|
#>RIGHTSCHECK
|
|
if ($self eq 'root') {
|
|
osh_debug "Real root, skipping checks of permissions";
|
|
}
|
|
else {
|
|
# need to perform another security check
|
|
$fnret = OVH::Bastion::is_user_in_group(user => $self, group => ($account eq 'root' ? "osh-rootListIngressKeys" : "osh-accountListIngressKeys"));
|
|
if (!$fnret) {
|
|
HEXIT('ERR_SECURITY_VIOLATION', msg => "You're not allowed to run this, dear $self");
|
|
}
|
|
}
|
|
|
|
#<RIGHTSCHECK
|
|
|
|
#>PARAMS:ACCOUNT
|
|
osh_debug("Checking account");
|
|
my $accounthome;
|
|
if ($account ne 'root') {
|
|
$fnret = OVH::Bastion::is_bastion_account_valid_and_existing(account => $account);
|
|
$fnret or HEXIT($fnret);
|
|
$account = $fnret->value->{'account'}; # untainted
|
|
$accounthome = $fnret->value->{'dir'};
|
|
}
|
|
else {
|
|
$account = 'root';
|
|
$accounthome = '/root';
|
|
}
|
|
|
|
#<PARAMS:ACCOUNT
|
|
|
|
my @keys;
|
|
|
|
# by default, we only look in the authorized_keys file used by the bastion
|
|
my %files = ($accounthome . '/' . OVH::Bastion::AK_FILE => 1);
|
|
|
|
if ($allfiles) {
|
|
|
|
# if allfiles is requested, add all well-known potentially existing authorized_keys used by sshd
|
|
$files{"$accounthome/.ssh/authorized_keys"} = 1;
|
|
$files{"$accounthome/.ssh/authorized_keys2"} = 1;
|
|
}
|
|
|
|
foreach my $file (keys %files) {
|
|
$fnret = OVH::Bastion::get_authorized_keys_from_file(file => $file);
|
|
push @keys, @{$fnret->value} if ($fnret && $fnret->value);
|
|
}
|
|
HEXIT('OK', value => \@keys);
|