-
Notifications
You must be signed in to change notification settings - Fork 89
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
5 changed files
with
249 additions
and
2 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,119 @@ | ||
#! /usr/bin/perl -T | ||
# vim: set filetype=perl ts=4 sw=4 sts=4 et: | ||
# NEEDGROUP osh-assetForgetHostKey | ||
# SUDOERS %osh-assetForgetHostKey ALL=(root) NOPASSWD:/usr/bin/env perl -T /opt/bastion/bin/helper/osh-assetForgetHostKey * | ||
# FILEMODE 0700 | ||
# FILEOWN 0 0 | ||
|
||
#>HEADER | ||
use common::sense; | ||
use Getopt::Long qw(:config no_auto_abbrev no_ignore_case); | ||
use Net::IP; | ||
use DateTime; | ||
|
||
use File::Basename; | ||
use lib dirname(__FILE__) . '/../../lib/perl'; | ||
use OVH::Result; | ||
use OVH::Bastion; | ||
use OVH::Bastion::Helper; | ||
|
||
# Fetch command options | ||
my $fnret; | ||
my ($result, @optwarns); | ||
my ($ip, $port); | ||
eval { | ||
local $SIG{__WARN__} = sub { push @optwarns, shift }; | ||
$result = GetOptions( | ||
"ip=s" => sub { $ip //= $_[1] }, | ||
"port=i" => sub { $port //= $_[1] }, | ||
); | ||
}; | ||
if ($@) { die $@ } | ||
|
||
if (!$result) { | ||
local $" = ", "; | ||
HEXIT('ERR_BAD_OPTIONS', msg => "Error parsing options: @optwarns"); | ||
} | ||
|
||
OVH::Bastion::Helper::check_spurious_args(); | ||
|
||
if (not $ip or not $port) { | ||
HEXIT('ERR_MISSING_PARAMETER', msg => "Missing argument 'ip' or 'port'"); | ||
} | ||
|
||
#<HEADER | ||
|
||
#>CODE | ||
|
||
# Build the regex we'll be looking for. | ||
my $re; | ||
if ($port == 22) { | ||
# format is "IP ssh-..." | ||
$re = qr/^\Q$ip ssh-\E/m; | ||
} | ||
else { | ||
# format is "[IP]:port ssh-..." | ||
$re = qr/^\Q[$ip]:$port ssh-\E/m; | ||
} | ||
|
||
# First, get all bastion accounts, including realm sysaccounts | ||
$fnret = OVH::Bastion::get_account_list(); | ||
$fnret or HEXIT($fnret); | ||
my %accounts = %{$fnret->value || {}}; | ||
|
||
$fnret = OVH::Bastion::get_realm_list(); | ||
$fnret or HEXIT($fnret); | ||
foreach my $realmName (keys %{$fnret->value || {}}) { | ||
$accounts{$fnret->value->{$realmName}{'sysaccount'}} = $fnret->value->{$realmName}; | ||
} | ||
|
||
my $nbchanges = 0; | ||
my $now = DateTime->now()->iso8601() . 'Z'; | ||
foreach my $name (keys %accounts) { | ||
my $accountHome = $accounts{$name}{'home'}; | ||
if (!-d $accountHome) { | ||
warn_syslog("Account '$name' home '$accountHome' doesn't exist"); | ||
next; | ||
} | ||
|
||
my $knownHosts = "$accountHome/.ssh/known_hosts"; | ||
if (!-e -f $knownHosts) { | ||
# This can happen if the account has never been used yet | ||
next; | ||
} | ||
|
||
# now, slurp the file and look for the host we're being asked about | ||
if (open(my $fh, '<', $knownHosts)) { | ||
my $contents = do { | ||
local $/; | ||
<$fh>; | ||
}; | ||
close($fh); | ||
#my $nbfound = grep { $_ =~ $re } split(/\n/, $contents || ''); | ||
my $nbmatches = $contents =~ s/$re/# removed by $self at $now in session with uniqid $ENV{'UNIQID'}: $&/g; | ||
# remove found lines if any | ||
if ($nbmatches) { | ||
osh_info("Removing $nbmatches lines from ${name}'s known_hosts file"); | ||
if (open($fh, '>', $knownHosts)) { | ||
print $fh $contents; | ||
close($fh); | ||
$nbchanges++; | ||
} | ||
else { | ||
osh_warn("Couldn't adjust ${name}'s known_hosts file"); | ||
warn_syslog("Error while opening $knownHosts file for write: $!"); | ||
} | ||
} | ||
} | ||
else { | ||
warn_syslog("Couldn't open '$knownHosts': $!"); | ||
} | ||
} | ||
|
||
HEXIT( | ||
R( | ||
$nbchanges ? 'OK' : 'OK_NO_CHANGE', | ||
msg => "Finally modified $nbchanges known_hosts accounts' files", | ||
value => {changed_files => $nbchanges} | ||
) | ||
); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,43 @@ | ||
#! /usr/bin/env perl | ||
# vim: set filetype=perl ts=4 sw=4 sts=4 et: | ||
use common::sense; | ||
|
||
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 => "remove the host key of a given asset from all accounts' known hosts", | ||
options => {}, | ||
helptext => <<'EOF', | ||
Remove the host key of a given asset from all accounts' known hosts | ||
Usage: --osh SCRIPT_NAME --host <HOST|IP> [--port <PORT>] | ||
--host HOST|IP Asset whose host key should be removed | ||
--port PORT Asset port serving SSH (default: 22) | ||
EOF | ||
); | ||
|
||
if (!$ip) { | ||
help(); | ||
osh_exit 'ERR_MISSING_PARAMETER', "Missing mandatory parameter --host (or host didn't resolve correctly)"; | ||
} | ||
|
||
# IP can't be a prefix | ||
if ($ip =~ m{/}) { | ||
help(); | ||
osh_exit 'ERR_INVALID_PARAMETER', "Specified IP must not be a prefix ($ip)"; | ||
} | ||
|
||
osh_info "Removing $ip host key from accounts..."; | ||
|
||
my @command = qw{ sudo -n -u root -- /usr/bin/env perl -T }; | ||
push @command, $OVH::Bastion::BASEPATH . '/bin/helper/osh-assetForgetHostKey'; | ||
push @command, '--ip', $ip; | ||
push @command, '--port', ($port ? $port : 22); | ||
|
||
osh_exit OVH::Bastion::helper(cmd => \@command); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
# to modify all accounts' known_hosts we need to be root | ||
%osh-assetForgetHostKey ALL=(root) NOPASSWD:/usr/bin/env perl -T /opt/bastion/bin/helper/osh-assetForgetHostKey * |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,73 @@ | ||
# vim: set filetype=sh ts=4 sw=4 sts=4 et: | ||
# shellcheck shell=bash | ||
# shellcheck disable=SC2086,SC2016,SC2046 | ||
# below: convoluted way that forces shellcheck to source our caller | ||
# shellcheck source=tests/functional/launch_tests_on_instance.sh | ||
. "$(dirname "${BASH_SOURCE[0]}")"/dummy | ||
|
||
testsuite_assetforgethostkey() | ||
{ | ||
# create a1 and a2 | ||
grant accountCreate | ||
|
||
success create_account1 $a0 --osh accountCreate --account $account1 --uid $uid1 --public-key \""$(cat $account1key1file.pub)"\" | ||
json .error_code OK .command accountCreate .value null | ||
|
||
success create_account2 $a0 --osh accountCreate --account $account2 --uid $uid2 --public-key \""$(cat $account2key1file.pub)"\" | ||
json .error_code OK .command accountCreate .value null | ||
|
||
revoke accountCreate | ||
|
||
# grant personal accesses to these accounts | ||
grant accountAddPersonalAccess | ||
|
||
success a0_allow_a1_localhost $a0 --osh accountAddPersonalAccess --account $account1 --host 127.0.0.0/24 --port '*' --user '*' | ||
json .error_code OK .command accountAddPersonalAccess | ||
|
||
success a0_allow_a2_localhost $a0 --osh accountAddPersonalAccess --account $account2 --host 127.0.0.0/24 --port '*' --user '*' | ||
json .error_code OK .command accountAddPersonalAccess | ||
|
||
revoke accountAddPersonalAccess | ||
|
||
# connect to localhost from these accounts (it won't work in the end but their known_hosts files will be updated and that's what we need) | ||
run a1_connect_localhost1 $a1 [email protected] | ||
contain "Connecting..." | ||
|
||
run a2_connect_localhost1_226 $a2 [email protected] -p 226 | ||
contain "Connecting..." | ||
|
||
run a2_connect_localhost1 $a2 [email protected] | ||
contain "Connecting..." | ||
|
||
run a2_connect_localhost2 $a2 [email protected] | ||
contain "Connecting..." | ||
|
||
grant assetForgetHostKey | ||
|
||
# now, delete the host keys for 127.0.0.1 | ||
success a0_asset_forgethostkey $a0 --osh assetForgetHostKey --host 127.0.0.1 | ||
json .error_code OK .command assetForgetHostKey .value.changed_files 2 | ||
|
||
success a0_asset_forgethostkey_dupe $a0 --osh assetForgetHostKey --host 127.0.0.1 | ||
json .error_code OK_NO_CHANGE .command assetForgetHostKey .value.changed_files 0 | ||
|
||
# same but with port 226 | ||
success a0_asset_forgethostkey_226 $a0 --osh assetForgetHostKey --host 127.0.0.1 --port 226 | ||
json .error_code OK .command assetForgetHostKey .value.changed_files 1 | ||
|
||
success a0_asset_forgethostkey_226_dupe $a0 --osh assetForgetHostKey --host 127.0.0.1 --port 226 | ||
json .error_code OK_NO_CHANGE .command assetForgetHostKey .value.changed_files 0 | ||
|
||
revoke assetForgetHostKey | ||
|
||
# delete those accounts | ||
grant accountDelete | ||
|
||
success account1_cleanup $a0 --osh accountDelete --account $account1 --no-confirm | ||
success account2_cleanup $a0 --osh accountDelete --account $account2 --no-confirm | ||
|
||
revoke accountDelete | ||
} | ||
|
||
testsuite_assetforgethostkey | ||
unset -f testsuite_assetforgethostkey |