NGINX est depuis longtemps reconnu comme l’une des meilleures solutions pour faire fonctionner des serveurs web et des répartiteurs de charge hautes performances. Cependant, avec l’essor des architectures de microservices et la nécessité d’une gestion efficace des API, NGINX est également devenu un choix populaire pour créer des passerelles API.
Dans cet article, nous verrons comment transformer une définition de schéma OpenAPI en une configuration NGINX entièrement fonctionnelle, utilisée comme passerelle API avec la sécurité d’un « pare-feu d’applications web » et un « portail pour les développeurs », à l’aide d’une approche d’API déclarative.
Nous vous fournirons des instructions détaillées et des conseils pour tirer parti de NGINX Plus afin de simplifier vos processus de gestion des API et de garantir des performances optimales pour vos applications.
Présentation de la passerelle API
Une passerelle API sert de point central pour gérer et sécuriser les communications entre les clients et les services backend. Elle agit comme un proxy inverse placé entre le client et les serveurs backend, acheminant les requêtes entrantes et les distribuant aux services appropriés. Cela permet une communication plus efficace entre le client et les services, tout en permettant à la passerelle API de prendre en charge 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 faire office de couche de sécurité, protégeant ainsi les services backend contre les menaces et attaques potentielles. Elle peut appliquer des mesures de sécurité telles que le chiffrement, l’authentification par jeton et le contrôle d’accès, afin de garantir que seuls les utilisateurs autorisés puissent accéder aux services. En centralisant 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é liée à la mise en œuvre de mesures de sécurité dans plusieurs services.
Projet d’API déclarative NGINX
Le projet NGINX Declarative API, soutenu par la communauté, fournit un ensemble d’API REST déclaratives pour NGINX Instance Manager.
Il permet de gérer le cycle de vie des configurations NGINX Plus et de créer des configurations NGINX Plus à l’aide de définitions de services JSON. L’intégration GitOps est prise en charge lorsqu’il est utilisé avec NGINX Instance Manager : la source de vérité est vérifiée afin de détecter les mises à jour des objets référencés, et les configurations NGINX sont automatiquement maintenues synchronisées.
Les schémas OpenAPI peuvent être utilisés pour configurer automatiquement NGINX en tant que passerelle d’API. La création d’un portail pour les développeurs est prise en charge par Redocly.
Prérequis
Pour exécuter les exemples présentés dans cet article, vous aurez besoin des éléments suivants :
- Une instance en cours d’exécution de NGINX Instance Manager
- Un abonnement (ou un essai gratuit de 30 jours) à NGINX Plus et à NGINX App Protect WAF. NGINX Agent doit être installé pour se connecter à NGINX Instance Manager et faire partie du groupe d’instances
declarativeAPITestinstance group - Un hôte Linux (serveur physique ou machine virtuelle) avec docker et docker-compose pour exécuter le projet NGINX Declarative API
- Postman pour envoyer les requêtes à l’API déclarative
- Un hôte client pour exécuter Postman
Présentation du laboratoire
Après l’installation et l’exécution de tous les prérequis, NGINX Instance Manager indique que l’instance NGINX Plus est en ligne avec NGINX App Protect WAF.

L’instance NGINX Plus fait partie du groupe d’instances « declarativeAPITest »

Déploiement de l’API déclarative
Le projet NGINX Declarative API s’appuie sur l’API REST fournie par NGINX Instance Manager et offre une abstraction déclarative basée sur JSON. Suivez ces instructions pour exécuter le projet Declarative API :
1. Exécutez docker ps pour vérifier que Docker est en cours d’exécution :
f5@ubuntu:~$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
2. Sur l’hôte Linux, clonez le dépôt Github :
f5@ubuntu:~$ git clone https://github.com/f5devcentral/NGINX-Declarative-API/
Cloning into 'NGINX-Declarative-API'...
remote: Enumerating objects: 4072, done.
remote: Counting objects: 100% (1982/1982), done.
remote: Compressing objects: 100% (1332/1332), done.
remote: Total 4072 (delta 668), reused 876 (delta 609), pack-reused 2090
Receiving objects: 100% (4072/4072), 19.05 MiB | 4.88 MiB/s, done.
Resolving deltas: 100% (1154/1154), done.
f5@ubuntu:~$
3. Accédez au répertoire docker-compose :
f5@ubuntu:~$ cd NGINX-Declarative-API/contrib/docker-compose/
4. Utilisez le script « nginx-dapi.sh » pour démarrer tous les conteneurs via docker-compose. Lors du premier démarrage, toutes les images Docker sont créées automatiquement :
f5@ubuntu:~/NGINX-Declarative-API/contrib/docker-compose$ ./nginx-dapi.sh -c start
-> Updating docker images
[+] Pulling 11/11
[...]
-> Deploying NGINX Declarative API
[+] Running 4/4
✔ Network nginx-dapi_dapi-network Created 0.1s
✔ Container redis Started 1.5s
✔ Container devportal Started 1.5s
✔ Container nginx-dapi Started
5. Vérifiez les conteneurs Docker en cours d’exécution :
f5@ubuntu:~/NGINX-Declarative-API/contrib/docker-compose$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
e29a2f783da2 nginx-declarative-api "/deployment/env/bin…" 5 minutes ago Up 5 minutes 0.0.0.0:5000->5000/tcp, :::5000->5000/tcp nginx-dapi
97142840eaf7 redis "docker-entrypoint.s…" 5 minutes ago Up 5 minutes 0.0.0.0:6379->6379/tcp, :::6379->6379/tcp redis
6b50c0426643 nginx-declarative-api-devportal "/deployment/src/sta…" 5 minutes ago Up 5 minutes 0.0.0.0:5001->5000/tcp, :::5001->5000/tcp devportal
6. Sur l’hôte client, lancez Postman et importez la collection NGINX Declarative API disponible à l’adresse suivante : 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 s’exécute le docker-compose de l’API déclarativencg_port- Port TCP de l’API déclarative NGINX : 5000 est la valeur par défautnim_host- URL de base de NGINX Instance Manager (par ex. https://nms.k8s.ie.ff.lan)nim_username- nom d’utilisateur d’authentification de NGINX Instance Managernim_password- mot de passe d’authentification de NGINX Instance Manager

9. Enregistrez toutes les modifications dans Postman
10. Dans la collection Postman, accédez à « Petstore API Gateway RateLimit + JWT AuthN/AuthZ + WAF », puis ouvrez la requête

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"
],
"certificates": [
{
"type": "certificate",
"name": "test_cert",
"contents": {
"content": "{{github_gitops_root}}/v4.2/testcert.crt"
}
},
{
"type": "key",
"name": "test_key",
"contents": {
"content": "{{github_gitops_root}}/v4.2/testcert.key"
}
}
],
"policies": [
{
"type": "app_protect",
"name": "production-policy",
"active_tag": "xss-blocked",
"versions": [
{
"tag": "xss-blocked",
"displayName": "Production Policy - XSS blocked",
"description": "This is a production-ready policy - XSS blocked",
"contents": {
"content": "{{github_gitops_root}}/v4.2/nap-policy-xss-blocked-bot-allowed.json"
}
},
{
"tag": "xss-allowed",
"displayName": "Production Policy - XSS allowed",
"description": "This is a production-ready policy - XSS allowed",
"contents": {
"content": "{{github_gitops_root}}/v4.2/nap-policy-xss-allowed.json"
}
}
]
}
]
}
},
"declaration": {
"http": {
"servers": [
{
"name": "Petstore API",
"names": [
"apigw.nginx.lab"
],
"resolver": "8.8.8.8",
"listen": {
"address": "0.0.0.0:443",
"http2": true,
"tls": {
"certificate": "test_cert",
"key": "test_key",
"ciphers": "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": "Petstore JWT Authentication"
}
],
"enforceOnPaths": true,
"paths": [
"/user/login",
"/user/logout"
]
},
"authorization": [
{
"profile": "JWT role based authorization",
"enforceOnPaths": true,
"paths": [
"/user/login",
"/user/logout"
]
}
],
"rate_limit": [
{
"profile": "petstore_ratelimit",
"httpcode": 429,
"burst": 0,
"delay": 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",
"rate": "2r/s"
}
],
"authentication": {
"client": [
{
"name": "Petstore JWT Authentication",
"type": "jwt",
"jwt": {
"realm": "Petstore Authentication",
"key": "{\"keys\": [{\"k\":\"ZmFudGFzdGljand0\",\"kty\":\"oct\",\"kid\":\"0001\"}]}",
"cachetime": 5
}
}
]
},
"authorization": [
{
"name": "JWT role based authorization",
"type": "jwt",
"jwt": {
"claims": [
{
"name": "roles",
"value": [
"~(devops)"
],
"errorcode": 403
}
]
}
}
]
}
}
}
La section « output » définit :
- Le serveur NGINX Instance Manager sur lequel l’API déclarative publiera la configuration NGINX
- Certificats et clés TLS : ils peuvent être référencés par l’URL de la source de référence où ils sont stockés
- Politiques de sécurité WAF NGINX App Protect : elles peuvent être référencées à l’aide de l’URL de la source de référence où elles sont stockées
La section declaration décrit :
- Le serveur NGINX à créer
- Indique si le déchargement TLS est effectué ou non
- Où consigner les entrées d’accès et d’erreur
- L’URI de base
/petstoresur laquelle la configuration d’API Gateway sera déployée et rendue accessible aux clients - La configuration d’API Gateway et le portail des développeurs à publier
- Comment NGINX App Protect WAF est activé, quelle politique de sécurité utiliser et où consigner les violations de sécurité
- Comment authentifier et autoriser les requêtes des clients
La section de déclaration de la passerelle d’API décrit comment l’API déclarative fournira son résultat.
Le schéma OpenAPI est référencé par 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 transmet les requêtes au serveur en amont en tant que proxy inverse, 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 développeur sous un 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 » :
"authentication": {
"client": [
{
"profile": "Petstore JWT Authentication"
}
],
"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 » :
"authorization": [
{
"profile": "JWT role based authorization",
"enforceOnPaths": true,
"paths": [
"/user/login",
"/user/logout"
]
}
],
La limitation du débit s’applique à /user/login et /user/logout selon le profil spécifié :
"rate_limit": [
{
"profile": "petstore_ratelimit",
"httpcode": 429,
"burst": 0,
"delay": 0,
"enforceOnPaths": true,
"paths": [
"/user/login",
"/user/logout"
]
}
]
},
12. Utilisez le bouton Send de Postman pour envoyer la requête à l’API déclarative. La réponse ressemble à ceci :
{
"code": 200,
"content": {
"createTime": "2024-04-26T17:09:10.419574328Z",
"details": {
"failure": [],
"pending": [],
"success": [
{
"name": "vm-test"
}
]
},
"id": "1060ec49-120e-45ca-820b-5203c8b3538d",
"message": "Instance Group config successfully published to 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 en tant que passerelle API, la sécurité WAF est appliquée et le portail des développeurs est publié.
Tester la passerelle API
Remarque : on suppose que le nom de domaine complet (FQDN) apigw.nginx.lab se résout en l’adresse IP de la machine virtuelle sur laquelle l’instance NGINX s’exécute
1. Accédez au répertoire jwt :
f5@ubuntu:~$ cd ~/NGINX-Declarative-API/contrib/gitops-examples/jwt
2. Accédez à un point de terminaison d’API REST non authentifié :
$ curl -w '\n' -ki https://apigw.nginx.lab/petstore/store/inventory
HTTP/2 200
date: Fri, 26 Apr 2024 17:13:54 GMT
content-type: application/json
access-control-allow-origin: *
access-control-allow-methods: GET, POST, DELETE, PUT
access-control-allow-headers: Content-Type, api_key, Authorization
{"totvs":5,"aut":1,"FORsold":1,[...]
3. Limitation du 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: Fri, 26 Apr 2024 17:14:51 GMT
content-type: text/html
content-length: 179
www-authenticate: Bearer realm="Petstore Authentication"
<html>
<head><title>401 Authorization Required</title></head>
<body>
<center><h1>401 Authorization Required</h1></center>
<hr><center>nginx/1.25.3</center>
</body>
</html>
HTTP/2 429
date: Fri, 26 Apr 2024 17:14:51 GMT
content-type: text/html
content-length: 169
<html>
<head><title>429 Too Many Requests</title></head>
<body>
<center><h1>429 Too Many Requests</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 "Authorization: Bearer `cat jwt.devops`"
HTTP/2 200
date: Fri, 26 Apr 2024 17:15:41 GMT
content-type: application/json
access-control-allow-origin: *
access-control-allow-methods: GET, POST, DELETE, PUT
access-control-allow-headers: Content-Type, api_key, Authorization
x-expires-after: Fri Apr 26 18:15:41 UTC 2024
x-rate-limit: 5000
{"code":200,"type":"unknown","message":"logged in user session:1714151741883"}
5. Authentification et autorisation non valide :
$ curl -w '\n' -ki https://apigw.nginx.lab/petstore/user/login -H "Authorization: Bearer `cat jwt.guest`"
HTTP/2 403
date: Fri, 26 Apr 2024 17:16:07 GMT
content-type: text/html
content-length: 153
<html>
<head><title>403 Forbidden</title></head>
<body>
<center><h1>403 Forbidden</h1></center>
<hr><center>nginx/1.25.3</center>
</body>
</html>
6. NGINX App Protect WAF et violation de sécurité de type Cross-Site Scripting :
$ curl -w '\n' -ki "https://apigw.nginx.lab/petstore/store/inventory?
"
HTTP/2 200
content-type: text/html; charset=utf-8
cache-control: no-cache
pragma: no-cache
content-length: 2467. Le portail des développeurs est accessible à l’adresse suivante :
https://apigw.nginx.lab/petstore/petstore-devportal.html
Commencer
Pour essayer les solutions NGINX présentées dans cet article, commencez 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 : il est gratuit et open source.
À propos de l’auteur

Articles de blog associés

Tendances actuelles des technologies cloud natives, de l’ingénierie de plateforme et de l’IA
Découvrez les principaux enseignements tirés des réponses à l’enquête annuelle F5 NGINX sur les dernières tendances en matière de technologies cloud natives, de sécurité, d’ingénierie de plateforme et d’IA.
Quels contrôleurs Ingress NGINX sont affectés par les vulnérabilités CVE-2022-4886, CVE-2023-5043 et CVE-2023-5044 ?
Lorsque de nouvelles CVE sont signalées, il est facile de ne plus savoir si elles concernent un outil de contrôleur Ingress NGINX particulier, car il existe plusieurs projets. Cet article présente les CVE et explique comment distinguer les différents projets de contrôleurs Ingress afin de dissiper toute confusion.
Votre API est-elle en temps réel ? Testez sa latence avec l’outil rtapi de NGINX
Votre API répond-elle aux requêtes en moins de 30 ms ? Si ce n’est pas le cas, il ne s’agit pas d’une API en temps réel offrant la faible latence exigée par la grande majorité des organisations. Mesurez la latence de votre API avec l’outil rtapi de NGINX et découvrez comment NGINX peut l’aider à offrir une réactivité en temps réel.

Un testeur d’expressions régulières pour NGINX et NGINX Plus
Le testeur d’expressions régulières (regex) pour NGINX et NGINX Plus vous évite de tâtonner en vous indiquant si une expression régulière utilisée dans un bloc location ou map correspond aux valeurs comme prévu. Il génère la configuration appropriée et affiche les valeurs des groupes de capture.
Caches partagés avec les clusters de cache NGINX Plus, partie 1
Optimisez la capacité de votre cache web en le répartissant entre plusieurs serveurs de cache web NGINX ou NGINX Plus. Découvrez comment procéder dans cet article.
Introduction aux microservices
Les microservices suscitent actuellement beaucoup d’intérêt. Cet article de blog est le premier d’une série de sept consacrée à la conception, au développement et au déploiement de microservices.