BLOG | NGINX

Von OpenAPI zu NGINX als API-Gateway mithilfe einer deklarativen API

NGINX-Teil-von-F5-horiz-schwarz-Typ-RGB
Fabrizio Fiorucci Miniaturbild
Fabrizio Fiorucci
Veröffentlicht am 17. Juni 2024

NGINX gilt seit langem als eine der besten Optionen für den Betrieb leistungsstarker Webserver und Lastenausgleichsmodule. Mit dem Aufkommen von Microservices-Architekturen und dem Bedarf an effizienter API-Verwaltung ist NGINX jedoch auch eine beliebte Wahl für den Aufbau von API-Gateways geworden.

In diesem Blog untersuchen wir, wie eine OpenAPI-Schemadefinition in eine voll funktionsfähige NGINX-Konfiguration umgewandelt wird, die als API-Gateway mit Web Application Firewall- Sicherheit und Entwicklerportal unter Verwendung eines deklarativen API-Ansatzes ausgeführt wird.

Wir bieten Ihnen Schritt-für-Schritt-Anleitungen und Einblicke, wie Sie NGINX Plus nutzen können, um Ihre API-Verwaltungsprozesse zu optimieren und eine optimale Leistung für Ihre Anwendungen sicherzustellen.

Einführung des API-Gateways

Ein API-Gateway dient als zentraler Hub zum Verwalten und Sichern der Kommunikation zwischen Clients und Backend-Diensten. Es fungiert als Reverse-Proxy, der zwischen dem Client und den Backend-Servern sitzt, eingehende Anfragen weiterleitet und an die entsprechenden Dienste verteilt. Dies ermöglicht eine effizientere Kommunikation zwischen dem Client und den Diensten und ermöglicht es dem API-Gateway, Aufgaben wie Authentifizierung , Autorisierung , Ratenbegrenzung und Caching zu übernehmen.

Darüber hinaus kann ein API-Gateway als Sicherheitsebene fungieren und die Backend-Dienste vor potenziellen Bedrohungen und Angriffen schützen. Es kann Sicherheitsmaßnahmen wie Verschlüsselung, tokenbasierte Authentifizierung und Zugriffskontrolle durchsetzen und so sicherstellen, dass nur autorisierte Benutzer auf die Dienste zugreifen können. Durch die Konsolidierung und Verwaltung dieser Sicherheitsfunktionen an einem einzigen Ort trägt das API-Gateway dazu bei, die allgemeine Sicherheitsarchitektur des Systems zu vereinfachen und die Komplexität der Implementierung von Sicherheitsmaßnahmen über mehrere Dienste hinweg zu verringern.

NGINX Declarative API-Projekt

Das von der Community unterstützte NGINX Declarative API- Projekt bietet eine Reihe deklarativer REST-APIs für den NGINX Instance Manager .

Es kann verwendet werden, um NGINX Plus-Konfigurationslebenszyklen zu verwalten und NGINX Plus-Konfigurationen mithilfe von JSON-Dienstdefinitionen zu erstellen. Bei Verwendung mit NGINX Instance Manager wird die GitOps-Integration unterstützt: Die Quelle der Wahrheit wird auf Aktualisierungen referenzierter Objekte überprüft und NGINX-Konfigurationen werden automatisch synchronisiert.

OpenAPI-Schemas können verwendet werden, um NGINX automatisch als API-Gateway zu konfigurieren. Die Erstellung von Entwicklerportalen wird durch Redocly unterstützt.

Voraussetzungen

Um die Inhalte dieses Blogs auszuführen, benötigen Sie:

  • Eine laufende Instanz von NGINX Instance Manager
  • Ein Abonnement (oder eine 30-tägige kostenlose Testversion ) für NGINX Plus und NGINX App Protect WAF . NGINX Agent muss installiert sein, um eine Verbindung zum NGINX Instance Manager herzustellen und Teil der declarativeAPITest- Instanzgruppe zu sein
  • Ein Linux-Host (Bare Metal oder VM) mit Docker und Docker-Compose zum Ausführen des NGINX Declarative API-Projekts
  • Postman zum Senden der deklarativen API-Anfragen
  • Ein Client-Host zum Ausführen von Postman

Laborübersicht

Nach der Installation und Ausführung aller Voraussetzungen zeigt der NGINX Instance Manager die NGINX Plus-Instanz mit NGINX App Protect WAF als online an.

Die NGINX Plus-Instanz ist Teil der declarativeAPITest -Instanzgruppe

Bereitstellung der deklarativen API

Das NGINX Declarative API-Projekt basiert auf der vom NGINX Instance Manager bereitgestellten REST-API und bietet die deklarative, JSON-basierte Abstraktion. Befolgen Sie diese Anweisungen, um das deklarative API-Projekt auszuführen:

1. Führen Sie „docker ps“ aus, um zu überprüfen, ob Docker ausgeführt wird:


f5@ubuntu:~$ docker ps
CONTAINER-ID IMAGE-BEFEHL ERSTELLT STATUS PORTS NAMEN


2. Klonen Sie auf dem Linux-Host das Github-Repository:


f5@ubuntu:~$ git clone https://github.com/f5devcentral/NGINX-Declarative-API/
Klonen in „NGINX-Declarative-API“...
remote: Objekte aufzählen: 4072, fertig.
Remote: Objekte zählen: 100 % (1982/1982), erledigt.
Fernbedienung: Komprimieren von Objekten: 100 % (1332/1332), fertig.
Remote: Gesamt 4072 (Delta 668), wiederverwendet 876 (Delta 609), Pack-wiederverwendet 2090
Empfangene Objekte: 100 % (4072/4072), 19,05 MiB | 4,88 MiB/s, fertig.
Auflösen von Deltas: 100 % (1154/1154), erledigt.
f5@ubuntu:~$


3. Wechseln Sie in das Docker-Compose-Verzeichnis:


f5@ubuntu:~$ cd NGINX-Declarative-API/contrib/docker-compose/


4. Verwenden Sie das Skript nginx-dapi.sh, um alle Container über Docker-Compose zu starten. Beim ersten Start werden alle Docker-Images automatisch erstellt:


f5@ubuntu:~/NGINX-Declarative-API/contrib/docker-compose$ ./nginx-dapi.sh -c start
-> Docker-Images aktualisieren
[+] 11/11 abrufen
[...]
-> NGINX Declarative API bereitstellen
[+] 4/4 ausführen
✔ Netzwerk nginx-dapi_dapi-network erstellt 0,1 s 
✔ Container redis gestartet 1,5 s 
✔ Container devportal gestartet 1,5 s 
✔ Container nginx-dapi gestartet


5. Überprüfen Sie laufende Docker-Container:


f5@ubuntu:~/NGINX-Declarative-API/contrib/docker-compose$ docker ps
CONTAINER-ID IMAGE BEFEHL ERSTELLT STATUS PORTS NAMEN
e29a2f783da2 nginx-declarative-api "/deployment/env/bin…" vor 5 Minuten Aktiv vor 5 Minuten 0.0.0.0:5000->5000/tcp, :::5000->5000/tcp nginx-dapi
97142840eaf7 redis "docker-entrypoint.s…" vor 5 Minuten Aktiv vor 5 Minuten 0.0.0.0:6379->6379/tcp, :::6379->6379/tcp redis
6b50c0426643 nginx-declarative-api-devportal "/deployment/src/sta…" vor 5 Minuten Aktiv seit 5 Minuten 0.0.0.0:5001->5000/tcp, :::5001->5000/tcp devportal


6. Führen Sie auf dem Client-Host Postman aus und importieren Sie die NGINX Declarative API-Sammlung unter https://raw.githubusercontent.com/f5devcentral/NGINX-Declarative-API/main/contrib/postman/NGINX%20Declarative%20API.postman_collection.json.

7. Bearbeiten Sie die Postman-Sammlungsvariablen, um sie an Ihre Umgebung anzupassen:

8. Legen Sie die folgenden Variablen fest:

  • ncg_host - Hostname oder IP-Adresse des Linux-Hosts, auf dem die deklarative API Docker-Compose ausgeführt wird
  • ncg_port – TCP-Port für die NGINX Declarative API: 5000 ist der Standardwert
  • nim_host – Basis-URL des NGINX Instance Managers (z. B. https://nms.k8s.ie.ff.lan)
  • nim_username – NGINX Instance Manager-Authentifizierungsbenutzername
  • nim_password - Authentifizierungskennwort für NGINX Instance Manager

9. Alle Änderungen in Postman speichern

10. Navigieren Sie in der Postman-Sammlung zu Petstore API Gateway RateLimit + JWT AuthN/AuthZ + WAF und öffnen Sie die Anfrage

Die JSON-Deklaration sieht wie folgt aus:


{
"Ausgabe": {
"Typ": "nms",
"nms": {
"URL": "{{nim_host}}",
"Benutzername": "{{nim_username}}",
"Passwort": "{{nim_password}}",
"Instanzgruppe": "{{nim_instancegroup}}",
"Synchronisierungszeit": 0,
„Module“: [
„ngx_http_app_protect_module“
],
„Zertifikate“: [
{
„Typ“: „Zertifikat“,
„Name“: „Testzertifikat“,
„Inhalt“: {
„Inhalt“: „{{github_gitops_root}}/v4.2/testcert.crt“
}
},
{
„Typ“: „Schlüssel“,
„Name“: „Testschlüssel“,
„Inhalt“: {
„Inhalt“: „{{github_gitops_root}}/v4.2/testcert.key“
}
}
],
„Richtlinien“: [
{
„Typ“: „App_protect“,
„Name“: „Produktionsrichtlinie“,
„Active_Tag“: „xss-blockiert“,
„Versionen“: [
{
„Tag“: „xss-blockiert“,
„Anzeigename“: „Produktionsrichtlinie – XSS blockiert“,
„Beschreibung“: „Dies ist eine produktionsreife Richtlinie – XSS blockiert“,
„contents“: {
„content“: „{{github_gitops_root}}/v4.2/nap-policy-xss-blocked-bot-allowed.json“
}
},
{
„tag“: „xss-allowed“,
„displayName“: „Produktionsrichtlinie – XSS erlaubt“,
„Beschreibung“: „Dies ist eine produktionsreife Richtlinie – XSS erlaubt“,
„contents“: {
„content“: „{{github_gitops_root}}/v4.2/nap-policy-xss-allowed.json“
}
}
]
}
]
}
},
„declaration“: {
„http“: {
„servers“: [
{
„name“: "Petstore API",
"Namen": [
"apigw.nginx.lab"

],
"Resolver": "8.8.8.8",
"hören": {
"Adresse": "0.0.0.0:443",
"http2": true,
"tls": {
"Zertifikat": "Testzertifikat",
"Schlüssel": "Testschlüssel",
"Chiffren": "STANDARD",
"Protokolle": [
"TLSv1.2",
"TLSv1.3"

]

}

},
"Protokoll": {
"Zugriff": "/var/log/nginx/apigw.nginx.lab-access_log",
"Fehler": "/var/log/nginx/apigw.nginx.lab-error_log"

},
"Standorte": [

{
"URI": "/petstore",
"URI-Match": "Präfix",
"Apigateway": {
"OpenAPI_Schema": {
"Inhalt": "http://petstore.swagger.io/v2/swagger.json"

},
"API_Gateway": {
"Aktiviert": wahr,
"Strip_URI": wahr,
"Server-URL": "https://petstore.swagger.io/v2"

},
"Entwicklerportal": {
"Aktiviert": true,
"uri": "/petstore-devportal.html"
},
"Authentifizierung": {
"Client": [
{
"Profil": "Petstore JWT-Authentifizierung"
}
],
"enforceOnPaths": true,
"paths": [
"/user/login",
"/user/logout"
]
},
"authorization": [
{
"profile": "Rollenbasierte JWT-Autorisierung",
"enforceOnPaths": true,
"paths": [
"/user/login",
"/user/logout"

]

}

],
"rate_limit": [

{
"profile": "petstore_ratelimit",
"httpcode": 429,
"platzen": 0,
"Verzögerung": 0,
„enforceOnPaths“: true,
„Pfade“: [
„/user/login“,
„/user/logout“
]
}
]
},
„log“: {
„Zugriff“: „/var/log/nginx/petstore-access_log“,
„Fehler“: „/var/log/nginx/petstore-error_log“
},
„app_protect“: {
„aktiviert“: true,
„Richtlinie“: „Produktionsrichtlinie“,
„log“: {
„Profilname“: „secops_dashboard“,
„aktiviert“: true,
„Ziel“: "127.0.0.1:514"
}
}
}
]
}
],
"Ratenlimit": [
{
"Name": "petstore_ratelimit",
"Schlüssel": "$binary_remote_addr",
"Größe": "10m",
"Bewerten": "2r/s"
}
],
"Authentifizierung": {
"Client": [
{
"Name": „Petstore JWT-Authentifizierung“,
„Typ“: „jwt“,
„jwt“: {
„Bereich“: "Petstore-Authentifizierung",
"Schlüssel": "{\"Schlüssel\": [{\"k\":\"ZmFudGFzdGljand0\",\"kty\":\"oct\",\"kid\":\"0001\"}]}",
"Cachezeit": 5
}
}
]
},
"Autorisierung": [
{
"Name": „Rollenbasierte JWT-Autorisierung“,
„Typ“: „jwt“,
„jwt“: {
„Ansprüche“: [
{
„Name“: „Rollen“,
„Wert“: [
„~(devops)“
],
„Fehlercode“: 403 } ] } } ] } } }


Der Ausgabeabschnitt definiert:

  • Der NGINX Instance Manager-Server und die Declarative API veröffentlichen die NGINX-Konfiguration an
  • TLS-Zertifikate und -Schlüssel - diese können über die URL der Quelle der Wahrheit referenziert werden, in der sie gespeichert sind
  • NGINX App schützt WAF-Sicherheitsrichtlinien - diese können über die URL der Quelle der Wahrheit referenziert werden, in der sie gespeichert sind

Der Deklarationsabschnitt beschreibt:

  • Der zu erstellende NGINX-Server
  • Ob TLS-Offload durchgeführt wird oder nicht
  • Wo werden Zugriffe und Fehlereinträge protokolliert?
  • Die /petstore- Basis-URI, unter der die API-Gateway-Konfiguration bereitgestellt und für Clients zugänglich gemacht wird
  • Die API Gateway-Konfiguration und das Entwicklerportal werden veröffentlicht
  • Wie NGINX App Protect WAF aktiviert wird, welche Sicherheitsrichtlinie zu verwenden ist und wo Sicherheitsverletzungen protokolliert werden
  • So authentifizieren und autorisieren Sie Clientanforderungen

Der Abschnitt „API Gateway-Deklaration“ beschreibt, wie die deklarative API ihr Ergebnis liefert.

Auf das OpenAPI-Schema wird über seine vollständige URL verwiesen:


"apigateway": {
"openapi_schema": {
"content": "http://petstore.swagger.io/v2/swagger.json"
},


Die Erstellung der NGINX API Gateway-Konfiguration wird angefordert und der Upstream-Server wird definiert. Wenn NGINX Anfragen per Reverse-Proxy an den Upstream weiterleitet, wird die /petstore- Basis-URI entfernt:


"api_gateway": {
"aktiviert": true,
"strip_uri": true,
"server_url": "https://petstore.swagger.io/v2"
},




Die Erstellung eines Entwicklerportals und die Bereitstellung unter einer bestimmten URI sind erforderlich:


"developer_portal": {
"enabled": true,
"uri": "/petstore-devportal.html"
},


Die Client-Authentifizierung basierend auf dem angegebenen Client-Authentifizierungsprofil wird für /user/login und /user/logout erzwungen:


"Authentifizierung": {
"Client": [
{
"Profil": "Petstore JWT-Authentifizierung"
}
],
"enforceOnPaths": true,
"paths": [
"/user/login",
"/user/logout"
]
},


Die Client-Autorisierung basierend auf dem angegebenen Client-Autorisierungsprofil wird für /user/logout und /user/logout erzwungen:


"Autorisierung": [
{
"Profil": "Rollenbasierte JWT-Autorisierung",
"enforceOnPaths": true,
"paths": [
"/user/login",
"/user/logout"
]
}
],




Die Ratenbegrenzung wird für /user /logout basierend auf dem angegebenen Profil angewendet:


"Ratenlimit": [
{
"Profil": "petstore_Ratenlimit",
"httpcode": 429,
"platzen": 0,
"Verzögerung": 0,
"enforceOnPaths": true,
"paths": [
"/user/login",
"/user/logout"
]
}
]
},


12. Verwenden Sie die Schaltfläche „Senden“ von Postman, um die Anforderung an die deklarative API zu veröffentlichen. Die Antwort sieht ungefähr so aus:


{
"Code": 200,
"Inhalt": {
"Erstellungszeit": "2024-04-26T17:09:10.419574328Z",
"Details": {
"Fehler": [],
"Ausstehend": [],
"Erfolg": [
{
"Name": "vm-test"
}
]
},
"ID": "1060ec49-120e-45ca-820b-5203c8b3538d",
"Nachricht": „Instanzgruppenkonfiguration erfolgreich in declarativeAPITest veröffentlicht“,
„status“: „erfolgreich“,
„updateTime“: "2024-04-26T17:09:10.881509913Z"
},
"configUid": "eecf1da6-9d8f-4e44-89cc-a470af79379d"
}


13. In dieser Phase wird die NGINX-Instanz als API-Gateway konfiguriert, die WAF-Sicherheit erzwungen und das Entwicklerportal veröffentlicht.

Testen des API-Gateways

Hinweis: Es wird davon ausgegangen, dass der FQDN apigw.nginx.lab in die IP-Adresse der virtuellen Maschine aufgelöst wird, auf der die NGINX-Instanz ausgeführt wird

1. Wechseln Sie in das jwt -Verzeichnis:


f5@ubuntu:~$ cd ~/NGINX-Declarative-API/contrib/gitops-examples/jwt


2. Greifen Sie auf einen nicht authentifizierten REST-API-Endpunkt zu:


$ curl -w '\n' -ki https://apigw.nginx.lab/petstore/store/inventory
HTTP/2 200 
Datum: Fr., 26. April 2024 17:13:54 GMT
Inhaltstyp: application/json
Zugriffskontroll-Allow-Origin: *
Zugriffskontroll-Allow-Methoden: GET, POST, DELETE, PUT
Zugriffssteuerungs-Allow-Header: Inhaltstyp, API-Schlüssel, Autorisierung

{"totvs":5,"aut":1,"FORsold":1,[...]



3. Ratenbegrenzung:

    
    $ curl -w '\n' -ki https://apigw.nginx.lab/petstore/user/login;curl -w '\n' -ki 
https://apigw.nginx.lab/petstore/user/login
HTTP/2 401 
Datum: Fr, 26. April 2024 17:14:51 GMT
Inhaltstyp: Text/HTML
Inhaltslänge: 179
www-authentifizieren: Bearer realm="Petstore-Authentifizierung"
<html>
<head><title>401-Autorisierung erforderlich</title></head>
<body>
<center><h1>401-Autorisierung erforderlich</h1></center>
<hr><center>nginx/1.25.3</center>
</body>
</html>
HTTP/2 429 
Datum: Fr, 26. April 2024 17:14:51 GMT
Inhaltstyp: Text/HTML
Inhaltslänge: 169
<html>
<head><title>429 Zu viele Anfragen</title></head>
<body>
<center><h1>429 Zu viele Anfragen</h1></center>
<hr><center>nginx/1.25.3</center>
</body>
</html>
    

4. Authentifizierung und gültige Autorisierung:


$ curl -w '\n' -ki https://apigw.nginx.lab/petstore/user/login -H "Autorisierung: Träger `cat jwt.devops`"
HTTP/2 200 
Datum: Fr., 26. April 2024 17:15:41 GMT
Inhaltstyp: application/json
Zugriffskontroll-Allow-Origin: *
Zugriffskontroll-Allow-Methoden: GET, POST, DELETE, PUT
Zugriffssteuerungs-Allow-Header: Inhaltstyp, API-Schlüssel, Autorisierung
x-expires-after: Fr. 26. Apr. 18:15:41 UTC 2024
x-Ratenlimit: 5000

{"code":200,"type":"unbekannt","message":"angemeldeter Benutzer:1714151741883"}



5. Authentifizierung und ungültige Autorisierung:


$ curl -w '\n' -ki https://apigw.nginx.lab/petstore/user/login -H "Autorisierung: Träger `cat jwt.guest`"
HTTP/2 403 
Datum: Fr, 26. April 2024 17:16:07 GMT
Inhaltstyp: Text/HTML
Inhaltslänge: 153
<html>
<head><title>403 Verboten</title></head>
<body>
<center><h1>403 Verboten</h1></center>
<hr><center>nginx/1.25.3</center>
</body>
</html>


6. Sicherheitsverletzung bei NGINX App Protect WAF und Cross-Site-Scripting:


$ curl -w '\n' -ki "https://apigw.nginx.lab/petstore/store/inventory?
"
HTTP/2 200 Inhaltstyp: Text/HTML; Zeichensatz = UTF-8 Cache-Steuerung: kein Cache Pragma: kein Cache Inhaltslänge: 246
<html><head><title>Anfrage abgelehnt</title></head><body>Die angeforderte URL wurde abgelehnt. Bitte wenden Sie sich an Ihren Administrator.Ihre Support-ID lautet: 7283327928460093545[Zurück]

7. Das Entwicklerportal erreichen Sie über


https://apigw.nginx.lab/petstore/petstore-devportal.html


Erste Schritte

Um die in diesem Beitrag besprochenen NGINX-Lösungen auszuprobieren, starten Sie noch heute eine 30-tägige kostenlose Testversion oder kontaktieren Sie uns , um Ihre Anwendungsfälle zu besprechen:

Laden Sie NGINX Agent herunter – es ist kostenlos und Open Source.


„Dieser Blogbeitrag kann auf Produkte verweisen, die nicht mehr verfügbar und/oder nicht mehr unterstützt werden. Die aktuellsten Informationen zu verfügbaren F5 NGINX-Produkten und -Lösungen finden Sie in unserer NGINX-Produktfamilie . NGINX ist jetzt Teil von F5. Alle vorherigen NGINX.com-Links werden auf ähnliche NGINX-Inhalte auf F5.com umgeleitet."