mirror of
https://github.com/ovh/the-bastion.git
synced 2025-01-06 15:31:56 +08:00
167 lines
5.4 KiB
Perl
Executable file
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).";
|