NGINX ha sido reconocido desde hace mucho tiempo como una de las mejores opciones para potenciar servidores web y balanceadores de carga de alto rendimiento. Sin embargo, con el auge de las arquitecturas de microservicios y la necesidad de una gestión eficiente de API, 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 una definición de esquema OpenAPI en una configuración NGINX completamente funcional que se ejecuta como una API Gateway con seguridad de firewall de aplicação web y un portal para desarrolladores utilizando un enfoque de API declarativa.
Proporcionaremos instrucciones paso a paso y conocimientos sobre cómo aprovechar NGINX Plus para optimizar sus procesos de gestión de API y garantizar un rendimiento óptimo para sus aplicações.
Una puerta de enlace API funciona como un centro central para administrar y proteger la comunicación entre clientes y servicios backend. Actúa como un proxy inverso que se ubica entre el cliente y los servidores back-end, enrutando las solicitudes entrantes y distribuyéndolas a los servicios apropiados. Esto permite una comunicación más eficiente entre el cliente y los servicios, además de permitir que la puerta de enlace API gestione tareas como autenticación , autorización , limitación de velocidad y almacenamiento en caché.
Además, una puerta de enlace API puede actuar como una capa de seguridad , protegiendo los servicios backend de posibles amenazas y ataques. Puede aplicar medidas de seguridad como cifrado, autenticación basada en tokens y control de acceso, garantizando que solo los usuarios autorizados puedan acceder a los servicios. Al consolidar y administrar estas funciones de seguridad en un solo lugar, la puerta de enlace 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.
El proyecto NGINX Declarative API, respaldado por la comunidad, proporciona un conjunto de API REST declarativas para NGINX Instance Manager .
Se puede utilizar para administrar los ciclos de vida de configuración de NGINX Plus y para crear configuraciones de NGINX Plus utilizando definiciones de servicio JSON. La integración de GitOps es compatible cuando se utiliza con NGINX Instance Manager: se verifica la fuente de verdad para las actualizaciones de los objetos referenciados y las configuraciones de NGINX se mantienen sincronizadas automáticamente.
Los esquemas OpenAPI se pueden utilizar para configurar automáticamente NGINX como una API Gateway. La creación de un portal para desarrolladores se realiza a través de Redocly .
Para ejecutar los contenidos de este blog, necesitas:
pruebaAPI declarativa
grupo de instanciasDespués de instalar y ejecutar todos los requisitos previos, NGINX Instance Manager muestra la instancia NGINX Plus como en línea con NGINX App Protect WAF.
La instancia NGINX Plus es parte del grupo de instancias declarativeAPITest
El proyecto de API declarativa de NGINX se basa en la API REST proporcionada por NGINX Instance Manager y proporciona la abstracción declarativa basada en JSON. Siga estas instrucciones para ejecutar el proyecto de API declarativa:
1.Ejecute docker ps para verificar que Docker se esté ejecutando:
f5@ubuntu:~$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
2.En el host Linux, clona 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.Cambiar 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 a través de docker-compose. Durante el inicio inicial, todas las imágenes de Docker se crean 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 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 del cliente, ejecute Postman e importe la colección de API declarativa de NGINX en https://raw.githubusercontent.com/f5devcentral/NGINX-Declarative-API/main/contrib/postman/NGINX%20Declarative%20API.postman_collection.json
7.Edite las variables de colección de Postman para ajustarlas a su entorno:
8.Establezca las siguientes variables:
ncg_host
: nombre de host o dirección IP del host Linux donde se ejecuta la API declarativa docker-composencg_port
- Puerto TCP para la API declarativa NGINX: 5000 es el valor predeterminadonim_host
: URL base del administrador de instancias de NGINX (por ejemplo, https://nms.k8s.ie.ff.lan)nim_username
- Nombre de usuario de autenticación del administrador de instancias de NGINXnim_password
- Contraseña de autenticación del administrador de instancias de NGINX9.Guardar todos los cambios en Postman
10.En la colección Postman, busque Petstore API Gateway RateLimit + JWT AuthN/AuthZ + WAF
y abra la solicitud
La declaración JSON se ve así:
{
"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 de salida
define:
La sección de declaración
describe:
/petstore
donde se implementará la configuración de API Gateway y será accesible para los clientesLa sección de declaración de API Gateway describe cómo la API declarativa entregará su resultado.
El esquema OpenAPI se referencia a través de 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 ascendente. Cuando NGINX realiza un proxy inverso de las solicitudes al origen, 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 e implementación del portal para desarrolladores bajo una URI específica:
"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 para /user/login
y /user/logout
:
"authentication": {
"client": [
{
"profile": "Petstore JWT Authentication"
}
],
"enforceOnPaths": true,
"paths": [
"/user/login",
"/user/logout"
]
},
La autorización de clientes basada en el perfil de autorización de cliente especificado se aplica para /user/login
y /user/logout
:
"authorization": [
{
"profile": "JWT role based authorization",
"enforceOnPaths": true,
"paths": [
"/user/login",
"/user/logout"
]
}
],
Se aplica una limitación de velocidad para /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.Utilice el botón Enviar de
Postman para publicar la solicitud en la API declarativa. La respuesta es similar a esta:
{
"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 etapa, la instancia NGINX se configura como API Gateway, se aplica la seguridad WAF y se publica el portal para desarrolladores.
Nota: se supone que el FQDN apigw.nginx.lab
se resuelve en la dirección IP de la máquina virtual donde se ejecuta la instancia NGINX
1.Cambiar al directorio jwt
:
f5@ubuntu:~$ cd ~/NGINX-Declarative-API/contrib/gitops-examples/jwt
2.Acceder a un punto final de API REST no autenticado:
$ 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.Violació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: 246
<html><head><title>Request Rejected</title></head><body>The requested URL was rejected. Please consult with your administrator.<br><br>Your support ID is: 7283327928460093545<br><br><a href='javascript:history.back();'>[Go Back]</a></body></html>
7.Se puede acceder al portal para desarrolladores navegando hasta
https://apigw.nginx.lab/petstore/petstore-devportal.html
Para probar las soluciones NGINX analizadas en esta publicación, comience hoy mismo una prueba gratuita de 30 días o contáctenos para analizar sus casos de uso:
Descargue NGINX Agent : es gratis y de código abierto.
"Esta publicación de blog puede hacer referencia a productos que ya no están disponibles o que ya no reciben soporte. Para obtener la información más actualizada sobre los productos y soluciones F5 NGINX disponibles, explore nuestra familia de productos NGINX . NGINX ahora es parte de F5. Todos los enlaces anteriores de NGINX.com redirigirán a contenido similar de NGINX en F5.com.