* Fixed a few bugs with how rsync is handled, specifically in the rsync wrapper script.

* Fixed a bug with handling ssh fingerprints (and removed comments going to the known_hosts file).
* Added more nested debug parameter passing when methods call other methods (though more work is needed to catch up)

Signed-off-by: Digimer <digimer@alteeve.ca>
main
Digimer 7 years ago
parent ea43896fca
commit 188cab5ec0
  1. 3
      Anvil/Tools.pm
  2. 2
      Anvil/Tools/Get.pm
  3. 28
      Anvil/Tools/Remote.pm
  4. 39
      Anvil/Tools/Storage.pm
  5. 3
      share/words.xml
  6. 13
      tools/anvil-configure-network

@ -785,6 +785,7 @@ sub _set_paths
expect => "/usr/bin/expect", expect => "/usr/bin/expect",
'firewall-cmd' => "/usr/bin/firewall-cmd", 'firewall-cmd' => "/usr/bin/firewall-cmd",
gethostip => "/usr/bin/gethostip", gethostip => "/usr/bin/gethostip",
'grep' => "/usr/bin/grep",
head => "/usr/bin/head", head => "/usr/bin/head",
hostname => "/usr/bin/hostname", hostname => "/usr/bin/hostname",
hostnamectl => "/usr/bin/hostnamectl", hostnamectl => "/usr/bin/hostnamectl",
@ -807,7 +808,7 @@ sub _set_paths
rsync => "/usr/bin/rsync", rsync => "/usr/bin/rsync",
sed => "/usr/bin/sed", sed => "/usr/bin/sed",
'shutdown' => "/usr/sbin/shutdown", 'shutdown' => "/usr/sbin/shutdown",
'ssh-keyscan' => "/usr/bin/ssh-keygen", 'ssh-keyscan' => "/usr/bin/ssh-keyscan",
strings => "/usr/bin/strings", strings => "/usr/bin/strings",
stty => "/usr/bin/stty", stty => "/usr/bin/stty",
su => "/usr/bin/su", su => "/usr/bin/su",

@ -715,7 +715,7 @@ sub users_home
my $home_directory = 0; my $home_directory = 0;
my $user = $parameter->{user} ? $parameter->{user} : ""; my $user = defined $parameter->{user} ? $parameter->{user} : "";
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { user => $user }}); $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { user => $user }});
# Make sure the user is only one digit. Sometimes $< (and others) will return multiple IDs. # Make sure the user is only one digit. Sometimes $< (and others) will return multiple IDs.

@ -124,7 +124,7 @@ sub add_target_to_known_hosts
}}); }});
# Get the local user's home # Get the local user's home
my $users_home = $anvil->Get->users_home({user => $user}); my $users_home = $anvil->Get->users_home({debug => $debug, user => $user});
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, secure => 0, list => { users_home => $users_home }}); $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, secure => 0, list => { users_home => $users_home }});
if (not $users_home) if (not $users_home)
{ {
@ -156,6 +156,7 @@ sub add_target_to_known_hosts
{ {
# We don't know about this machine yet, so scan it. # We don't know about this machine yet, so scan it.
my $added = $anvil->Remote->_call_ssh_keyscan({ my $added = $anvil->Remote->_call_ssh_keyscan({
debug => $debug,
target => $target, target => $target,
port => $port, port => $port,
user => $user, user => $user,
@ -472,7 +473,7 @@ sub call
{ {
# Can we log in without a password? # Can we log in without a password?
my $user = getpwuid($<); my $user = getpwuid($<);
my $home_directory = $anvil->Get->users_home({user => $user}); my $home_directory = $anvil->Get->users_home({debug => $debug, user => $user});
my $public_key = $home_directory."/.ssh/id_rsa.pub"; my $public_key = $home_directory."/.ssh/id_rsa.pub";
my $private_key = $home_directory."/.ssh/id_rsa"; my $private_key = $home_directory."/.ssh/id_rsa";
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $log_level, list => { $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $log_level, list => {
@ -695,12 +696,13 @@ sub _call_ssh_keyscan
user => $user, user => $user,
}}); }});
my $shell_call = $anvil->data->{path}{exe}{'ssh-keyscan'}." ".$target." >> ".$known_hosts; # Redirect STDERR to STDOUT and grep off the comments.
my $shell_call = $anvil->data->{path}{exe}{'ssh-keyscan'}." ".$target." 2>&1 | ".$anvil->data->{path}{exe}{'grep'}." -v ^# >> ".$known_hosts;
if (($port) && ($port ne "22")) if (($port) && ($port ne "22"))
{ {
$shell_call = $anvil->data->{path}{exe}{'ssh-keyscan'}." -p ".$port." ".$target." >> ".$known_hosts; $shell_call = $anvil->data->{path}{exe}{'ssh-keyscan'}." -p ".$port." ".$target." 2>&1 | ".$anvil->data->{path}{exe}{'grep'}." -v ^# >> ".$known_hosts;
} }
my $output = $anvil->System->call({shell_call => $shell_call}); my $output = $anvil->System->call({debug => $debug, shell_call => $shell_call});
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { output => $output }}); $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { output => $output }});
foreach my $line (split/\n/, $output) foreach my $line (split/\n/, $output)
{ {
@ -769,6 +771,7 @@ sub _check_known_hosts_for_target
my $port = defined $parameter->{port} ? $parameter->{port} : ""; my $port = defined $parameter->{port} ? $parameter->{port} : "";
my $target = defined $parameter->{target} ? $parameter->{target} : ""; my $target = defined $parameter->{target} ? $parameter->{target} : "";
my $user = defined $parameter->{user} ? $parameter->{user} : $<; my $user = defined $parameter->{user} ? $parameter->{user} : $<;
my $known_machine = 0;
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, secure => 0, list => { $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, secure => 0, list => {
delete_if_found => $delete_if_found, delete_if_found => $delete_if_found,
known_hosts => $known_hosts, known_hosts => $known_hosts,
@ -777,12 +780,19 @@ sub _check_known_hosts_for_target
user => $user, user => $user,
}}); }});
# Is there a known_hosts file at all?
if (not $known_hosts)
{
# Nope.
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => $debug, secure => 0, key => "log_0163", variables => { file => $$known_hosts }});
return($known_machine)
}
# read it in and search. # read it in and search.
my $known_machine = 0; my $body = $anvil->Storage->read_file({debug => $debug, file => $known_hosts});
my $body = $anvil->Storage->read_file({file => $known_hosts}); $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, secure => 0, list => { body => $body }});
foreach my $line (split/\n/, $body) foreach my $line (split/\n/, $body)
{ {
my $line = $_;
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, secure => 0, list => { line => $line }}); $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, secure => 0, list => { line => $line }});
if (($line =~ /$target ssh-rsa /) or ($line =~ /\[$target\]:$port ssh-rsa /)) if (($line =~ /$target ssh-rsa /) or ($line =~ /\[$target\]:$port ssh-rsa /))
@ -805,7 +815,7 @@ sub _check_known_hosts_for_target
$shell_call = $anvil->data->{path}{exe}{su}." - ".$user." -c '".$anvil->data->{path}{exe}{'ssh-keygen'}." -R ".$target."'"; $shell_call = $anvil->data->{path}{exe}{su}." - ".$user." -c '".$anvil->data->{path}{exe}{'ssh-keygen'}." -R ".$target."'";
} }
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, secure => 0, list => { shell_call => $shell_call }}); $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, secure => 0, list => { shell_call => $shell_call }});
my $output = $anvil->System->call({shell_call => $shell_call}); my $output = $anvil->System->call({debug => $debug, shell_call => $shell_call});
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { output => $output }}); $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { output => $output }});
foreach my $line (split/\n/, $output) foreach my $line (split/\n/, $output)
{ {

@ -917,6 +917,7 @@ sub read_file
# Setup the temp file name. # Setup the temp file name.
my $temp_file = $file; my $temp_file = $file;
$temp_file =~ s/\//_/g; $temp_file =~ s/\//_/g;
$temp_file =~ s/^_//g;
$temp_file = "/tmp/".$temp_file.".".$target; $temp_file = "/tmp/".$temp_file.".".$target;
$temp_file =~ s/\s+/_/g; $temp_file =~ s/\s+/_/g;
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { temp_file => $temp_file }}); $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { temp_file => $temp_file }});
@ -937,12 +938,14 @@ sub read_file
else else
{ {
# Read from the target by rsync'ing the file here. # Read from the target by rsync'ing the file here.
$anvil->Storage->rsync({ my $failed = $anvil->Storage->rsync({
debug => $debug,
destination => $temp_file, destination => $temp_file,
password => $password, password => $password,
port => $port, port => $port,
source => $remote_user."\@".$target.$file, source => $remote_user."\@".$target.":".$file,
}); });
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { failed => $failed }});
if (-e $temp_file) if (-e $temp_file)
{ {
@ -1251,8 +1254,9 @@ sub rsync
} }
# Make sure we know the fingerprint of the remote machine # Make sure we know the fingerprint of the remote machine
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => $debug, secure => 0, key => "log_0158", variables => { target => $target }}); $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => $debug, secure => 0, key => "log_0158", variables => { target => $target, user => $< }});
$anvil->Remote->add_target_to_known_hosts({ $anvil->Remote->add_target_to_known_hosts({
debug => $debug,
target => $target, target => $target,
user => $<, user => $<,
}); });
@ -1269,13 +1273,15 @@ sub rsync
} }
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, secure => 0, list => { shell_call => $shell_call }}); $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, secure => 0, list => { shell_call => $shell_call }});
# Now make the call # Now make the call (this exposes the password so 'secure' is set).
my $conflict = ""; my $conflict = "";
my $output = $anvil->System->call({shell_call => $shell_call}); my $output = $anvil->System->call({secure => 1, shell_call => $shell_call});
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { output => $output }}); $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, secure => 1, list => { output => $output }});
foreach my $line (split/\n/, $output) foreach my $line (split/\n/, $output)
{ {
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { line => $line }}); # This exposes the password on the 'password: ' line.
my $secure = $line =~ /password/i ? 1 : 0;
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, secure => $secure, list => { line => $line }});
if ($line =~ /Offending key in (\/.*\/).ssh\/known_hosts:(\d+)$/) if ($line =~ /Offending key in (\/.*\/).ssh\/known_hosts:(\d+)$/)
{ {
@ -1643,6 +1649,7 @@ fi";
# OK, now write the file locally, then we'll rsync it over. # OK, now write the file locally, then we'll rsync it over.
my $temp_file = $file; my $temp_file = $file;
$temp_file =~ s/\//_/g; $temp_file =~ s/\//_/g;
$temp_file =~ s/^_//g;
$temp_file = "/tmp/".$temp_file; $temp_file = "/tmp/".$temp_file;
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { temp_file => $temp_file }}); $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { temp_file => $temp_file }});
$anvil->Storage->write_file({ $anvil->Storage->write_file({
@ -1659,12 +1666,14 @@ fi";
# Now rsync it. # Now rsync it.
if (-e $temp_file) if (-e $temp_file)
{ {
$anvil->Storage->rsync({ my $failed = $anvil->Storage->rsync({
destination => $remote_user."\@".$target.$file, debug => $debug,
destination => $remote_user."\@".$target.":".$file,
password => $password, password => $password,
port => $port, port => $port,
source => $temp_file, source => $temp_file,
}); });
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { failed => $failed }});
# Unlink # Unlink
unlink $temp_file; unlink $temp_file;
@ -1786,14 +1795,14 @@ sub _create_rsync_wrapper
return(""); return("");
} }
### NOTE: The first line needs to be the '#!...' line, hence the odd formatting below.
my $timeout = 3600; my $timeout = 3600;
my $wrapper_script = "/tmp/rsync.$target"; my $wrapper_script = "/tmp/rsync.$target";
my $wrapper_body = " my $wrapper_body = "#!".$anvil->data->{path}{exe}{expect}."
".$anvil->data->{path}{exe}{echo}." #!".$anvil->data->{path}{exe}{expect}." set timeout ".$timeout."
".$anvil->data->{path}{exe}{echo}." set timeout ".$timeout." eval spawn rsync \$argv
".$anvil->data->{path}{exe}{echo}." eval spawn rsync \$argv expect \"password:\" \{ send \"".$password."\\n\" \}
".$anvil->data->{path}{exe}{echo}." expect \"password:\" \{ send \"".$password."\\n\" \} expect eof
".$anvil->data->{path}{exe}{echo}." expect eof
"; ";
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, secure => 0, list => { $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, secure => 0, list => {
wrapper_script => $wrapper_script, wrapper_script => $wrapper_script,

@ -236,11 +236,12 @@ The database connection error was:
<key name="log_0155">Removing the old network configuration file: [#!variable!file!#] as part of the network reconfiguration.</key> <key name="log_0155">Removing the old network configuration file: [#!variable!file!#] as part of the network reconfiguration.</key>
<key name="log_0156"><![CDATA[[ Error ] - The method: [#!variable!method!#] must be called with root-level priviledges.]]></key> <key name="log_0156"><![CDATA[[ Error ] - The method: [#!variable!method!#] must be called with root-level priviledges.]]></key>
<key name="log_0157"><![CDATA[[ Error ] - The method Storage->write_file() was asked to write the file: [#!variable!file!#] but it appears to be missing the file name. Aborting.]]></key> <key name="log_0157"><![CDATA[[ Error ] - The method Storage->write_file() was asked to write the file: [#!variable!file!#] but it appears to be missing the file name. Aborting.]]></key>
<key name="log_0158">Ensuring we've recorded: [#!variable!target!#]'s RSA fingerprint.</key> <key name="log_0158">Ensuring we've recorded: [#!variable!target!#]'s RSA fingerprint for the user: [#!variable!user!#].</key>
<key name="log_0159">Adding the target: [#!variable!target!#]:[#!variable!port!#]'s RSA fingerprint to: [#!variable!user!#]'s list of known hosts.</key> <key name="log_0159">Adding the target: [#!variable!target!#]:[#!variable!port!#]'s RSA fingerprint to: [#!variable!user!#]'s list of known hosts.</key>
<key name="log_0160"><![CDATA[[ Error ] - The method Storage->read_file() was asked to read the remote file: [#!variable!file!#] but it is not a full path. Aborting.]]></key> <key name="log_0160"><![CDATA[[ Error ] - The method Storage->read_file() was asked to read the remote file: [#!variable!file!#] but it is not a full path. Aborting.]]></key>
<key name="log_0161"><![CDATA[[ Error ] - The method Storage->read_file() was asked to read the remote file: [#!variable!file!#] but it appears to be missing the file name. Aborting.]]></key> <key name="log_0161"><![CDATA[[ Error ] - The method Storage->read_file() was asked to read the remote file: [#!variable!file!#] but it appears to be missing the file name. Aborting.]]></key>
<key name="log_0162"><![CDATA[[ Error ] - The method Storage->read_file() tried to rsync the remote file: [#!variable!remote_file!#] to the local temporary file: [#!variable!local_file!#], but it did not arrive. There might be more information above.]]></key> <key name="log_0162"><![CDATA[[ Error ] - The method Storage->read_file() tried to rsync the remote file: [#!variable!remote_file!#] to the local temporary file: [#!variable!local_file!#], but it did not arrive. There might be more information above.]]></key>
<key name="log_0163">The file: [#!variable!file!#] does not exist.</key>
<!-- Test words. Do NOT change unless you update 't/Words.t' or tests will needlessly fail. --> <!-- Test words. Do NOT change unless you update 't/Words.t' or tests will needlessly fail. -->
<key name="t_0000">Test</key> <key name="t_0000">Test</key>

@ -59,6 +59,19 @@ if (not $connections)
$anvil->nice_exit({exit_code => 2}); $anvil->nice_exit({exit_code => 2});
} }
$anvil->Storage->write_file({
debug => 2,
body => "This is only a test.\n",
file => "/home/admin/test.file",
group => "admin",
mode => "0644",
overwrite => 0,
port => 22,
password => "Initial1",
target => "192.168.122.202",
user => "admin",
remote_user => "admin",
});
die "Testing...\n"; die "Testing...\n";

Loading…
Cancel
Save