La creciente demanda de aplicaciones y servicios ha generado una gran necesidad de gestionar más eficientemente las API que los comunican. Para satisfacer esta necesidad, existe Apache APISIX, que es una plataforma de gestión de APIs de código abierto, escalable y de alto rendimiento y que actúa como gateway para administrar, proteger y optimizar el tráfico de las APIs. Proporciona funcionalidades como la supervisión, el equilibrio de carga, el flujo ascendente dinámico, el almacenamiento en caché, el canary release, el circuit breaking, la autenticación y la observabilidad.
Para gestionar el tráfico de API de APISIX, éste se basa en NGINX (a través de OpenResty), que es un servidor web, proxy inverso y balanceador de carga conocido por su alto rendimiento y eficiencia en la gestión de conexiones concurrentes. Por otro lado, proporciona la infraestructura para procesar las solicitudes y reglas configuradas en APISIX. Además, APISIX utiliza etcd, que es una base de datos distribuida de alta disponibilidad y consistencia, lo que es indispensable para que los cambios en la configuración se reflejen en tiempo real sin necesidad de reiniciar el gateway.
Elementos principales de APISIX
- El componente principal de APISIX es el Gateway, que se encarga de enrutar el tráfico de API entre los clientes y los servicios de backend. Para ello, recibe y procesa las requests según las reglas de enrutamiento y envía la respuesta. Además, aplica las políticas de seguridad y de control de tráfico definidas mediante los plugins.
- Esta tecnología define rutas, que son una serie de reglas que definen cómo se componen las requests, principalmente con una URL que la identifica y el destino de la request. Estas rutas pueden incluir parámetros de consulta y cabeceras, y pueden ser configuradas para manejar distintos métodos HTTP, como GET, POST, PUT, DELETE.
- Un servicio representa al destino backend al cual se van a enviar las requests cuando hayan pasado por las rutas. En él, se pueden especificar elementos como la URL del servicio y el protocolo y se será utilizado por las rutas para redirigir el tráfico al servicio backend al que representa.
- Los upstreams son grupos de instancias de backend que manejan las solicitudes y se emplean como balanceadores de carga entre varias instancias de un servicio.
- Para extender su funcionalidad, APISIX emplea plugins como módulos adicionales con los que puede satisfacer necesidades como la gestión de la autenticación, la limitación de tasa, la autorización, manipulación de requests o respuestas y el registro de datos.
Ventajas del uso de APISIX
- Posee un dashboard para facilitar la configuración de las rutas, servicios, upstreams y plugins a los usuarios. Sin embargo, sólo está disponible hasta la versión 3.0. La decisión de descontinuar el dashboard en versiones posteriores se basa en la necesidad de enfocar los recursos en la mejora del rendimiento y la escalabilidad del gateway, la evolución de herramientas externas de gestión y la preferencia por una arquitectura modular y flexible.
- Puedes crear plugins personalizados para ajustar el gateway a tus casos específicos. Aunque Lua es el lenguaje más utilizado y nativamente soportado para el desarrollo de plugins en APISIX, se puede escribir plugins en JavaScript a través de WASM y en Go utilizando el APISIX Go Plugin Runner.
- Posee un controlador de configuración, que es un componente que se encarga de manejar y sincronizar la configuración del gateway, permitiendo configurar rutas, servicios y plugins sin necesidad de reiniciar el gateway.
- Envía datos de log para monitorizar y registrar el tráfico. Esto puede ser también útil para debuggear en caso de errores en la configuración de algún elemento.
Instalación de APISIX con Docker
- Clonamos el repositorio:
git clone https://github.com/apache/apisix-docker.git
- Navegamos hasta la carpeta example, que tiene la configuración para el despliegue:
cd apisix-docker/example
- Iniciamos los servicios definidos en el docker-compose.yaml:
docker-compose up -p post_apisix
Cuando finaliza el proceso, podemos ver que tenemos ejecutándose seis contenedores. Para este post, nos centraremos en el contenedor post_apisix_apisix_1, ya que es el que vamos a utilizar para crear los elementos. En él, encontramos los puertos 9180, que será el que emplearemos para configurar los recursos, y el 9080, que es el que emplearemos para realizar las requests desde consola.
Configuración de APISIX con Auth0
A continuación, veremos cómo se configura el plugin de autenticación openid-connect para realizar un caso de uso completo de APISIX. En éste, vamos a autenticarnos con Auth0 de dos formas: la primera será en la web mediante las credenciales del usuario (método para personas físicas) y la segunda será solicitando un token por consola mediante las credenciales del cliente (método para aplicaciones y servicios). Primeramente, tenemos que crear una aplicación en Auth0 de la siguiente manera:
- Regístrate en Auth0.
- Navega a Applications > APIs y selecciona el botón Create API y créala.
- En la configuración de la API creada, navega hasta Machine To Machine Applications y asegúrate de que la opción Authorized está habilitada.
- Navega hasta Applications > ‘{your_application (Test Application)}’ y agrega «http://localhost:9080/anything/callback» al campo Allowed Callback URLs. Luego, baja hasta Advanced Settings > Grand Types y habilita las opciones Authorization Code y Client Credentials.
- Haz scroll hasta arriba del todo y copia los parámetros Domain, Client ID y Client Secret para los siguientes pasos.
Autenticación con usuario
Vamos a crear una ruta con el plugin openid-connect, para que reenvíe las peticiones de los clientes a la web httpbin.org, que es un servicio web público muy sencillo diseñado para ayudar a desarrolladores y testers a probar y depurar solicitudes HTTP. Para ello, copia el siguiente esquema y cambia los parámetros Domain, Client ID y Client Secret por los de tu aplicación. Fíjate que usamos el puerto 9180 en la configuración, como comentamos anteriormente, y que también definimos la url de redirección, que se asegura de que los usuarios y motores de búsqueda siempre lleguen al contenido correcto, incluso si las URLs cambian o los recursos se trasladan.
La ruta /anything/'{cualquier_cosa}’ de httpbin.org devuelve cualquier cosa pasada en los datos de la solicitud en tipo JSON, como métodos, argumentos y cabeceras.
curl -i "http://127.0.0.1:9180/apisix/admin/routes" -H "X-API-KEY: edd1c9f034335f136f87ad84b625c8f1" -X PUT -d '
{
"id": "auth-with-oidc",
"uri":"/anything/*",
"plugins": {
"openid-connect": {
"client_id": "m5bTMKvbRqn7JklTjIEZsO0saVLvIAoV",
"client_secret": "YKHDG4_oBE7XbciMsCh0sMO1IjgHK9ZPZcunlfLQfGbNmTyuZVY6YXv5lgbMFbKu",
"discovery": "'{auth0_domain}'",
"scope": "openid profile",
"redirect_uri": "http://localhost:9080/anything/callback"
}
},
"upstream":{
"type":"roundrobin",
"nodes":{
httpbin.org:80":1
}
}
}'
Este es el resultado que debería darnos tras crear la ruta completa:
Ahora que tenemos configurada la ruta, realizamos la request a la siguiente dirección: http://localhost:9080/anything/get
Nos aparecerá el login de Auth0:
Al autenticarnos correctamente, debería aparecer un JSON web parecido al siguiente:
Autenticación con credenciales del cliente
Otra forma de autenticarse es mediante las credenciales del cliente para obtener un token JWT de acceso. Para ello, tenemos que habilitar dos parámetros más en la configuración de la ruta anterior:
curl -i "http://127.0.0.1:9180/apisix/admin/routes" -H "X-API-KEY: edd1c9f034335f136f87ad84b625c8f1" -X PUT -d '
{
"id": "auth-with-oidc",
"uri":"/anything/*",
"plugins": {
"openid-connect": {
"client_id": "m5bTMKvbRqn7JklTjIEZsO0saVLvIAoV",
"client_secret": "YKHDG4_oBE7XbciMsCh0sMO1IjgHK9ZPZcunlfLQfGbNmTyuZVY6YXv5lgbMFbKu",
"discovery": "'{auth0_domain}'",
"scope": "openid profile",
"redirect_uri": "http://localhost:9080/anything/callback",
"bearer_only": true,
"use_jwks": true
}
},
"upstream":{
"type":"roundrobin",
"nodes":{
httpbin.org:80":1
}
}
}'
Nuevamente, si no nos hemos dejado alguna comilla sin cerrar u olvidado alguna coma, debería darnos el siguiente resultado.
Ahora que ya tenemos la configuración hecha, vamos a solicitar el token de acceso, usando para ello los parámetros audience (Auth0 > APIs > copiar “Api audience”), client_id, client_secret y grand_type.
curl -i "'{auth0_domain}'" -X POST \
-H 'content-type: application/json' \
-d '{
"client_id":"m5bTMKvbRqn7JklTjIEZsO0saVLvIAoV",
"client_secret":"YKHDG4_oBE7XbciMsCh0sMO1IjgHK9ZPZcunlfLQfGbNmTyuZVY6YXv5lgbMFbKu",
"audience":"https://clientcredentials.com",
"grant_type":"client_credentials"
}'
El token obtenido lo copiamos y lo pegamos en el siguiente comando para acceder al recurso:
curl -i "http://127.0.0.1:9080/anything/test" -H "Authorization: Bearer '{token_ey_obtenido}'"
Conclusión
Apache APISIX se presenta como una poderosa y flexible solución de gestión de API de código abierto, diseñada para manejar el tráfico en tiempo real con alta eficiencia. Su capacidad de extensión mediante plugins personalizados, lo convierten en una opción ideal para situaciones en las que busque un control detallado y dinámico sobre sus APIs. Las ventajas de APISIX incluyen su alto rendimiento, soporte para múltiples protocolos y su capacidad para escalar en entornos complejos. Además, su configuración basada en etcd proporciona una manera eficiente y robusta de gestionar la configuración distribuida, asegurando consistencia y disponibilidad.