From a6cd5c6604a35a6732b9603c13b985e498e3fbc1 Mon Sep 17 00:00:00 2001 From: Digimer Date: Fri, 28 Oct 2022 20:00:53 -0400 Subject: [PATCH] * Starting work in the new anvil-manage-alerts, which will (when done), allow for management of mail servers, alert recipients, notification over-rides and to trigger test alerts. * Updated Database->get_recipients() to record recipients by name for better sorting. Signed-off-by: Digimer --- Anvil/Tools/Database.pm | 2 + man/anvil-manage-alerts.8 | 142 +++++++++ share/words.xml | 12 + tools/anvil-manage-alerts | 634 ++++++++++++++++++++++++++++++++++++++ 4 files changed, 790 insertions(+) create mode 100644 man/anvil-manage-alerts.8 create mode 100755 tools/anvil-manage-alerts diff --git a/Anvil/Tools/Database.pm b/Anvil/Tools/Database.pm index 6d10b887..f33e3d19 100644 --- a/Anvil/Tools/Database.pm +++ b/Anvil/Tools/Database.pm @@ -4632,8 +4632,10 @@ WHERE # Make it easy to look up the mail server's UUID from the server address. $anvil->data->{recipients}{email_to_uuid}{$recipient_email} = $recipient_uuid; + $anvil->data->{recipients}{name_to_uuid}{$recipient_name} = $recipient_uuid; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { "recipients::email_to_uuid::${recipient_email}" => $anvil->data->{recipients}{email_to_uuid}{$recipient_email}, + "recipients::name_to_uuid::${recipient_name}" => $anvil->data->{recipients}{email_to_uuid}{$recipient_name}, }}); # If there is an override for a given recipient on this host, mark it as such. diff --git a/man/anvil-manage-alerts.8 b/man/anvil-manage-alerts.8 new file mode 100644 index 00000000..c0a2c764 --- /dev/null +++ b/man/anvil-manage-alerts.8 @@ -0,0 +1,142 @@ +.\" Manpage for the Anvil! server removal tool +.\" Contact mkelly@alteeve.com to report issues, concerns or suggestions. +.TH anvil-manage-alerts "8" "October 26 2022" "Anvil! Intelligent Availability™ Platform" +.SH NAME +anvil-manage-alerts \- This program manages alerts; Email servers, recipients, notification overrides, and generating test alerts. +.SH SYNOPSIS +.B anvil-manage-alerts +\fI\, \/\fR +.SH DESCRIPTION +The program allows you to add, edit and delete email servers, alert recipients, and notification overrides. You can also use it to generate a test alert. +If run without any switches, the list of mail servers and recipients are returned. + +When called without any switches, the list of currect mail servers, alert recipients and notification overrides are shown, along with all known hosts. +.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\-\-add\fR +This is used to add a new mail server or alert recipient. +.TP +\fB\-\-edit\fR +This is used to edit and existing mail server or alert recipient. + +NOTE: All fields are required when editing an existing mail server or recipient! +.TP +\fB\-\-delete\fR +This deletes an existing mail server or alert recipient. +.TP +\fB\-\-mail-servers\fR +This is used to manage mail servers. Specifically, this control the mail server that we send alert emails to. The options used with this are; +.TP +\fB\-\-mail-server-uuid\fR +This is required for \fB\-\-edit\fR and \fB\-\-delete\fR. It is the existing mail server being worked on. +.TP +\fB\-\-mail-server-address\fR +This is the URL or IP address of the mail server we're logging into to send email. + +Example: mail.example.com +.TP +\fB\-\-mail-server-port\fR +This is the TCP port used when connecting to the target mail server. + +Example: 587 +.TP +\fB\-\-mail-server-username\fR +This is the mail server user name (usually an email address) used when authenticating against the mail server. + +Example: admin@example.com +.TP +\fB\-\-mail-server-password\fR +This is the password used along with \fB\-\-mail-server-username\fR when authenticating against the mail server. Not all mail servers require a password, so this is optional. +.TP +\fB\-\-mail-server-security\fR +This is the security type used when authenticating against the mail server. + +Valid values are: 'none', 'starttls' or 'tls-ssl'. +.TP +\fB\-\-mail-server-authentication\fR +This is how passwords are passed to the mail server. + +Valid values are: 'none', 'plain-text', or 'encrypted' +.TP +\fB\-\-mail-server-helo-domain\fR +This is the 'HELO' domain name used when communicating with the mail server. This is the domain we're telling the mail server that the email is coming from. You can use your domain, or the domain of the host. + +Example: example.com + +See: https://www.ibm.com/docs/en/zos/2.2.0?topic=sc-helo-command-identify-domain-name-sending-host-smtp +.TP +\fB\-\-notifications\fR +This is where an alert recipient can have notification overrides. Typically this is used so that a given user can ignore alerts from a specific Anvil! node pair. +.TP +\fB\-\-notification-uuid\fR +This is required for \fB\-\-edit\fR and \fB\-\-delete\fR. It is the existing notification override being worked on. +.TP +\fB\-\-notification-recipient-uuid\fR +This is the recipients -> recipient_uuid who we are creating the override for. +.TP +\fB\-\-notification-host-uuid\fR +This is the hosts -> host_uuid of the machine that you are creating the alert +.TP +\fB\-\-notification-alert-level\fR <1, 2, 3 or 4> +This is the desired override alert level. + +Valid values are: + +1 = "critical" alerts only + +2 = "warning" and critical alerts + +3 = "notice", warning and critical alerts + +4 = "info"; All alerts. This generates almost constant alerts! +.TP +\fB\-\-recipients\fR +This is used to manage alert recipients. Specifically, this control the mail server that we send alert emails to. The options used with this are; +.TP +\fB\-\-recipient-uuid\fR +This is required for \fB\-\-edit\fR and \fB\-\-delete\fR. It is the existing alert recipient is being worked on. +.TP +\fB\-\-recipient-name\fR +This is the name of the person receiving the alerts. This is used in the email header. + +Example: Austin Powers +.TP +\fB\-\-recipient-email\fR +This is the email address for the alert recipient. + +Example: notaspy@example.com +.TP +\fB\-\-recipient-language\fR +In the future, languages will be added and this can be used to indicate what language the user will receive their alerts in. At the time of writing this man page, only 'en_CA' is supported. +.TP +\fB\-\-recipient-level\fR <1, 2, 3 or 4> +This is the default alert level this recipient is interested in. It can be adjusted on a per-host basis via the 'notifications' over-rides. + +Valid values are: + +1 = "critical" alerts only + +2 = "warning" and critical alerts + +3 = "notice", warning and critical alerts + +4 = "info"; All alerts. This generates almost constant alerts! +.TP +.SH AUTHOR +Written by Madison Kelly, Alteeve staff and the Anvil! project contributors. +.SH "REPORTING BUGS" +Report bugs to users@clusterlabs.org + + +", "download", "everywhere", "file", "is-script", "job-uuid", "rename", "to \ No newline at end of file diff --git a/share/words.xml b/share/words.xml index 71a0f0a0..9d9b7661 100644 --- a/share/words.xml +++ b/share/words.xml @@ -534,6 +534,18 @@ The definition data passed in was: [ Error ] - The '--type' must be 'host' or 'dr'. Was given: [#!variable!type!#]. [ Error ] - The UUID: [#!variable!uuid!#] is not a valid UUID. [ Error ] - Neither '--host-ip-address' or '--target' were used to define who we are trying to connect to. + [ Error ] - The UUID: [#!variable!uuid!#] passed in by the switch: [#!variable!switch!#] appears to be invalid. + [ Error ] - The domain or IP: [#!variable!name!#] passed in by the switch: [#!variable!switch!#] appears to be invalid. + [ Error ] - The alert level: [#!variable!level!#] passed in by the switch: [#!variable!switch!#] appears to be invalid. Valid values are '1', '2', '3' or '4'. These represent; +1 = "critical" alerts only +2 = "warning" and critical alerts +3 = "notice", warning and critical alerts +4 = "info"; All alerts. This generates almost constant alerts! + + [ Error ] - The TCP port: [#!variable!port!#] passed in by the switch: [#!variable!switch!#] appears to be invalid. TCP ports must be integers between 1 and 65535. + [ Error ] - The mail server security: [#!variable!security!#] appears to be invalid. Valid options are 'none', 'starttls' or 'tls-ssl'. + [ Error ] - The mail server authentication: [#!variable!auth!#] appears to be invalid. Valid options are 'none', 'plain-text', or 'encrypted'. + [ Error ] - The email address: [#!variable!email!#] appears to be invalid. diff --git a/tools/anvil-manage-alerts b/tools/anvil-manage-alerts new file mode 100755 index 00000000..657f181c --- /dev/null +++ b/tools/anvil-manage-alerts @@ -0,0 +1,634 @@ +#!/usr/bin/perl + +use strict; +use warnings; +use Anvil::Tools; +use Data::Dumper; +use Text::Diff; + +$| = 1; + +my $THIS_FILE = ($0 =~ /^.*\/(.*)$/)[0]; +my $running_directory = ($0 =~ /^(.*?)\/$THIS_FILE$/)[0]; +if (($running_directory =~ /^\./) && ($ENV{PWD})) +{ + $running_directory =~ s/^\./$ENV{PWD}/; +} + +my $anvil = Anvil::Tools->new(); + +# Get a list of all interfaces with IP addresses. +$anvil->Get->switches({list => [ + "add", + "edit", + "delete", + "mail-servers", + "mail-server-uuid", + "mail-server-address", + "mail-server-port", + "mail-server-username", + "mail-server-password", + "mail-server-security", + "mail-server-authentication", + "mail-server-helo-domain", + "notifications", + "notification-uuid", + "notification-recipient-uuid", + "notification-host-uuid", + "notification-alert-level", + "recipients", + "recipient-uuid", + "recipient-name", + "recipient-email", + "recipient-language", + "recipient-level", +]}); +$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => $anvil->data->{switches}}); + +$anvil->Database->connect(); +$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 2, secure => 0, key => "log_0132" }); +if (not $anvil->data->{sys}{database}{connections}) +{ + # No databases, exit. + $anvil->Log->entry({ source => $THIS_FILE, line => __LINE__, level => 0, 'print' => 1, priority => "err", key => "error_0003" }); + $anvil->nice_exit({ exit_code => 1 }); +} + +check_switches($anvil); + +if ($anvil->data->{switches}{"mail-servers"}) +{ + handle_mail_servers($anvil); +} +elsif ($anvil->data->{switches}{"notifications"}) +{ + handle_notifications($anvil); +} +elsif ($anvil->data->{switches}{"recipients"}) +{ + handle_recipients($anvil); +} +else +{ + show_existing($anvil); +} + +$anvil->nice_exit({exit_code => 0}); + + +############################################################################################################# +# Functions # +############################################################################################################# + +sub recipients +{ + my ($anvil) = @_; + + + + return(0); +} + +sub handle_mail_servers +{ + my ($anvil) = @_; + + + + return(0); +} + +sub handle_notifications +{ + my ($anvil) = @_; + + + + return(0); +} + +# Show existing mail servers. +sub show_existing +{ + my ($anvil) = @_; + + # Show mail servers + $anvil->data->{longest}{mail_server_address} = 0; + $anvil->data->{longest}{mail_server_port} = 0; + $anvil->data->{longest}{mail_server_username} = 0; + $anvil->data->{longest}{mail_server_password} = 0; + $anvil->data->{longest}{mail_server_security} = 0; + $anvil->data->{longest}{mail_server_authentication} = 0; + $anvil->data->{longest}{mail_server_helo_domain} = 0; + $anvil->data->{longest}{notification_recipient_name} = 0; + $anvil->data->{longest}{notification_host_name} = 0; + $anvil->data->{longest}{notification_anvil_name} = 0; + $anvil->data->{longest}{notification_alert_level} = 0; + $anvil->data->{longest}{recipient_name} = 0; + $anvil->data->{longest}{recipient_email} = 0; + $anvil->data->{longest}{recipient_language} = 0; + $anvil->data->{longest}{recipient_alert_level} = 0; + + $anvil->data->{say_alert}{1} = "1 (".$anvil->Words->string({key => "unit_0024"}).")"; + $anvil->data->{say_alert}{2} = "2 (".$anvil->Words->string({key => "unit_0025"}).")"; + $anvil->data->{say_alert}{3} = "3 (".$anvil->Words->string({key => "unit_0026"}).")"; + $anvil->data->{say_alert}{4} = "4 (".$anvil->Words->string({key => "unit_0027"}).")"; + $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { + 'say_alert::1' => $anvil->data->{say_alert}{1}, + 'say_alert::2' => $anvil->data->{say_alert}{2}, + 'say_alert::3' => $anvil->data->{say_alert}{3}, + 'say_alert::4' => $anvil->data->{say_alert}{4}, + }}); + + # Get longest counts. + foreach my $mail_server_address (sort {$a cmp $b} keys %{$anvil->data->{mail_servers}{address_to_uuid}}) + { + my $mail_server_uuid = $anvil->data->{mail_servers}{address_to_uuid}{$mail_server_address}; + my $mail_server_port = $anvil->data->{mail_servers}{mail_server}{$mail_server_uuid}{mail_server_port}; + my $mail_server_username = $anvil->data->{mail_servers}{mail_server}{$mail_server_uuid}{mail_server_username}; + my $mail_server_password = $anvil->data->{mail_servers}{mail_server}{$mail_server_uuid}{mail_server_password}; + my $mail_server_security = $anvil->data->{mail_servers}{mail_server}{$mail_server_uuid}{mail_server_security}; + my $mail_server_authentication = $anvil->data->{mail_servers}{mail_server}{$mail_server_uuid}{mail_server_authentication}; + my $mail_server_helo_domain = $anvil->data->{mail_servers}{mail_server}{$mail_server_uuid}{mail_server_helo_domain}; + $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { + 's1:mail_server_address' => $mail_server_address, + 's2:mail_server_uuid' => $mail_server_uuid, + 's3:mail_server_port' => $mail_server_port, + 's4:mail_server_username' => $mail_server_username, + 's5:mail_server_password' => $anvil->Log->is_secure($mail_server_password), + 's6:mail_server_security' => $mail_server_security, + 's7:mail_server_authentication' => $mail_server_authentication, + 's8:mail_server_helo_domain' => $mail_server_helo_domain, + }}); + + if (length($mail_server_address) > $anvil->data->{longest}{mail_server_address}) + { + $anvil->data->{longest}{mail_server_address} = length($mail_server_address); + $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { + 'longest::mail_server_address' => $anvil->data->{longest}{mail_server_address}, + }}); + } + + if (length($mail_server_port) > $anvil->data->{longest}{mail_server_port}) + { + $anvil->data->{longest}{mail_server_port} = length($mail_server_port); + $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { + 'longest::mail_server_port' => $anvil->data->{longest}{mail_server_port}, + }}); + } + + if (length($mail_server_username) > $anvil->data->{longest}{mail_server_username}) + { + $anvil->data->{longest}{mail_server_username} = length($mail_server_username); + $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { + 'longest::mail_server_username' => $anvil->data->{longest}{mail_server_username}, + }}); + } + + if (length($mail_server_password) > $anvil->data->{longest}{mail_server_password}) + { + $anvil->data->{longest}{mail_server_password} = length($mail_server_password); + $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { + 'longest::mail_server_password' => $anvil->data->{longest}{mail_server_password}, + }}); + } + + if (length($mail_server_security) > $anvil->data->{longest}{mail_server_security}) + { + $anvil->data->{longest}{mail_server_security} = length($mail_server_security); + $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { + 'longest::mail_server_security' => $anvil->data->{longest}{mail_server_security}, + }}); + } + + if (length($mail_server_authentication) > $anvil->data->{longest}{mail_server_authentication}) + { + $anvil->data->{longest}{mail_server_authentication} = length($mail_server_authentication); + $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { + 'longest::mail_server_authentication' => $anvil->data->{longest}{mail_server_authentication}, + }}); + } + + if (length($mail_server_helo_domain) > $anvil->data->{longest}{mail_server_helo_domain}) + { + $anvil->data->{longest}{mail_server_helo_domain} = length($mail_server_helo_domain); + $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { + 'longest::mail_server_helo_domain' => $anvil->data->{longest}{mail_server_helo_domain}, + }}); + } + } + + foreach my $notification_uuid (sort {$a cmp $b} keys %{$anvil->data->{notifications}{notification_uuid}}) + { + my $notification_recipient_uuid = $anvil->data->{notifications}{notification_uuid}{$notification_uuid}{notification_recipient_uuid}; + my $notification_recipient_name = $anvil->data->{recipients}{recipient_uuid}{$notification_recipient_uuid}{recipient_name}; + my $notification_recipient_email = $anvil->data->{recipients}{recipient_uuid}{$notification_recipient_uuid}{recipient_email}; + my $say_recipient = $notification_recipient_name." <".$notification_recipient_email.">"; + my $notification_host_uuid = $anvil->data->{notifications}{notification_uuid}{$notification_uuid}{notification_host_uuid}; + my $notification_short_host_name = $anvil->data->{hosts}{host_uuid}{$notification_host_uuid}{short_host_name}; + my $say_anvil_name = $anvil->data->{hosts}{host_uuid}{$notification_host_uuid}{anvil_name} ? $anvil->data->{hosts}{host_uuid}{$notification_host_uuid}{anvil_name} : "--"; + my $notification_alert_level = $anvil->data->{notifications}{notification_uuid}{$notification_uuid}{notification_alert_level}; + $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { + 's1:notification_uuid' => $notification_uuid, + 's2:notification_recipient_uuid' => $notification_recipient_uuid, + 's3:notification_recipient_name' => $notification_recipient_name, + 's4:notification_recipient_email' => $notification_recipient_email, + 's5:say_recipient' => $say_recipient, + 's6:notification_host_uuid' => $notification_host_uuid, + 's7:notification_short_host_name' => $notification_short_host_name, + 's8:say_anvil_name' => $say_anvil_name, + 's9:notification_alert_level' => $notification_alert_level, + }}); + + if (length($say_recipient) > $anvil->data->{longest}{notification_recipient_name}) + { + $anvil->data->{longest}{notification_recipient_name} = length($say_recipient); + $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { + 'longest::notification_recipient_name' => $anvil->data->{longest}{notification_recipient_name}, + }}); + } + + if (length($notification_short_host_name) > $anvil->data->{longest}{notification_host_name}) + { + $anvil->data->{longest}{notification_host_name} = length($notification_short_host_name); + $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { + 'longest::notification_host_name' => $anvil->data->{longest}{notification_host_name}, + }}); + } + + if (length($say_anvil_name) > $anvil->data->{longest}{notification_anvil_name}) + { + $anvil->data->{longest}{notification_anvil_name} = length($say_anvil_name); + $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { + 'longest::notification_anvil_name' => $anvil->data->{longest}{notification_anvil_name}, + }}); + } + + if (length($anvil->data->{say_alert}{$notification_alert_level}) > $anvil->data->{longest}{notification_alert_level}) + { + $anvil->data->{longest}{notification_alert_level} = length($anvil->data->{say_alert}{$notification_alert_level}); + $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { + 'longest::notification_alert_level' => $anvil->data->{longest}{notification_alert_level}, + }}); + } + + # This will let us display over-rides by user in order. + $anvil->data->{notifications}{name_to_uuid}{$notification_recipient_name} = $notification_uuid; + $anvil->data->{notifications}{notification_uuid}{$notification_uuid}{recipient_name} = $say_recipient; + $anvil->data->{notifications}{notification_uuid}{$notification_uuid}{anvil_name} = $say_anvil_name; + $anvil->data->{notifications}{notification_uuid}{$notification_uuid}{host_uuid} = $notification_host_uuid; + $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { + "s1:notifications::name_to_uuid::${notification_recipient_name}" => $anvil->data->{notifications}{name_to_uuid}{$notification_recipient_name}, + "s2:notifications::notification_uuid::${notification_uuid}::recipient_name" => $anvil->data->{notifications}{notification_uuid}{$notification_uuid}{recipient_name}, + "s3:notifications::notification_uuid::${notification_uuid}::anvil_name" => $anvil->data->{notifications}{notification_uuid}{$notification_uuid}{anvil_name}, + "s4:notifications::notification_uuid::${notification_uuid}::host_uuid" => $anvil->data->{notifications}{notification_uuid}{$notification_uuid}{host_uuid}, + }}); + } + + foreach my $recipient_name (sort {$a cmp $b} keys %{$anvil->data->{recipients}{name_to_uuid}}) + { + my $recipient_uuid = $anvil->data->{recipients}{name_to_uuid}{$recipient_name}; + my $recipient_email = $anvil->data->{recipients}{recipient_uuid}{$recipient_uuid}{recipient_email}; + my $recipient_language = $anvil->data->{recipients}{recipient_uuid}{$recipient_uuid}{recipient_language}; + my $say_language = $anvil->data->{sys}{languages}{$recipient_language}; + my $recipient_level = $anvil->data->{recipients}{recipient_uuid}{$recipient_uuid}{recipient_level}; + $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { + "s1:recipient_name" => $recipient_name, + "s2:recipient_uuid" => $recipient_uuid, + "s3:recipient_email" => $recipient_email, + "s4:recipient_language" => $recipient_language, + "s5:say_language" => $say_language, + "s6:recipient_level" => $recipient_level, + }}); + + if (length($recipient_name) > $anvil->data->{longest}{recipient_name}) + { + $anvil->data->{longest}{recipient_name} = length($recipient_name); + $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { + 'longest::recipient_name' => $anvil->data->{longest}{recipient_name}, + }}); + } + + if (length($recipient_email) > $anvil->data->{longest}{recipient_email}) + { + $anvil->data->{longest}{recipient_email} = length($recipient_email); + $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { + 'longest::recipient_email' => $anvil->data->{longest}{recipient_email}, + }}); + } + + if (length($say_language) > $anvil->data->{longest}{recipient_language}) + { + $anvil->data->{longest}{recipient_language} = length($say_language); + $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { + 'longest::recipient_language' => $anvil->data->{longest}{recipient_language}, + }}); + } + + if (length($anvil->data->{say_alert}{$recipient_level}) > $anvil->data->{longest}{recipient_alert_level}) + { + $anvil->data->{longest}{recipient_alert_level} = length($anvil->data->{say_alert}{$recipient_level}); + $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { + 'longest::recipient_alert_level' => $anvil->data->{longest}{recipient_alert_level}, + }}); + } + } + + # Now show the data. +# my $break_line = "+-".sprintf("%0${longest_anvil_name}d", 0); +# my $header_line = "| ".sprintf("%-${longest_anvil_name}s", $anvil_header)." "; +# my $blank_lead = "| ".sprintf("%-${longest_anvil_name}s", $anvil_header)." "; + print "-=] Mail Servers;\n"; + print "Address, Port, Login User, Password, Security, Authentication, HELO Domaon, Mail Server UUID\n"; + my $mail_servers = 0; + foreach my $mail_server_address (sort {$a cmp $b} keys %{$anvil->data->{mail_servers}{address_to_uuid}}) + { + my $mail_server_uuid = $anvil->data->{mail_servers}{address_to_uuid}{$mail_server_address}; + my $mail_server_port = $anvil->data->{mail_servers}{mail_server}{$mail_server_uuid}{mail_server_port}; + my $mail_server_username = $anvil->data->{mail_servers}{mail_server}{$mail_server_uuid}{mail_server_username}; + my $mail_server_password = $anvil->data->{mail_servers}{mail_server}{$mail_server_uuid}{mail_server_password}; + my $mail_server_security = $anvil->data->{mail_servers}{mail_server}{$mail_server_uuid}{mail_server_security}; + my $mail_server_authentication = $anvil->data->{mail_servers}{mail_server}{$mail_server_uuid}{mail_server_authentication}; + my $mail_server_helo_domain = $anvil->data->{mail_servers}{mail_server}{$mail_server_uuid}{mail_server_helo_domain}; + $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { + 's1:mail_server_address' => $mail_server_address, + 's2:mail_server_uuid' => $mail_server_uuid, + 's3:mail_server_port' => $mail_server_port, + 's4:mail_server_username' => $mail_server_username, + 's5:mail_server_password' => $anvil->Log->is_secure($mail_server_password), + 's6:mail_server_security' => $mail_server_security, + 's7:mail_server_authentication' => $mail_server_authentication, + 's8:mail_server_helo_domain' => $mail_server_helo_domain, + }}); + + print $mail_server_address.", ".$mail_server_port.", ".$mail_server_username.", ".$mail_server_password.", ".$mail_server_security.", ".$mail_server_authentication.", ".$mail_server_helo_domain.", ".$mail_server_uuid."\n"; + $mail_servers++; + } + if (not $mail_servers) + { + print "No mail servers configured yet!\n"; + } + print "\n"; + print "-=] Recipients;\n"; + print "Name, Email, Alert Level, Language, Recipient UUID\n"; + my $recipients = 0; + foreach my $recipient_name (sort {$a cmp $b} keys %{$anvil->data->{recipients}{name_to_uuid}}) + { + my $recipient_uuid = $anvil->data->{recipients}{name_to_uuid}{$recipient_name}; + my $recipient_email = $anvil->data->{recipients}{recipient_uuid}{$recipient_uuid}{recipient_email}; + my $recipient_language = $anvil->data->{recipients}{recipient_uuid}{$recipient_uuid}{recipient_language}; + my $say_language = $anvil->data->{sys}{languages}{$recipient_language}; + my $recipient_level = $anvil->data->{recipients}{recipient_uuid}{$recipient_uuid}{recipient_level}; + $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { + "s1:recipient_name" => $recipient_name, + "s2:recipient_uuid" => $recipient_uuid, + "s3:recipient_email" => $recipient_email, + "s4:recipient_language" => $recipient_language, + "s5:say_language" => $say_language, + "s6:recipient_level" => $recipient_level, + }}); + + print $recipient_name.", ".$recipient_email.", ".$anvil->data->{say_alert}{$recipient_level}.", ".$say_language.", ".$recipient_uuid."\n"; + $recipients++; + } + if (not $recipients) + { + print "No alert recipients added yet!\n"; + } + + print "\n"; + print "-=] Notification Over-rides;\n"; + print "Recipient, Host, Anvil!, Alert Level, Notification UUID\n"; + my $notifications = 0; + foreach my $recipient_name (sort {$a cmp $b} keys %{$anvil->data->{notifications}{name_to_uuid}}) + { + my $notification_uuid = $anvil->data->{notifications}{name_to_uuid}{$recipient_name}; + my $say_recipient = $anvil->data->{notifications}{notification_uuid}{$notification_uuid}{recipient_name}; + my $say_anvil_name = $anvil->data->{notifications}{notification_uuid}{$notification_uuid}{anvil_name}; + my $host_uuid = $anvil->data->{notifications}{notification_uuid}{$notification_uuid}{notification_host_uuid}; + my $short_host_name = $anvil->data->{hosts}{host_uuid}{$host_uuid}{short_host_name}; + my $alert_level = $anvil->data->{notifications}{notification_uuid}{$notification_uuid}{notification_alert_level}; + $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { + 's1:notification_uuid' => $notification_uuid, + 's2:say_recipient' => $say_recipient, + 's3:say_anvil_name' => $say_anvil_name, + 's4:alert_level' => $alert_level, + }}); + + print $say_recipient.", ".$short_host_name.", ".$say_anvil_name.", ".$anvil->data->{say_alert}{$alert_level}.", ".$notification_uuid."\n"; + $notifications++; + } + if (not $notifications) + { + print "No notification over-rides found.\n"; + } + + # Lastly, show machines. + print "\n"; + print "-=] Striker Dashboards;\n"; + foreach my $host_name (sort {$a cmp $b} keys %{$anvil->data->{sys}{hosts}{by_name}}) + { + my $host_uuid = $anvil->data->{sys}{hosts}{by_name}{$host_name}; + my $host_type = $anvil->data->{hosts}{host_uuid}{$host_uuid}{host_type}; + next if $host_type ne "striker"; + $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { + 's1:host_name' => $host_name, + 's2:host_uuid' => $host_uuid, + }}); + + print "- ".$host_name.", UUID: [".$host_uuid."]\n"; + } + print "\n"; + print "-=] Anvil! Nodes;\n"; + foreach my $anvil_name (sort {$a cmp $b} keys %{$anvil->data->{anvils}{anvil_name}}) + { + my $anvil_uuid = $anvil->data->{anvils}{anvil_name}{$anvil_name}{anvil_uuid}; + my $anvil_description = $anvil->data->{anvils}{anvil_name}{$anvil_name}{anvil_description}; + my $anvil_node1_host_uuid = $anvil->data->{anvils}{anvil_name}{$anvil_name}{anvil_node1_host_uuid}; + my $anvil_node2_host_uuid = $anvil->data->{anvils}{anvil_name}{$anvil_name}{anvil_node2_host_uuid}; + my $anvil_dr1_host_uuid = $anvil->data->{anvils}{anvil_name}{$anvil_name}{anvil_dr1_host_uuid}; + my $say_dr1_name = $anvil_dr1_host_uuid ? $anvil->data->{hosts}{host_uuid}{$anvil_dr1_host_uuid}{short_host_name} : "--"; + my $say_dr1_uuid = $anvil_dr1_host_uuid ? $anvil_dr1_host_uuid : "--"; + print "- Name: [".$anvil_name."], UUID: [".$anvil_uuid."], Description: [".$anvil_uuid."]\n"; + print " - Node 1: .. [".$anvil->data->{hosts}{host_uuid}{$anvil_node1_host_uuid}{short_host_name}."], UUID: [".$anvil_node1_host_uuid."]\n"; + print " - Node 2: .. [".$anvil->data->{hosts}{host_uuid}{$anvil_node2_host_uuid}{short_host_name}."], UUID: [".$anvil_node2_host_uuid."]\n"; + print " - DR Host 1: [".$say_dr1_name."], UUID: [".$say_dr1_uuid."]\n"; + } + + return(0); +} + +# This sanity checks input switches. By necessity, this also loads data from the database. +sub check_switches +{ + my ($anvil) = @_; + + # Load data + $anvil->Database->get_hosts(); + $anvil->Database->get_anvils(); + $anvil->Database->get_mail_servers(); + $anvil->Database->get_recipients(); + $anvil->Database->get_notifications(); + $anvil->Words->language_list(); + + ### Now sanity check + my $problem = 0; + + # Validate UUIDs. + foreach my $switch ("mail-server-uuid", "notification-uuid", "recipient-uuid", "notification-recipient-uuid", "notification-host-uuid") + { + $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { switch => $switch }}); + if (($anvil->data->{switches}{$switch}) && (not $anvil->Validate->uuid({uuid => $anvil->data->{switches}{$switch}}))) + { + # Invalid UUID. + $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 2, key => "error_0380", variables => { + uuid => $anvil->data->{switches}{$switch}, + switch => "--".$switch, + }}); + + $problem = 1; + $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { problem => $problem }}); + } + } + + # Validate domain or IP data. + foreach my $switch ("mail-server-address", "mail-server-helo-domain") + { + $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { switch => $switch }}); + if ($anvil->data->{switches}{$switch}) + { + # Make sure it's a domain or IP address. + if ((not $anvil->Validate->domain_name({name => $anvil->data->{switches}{$switch}})) && (not $anvil->Validate->ip({ip => $anvil->data->{switches}{$switch}}))) + { + $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 2, key => "error_0381", variables => { + name => $anvil->data->{switches}{$switch}, + switch => "--".$switch, + }}); + + $problem = 1; + $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { problem => $problem }}); + } + } + } + + # Check log levels. + foreach my $switch ("notification-alert-level", "recipient-level") + { + $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { switch => $switch }}); + if ($anvil->data->{switches}{$switch}) + { + # If they used a level name, convert it to a number. + # 1 = "critical" alerts only + # 2 = "warning" and critical alerts + # 3 = "notice", warning and critical alerts + # 4 = "info"; All alerts. This generates almost constant alerts! + if ($anvil->data->{switches}{$switch} eq "critical") + { + $anvil->data->{switches}{$switch} = 1; + $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { "switches::".$switch => $anvil->data->{switches}{$switch} }}); + } + elsif ($anvil->data->{switches}{$switch} eq "warning") + { + $anvil->data->{switches}{$switch} = 2; + $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { "switches::".$switch => $anvil->data->{switches}{$switch} }}); + } + elsif ($anvil->data->{switches}{$switch} eq "notice") + { + $anvil->data->{switches}{$switch} = 3; + $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { "switches::".$switch => $anvil->data->{switches}{$switch} }}); + } + elsif ($anvil->data->{switches}{$switch} eq "info") + { + $anvil->data->{switches}{$switch} = 4; + $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { "switches::".$switch => $anvil->data->{switches}{$switch} }}); + } + + if (($anvil->data->{switches}{$switch} =~ /\D/) or + ($anvil->data->{switches}{$switch} < 1) or + ($anvil->data->{switches}{$switch} > 4)) + { + $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 2, key => "error_0382", variables => { + level => $anvil->data->{switches}{$switch}, + switch => "--".$switch, + }}); + + $problem = 1; + $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { problem => $problem }}); + } + } + } + + # Ports (there's only one) + if ($anvil->data->{switches}{"mail-server-port"}) + { + # Make sure it's a valid port. + if (($anvil->data->{switches}{"mail-server-port"} =~ /\D/) or + ($anvil->data->{switches}{"mail-server-port"} < 1) or + ($anvil->data->{switches}{"mail-server-port"} > 65535)) + { + $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 2, key => "error_0383", variables => { + port => $anvil->data->{switches}{"mail-server-port"}, + switch => "--mail-server-port", + }}); + + $problem = 1; + $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { problem => $problem }}); + } + } + + # Make sure mail server security is correct. + if ($anvil->data->{switches}{"mail-server-security"}) + { + $anvil->data->{switches}{"mail-server-security"} = lc($anvil->data->{switches}{"mail-server-security"}); + if (($anvil->data->{switches}{"mail-server-security"} ne "none") && + ($anvil->data->{switches}{"mail-server-security"} ne "starttls") && + ($anvil->data->{switches}{"mail-server-security"} ne "tls-ssl")) + { + $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 2, key => "error_0384", variables => { + security => $anvil->data->{switches}{"mail-server-security"}, + }}); + + $problem = 1; + $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { problem => $problem }}); + } + } + + if ($anvil->data->{switches}{"mail-server-authentication"}) + { + $anvil->data->{switches}{"mail-server-authentication"} = lc($anvil->data->{switches}{"mail-server-authentication"}); + if (($anvil->data->{switches}{"mail-server-authentication"} ne "none") && + ($anvil->data->{switches}{"mail-server-authentication"} ne "plain-text") && + ($anvil->data->{switches}{"mail-server-authentication"} ne "encrypted")) + { + $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 2, key => "error_0385", variables => { + auth => $anvil->data->{switches}{"mail-server-authentication"}, + }}); + + $problem = 1; + $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { problem => $problem }}); + } + } + if ($anvil->data->{switches}{"recipient-email"}) + { + if (not $anvil->Validate->email({email => $anvil->data->{switches}{"recipient-email"}})) + { + $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 2, key => "error_0386", variables => { + email => $anvil->data->{switches}{"recipient-email"}, + }}); + + $problem = 1; + $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { problem => $problem }}); + } + } + + # Later, we'll need to parse the language file, for now, we always force 'en_CA'. + $anvil->data->{switches}{"recipient-language"} = "en_CA"; + + # If there's a problem, exit now. + if ($problem) + { + $anvil->nice_exit({exit_code => 1}); + } + + return(0); +}