Eine sichere API mit gRPC erstellen
Vitalis Ogbonna
25. August 2022
0 Min. LesezeitEin Google Remote Procedure Call (gRPC) ist Googles Open-Source-Version des Remote-Procedure-Call-Frameworks (RPC). Es handelt sich um ein Kommunikationsprotokoll, das HTTP/2 und Protocol-Buffer-Technologien (protobuf) nutzt. Mit gRPC kann ein Remote-Client oder -Server mit einem anderen Server kommunizieren, indem er einfach die Funktion des empfangenden Servers aufruft, als wäre sie lokal verfügbar. Dadurch lassen sich in verteilten Systemen große Datenmengen viel einfacher zwischen Client und Server übertragen.
Wie andere RPC-Systeme definiert gRPC einen Service. Seine Methoden und Rückgabetypen werden mithilfe von protobuf festgelegt – einem Google-Protokoll zur Serialisierung und Deserialisierung. So lassen sich Services einfach definieren und Clientbibliotheken automatisch generieren. gRPC verwendet dieses Protokoll, derzeit in Version 3, als Schnittstellendefinitionssprache und Serialisierungstoolset.
Für die meisten modernen Anwendungen ist gRPC dank seiner hervorragenden Unterstützung aller Datentypen eine ausgezeichnete Wahl. Es eignet sich besonders für große Datenmengen, etwa bei Streaming-Daten, kann für einfache Anwendungen, bei denen umfangreiche Datenübertragungen kaum eine Rolle spielen, jedoch überdimensioniert sein.
In diesem Artikel erfahren Sie, wie Sie gRPC für die client- und serverähnliche Kommunikation zwischen zwei Node.js-Anwendungen verwenden. Außerdem stellen wir einige Sicherheitsmaßnahmen für den Einsatz von gRPC als Kommunikationsmechanismus in Ihren Services vor.
Voraussetzungen für das Tutorial
Für dieses Tutorial müssen OpenSSL und Node.js (Version 4.0 oder höher) auf Ihrem PC installiert sein. Grundkenntnisse in Node.js und JavaScript sind unerlässlich. Außerdem benötigen Sie in Ihrer Arbeitsumgebung Administratorrechte.
Node.js-Projekt einrichten
Erstellen Sie zunächst für die Ordnerstruktur der Anwendung einen Ordner mit dem Namen event-app-node-grpc und initialisieren Sie ein Node.js-Projekt mit npm, indem Sie die folgenden Befehle eingeben:
Nachdem Sie Ihre Anwendung initialisiert haben, erstellen Sie die folgende Ordnerstruktur. Den vollständigen, in diesem Tutorial verwendeten Code finden Sie auf GitHub:
Pakete installieren
Wechseln Sie im Terminal zum Stammverzeichnis Ihrer Anwendung. Installieren Sie die folgenden Pakete mit dem Befehl npm install, wie im folgenden Codeausschnitt gezeigt:
Sehen wir uns die Pakete an, die Sie im obigen Codeausschnitt installiert haben:
Expressist der HTTP-Server Ihrer Anwendung.@grpc/grpc-jsist eine gRPC-Bibliothek für Node.js. Damit können wir einen gRPC-Service in der Node.js-Laufzeitumgebung erstellen.@grpc/proto-loaderist ein Paket, das zum Laden von protobuf-Dateien für die Verwendung mit gRPC benötigt wird. Es nutzt Version 3 des Paketsprotobuf.js.
Öffnen Sie nach der Installation der oben genannten Pakete die Datei package.json und ergänzen Sie die folgenden Konfigurationen in den scripts-Tags, wie im nachstehenden Codeausschnitt gezeigt:
Die oben gezeigten zusätzlichen Konfigurationen dienen der Laufzeitkonfiguration der Anwendung und der Erstellung des SSL-Zertifikats. Nach dem Hinzufügen sollte Ihre aktualisierte Datei package.json dem folgenden Codeausschnitt ähneln:
Der obige Codeausschnitt zeigt die aktualisierte Datei package.json mit den Befehlen für die Laufzeitkonfiguration der Anwendung und die Erstellung des SSL-Zertifikats im scripts-Tag.
Protocol Buffer definieren
Dieses Tutorial zeigt, wie Sie gRPC in einer einfachen Anwendung zur Ereignisverfolgung verwenden. Die Demoanwendung nimmt Ereignisdetails entgegen und speichert sie in einer In-Memory-Datenbank. Die Ereignisdaten können aktualisiert, abgerufen und gelöscht werden.
In gRPC-Anwendungen befinden sich die Service-Schnittstelle und die benötigten Payloads in einer protobuf-Datei, damit verschiedene Anwendungen miteinander kommunizieren können. protobuf-Dateien haben die Erweiterung .proto, wie im Schema für unsere Projekteinrichtung dargestellt.
Erstellen Sie nun im Stammverzeichnis Ihrer Anwendung eine Datei namens events.proto und fügen Sie den folgenden Code ein. Zur Orientierung können Sie sich die zuvor definierte Schema-Struktur des Projekts ansehen.
In den obigen Codeausschnitten für die proto-Definition haben wir zunächst mit der Definition syntax = "proto3" die Protocol-Buffer-Version angegeben und anschließend die Protocol-Service-Definition festgelegt.
Als Nächstes haben wir in der Beschreibung des Protocol-Event-Service einen Service namens EventService erstellt. Innerhalb dieses Services haben wir rpc-Funktionen mit den erforderlichen Parametern und erwarteten Rückgabewerten definiert. Sie können so viele Services definieren, wie Ihre Anwendung benötigt. Der Einfachheit halber definieren wir hier jedoch nur einen.
In der Definition von EventService haben wir außerdem die Datentypen für die rpc-Funktion sowie die Rückgabewerte mithilfe des eindeutigen Feldnummerierungssystems von gRPC festgelegt. Dieses beschreibt, wie viele Bytes bei der Codierung verwendet werden. Weitere Informationen finden Sie in der offiziellen protobuf-Dokumentation.
gRPC-Server erstellen
Erstellen Sie entsprechend der oben beschriebenen Ordnerstruktur im Stammverzeichnis Ihrer Anwendung einen Ordner namens server und darin die Datei index.js. Fügen Sie den folgenden Codeausschnitt in die neu erstellte Datei server/index.js ein:
Im obigen Codeausschnitt haben wir die zuvor definierte Datei events.proto als Variable PROTO_PATH importiert und mit der Methode loadSync der Bibliothek protoLoader geladen. Anschließend haben wir die proto-Definitionen in der Variable eventsProto gespeichert, die alle proto-Definitionen enthält.
Fügen Sie nun direkt nach der Variable eventsProto den folgenden Codeausschnitt in die zuvor definierte Datei server/index.js ein.
Im obigen Codeausschnitt haben wir das Paket node:crypto und seine Funktion randomUUID eingebunden, mit der zufällige eindeutige Zeichenfolgen für unsere Ereignis-IDs generiert werden. Da wir für dieses Tutorial eine In-Memory-Datenbank verwenden, definieren wir sie als Array, in dem unsere Ereignisliste gespeichert wird. Anschließend richten wir unsere Serverinstanz ein, indem wir eine neue Methode grpc.Server aufrufen.
Als Nächstes registrieren wir die Anwendungsservices. Fügen Sie dazu den folgenden Codeausschnitt direkt nach der Variable server im obigen Code ein:
Im obigen Codeausschnitt haben wir die Methode addService für die gRPC-Serverinstanz aufgerufen, um die Anwendungsservices zu registrieren. Dabei handelte es sich im Wesentlichen um Vorgänge zum Erstellen, Lesen und Aktualisieren von Ereignissen.
Damit der Anwendungsserver gestartet werden kann, fügen Sie den folgenden Codeausschnitt direkt nach der Methode addService aus dem obigen Code ein.
gRPC-Client erstellen
Erstellen Sie entsprechend der oben beschriebenen Ordnerstruktur im Stammverzeichnis Ihrer Anwendung einen Ordner namens client. Legen Sie darin zwei Dateien an: index.js und app.js. Fügen Sie den folgenden Codeausschnitt in die Datei client/app.js ein.
Im obigen Codeausschnitt haben wir die zuvor erstellten proto-Definitionen importiert, mit protoLoader geladen, den grpc-Client mit der IP-Adresse der Serveranwendung verbunden und den Event-Service unter dem Variablennamen client exportiert. Außerdem haben wir dem Client ein SSL-Zertifikat zur Authentifizierung und Verschlüsselung der Client-Server-Kommunikation hinzugefügt.
Fügen Sie anschließend den folgenden Codeausschnitt in die Datei client/index.js ein:
Im obigen Codeausschnitt haben wir event-service aus der Datei client/app.js importiert. Anschließend haben wir einen Express-Server mit einfachen Endpunkten zum creation, update, fetch und delete von Ereignissen eingerichtet. Dafür rufen wir die Serveranwendung mithilfe von gRPC-Techniken remote auf.
Server- und Clientanwendungen testen
Nun können wir unsere Arbeit testen und prüfen, ob alles wie geplant funktioniert.
Der Server
Wechseln Sie im Terminal zum Stammverzeichnis des Projekts und führen Sie dann die folgenden Befehle aus:
Die Serveranwendung sollte unter http://localhost:50051 erreichbar sein:
Der Client
Öffnen Sie ein neues Terminalfenster, wechseln Sie vom Stammverzeichnis Ihrer Anwendung in den client-Ordner und führen Sie dann die folgenden Befehle aus:
Die Anwendung sollte unter http://localhost:50050 erreichbar sein:
Rufen Sie zum Testen localhost:50050 in Ihrem Browser auf oder verwenden Sie ein API-Testtool wie Postman. Sie sollten das Standardereignis sehen, das wir anfangs zu unserem Ereignis-Array hinzugefügt haben. Die Antwort sollte mit dem folgenden Screenshot übereinstimmen:

gRPC-API authentifizieren und absichern
Das gRPC-Protokoll unterstützt verschiedene Authentifizierungsmechanismen und lässt sich dadurch einfach an neue und bestehende Systeme anpassen. Die Authentifizierung in der gRPC-Client-Server-Kommunikation können wir mithilfe empfohlener Mechanismen wie SSL und TLS implementieren, mit oder ohne Google-Token-basierte Authentifizierung. Außerdem können wir eine benutzerdefinierte Authentifizierung erstellen, indem wir die integrierte Authentifizierungsfunktion von gRPC erweitern.
Standardmäßig umfasst gRPC die folgenden Authentifizierungsmechanismen:
SSL und TLS zur Authentifizierung des Servers und zur Verschlüsselung der zwischen Client und Server ausgetauschten Daten
ALTS (ein von Google entwickeltes gegenseitiges Transport- und Authentifizierungsprotokoll) zur Absicherung der RPC-Kommunikation von Anwendungen auf der Google Cloud Platform (GCP)
Ein generischer Token-basierter Authentifizierungsmechanismus zum Hinzufügen metadatenbasierter Anmeldedaten zu Anfragen und Antworten
Wie in der Einleitung des Tutorials erwähnt, implementieren wir die Authentifizierung in diesem Tutorial mit SSL. Anschließend ändern wir den Code in den Dateien client/app.js und server/index.js, damit er diese neue Funktion unterstützt.
SSL-Zertifikat mit OpenSSL generieren
Generieren wir zunächst mit OpenSSL ein SSL-Zertifikat. Dazu muss OpenSSL installiert sein. Außerdem benötigen Sie die Berechtigung zum Ausführen von Bash-Skripten. Diese Voraussetzungen sind wichtig, um Berechtigungsfehler zu vermeiden.
Erstellen Sie in unserer Ordnerstruktur einen Ordner namens scripts und darin eine Datei namens generate-certs.sh. Fügen Sie den folgenden Codeausschnitt in die Datei ein:
Der obige Code generiert die SSL-Zertifikate, die für eine sichere, verschlüsselte Verbindung zwischen Server- und Clientanwendung erforderlich sind. Bei der Ausführung erstellt er einen Ordner certs, generiert mit OpenSSL die SSL-Zertifikate für Server und Client und speichert sie anschließend im Ordner certs. Weitere Informationen zu diesen Konfigurationen und ihrer Funktion finden Sie auf der OpenSSL-Website.
SSL-Zertifikat für die Anwendung mit npm generieren
Verwenden Sie nun das Skript, um ein SSL-Zertifikat für Ihre Anwendung zu generieren. Führen Sie dazu im Terminal im Stammverzeichnis der Anwendung die folgenden Befehle aus.
Dadurch wird ein Ordner certs erstellt, der die generierten SSL-Zertifikate enthält.
Beachten Sie, dass dafür Administratorrechte erforderlich sind. Wenn beim Ausführen des Skripts ein Berechtigungsfehler auftritt, erteilen Sie dem Skript mit den folgenden Befehlen die Berechtigung zum Ausführen und versuchen Sie es dann erneut.
Im Terminal sollte folgende Ausgabe erscheinen:
Dateien client/app.js und server/index.js aktualisieren
Wir haben nun die SSL-Zertifikate generiert, die zur Authentifizierung unserer gRPC-APIs erforderlich sind. Als Nächstes ändern wir die Dateien client/index.js und server/index.js, damit sie mit diesen generierten Zertifikaten arbeiten.
In der unten gezeigten aktualisierten Datei client/app.js haben wir das Modul fs hinzugefügt, um die generierten Zertifikate einzulesen. Anschließend haben wir damit gRPC-SSL-Anmeldedaten erstellt und diese schließlich auf den gRPC-Service angewendet.
Auch in der unten gezeigten aktualisierten Datei server/index.js haben wir das Modul fs hinzugefügt, um die generierten Zertifikate einzulesen. Anschließend haben wir damit gRPC-SSL-Anmeldedaten erstellt und diese auf den Server angewendet.
Server- und Clientanwendungen ausführen
Wir haben erfolgreich eine Lösung zur Ereignisverwaltung mithilfe der gRPC-Spezifikationen implementiert. Um die Endpunkte zu testen, starten Sie die Anwendung über das Terminal und führen Sie die folgenden Schritte aus.
Der Server
Navigieren Sie im Terminal zum Stammverzeichnis des Projekts und führen Sie die folgenden Befehle aus:
Anschließend sollte die Serveranwendung unter http://0.0.0.0:50051 verfügbar sein:
Der Client
Öffnen Sie ein neues Terminalfenster, navigieren Sie vom Stammverzeichnis Ihrer Anwendung zum Client-Ordner und führen Sie anschließend die folgenden Befehle aus:
Anschließend sollte die Client-Anwendung unter http://localhost:50050 verfügbar sein:
Rufen Sie zum Testen der Anwendung in Ihrem Browser localhost:50050 auf oder verwenden Sie ein API-Testtool wie Postman. Sie sollten das Standardereignis sehen, das wir anfangs zu unserem Events-Array hinzugefügt haben. Ihre Antwort sollte mit dem folgenden Screenshot übereinstimmen:

Sie können nun weitere Endpunkte der Anwendung testen, um sicherzustellen, dass alles wie erwartet funktioniert.
Sie haben eine sichere API mit gRPC erstellt!
In diesem Tutorial haben wir mit Node.js eine einfache API in gRPC erstellt und ihre Funktionsweise sowie zahlreiche Vorteile beleuchtet, darunter HTTP/2 und SSL/TLS für die durchgängige Authentifizierung und Verschlüsselung zur Verbesserung der API-Sicherheit.
Trotz dieser Vorteile hat gRPC auch Schwächen: Dazu zählen die eingeschränkte Browser-Unterstützung, das nicht menschenlesbare Datenformat, die steile Lernkurve und die mangelnde Unterstützung für Edge-Caching. Doch ungeachtet dieser Einschränkungen ist gRPC dank seiner unübertroffenen Leistung und Mehrsprachigkeit die beste Option für die Kommunikation zwischen internen Microservices. Das gRPC-Protokoll ist beeindruckend und hat seit seiner ersten Veröffentlichung im August 2016 in der Branche breite Akzeptanz gefunden. Dieser Trend wird sich zweifellos fortsetzen.
Mit gRPC können Sie noch vieles mehr tun. Das Beispiel in diesem Tutorial kratzt nur an der Oberfläche dessen, was gRPC zu bieten hat. In der Dokumentation können Sie Ihr Wissen über gRPC vertiefen, um die Kommunikationsprozesse Ihrer Anwendung und Strategien zur Gewährleistung der gRPC-Sicherheit zu verbessern.
