diff --git a/Anvil/Tools/Database.pm b/Anvil/Tools/Database.pm index 5b26766a..6f341595 100644 --- a/Anvil/Tools/Database.pm +++ b/Anvil/Tools/Database.pm @@ -2635,6 +2635,202 @@ WHERE return($file_uuid); } +=head2 insert_or_update_host_keys + +This updates (or inserts) a record in the 'host_keys' table. The C<< host_key_uuid >> UUID will be returned. + +If there is an error, an empty string is returned. + +Parameters; + +=head3 uuid (optional) + +If set, only the corresponding database will be written to. + +=head3 file (optional) + +If set, this is the file name logged as the source of any INSERTs or UPDATEs. + +=head3 line (optional) + +If set, this is the file line number logged as the source of any INSERTs or UPDATEs. + +=head3 host_key_host_uuid (optional, default is Get->host_uuid) + +This is the host that the corresponding user and key belong to. + +=head3 host_key_public_key (required) + +This is the B<> key for the user, the full line stored in the user's C<< ~/.ssh/id_rsa.pub >> file. + +=head3 host_key_user_name (required) + +This is the name of the user that the public key belongs to. + +=head3 host_key_uuid (optional) + +This is the specific record to update. If not provides, a search will be made to find a matching entry. If found, the record will be updated if one of the values has changed. If not, a new record will be inserted. + +=cut +sub insert_or_update_host_keys +{ + my $self = shift; + my $parameter = shift; + my $anvil = $self->parent; + my $debug = defined $parameter->{debug} ? $parameter->{debug} : 3; + $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => $debug, key => "log_0125", variables => { method => "Database->insert_or_update_host_keys()" }}); + + my $uuid = defined $parameter->{uuid} ? $parameter->{uuid} : ""; + my $file = defined $parameter->{file} ? $parameter->{file} : ""; + my $line = defined $parameter->{line} ? $parameter->{line} : ""; + my $host_key_host_uuid = defined $parameter->{host_key_host_uuid} ? $parameter->{host_key_host_uuid} : $anvil->Get->host_uuid; + my $host_key_public_key = defined $parameter->{host_key_public_key} ? $parameter->{host_key_public_key} : ""; + my $host_key_user_name = defined $parameter->{host_key_user_name} ? $parameter->{host_key_user_name} : ""; + my $host_key_uuid = defined $parameter->{host_key_uuid} ? $parameter->{host_key_uuid} : ""; + $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { + uuid => $uuid, + file => $file, + line => $line, + host_key_host_uuid => $host_key_host_uuid, + host_key_public_key => $host_key_public_key, + host_key_user_name => $host_key_user_name, + host_key_uuid => $host_key_uuid, + }}); + + if (not $host_key_public_key) + { + # Throw an error and exit. + $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 0, priority => "err", key => "log_0020", variables => { method => "Database->insert_or_update_host_keys()", parameter => "host_key_public_key" }}); + return(""); + } + if (not $host_key_user_name) + { + # Throw an error and exit. + $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 0, priority => "err", key => "log_0020", variables => { method => "Database->insert_or_update_host_keys()", parameter => "host_key_user_name" }}); + return(""); + } + + # If we don't have a UUID, see if we can find one for the given user and host. + if (not $host_key_uuid) + { + my $query = " +SELECT + host_key_uuid +FROM + host_keys +WHERE + host_key_user_name = ".$anvil->data->{sys}{database}{use_handle}->quote($host_key_user_name)." +AND + host_key_host_uuid = ".$anvil->data->{sys}{database}{use_handle}->quote($host_key_host_uuid)." +;"; + $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { query => $query }}); + + my $results = $anvil->Database->query({query => $query, source => $file ? $file." -> ".$THIS_FILE : $THIS_FILE, line => $line ? $line." -> ".__LINE__ : __LINE__}); + my $count = @{$results}; + $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { + results => $results, + count => $count, + }}); + if ($count) + { + $host_key_uuid = $results->[0]->[0]; + $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { host_key_uuid => $host_key_uuid }}); + } + } + + # If I still don't have an host_key_uuid, we're INSERT'ing . + $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { host_key_uuid => $host_key_uuid }}); + if (not $host_key_uuid) + { + # INSERT + $host_key_uuid = $anvil->Get->uuid(); + $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { host_key_uuid => $host_key_uuid }}); + + my $query = " +INSERT INTO + host_keys +( + host_key_uuid, + host_key_host_uuid, + host_key_public_key, + host_key_user_name, + modified_date +) VALUES ( + ".$anvil->data->{sys}{database}{use_handle}->quote($host_key_uuid).", + ".$anvil->data->{sys}{database}{use_handle}->quote($host_key_host_uuid).", + ".$anvil->data->{sys}{database}{use_handle}->quote($host_key_public_key).", + ".$anvil->data->{sys}{database}{use_handle}->quote($host_key_user_name).", + ".$anvil->data->{sys}{database}{use_handle}->quote($anvil->data->{sys}{database}{timestamp})." +); +"; + $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { query => $query }}); + $anvil->Database->write({query => $query, source => $file ? $file." -> ".$THIS_FILE : $THIS_FILE, line => $line ? $line." -> ".__LINE__ : __LINE__}); + } + else + { + # Query the rest of the values and see if anything changed. + my $query = " +SELECT + host_key_host_uuid, + host_key_public_key, + host_key_user_name +FROM + host_keys +WHERE + host_key_uuid = ".$anvil->data->{sys}{database}{use_handle}->quote($host_key_uuid)." +;"; + $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { query => $query }}); + + my $results = $anvil->Database->query({query => $query, source => $file ? $file." -> ".$THIS_FILE : $THIS_FILE, line => $line ? $line." -> ".__LINE__ : __LINE__}); + my $count = @{$results}; + $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { + results => $results, + count => $count, + }}); + if (not $count) + { + # I have a host_key_uuid but no matching record. Probably an error. + $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 0, priority => "err", key => "log_0216", variables => { uuid_name => "host_key_uuid", uuid => $host_key_uuid }}); + return(""); + } + foreach my $row (@{$results}) + { + my $old_host_key_host_uuid = $row->[0]; + my $old_host_key_public_key = $row->[1]; + my $old_host_key_user_name = $row->[2]; + $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { + old_host_key_host_uuid => $old_host_key_host_uuid, + old_host_key_public_key => $old_host_key_public_key, + old_host_key_user_name => $old_host_key_user_name, + }}); + + # Anything change? + if (($old_host_key_host_uuid ne $host_key_host_uuid) or + ($old_host_key_public_key ne $host_key_public_key) or + ($old_host_key_user_name ne $host_key_user_name)) + { + # Something changed, save. + my $query = " +UPDATE + host_keys +SET + host_key_host_uuid = ".$anvil->data->{sys}{database}{use_handle}->quote($host_key_host_uuid).", + host_key_public_key = ".$anvil->data->{sys}{database}{use_handle}->quote($host_key_public_key).", + host_key_user_name = ".$anvil->data->{sys}{database}{use_handle}->quote($host_key_user_name).", + modified_date = ".$anvil->data->{sys}{database}{use_handle}->quote($anvil->data->{sys}{database}{timestamp})." +WHERE + host_key_uuid = ".$anvil->data->{sys}{database}{use_handle}->quote($host_key_uuid)." +"; + $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { query => $query }}); + $anvil->Database->write({query => $query, source => $file ? $file." -> ".$THIS_FILE : $THIS_FILE, line => $line ? $line." -> ".__LINE__ : __LINE__}); + } + } + } + + $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { host_key_uuid => $host_key_uuid }}); + return($host_key_uuid); +} + =head2 insert_or_update_hosts This updates (or inserts) a record in the 'hosts' table. The C<< host_uuid >> UUID will be returned. diff --git a/Anvil/Tools/Storage.pm b/Anvil/Tools/Storage.pm index ca81d618..9506586a 100644 --- a/Anvil/Tools/Storage.pm +++ b/Anvil/Tools/Storage.pm @@ -504,7 +504,7 @@ sub check_md5sums { # Exit. $exit = 1; - $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 0, priority => "warn", key => "log_0250", variables => { + $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 0, priority => "alert", key => "log_0250", variables => { file => $0, old_sum => $anvil->data->{md5sum}{$caller}{start_time}, new_sum => $anvil->data->{md5sum}{$caller}{now}, @@ -541,7 +541,7 @@ sub check_md5sums { # Changed. $exit = 1; - $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 0, priority => "warn", key => "log_0250", variables => { + $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 0, priority => "alert", key => "log_0250", variables => { file => $module_file, old_sum => $anvil->data->{md5sum}{$module_file}{start_time}, new_sum => $anvil->data->{md5sum}{$module_file}{now}, @@ -566,7 +566,7 @@ sub check_md5sums if ($anvil->data->{md5sum}{$file}{start_time} ne $anvil->data->{md5sum}{$file}{now}) { $exit = 1; - $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 0, priority => "warn", key => "log_0250", variables => { + $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 0, priority => "alert", key => "log_0250", variables => { file => $file, old_sum => $anvil->data->{md5sum}{$file}{start_time}, new_sum => $anvil->data->{md5sum}{$file}{now}, diff --git a/cgi-bin/upload.pl b/cgi-bin/upload.pl index 0b297223..2ec93903 100755 --- a/cgi-bin/upload.pl +++ b/cgi-bin/upload.pl @@ -134,7 +134,7 @@ if ($cgi->param()) else { # Why are we here? - $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, 'print' => 1, level => 1, priority => "warn", key => "log_0261", variables => { file => $THIS_FILE }}); + $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, 'print' => 1, level => 1, priority => "alert", key => "log_0261", variables => { file => $THIS_FILE }}); } exit(0); diff --git a/share/words.xml b/share/words.xml index d8449439..c4674df8 100644 --- a/share/words.xml +++ b/share/words.xml @@ -572,6 +572,7 @@ The user: [#!variable!user!#]'s SSH key yet has been generated. The output is be ==== The user: [#!variable!user!#] doesn't appear to have a base SSH directory. Will now create: [#!variable!directory!#]. + The user: [#!variable!user!#]'s: [#!variable!file!#] file needs to be updated. Test @@ -838,6 +839,7 @@ Failed to generate an RSA public key for the user: [#!variable!user!#]. The outp #!variable!output!# ==== + Failed to backup: [#!variable!file!#], skipping.. Yes diff --git a/tools/anvil-daemon b/tools/anvil-daemon index 6a6b6f04..0f38228c 100755 --- a/tools/anvil-daemon +++ b/tools/anvil-daemon @@ -50,6 +50,7 @@ use JSON; use HTML::Strip; use HTML::FromText; use Data::Dumper; +use Text::Diff; my $THIS_FILE = ($0 =~ /^.*\/(.*)$/)[0]; my $running_directory = ($0 =~ /^(.*?)\/$THIS_FILE$/)[0]; @@ -73,6 +74,9 @@ $anvil->Log->secure({set => 1}); $anvil->Database->connect({debug => 3, check_if_configured => 1}); $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 3, secure => 0, key => "log_0132"}); +check_ssh_keys($anvil); +die; + # If I have no databases, sleep for a second and then exit (systemd will restart us). if (not $anvil->data->{sys}{database}{connections}) { @@ -174,7 +178,7 @@ while(1) # Exit if 'run-once' selected. if ($anvil->data->{switches}{'run-once'}) { - $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 0, priority => "warn", key => "message_0055"}); + $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 0, priority => "alert", key => "message_0055"}); $anvil->nice_exit({code => 0}); } @@ -219,7 +223,7 @@ sub handle_periodic_tasks if ((not $anvil->data->{timing}{jobs_running}) && ($anvil->Storage->check_md5sums)) { # NOTE: We exit with '0' to prevent systemctl from showing a scary red message. - $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 0, priority => "warn", key => "message_0014"}); + $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 0, priority => "alert", key => "message_0014"}); $anvil->nice_exit({code => 0}); } @@ -253,7 +257,7 @@ sub handle_periodic_tasks if ($failed) { # Something went wrong. - $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 0, priority => "warn", key => "log_0254", variables => { + $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 0, priority => "alert", key => "log_0254", variables => { directory => $directory, }}); } @@ -311,12 +315,14 @@ sub check_ssh_keys # Get a list of all hosts and IPs we know about. We'll use this to update + # Get a list of machine host keys and user public keys from other machines. + get_other_keys($anvil); # Users to check: # root, admin, hacluster foreach my $user ("root", "admin") { - $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 3, list => { user => $user }}); + $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { user => $user }}); my $user_home = $anvil->Get->users_home({user => $user}); $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 3, list => { user_home => $user_home }}); @@ -331,7 +337,7 @@ sub check_ssh_keys if (not -e $ssh_directory) { # Create it. - $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 2, key => "log_0272", variables => { user => $user, directory => $ssh_directory }}); + $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 1, key => "log_0272", variables => { user => $user, directory => $ssh_directory }}); $anvil->Storage->make_directory({ directory => $ssh_directory, user => $user, @@ -347,20 +353,20 @@ sub check_ssh_keys my $ssh_private_key_file = $user_home."/.ssh/id_rsa"; my $ssh_public_key_file = $user_home."/.ssh/id_rsa.pub"; - $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { + $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 3, list => { ssh_public_key_file => $ssh_public_key_file, ssh_private_key_file => $ssh_private_key_file, }}); if (not -e $ssh_public_key_file) { # Generate the SSH keys. - $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 2, key => "log_0270", variables => { user => $user }}); + $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 1, key => "log_0270", variables => { user => $user }}); my $output = $anvil->System->call({shell_call => $anvil->data->{path}{exe}{'ssh-keygen'}." -t rsa -N \"\" -b 8191 -f ".$ssh_private_key_file}); if (-e $ssh_public_key_file) { # Success! - $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 2, key => "log_0271", variables => { user => $user, output => $output }}); + $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 1, key => "log_0271", variables => { user => $user, output => $output }}); } else { @@ -369,11 +375,305 @@ sub check_ssh_keys next; } } - + # Now read in the key. my $users_public_key = $anvil->Storage->read_file({file => $ssh_public_key_file}); $users_public_key =~ s/\n$//; - $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { users_public_key => $users_public_key }}); + $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 3, list => { users_public_key => $users_public_key }}); + + # Now store the key in the 'host_key' table, if needed. + my $host_key_uuid = $anvil->Database->insert_or_update_host_keys({ + debug => 3, + host_key_host_uuid => $anvil->Get->host_uuid, + host_key_public_key => $users_public_key, + host_key_user_name => $user, + }); + + # Read in the existing 'known_hosts' file, if it exists. The 'old' and 'new' variables will + # be used when looking for needed changes. + my $known_hosts_file_body = ""; + my $known_hosts_old_body = ""; + my $known_hosts_new_body = ""; + my $known_hosts_file = $ssh_directory."/known_hosts"; + $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 3, list => { known_hosts_file => $known_hosts_file }}); + if (-e $known_hosts_file) + { + $known_hosts_file_body = $anvil->Storage->read_file({file => $known_hosts_file}); + $known_hosts_old_body = $known_hosts_file_body; + $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 3, list => { known_hosts_file_body => $known_hosts_file_body }}); + } + + # Read in the existing 'authorized_keys' file, if it exists. + my $authorized_keys_file_body = ""; + my $authorized_keys_old_body = ""; + my $authorized_keys_new_body = ""; + my $authorized_keys_file = $ssh_directory."/authorized_keys"; + $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 3, list => { authorized_keys_file => $authorized_keys_file }}); + if (-e $authorized_keys_file) + { + $authorized_keys_file_body = $anvil->Storage->read_file({file => $authorized_keys_file}); + $authorized_keys_old_body = $authorized_keys_file_body; + $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 3, list => { authorized_keys_file_body => $authorized_keys_file_body }}); + } + + ### Walk through each host we now know of. As we we do, loop through the old file body to see + ### if it exists. If it does, and the key has changed, update the line with the new key. If + ### it isn't found, add it. Once we check the old body for this entry, change the "old" body + ### to the new one, then repeat the process. + + # Look at all the hosts I know about (other than myself) and see if any of the machine or + # user keys either don't exist or have changed. + my $update_known_hosts = 0; + my $update_authorized_keys = 0; + foreach my $host_uuid (keys %{$anvil->data->{peers}{ssh_keys}}) + { + $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { host_uuid => $host_uuid }}); + foreach my $host_name (sort {$a cmp $b} keys %{$anvil->data->{peers}{ssh_keys}{$host_uuid}{host}}) + { + my $key = $anvil->data->{peers}{ssh_keys}{$host_uuid}{host}{$host_name}; + $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 3, list => { + 's1:host_name' => $host_name, + 's2:key' => $key, + }}); + + # Is this in the file and, if so, has it changed? + my $found = 0; + my $test_line = $host_name." ".$key; + $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { test_line => $test_line }}); + foreach my $line (split/\n/, $known_hosts_old_body) + { + $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { line => $line }}); + if ($line eq $test_line) + { + # No change needed, key is the same. + $found = 1; + $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { found => $found }}); + last; + } + elsif ($line =~ /^$host_name /) + { + # Key has changed, update. + $found = 1; + $line = $test_line; + $update_known_hosts = 1; + $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { + found => $found, + line => $line, + update_known_hosts => $update_known_hosts, + }}); + } + $known_hosts_new_body .= $line."\n"; + } + # If we didn't find the key, add it. + $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { found => $found }}); + if (not $found) + { + $update_known_hosts = 1; + $known_hosts_new_body .= $test_line."\n"; + $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { + 's1:update_known_hosts' => $update_known_hosts, + 's2:known_hosts_new_body' => $known_hosts_new_body, + }}); + } + + # Move the new body over to the old body (even though it may not have + # changed) and then clear the new body to prepare for the next pass. + $known_hosts_old_body = $known_hosts_new_body; + $known_hosts_new_body = ""; + } + } + # Lastly, copy the last version of the old body to the new body, + $known_hosts_new_body = $known_hosts_old_body; + $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { + 's1:update_known_hosts' => $update_known_hosts, + 's2:known_hosts_file_body' => $known_hosts_file_body, + 's3:known_hosts_new_body' => $known_hosts_new_body, + 's4:difference' => diff \$known_hosts_file_body, \$known_hosts_new_body, { STYLE => 'Unified' }, + }}); + + die; + + # Update files, if needed. + $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { update_known_hosts => $update_known_hosts }}); + if ($update_known_hosts) + { + $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 2, key => "log_0273", variables => { user => $user, file => $known_hosts_file }}); + if (-e $known_hosts_file) + { + my $backup_file = $anvil->Storage->backup({ + debug => 2, + fatal => 1, + file => $known_hosts_file, + }); + $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { backup_file => $backup_file }}); + if (-e $backup_file) + { + $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 2, key => "log_0154", variables => { source_file => $known_hosts_file, target_file => $backup_file }}); + } + else + { + $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 1, priority => "alert", key => "error_0058", variables => { file => $known_hosts_file }}); + } + } + my $failed = $anvil->Storage->write_file({ + debug => 3, + overwrite => 1, + file => $known_hosts_file, + body => $known_hosts_new_body, + user => $user, + group => $user, + mode => "0644", + }); + $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { failed => $failed }}); + } + $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { update_authorized_keys => $update_authorized_keys }}); + if ($update_authorized_keys) + { + $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 2, key => "log_0273", variables => { user => $user, file => $authorized_keys_file }}); + if (-e $authorized_keys_file) + { + my $backup_file = $anvil->Storage->backup({ + debug => 2, + fatal => 1, + file => $authorized_keys_file, + }); + $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { backup_file => $backup_file }}); + if (-e $backup_file) + { + $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 2, key => "log_0154", variables => { source_file => $authorized_keys_file, target_file => $backup_file }}); + } + else + { + $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 1, priority => "alert", key => "error_0058", variables => { file => $authorized_keys_file }}); + } + } + my $failed = $anvil->Storage->write_file({ + debug => 3, + overwrite => 1, + file => $authorized_keys_file, + body => $authorized_keys_new_body, + user => $user, + group => $user, + mode => "0644", + }); + $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { failed => $failed }}); + } + } + + return(0); +} + +# Get a list of machine host keys and user public keys from other machines. +sub get_other_keys +{ + my ($anvil) = @_; + + delete $anvil->data->{peers}{ssh_keys}; + + # Get the machine keys for other hosts. + my $query = " +SELECT + host_uuid, + host_name, + host_key +FROM + hosts +WHERE + host_uuid != ".$anvil->data->{sys}{database}{use_handle}->quote($anvil->Get->host_uuid)." +;"; + $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 3, list => { query => $query }}); + + my $results = $anvil->Database->query({query => $query, source => $THIS_FILE, line => __LINE__}); + my $count = @{$results}; + $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 3, list => { + results => $results, + count => $count, + }}); + foreach my $row (@{$results}) + { + my $host_uuid = $row->[0]; + my $host_name = $row->[1]; + my $host_key = $row->[2]; + $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 3, list => { + host_uuid => $host_uuid, + host_name => $host_name, + host_key => $host_key, + }}); + + $anvil->data->{peers}{ssh_keys}{$host_uuid}{host}{$host_name} = $host_key; + $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 3, list => { + "peers::ssh_keys::${host_uuid}::host::${host_name}" => $anvil->data->{peers}{ssh_keys}{$host_uuid}{host}{$host_name}, + }}); + + # If the host name is the long host name, create another entry with the short name. + if ($host_name =~ /^(.*?)\./) + { + my $short_hostname = $1; + $anvil->data->{peers}{ssh_keys}{$host_uuid}{host}{$short_hostname} = $host_key; + $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 3, list => { + "peers::ssh_keys::${host_uuid}::host::${short_hostname}" => $anvil->data->{peers}{ssh_keys}{$host_uuid}{host}{$short_hostname}, + }}); + } + + # Find any IP addresses for this host. + my $query = "SELECT ip_address_address FROM ip_addresses WHERE ip_address_host_uuid = ".$anvil->data->{sys}{database}{use_handle}->quote($host_uuid).";"; + $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 3, list => { query => $query }}); + + my $results = $anvil->Database->query({query => $query, source => $THIS_FILE, line => __LINE__}); + my $count = @{$results}; + $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 3, list => { + results => $results, + count => $count, + }}); + foreach my $row (@{$results}) + { + my $ip_address_address = $row->[0]; + $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 3, list => { + ip_address_address => $ip_address_address, + }}); + + $anvil->data->{peers}{ssh_keys}{$host_uuid}{host}{$ip_address_address} = $host_key; + $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 3, list => { + "peers::ssh_keys::${host_uuid}::host::${ip_address_address}" => $anvil->data->{peers}{ssh_keys}{$host_uuid}{host}{$ip_address_address}, + }}); + } + + } + + # Now read in the public key for other users on other machines. + $query = " +SELECT + host_key_host_uuid, + host_key_user_name, + host_key_public_key +FROM + host_keys +WHERE + host_key_host_uuid != ".$anvil->data->{sys}{database}{use_handle}->quote($anvil->Get->host_uuid)." +;"; + $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 3, list => { query => $query }}); + + $results = $anvil->Database->query({query => $query, source => $THIS_FILE, line => __LINE__}); + $count = @{$results}; + $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 3, list => { + results => $results, + count => $count, + }}); + foreach my $row (@{$results}) + { + my $host_key_host_uuid = $row->[0]; + my $host_key_user_name = $row->[1]; + my $host_key_public_key = $row->[2]; + $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 3, list => { + host_key_host_uuid => $host_key_host_uuid, + host_key_user_name => $host_key_user_name, + host_key_public_key => $host_key_public_key, + }}); + + $anvil->data->{peers}{ssh_keys}{$host_key_host_uuid}{user}{$host_key_user_name} = $host_key_public_key; + $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 3, list => { + "peers::ssh_keys::${host_key_host_uuid}::user::${host_key_user_name}" => $anvil->data->{peers}{ssh_keys}{$host_key_host_uuid}{user}{$host_key_user_name}, + }}); } return(0); @@ -489,7 +789,7 @@ FROM WHERE variable_source_table = 'hosts' AND - variable_source_uuid = ".$anvil->data->{sys}{database}{use_handle}->quote($anvil->data->{sys}{host_uuid})." + variable_source_uuid = ".$anvil->data->{sys}{database}{use_handle}->quote($anvil->Get->host_uuid)." AND variable_name = 'reboot::needed' ;"; diff --git a/tools/scancore b/tools/scancore index 093b367f..06c06c42 100755 --- a/tools/scancore +++ b/tools/scancore @@ -220,7 +220,7 @@ sub exit_if_sums_changed if ($anvil->Storage->check_md5sums) { # NOTE: We exit with '0' to prevent systemctl from showing a scary red message. - $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, 'print' => 1, level => 0, priority => "warn", key => "message_0014"}); + $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, 'print' => 1, level => 0, priority => "alert", key => "message_0014"}); $anvil->nice_exit({code => 0}); }