the-bastion/bin/cron/osh-cleanup-guest-key-access.pl
2022-07-12 10:07:16 +02:00

167 lines
5.4 KiB
Perl
Executable file

#! /usr/bin/env perl
# vim: set filetype=perl ts=4 sw=4 sts=4 et:
use common::sense;
use Getopt::Long;
use File::Basename;
use lib dirname(__FILE__) . '/../../lib/perl';
use OVH::Bastion;
use OVH::Result;
use OVH::SimpleLog;
# this'll be used in syslog
$ENV{'UNIQID'} = OVH::Bastion::generate_uniq_id()->value;
my $fnret;
# abort early if we're not a master instance
if (OVH::Bastion::config('readOnlySlaveMode')->value) {
_log "We're not a master instance, don't do anything";
exit 0;
}
$fnret = OVH::Bastion::load_configuration_file(
file => OVH::Bastion::main_configuration_directory() . "/osh-cleanup-guest-key-access.conf",
secure => 1,
);
my $config;
if (!$fnret) {
if (-e OVH::Bastion::main_configuration_directory() . "/osh-cleanup-guest-key-access.conf") {
_warn "Error while loading configuration, continuing anyway with default values...";
}
else {
_log "No configuration file found, using default config values...";
}
}
else {
$config = $fnret->value;
if (ref $config ne 'HASH') {
_warn "Invalid data returned while loading configuration, continuing anyway with default values...";
}
}
# set default values
$config = {} if ref $config ne 'HASH';
$config->{'syslog_facility'} //= ($config->{'SyslogFacility'} // 'local6');
$config->{'enabled'} //= ($config->{'Enabled'} // 1);
# logging
if ($config->{'syslog_facility'}) {
OVH::SimpleLog::setSyslog($config->{'syslog_facility'});
}
if (!$config->{'enabled'}) {
_log "Script is disabled.";
exit 0;
}
# command-line
sub print_usage {
print <<"EOF";
$0 [options]
--dry-run Don't actually do anything, just report what would be done
--verbose More detailed logging
EOF
return 1;
}
my ($dryRun, $verbose);
{
my $optwarn = 'Unknown error';
local $SIG{'__WARN__'} = sub { $optwarn = shift; };
if (
!GetOptions(
"dry-run" => \$dryRun,
"verbose+" => \$verbose,
)
)
{
_err "Error while parsing command-line options: $optwarn";
print_usage();
exit 1;
}
}
_log "Looking for group guests that no longer have any access to any server of the group...";
$fnret = OVH::Bastion::get_group_list(groupType => "key");
if (!$fnret) {
_err "Couldn't get group list:" . $fnret->msg;
exit 1;
}
my $groups = $fnret->value;
foreach my $shortGroup (sort keys %$groups) {
foreach my $account (@{$groups->{$shortGroup}{'members'}}) {
next if ($account eq 'allowkeeper'); # don't need to check this special user
_log "<$shortGroup/$account> checking if group guest..." if $verbose;
# rule out realm accounts, we would need to check every remote account's info
next if ($account =~ /^realm_/);
# the "members" of the system group key$shortGroup might be either members or guests,
# so we first rule out members
next if OVH::Bastion::is_group_member(account => $account, group => $shortGroup, cache => 1);
# it seems to be a guest, double-check that
next if !OVH::Bastion::is_group_guest(account => $account, group => $shortGroup, cache => 1);
_log "<$shortGroup/$account> found a guest, checking remaining accesses..." if $verbose;
# okay, any access remaining?
$fnret = OVH::Bastion::get_acl_way(way => 'groupguest', group => $shortGroup, account => $account);
if (!$fnret) {
_warn "<$shortGroup/$account> Error getting guest accesses ($fnret), skipping";
next;
}
elsif ($fnret->err eq 'OK') {
_log "<$shortGroup/$account> The account still has "
. (@{$fnret->value})
. " accesses to the group, skipping"
if $verbose;
next;
}
elsif ($fnret->err eq 'OK_EMPTY' && !@{$fnret->value}) {
# this is a guest, but no ACL remains (probably the last one had a TTL),
# so we'll cleanup this guest
if ($dryRun) {
_log
"<$shortGroup/$account> The account is a guest of group but has no remaining access, would have cleaned up in non-dry-run mode";
next;
}
_log "<$shortGroup/$account> The account is a guest of group but has no remaining access, cleaning up...";
# get $group from $shortGroup
$fnret = OVH::Bastion::is_valid_group_and_existing(group => $shortGroup, groupType => 'key', cache => 1);
if (!$fnret) {
_warn "<$shortGroup/$account> Group seems invalid ($fnret), skipping";
next;
}
my $group = $fnret->value->{'group'};
# remove account from group
my @command = qw{ /usr/bin/env perl -T };
push @command, $OVH::Bastion::BASEPATH . '/bin/helper/osh-groupSetRole';
push @command, '--type', 'guest';
push @command, '--group', $group;
push @command, '--account', $account;
push @command, '--action', 'del';
$fnret = OVH::Bastion::helper(cmd => \@command);
if (!$fnret) {
_err "<$shortGroup/$account> Failed to revoke key access: $fnret";
}
else {
_log "<$shortGroup/$account> Key access revoked";
}
}
}
}
_log "Done, got " . (OVH::SimpleLog::nb_errors()) . " error(s) and " . (OVH::SimpleLog::nb_warnings()) . " warning(s).";