NGINX lleva mucho tiempo siendo reconocido como una de las mejores opciones para implementar servidores web y balanceadores de carga de alto rendimiento. Sin embargo, con el auge de las arquitecturas de microservicios y la necesidad de gestionar las API de forma eficiente, NGINX también se ha convertido en una opción popular para crear puertas de enlace de API.
En este blog, exploraremos cómo transformar la definición de un esquema OpenAPI en una configuración de NGINX totalmente funcional que opere como una puerta de enlace de API con seguridad mediante un firewall de aplicaciones web y un portal para desarrolladores, utilizando un enfoque de API declarativa.
Proporcionaremos instrucciones paso a paso e información práctica sobre cómo aprovechar NGINX Plus para optimizar sus procesos de gestión de API y garantizar un rendimiento óptimo de sus aplicaciones.
Presentación de la puerta de enlace de API
Una puerta de enlace de API actúa como eje central para gestionar y proteger la comunicación entre los clientes y los servicios de backend. Funciona como un proxy inverso situado entre el cliente y los servidores de backend, que enruta las solicitudes entrantes y las distribuye a los servicios correspondientes. Esto permite una comunicación más eficiente entre el cliente y los servicios, además de permitir que la puerta de enlace de API se encargue de tareas como la autenticación, la autorización, la limitación de solicitudes y el almacenamiento en caché.
Además, una puerta de enlace de API puede actuar como una capa de seguridad, protegiendo los servicios de backend frente a posibles amenazas y ataques. Puede aplicar medidas de seguridad como el cifrado, la autenticación basada en tokens y el control de acceso, garantizando que solo los usuarios autorizados puedan acceder a los servicios. Al centralizar y gestionar estas funciones de seguridad en un único lugar, la puerta de enlace de API ayuda a simplificar la arquitectura de seguridad general del sistema y a reducir la complejidad de implementar medidas de seguridad en múltiples servicios.
Proyecto de API declarativa de NGINX
El proyecto NGINX Declarative API, respaldado por la comunidad, proporciona un conjunto de API REST declarativas para NGINX Instance Manager.
Se puede utilizar para gestionar los ciclos de vida de las configuraciones de NGINX Plus y crear configuraciones de NGINX Plus mediante definiciones de servicios en JSON. La integración con GitOps es compatible cuando se utiliza con NGINX Instance Manager: se comprueba si hay actualizaciones de los objetos referenciados en la fuente de verdad y las configuraciones de NGINX se mantienen sincronizadas automáticamente.
Los esquemas OpenAPI se pueden utilizar para configurar automáticamente NGINX como puerta de enlace de API. Se admite la creación de portales para desarrolladores mediante Redocly.
Requisitos previos
Para ejecutar el contenido de este blog, necesitas:
- Una instancia en ejecución de NGINX Instance Manager
- Una suscripción (o una prueba gratuita de 30 días) para NGINX Plus y NGINX App Protect WAF. NGINX Agent debe estar instalado para conectarse a NGINX Instance Manager y formar parte del grupo de instancias
declarativeAPITestinstance group - Un host Linux (servidor físico o máquina virtual) con docker y docker-compose para ejecutar el proyecto de la API declarativa de NGINX
- Postman para enviar las solicitudes de la API declarativa
- Un host cliente en el que ejecutar Postman
Descripción general del laboratorio
Después de instalar y ejecutar todos los requisitos previos, NGINX Instance Manager muestra la instancia de NGINX Plus como conectada y con NGINX App Protect WAF.

La instancia de NGINX Plus forma parte del grupo de instancias declarativeAPITest Instance Group

Implementación de la API declarativa
El proyecto de la API declarativa de NGINX se basa en la API REST proporcionada por NGINX Instance Manager y ofrece una abstracción declarativa basada en JSON. Siga estas instrucciones para ejecutar el proyecto de la API declarativa:
1. Ejecuta docker ps para comprobar que Docker se está ejecutando:
f5@ubuntu:~$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
2. En el host Linux, clone el repositorio de 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. Cambia al directorio docker-compose:
f5@ubuntu:~$ cd NGINX-Declarative-API/contrib/docker-compose/
4. Utilice el script nginx-dapi.sh para iniciar todos los contenedores mediante docker-compose. Durante el arranque inicial, todas las imágenes de Docker se compilan automáticamente:
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. Comprueba los contenedores de Docker en ejecución:
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. En el host cliente, ejecute Postman e importe la colección de la API declarativa de NGINX disponible en https://raw.githubusercontent.com/f5devcentral/NGINX-Declarative-API/main/contrib/postman/NGINX%20Declarative%20API.postman_collection.json
7. Edite las variables de la colección de Postman para adaptarlas a su entorno:

8. Establezca las siguientes variables:
ncg_host- nombre de host o dirección IP del host Linux donde se está ejecutando el docker-compose de la API declarativancg_port- Puerto TCP para la API declarativa de NGINX: 5000 es el valor predeterminadonim_host- URL base de NGINX Instance Manager (p. ej., https://nms.k8s.ie.ff.lan)nim_username- nombre de usuario de autenticación de NGINX Instance Managernim_password- contraseña de autenticación de NGINX Instance Manager

9. Guarda todos los cambios en Postman
10. En la colección de Postman, ve a «Petstore API Gateway RateLimit + JWT AuthN/AuthZ + WAF» y abre la solicitud

La declaración JSON tiene el siguiente aspecto:
{
"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 sección output define:
- El servidor de NGINX Instance Manager en el que la API declarativa publicará la configuración de NGINX
- Certificados y claves TLS: se puede hacer referencia a ellos mediante la URL de la fuente de información fiable donde están almacenados
- Políticas de seguridad de NGINX App Protect WAF: se puede hacer referencia a ellas mediante la URL de la fuente de referencia donde están almacenadas
La sección declaration describe:
- El servidor NGINX que se va a crear
- Si se realiza o no la descarga de TLS
- Dónde registrar las entradas de acceso y de error
- El URI base
/petstoreen el que se desplegará la configuración de API Gateway y se pondrá a disposición de los clientes - La configuración de API Gateway y el portal para desarrolladores que se publicarán
- Cómo se habilita NGINX App Protect WAF, qué política de seguridad se debe utilizar y dónde se deben registrar las infracciones de seguridad
- Cómo autenticar y autorizar las solicitudes de los clientes
La sección de declaración de API Gateway describe cómo la API declarativa proporcionará su resultado.
Se hace referencia al esquema OpenAPI mediante su URL completa:
"apigateway": {
"openapi_schema": {
"content": "http://petstore.swagger.io/v2/swagger.json"
},
Se solicita la creación de la configuración de NGINX API Gateway y se define el servidor upstream. Cuando NGINX actúa como proxy inverso de las solicitudes al servidor upstream, se elimina el URI base /petstore:
"api_gateway": {
"enabled": true,
"strip_uri": true,
"server_url": "https://petstore.swagger.io/v2"
},
Se solicita la creación y el despliegue del portal para desarrolladores en un URI específico:
"developer_portal": {
"enabled": true,
"uri": "/petstore-devportal.html"
},
La autenticación de clientes basada en el perfil de autenticación de cliente especificado se aplica en /user/login y /user/logout:
"authentication": {
"client": [
{
"profile": "Petstore JWT Authentication"
}
],
"enforceOnPaths": true,
"paths": [
"/user/login",
"/user/logout"
]
},
La autorización de los clientes basada en el perfil de autorización de cliente especificado se aplica en /user/login y /user/logout:
"authorization": [
{
"profile": "JWT role based authorization",
"enforceOnPaths": true,
"paths": [
"/user/login",
"/user/logout"
]
}
],
La limitación de solicitudes se aplica a /user/login y /user/logout según el perfil especificado:
"rate_limit": [
{
"profile": "petstore_ratelimit",
"httpcode": 429,
"burst": 0,
"delay": 0,
"enforceOnPaths": true,
"paths": [
"/user/login",
"/user/logout"
]
}
]
},
12. Usa el botón Enviar de Postman para publicar la solicitud en la API declarativa. La respuesta es similar a la siguiente:
{
"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. En esta fase, la instancia de NGINX está configurada como una puerta de enlace de API, se aplica la seguridad de WAF y se publica el portal para desarrolladores.
Prueba de la puerta de enlace de API
Nota: se presupone que el FQDN apigw.nginx.lab se resuelve en la dirección IP de la máquina virtual en la que se está ejecutando la instancia de NGINX
1. Cambie al directorio jwt:
f5@ubuntu:~$ cd ~/NGINX-Declarative-API/contrib/gitops-examples/jwt
2. Accede a un endpoint de la API REST sin autenticar:
$ 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. Limitación de velocidad:
$ 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. Autenticación y autorización válida:
$ 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. Autenticación y autorización no válida:
$ 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. Infracción de seguridad de NGINX App Protect WAF y 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. Se puede acceder al portal para desarrolladores navegando a
https://apigw.nginx.lab/petstore/petstore-devportal.html
Primeros pasos
Para probar las soluciones de NGINX que se describen en esta publicación, inicie hoy mismo una prueba gratuita de 30 días o póngase en contacto con nosotros para hablar sobre sus casos de uso:
Descarga NGINX Agent; es gratuito y de código abierto.
Sobre el autor

Artículos relacionados del blog
Únete a F5 NGINX en AppWorld 2024
Descubre las numerosas razones para asistir al evento insignia de F5, que incluirá un emocionante anuncio sobre la cartera de productos NGINX.
Rotación de certificados SSL/TLS sin reinicios en NGINX Open Source
La función de diccionario compartido permite configurar NGINX sin necesidad de reiniciarlo al renovar los certificados SSL/TLS.
Exposición de APIs en Kubernetes
La unidad 2 de Microservices March 2022 se centra en cómo exponer tus API en Kubernetes. Aquí tienes enlaces a los recursos que necesitas: la retransmisión en directo del 14 de marzo, artículos de blog y otros recursos de preparación, y el laboratorio práctico «Protege las API de Kubernetes mediante la limitación de solicitudes».
NGINX Sprint 2.0: visión clara, código renovado y nuevos compromisos con el código abierto
Hoy, en NGINX Sprint 2.0, anunciamos cómo respaldaremos nuestra visión del futuro de las aplicaciones modernas con una mayor presencia en la comunidad de código abierto, incluida la participación en el proyecto comunitario Kubernetes, nuevos proyectos de software de código abierto y la arquitectura de referencia para aplicaciones modernas.
Presentamos NGINX Plus R22
NGINX Plus R22 incorpora nuevas funcionalidades, como la compatibilidad con OCSP para verificar la revocación de certificados en TLS mutuo, el uso de varios proveedores de identidad OIDC en una configuración, el seguimiento en tiempo real de la limitación de solicitudes y conexiones en el panel de NGINX Plus y mejoras en NGINX JavaScript.
Presentamos NGINX Plus R17
NGINX Plus R17 incorpora compatibilidad con la limitación de velocidad en dos fases y con TLS 1.3, la versión más reciente del protocolo Transport Layer Security. La configuración de OpenID Connect es más sencilla y NGINX ModSecurity WAF es el doble de rápido que antes. También se ha actualizado el módulo JavaScript de NGINX.