pixel
Seite wählen

NETWAYS Blog

Aus Graylog ENTERPRISE wird Graylog Operations

Wie im Blogpost von Graylog bekannt gegeben, wurde die Lösung Graylog ENTERPRISE umbenannt in Graylog Operations. Der neue Name spiegelt dabei das Ziel von Graylog wider, sich verstärkt in den operational Bereich einzugliedern und Herausforderungen, die sich aus diesem ergeben, anzugehen.

Graylog Operations ist eine mächtige und dabei einfach zu bedienende Lösung, um Loginformationen und Ereignisse zu sammeln, zu korrelieren, aufzubereiten und visuell darzustellen. Dadurch werden mögliche Schwachstellen, Bottlenecks und zu verbessernde IT-Prozesse aufgezeigt und erlaubt es den Nutzern, mit diesen Reports die interne Infrastruktur weiter zu optimieren.

Graylog Security

Neben dem neuen Namen Graylog Operations und der daraus resultierenden Mission, ist Graylog Security nun ebenfalls flächendeckend verfügbar. Das Ziel von Graylog Security ist es, die interne IT auf mögliche Bedrohungen hin zu analysieren, schadhaftes Verhalten aufzudecken und die Cyberabwehr zu stärken.

Dabei hilft die kosteneffiziente Lösung, alle Informationen nicht nur zu sammeln, sondern auch auszuwerten, grafisch darzustellen und mithilfe der Reporting Funktion automatisiert detaillierte Reports über den aktuellen Status der Umgebung zu erstellen. Der Vorteil von Graylog Security ist dabei, dass die Informationen einfach eingesammelt und dargestellt werden können, ohne auf komplexe SIEM Lösungen zurückgreifen zu müssen.

 

Wir haben euer Interesse geweckt? Dann nehmt doch einfach Kontakt mit uns auf. Wir stehen bei Rückfragen und Informationen rund um Graylog Operations und Graylog Security gerne zur Verfügung!

Christian Stein
Christian Stein
Lead Senior Account Manager

Christian kommt ursprünglich aus der Personalberatungsbranche, wo er aber schon immer auf den IT Bereich spezialisiert war. Bei NETWAYS arbeitet er als Senior Sales Engineer und berät unsere Kunden in der vertrieblichen Phase rund um das Thema Monitoring. Gemeinsam mit Georg hat er sich Mitte 2012 auch an unserem Hardware-Shop "vergangen".

ServiceNow Data Asset Import mit dem Director

Hallo Liebe Leser dieses Blogs,

nach einer weile der Abwesenheit hab ich heute die Freude ihnen etwas näher bringen zu dürfen.
Da viele unserer Kunden inzwischen auch ServiceNow verwenden und diese auch als Assetmanagement / CMDB verwenden.

Kommt doch die Frage auf wie man gegebenenfalls hier die Daten abfragen kann um Sie in den Director zu importieren um daraus dann Hosts/Services zur Überwachung zu formen.Ich versuche in diesem kleinen Blogpost zumindest einen Ansatzpunkt hierzu aufzuzeigen. Viele verwenden in diesem Fall ja ServiceNow als SaaS, aber es gibt auch Kunden welche es als On Prem einsetzen.
Aber fangen wir an 🙂 in diesem Fall ist der Anlaufpunkt hier die ServiceNow API, wer hätte es gedacht.
In diesem Fall ziehe ich mal die folgende API (Link) zur rate:

Hier wird die ‘cmdb-instance’ in welcher die CMDB Daten landen dokumentiert. Es ist aber zu bedenken, dass die Instanz natürlich abweichen kann daher ist dies bitte nicht direkt 1:1 zu übernehmen.
Wir feuern per curl gegen die ServiceNow API, die folgende Abfrage… in Hoffnung, dass wir valides JSON zurückerhalten mit all unseren Objekten.


curl -k -s -S -i -u 'servicenow_apiuser:servicenow_apiuserpassword' -H 'Accept: application/json' -H 'X-HTTP-Method-Override: GET' -X POST 'https://instance.servicenow.com/api/now/cmdb/instance/cmdb_ci_linux_server'

und wir erhalten als Antwort das folgende JSON:


{
"result": {
...
"attributes": {
"firewall_status": "Intranet",
"os_address_width": "",
"sys_updated_on": "2020-07-08 11:16:51",
"sys_created_by": "glide.maint",
"warranty_expiration": "",
"ram": "2048",
"cpu_name": "",
"cpu_speed": "2800",
"classification": "Production",
"disk_space": "40",
"dns_domain": "",
"assigned": "2020-01-04 07:00:00",
"floppy": "",
...
"sys_class_name": "cmdb_ci_linux_server",
...
"cpu_count": "1",
...
"os_version": "2.6.9-22.0.1.ELsmp",
"serial_number": "",
"attributes": "",
...
"form_factor": "",
"cpu_core_count": "",
"sys_updated_by": "system",
"sys_created_on": "2008-10-26 17:17:28",
...
"name": "PS LinuxApp01",
"default_gateway": "",
"chassis_type": "",
"sys_id": "3a290cc60a0a0bb400000bdb386af1cf",
"po_number": "",
"checked_in": "",
...
"comments": "",
"os": "Linux Red Hat",
"sys_mod_count": "24",
"monitor": "false",
"model_id": {
"display_value": "Iris 5875",
"link": "https://instance.servicenow.com/api/now/table/cmdb_model/5f5fbcc3c0a8010e00f3b27814f3b96b",
"value": "5f5fbcc3c0a8010e00f3b27814f3b96b"
},
"ip_address": "192.168.178.1",
"duplicate_of": "",
"location": {
"display_value": "Somewhere Street, Someplace, State",
},
"category": "Do not migrate to asset",
"fault_count": "0",
"host_name": "",
"lease_id": ""
},
}

Den Output schreiben wir als Datei raus, so dass wir hier als Beipiel eine Datei haben, mit der wir weiterarbeiten können. Als Beispiel nennen wir diese servicenow.json
(Exclaimer) Ich habe das JSON hier als Beispiel mal extrem zusammengekürzt, damit wir thementechnisch nicht zu weit Abdriften.
Anyway, aber damit lässt sich arbeiten.
Damit wir mit diesem JSON arbeiten können, verwenden wir das Tool ‘jq’, um relevante key/value Paare herauszufiltern.
Ich habe hier mal den folgenden ‘jq’ Aufruf verwendet:


jq -j '.result.attributes.os,",",.result.attributes.ip_address,",",.result.attributes.classification,",",.result.attributes.sys_class_name,",",.result.attributes.name,",",.result.attributes.location.display_value,","' servicenow.json

Der somit gewonnene Output ist der folgende, bitte beachtet die ‘,’ Kommata. Die meisten werden schon ahnen worauf ich gleich hinaus will.
Zurück zu dem nun mit ‘jq’ aufbereiteteb Output, dieser ist der folgende:


Linux Red Hat,192.168.178.1,Production,cmdb_ci_linux_server,PS LinuxApp01,Somewhere Street, Someplace, State,

Mit etwas Bash Scripting kann man das schön automatisieren und hat am Ende dieses Vorgangs eine CSV Datei, die man hervorragend im Director per Fileshipper weiterverarbeiten kann.
Das mit dem CSV ist eine Geschmacksfrage, denn man kann auch direkt JSON per Fileshipper importieren … ich würde aber dazu tendieren, die Datenmenge durch etwas vorfiltern zu verkleinern. So eine Filterung, wie gesehen, kann auch per ‘jq’ erfolgen, so dass man ein kleineres JSON File erhält.
Wer wissen möchte, wie man mit dem Director einen Fileshipper-Import durchführt, dem sei der Blogpost meines Kollegen Johannes empfohlen.

Blogpost Director Fileshipper Import

Das war schon mein kleines Intermezzo wie ServiceNow-Data-Assets per Fileshipper in den Director zu importiert sind.
Bis zum nächsten Mal

Mit freundlichem Gruß
David

David Okon
David Okon
Senior Systems Engineer

Weltenbummler David hat aus Berlin fast den direkten Weg zu uns nach Nürnberg genommen. Bevor er hier anheuerte, gab es einen kleinen Schlenker nach Irland, England, Frankreich und in die Niederlande. Alles nur, damit er sein Know How als IHK Geprüfter DOSenöffner so sehr vertiefen konnte, dass er vom Apple Consultant den Sprung in unser Professional Services-Team wagen konnte. Er ist stolzer Papa eines Sohnemanns und bei uns mit der Mission unterwegs, unsere Kunden zu...

OpenSearch: Wie verwalten wir unsere Daten?

This entry is part 3 of 3 in the series Offen gesucht! Offen gefragt! OpenSearch

OpenSearch: Ordnung muss sein! III

In der letzten Runde haben wir uns mit der Einlieferung der Daten und der ersten Schritte im OpenSearch Dashboards gewidmet. Heute wollen wir uns einmal mit der Haushaltung der Informationen befassen. Der erste wichtigste Unterschied ist die Bezeichnung. Im Elasticsearch sprechen wir vom ILM (Index Lifecycle Management), wohin gegen wir im OpenSearch Plugin von ISM (Index State Management) sprechen. Beide behandeln aber den selben Nenner “Policies” für die Verwaltung der Vorhaltung der Daten.

ISM erklärt

Leider ist die Dokumentation zur ISM nach wie vor sehr Schlank. Alle Teile sind sehr knapp beschrieben.

Eine ISM Policy gliedert sich wie folgt auf:

  • Policy Info: ID und Beschreibung
  • Error Notification: Benachrichtigungen bei Fehlschlag
  • ISM Templates: Hier werden die Index-Pattern definiert, auf die die ISM Policy angewendet werden soll
    • Hierbei ist wichtig, dass der Index initial mit einem Hyphen Suffix angelegt wird z.B./e.g.: “myindex-00001” (Regex-Muster: `^.*-\\d+$`)
  • States: Mit States werden die einzelnen Phasen eines Index definiert. In den States werden “Actions” und “Transitions” gesetzt. Die Transition kann zum Beispiel einer Action Rollover folgen, um den  Index in den nächsten State zu setzen. In dem neuen State wird der Index dann zum Beispiel auf “Read Only” gesetzt oder der “Replica Count=0” gesetzt.

Ring frei

Wir wollen uns das ganze mal an einem Beispielablauf anschauen. Leider war es für mich mit den bisher genutzten Mitteln nicht 100% automatisierbar, auch die Hilfen im Forum und dem restlichen Web waren nicht sehr aufschlussreich. Folgend setzten wir uns mit dem erstellen eines ISM mit entsprechenden Rollover, dass was wir in der Produktion immer wollen.

Bedingungen für die Runde

Einlieferung

Zur Einlieferung nutzen wir den Fluent Bit wie folgt Konfiguriert:


[INPUT]
name cpu
tag cpu.local

# Read interval (sec) Default: 1
interval_sec 1

[INPUT]
name tail
path /tmp/json-output
parser json

[OUTPUT]
name opensearch
match *
host 192.168.2.42
port 9200
index fluentbit-000001
type _doc
http_user admin
http_passwd admin
tls On
tls.verify Off

Wichtig ist hier beim Output, dass wir entsprechend Initial einen Hyphen am Ende mit einem Pattern haben welches sich hochzählen lässt.

Index Template für den Rollover

Für das Rollover handling setzen wir einen Rollover-alias. Dieser muss gesetzt sein. Dies regeln wir über ein Template


PUT _index_template/ism_rollover
{
 "index_patterns": ["fluentbit-*"],
"template": {

  "settings": {
    plugins.index_state_management.rollover_alias": "fluentbit"
   }
 }
}

Hier ist es wichtig keinen Index-Alias zu setzen dieser wird nach dem des Start des ISM-Init auf den index manuell gesetzt. Das ist sehr wichtig. Denn wenn wir den alias im template definieren, dann bekommen wir keinen rollover. Der folgende Fehler wäre dann der Fall:


Rollover alias [fluentbit] can point to multiple indices, found duplicated alias [[fluentbit]] in index template [ism_rollover]

Anlegen der Policy

Nun können wir unsere Policy anlegen.

Erstellung von ISM-Policies

Aufgrund der Übersichtlichkeit erkläre ich hier das ganz im JSON:


{
"id": "test_flow",
"seqNo": 603481,
"primaryTerm": 10,
"policy": {
"policy_id": "test_flow",
"description": "A sample description of the policy",
"last_updated_time": 1653467076033,
"schema_version": 13,
"error_notification": null,
"default_state": "Hot",
"states": [
{
"name": "Hot",
"actions": [
{
"retry": {
"count": 3,
"backoff": "exponential",
"delay": "1m"
},
"rollover": {
"min_doc_count": 50,
"min_index_age": "4m"
}
}
],
"transitions": [
{
"state_name": "Warm",
"conditions": {
"min_rollover_age": "5m"
}
}
]
},
{
"name": "Warm",
"actions": [
{
"retry": {
"count": 3,
"backoff": "exponential",
"delay": "1m"
},
"read_only": {}
}
],
"transitions": [
{
"state_name": "Cold",
"conditions": {
"min_rollover_age": "10m"
}
}
]
},
{
"name": "Cold",
"actions": [
{
"retry": {
"count": 3,
"backoff": "exponential",
"delay": "1m"
},
"force_merge": {
"max_num_segments": 1
}
},
{
"retry": {
"count": 3,
"backoff": "exponential",
"delay": "1m"
},
"replica_count": {
"number_of_replicas": 0
}
}
],
"transitions": [
{
"state_name": "DELETE",
"conditions": {
"min_rollover_age": "1h"
}
}
]
},
{
"name": "DELETE",
"actions": [
{
"retry": {
"count": 1,
"backoff": "exponential",
"delay": "1m"
},
"delete": {}
}
],
"transitions": []
}
],
"ism_template": [
{
"index_patterns": [
"fluentbit-*"
],
"priority": 1,
"last_updated_time": 1652268548245
}
]
}
}

Ich habe hier unterschiedlich States, eine Transition erfolgt immer in den darauf folgenden State, könnte aber auch umgekehrt werden. Bei der Berechnung der Zeitlichen Spanne ab wann eine Aktion oder Transition ausgeführt werden soll ist folgend immer auf den Rollover-Age zu setzen.

Weiter gehts…

Nach dem anlegen des Templates und der ISM Policy, starten wir den Fluent-bit. Danach sehen wir ziemlich zeitnah den INIT. Leider habe ich nur ein Bild wo den INIT des zweiten Index zeigt. Sorry.

Danach müssen wir den Index-Alias manuell setzen:


POST /_aliases
{
"actions" : [
{ "add" : { "index" : "fluentbit-000001", "alias" : "fluentbit" } }
]
}

Dann stoppen wir den Fluent-bit-Daemon und ändern den Index-Namen auf den Alias ab:


[OUTPUT]
name opensearch
match *
host 192.168.2.42
port 9200
index fluentbit
type _doc
http_user admin
http_passwd admin
tls On
tls.verify Off

Danach wird der Dienst wieder gestartet.

Diese Abfolge ist wichtig wird der Alias nicht gesetzt, schlägt uns der folgende Fehler auf:


Missing alias or not the write index when rollover [index=fluent-bit-000001]

Nun können wir die Runde entspannt laufen lassen. Die ISM Policy wird erfolgreich angewendet und wir sehen die einzelnen Transistions.

Managed Indices

Hilfen zur Analyse bei Fehlern

Folgend möchte ich euch noch ein paar hilfreiche API-Abfragen für die DEV-Tools liefern.

Prüfen der Aliases

Damit solletst du sehen ob dein Alias gesetzt ist.


GET _cat/aliases

ISM Erklärung

Dieser API-Punkt erklärt dir genau wie der ISM State für ein Index aussieht

GET _plugins/_ism/explain/fluentbit-000001

Abfrage ISM Policy

Dieser API-Punkt gibt dir deine Policy so zurück wie diese im Cluster gespeichert ist.

 GET _plugins/_ism/policies/test_flow 

Der Gong ertönt!

Und wieder ist eine Runde rum. Diese Runde war nicht leicht, denn es galt verständlich sehr komplexes und dünn dokumentiertes Wissen zu transportieren. Auch die Tatsache, dass hier das verhalten im Vergleich zur Verwandschaft gänzlich anders ist.

Aber auch die Runde konnten wir mit ordentlich Punkten meistern. Auf die nächste Runde dürft Ihr gespannt sein, ich weis selbst noch nicht genau was uns erwartet. Weil es denke ich hilft gibt es auch noch ein Video.

Wenn Euch das, was ihr jetzt schon gelesen habt noch mehr reizt und ihr schneller zum Sieg über ein KO in der nächsten Runde erringen wollt, dann meldet Euch doch einfach bei unserem Sales Team sales[at]netways.de. Wir helfen Euch in einem PoC (Proof of Concept) gleich von Runde I an mit zu kämpfen! Nach den letzten Monaten intensiver OpenSearch Evaluierung bin ich der Trainer der euch “State of the Art” Euren “Kampf gegen die Informationsflut” gewinnen lässt. Ihr dürft gespannt sein auf Runde IV.

Daniel Neuberger
Daniel Neuberger
Senior Consultant

Nach seiner Ausbildung zum Fachinformatiker für Systemintegration und Tätigkeit als Systemadministrator kam er 2012 zum Consulting. Nach nun mehr als 4 Jahren Linux und Open Source Backup Consulting zieht es ihn in die Welt des Monitorings und System Management. Seit April 2017 verstärkt er das NETWAYS Professional Services Team im Consulting rund um die Themen Elastic, Icinga und Bareos. Wenn er gerade mal nicht um anderen zu Helfen durch die Welt tingelt geht er seiner...

So repliziert man Daten mit InfluxDB

Mit InfluxDB 2.0 hat influxdata einen großen Schritt gewagt und viele Neuerungen eingeführt. Hierzu gehören unter anderem die Integration von Webinterface und Task-Engine und DBMS, aber auch die neue Abfragesprache Flux. Ein paar Funktionen, die in es in InfluxDB 1.x gab, wurden zunächst jedoch noch nicht Umgesetzt. Hierzu gehörte bis jetzt das Thema Replikation.
Von Replikation spricht man, wenn Daten von einem Server automatisiert auf einen oder mehrere weitere Server kopiert werden um beispielsweise die Datensicherheit zu erhöhen oder den Zugriff zu beschleunigen.

Seit influxDB 2.2 ist Replikation als technical preview in der Open Source Version enthalten und kann schnell und einfach über das influx command line interface eingerichtet werden. Bei diesem Verfahren werden die Daten TLS gesichert an die API eines oder mehrerer InfluxDB Server gesendet. Wird die Verbindung zwischen Quell- und Zielserver unterbrochen, werden die Daten zu einem späteren Zeitpunkt übertragen.

Einrichtung

Vorab werden hierfür ein Quell-Bucket und ein Authentifizierungstoken auf Server1, und ein Ziel-Bucket plus Authentifizierungstoken auf Server2 benötigt. Bei der Gelegenheit sollte man sich auch schon einmal die Organisations-IDs und Bucket-IDs notieren

# Server 1
user@server1$ influx org ls
user@server1$ influx bucket create -n example-local-bucket
user@server1$ influx auth create ...
# Server 2
user@server2$ influx org ls
user@server2$ influx bucket create -n example-remote-bucket
user@server2$ influx auth create ...

Nach dieser Vorarbeit muss zunächst Remote-Verbindung zu Server 2 angeben werden. Diese wird dann mit im folgenden Schritt genutzt um die Replikation zu aktivieren. In einer nicht gesicherten Testumgebung können zudem die Schalter -allow-insecure-tls und –skip-verify hilfreich sein.

user@server1$ influx remote create \
--name myremote \
--org-id <org ID> \
--token <token> \
--remote-url <remote URL> \
--remote-api-token <remote token> \
--remote-org-id <remote org ID> \

user@server1$ influx replication create \
--name myreplication
--local-bucket example-local-bucket
--remote-bucket example-remote-bucket
--remote-id 0ooxX0xxXo0x

Das ganze ist auch noch weitergehend konfigurierbar, es kann z.B. die Länge des Replay-Logs oder das maximale Alter von zu replizierenden Daten geändert werden.

Weitergehende Informationen finden sich in der Influxdb-Doku:

Christoph Niemann
Christoph Niemann
Senior Consultant

Christoph hat bei uns im Bereich Managed Service begonnen und sich dort intensiv mit dem internen Monitoring auseinandergesetzt. Seit 2011 ist er nun im Consulting aktiv und unterstützt unsere Kunden vor Ort bei größeren Monitoring-Projekten und PERL-Developer-Hells.

Modifier im Icinga-Director selbstgemacht

Ich bin sowohl als Consultant als auch als Ausbilder ein großer Fan von Hilfe zur Selbsthilfe. Der Blogpost wird also zum einen dem geneigten Leser hoffentlich helfen sich bei Bedarf seine eigenen Modifier für den Icinga-Director zu bauen, zum anderen will ich anhand des Beispiels auch beleuchten was ich so unter Hilfe zu Selbsthilfe verstehe. Daher will ich etwas weiter ausholen bevor der erste Code-Schnipsel kommt, wer also schon weiß was Modifier sind, wie man sie nutzt und warum man vielleicht Bedarf nach einem eigenen hat, darf gerne die Einleitung überspringen.

Modifier im Director ermöglichen es Daten aus der Import-Quelle anzupassen oder auch anzureichern, sprich es erlaubt der Monitoring-Administration auszubügeln was in der Datenquelle nicht passt oder auch einfach nicht für das geplante Regelwerk in Icinga 2 geeignet ist. Einfache Stringoperationen ermöglichen es bereits aus Hostnamen einen FQDN zu machen oder diesen aus möglicherweise getrenntem Hostnamen und Domäne zu kombinieren, komplexere Modifier machen beispielsweise einen DNS-Lookup um Icinga 2 zur Laufzeit vom DNS unabhängig zu machen. Bereits an den Beispielen sieht man hoffentlich, wie hilfreich diese Optionen sein können, und wenn damit dann Icinga 2 voll automatisiert mit Tausenden von Hosts befüllt wird, wird hoffentlich klar wie kritisch die Funktion ist. Nun gibt es natürlich trotzdem Bugs, einen hat Tom mit dem Release 1.9.1 gefixt und zwar dass bei Stringoperationen aus NULL-Werten ein leerer String wurde. Nachdem dieses Verhalten nun bereits länger so war, hat vielleicht der ein oder andere sich darauf verlassen, so dass es nun statt eines lang ersehnten Bug-Fix wie für mich, für diese Nutzer wie ein Bug erscheinen mag. Der Supportkunde der nun bei Patrick aufgeschlagen war, da dieser gerade wieder im Rahmen der Ausbildung das Operations-Team verstärkt, hatte zum Glück Verständnis für den Bug-Fix, aber trotzdem war nun sein Workflow kaputt. Als ein Beispiel wurde genannt, dass sie aktuell einen DNS-Lookup als Modifier nutzen, der gegebenenfalls wenn ein Name nicht auflösbar ist einen NULL-Wert zurückgibt, im nächsten Schritt wurde daraus ein leerer String und dann wurde der leere String durch einen regulären Ausdruck zum String “Unknown”. Von Patrick um eine kurze Einschätzung gebeten, sagte ich ihm er soll mal schauen ob der Modifier statt einem NULL-Wert direkt einen leeren String zurückgeben kann oder ein anderer Modifier genutzt werden kann um NULL-Werte zu befüllen. Nachdem diese Suche erfolglos geblieben war, hat er das Ticket in Richtung Icinga eskaliert, da das Kundenproblem nicht ohne Software-Änderung zu lösen war.

Nun hätten wir es darauf beruhen lassen können, da ich aber bei meinen Auszubildenden den Drang fördere, eine Lösung zu suchen statt das Problem nur jemand anders zuzuschieben und Patrick auch von Natur aus nicht zufrieden ist wenn er ungelöste Probleme vor sich hat, kam er erneut auf mich zu. Mit meiner Antwort, dass so ein Modifier in etwa 10 Minuten geschrieben sei, und dass er dies doch übernehmen könne, war er natürlich nicht ganz zufrieden bis ich ihm dafür meine Unterstützung angeboten habe. Da ich hier schon entsprechendes beigetragen habe, konnte ich ihm direkt sagen was zu tun ist und es kam dabei der Commit 4692b28 für den Director heraus. Dieser fügt einen Modifier hinzu der es erlaubt NULL-Werte direkt durch einen angegebenen String zu ersetzen, heißt der Kunde kann wieder seinen Workflow bauen und dieser dürfte sogar einfacher sein.

Modifier: Replace null value with String

Wenn man sich den Commit nun anschaut sind es nur zwei veränderte Dateien, zum einen der neu erstellte Modifier und zum anderen ist eine Registrierung notwendig. Der Modifier selbst besteht quasi aus einem Rumpf aus Namespace, verwendeten Klassen und seiner eigenen Klasse als Implementierung der Basisklasse sowie drei Funktionen in der Datei library/Director/PropertyModifier/PropertyModifierReplaceNull.php. Die Funktion getName() erlaubt es eine Beschreibung für das Auswahlfeld der Modifier zurückzugeben, addSettingsFormFields(QuickForm $form) erlaubt es zusätzliche, für den Modifier benötigte Eingabefelder zu definieren und transform($value) ist dann die eigentliche Modifikation, also bei einem NULL-Wert den eingegebenen String zurückzugeben ansonsten den ursprünglichen Wert. Entstanden ist das Ganze durch Kopieren und Anpassen eines ähnlichen Modifiers in 5 Minuten Arbeitszeit und 30 Minuten Erklärung.

<?php

namespace Icinga\Module\Director\PropertyModifier;

use Icinga\Module\Director\Hook\PropertyModifierHook;
use Icinga\Module\Director\Web\Form\QuickForm;

class PropertyModifierReplaceNull extends PropertyModifierHook
{

    public function getName()
    {
        return 'Replace null value with String';
    }

    public static function addSettingsFormFields(QuickForm $form)
    {
        $form->addElement('text', 'string', array(
            'label'       => 'Replacement String',
            'description' => $form->translate('Your replacement string'),
            'required'    => true,
        ));
    }

    public function transform($value)
    {
        if ($value === null) {
            return $this->getSetting('string');
        } else {
	    return $value;
	}  
    }
}

Zusätzlich muss der Modifier noch in register-hooks.php registriert werden, dazu benötigt es zwei Einträge. Zum einen muss der Modifier an sich bekannt gemacht werden und zum anderen dann noch als Umsetzung des Hook angeboten werden was der Director über eine Iteration durch ein mehrdimensionales Array löst, so dass der Modifier nur an entsprechender Stelle dem Array hinzugefügt werden muss. Dabei der Ordnung halber an die alphabetische Reihe gehalten und schon ist es auch hübsch. Dafür nehmen wir mal 1 Minute Arbeitszeit und 5 Minuten erklären an.

...
use Icinga\Module\Director\PropertyModifier\PropertyModifierReplaceNull;
...
        PropertyModifierReplaceNull::class,
...

Noch mal den Git-Workflow erklärt, den Commit in Patrick’s Fork gepusht, auf seinem Testsystem ausgecheckt, getestet und für gut befunden, Pull-Request erstellt, macht weitere 5 Minuten Arbeitszeit und 5 Minuten Erklärung, wobei ich mir diese hier spare und stattdessen auf einen älteren Blogpost verweise, den zusammen mit Kollegen geschrieben hatte. In Summe macht das in etwa eine Stunde aufgewandte Zeit, aber ich habe nun einen Auszubildenden, der beim nächsten Mal ein ähnliches Problem besser verstehen wird, es direkt lösen kann und als Bonus neben dem Erfolgserlebnis auch als Contributor beim Director auftaucht. Patrick hat sein Wissen erweitert, den Icinga-Kollegen Arbeit abgenommen und dem Kunden ohne lange Wartezeit eine Lösung geliefert, von der auch andere zukünftig profitieren werden. Beim nächsten Mal sind es dann vermutlich wirklich 10 Minuten Arbeit für Patrick! 😉

Was aber nun wenn man einen so speziellen Modifier benötigt, dass es keinen Sinn macht diesen dem Director und damit der Allgemeinheit zur Verfügung zu stellen? Durch den modularen Aufbau von Icinga Web 2 lassen sich Modifier als Hook auch aus einem eigenen Modul anbieten. Heißt wenn der Modifier speziell für eine bestimmte Import-Quelle benötigt wird, kann der Modifier im gleichen Modul eingebaut werden. Ist er dagegen nur für die eigene Umgebung relevant kann man ihn in ein separates Modul packen oder vielleicht mit in das Modul für das Theme des Unternehmens. Dafür müssten nur ein paar Kleinigkeiten angepasst werden. Der Modifier wäre dann im Modul an der Stelle library/MODULENAME/ProvidedHook/Director/PropertyModifier/ abzulegen, dementsprechend wäre der Namespace Icinga\Module\MODULENAME\ProvidedHook\Director\PropertyModifier und statt einer register-hooks.php erstellt man eine run.php mit folgendem Inhalt:

<?php

use Icinga\Module\MODULENAME\ProvidedHook\Director\PropertyModifier\PropertyModifierMODIFIERNAME;

$this->provideHook('director/PropertyModifier', PropertyModifierMODIFIERNAME::class);

Ich hoffe das Beispiel und die Erklärungen helfen demjenigen, der einen eigenen Modifier braucht, und ich konnte auch zeigen warum ich so ein großer Fan von Hilfe zur Selbsthilfe bin. Wer noch gar nichts mit den Import-Möglichkeiten des Directors anfangen kann, ist in der überarbeiteten Schulung Icinga 2 Advanced willkommen. Das Kapitel zu Import kommt aus meiner Feder und erklärt ausführlich und anhand von Übungen wie man Daten mittels SQL aus einer Datenbank importiert und mit dem Inhalt einer CSV-Datei ergänzt um Hosts anzulegen und aus einem LDAP-Verzeichnisdienst Benutzer und Gruppen zieht. Wer dagegen jemanden kennt, der ein bisschen Hilfe zur Selbsthilfe bekommen will, wir haben noch Ausbildungsplätze bei uns im Professional Services frei! Ich verspreche aber auch allen anderen Kollegen zu helfen, wenn sich jemand für eine der anderen Stellen interessiert! 😉

Das Beitragsbild kombiniert den Director von rones auf Openclipart mit dem Icinga-Logo.

Dirk Götz
Dirk Götz
Principal Consultant

Dirk ist Red Hat Spezialist und arbeitet bei NETWAYS im Bereich Consulting für Icinga, Puppet, Ansible, Foreman und andere Systems-Management-Lösungen. Früher war er bei einem Träger der gesetzlichen Rentenversicherung als Senior Administrator beschäftigt und auch für die Ausbildung der Azubis verantwortlich wie nun bei NETWAYS.