Protegiendo la API Admin de Kong con API Key y ACLs

La API Admin de Kong permite realizar cualquier tarea de administración de Kong, lo que hace, que en caso de verse comprometida, se convierta en una vulnerabilidad y un riesgo grave. Por defecto, el puerto de Admin sólo escucha las peticiones que vienen de Localhost (es decir, sólo está disponible desde el propio servidor de Kong), pero habitualmente necesitaremos que esté disponible para su acceso desde más ubicaciones de red, por lo que necesitaremos protegerlo de alguna forma, mínimo mediante algún mecanismo de autenticación, quizás también mediante filtrado de IP. Cómo podemos hacerlo? Pues con el propio Kong.

Continuando con la serie de Posts acerca de Kong, en esta ocasión vamos a ver cómo podemos proteger la API Admin de Kong, utilizando para ello el propio Kong, publicándola como un Servicio más, y protegiéndola mediante autenticación de API Key y ACLs, de forma similar a lo que vimos en el anterior Post de Consumidores, Autenticación, y Autorización de APIs en Kong – I.

Si quieres seguir este Post paso a paso, te recomiendo que te apoyes en el Docker Compose que compartí en GitHub (GitHub – ElWillieES – kong-docker-lab) y que revises al menos el Post primero (Introducción a Kong Gateway y Kong Dashboard) para tener el contexto de qué es Kong (si no lo tienes), y que también explica el Docker Compose compartido en GitHub. Este Docker Compose viene con todo incluido: Kong, Konga, Elasticsearch, ElasticHQ, Logstash, Kibana, Prometheus, y Grafana (entre otras cosas), lo que te ayudará a que puedas probar muchas cosas, de una forma rápida y sencilla. Dicho esto, continuamos.

Lo primero que deberemos hacer, es crear un Servicio y una Ruta para publicar la API Admin de Kong a través de Kong. Esto lo podemos hacer con un par de comandos curl como los siguientes (también desde Konga, claro), que publican la API Admin de Kong sobre /admin-api.

curl -X POST http://127.0.0.1:8001/services \
  --data name=admin-api \
  --data host=127.0.0.1 \
  --data port=8001

curl -X POST http://127.0.0.1:8001/services/admin-api/routes \
  --data name=admin-api \
  --data paths[]=/admin-api

Hecho esto, podemos acceder a la API Admin de Kong, a través del propio Kong (como si fuera cualquier otra API que publiquemos), desde cualquier ubicación desde la que tengamos conectividad, con un comando como el siguiente. Dado que para mi laboratorio estoy utilizando Docker, sigo accediendo a través de Localhost. Pero aún seguimos accediendo sin ningún tipo de autenticación.

curl localhost:8000/admin-api/services

Seguidamente, activamos el Plugin de Key Auth sobre el Servicio en el que publicamos la API Admin de Kong, creamos un consumidor, generamos una API Key aleatoria al consumidor, y consultamos el valor de dicha API Key.

curl -X POST http://localhost:8001/services/admin-api/plugins \
    --data "name=key-auth"  \
    --data "config.key_in_query=false"  \
    --data "config.key_names=apikey"

curl -d "username=admin-api" http://localhost:8001/consumers/

curl -X POST http://localhost:8001/consumers/admin-api/key-auth

curl http://localhost:8001/consumers/admin-api/key-auth

Hecho esto, conseguimos que el acceso a la API Admin sea mediante API Key, aunque cualquier consumidor que tenga una API Key podría utilizarla: nos falta aún tener el control de que sólo puedan acceder los consumidores o usuarios que especifiquemos, es decir, nos faltan las ACLs.

Ahora vamos a añadir el Plugin de ACLs en el Servicio en el que publicamos la API Admin de Kong permitiendo sólo un grupo (el que deseemos, en nuestro caso es: api-admin-allowed-users), y asociamos al consumidor que deseamos autorizar el acceso a dicho grupo. Esto se puede hacer con los siguientes dos comandos curl.

curl -X POST http://localhost:8001/services/admin-api/plugins \
    --data "name=acl"  \
    --data "config.allow=api-admin-allowed-users" \
    --data "config.hide_groups_header=true"

curl -X POST http://localhost:8001/consumers/admin-api/acls \
    --data "group=api-admin-allowed-users"

Ahora sólo podrán acceder a la API Admin los consumidores autorizados, como podemos ver en la siguiente pantalla capturada.

Si utilizamos Konga, tendemos que cambiar la conexión de Konga a Kong, para que acceda a través del Servicio que acabamos de publicar, y con una API Key válida (en lugar de a través del puerto de admin sin API Key).

Hecho esto, podríamos configurar Kong para que el puerto de Admin sólo escuche en localhost, y así garantizar que todos los accesos son mediante una API Key válida. En nuestro caso de ejemplo que estamos usando Docker, con eliminar o comentar la siguiente línea del Docker Compose, es suficiente (por defecto, Kong sólo escucha el puerto de admin en localhost).

Fácil y sencillo.

Despedida y Cierre

Hasta aquí llega este Post sobre Kong, donde hemos podido ver cómo securizar el acceso a la propia API Admin de Kong publicándola a través del propio Kong, y aprovechando los Plugin de autenticación (Key Auth) y ACLs.

Poco más por hoy, como siempre confío que la lectura resulte de interés.