From 3e015372098e5b863ab68c725ded5fb0dc0ecba5 Mon Sep 17 00:00:00 2001 From: Digimer Date: Fri, 27 Sep 2019 23:21:24 -0400 Subject: [PATCH] * Updated how bad keys are removed. No longer are speciifc lines removed by number, but now all entries for the given target in the known_hosts file is removed. * Updated the pxe.txt file to now write a caller for anvil-update-issue in /etc/NetworkManager/dispatcher.d/ifup-local to have the /etc/issue file is updated as soon as the network is brought up, before the GDM login prompt is shown. * Fixed a couple bugs in tools/anvil-manage-keys, including to ensure that the permissions are retained when a file is updated. Signed-off-by: Digimer --- Anvil/Tools/Remote.pm | 2 + Anvil/Tools/Words.pm | 9 ++-- cgi-bin/striker | 36 +++++++-------- html/skins/alteeve/pxe.txt | 15 +++++-- html/skins/alteeve/striker.html | 16 +++---- share/words.xml | 6 +-- tools/anvil-manage-keys | 78 +++++++++++++++++---------------- tools/striker-initialize-host | 14 ++++-- 8 files changed, 99 insertions(+), 77 deletions(-) diff --git a/Anvil/Tools/Remote.pm b/Anvil/Tools/Remote.pm index 13791569..17e7a315 100644 --- a/Anvil/Tools/Remote.pm +++ b/Anvil/Tools/Remote.pm @@ -477,6 +477,8 @@ sub call $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { line => $line }}); if ($line =~ /Offending .*? key in (\/.*?known_hosts):(\d+)$/) { + # NOTE: We don't use the line now, but we're recording it + # anyway in case it happens to be useful in the future. $bad_file = $1; $bad_line = $2; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { diff --git a/Anvil/Tools/Words.pm b/Anvil/Tools/Words.pm index b0f3102b..5846a371 100644 --- a/Anvil/Tools/Words.pm +++ b/Anvil/Tools/Words.pm @@ -390,13 +390,13 @@ sub parse_banged_string } # Parse the line now. - $out_string .= $anvil->Words->string({key => $key, variables => $variables}); + $out_string .= $anvil->Words->string({debug => $debug, key => $key, variables => $variables}); $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { out_string => $out_string }}); } else { # This key is just a key, no variables. - $out_string .= $anvil->Words->string({key => $message}); + $out_string .= $anvil->Words->string({test => 0, key => $message}); $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { out_string => $out_string }}); } } @@ -616,8 +616,9 @@ sub string $loops++; die "$THIS_FILE ".__LINE__."; Infinite loop detected while processing the string: [".$string."] from the key: [$key] in language: [$language], exiting.\n" if $loops > $limit; } - print $THIS_FILE." ".__LINE__."; [ Error ] - The method Words->string() was asked to process the string: [".$string."] which has insertion variables, but nothing was passed to the 'variables' parameter.\n" if $test; - return("#!error!#"); + my $error = "[ Error ] - The method Words->string() was asked to process the string: [".$string."] which has insertion variables, but nothing was passed to the 'variables' parameter."; + print $THIS_FILE." ".__LINE__."; $error\n" if $test; + return($error); } # We set the 'loop' variable to '1' and check it at the end of each pass. This is done diff --git a/cgi-bin/striker b/cgi-bin/striker index 579529d6..03bc8d7f 100755 --- a/cgi-bin/striker +++ b/cgi-bin/striker @@ -497,8 +497,6 @@ sub process_keys { my ($anvil) = @_; - ### TODO: Left off here... Create a check-box list of state_uuid(s) the user selected, if any, and store them as a comma-separated list. - ### NOTE: This doesn't update Striker (the Alteeve) stack yet, just the base OK. my $show_list = 1; $anvil->data->{cgi}{'delete'}{value} = "" if not defined $anvil->data->{cgi}{'delete'}{value}; @@ -558,14 +556,17 @@ sub process_keys # Get a list of bad keys we know about and ask the user which they want to remove my $query = " SELECT - state_uuid, - state_host_uuid, - state_name, - state_note + a.state_uuid, + b.host_name, + a.state_name, + a.state_note FROM - states + states a, + hosts b WHERE - state_name LIKE 'host_key_changed::%' + a.state_host_uuid = b.host_uuid +AND + a.state_name LIKE 'host_key_changed::%' ;"; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { query => $query }}); my $results = $anvil->Database->query({query => $query, source => $THIS_FILE, line => __LINE__}); @@ -586,15 +587,15 @@ WHERE foreach my $row (@{$results}) { - my $state_uuid = $row->[0]; - my $state_host_uuid = $row->[1]; - my $state_name = $row->[2]; - my $state_note = $row->[3]; + my $state_uuid = $row->[0]; + my $host_name = $row->[1]; + my $state_name = $row->[2]; + my $state_note = $row->[3]; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { - state_uuid => $state_uuid, - state_host_uuid => $state_host_uuid, - state_name => $state_name, - state_note => $state_note, + state_uuid => $state_uuid, + host_name => $host_name, + state_name => $state_name, + state_note => $state_note, }}); my $bad_file = ""; @@ -626,7 +627,6 @@ WHERE bad_line => $bad_line, }}); - my $checkbox_key = "state_uuid_".$state_uuid; my $checked = ""; if ((exists $anvil->data->{cgi}{$checkbox_key}) && ($anvil->data->{cgi}{$checkbox_key}{value})) @@ -639,7 +639,7 @@ WHERE target => $target, user => $user, file => $bad_file, - line => $bad_line, + host => $host_name, }}); } diff --git a/html/skins/alteeve/pxe.txt b/html/skins/alteeve/pxe.txt index 2c8044c2..f36cd322 100644 --- a/html/skins/alteeve/pxe.txt +++ b/html/skins/alteeve/pxe.txt @@ -193,14 +193,23 @@ chmod 755 /mnt/sysimage/usr/sbin/anvil-update-issue # Add this to crontab. cat << EOF > /mnt/sysimage/var/spool/cron/root MAILTO="" -# First one keeps the list updated, the second one to make sure the list is -# there before the first login page is shown. * * * * * /usr/sbin/anvil-update-issue >> /var/log/anvil.cron 2>&1 -@reboot /usr/sbin/anvil-update-issue >> /var/log/anvil.cron 2>&1 EOF chown 0:0 /mnt/sysimage/var/spool/cron/root chmod 0600 /mnt/sysimage/var/spool/cron/root +echo 'Writing out the initial /etc/issue script.' +reset +cat << EOF > /mnt/sysimage/etc/NetworkManager/dispatcher.d/ifup-local +#!/usr/bin/bash +# +# Make sure that we update /etc/issue as soon as the network is up, before the +# logic in shown to the user after boot. + +/usr/sbin/anvil-update-issue +EOF +chmod +x /mnt/sysimage/etc/NetworkManager/dispatcher.d/ifup-local + %end diff --git a/html/skins/alteeve/striker.html b/html/skins/alteeve/striker.html index fbe65501..e224c1ff 100644 --- a/html/skins/alteeve/striker.html +++ b/html/skins/alteeve/striker.html @@ -4,16 +4,16 @@ - #!variable!user!# + #!variable!host!# - - #!variable!target!# + #!variable!user!# - - #!variable!file!# + #!variable!target!# - - #!variable!line!# + #!variable!file!# @@ -43,6 +43,10 @@   + + + #!string!header_0015!# + #!string!header_0013!# @@ -56,10 +60,6 @@ #!string!header_0014!# - - - #!string!header_0015!# - diff --git a/share/words.xml b/share/words.xml index 7fa5c704..bd4242fa 100644 --- a/share/words.xml +++ b/share/words.xml @@ -803,7 +803,7 @@ Here we will inject 't_0006', which injects 't_0001' which has a variable: [#!st Target User File - Line + On Host Welcome! Lets setup your #!string!brand_0003!# dashboard... @@ -1020,7 +1020,7 @@ Failure! The return code: [#!variable!return_code!#] was received ('0' was expec [ Error ] - The known hosts file: [#!variable!file!#] was not found. Skipping it. Finished. [ Error ] - There was a problem reading the known hosts file: [#!variable!file!#]. Skipping it. - Found the offending line, removing it. + Found an entry for the target at line: [#!variable!line!#], removing it. [ Error ] - The line number: [#!variable!line!#] in: [#!variable!file!#] does not appear to be for the target: [#!variable!target!#]. Has the file already been updated? Skipping it. Rewriing: [#!variable!file!#]. Manage Keys @@ -1042,7 +1042,7 @@ Failure! The return code: [#!variable!return_code!#] was received ('0' was expec The IP address is not a valid IPv4 address The SSH port is not a valid (usually it is 22, but it has to be between 1 ~ 65536) Failed to log into the host. Is the IP or root user's password right? - The target's host key has changed. If the target has been rebuilt, or the target IP reused, the old key will need to be removed. Problem file: [#!variable!file!#:#!variable!line!#]. + Click here to resolve.]]> There are not enough network interfaces on this machine. You have: [#!variable!interface_count!#] interface(s), and you need at least: [#!variable!required_interfaces_for_single!#] interfaces to connect to the requested networks (one for Back-Channel and one for each Internet-Facing network). diff --git a/tools/anvil-manage-keys b/tools/anvil-manage-keys index 17881492..37909174 100755 --- a/tools/anvil-manage-keys +++ b/tools/anvil-manage-keys @@ -11,6 +11,9 @@ # 2 = Job not found. # 3 = No offending keys found. # +# TODO: We might want to offer an option to remove all keys found for a given target. Somehow, at least in +# testing, multiple keys got into a single known_hosts file. +# use strict; use warnings; @@ -116,7 +119,7 @@ WHERE if ($state_host_uuid ne $anvil->data->{sys}{host_uuid}) { # Um... - $anvil->data->{job}{progress} += 10; $anvil->data->{job}{progress} = 95 if $anvil->data->{job}{progress} > 95; + $anvil->data->{job}{progress} += 10; update_progress($anvil, $anvil->data->{job}{progress}, "job_0058,!!state_uuid!".$state_uuid."!!,!!host_uuid!".$state_host_uuid."!!"); $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, 'print' => 1, level => 2, key => "job_0058", variables => { state_uuid => $state_uuid, @@ -125,6 +128,7 @@ WHERE next; } + ### NOTE: We don't need the line anymore, but we're not removing it yet. # Pull out the details. my $bad_file = ""; my $bad_line = ""; @@ -155,8 +159,8 @@ WHERE bad_line => $bad_line, }}); - $anvil->data->{job}{progress} += 5; $anvil->data->{job}{progress} = 95 if $anvil->data->{job}{progress} > 95; - update_progress($anvil, $anvil->data->{job}{progress}, "job_0049,!!line!:".$bad_line.",!!file!".$bad_file."!!,!!target!".$target."!!"); + $anvil->data->{job}{progress} += 5; + update_progress($anvil, $anvil->data->{job}{progress}, "job_0049,!!line!:".$bad_line."!!,!!file!".$bad_file."!!,!!target!".$target."!!"); $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, 'print' => 1, level => 2, key => "job_0049", variables => { line => $bad_line, file => $bad_file, @@ -166,7 +170,7 @@ WHERE # Read in the file, if it exists. if (not -e $bad_file) { - $anvil->data->{job}{progress} += 10; $anvil->data->{job}{progress} = 95 if $anvil->data->{job}{progress} > 95; + $anvil->data->{job}{progress} += 10; update_progress($anvil, $anvil->data->{job}{progress}, "job_0050,!!file!".$bad_file."!!"); $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, 'print' => 1, level => 2, key => "job_0050", variables => { file => $bad_file }}); @@ -180,7 +184,7 @@ WHERE if ($old_body eq "!!error!!") { # Failed to read the file - $anvil->data->{job}{progress} += 10; $anvil->data->{job}{progress} = 95 if $anvil->data->{job}{progress} > 95; + $anvil->data->{job}{progress} += 10; update_progress($anvil, $anvil->data->{job}{progress}, "job_0052,!!file!".$bad_file."!!"); $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, 'print' => 1, level => 2, key => "job_0052", variables => { file => $bad_file }}); @@ -201,33 +205,16 @@ WHERE 's2:bad_line' => $bad_line, 's3:line' => $line, }}); - if ($line_number eq $bad_line) + + # If the line starts with our target, remove it. + if ($line =~ /^$target /) { - # Verify that this is, indeed, the right line. - if ($line =~ /^$target /) - { - # Found it! - $anvil->data->{job}{progress} += 5; $anvil->data->{job}{progress} = 95 if $anvil->data->{job}{progress} > 95; - update_progress($anvil, $anvil->data->{job}{progress}, "job_0053"); - $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, 'print' => 1, level => 2, key => "job_0053"}); - $update = 1; - $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { update => $update }}); - } - else - { - # Line found, but not for the target. - $anvil->data->{job}{progress} += 10; $anvil->data->{job}{progress} = 95 if $anvil->data->{job}{progress} > 95; - update_progress($anvil, $anvil->data->{job}{progress}, "job_0054,!!line!".$bad_line."!!,!!file!".$bad_file."!!,!!target!".$target."!!"); - $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, 'print' => 1, level => 2, key => "job_0054", variables => { - line => $bad_line, - file => $bad_file, - target => $target, - }}); - - # Remove this job and go on to the next bad key (if any). - delete_state($anvil, $state_uuid); - last; - } + # Found it! + $anvil->data->{job}{progress} += 5; + update_progress($anvil, $anvil->data->{job}{progress}, "job_0053,!!line!".$line_number."!!"); + $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, 'print' => 1, level => 2, key => "job_0053", variables => { line => $line_number }}); + $update = 1; + $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { update => $update }}); } else { @@ -243,20 +230,33 @@ WHERE if ($update) { # Write the file out. - $anvil->data->{job}{progress} += 5; $anvil->data->{job}{progress} = 95 if $anvil->data->{job}{progress} > 95; + $anvil->data->{job}{progress} += 5; update_progress($anvil, $anvil->data->{job}{progress}, "job_0055,!!file!".$bad_file."!!"); $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, 'print' => 1, level => 2, key => "job_0055", variables => { file => $bad_file }}); + # Get the owning user and group. + my ($owning_uid, $owning_gid) = (stat($bad_file))[4,5]; + my $owning_user = getpwuid($owning_uid); + my $owning_group = getpwuid($owning_gid); + $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { + owning_uid => $owning_uid, + owning_gid => $owning_gid, + owning_user => $owning_user, + owning_group => $owning_group, + }}); + my $error = $anvil->Storage->write_file({ - body => $new_body, - debug => 2, - file => $bad_file, - overwrite => 1, + body => $new_body, + debug => 2, + file => $bad_file, + overwrite => 1, + user => $owning_user, + group => $owning_group }); $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, secure => 0, list => { error => $error }}); if ($error) { - $anvil->data->{job}{progress} += 5; $anvil->data->{job}{progress} = 95 if $anvil->data->{job}{progress} > 95; + $anvil->data->{job}{progress} += 5; update_progress($anvil, $anvil->data->{job}{progress}, "job_0059,!!file!".$bad_file."!!"); $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, 'print' => 1, level => 2, key => "job_0059", variables => { file => $bad_file }}); } @@ -264,7 +264,7 @@ WHERE { # Success! delete_state($anvil, $state_uuid); - $anvil->data->{job}{progress} += 5; $anvil->data->{job}{progress} = 95 if $anvil->data->{job}{progress} > 95; + $anvil->data->{job}{progress} += 5; update_progress($anvil, $anvil->data->{job}{progress}, "job_0060,!!file!".$bad_file."!!"); $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, 'print' => 1, level => 2, key => "job_0060", variables => { file => $bad_file }}); } @@ -375,6 +375,8 @@ sub update_progress { my ($anvil, $progress, $message) = @_; + $progress = 95 if $progress > 100; + # Log the progress percentage. $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 3, list => { progress => $progress, diff --git a/tools/striker-initialize-host b/tools/striker-initialize-host index ad08e55a..e44e34aa 100755 --- a/tools/striker-initialize-host +++ b/tools/striker-initialize-host @@ -233,7 +233,15 @@ EOF error => $error, return_code => $return_code, }}); - if ($return_code) + if ($return_code eq "70") + { + # No Internet (or can't reach the subscriion servers) + $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 2, 'print' => 1, key => "job_0032"}); + update_progress($anvil, 10, "job_0032"); + $subscribe = 0; + $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { subscribe => $subscribe }}); + } + elsif ($return_code) { # Something went wrong $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 0, 'print' => 1, key => "job_0035", variables => { @@ -592,9 +600,9 @@ sub get_job_details $anvil->data->{data}{say_target} = "root\@".$anvil->data->{data}{host_ip_address}.":".$anvil->data->{data}{ssh_port}; # Update that we've picked the job up. - $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 2, 'print' => 1, key => "job_0027,!!job-uuid!".$anvil->data->{switches}{'job-uuid'}."!!"}); + $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 2, 'print' => 1, key => "job_0027", variables => { 'job-uuid' => $anvil->data->{switches}{'job-uuid'} }}); update_progress($anvil, 0, "clear"); - update_progress($anvil, 1, "job_0027"); + update_progress($anvil, 1, "job_0027,!!job-uuid!".$anvil->data->{switches}{'job-uuid'}."!!"); return(0); }