Saltar a contenido

Seguridad por escenario de despliegue en Mentat

Consideraciones de seguridad a tener en cuenta al desplegar Mentat en cada escenario —no una auditoría de vulnerabilidades, sino qué mirar y qué decidir en cada caso.

TL;DR

  • Mentat se despliega en cuatro escenarios (GPU compartida, cloud autogestionado, cliente que solo consume agentes, y on-premise), y cada uno tiene un perfil de riesgo distinto.
  • El más delicado es el Escenario 3 (cliente solo consume agentes): conviven dos aplicaciones sobre la misma infraestructura y hay que resolver sesión y autorización con cuidado.
  • Las preocupaciones recurrentes son la exposición de puertos, el aislamiento de trazas en Langfuse y el control de acceso al gateway LiteLLM.
  • Al final hay una tabla-resumen de riesgos y una lista de decisiones de seguridad pendientes.

Contexto de arquitectura

Este artículo asume la arquitectura descrita en Arquitectura de Mentat — el framework RAG. En resumen: Mentat es la plataforma base (ingesta + RAG) sobre la que cada cliente monta sus agentes; todas las llamadas a los modelos pasan por un gateway LiteLLM con trazas en Langfuse, los modelos corren en local con Ollama, y los datos viven en Qdrant (vectores) y PostgreSQL (estructurado).

Dimensiones de seguridad analizadas

  1. Autenticación — ¿quién puede entrar y cómo se verifica?
  2. Autorización — ¿qué puede ver y hacer cada rol?
  3. Aislamiento de datos — ¿puede un usuario ver datos de otro cliente?
  4. Trazas y observabilidad — ¿quién ve las trazas de Langfuse?
  5. Sesión compartida — ¿la UI de Mentat y la app del cliente comparten sesión?

Escenario 1 — Múltiples clientes, GPU compartida

Dimensión Situación Riesgo Recomendación
Autenticación Cada instancia de Mentat tiene su propio sistema de auth (sesiones Redis) Bajo — instancias aisladas Mantener auth por instancia
Autorización Roles admin / user_avc por instancia Bajo Añadir rol consumer para usuarios finales
Aislamiento de datos Cada cliente tiene su propio Qdrant + PostgreSQL Bajo Verificar que el DOCS_COLLECTION no se comparte
Trazas Langfuse Si Langfuse es compartido, el equipo ve las trazas de todos los clientes Medio Separar proyectos en Langfuse por cliente, o un Langfuse por instancia
Sesión compartida La UI de Mentat y app cliente en el mismo dominio/puerto → misma cookie Bajo Sin problema si van en la misma instancia
LiteLLM compartido Todas las llamadas LLM pasan por el mismo proxy con una LITELLM_MASTER_KEY compartida (gasto agregado, sin distinguir servicios) Medio Separar en virtual keys por cliente/servicio (fase Build) para atribución de gasto y límites de uso; la Admin UI requiere una BD litellm propia en PostgreSQL

Escenario 2 — Cliente autogestionado en cloud

Dimensión Situación Riesgo Recomendación
Autenticación Instancia propia → auth propia Bajo El cliente gestiona sus propios usuarios
Autorización El cliente es admin de su instancia Medio Definir qué puede tocar el cliente admin y qué no (ej. no puede modificar prompts base de Mentat)
Aislamiento de datos Stack completo aislado Bajo Sin riesgo de fuga entre clientes
Trazas Langfuse Langfuse propio del cliente Bajo El cliente ve solo sus trazas
Sesión compartida App cliente en la misma instancia Bajo Sin problema
Exposición de puertos El cliente gestiona su infraestructura cloud Alto Documentar qué puertos deben estar cerrados al exterior (Qdrant, Redis, PostgreSQL, Adminer solo en localhost)

Escenario 3 — Cliente solo consume agentes

El escenario más complejo

Es el más delicado desde el punto de vista de seguridad porque hay dos aplicaciones (la UI de Mentat interna + la app de cliente externa) sobre la misma infraestructura.

Dimensión Situación Riesgo Recomendación
Autenticación Dos apps, ¿una sesión o dos? Alto Definir estrategia (ver opciones abajo)
Autorización El cliente no debe ver ingesta, prompts internos ni jobs Alto Rol consumer: solo accede a /agentes, sin acceso al resto de Mentat
Aislamiento de datos El cliente solo consulta su colección Qdrant Medio agents-api debe validar que el collection pertenece al cliente autenticado
Trazas Langfuse El cliente no debería ver las trazas Medio Langfuse es solo para el equipo interno, no expuesto al cliente
Sesión compartida Apps en dominios distintos → cookies no se comparten Alto Ver opciones de sesión compartida abajo
API agents-api expuesta El cliente llama directamente a agents-api Medio agents-api debe requerir autenticación, no ser un endpoint público

Opciones para gestión de sesión

Opción A — Mismo dominio, rutas separadas (recomendada para empezar)

  • Admin (Mentat) en https://app.empresa.com
  • App cliente en https://app.empresa.com/cliente
  • Misma cookie de sesión, el rol consumer limita el acceso
  • Ventaja: sin complejidad de auth adicional
  • Desventaja: el cliente accede al mismo dominio que el equipo interno

Opción B — Subdominios con sesión compartida

  • Admin (Mentat) en https://admin.empresa.com
  • App cliente en https://app.empresa.com
  • Sesión compartida via cookie en dominio padre (.empresa.com)
  • Ventaja: separación visual clara
  • Desventaja: requiere HTTPS y configuración de cookies de dominio

Opción C — Auth independiente con JWT

  • Cada app tiene su propio sistema de auth
  • agents-api valida JWT en lugar de cookie de sesión
  • Ventaja: máxima independencia
  • Desventaja: duplicar la gestión de usuarios, más complejidad

Escenario 4 — On-premise en el cliente

Dimensión Situación Riesgo Recomendación
Autenticación El cliente gestiona todo Bajo Documentar cómo crear el primer admin
Autorización El cliente es dueño de la instancia Bajo Sin restricciones adicionales
Aislamiento de datos Todo en la red del cliente Bajo El mayor riesgo es la seguridad de la red interna del cliente, no nuestra responsabilidad
Trazas Langfuse 100% en local del cliente Bajo Soberanía total de datos
Exposición de puertos Crítico — el docker-compose actual expone algunos puertos sin restricción Alto Ver checklist abajo
Ollama expuesto Ollama por defecto escucha en 0.0.0.0 Medio Configurar Ollama para escuchar solo en localhost o red interna

Resumen de riesgos por escenario

Escenario Riesgo global Principal preocupación
1 — GPU compartida Medio Langfuse compartido puede exponer trazas entre clientes
2 — Cloud autogestionado Medio Puertos expuestos en cloud si el cliente no configura el firewall
3 — Solo consume agentes Alto Gestión de sesión entre dos apps y autorización granular
4 — On-premise Bajo-Medio Puertos expuestos en red interna del cliente

Decisiones de seguridad pendientes

  1. Rol consumer — definir exactamente qué rutas puede ver y cuáles están bloqueadas
  2. Estrategia de sesión Escenario 3 — elegir entre Opción A, B o C antes de implementar la UI del cliente
  3. Autenticación en agents-api — actualmente no requiere auth propia (confía en que el backend NestJS actúa de proxy). Si se expone directamente al cliente, necesita validación de sesión propia
  4. Langfuse por cliente vs compartido — decidir en Escenario 1 si Langfuse es compartido o por instancia
  5. Reverse proxy — para producción, todos los servicios deberían estar detrás de nginx/Caddy con HTTPS

Vuelta a la arquitectura completa: Arquitectura de Mentat — el framework RAG.