himpler.com himpler.com

Die eigene API mit Node-RED und Traefik

4 Min.

Zuletzt benötigte ich über eine HTTP-API Zugriff auf einige Daten aus meinem Heimnetzwerk. Der Zugriff musste auch ohne VPN von unterwegs funktionieren und sollte mit einer Authentifizierung geschützt sein. Wie sich so etwas leicht und schnell mit Node-RED und Traefik als Reverse Proxy umsetzen lässt, zeige ich in diesem Post.

Erzeugung einer API mit Node-RED

Ich nutze Node-RED zur Erstellung der API. Node-RED bringt dazu nicht nur bereits alles mit, sondern macht die Erstellung der Schnittstelle durch die GUI auch ziemlich einfach. Stehen die Daten schon irgendwo zur Verfügung ist das in wenigen Minuten erledigt.

Der eigentliche Flow zur Ausgabe der Daten über einen HTTP Response, v.l.n.r: HTTP-in, Switch und HTTP-Response-Node

In meinem Fall kommen die Daten eventbasiert aus unterschiedlichen Quellen und werden nach Ankunft mit einer Funktion (siehe unten) im Kontext des Flows gespeichert. Wird die API über eine URL aufgerufen, wird der jeweils aktuelle Stand der Daten aus dem Flow-Kontext geladen und als JSON ausgegeben.

const context = flow.get('somerandomkey') || {};
context[msg.topic] = msg.payload;
flow.set('somerandomkey', context);

return msg;

Die API öffentlich bereitstellen

Grundsätzlich ist die Node-RED Instanz nur innerhalb meines Netzwerks erreichbar. Und das soll, abgesehen von der HTTP-API, auch so bleiben. Da ich ohnehin schon Traefik als Reverse Proxy nutze, bietet sich dieses geniale Tool auch zur Freigabe der gebauten Schnittstelle an. Praktischerweise bringt Traefik bereits von Haus aus eine BasicAuth-Middleware mit. Diese schützt eine Route dann mit dem Basic-Authentifizierungsverfahren. Details zur Funktion gibt es auch in der Traefik-Dokumentation.

File Service Provider

Damit nicht die gesamte Node-RED Instanz im Netz landet, greife ich anstelle des Docker Service Providers in diesem Fall auf den File Service Provider zurück. Dieser wird zuerst in der Traefik Konfiguration aktiviert:

# traefik.yml
# ...

providers:
  file:
    filename: "/etc/traefik/dynamic_conf.yml"
    watch: true

# ...

Die Anpassung der traefik.yml ist fast selbsterklärend. Den Providern wird ein neuer Eintrag hinzugefügt. Der filename verweist dabei auf eine noch zu erstellende Konfigurationsdatei, watch sorgt für die automatische Überwachung von Änderungen. Sonst wäre bei jeder späteren Änderung ein Neustart von Traefik erforderlich.

Jetzt wird die oben referenzierte Datei befüllt:

# dynamic_conf.yml

http:
  routers:
    node-red-api-router:
      rule: "Host(`api.example.com`)"
      service: node-red-api
      middlewares:
        - "api-auth"
        - "add-api-prefix"
      entrypoints:
        - websecure
      tls:
        certResolver: letsencrypt

  middlewares:
    add-api-prefix:
      addPrefix:
        prefix: "/api"
    api-auth:
      basicAuth:
        users:
          - "someusername:$fy$95$A19KTpomnUW1NoszBcS"

  services:
    node-red-api:
      loadBalancer:
        servers:
        - url: "http://192.168.1.99:1880"

Middleware

Beginnen wir mit den Middlewares. Zum einen wird die Middleware basicAuth konfiguriert. Dort wird ein User unter Angabe eines BasicAuth-Strings angelegt. Zur Vereinfachung gibt es online zahlreiche Tools, die einem den passenden String generieren.

Jetzt müssen wir Traefik noch beibringen, dass unsere API unter dem Pfad /api erreichbar ist. Über die addPrefix Middleware wird jedem eingehenden Request ein /api vorangestellt. Somit ist auch sichergestellt, das selbst eingeloggte User nicht auf einen Pfad oberhalb des Prefix zugreifen können.

Service

Damit Traefik weiß, wohin eingehende Requests gesteuert werden sollen, definieren wir einen Service mit dem Namen node-red-api. Dieser wird mit der lokalen URL der Node-RED Instanz, also z.B. http://192.168.1.99:1880 konfiguriert. Node-RED kann also auch ohne weiteres auf einem anderen Gerät betrieben werden.

Router

Jetzt legen wir die Route an und binden die Middlewares und den Service daran an. Die rule wird mit dem gewünschten Hostnamen definiert, also der jeweiligen URL die auf Traefik verweist und unter der die Schnittstelle erreichbar sein soll. Im Post zum Einsatz von Traefik mit Docker habe ich z.B. den kostenfreien Dienst DuckDNS verwendet.

Unter dem Punkt service listen wir unseren node-red-api Service auf und unter middlewares entsprechend die Namen unserer Middlewares. Über den Entrypoint wird festgelegt, dass unsere API nur über HTTPS (Port 443) erreichbar ist. Damit unsere API auch ein gültiges Zertifikat hat, fügen wir über tlscertresolver unseren Zertifikat-Resolver hinzu. Die Konfiguration der letzten beiden Punkte wird auch im oben verlinkten Post erläutert.

Test der API

Da wir eine Änderung an der Hauptkonfiguration von Traefik gemacht haben, starten wir Traefik zunächst neu. Ruft man jetzt https://api.example.com/endpoint (die URL muss natürlich durch eure eigene ersetzt werden) im Browser auf, sollte das BasicAuth Anmeldefenster erscheinen. Mit den festgelegten Benutzerdaten könnt ihr euch anmelden und seht dann die Ausgabe des Aufrufs. Für einen automatisierten Abruf muss im Request der Authorization-Header gefüllt sein.

Fazit

Mit Hilfe von Node-RED und Traefik lässt sich sehr leicht eine öffentliche API-Schnittstelle mit SSL Verschlüsselung bauen. Über den FileServiceProvider lässt sich der Reverse Proxy übersichtlich in einer Datei konfigurieren. Dank SSL und BasicAuth ist der Service zumindest etwas geschützt. Hochsensible Daten sollte man so aber besser nicht bereitstellen. Wenn Du dich an der Anleitung orientierst gilt wie immer: Ich übernehme keine Haftung falls doch mal was schief geht.

Share this post!

Das könnte dir auch gefallen