feat: replace --wait by a tcp-based connection try

This commit is contained in:
Stéphane Lesimple 2024-04-05 13:40:59 +00:00 committed by Stéphane Lesimple
parent dac0fedb89
commit a1efcec582
2 changed files with 36 additions and 37 deletions

View file

@ -371,7 +371,6 @@ my $remainingOptions;
"interactive|i" => \my $interactive,
"netconf" => \my $netconf,
"wait" => \my $wait,
"wait-port=i" => \my $wait_port,
"ssh-as=s" => \my $sshAs,
"use-key=s" => \my $useKey,
"kbd-interactive" => \my $userKbdInteractive,
@ -1488,39 +1487,27 @@ osh_debug("about to exec: " . join(' ', @ttyrec));
# if --wait is specified, we wait for the host to be alive before connecting
if ($wait) {
require IO::Socket::INET;
my $startedat = time();
osh_info "Pinging $host, will connect as soon as it's alive...";
while (1) {
my @pingcmd = qw{ fping -- };
push @pingcmd, $host;
my $fnretexec = OVH::Bastion::execute(cmd => \@pingcmd, noisy_stdout => 1, noisy_stderr => 1);
$fnretexec or exit(OVH::Bastion::EXIT_EXEC_FAILED);
if ($fnretexec->value->{'sysret'} == 0) {
my $loops = 0;
osh_info "Waiting for port $port to be open on $host before attempting to connect...";
while ($loops < 3600) { # can be up to 2h (socket timeout + sleep 1)
my $Sock = IO::Socket::INET->new(
Proto => 'tcp',
Timeout => 1,
PeerAddr => $ip,
PeerPort => $port,
);
if ($Sock) {
osh_info "Alive after waiting for " . (time() - $startedat) . " seconds, connecting...";
sleep 2 if (time() > $startedat + 1); # so that ssh has the time to startup... hopefully
$Sock->close();
last;
}
sleep 1;
}
}
# if --wait-port is specified, we wait for the host specific port to be open before connecting
if ($wait_port) {
my $startedat = time();
osh_info "Testing $host port $wait_port, will connect as soon as it's open...";
while (1) {
my @testportcmd = qw{ nc -w 1 -z -v -n };
push @testportcmd, $host, $wait_port;
my $fnretexec = OVH::Bastion::execute(cmd => \@testportcmd, noisy_stdout => 1, noisy_stderr => 1);
$fnretexec or exit(OVH::Bastion::EXIT_EXEC_FAILED);
if ($fnretexec->value->{'sysret'} == 0) {
osh_info "Open after waiting for " . (time() - $startedat) . " seconds, connecting...";
sleep 2 if (time() > $startedat + 1); # so that ssh has the time to startup... hopefully
last;
sleep 1; # to avoid looping too fast if the failure is immediate and not a timeout (i.e. port closed)
$loops++;
if ($loops % 5 == 0) {
osh_info("Still trying to connect to $host:$port after " . (time() - $startedat) . " seconds...");
}
sleep 1;
}
}
@ -2021,7 +2008,6 @@ Usage (osh cmd): $bastionName --osh [OSH_COMMAND] [OSH_OPTIONS]
--always-escape Bypass config and force the bugged behavior of old bastions for REMOTE_COMMAND escaping. Don't use.
--never-escape Bypass config and force the new behavior of new bastions for REMOTE_COMMAND escaping. Don't use.
--wait Ping the host before connecting to it (useful to ssh just after a reboot!)
--wait-port Test the host specific port to be open before connecting to it
--long-help Print this
[REMOTE_COMMAND]

View file

@ -141,28 +141,41 @@ EOS
# now that we have several keys, take the opportunity to test force-key
plgfail a1_add_access_force_key_and_pwd_g1 $a1 --osh groupAddServer --host 127.1.2.3 --user-any --port-any --force --force-password '$1$2$3456' --force-key "$key1fp" --group $group1
plgfail a1_add_access_force_key_and_pwd_g1 $a1 --osh groupAddServer --host 127.0.0.5 --user-any --port-any --force --force-password '$1$2$3456' --force-key "$key1fp" --group $group1
json .error_code ERR_INCOMPATIBLE_PARAMETERS
success a1_add_access_force_key_g1 $a1 --osh groupAddServer --host 127.1.2.3 --user 'ar@base' --port-any --force --force-key "$key1fp" --group $group1
success a1_add_access_force_key_g1 $a1 --osh groupAddServer --host 127.0.0.5 --user 'ar@base' --port-any --force --force-key "$key1fp" --group $group1
json .value.user 'ar@base'
success a1_list_servers_check_force_key_g1 $a1 --osh groupListServers --group $group1
json '.value|.[]|select(.ip=="127.1.2.3")|.forceKey' "$key1fp"
json '.value|.[]|select(.ip=="127.1.2.3")|.user' "ar@base"
json '.value|.[]|select(.ip=="127.0.0.5")|.forceKey' "$key1fp"
json '.value|.[]|select(.ip=="127.0.0.5")|.user' "ar@base"
# try to use the force key
# try to use the force key AND --wait
run a1_connect_g1_with_forcekey $a1 ar@base@127.1.2.3 -- false
run a1_connect_g1_with_forcekey_and_wait $a1 --wait ar@base@127.0.0.5 -- false
contain 'Connecting...'
contain 'FORCED IN ACL'
contain "$key1fp"
nocontain "$key0fp"
contain "Waiting for port 22 to be open on "
contain REGEX "Alive after waiting for [0-9] seconds"
success a1_remove_forcekey_acl_g1 $a1 --osh groupDelServer --host 127.1.2.3 --user 'ar@base' --port-any --group $group1
success a1_remove_forcekey_acl_g1 $a1 --osh groupDelServer --host 127.0.0.5 --user 'ar@base' --port-any --group $group1
# /force-key
success a1_add_non_routable_ip $a1 --osh groupAddServer --host 192.0.2.0 --user-any --port-any --force --group $group1
run a1_ssh_wait $a1 --wait 192.0.2.0
retvalshouldbe 124 # timeout
contain "Waiting for port 22 to be open on 192.0.2.0"
contain REGEX "Still trying to connect to 192.0.2.0:22 after 1[0-9] seconds"
success a1_remove_non_routable_ip $a1 --osh groupDelServer --host 192.0.2.0 --user-any --port-any --group $group1
# test --alive
run a0_del_key_g1 $a0 --osh groupDelEgressKey --group $group1 --id $key1id
retvalshouldbe 106
json .command null .error_code KO_RESTRICTED_COMMAND .value null