Diseñar una arquitectura segura para sistemas distribuidos

Laseguridad de sistemas distribuidos representa un desafío complejo debido a la diversidad y escala de los componentes involucrados. Con varios servicios interactuando a través de redes potencialmente inseguras, el riesgo de acceso no autorizado y brechas de datos aumenta significativamente. Este artículo explora una aproximación práctica para la seguridad de sistemas distribuidos utilizando un proyecto de código abierto. El proyecto muestra cómo integrar varios mecanismos de seguridad y tecnologías para abordar los desafíos de seguridad comunes como la autenticación, la autorización y la comunicación segura.

Comprensión de los Desafíos de Seguridad en Sistemas Distribuidos

Los sistemas distribuidos implican varios servicios o microservicios que deben comunicarse de manera segura a través de una red. Los desafíos de seguridad clave en esas arquitecturas incluyen:

  1. Comunicación segura: Asegurar que los datos transmitidos entre servicios estén cifrados y estén a salvo de interceptación o manipulación
  2. Autenticación: Verificar las identidades de los usuarios y servicios para evitar el acceso no autorizado
  3. Autorización: Controlar qué actividades están permitidas para usuarios y servicios autenticados, basadas en sus roles y permisos
  4. Aplicación de políticas: Implementar controles de acceso de alto grado y políticas que gobiernan las interacciones entre servicios y usuarios.
  5. Gestión de certificados: Gestionar certificados digitales para cifrar datos y establecer confianza entre servicios

Este proyecto de código abierto aborda estos retos utilizando varias tecnologías y soluciones integradas.

Configuración y establecimiento del proyecto

El proyecto comienza estableciendo un entorno seguro mediante scripts de shell y Docker. La configuración implica proporcionar certificados digitales y iniciar los servicios necesarios para asegurar que todos los componentes estén listos para la comunicación segura.

Pasos para configurar el entorno

1. Provisión de certificados

El proyecto utiliza un script de shell (provisioning.sh) para simular una Autoridad Certificadora (CA) y generar los certificados necesarios para los servicios.

   ./provisioning.sh

2. Iniciando servicios

Docker Compose se utiliza para iniciar todos los servicios definidos en el proyecto, asegurando que estén configurados correctamente para operar de manera segura.

   docker-compose up

3. Prueba de comunicación servicio-a-servicio

Para validar la comunicación entre servicios utilizando certificados y tokens JWT, se proporciona el script test_services.sh. Este script muestra cómo diferentes servicios interactúan de manera segura utilizando sus certificados asignados.

Resolviendo los Desafíos de Seguridad en Sistemas Distribuidos

El proyecto integra varias tecnologías clave para addressing los desafíos de seguridad mencionados anteriormente. Aquí cómo cada desafío se aborda:

1. Comunicación Segura con Mutual TLS (mTLS)

Desafío

En un sistema distribuido, los servicios deben comunicarse de manera segura para evitar accesos no autorizados y brechas de datos.

Solución

El proyecto utiliza Mutual TLS (mTLS) para asegurar la comunicación entre servicios. mTLS garantiza que ambos, el cliente y el servidor, autentiquen a los demás usando sus certificados respectivos. Esta autentificación mutua evita que servicios no autorizados se comunique con servicios legítimos.

Implementación

Nginx está configurado como un proxy inverso para manejar mTLS. Requiere certificados de cliente y servidor para establecer una conexión segura, garantizando que los datos transmitidos entre servicios permanecen confidenciales y impresibles.

2. Autenticación con Keycloak

Reto

La autenticación correcta de usuarios y servicios es fundamental para evitar el acceso no autorizado.

Solución

El proyecto aprovecha Keycloak, una solución de gestión de identidad y acceso de código abierto, para manejar la autenticación. Keycloak admite varios métodos de autenticación, incluidos OpenID Connect y las credenciales del cliente, lo que lo hace adecuado para la autenticación tanto de usuarios como de servicios.

  • Autenticación de Usuarios:
    Los usuarios se autentican usando OpenID Connect. Keycloak se configura con un cliente (appTest-login-client) que maneja los flujos de autenticación de usuarios, incluyendo el inicio de sesión, la emisión de tokens y el manejo de callbacks.
  • Autenticación de Servicios:
    Para la autenticación servicio-a-servicio, el proyecto utiliza un cliente de Keycloak (client_credentials-test) configurado para el tipo de permiso de credenciales del cliente. Este método es ideal para autenticar servicios sin intervención del usuario.

Ejemplo de Flujo de Autenticación

  1. Los usuarios navegan hasta la página de inicio de sesión.
  2. Después de iniciar sesión correctamente, Keycloak redirige al usuario a una página de callback con un código de autorización.
  3. El código de autorización se intercambia a continuación por un token JWT, que se utiliza para las solicitudes subsiguientes. El archivo authn.js en el directorio nginx/njs proporciona una implementación detallada de este flujo.

Ejemplo de Autenticación de Servicio Utilizando Credenciales del Cliente

curl -X POST "http://localhost:9000/realms/tenantA/protocol/openid-connect/token" \
     -H "Content-Type: application/x-www-form-urlencoded" \
     -d "grant_type=client_credentials" \
     -d "client_id=client_credentials-test" \
     -d "client_secret=your-client-secret-here"

3. Autorización de Usuarios con Open Policy Agent (OPA) y JWT

Reto

Implementación de controles de acceso fino-grafinados para garantizar que solo los usuarios y servicios autenticados tengan acceso a recursos autorizados

Solución

El proyecto utiliza una combinación de Open Policy Agent (OPA) y tokenes JWT para imponer políticas de autorización. El proyecto demuestra tres estrategias diferentes de validación de JWT para garantizar una seguridad robusta:

  1. Recuperación de certificados de Keycloak: Recupera los certificados dinámicamente de Keycloak para validar el token.
  2. Uso de x5t (Huella digital): Utiliza la huella digital integrada en el token para recuperar la clave pública de un almacén de confianza local.
  3. Validación de certificado integrado: Valida el token utilizando un certificado integrado, garantizando que el certificado se valida contra una Autoridad Certificadora (CA) confiable.

Consulte el archivo nginx/njs/token.js para la implementación detallada de estas estrategias.

4. Aplicación de Políticas con Open Policy Agent (OPA)

Reto

Implementación de políticas de control de acceso dinámicas y flexibles tanto para servicios como para usuarios

Solución

OPA se utiliza para aplicar políticas de control de acceso con granularidad. Las políticas se escriben en un lenguaje declarativo (Rego) y se almacenan en el directorio opa/. Estas políticas determinan las condiciones bajo las cuales los servicios pueden comunicarse y los usuarios pueden acceder a recursos, garantizando que los controles de acceso se apliquen de manera consistente a través del sistema.

5. Gestión de Certificados

Reto

Gestión de certificados digitales para servicios para establecer la confianza y asegurar las comunicaciones

Solución:
El proyecto incluye un sistema robusto de gestión de certificados. Un script de shell (provisioning.sh) se utiliza para simular una Autoridad Certificadora (CA) y generar certificados para cada servicio. Este enfoque simplifica la gestión de certificados y garantiza que todos los servicios tienen las credenciales necesarias para la comunicación segura.

También hemos agregado un punto final para actualizar el certificado del servicio sin la necesidad de reiniciar nginx.

curl --insecure  https://localhost/certs  --cert certificates/gen/serviceA/client.crt --key certificates/gen/serviceA/client.key -F cert=@certificates/gen/serviceA/client.crt -F key=@certificates/gen/serviceA/client.key

Conclusión

Construir un sistema distribuido seguro requiere un cuidado considerado de varios aspectos de seguridad, incluyendo la comunicación segura, autenticación, autorización, aplicación de políticas y gestión de certificados. Este proyecto de código abierto proporciona un ejemplo completo de cómo integrar varios mecanismos de seguridad para abordar estos retos efectivamente.

Al seguir las configuraciones y ajustes demostrados en este proyecto, los desarrolladores pueden aprovechar el TLS mutuo, Keycloak, Open Policy Agent y Nginx para construir una arquitectura de seguridad robusta. Estas tecnologías, combinadas, proporcionan una fuerte base para proteger sistemas distribuidos contra una amplia gama de amenazas, garantizando tanto la protección de datos como el control de acceso seguro.

Source:
https://dzone.com/articles/designing-a-secure-architecture-for-distributed-systems