Icinga2 Benachrichtigungen mit Alexa / Amazon Echo

Wir hatten die Idee, unsere Benachrichtigungen aus Icinga2 nicht nur über E-Mail, Pushover, Telegram und Rocket.Chat zu empfangen, sondern zusätzlich dazu auch von Alexa vorlesen zu lassen. Ein Amazon Echo Dot war schnell bestellt und wir machten uns an die Umsetzung. Nach erfolgreichem Test und Produktiv-Einsatz bei uns im Büro wollen wir nun die Vorgehensweise hier veröffentlichen.

Folgender Beitrag von Alexander Noack und sein Script alexa_remote_control.sh dienten uns dabei als Grundlage: https://blog.loetzimmer.de/2017/10/amazon-alexa-hort-auf-die-shell-echo.html

In diesem Blogbeitrag möchte ich auf die Icinga2 Konfiguration eingehen, die nötig ist um externe Scripte als Benachrichtigung einzusetzen, und Benachrichtigungen aus Icinga2 von Alexa vorlesen zu lassen. Grundkenntnisse über Icinga2 Konfigurationsobjekte werden dabei vorausgesetzt.

Überblick

In diesem Artikel werden wir gemeinsam folgende Schritte vornehmen:

Vorbereitung: Alexa Script herunterladen

Zuerst müssen Sie das Script hier herunterladen und irgendwo im Dateisystem ablegen. Zum Beispiel im Standard-Ordner für Icinga2 Notification Scripte: /etc/icinga2/scripts

Dann das Script ausführbar machen und den Besitzer anpassen:

chmod 755 /etc/icinga2/scripts/alexa_remote_control.sh
chown root:root /etc/icinga2/scripts/alexa_remote_control.sh

Eventuell muss in Ihrem Linux Betriebssystem noch der JSON Parser jq installiert werden damit das Script ohne Fehler läuft (Beispiel mit apt auf Ubuntu):

apt install jq

Anmerkung: Bei Bedarf gibt es auf Alexander Noacks Blog auch eine Version des Scriptes ohne den JSON Parser jq, diese Version haben wir allerdings noch nicht getestet.

Amazon Account

Es muss außerdem ein Amazon Account eingerichtet und verknüpft werden. Die Accountdaten werden dabei im Script hinterlegt, damit es sich mit dem Account verbinden und Alexa steuern kann. Auf die Erstellung und Verknüpfung des Amazon Accounts möchte ich hier in diesem Artikel aber nicht weiter eingehen.

Notification Command

Wir erstellen wir ein NotificationCommand, importieren ein Standard Notification Template, und verwenden je nach Status (UP, DOWN) unterschiedliche Commands, da wir unterschiedliche Sätze ausgeben wollen. Dabei wird jedesmal dasselbe Script aufgerufen, aber mit verschiedenen Übergabeparametern. Dies erreichen wir mit der bedingten Anweisung if else indem wir eine Funktion {{ }} für die Variable command definieren.

ACHTUNG! Die Parameter -e und speak müssen dabei einzeln übergeben werden, mit , getrennt. Eine Verkettung der Strings mit + führt nicht zum gewünschten Ergebnis, da sonst alles als ein einziger Kommandozeilenparameter an das Script übergeben würde. Alles was hinter dem Parameter speak kommt, muss hingegen zwingend als String verkettet und idealerweise in ' ' eingepackt werden.

///////////////////////////////////////////
/// *** Alexa Notification Commands *** ///
///////////////////////////////////////////

// Alexa Host Notifications
object NotificationCommand "alexa-host-notification" {
   import "mail-host-notification-template"
   command = {{
         // 0=UP 1=DOWN
         if (host.state == 1){
                 var problem_command = [ SysconfDir + "/icinga2/scripts/alexa_remote_control.sh", "-e", "speak:'" + host.display_name + " ist nicht erreichbar'" ]
                 return problem_command
         } else {
                 var recovery_command = [ SysconfDir + "/icinga2/scripts/alexa_remote_control.sh", "-e", "speak:'" + host.display_name + " ist wieder erreichbar'" ]
                 return recovery_command
         }
   }}
 }

// Alexa Service Notifications
object NotificationCommand "alexa-service-notification" {
   import "mail-service-notification-template"
   command = {{
         // 0=OK 1=WARNING 2=CRITICAL 3=UNKNOWN
         if (service.state == 1) {
                 var problem_command = [ SysconfDir + "/icinga2/scripts/alexa_remote_control.sh", "-e", "speak:' Service auf" + host.display_name + " ist WARNING'" ]
                 return problem_command
         } else if (service.state == 2) {
                 var problem_command = [ SysconfDir + "/icinga2/scripts/alexa_remote_control.sh", "-e", "speak:' Service auf" + host.display_name + " ist CRITICAL'" ]
                 return problem_command
         } else {
                 var recovery_command = [ SysconfDir + "/icinga2/scripts/alexa_remote_control.sh", "-e", "speak:' Service auf" + host.display_name + " ist OK'" ]
                 return recovery_command
         }
   }}
 }

Anmerkung: Sie können bei der Service Benachrichtigung noch analog zum host.display_name auch den service.display_name und/oder weitere Variablen mit ausgeben lassen.

Variable Icinga2 Benachrichtigungen an Alexa

Alternativ könnten wir auch den zu sprechenden Satz in Custom Variablen beim Host oder Service schreiben, und diese beim Aufruf im NotificationCommand an das Script übergeben. Zum Beispiel so:

// insert in object Host
 vars += {
     alexa_speak_ok = "Host " + host.display_name + " ist UP"
     alexa_speak_recovery = "Host " + host.display_name + " ist wieder UP"
     alexa_speak_critical = "Host " + host.display_name + " ist DOWN"
 }

Dann muss der NotificationCommand entsprechend abgeändert und die Variable eingefügt werden:

problem_command = [ SysconfDir + "/icinga2/scripts/alexa_remote_control.sh", "-e", "speak:'" + vars.alexa_speak_critical + "'" ]

Sie können natürlich auch andere Laufzeitparameter mit ausgeben, wie z.B.

  • address
  • service.output
  • service.last_hard_state_change
  • usw…

Notification Template

Nach dem NotificationCommand erstellen wir eine Alexa Benachrichtigungs Vorlage, fügen bei command unsere neu erstellen NotificationCommands ein und passen states, types und period unseren Bedürfnissen an.

////////////////////////////////////////////
/// *** Alexa Notification Templates *** ///
////////////////////////////////////////////
template Notification "alexa-host-notification" {
   command = "alexa-host-notification"
   states = [ Up, Down ]
   types  = [ Problem, Acknowledgement, Recovery, Custom ]
   //only notify once, disable re-notification
   interval = 0
   //timeperiod for this notification
   period = "8to18"
 }
 template Notification "alexa-service-notification" {
   command = "alexa-service-notification"
   states = [ OK, Critical, Unknown ]
   types  = [ Problem, Acknowledgement, Recovery, Custom ]
   //only notify once, disable re-notification
   interval = 0
   //timeperiod for this notification
   period = "8to18"
 }

Notification

Nun können die eigentlichen Notification Objekte erstellt und zugewiesen werden. Es wird das obige Notification Template importiert und eine user_group zugewiesen, die diese Benachrichtigung empfangen soll. In unserem Fall ist die Benutzergruppe alexa_notification nur eine Dummy Gruppe ohne echte Kontaktdaten oder Email-Adressen.

Für die assign Regel haben wir hier für das Beispiel den einfachsten Weg gewählt und aktivieren die Benachrichtigung einfach über eine Custom Variable alexa_notification die beim gewünschten Host bzw Service auf true gesetzt wird.

///////////////////////////////////
/// *** Alexa Notifications *** ///
///////////////////////////////////
apply Notification "alexa-notification" to Host {
   import "alexa-host-notification"
   user_groups += [ "alexa_notification" ]
 assign where host.vars.alexa_notification == true
 }
 apply Notification "alexa-notification" to Service {
   import "alexa-service-notification"
   user_groups += [ "alexa_notification" ]
 assign where service.vars.alexa_notification == true
 }

Notification User Alexa

Icinga2 kann keine Benachrichtigungs-Objekte initialisieren ohne die zwingend erforderliche Variable user. Deshalb legen wir einen leeren „Dummy User“ Alexa für die Benachrichtigungen an und weisen ihn einer Gruppe zu. Dieser User benötigt keine Email Adresse oder sonstige Angaben. Bei states und types tragen wir alle Zustände ein, für die wir Benachrichtigunen empfangen wollen. In unserem Beispiel hier wollen wir z.B. WARNING Zustände ausschließen, sondern nur Benachrichtigungen für OK, CRITICAL, UNKNOWN Zustände erhalten.

Achtung! Bei states und types auf die richtige Icinga2 Schreibweise mit Groß- und Kleinschreibung achten!

////////////////////////////////
/// *** Alexa Dummy User *** ///
////////////////////////////////
object User "alexa-notification-user" {
   display_name = "Alexa"
   states = [ Up, Down, OK, Critical, Unknown ]
   types  = [ Problem, Acknowledgement, Recovery, Custom ]
   groups = [ "alexa_notification" ]
}

////////////////////////////////
/// *** Alexa User Group *** ///
////////////////////////////////
object UserGroup "alexa_notification" {
   display_name = "Alexa UserGroup"
}

Zum Schluss müssen wir nur noch dafür sorgen, dass bei den gewünschten Hosts und Services die Variable vars.alexa_notification = true gesetzt ist und schon liest Alexa uns die Icinga2 Benachrichtigungen von 8:00 bis 18:00 Uhr laut vor.

Anmerkung: Die Nachricht sollte dabei nicht allzu lang und komplex sein. Benachrichtigungen wie DISK CRITICAL - free space: / 9 GB (13% inode=93%) funktionieren zwar per Email und Pushover sehr gut, aber vorgelesen von Alexa ist es eine Katastrophe! Beschränken Sie sich also wie wir im obigen Beispiel auf möglichst einfache Sätze.

Viel Spass beim Ausprobieren!


Ähnliche Themen:

Visuelle Alarme mit Nanoleaf Light Panels über Curl steuern

Anton Daudrich

IT Entwicklungsleiter bei ADMIN INTELLIGENCE GmbH
Icinga2 Consultant, Linux Professional
Anton Daudrich