miércoles, 18 de enero de 2012

De terror: Weblogic y filtros de servlets

Para hacer el cuento corto: a un suscriptor de Dinámica en Perú le tocó instalar una webapp hecha con nuestro framework en un servidor WebLogic y reportó un comportamiento absolutamente anormal: "un usuario sin autorización puede ejecutar un URL restringido, el filtro de seguridad de Dinámica parece no estar funcionando en WebLogic! aunque las pruebas en Tomcat funcionaron perfecto..." y por nuestra parte hemos verificado este mecanismo en Glassfish, Oracle J2EE container y Resin, además de Tomcat. Tiene años funcionando sin novedades.

No tuvimos alternativa, nos tocó montar un WebLogic de desarrollo para hacer nuestras propias pruebas controladas, usamos el último disponible, v12.1.1. Un proceso innecesariamente accidentado, a pesar que en principio era descomprimir un ZIP y cambiar unas variables de ambiente, resultó un dolor de cabeza por diversos motivos. En fin, lo pusimos en marcha y procedimos a probarlo reproduciendo el caso reportado por nuestro suscriptor, usando la webapp que sirve como consola de seguridad -Admin-, pero levantando unas trazas adicionales que serían útiles para diagnosticar el caso, usando tanto facilidades del framework Dinámica así como los logs del servidor.

Usando una credencial de usuario sin suficientes permisos, pudimos comprobar que nos dejaba ejecutar URLs restringidas... ese era el síntoma. Las evidencias resultaron más inquietantes.

El filtro de seguridad verifica los roles del usuario y los niveles de autorización de cada rol para ver si el URL requerido puede o no ser ejecutado, si no tiene permisos suficientes, se retorna un error http 403, acceso denegado, de lo contrario se deja pasar el request. No hay espacio para la ambiguedad:

Cuando verificamos los logs HTTP de WebLogic, la cosa se pone peor:

[12/Jan/2012:21:04:26 -0430] "GET /admin/action/admin/app/view HTTP/1.1" 200 4648 
[12/Jan/2012:21:06:12 -0430] "GET /admin/action/admin/app/edit?id=501 HTTP/1.1" 403 1833


El URL o Action -en la jerga de Dinámica- en cuestión es /app/edit, pudimos constatar en el browser que el servidor nos retornó la página que por la configuración de seguridad no deberíamos haber visto, pero lo más extraño es que quedó registrada una respuesta 403, de acceso denegado, sin embargo la página objetivo fue retornada, no un mensaje de error, ¿cómo es esto posible? El filtro parece estar haciendo su trabajo, pero el mismo es ignorado por WebLogic!

Más evidencia, esta vez de las trazas que deja el mecanismo de seguridad de Dinámica al momento de interceptar el request para el URL restringido /app/edit:

#### <[Dinamica_DEBUG_SecurityFilter] URI (/action/admin/app/edit) Intercepting request...> 
#### <[Dinamica_DEBUG_SecurityFilter] URI (/action/admin/app/edit) Session Cookie: f78WPPKWfgbGCNjhgJhTv80GpqqvWjXnWXyh19Nb0QlxfQQcNp1W!-750755119!1326418454955>
#### <[Dinamica_DEBUG_SecurityFilter] URI (/action/admin/app/edit) Authorized Roles (sysadmin;) USER (mcordova) User Roles (tester;) > 
#### <[Dinamica_DEBUG_SecurityFilter] URI (/action/admin/app/edit) Request rechazado por falla de autorización> 

Se puede ver claramente que el filtro rechazó el request!!! nunca se ejecutó el método next.doFilter() que es  lo que haría que el request se ejecute después de pasar por el filtro. ¿Cómo es posible que WebLogic retorne la página si nunca se ejecutó el doFilter? Una falla horrorosa en la implementación de la especificación de servlets.

La causa:

Resulta ser que en el web.xml de una aplicación hecha por Dinámica, se mapea el código de error HTTP 403 a un Servlet, práctica perfectamente aceptada en el estándar de servlets.


Pues esto no le gustó a WebLogic, y en vez de dejar algún rastro en sus logs o de retornar un propio mensaje para el código 403, decidió que era mejor retornar el recurso solicitado, aunque el filtro nunca lo dejo pasar!

La solución al problema fue usar un recurso estático, una página HTML en la raíz de la webapp y referenciarlo como mapping para el error 403 en web.xml. El problema desapareció y el filtro de seguridad de Dinámica funcionó como se esperaba, consistente con la configuración de seguridad.

La experiencia sirvió para enriquecer y actualizar nuestra guía de Deployment JEE de Dinámica, que muestra como hacer deployment de webapps hechas con Dinámica en distintos servidores JEE, ahora incluyendo a WebLogic v12.1.