Updated anvil-manage-keys to work from the command line

Signed-off-by: digimer <mkelly@alteeve.ca>
main
digimer 1 year ago
parent c2b86e57e1
commit d9aa8aee74
  1. 16
      Anvil/Tools/Remote.pm
  2. 33
      man/anvil-manage-keys.1
  3. 3
      share/words.xml
  4. 3
      tools/anvil-manage-dr
  5. 135
      tools/anvil-manage-keys
  6. 2
      tools/anvil-manage-server-storage

@ -489,6 +489,12 @@ sub call
foreach (my $i = 0; $i <= $last_loop; $i++) foreach (my $i = 0; $i <= $last_loop; $i++)
{ {
last if $connected; last if $connected;
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => {
's1:i' => $i,
's2:target' => $target,
's3:remote_user' => $remote_user,
's4:port' => $port,
}});
($connect_output) = capture_merged { ($connect_output) = capture_merged {
$ssh_fh = Net::OpenSSH->new($target, $ssh_fh = Net::OpenSSH->new($target,
user => $remote_user, user => $remote_user,
@ -500,12 +506,9 @@ sub call
$connect_output =~ s/\r//gs; $connect_output =~ s/\r//gs;
$connect_output =~ s/\n$//; $connect_output =~ s/\n$//;
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => {
's1:i' => $i, 's1:ssh_fh' => $ssh_fh,
's2:target' => $target, 's2:ssh_fh->error' => $ssh_fh->error,
's3:port' => $port, 's3:connect_output' => $connect_output,
's4:ssh_fh' => $ssh_fh,
's5:ssh_fh->error' => $ssh_fh->error,
's6:connect_output' => $connect_output,
}}); }});
# Any fatal issues reaching the target? # Any fatal issues reaching the target?
@ -668,7 +671,6 @@ sub call
ssh_fh_key => $ssh_fh_key, ssh_fh_key => $ssh_fh_key,
}}); }});
} }
} }
# If I have a valid handle, try to call our command now. Note that if we're using a cached connection # If I have a valid handle, try to call our command now. Note that if we're using a cached connection

@ -0,0 +1,33 @@
.\" Manpage for the Anvil! server system manager
.\" Contact mkelly@alteeve.com to report issues, concerns or suggestions.
.TH anvil-manage-keys "8" "November 13 2023" "Anvil! Intelligent Availability™ Platform"
.SH NAME
anvil-manage-keys \- Tool used to manage ssh keys
.SH SYNOPSIS
.B anvil-manage-keys
\fI\,<command> \/\fR[\fI\,options\/\fR]
.SH DESCRIPTION
anvil-manage-keys \- This tool is used remove old SSH keys from a machine that has been rebuilt.
.TP
.SH OPTIONS
.TP
\-?, \-h, \fB\-\-help\fR
Show this man page.
.TP
\fB\-\-log-secure\fR
When logging, record sensitive data, like passwords.
.TP
\-v, \-vv, \-vvv
Set the log level to 1, 2 or 3 respectively. Be aware that level 3 generates a significant amount of log data.
.SS "Commands:"
.TP
\fB\-\-confirm\fR
When called without a job-uuid, a search is made to find any bad keys. If they are found, the user is prompted to delete them. This switch assumes consent is given and the keys are removed.
.TP
\fB\-\-job\-uuid\fR
This is the jobs -> job_uuid to execute. Generally this is only used by other programs.
.IP
.SH AUTHOR
Written by Madison Kelly, Alteeve staff and the Anvil! project contributors.
.SH "REPORTING BUGS"
Report bugs to users@clusterlabs.org

@ -3223,6 +3223,9 @@ proceeding.
<key name="message_0361">- [ Note ] - The original partition table for: [#!variable!device_path!#] has been saved to: [#!variable!partition_backup!#] <key name="message_0361">- [ Note ] - The original partition table for: [#!variable!device_path!#] has been saved to: [#!variable!partition_backup!#]
If anything goes wrong, we will attempt to recover automatically. If needed, you can try If anything goes wrong, we will attempt to recover automatically. If needed, you can try
recovering with: [#!variable!restore_command!#]</key> recovering with: [#!variable!restore_command!#]</key>
<key name="message_0362">Bad SSH key target: [#!variable!target!#], file:line with the bad entry: [#!variable!file!#:#!variable!line!#].</key>
<key name="message_0363">[ Warning ] - Only proceed if you know the target has been rebuily!
- Do you want to remove these bad keys? [y/N]</key>
<!-- Translate names (protocols, etc) --> <!-- Translate names (protocols, etc) -->
<key name="name_0001">Normal Password</key> <!-- none in mail-server --> <key name="name_0001">Normal Password</key> <!-- none in mail-server -->

@ -668,6 +668,7 @@ sub sanity_check
"sys::dr_short_host_name" => $anvil->data->{sys}{dr_short_host_name}, "sys::dr_short_host_name" => $anvil->data->{sys}{dr_short_host_name},
}}); }});
### TODO: Switch to: my $target_ip = $anvil->Network->find_target_ip({});
# Can we access DR, if we're not the DR host? # Can we access DR, if we're not the DR host?
$anvil->Database->get_ip_addresses({debug => 2}); $anvil->Database->get_ip_addresses({debug => 2});
my $password = $anvil->data->{anvils}{anvil_uuid}{$anvil_uuid}{anvil_password}; my $password = $anvil->data->{anvils}{anvil_uuid}{$anvil_uuid}{anvil_password};
@ -684,7 +685,7 @@ sub sanity_check
if ((not $dr_ip) or ($dr_ip eq "!!error!!")) if ((not $dr_ip) or ($dr_ip eq "!!error!!"))
{ {
# Failed to find an IP we can access the DR host. Has it been configured? Is it running? Exiting. # Failed to find an IP we can access the DR host. Has it been configured? Is it running? Exiting.
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, 'print' => 1, level => 2, secure => 0, key => "error_0334", variables => { host_name => $dr_host_name }}); $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, 'print' => 1, level => 0, secure => 0, key => "error_0334", variables => { host_name => $dr_host_name }});
$anvil->Job->update_progress({ $anvil->Job->update_progress({
progress => 0, progress => 0,
message => "error_0334,!!host_name!".$dr_host_name."!!", message => "error_0334,!!host_name!".$dr_host_name."!!",

@ -34,12 +34,12 @@ my $anvil = Anvil::Tools->new();
# Read switches (target ([user@]host[:port]) and the file with the target's password. If the password is # Read switches (target ([user@]host[:port]) and the file with the target's password. If the password is
# passed directly, it will be used. Otherwise, the password will be read from the database. # passed directly, it will be used. Otherwise, the password will be read from the database.
$anvil->data->{switches}{'job-uuid'} = ""; $anvil->Get->switches({list => [
$anvil->Get->switches; "confirm",
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 2, secure => 0, key => "log_0115", variables => { program => $THIS_FILE }}); "job-uuid",
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { ], man => $THIS_FILE});
'switches::job-uuid' => $anvil->data->{switches}{'job-uuid'}, $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => $anvil->data->{switches}});
}}); $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 2, key => "log_0115", variables => { program => $THIS_FILE }});
$anvil->Database->connect(); $anvil->Database->connect();
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 2, secure => 0, key => "log_0132"}); $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 2, secure => 0, key => "log_0132"});
@ -329,10 +329,128 @@ sub load_job_data
{ {
my ($anvil) = @_; my ($anvil) = @_;
$anvil->data->{state_uuids} = [];
if (not $anvil->data->{switches}{'job-uuid'}) if (not $anvil->data->{switches}{'job-uuid'})
{ {
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, 'print' => 1, level => 0, priority => "err", key => "error_0080"}); # See if we can get the data from the command line switches.
$anvil->nice_exit({exit_code => 1}); my $bad_keys = 0;
my $query = "
SELECT
state_uuid,
state_name,
state_note
FROM
states
WHERE
state_name
LIKE
'host_key_changed::%'
AND
state_host_uuid = ".$anvil->Database->quote($anvil->Get->host_uuid)."
;";
# Collect from all DBs.
foreach my $uuid (keys %{$anvil->data->{cache}{database_handle}})
{
my $results = $anvil->Database->query({uuid => $uuid, query => $query, source => $THIS_FILE, line => __LINE__});
my $count = @{$results};
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => {
results => $results,
count => $count,
}});
foreach my $row (@{$results})
{
my $state_uuid = $row->[0];
my $state_name = $row->[1];
my $state_note = $row->[2];
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => {
's1:state_uuid' => $state_uuid,
's2:state_name' => $state_name,
's2:state_note' => $state_note,
}});
my $bad_file = "";
my $bad_line = "";
foreach my $pair (split/,/, $state_note)
{
my ($variable, $value) = ($pair =~ /^(.*?)=(.*)$/);
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => {
pair => $pair,
variable => $variable,
value => $value,
}});
if ($variable eq "file")
{
$bad_file = $value;
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { bad_file => $bad_file }});
}
if ($variable eq "line")
{
$bad_line = $value;
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { bad_line => $bad_line }});
}
}
$bad_keys++;
my ($target) = ($state_name =~ /host_key_changed::(.*)$/);
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => {
bad_keys => $bad_keys,
target => $target,
bad_file => $bad_file,
bad_line => $bad_line,
}});
$anvil->data->{bad_keys}{$target}{$bad_file}{$bad_line}{$state_uuid} = 1;
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => {
"bad_keys::${target}::${bad_file}::${bad_line}" => $anvil->data->{bad_keys}{$target}{$bad_file}{$bad_line},
}});
}
}
foreach my $target (sort {$a cmp $b} keys %{$anvil->data->{bad_keys}})
{
foreach my $bad_file (sort {$a cmp $b} keys %{$anvil->data->{bad_keys}{$target}})
{
foreach my $bad_line (sort {$a cmp $b} keys %{$anvil->data->{bad_keys}{$target}{$bad_file}})
{
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, 'print' => 1, level => 0, key => "message_0362", variables => {
target => $target,
file => $bad_file,
line => $bad_line,
}});
foreach my $state_uuid (sort {$a cmp $b} keys %{$anvil->data->{bad_keys}{$target}{$bad_file}{$bad_line}})
{
push @{$anvil->data->{state_uuids}}, $state_uuid;
}
}
}
}
# Ask the user to confirm?
if ($anvil->data->{switches}{confirm})
{
# No.
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, 'print' => 1, level => 0, key => "message_0359"});
return(0);
}
# Ask the user to confirm.
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, 'print' => 1, level => 0, key => "message_0363"});
my $answer = <STDIN>;
chomp $answer;
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 0, key => "log_0828", variables => { answer => $answer }});
if ((lc($answer) eq "y") or (lc($answer) eq "yes"))
{
# Proceed.
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, 'print' => 1, level => 0, key => "message_0175"});
return(0);
}
else
{
# Abort.
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, 'print' => 1, level => 0, key => "message_0022"});
$anvil->nice_exit({exit_code => 0});
}
} }
my $query = "SELECT job_data FROM jobs WHERE job_uuid = ".$anvil->Database->quote($anvil->data->{switches}{'job-uuid'}).";"; my $query = "SELECT job_data FROM jobs WHERE job_uuid = ".$anvil->Database->quote($anvil->data->{switches}{'job-uuid'}).";";
@ -372,7 +490,6 @@ sub load_job_data
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, 'print' => 1, level => 2, key => "job_0048"}); $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, 'print' => 1, level => 2, key => "job_0048"});
# Break the job up. # Break the job up.
$anvil->data->{state_uuids} = [];
foreach my $state_uuid (split/,/, $job_data) foreach my $state_uuid (split/,/, $job_data)
{ {
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { state_uuid => $state_uuid }}); $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { state_uuid => $state_uuid }});

@ -41,7 +41,7 @@ $| = 1;
my $anvil = Anvil::Tools->new(); my $anvil = Anvil::Tools->new();
# Read switches (target ([user@]host[:port]) and the file with the target's password. # Read switches
$anvil->Get->switches({list => [ $anvil->Get->switches({list => [
"add", "add",
"anvil", "anvil",

Loading…
Cancel
Save