Seite wählen

NETWAYS Blog

Ein simpler Installer für Icinga

Aus der anstehenden Überarbeitung des Icinga-Buchs habe ich mit dem Icinga-Installer ein Projekt gestartet, um Icinga in seiner Gesamtheit als Stack bestehend aus Icinga 2, Icinga Web 2, MariaDB oder PostgreSQL und Apache leicht und einfach zu installieren.

Der Installer basiert auf den Icinga-Puppet-Modulen und setzt auf das von The Foreman gepflegte Kafo Ruby-Gem-Projekt, das auch beim Foreman-Installer zum Einsatz kommt. Neben dem Puppet-Agent ist nur noch das Paket icinga-installer aus dem neuen Software-Repository https://packages.netways.de/extras erforderlich. Dort liegen Pakete für RHEL, Ubuntu und Debian bereit. Zur Zeit stehen Szenarien zur Installation eines Servers mit Icinga Web 2, Datenbank und Apache zur Verfügung, sowie zur Installation und Konfiguration eines Workers aka Satellit und als Agent.


$ icinga-installer -S server | worker | agent [-i] [--help]

Mit der Option -i kann der interaktive Modus gestartet werden, dort lassen sich dann Installations-Parameter ändern. Dort ist z.B. auch möglich von MariaDB auf PostgreSQL umzuschalten, das Logging anzupassen oder für den Fall eines dedizierten Datenbankservers die nötigen Anpassungen vorzunehmen. Alle diese Konfigurationen können ebenfalls über Optionen eingestellt werden, –help verrät mehr.

Lennart Betz
Lennart Betz
Senior Consultant

Der diplomierte Mathematiker arbeitet bei NETWAYS im Bereich Consulting und bereichert seine Kunden mit seinem Wissen zu Icinga, Nagios und anderen Open Source Administrationstools. Im Büro erleuchtet Lennart seine Kollegen mit fundierten geschichtlichen Vorträgen die seinesgleichen suchen.

Monitoring-Plugins Software-Repository von NETWAYS

Ab sofort bieten wir unter https://packages.netways.de/plugins, die von uns meist genutzten Monitoring-Plugins als Pakete für RHEL 8 und 7, Debian Buster und Stretch, sowie Ubuntu Bionic Beaver und Focal Fossa zum Download an.

Zur Zeit überwiegen die RPM Pakete in der Anzahl, wir hoffen dies in den kommenden Wochen auszugleichen. Wir werden auch bemüht sein, das Angebot in den kommenden Wochen sukzessive zu erweitern. Gerne verfolgen wir dies auch innerhalb von Kundenprojekten, um diesen und allen anderen einen Zugang zu regelmäßig aktualisierten Plugin-Paketen anzubieten.

Lennart Betz
Lennart Betz
Senior Consultant

Der diplomierte Mathematiker arbeitet bei NETWAYS im Bereich Consulting und bereichert seine Kunden mit seinem Wissen zu Icinga, Nagios und anderen Open Source Administrationstools. Im Büro erleuchtet Lennart seine Kollegen mit fundierten geschichtlichen Vorträgen die seinesgleichen suchen.

Encoding “leicht gemacht” mit PostgreSQL

In der Urzeit der Computerei passierte das alles in den USA. Und die Vereinigten Amerikaner haben seinerzeit wie üblich nicht über den Tellerrand geschaut, sondern ihren Zeichensatz an ihre Sprache angepasst (ASCII). Irgendwann “durften” dann auch die Alliierten ran, und die Probleme kamen auf… dieser Zeit verdanken wir ISO-8859-1, WIN-1252 und wie sie alle heißen. Mittlerweile gibt es aber ja seit 30 Jahren Unicode, die Probleme sind also doch Schnee von gestern. Richtig?

PostgreSQL ist – aus guten Gründen – ein beliebtes Ziel für Migrationen. Und PostgreSQL ist von vorne bis hinten auf UTF-8 aufgestellt. Leider hat man es aber oft mit Altsystemen, Altdaten und Gammelcode zu tun, die irgendwie übernommen werden müssen.

So bestehen unfassbare Mengen an altem Perl-, Python-, PHP-, VBA-, … Code, der für frühe Access-, MySQL-, MS-SQL-, Oracle-, Sybase oder was auch immer für Datenbanken geschrieben wurde und mit Unicode nichts am Hut hat. (Einige dieser Systeme sind bis heute nicht wirklich gut darin…)

Gerne sind wir auch gezwungen, “Pseudo-CSV” aus M$ Excel zu importieren (warum ist es “normal”, comma separated values mit Semikolon zu separieren?!?), und Microsoft tut sich bis heute immer noch schwer mit UTF-8.


~$ file importtest.win-1252.csv
importtest.win-1252.csv: ISO-8859 text, with CRLF line terminators

Betreiber solcher Software haben sich üblicherweise aus der Affäre gezogen, indem sie die Datenbank, auch bei Updates, immer wieder im alten, überholten Encoding betrieben haben. Jetzt steht also die Umstellung auf PostgreSQL an, und beim ersten Testimport von Altdaten kommt diese Meldung:


blog=# \COPY csvimport FROM importtest.win-1252.csv WITH (DELIMITER ';', FORMAT CSV);
ERROR: invalid byte sequence for encoding "UTF8": 0xfc
CONTEXT: COPY csvimport, line 1
blog=#

Viele Entwickler*innen werden jetzt reflexhaft ihre bewährte Methode benutzen wollen, und ja, ich kann, auch wenn mein DB-Cluster anders initialisiert wurde, genau das auch tun:


blog=# \h CREATE DATABASE
Command: CREATE DATABASE
Description: create a new database
Syntax:
CREATE DATABASE name
[ [ WITH ] [ OWNER [=] user_name ]
[ TEMPLATE [=] template ]
[ ENCODING [=] encoding ]
[ LOCALE [=] locale ]
[ LC_COLLATE [=] lc_collate ]
[ LC_CTYPE [=] lc_ctype ]
[ TABLESPACE [=] tablespace_name ]
[ ALLOW_CONNECTIONS [=] allowconn ]
[ CONNECTION LIMIT [=] connlimit ]
[ IS_TEMPLATE [=] istemplate ] ]

siehe auch hier.

Ah, da ist es ja, [ ENCODING [=] encoding ] als “Weg des geringsten Widerstands”. Dann ist das doch normal, oder nicht?! Ja, kann man so machen, ist dann nur kacke und man hat eine Top-Gelegenheit verpasst! Besser ist es, die Gelegenheit zu nutzen und hier und jetzt den Weg auf UTF-8 einzuleiten. Dafür reicht es, das client_encoding für den Import anzupassen:


blog=# SHOW client_encoding ;
client_encoding
-----------------
UTF8
(1 row)
blog=# SET client_encoding TO 'win-1252';
blog=# \COPY csvimport FROM importtest.win-1252.csv WITH (DELIMITER ';', FORMAT CSV);
blog=#

Gut! Das hat schonmal geklappt. Dann schauen wir doch mal, wie das in der Tabelle aussieht:


blog=# SELECT * FROM csvimport ;
id | spalte1 | spalte2
----+-----------------------------+----------------------------
1 | Dies ist eine ▒bliche Datei | [NULL]
2 | mit M▒ll von M$ Excel | [NULL]
3 | [NULL] | und leeren Spalten (w▒rg).
(3 rows)

Pfui bah! Genau das wollten wir doch vermeiden!!!

Alles ist gut, unser client_encoding ist ja noch kaputt:


blog=# RESET client_encoding;
blog=# SELECT * FROM csvimport ;
id | spalte1 | spalte2
----+-----------------------------+----------------------------
1 | Dies ist eine übliche Datei | [NULL]
2 | mit Müll von M$ Excel | [NULL]
3 | [NULL] | und leeren Spalten (würg).
(3 rows)

Und wenn das Refakturieren aller beteiligten Komponenten gerade nicht opportun ist, kann das client_encoding z.B. per Rolle (User) gesetzt werden:


blog=# CREATE ROLE legacy_import LOGIN;
blog=# ALTER ROLE legacy_import SET client_encoding TO 'win-1252';

Alles, was von dieser Rolle nun geschrieben wird, verarbeitet PostgreSQL nun intern zu UTF-8. Alles, was die Rolle liest, wird in WIN-1252 umgewandelt. Alle modernen Clients können aber mit Unicode arbeiten, so dass einer Transition statt einer reinen Migration jetzt “nur noch” Code im Wege steht, keine Daten mehr.

P.S.: Es gibt natürlich noch weitere Möglichkeiten, das Encoding pro Client festzulegen, z.B. die Umgebungsvariable PGCLIENTENCODING.

 

Über den Autor:

Gunnar “Nick” Bluth hat seine Liebe zu relationalen Datenbanken Ende des letzten Jahrtausends entdeckt. Über MS Access und MySQL 3.x landete er sehr schnell bei PostgreSQL und hat nie zurückgeschaut, zumindest nie ohne Schmerzen. Er verdient seine Brötchen seit beinahe 20 Jahren mit FOSS (Administration, Schulungen, Linux, PostgreSQL). Gelegentlich taucht er auch tiefer in die Programmierung ein, so als SQL-Programmierer bei der Commerzbank oder in App-Nebenprojekten.
Lennart Betz
Lennart Betz
Senior Consultant

Der diplomierte Mathematiker arbeitet bei NETWAYS im Bereich Consulting und bereichert seine Kunden mit seinem Wissen zu Icinga, Nagios und anderen Open Source Administrationstools. Im Büro erleuchtet Lennart seine Kollegen mit fundierten geschichtlichen Vorträgen die seinesgleichen suchen.

Apache Rewrite von HTTP auf HTTPS am Beispiel von Icinga Web 2

Heute gibt es einen kleinen Tipp, wie man seine über einen Apache ausgelieferten Seiten, von HTTP einfach auf HTTPS umleiten kann. Eine einfache Rewrite-Regel sorgt dafür, dass beliebige URLs korrekt auf HTTPS umgeleitet werden. So sind auch als HTTP-URLs gespeicherte Bookmarks weiterhin uneingeschränkt nutzbar. Voraussetzung ist das Laden der Modules rewrite.

Das nun folgende Beispiel bezieht sich auf die Default-Site, es kann aber leicht für weitere Sites abgewandelt werden. Hierzu ist das Beispiel um die Direktiven ServerName und optional ServerAlias zu ergänzen.


<VirtualHost *:80>
RewriteEngine on
RewriteRule ^ https://%{SERVER_NAME}%{REQUEST_URI} [END,NE,R=permanent]
</VirtualHost>


<VirtualHost _default_:443>
SSLEngine on
Alias /icingaweb2 "/usr/share/icingaweb2/public"
...
</VirtualHost>

Alle weiteren für TLS und Icinga Web 2 nötigen Einstellungen wurden hier ausgelassen.

Lennart Betz
Lennart Betz
Senior Consultant

Der diplomierte Mathematiker arbeitet bei NETWAYS im Bereich Consulting und bereichert seine Kunden mit seinem Wissen zu Icinga, Nagios und anderen Open Source Administrationstools. Im Büro erleuchtet Lennart seine Kollegen mit fundierten geschichtlichen Vorträgen die seinesgleichen suchen.

Benachrichtigung mal einfach


Neulich beim Kunden, sollte folgendes Szenario zur Benachrichtigung umgesetzt werden. Der Weg, also ob Mail, Slack oder Telegram, soll vom Benutzer abhängig sein, je nach dessen Vorliebe. Ist beim Benutzer eine Mailadresse gesetzt, wird er auch per Mail informiert. Soll die Benachrichtigung hingegen via Telegram bzw. Slack erfolgen, muss der notwendige Empfangs-Hook über ein User-Custom-Attribute angegeben werden.

Wer zu benachrichtigen ist, wird am Host-Objekt angegeben. Die zu benachrichtigen Benutzer können hierbei in einer Liste (host.vars.notification.user) oder über die Mitgliedschaft in einer Gruppe, die ebenfalls am Host in einer Liste (host.vars.notification.groups) angegeben werden, zu gewiesen.

Sei ein Benutzer admin Mitglied der Gruppen icingaadmins und linuxadmins. Soll bei folgendem Host

object Host "localhost" {
  import "generic-host"

  address = "127.0.0.1"

  vars.notifiction = {
    groups = [ "icingaadmins", "linuxadmins", "vips" ]
  }
}

für den Benutzer admin, aber keine doppelten Nachrichten versandt werden, kann dies zunächst mit dieser Regel umgesetzt werden:

apply Notification "mail-admin to Host {
  import "mail-host-notification"
  users = [ "admin" ]

  assign where "admin" in host.vars.notification.users || f("admin", host.vars.notification.groups)
}

Über den ersten Teil der assign-Regel wäre das Vorhandensein von admin in der Liste der zu benachrichtigen Benutzer am Host abgehandelt. Der zweite Teil ist eine selbstdefinierte Funktion die ein true zurück liefert, sofern der Benutzer mindestens einer der Gruppen aus der Liste angehört.

function f(user,groups) {
  if (typeof(groups) == Array) {
    for (grp in groups) {
      if (grp in get_user(user).groups) {
        return true
      }
    }
  }
  return false
}

Nun möchte man nicht für jeden Benutzer am Icinga-System eine solche Notification definieren, zumal die Services noch nicht berücksichtigt sind, dann wären deren für jeden Benutzer, immer gleich zwei Notification-Definitionen. Notifications werden vom Config-Compiler immer nach den User- und Usergroup-Objekten ausgewertet, somit kann die Notification zu ein Notification-for, die eine Schleife über alle bekannten Benutzer führt, umgewandelt bzw. erweitert werden:

apply Notification for (user in get_objects(User)) to Host {
  import "mail-host-notification"
  users = [ user.name ]

  assign where user.name in host.vars.notification.users || f(user.name, host.vars.notification.groups)
  ignore where ! get_user(user.name).email
}

Die abschließende ignore-Klausel stellt sich, dass keine Notification für Benutzer erzeugt wird, die keine Mailadresse angegeben haben. Sollen nun die selben Benutzer, nicht nur für den Host, sondern auch über Probleme bei den zum Host gehörigen Services benachrichtigt werden, ist das ganze nur noch eine Fingerübung:

apply Notification for (user in get_objects(User)) to Service {
  import "mail-service-notification"
  users = [ user.name ]

  assign where user.name in host.vars.notification.users || f(user.name, host.vars.notification.groups)
  ignore where ! get_user(user.name).email
}

Äquivalente Notifications lassen sich damit auch für die alternativen Benachrichtigungswege Slack, Telegram und weitere erstellen.

Lennart Betz
Lennart Betz
Senior Consultant

Der diplomierte Mathematiker arbeitet bei NETWAYS im Bereich Consulting und bereichert seine Kunden mit seinem Wissen zu Icinga, Nagios und anderen Open Source Administrationstools. Im Büro erleuchtet Lennart seine Kollegen mit fundierten geschichtlichen Vorträgen die seinesgleichen suchen.

Veranstaltungen

Di 20

Icinga 2 Advanced Training | Online

April 20 @ 09:00 - April 22 @ 17:00
Di 20

InfluxDB & Grafana | Online

April 20 @ 09:00 - April 21 @ 17:00
Di 27

Elastic Stack Training | Online

April 27 @ 09:00 - April 29 @ 17:00
Di 27

Graylog Training | Online

April 27 @ 09:00 - April 28 @ 17:00
NETWAYS Headquarter | Nürnberg
Mai 04

GitLab Fundamentals Training | Online

Mai 4 @ 09:00 - Mai 5 @ 17:00