2020-10-16 00:32:37 +08:00
|
|
|
#! /usr/bin/env perl
|
|
|
|
# vim: set filetype=perl ts=4 sw=4 sts=4 et:
|
|
|
|
use common::sense;
|
|
|
|
use Term::ANSIColor;
|
|
|
|
|
|
|
|
use File::Basename;
|
|
|
|
use lib dirname(__FILE__) . '/../../../lib/perl';
|
|
|
|
use OVH::Result;
|
|
|
|
use OVH::Bastion;
|
|
|
|
use OVH::Bastion::Plugin qw( :DEFAULT help );
|
|
|
|
|
|
|
|
my $remainingOptions = OVH::Bastion::Plugin::begin(
|
|
|
|
argv => \@ARGV,
|
|
|
|
header => "OSH help",
|
|
|
|
options => {},
|
|
|
|
helptext => <<'EOF',
|
|
|
|
I'm So Meta, Even This Acronym
|
|
|
|
|
|
|
|
Usage: --osh SCRIPT_NAME
|
|
|
|
EOF
|
|
|
|
);
|
|
|
|
|
|
|
|
#
|
|
|
|
# code
|
|
|
|
#
|
|
|
|
my $fnret;
|
|
|
|
|
|
|
|
my @knownPlugins = (
|
|
|
|
'MANAGE YOUR ACCOUNT' => [
|
|
|
|
'manage your ingress credentials (you->bastion)' => [
|
|
|
|
qw{ selfListIngressKeys selfResetIngressKeys selfAddIngressKey selfDelIngressKey
|
|
|
|
selfGenerateProxyPassword selfMFASetupPassword selfMFAResetPassword selfMFASetupTOTP selfMFAResetTOTP }
|
|
|
|
],
|
|
|
|
'manage your egress credentials (bastion->server)' => [qw{ selfListEgressKeys selfGenerateEgressKey selfDelEgressKey selfGeneratePassword selfListPasswords }],
|
|
|
|
'manage your accesses to servers' => [qw{ selfListAccesses selfAddPersonalAccess selfDelPersonalAccess selfForgetHostKey }],
|
|
|
|
'manage your current sessions' => [qw{ lock unlock }],
|
|
|
|
'review past sessions' => [qw{ selfListSessions selfPlaySession }],
|
|
|
|
'other commands' => [qw{ selfModify }],
|
|
|
|
],
|
|
|
|
'MANAGE OTHER ACCOUNTS' => [
|
|
|
|
'manage bastion accounts' => [qw{ accountList accountCreate accountCreateOvh accountDelete accountUnexpire accountModify accountPIV }],
|
|
|
|
'manage accounts ingress credentials (them->bastion)' => [qw{ accountListIngressKeys accountResetIngressKeys accountMFAResetPassword accountMFAResetTOTP }],
|
|
|
|
'manage accounts egress credentials (bastion->server)' => [qw{ accountListEgressKeys accountGeneratePassword accountListPasswords }],
|
|
|
|
'manage access to restricted commands' => [qw{ accountGrantCommand accountRevokeCommand accountInfo }],
|
|
|
|
'manage another account accesses to servers' => [qw{ accountListAccesses accountAddPersonalAccess accountDelPersonalAccess whoHasAccessTo }],
|
|
|
|
'review past sessions' => [qw{ accountListSessions globalListSessions }],
|
|
|
|
],
|
|
|
|
'MANAGE GROUPS' => [
|
|
|
|
'information and lifecycle' => [qw{ groupInfo groupListServers groupList groupCreate groupDelete }],
|
|
|
|
'group owner commands' => [
|
|
|
|
qw{ groupAddGatekeeper groupDelGatekeeper groupAddAclkeeper groupDelAclkeeper
|
2021-04-14 16:40:29 +08:00
|
|
|
groupAddOwner groupDelOwner groupTransmitOwnership groupGenerateEgressKey groupDelEgressKey groupModify }
|
2020-10-16 00:32:37 +08:00
|
|
|
],
|
|
|
|
'egress passwords commands' => [qw{ groupListPasswords groupGeneratePassword groupDelPassword }],
|
2021-06-16 23:15:57 +08:00
|
|
|
'gatekeeper commands to manage members' => [qw{ groupAddMember groupDelMember }],
|
2020-10-16 00:32:37 +08:00
|
|
|
'gatekeeper commands to manage guests' => [qw{ groupListGuestAccesses groupAddGuestAccess groupDelGuestAccess }],
|
|
|
|
'aclkeeper commands to manage group servers' => [qw{ groupAddServer groupDelServer }],
|
|
|
|
],
|
|
|
|
'BASTION ADMIN' => [
|
|
|
|
'other commands' => [qw{ adminSudo adminMaintenance }],
|
|
|
|
],
|
|
|
|
'MISC COMMANDS' => [
|
|
|
|
'basic commands' => [qw{ help info }],
|
|
|
|
'utility commands' => [qw{ nc ping mtr alive clush scp batch }],
|
|
|
|
'realm commands' => [qw{ realmList realmInfo realmCreate realmDelete }],
|
|
|
|
'audit commands' => [qw{ rootListIngressKeys }],
|
|
|
|
'other specific commands',
|
|
|
|
],
|
|
|
|
);
|
|
|
|
|
|
|
|
my %colorpanel = (
|
|
|
|
'open' => 'green',
|
|
|
|
'restricted' => 'cyan',
|
|
|
|
'group-aclkeeper' => 'yellow',
|
|
|
|
'group-gatekeeper' => 'yellow',
|
|
|
|
'group-owner' => 'magenta',
|
|
|
|
'admin' => 'red',
|
|
|
|
);
|
|
|
|
|
|
|
|
# create a hash with all the plugins listed above
|
|
|
|
my %alreadySeenPlugins;
|
|
|
|
my $i = 1;
|
|
|
|
while ($i < scalar @knownPlugins) {
|
|
|
|
my $j = 1;
|
|
|
|
while ($j < scalar @{$knownPlugins[$i]}) {
|
|
|
|
foreach (@{$knownPlugins[$i]->[$j]}) {
|
|
|
|
$alreadySeenPlugins{$_} = 1;
|
|
|
|
}
|
|
|
|
$j += 2;
|
|
|
|
}
|
|
|
|
$i += 2;
|
|
|
|
}
|
|
|
|
|
|
|
|
# then get the real list of this bastion
|
|
|
|
$fnret = OVH::Bastion::get_plugin_list();
|
|
|
|
$fnret or osh_exit $fnret;
|
|
|
|
|
|
|
|
# and add plugins not listed above to the 'other specific commands' section
|
|
|
|
my @otherPlugins;
|
|
|
|
foreach my $plugin (sort keys %{$fnret->value}) {
|
|
|
|
next if exists $alreadySeenPlugins{$plugin};
|
|
|
|
osh_debug("an unknown but valid command $plugin in " . $fnret->value->{$plugin}{'dir'});
|
|
|
|
push @otherPlugins, $plugin;
|
|
|
|
}
|
|
|
|
$knownPlugins[-1][scalar(@{$knownPlugins[-1]})] = \@otherPlugins;
|
|
|
|
|
|
|
|
$i = 0;
|
|
|
|
while ($i < scalar @knownPlugins) {
|
|
|
|
my $mainCategoryName = $knownPlugins[$i++];
|
|
|
|
my $mainCategoryArray = $knownPlugins[$i++];
|
|
|
|
my $mainCategoryNamePrinted = 0;
|
|
|
|
my $j = 0;
|
|
|
|
while ($j < scalar @$mainCategoryArray) {
|
|
|
|
my $subCategoryName = $mainCategoryArray->[$j++];
|
|
|
|
my @plugins = @{$mainCategoryArray->[$j++]};
|
|
|
|
|
|
|
|
osh_debug("working on cat [$mainCategoryName // $subCategoryName] with " . (scalar @plugins) . " commands");
|
|
|
|
osh_debug("plugins are: " . join('/', @plugins));
|
|
|
|
|
|
|
|
my @availableCommands;
|
|
|
|
my $curLen;
|
|
|
|
my $curIndex;
|
|
|
|
foreach my $cmd (@plugins) {
|
|
|
|
$fnret = OVH::Bastion::can_account_execute_plugin(account => $self, plugin => $cmd);
|
|
|
|
next unless $fnret;
|
|
|
|
if (($curLen + length($fnret->value->{'plugin'})) > 80) {
|
|
|
|
$curIndex++;
|
|
|
|
$curLen = 0;
|
|
|
|
}
|
|
|
|
$curLen += length($fnret->value->{'plugin'});
|
|
|
|
push @{$availableCommands[$curIndex]}, colored($fnret->value->{'plugin'}, $colorpanel{$fnret->value->{'type'}});
|
|
|
|
}
|
|
|
|
if (@availableCommands) {
|
|
|
|
if (not $mainCategoryNamePrinted) {
|
|
|
|
osh_info " > $mainCategoryName";
|
|
|
|
$mainCategoryNamePrinted = 1;
|
|
|
|
}
|
|
|
|
osh_info " - $subCategoryName:";
|
|
|
|
osh_info " " . join(' ', @$_) for @availableCommands;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
osh_info ' ';
|
|
|
|
}
|
|
|
|
|
|
|
|
osh_info "\nUse --help to get extra help when entering a command";
|
|
|
|
my $bastionName = OVH::Bastion::config('bastionName');
|
|
|
|
if ($bastionName) {
|
|
|
|
$bastionName = $bastionName->value;
|
|
|
|
osh_info "i.e. $bastionName --osh info --help";
|
|
|
|
}
|
|
|
|
my $docURL = OVH::Bastion::config('documentationURL');
|
|
|
|
if ($docURL && $docURL->value) {
|
|
|
|
osh_info "Documentation: " . $docURL->value;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (OVH::Bastion::config('readOnlySlaveMode')->value) {
|
|
|
|
osh_warn "\nNOTICE: This bastion is part of a cluster, and this instance is a read-only one (slave), "
|
|
|
|
. "so only read-only compliant commands are available. If you need to use write/modify commands, "
|
|
|
|
. "please do it on the master of the cluster instead.";
|
|
|
|
}
|
|
|
|
|
|
|
|
osh_ok;
|