Elastic ist ein sehr umfangreiches Werkzeug um Log-Einträge, jeder Art, gewinnbringend auszuwerten. Man kann damit Zugriffszahlen aus Webserver-Logs ableiten, Windows-Logs vereinen und übersichtlich gestalten, man kann sogar selbst erstellte Logdaten auf anschauliche Art und Weise auswerten.
Einen Elastic Server aufzusetzen, ist durch die Verwendung von Docker in sehr kurzer Zeit und auf jedem beliebigen Rechner, auf dem Docker läuft, machbar.
Install Elastic Search with Docker
Elastic besteht aus drei Teilen:
- Elasticsearch ist dabei das Herz des Servers, welches die gesamte Aufbewahrung, Verarbeitung und Durchsuchbarkeit der Daten ermöglicht.
- Kibana ist eine Weboberfläche, über die man die Daten auswerten kann und vor allem verschiedenste Arten von Diagrammen erstellen kann.
- Logstash ist das Einganstor zum Elasticsearch Server. Daten jeglicher Art können an die Logstash Instanz geschickt werden, sobald diese den entsprechenden Filter hat, werden diese direkt in den Elasticsearch Server gespeichert.
In meinem Artikel möchte ich nicht weiter auf Logstash eingehen, da ich es bis jetzt immer geschafft habe, die Daten so aufzubereiten, dass diese direkt an den Elasticsearch Server geschickt werden können.
Dies ist möglich, wenn man die Daten als JSON senden kann. Der Vorteil dabei ist, dass man nicht noch eine weitere Fehlerquelle durch einen defekten Logstash-Input-Filter untersuchen muss.
Elastic hat durch die Entwicklung von Beats einen weiteren wichtigen Baustein dazu beigesteuert, dass Logstash nicht immer nötig ist.
Mit Winlogbeat kann man das Eventlog eines jeden Windows Servers an den Elasticsearch Server schicken und dann im Kibana auswerten.
Früher fand ich (und finde es noch) das Ereignislog von Windows einfach nur grauenvoll. Sinnvolle, von sinnlosen Einträgen zu unterscheiden ist sehr schwer. Das beste Beispiel dafür ist für mich z.B., dass es nicht möglich ist (zumindest habe ich keine Lösung dafür gefunden) einen Benutzernamen in den Logs zu suchen. Ich kann diverse Filter setzen, aber nach dem Inhalt eines Eintrags kann ich nicht einfach suchen.
Nachdem jetzt alle Server brav ihre Daten in unserem Elasticsearch abgeben, kann ich einfach den Suchbegriff in die Suchleiste eingeben und nach beliebigen Dingen filtern.
Der größte Vorteil bei den Windows Ereignislogs ist für mich jedoch, es ist jetzt möglich durch eine grafische Auswertung Häufigkeiten festzustellen. Es fällt dann z.B. auf, dass ein bestimter Dienst häufig Logs durch, z.B. Abstürze oder Neustarts produziert.
Eine Sache zu den Indexen. Am Anfang haben wir fleißig alle Indizes tagesaktuell geschrieben. Dass heißt es gab dann in der Index-Übersicht sehr viele Einträge der Art:
web-log-2020-10-09
web-log-2020-10-08
web-log-2020-10-07
Die Daten die dabei anfallen sind durchaus sehr unterschiedlich. Elastic kann auch mit dieser Menge an Einzelindexen umgehen, es gibt aber einen Wert von maximal 1000 Indexen pro Knoten (Server). Diesen Wert kann man anheben aber es wird nicht empfohlen. Eine weitaus elegantere Lösung ist ein dynamischer Index. Dieser wird von Elastic selbständig verwaltet und man gibt nur noch an, was es für ein Limit für einen einzelnen Index geben soll. Standardmäßig sind z.B. 50 GB vorgesehen. Man kann dort aber auch eine maximale Anzahl von „docs“ (Einträgen) festlegen, oder ein maximales Alter.
Elastic API Key
Um Daten in den Elastic Server zu bekommen, kann man einerseits die alterhergebrachte Kombination Benutzer/Passwort benutzen. Einfacher und zukunftssicherer geht es aber mit API-Keys. Man kann sehr fein bestimmen, was ein API Key darf und kann für jede Anwendung einen eigenen erstellen. Es ist sogar möglich dem API-Key ein Ablaufdatum zu geben, so dass man z.B. Testzugänge für eine bestimmte Zeit geben kann.
POST /_security/api_key?pretty { "name": "windows_clients_defender_logs", "role_descriptors": { "role-a": { "cluster": ["none"], "index": [ { "names": ["windows-def*"], "privileges": ["create","create_index","write"] } ] } } }
Wichtig beim Erstellen des Keys ist der Name. Dort sollte man genauestens festhalten, wer zu welchem Zweck worauf zugreift. Dies ist nachher nicht mehr ohne weiteres Nachvollziehbar.
Die Antwort sieht dann z.B. so aus:
{ "id" : "3z2z-XUBT1MsipbxwsVsd", "name" : "windows_clients_defender_logs", "api_key" : "IL-93zaJ7S1wK3f8T8WB4zJQ" }
Wichtig bei der Verwendung des API-Keys; es muss immer das Format „id:api_key“ verwendet werden.
Es gibt bei github einen Post der vorschlägt als zusätzlichen Wert gleich die Base64 Variante mit zu geben, leider ist dass noch nicht weiter gekommen.
Wenn man den API-Key nämlich z.B. mit „curl“ verwenden möchte, muss man diesen vorher in Base64 umwandeln. In Linux geht das recht einfach mit
echo -n 'q-RoD3222ZxtEkCx2mF6:Hj1qAAAAbyoiYorLDyfwQ' | base64
M3oyei1YVUJUMU1pcGJ4VHNWc2o6SUwtOTN6SjdTMUszZjhUOFdCNHpKUQ==
Elastic Webserver Log
Damit die Daten des Apache-Webservers an den Elastic-Server geschickt werden können, müssen diese vorher aufbereitet werden. Dies kann z.B. mit LogStash gemacht werden. LogStash enthält eigene Module für solche Standard-Logs wie Apache. Es kann dabei sogar die Daten anreichern, z.B. die IP Adresse kann mit einem Geo-Tag versehen werden. Dies könnte man dann im Elastic wiederum auswerten.
Wir haben, wie bereits erwähnt, keinen LogStash im Einsatz. Aber Apache bietet auch die Möglichkeit Log-Daten in einem angepassten Format abzuspeichern. Um genauer zu sein, es ist sogar möglich diese Daten direkt über einen Socket zu verarbeiten.
Mit dem folgenden Schnipsel ist es möglich Daten direkt im, von Elastic präferierten, JSON-Format zu exportieren.
<VirtualHost *:443> LogFormat '@cee:{"client":"%h","request":"%r","status":"%>s","bytes":"%I","time_taken":"%D","filename":"%f","request_protocol":"%H","request_method":"%m","query_string":"%q","user_agent":"\"%{User-agent}i\","host":"%{Host}i"}' jsoncommon CustomLog "|/bin/logger -u /run/apache_log.socket" jsoncommon </VirtualHost>