Web Services als Datenquellen in Splunk verwenden - Ein Praxisleitfaden

Web Services als Datenquellen in Splunk verwenden

Ein Praxisleitfaden

Tomaso Vasella
von Tomaso Vasella
am 25. Juli 2019
Lesezeit: 15 Minuten

Keypoints

So nutzen Sie Web Services als Datenquellen für Splunk

  • Die Maschine-zu-Maschine Kommunikation nimmt eine immer wichtiger werdende Rolle ein
  • entsprechende Schnittstellen werden oft als APIs in Form von Web Services realisiert
  • solche Datenquellen für Analysen nutzen zu können ist eine häufige Anforderung
  • Splunk ist ein populäres Tool, das gerne für solche Aufgaben eingesetzt wird, aber keine eingebauten Funktionen für den Zugriff auf Web Service Datenquellen besitzt

Die Maschine-zu-Maschine Kommunikation nimmt eine immer wichtiger werdende Rolle in der modernen, von Digitalisierung geprägten Zeit ein. APIs sind keine neue Erscheinung: Bereits im Jahr 2000 konnte auf die Web-APIs von Salesforce und eBay zugegriffen werden. In den letzten Jahren gab es aber eine derart explosive Zunahme, dass man heute von einer API Economy spricht und es sogar Unternehmen gibt, deren Geschäftsmodell darauf basiert.

Themen wie Microservices oder IoT wären ohne derartige Möglichkeiten niemals so populär geworden, wie sie es heute sind. Mit der rasant zunehmenden Menge von erzeugten und gespeicherten Daten geht meistens auch der Wunsch einher, diese Daten über standardisierte Schnittstellen auszutauschen, zu analysieren und nutzbringende Informationen zu extrahieren. APIs in Form von Web Services spielen bei der Maschine-zu-Maschine Kommunikation eine zentrale Rolle und immer mehr Daten und Informationen sind auf diesem Weg verfügbar.

Solche Datenquellen für Analysen, Korrelationen usw. zu nutzen, ist eine häufige Aufgabenstellung. Dieser Beitrag zeigt ein mögliches Vorgehen, um mit Hilfe einer dafür erstellten Splunk App Daten von webbasierten APIs zu beziehen.

Splunk

Splunk ist ein populäres Tool, das Maschinendaten wie Logs, Metriken, usw. indexiert, speichert und visualisiert. Damit lassen sich umfangreiche Analysen und Korrelationen umsetzen und mittels Grafiken, Reports und Warnmeldungen anspruchsvolle Monitoring- und Reporting-Aufgaben lösen. Splunk lässt sich unter vielen modernen Betriebssystemen nutzen und kann mit einer Evaluierungslizenz während 60 Tagen mit vollem Funktionsumfang kostenlos genutzt werden.

Splunk Apps

Splunk besitzt von Haus aus viele Möglichkeiten, Daten von verschiedenen Quellen zu beziehen wie z.B. syslog über UDP/TCP oder das Lesen von Dateien mittels File Readern und Forwardern. Will man aber Daten von einer Schnittstelle beziehen, die nicht von Produkt bereits unterstützt wird oder vollständige Kontrolle über den Datenbezug ausüben, so braucht es eine entsprechende Erweiterung der Funktionalität. Dies wird meistens mit Hilfe einer App bzw. einem Add-on erreicht

Für den Zugriff auf webbasierte APIs wie REST-Schnittstellen sind keine vorgefertigten Möglichkeiten in Splunk vorhanden, so dass diese Funktionalität hier entsprechend als App realisiert wird. Hierbei erweist sich das in verschiedenen Entwicklungssprachen verfügbare SDK als nützlich; im Folgenden wird die Version für Python verwendet.

Dateneingaben (Data Inputs)

Datenquellen werden in Splunk über sogenannte Data Inputs angesteuert. Dies sind im Wesentlichen Definitionen, mit welchem Protokoll und ggf. mit welchen Credentials auf Datenquellen zugegriffen wird. Eine App kann eigene Data Inputs definieren, welche anschliessend über das GUI konfiguriert werden können. Diese Methode wird häufig für API-basierte Datenquellen eingesetzt. Das SDK enthält Funktionen, welche das Erstellen solcher Data Inputs stark vereinfacht. Die hier verwendete Datenquelle ist die API der VulDB; die nachfolgenden Ausführungen lassen sich jedoch einfach verallgemeinern und somit analog auf andere Datenquellen anwenden.

Neue App vorbereiten

Die einfachste Möglichkeit, mit dem Erstellen einer neuen App zu beginnen, bietet das Web GUI: Auf der Home Page auf Manage Apps (Gear Icon) klicken und dann Create app wählen. Für dieses Beispiel wurde als Name der App und des Verzeichnisses VulDB gewählt. Mit dem Klick auf App erstellen wird eine minimale App erzeugt, deren Verzeichnisstruktur im Pfad $SPLUNK_HOME/etc/apps/VulDB/ abgelegt wird:

bin/
    README
default/
    app.conf
    data/
        ui/
            nav/
                default.xml
            views/
                README
local/
    app.conf
metadata/
    default.meta
    local.meta

Weiterführende Informationen zu den verschiedenen Ordnern und Dateien von Apps finden sich in der Dokumentation.

SDK einbinden

Die benötigen Dateien aus dem Python SDK werden im Unterordner bin abgelegt. Es empfiehlt sich, nur diejenigen Ordner und Dateien des SDK nach bin zu kopieren, die in der App auch tatsächlich verwendet werden. Im vorliegenden Fall wird der Ordner splunklib aus dem SDK in das Verzeichnis bin/packages/ kopiert. Selbst entwickelte Scripts werden dann ebenfalls unter bin abgelegt.

Datenquelle ansteuern

Für den Zugriff auf die Datenquelle sind ein Client (im vorliegenden Fall die Python Library requests), eine geeignete Verarbeitung der Daten (hier JSON) und deren anschliessende Speicherung und Indexierung in Splunk nötig.

Das Erstellen eines Modular Input (eine bestimmte Art Data Input) ist dafür prädestiniert und lässt sich mit Hilfe des SDK recht einfach umsetzen. Dazu muss ein entsprechendes Skript geschrieben werden, welches folgende drei Aktivitäten ausführt:

  1. Ausgabe eines Schemas, welches Dinge wie die Konfiguration, mögliche Parameter und eine Beschreibung und des Inputs definiert;
  2. Validieren der Werte für die definierten Parameter, welche über das Web GUI eingegeben werden. Dieser Schritt ist optional, aber stark empfohlen;
  3. Übergabe der vom Skript bezogenen Daten an Splunk (Streaming).

Siehe hierzu auch die Dokumentation und weiterführende Beispiele.

Als erstes wird eine von splunklib.modularinput.script abgeleitete Klasse erstellt. Die genannten drei Schritte werden dann mit den dafür vorgesehenen Methoden get_scheme, validate_input und stream_events implementiert. Zusätzlich muss die Methode __main__ definiert werden, welche das Skript ausführt.

Um programmatisch auf APIs zuzugreifen ist es oft sinnvoll, einen dedizierten API Client zu implementieren. Damit lassen sich die Details der API-Interaktion besser abstrahieren und modularisieren und Themen wie Session Handling und Error Handling können eleganter gehandhabt werden. Eine beispielhafte Methode eines API Clients könnte wie folgt aussehen:

@request_error_handler
def get_latest_entries(self, latest=1000, details=0):
    post_data = {'format'  : 'json',
                 'recent'  : str(latest),
                 'details' : str(details)}

    return requests.post(self.url, data=post_data, headers=self.headers,
        proxies=self.proxies, verify=self.verify)

Die nachfolgenden Zeilen zeigen ein stark vereinfachtes Beispiel eines Skripts für einen modular Input anhand der erwähnten drei Methoden aus dem SDK:

import sys
import os
sys.path.insert(0, os.path.sep.join([os.path.dirname(__file__), 'packages']))

import splunklib.modularinput as mi
import json

class MyScript(Script):
    def get_scheme(self):
        scheme = mi.Scheme("VulDB")
        scheme.description = "Get information from VulDB, the number one vulnerability
                              database."

        scheme.add_argument(mi.Argument(name="api_key",
                                     title="VulDB API Key",
                                     description="The key for accessing the VulDB API",
                                     data_type=mi.Argument.data_type_string,
                                     required_on_create=True,
                                     required_on_edit=False))
        return scheme

    def validate_input(self, v):
        if 'api_key' in v.parameters:
            try:
                if not v.parameters['api_key'].isalnum():
                    raise ValueError('VulDB API key must be alphanumeric')
            except Exception as e:
                raise ValueError('VulDB API key must be alphanumeric')

    def stream_events(self, inputs, ew):
        for input_name, input_item in inputs.inputs.iteritems():

            # res contains the response of a web request to the VulDB API
            # such as the above example
            for data in res.json()['result']:
                try:
                    event = mi.Event()
                    event.stanza = input_name
                    event.data = json.dumps(data)
                    ew.write_event(event)
                except Exception as e:
                    ew.log('ERROR', 'An error has occurred writing data: {}'.format(e))

if __name__ == "__main__":
    sys.exit(MyScript().run(sys.argv))

Logging ist optional, wird aber wärmstens empfohlen. Dafür steht die Methode log() mit verschiedenen Kritikalitätsstufen wie INFO oder ERROR zur Verfügung. Die Logmeldungen werden in die Datei splunkd.log geschrieben.

Paginierung (Pagination)

Fragt ein API Client grosse Mengen an Daten ab, beispielsweise alle verfügbaren Daten in einem Zeitraum, kann es wünschenswert oder nötig sein, die Anfrage in Teilanfragen zu unterteilen, denn viele APIs schränken die Menge an Daten ein, die mit einem einzelnen Request angefragt werden kann. Um dies korrekt zu handhaben, wird in der Regel ein Paginierungsverfahren (Pagination) eingesetzt. Dabei gibt der API Client entsprechende Parameter in der Anfrage mit und definiert so, wo in der Sequenz der verfügbaren Daten die Anfrage beginnt (Seitennummer) und wie viele Daten ausgegeben werden sollen (Anzahl Datensätze pro Seite). Dies erfordert einerseits eine entsprechende Logik im Client und andererseits muss sich der Client merken, welche Datenpunkte er als letzte abgefragt hat, um in nachfolgenden Anfragen dort anzuknüpfen.

Schutz von API Schlüsseln

Häufig können APIs nur mit entsprechenden Schlüsseln verwendet werden. Solche Schlüssel sollten geschützt werden und nicht im Klartext in Skripts oder Konfigurationsdateien einsehbar sein. Splunk bietet die Möglichkeit sogenannter Storage Passwords. Das Passwort bzw. der API Key wird mit einem Schlüssel verschlüsselt, der sich auf dem Splunk Server befindet. Nur Benutzer mit der Rolle Admin können solche Passwörter einsehen, abgesehen von Systemadministratoren mit Zugriff auf das Dateisystem.

Nachfolgend sind Beispiele für das ablegen und auslesen solcher Credentials aufgeführt, wobei in diesem Beispiel als Benutzername der String api_key_label verwendet wird.

def protect_key(self, key):
    try:
        for storage_password in self.service.storage_passwords:
            if storage_password.username == self.api_key_label:
                self.service.storage_passwords.delete(username = self.api_key_label)
                break

        self.service.storage_passwords.create(key, self.api_key_label)
    except Exception as e:
        raise Exception("An error occurred protecting key: {}".format(e))

def get_protected_key(self):
    try:
        for storage_password in self.service.storage_passwords:
            if storage_password.username == self.api_key_label:
                return storage_password.content.clear_password
    except Exception as e:
        raise Exception("An error occurred retrieving protected key: {}".format(e))

Nachdem das Skript fertiggestellt wurde, kann es in eine App integriert werden. Dazu sind folgende Schritte erforderlich:

  1. Skript und SDK paketieren
  2. Erstellen der Datei app.conf
  3. Erstellen der Datei inputs.conf.spec
  4. Installation der App durch Ablegen des Pakets unter $SPLUNK_HOME/etc/apps/

Ausgehend von der oben erzeugten Ordnerstruktur wird das erstellte Modular Input Script in das Verzeichnis bin kopiert, ebenso alle weiteren erstellten Scripts wie z.B. der oben erwähnte API Client. Die resultierende Verzeichnisstruktur sieht damit so aus:

bin/
  packages/
    splunklib/
    VulDB.py
    VulDBApi.py
  README
default/
    app.conf
    data/
        ui/
            nav/
                default.xml
            views/
                README
local/
    app.conf
metadata/
    default.meta
    local.meta

Nun wird die Datei app.conf angepasst, welche verschiedene Aspekte der App definiert.

 [install]
is_configured = 0

[ui]
is_visible = 1
label = VulDB

[launcher]
author = VulDB
description = VulDB
version = 0.0.1

Die Konfiguration des Modular Input muss manuell erstellt werden. Als erstes muss dazu das Verzeichnis README auf der gleichen Ebene wie bin erstellt werden. Darin wird nun die Datei inputs.conf.spec erzeugt:

[VulDB://<name>]
vuldb_lang =
api_key =
details =

Die Zeilen müssen den im Modular Input Script mit der Methode scheme.add_argument definierten Parametern entsprechen. Weiterführende Infos finden sich in der Dokumentation.

Es resultiert damit folgende Verzeichnisstruktur:

bin/
  packages/
    splunklib/
    VulDB.py
    VulDBApi.py
  README
default/
    app.conf
    data/
        ui/
            nav/
                default.xml
            views/
                README
local/
    app.conf
metadata/
    default.meta
    local.meta
README/
    inputs.conf.spec

Als letzter Schritt muss diese gesamte Verzeichnisstruktur unter $SPLUNK_HOME/etc/apps/ abgelegt werden. Damit ist die App und der enthaltene Modular Input installiert. Splunk muss neu gestartet werden, damit diese Erweiterungen im Web GUI sichtbar werden. Die App sollte nun im GUI erscheinen und der definierte Modular Input ist im Menu Settings unter Data Inputs zu finden.

Datenformat einrichten

Die in diesem Beispiel bezogenen Daten werden im JSON Format vom API zurückgeliefert. Damit Splunk die Daten korrekt indexieren kann, wird eine entsprechende Konfiguration definiert. Dies geschieht in der Datei props.conf, die sich im Verzeichnis default/ befindet. Hier kann ausserdem definiert werden, wie der Zeitstempel aus den Daten extrahiert wird, sofern ein solcher in den Daten enthalten ist bzw. dieser verwendet werden soll.

[VulDB]
TRUNCATE = 0
TIME_PREFIX = timestamp":.*create":
TIME_FORMAT = %s
TZ = UTC
INDEXED_EXTRACTIONS = JSON

Als letzter Schritt wird nun im Web GUI eine neue Instanz des Modular Input erstellt und konfiguriert, entsprechend der im Skript und in der Datei inputs.conf.spec definierten Parameter. Hier kann auch festgelegt werden, welcher Splunk Source Type und welcher Index für die Datenspeicherung verwendet werden soll. Sobald das Skript erfolgreich ausgeführt wurde, werden die bezogenen Daten indexiert und gespeichert und stehen für die weitere Verwendung zur Verfügung.

Fazit

Die Kommunikation mit webbasierten APIs und deren Verwendung als Datenquellen für Analysen ist ein gefragter Anwendungsfall. Mit vergleichsweise geringem Aufwand lassen sich mit Splunk und dem zugehörigen SDK Lösungen in Form von Apps dafür entwickeln. Die native Unterstützung gängiger Datenformate wie JSON durch Splunk und die Verfügbarkeit leistungsfähiger Bibliotheken für den Webzugriff erweisen sich dabei als sehr nützlich. Es empfiehlt sich in der Regel, für die Kommunikation mit dem API und die Fehlerbehandlung einen dedizierten API Client zu implementieren. Ausserdem muss darauf geachtet werden, Credentials bzw. API Keys angemessen zu schützen und eventuelle Besonderheiten des angesprochenen APIs wie Paginierung zu berücksichtigen. Sobald die Daten in Splunk indexiert und gespeichert sind, stehen sie für Analysen, Korrelationen und Visualisierungen zur Verfügung. Das beschriebene Vorgehen lässt sich analog auch für andere Datenquellen verwenden und bietet somit eine rasch realisierbare und allgemein nützliche Lösung für Datenanalysen.

Über den Autor

Tomaso Vasella

Tomaso Vasella hat seinen Master in Organic Chemistry an der ETH Zürich abgeschlossen und ist seit 1999 im Bereich Cybersecurity aktiv. Positionen als Berater, Engineer, Auditor und Business Developer zählen zu seinen Erfahrungen. (ORCID 0000-0002-0216-1268)

Links

Sie wollen Ihr Log und Monitoring auf das nächste Level bringen?

Unsere Spezialisten kontaktieren Sie gern!

×
Datenverschlüsselung in der Cloud

Datenverschlüsselung in der Cloud

Tomaso Vasella

Offerten erstellen

Offerten erstellen

Tomaso Vasella

Microsoft Teams Security

Microsoft Teams Security

Tomaso Vasella

Sie wollen mehr?

Weitere Artikel im Archiv

Sie brauchen Unterstützung bei einem solchen Projekt?

Unsere Spezialisten kontaktieren Sie gern!

Sie wollen mehr?

Weitere Artikel im Archiv