Asegurando un API con mTLS – Parte 1

Cada día es más necesario utilizar prácticas seguras durante el desarrollo de toda aplicación para evitar los riesgos de seguridad una vez que la aplicación esté en producción.

Normalmente yo recomiendo asegurar tu API con OAuth2/OIDC, sin embargo, no siempre esto es posible o práctico, es más, para ciertos APIs, no es necesariamente la opción más segura, o no es suficientemente segura.

Me explico, OAuth2/OIDC es seguro, pero cuando nuestra información va a viajar usando muchas paradas, y si algunas de estas paradas van a descifrar el contenido, por motivos varios, entonces corremos el peligro de que nuestra información no esté 100% segura todo el tiempo.

En un mundo ideal, nuestra impresión de cómo fluye el tráfico de las aplicaciones a nuestro servidor es algo así:

Gráfico que muestra un tráfico encriptado de punto a punto
Cómo pensamos que funciona

Sin embargo, la realidad es que entre la aplicación y el servidor pueden haber muchas paradas. En una implementación más moderna es muy probable que el tráfico en realidad se vea así:

Gráfico que muestra que el tráfico probablemente no está encriptado como pensamos
Cómo realmente es

Para nuestra sorpresa, vemos que el tráfico entre el Balanceador de Carga y el Manejador de APIs dice Cifrado/Recifrado/No cifrado, ¿qué significa esto? Pues, que es muy probable que cuando publiques tu API, el administrador de tu red te pida el certificado para asegurar la información. En muchas topologías, se pone el certificado en el Balanceador de Carga para terminar el cifrado entre la aplicación y la infraestructura de la compañía en la puerta de entrada, y entre el Balanceador de Carga y el Manejador de APIs se puede crear una nueva sesión de TLS, o simplemente dejarlo sin cifrar. ¿Es seguro esto? En realidad, todo depende de cómo ha sido diseñada la infraestructura. Por ejemplo, si el Balanceador y el Manejador son un mismo producto, o corren en el mismo hardware, o en un ambiente hermético, es posible que esto suceda sin mayor peligro.

Algo aún más sorprendente es en el próximo tramo, entre el Manejador de APIs y el servidor del API, no solamente el tráfico no está cifrado, sino que además, está pre-autenticado y pre-autorizado, en otras palabras, el servidor del API aceptará la palabra del Manejador de APIs Y NO VOLVERÁ a verificar la autenticación y autorización del pedido, sino que lo servirá sin mayor precaución.

A simple vista, esto parece ser un problema serio, pero en realidad no lo es, es una ventaja muy grande. Si cada servidor de APIs tuviera que volver a implementar código de autorización y autenticación, nos encontraríamos con un dolor de cabeza en asegurarnos que cada API use exactamente el mismo nivel de seguridad en ambas funciones. APIs que fueron escritos hace dos años, tendrían que volverse a escribir para soportar las nuevas implementaciones o versiones de los algoritmos de seguridad. Las compañías, para evitar la deuda técnica tendrían que usar un solo lenguaje de programación y una librería de autenticación y autorización que sea actualizada constantemente y enlazada con el código de los API. Eso es exactamente lo que el Manejador de APIs provée, un lugar común donde estas funciones se ejecutan, dejando al mismo tiempo libertad de que cada API sea escrito en la tecnología más adecuada para ese API, teniendo la seguridad de que, si el pedido logra pasar por el Manejador de APIs, ha sido debidamente autenticado y autorizado.

Pero, eso todavía nos deja dos pequeñas dudas, ¿por qué no está cifrada la información entre el Manejador de APIs y el Servidor del API? y ¿Cómo sabe el Servidor del API que el pedido realmente viene del Manejador de APIs y no de un tercero? Buenas preguntas.

En cuanto a la primera, ¿es el mismo riesgo de no cifrar entre el Balanceador y el Manejador? No, el riesgo de no cifrar entre el manejador y el servidor es normalmente mayor. ¿Por qué? Porque el Balanceador y el Manejador son normalmente piezas de infraestructura, dentro de un ambiente de redes físico o virtual hermético, y esto no es necesariamente cierto entre el Manejador y tu servidor de APIs. Si tu infraestructura te puede asegurar una conexión de punto a punto entre el Manejador y tu Servidor que no pueda ser interceptada o inyectada por terceros, entonces no hay problema en que el tráfico entre el Manejador y el Servidor sea sin cifrar, y preautorizada y preautenticada. Sin embargo, no siempre este es el caso, en muchas ocasiones tu vas a querer que tu servidor esté cercano a tus datos, o en la nube, o por distintos otros motivos, lejos del Manejador. Entonces, ¿cuál es la alternativa? mTLS.

mTLS significa autenticación mútua, y en este caso es una tecnología usada para asegurarnos que, independientemente de cuánta lejanía exista entre dos servidores, ambos puedan confiar que están hablando con el servidor correcto, y la información no puede ser descifrada por los diferentes puntos por los cuáles pase el tráfico. Esto nos permite tener infraestructura en las nubes que sirva recursos on-prem, o infrastructura on-prem sirviendo recursos en las nubes, o cualquier combinación anterior, es decir, nos libera de que las funciones estén situadas en el lugar correcto sin tener que preocuparnos sobre la seguridad de la información en tránsito.

En TLS normal para que dos partes puedan comunicarse, una tiene que confiar en la otra. Es decir, en tu explorador entras la dirección https://duke.edu y te aparecerá la página de la Universidad Duke y podrás comprobar en la barra de navegación que dice que está segura que recibió la información de duke.edu. Esto se consigue porque tu navegador confía en el certificado servido por el servidor de Duke. El servidor de Duke, en cambio, no tiene conocimiento de quién fue que solicitó la información, ni le importa. Pero, si por algún motivo es importante que ambos lados sepan quién es el otro participante de la conversación, entonces se establece una doble autenticación, o autenticación mútua (mTLS). El iniciador le pide su certificado al destino, el destino provee su certificado, el iniciador verifica que es un certificado válido y luego provée al destino de su propio certificado, el destino verifica la validez del certificado y entonces, y solo entonces, información puede fluir entre los dos participantes. El siguiente gráfico muestra en forma simplificada la diferencia entre TLS y mTLS:

En el mundo de Kubernetes se está desarrollando estos conceptos en una forma más global y fácil a través de mallas de servicio y los próximos estándares de SPIFFE y SPIRE, pero el mismo concepto puede ser usado en cualquier sistema hoy, a través de implementar mTLS, que es la base para las mencionadas tecnologías en Kubernetes.

En la parte 2 mostraremos un ejemplo fácil de implementación práctica de mTLS.