BLOG | NGINX

De OpenAPI à NGINX en tant que passerelle API à l'aide d'une API déclarative

NGINX-Partie-de-F5-horiz-black-type-RGB
Miniature de Fabrizio Fiorucci
Fabrizio Fiorucci
Publié le 17 juin 2024

NGINX est depuis longtemps reconnu comme l’un des meilleurs choix pour alimenter des serveurs Web et des équilibreurs de charge hautes performances. Cependant, avec l’essor des architectures de microservices et le besoin d’une gestion efficace des API, NGINX est également devenu un choix populaire pour la création de passerelles API.

Dans ce blog, nous découvrirons comment transformer une définition de schéma OpenAPI en une configuration NGINX entièrement fonctionnelle fonctionnant comme une passerelle API avec la sécurité du pare-feu d'application Web et un portail de développeur à l'aide d'une approche API déclarative.

Nous vous fournirons des instructions étape par étape et des informations sur la manière d'exploiter NGINX Plus pour rationaliser vos processus de gestion des API et garantir des performances optimales pour vos applications.

Présentation de la passerelle API

Une passerelle API sert de hub central pour gérer et sécuriser la communication entre les clients et les services back-end. Il agit comme un proxy inverse qui se situe entre le client et les serveurs principaux, acheminant les requêtes entrantes et les distribuant aux services appropriés. Cela permet une communication plus efficace entre le client et les services, ainsi que de permettre à la passerelle API de gérer des tâches telles que l'authentification , l'autorisation , la limitation du débit et la mise en cache.

De plus, une passerelle API peut agir comme une couche de sécurité , protégeant les services back-end contre les menaces et attaques potentielles. Il peut appliquer des mesures de sécurité telles que le cryptage, l’authentification par jetons et le contrôle d’accès, garantissant que seuls les utilisateurs autorisés peuvent accéder aux services. En consolidant et en gérant ces fonctionnalités de sécurité en un seul endroit, la passerelle API contribue à simplifier l’architecture de sécurité globale du système et à réduire la complexité de la mise en œuvre des mesures de sécurité sur plusieurs services.

Projet API déclarative NGINX

Le projet d'API déclarative NGINX soutenu par la communauté fournit un ensemble d'API REST déclaratives pour NGINX Instance Manager .

Il peut être utilisé pour gérer les cycles de vie de configuration NGINX Plus et pour créer des configurations NGINX Plus à l'aide de définitions de service JSON. L'intégration GitOps est prise en charge lorsqu'elle est utilisée avec NGINX Instance Manager : la source de vérité est vérifiée pour les mises à jour des objets référencés et les configurations NGINX sont automatiquement synchronisées.

Les schémas OpenAPI peuvent être utilisés pour configurer automatiquement NGINX en tant que passerelle API. La création du portail des développeurs est prise en charge via Redocly .

Prérequis

Pour exécuter le contenu de ce blog, vous avez besoin de :

  • Une instance en cours d'exécution de NGINX Instance Manager
  • Un abonnement (ou un essai gratuit de 30 jours ) pour NGINX Plus et NGINX App Protect WAF . L'agent NGINX doit être installé pour se connecter à NGINX Instance Manager et faire partie du groupe d'instances declarativeAPITest
  • Un hôte Linux (bare metal ou VM) avec docker et docker-compose pour exécuter le projet d'API déclarative NGINX
  • Facteur pour soumettre les demandes d'API déclaratives
  • Un hôte client pour exécuter Postman

Présentation du laboratoire

Après avoir installé et exécuté toutes les conditions préalables, NGINX Instance Manager affiche l'instance NGINX Plus comme en ligne avec NGINX App Protect WAF.

L'instance NGINX Plus fait partie du groupe d'instances déclarativeAPITest

Déploiement de l'API déclarative

Le projet API déclarative NGINX s'appuie sur l'API REST fournie par NGINX Instance Manager et fournit l'abstraction déclarative basée sur JSON. Suivez ces instructions pour exécuter le projet d’API déclarative :

1. Exécutez docker ps pour vérifier que Docker est en cours d’exécution :


f5@ubuntu:~$ docker ps
ID DU CONTENEUR IMAGE COMMANDE CRÉÉE STATUT PORTS NOMS


2. Sur l’hôte Linux, clonez le dépôt Github :


f5@ubuntu:~$ git clone https://github.com/f5devcentral/NGINX-Declarative-API/
Clonage dans 'NGINX-Declarative-API'...
remote: Énumération des objets : 4072, terminé.
télécommande : Compter les objets : 100% (1982/1982), fait.
à distance : Compression d'objets : 100% (1332/1332), terminé.
à distance : Total 4072 (delta 668), réutilisés 876 (delta 609), réutilisés en pack 2090
Objets reçus : 100 % (4072/4072), 19,05 Mio | 4,88 Mio/s, terminé.
Résolution des deltas : 100% (1154/1154), c'est fait.
f5@ubuntu :~$


3. Accédez au répertoire docker-compose :


f5@ubuntu:~$ cd NGINX-Déclaratif-API/contrib/docker-compose/


4. Utilisez le script nginx-dapi.sh pour démarrer tous les conteneurs via docker-compose. Lors du démarrage initial, toutes les images Docker sont créées automatiquement :


f5@ubuntu:~/NGINX-Declarative-API/contrib/docker-compose$ ./nginx-dapi.sh -c start
-> Mise à jour des images Docker
[+] Extraction 11/11
[...]
-> Déploiement de l'API déclarative NGINX
[+] Exécution 4/4
✔ Réseau nginx-dapi_dapi-network Créé 0,1 s 
✔ Conteneur redis Démarré 1,5 s 
✔ Conteneur devportal Démarré 1,5 s 
✔ Conteneur nginx-dapi Démarré


5. Vérifiez les conteneurs Docker en cours d’exécution :


f5@ubuntu:~/NGINX-Declarative-API/contrib/docker-compose$ docker ps
ID CONTENEUR IMAGE COMMANDE CRÉÉE ÉTAT PORTS NOMS
e29a2f783da2 nginx-declarative-api "/deployment/env/bin…" il y a 5 minutes En ligne il y a 5 minutes 0.0.0.0:5000->5000/tcp, :::5000->5000/tcp nginx-dapi
97142840eaf7 redis "docker-entrypoint.s…" il y a 5 minutes En ligne il y a 5 minutes 0.0.0.0:6379->6379/tcp, :::6379->6379/tcp redis
6b50c0426643 nginx-declarative-api-devportal "/deployment/src/sta…" il y a 5 minutes Up 5 minutes 0.0.0.0:5001->5000/tcp, :::5001->5000/tcp devportal


6. Sur l'hôte client, exécutez Postman et importez la collection d'API déclaratives NGINX à l'adresse https://raw.githubusercontent.com/f5devcentral/NGINX-Declarative-API/main/contrib/postman/NGINX%20Declarative%20API.postman_collection.json

7. Modifiez les variables de la collection Postman pour les adapter à votre environnement :

8. Définissez les variables suivantes :

  • ncg_host - nom d'hôte ou adresse IP de l'hôte Linux sur lequel l'API déclarative docker-compose est exécutée
  • ncg_port - Port TCP pour l'API déclarative NGINX : 5000 est la valeur par défaut
  • nim_host - URL de base du gestionnaire d'instances NGINX (c'est-à-dire https://nms.k8s.ie.ff.lan)
  • nim_username - Nom d'utilisateur d'authentification du gestionnaire d'instances NGINX
  • nim_password - Mot de passe d'authentification du gestionnaire d'instances NGINX

9. Enregistrer toutes les modifications sur Postman

10. Dans la collection Postman, accédez à Petstore API Gateway RateLimit + JWT AuthN/AuthZ + WAF et ouvrez la demande

La déclaration JSON se présente comme suit :


{
"output": {
"type": "nms",
"nms": {
"url": "{{nim_host}}",
"username": "{{nim_username}}",
"password": "{{nim_password}}",
"instancegroup": "{{nim_instancegroup}}",
"synctime": 0,
"modules": [
"ngx_http_app_protect_module"
],
"certificats": [
{
"type": "certificat",
"nom": "test_cert",
"contenu": {
"contenu": "{{github_gitops_root}}/v4.2/testcert.crt"
}
},
{
"type": "clé",
"nom": "test_key",
"contenu": {
"contenu": "{{github_gitops_root}}/v4.2/testcert.key"
}
}
],
"politiques": [
{
"type": "app_protect",
"nom": "production-policy",
"active_tag": "xss-blocked",
"versions": [
{
"tag": "xss-blocked",
"displayName": « Politique de production – XSS bloqué »,
 « description » : "Il s'agit d'une politique prête pour la production - XSS bloqué",
"contents": {
"content": "{{github_gitops_root}}/v4.2/nap-policy-xss-blocked-bot-allowed.json"
}
},
{
"tag": "xss-allowed",
"displayName": « Politique de production - XSS autorisé »,
 « description » : "Il s'agit d'une politique prête pour la production - XSS autorisée",
"contents": {
"content": "{{github_gitops_root}}/v4.2/nap-policy-xss-allowed.json"
}
}
]
}
]
}
},
"declaration": {
"http": {
"servers": [
{
"name": "API Petstore",
"names": [
"apigw.nginx.lab"
],
"resolver": "8.8.8.8",
"écouter": {
"adresse": "0.0.0.0:443",
"http2": true,
"tls": {
"certificat": "test_cert",
"clé": "test_key",
"chiffres": "DEFAULT",
"protocols": [
"TLSv1.2",
"TLSv1.3"
]
}
},
"log": {
"access": "/var/log/nginx/apigw.nginx.lab-access_log",
"error": "/var/log/nginx/apigw.nginx.lab-error_log"
},
"locations": [
{
"uri": "/petstore",
"urimatch": "prefix",
"apigateway": {
"openapi_schema": {
"content": "http://petstore.swagger.io/v2/swagger.json"
},
"api_gateway": {
"enabled": true,
"strip_uri": true,
"server_url": "https://petstore.swagger.io/v2"
},
"developer_portal": {
"enabled": true,
"uri": "/petstore-devportal.html"
},
"authentication": {
"client": [
{
"profile": "Authentification JWT Petstore"
}
],
"enforceOnPaths": true,
"paths": [
"/user/login",
"/user/logout"
]
},
"authorization": [
{
"profile": "Autorisation basée sur les rôles JWT",
"enforceOnPaths": true,
"paths": [
"/user/login",
"/user/logout"
]
}
],
"rate_limit": [
{
"profile": "petstore_ratelimit",
"httpcode": 429,
"éclater" : 0,
"retard": 0,
"enforceOnPaths": true,
"paths": [
"/user/login",
"/user/logout"
]
}
]
},
"log": {
"access": "/var/log/nginx/petstore-access_log",
"error": "/var/log/nginx/petstore-error_log"
},
"app_protect": {
"enabled": true,
"policy": "production-policy",
"log": {
"profile_name": "secops_dashboard",
"enabled": true,
"destination": "127.0.0.1:514"
}
}
}
]
}
],
"rate_limit": [
{
"name": "petstore_ratelimit",
"key": "$binary_remote_addr",
"size": "10m",
"taux" : "2r/s"
}
],
"authentification": {
"client": [
{
"nom": "Authentification JWT Petstore",
"type": "jwt",
"jwt": {
"realm": "Authentification de l'animalerie",
"key": "{\"keys\": [{\"k\":\"ZmFudGFzdGljand0\",\"kty\":\"oct\",\"kid\":\"0001\"}]}",
"cachetime": 5
}
}
]
},
"autorisation": [
{
"nom": "Autorisation basée sur les rôles JWT",
"type": "jwt",
"jwt": {
"claims": [
{
"name": "roles",
"value": [
"~(devops)"
],
"errorcode": 403 } ] } } ] } } }


La section de sortie définit :

  • Le serveur NGINX Instance Manager, l'API déclarative, publiera la configuration NGINX sur
  • Certificats et clés TLS - ceux-ci peuvent être référencés par l'URL de la source de vérité où ils sont stockés
  • L'application NGINX protège les politiques de sécurité WAF - celles-ci peuvent être référencées par l'URL de la source de vérité où elles sont stockées

La section déclaration décrit :

  • Le serveur NGINX à créer
  • Que le déchargement TLS soit effectué ou non
  • Où enregistrer les entrées d'accès et d'erreur
  • L'URI de base /petstore où la configuration de la passerelle API sera déployée et rendue accessible aux clients
  • La configuration de la passerelle API et le portail des développeurs seront publiés
  • Comment NGINX App Protect WAF est activé, quelle politique de sécurité utiliser et où enregistrer les violations de sécurité
  • Comment authentifier et autoriser les demandes des clients

La section de déclaration de la passerelle API décrit comment l'API déclarative fournira son résultat.

Le schéma OpenAPI est référencé via son URL complète :


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


La création de la configuration de la passerelle API NGINX est demandée et le serveur en amont est défini. Lorsque NGINX envoie des requêtes par proxy inverse en amont, l'URI de base /petstore est supprimé :


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




La création et le déploiement d'un portail de développeur sous une URI spécifique sont demandés :


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


L'authentification des clients basée sur le profil d'authentification client spécifié est appliquée pour /user/login et /user/logout :


"authentification": {
"client": [
{
"profil": "Authentification JWT Petstore"
}
],
"enforceOnPaths": true,
"paths": [
"/user/login",
"/user/logout"
]
},


L'autorisation des clients basée sur le profil d'autorisation client spécifié est appliquée pour /user/login et /user/logout :


"autorisation" : [
{
"profil" : "Autorisation basée sur les rôles JWT",
"enforceOnPaths": true,
"paths": [
"/user/login",
"/user/logout"
]
}
],




La limitation du débit est appliquée pour /user/login et /user/logout en fonction du profil spécifié :


"rate_limit": [
{
"profile": "petstore_ratelimit",
"httpcode": 429,
"éclater" : 0,
"retard": 0,
"enforceOnPaths": true,
"paths": [
"/user/login",
"/user/logout"
]
}
]
},


12. Utilisez le bouton Envoyer du facteur pour publier la demande sur l'API déclarative. La réponse est similaire à :


{
"code": 200,
"contenu": {
"createTime": "2024-04-26T17:09:10.419574328Z",
"détails": {
"échec": [],
"en attente": [],
"succès": [
{
"nom": "vm-test"
}
]
},
"id": "1060ec49-120e-45ca-820b-5203c8b3538d",
"message": "La configuration du groupe d'instances a été publiée avec succès sur declarativeAPITest",
"status": "successful",
"updateTime": "2024-04-26T17:09:10.881509913Z"
},
"configUid": "eecf1da6-9d8f-4e44-89cc-a470af79379d"
}


13. À ce stade, l'instance NGINX est configurée comme passerelle API, la sécurité WAF est appliquée et le portail des développeurs est publié.

Test de la passerelle API

Remarque : il est supposé que le nom de domaine complet apigw.nginx.lab correspond à l'adresse IP de la machine virtuelle sur laquelle l'instance NGINX est exécutée

1. Accédez au répertoire jwt :


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


2. Accéder à un point de terminaison d’API REST non authentifié :


$ curl -w '\n' -ki https://apigw.nginx.lab/petstore/store/inventory
HTTP/2 200 
date : Ven. 26 avr. 2024 17:13:54 GMT
content-type: application/json
access-control-allow-origin: *
access-control-allow-methods: OBTENIR, PUBLIER, SUPPRIMER, METTRE
en-têtes d'autorisation de contrôle d'accès : Type de contenu, api_key, autorisation

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



3. Limitation de débit :

    
    $ 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 
date : Ven, 26 avr. 2024 17:14:51 GMT
content-type: text/html
content-length: 179
www-authentifier : Royaume du porteur ="Authentification animalerie"
<html>
<head><title>401 Autorisation requise</title></head>
<body>
<center><h1>401 Autorisation requise</h1></center>
<hr><center>nginx/1.25.3</center>
</body>
</html>
HTTP/2 429 
date : Ven, 26 avr. 2024 17:14:51 GMT
content-type: text/html
content-length: 169
<html>
<head><title>429 Trop de requêtes</title></head>
<body>
<center><h1>429 Trop de requêtes</h1></center>
<hr><center>nginx/1.25.3</center>
</body>
</html>
    

4. Authentification et autorisation valide :


$ curl -w '\n' -ki https://apigw.nginx.lab/petstore/user/login -H "Autorisation : Porteur `cat jwt.devops`"
HTTP/2 200 
date : Ven. 26 avr. 2024 17:15:41 GMT
content-type: application/json
access-control-allow-origin: *
access-control-allow-methods: OBTENIR, PUBLIER, SUPPRIMER, METTRE
en-têtes d'autorisation de contrôle d'accès : Type de contenu, api_key, autorisation
x-expires-after : Ven 26 avr 18:15:41 UTC 2024
x-rate-limit: 5000

{"code":200,"type":"inconnu","message":"session utilisateur connectée :1714151741883"}



5. Authentification et autorisation invalide :


$ curl -w '\n' -ki https://apigw.nginx.lab/petstore/user/login -H "Autorisation : Porteur `cat jwt.guest`"
HTTP/2 403 
date : Ven, 26 avr. 2024 17:16:07 GMT
content-type: text/html
content-length: 153
<html>
<head><title>403 Interdit</title></head>
<body>
<center><h1>403 Interdit</h1></center>
<hr><center>nginx/1.25.3</center>
</body>
</html>


6. Violation de sécurité WAF et Cross-Site Scripting de NGINX App Protect :


$ curl -w '\n' -ki "https://apigw.nginx.lab/petstore/store/inventory?
"
HTTP/2 200 type de contenu : texte/html ; jeu de caractères = utf-8 contrôle du cache : pas de cache pragma : pas de cache longueur du contenu : 246
<html><head><title>Requête rejetée</title></head><body>L'URL demandée a été rejetée. Veuillez consulter votre administrateur.Votre identifiant d'assistance est : 7283327928460093545[Retour]

7. Le portail des développeurs est accessible en naviguant vers


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


Commencer

Pour tester les solutions NGINX présentées dans cet article, démarrez dès aujourd'hui un essai gratuit de 30 jours ou contactez-nous pour discuter de vos cas d'utilisation :

Téléchargez NGINX Agent – c'est gratuit et open source.


« Cet article de blog peut faire référence à des produits qui ne sont plus disponibles et/ou qui ne sont plus pris en charge. Pour obtenir les informations les plus récentes sur les produits et solutions F5 NGINX disponibles, explorez notre famille de produits NGINX . NGINX fait désormais partie de F5. Tous les liens NGINX.com précédents redirigeront vers un contenu NGINX similaire sur F5.com."