h1

Permisos y Politicas de Seguridad con Java Frameworks: el caso de Glassfish

06/25/2008

Wizdoc [Icon By Buuf]

 Tips & Tricks

Como parte de las mejores prácticas del deployment de aplicaciones JEE, siempre es recomendable incluir en los WARs o EARs de nuestra distribución sólo el código que nosotros estamos implementando. Es decir, los frameworks y librerías de terceros que utiliza la aplicación deben estar fuera del directorio WEB-INF/lib, dejando en éste sólo los JARs que contengan nuestros componentes. Se ofrece un ejemplo utilizando esta distribución:

${j2ee-modules}
+—(Otras instalaciones)
.
.
+—MiAplicacion (directorio explotado / .WAR)
    |  web.xml
    |  struts-config.xml
    |
    +—web
    |      index.jsp
    |      error.jsp
    |
    —WEB-INF
        +—lib
        |      miscomponentes1.jar
        |      miscomponentes2.jar
        |
        —classes
               servlet1.class

En este post veremos cómo podemos extraer esos JARs de nuestras distribuciones para realizar un despliegue más limpio de la aplicación mientras al mismo tiempo mejoramos la seguridad sobre el código que estamos ejecutando; como ejemplo de configuración del servidor de aplicaciones utilizaremos el Sun Glassfish Enterprise Server (antes llamado Sun Java System Application Server), aunque este tipo de solución no se limita a éste.

Glassfish: aspectos de seguridad

Por defecto, la seguridad del Glassfish se encuentra activa. Es decir, a diferencia de otros servidores de aplicaciones como Weblogic, la creación y configuración de un dominio out-of-the-box contiene habilitadas todas las restricciones de seguridad, permitiendo sólo tareas como manipulación de sockets y archivos y generando errores de seguridad del género XPermissionException durante el despliegue o ejecución de "código no permitido". Aqui se muestran los permisos manejados por Java y aqui cómo deben manejarse estos privilegios en el código aplicativo.

Por otro lado, la mayoría de los frameworks actualmente disponibles – ya sea de web services como Axis2, persistencia como Hibernate o web como Java Server Faces – requieren ciertos permisos, de los cuales probablemente los más requeridos sean la creación y recuperación del Java ClassLoader y generar instancias de objetos a través de Reflexión.

Existen dos maneras de facilitar la ejecución de código que requiera permisos especiales de seguridad. La primera es fácil de implementar, aunque no es segura pues implica deshabilitar la seguridad de ejecución de código y la otra es un poco más complicada pero acota los permisos sólo al código o librerías que los requieren.

Deshabilitando la seguridad: la manera fácil

Para deshabilitar la seguridad durante la ejecución de código basta con ingresar a la consola de administración del Glassfish y editar las opciones de tiempo de ejecución de la Máquina Virtual de Java [Arbol de tareas >> Configuraciones >> <server-config> >> Configuración JVM >> Pestaña Opciones JVM]. En la pantalla mostrada eliminamos la opción -Djava.security.policy que indica la localización del archivo donde se encuentran configuradas las políticas de seguridad, como se muestra a continuación:


Eliminación de la variable -Djava.security.policy en la consola de administración del Glassfish. Nota: la pantalla muestra la solución para la Glassfish 8.2, pero también aplica para las siguientes, incluyendo la 9.1 U2.

La alternativa no gráfica a la solución consiste en eliminar o comentar la línea correspondiente en el archivo de configuración del dominio, encontrado en el archivo domain.xml y localizado en el directorio ${dir_install}/domains/<domain>/config/

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE domain … >

<domain … >
 <applications>…</applications>
 <resources>…</resources>
 <configs>
  <config dynamic-reconfiguration-enabled="true" name="server-config">
   <http-service>…</http-service>
   <java-config classpath-suffix="…">
    <!– various required jvm-options –>
    <jvm-options>…</jvm-options>
    <jvm-options>
     -Djava.security.policy=
${com.sun.aas.instanceRoot}/config/server.policy

    </jvm-options>
   </java-config>
    …
  </config>
 </configs>
</domain>

Sin embargo es conveniente observar que esta solución sólo es recomendable para ambientes de desarrollo, pues efectivamente estamos deshabilitando la seguridad de la JVM sobre la carga y ejecución de nuestras clases. Si en la aplicación existe código malicioso, podemos encontrarnos con una falla de seguridad potencialmente peligrosa.

Deshabilitando la seguridad: la forma talachuda pero correcta

Con esta opción, podremos designar en el archivo de políticas de seguridad sólo los permisos que nuestro código requiere. Dichas políticas se encuentran en el bloque grant del archivo server.policy localizado en el directorio de configuración del dominio ${dir_install} /domains/<domain>/config/

// Basic set of required permissions granted to all remaining code
grant {
  permission java.net.SocketPermission  "*", "connect";
  permission java.io.FilePermission   "<<ALL FILES>>", "read,write";
  permission java.util.PropertyPermission "*", "read";
};

Por otro lado, debemos depositar los JARs correspondientes a los frameworks y librerías externas en un directorio por separado. Por ejemplo, el directorio lib del dominio (${dir_install}/domains/domain1/lib/) es una buena opción si estamos compartiendo frameworks entre varios contextos aplicativos del dominio. Más tarde deberemos configurar el archivo de políticas de seguridad, agregando un bloque de permisos como se muestra a continuación:

grant codeBase "file:/opt/glass91/domains/domain1/lib/-" {
  permission java.lang.RuntimePermission "createClassLoader";
  permission java.lang.RuntimePermission "getClassLoader";
};

Nótese que estamos permitiendo la carga o creación de un ClassLoader a todas las librerías y código encontrados en /opt/glass91/domains/domain1/lib/. La asignación de permisos puede ser tan general o tan puntual como sea requerido, dependiendo de la criticidad del permiso (aqui se describe en detalle el formato de los bloques grant en un archivo de políticas de seguridad).

Finalmente, puede presentarse un problema de errores ClassNotFoundException lanzados durante la carga o ejecución de la aplicación. Esto se debe a que Glassfish no carga las librerías o código de ningún otro lugar que no sea el WEB-INF/lib de la aplicación o el directorio de librerías del servidor (${dir_install}/lib). Como solución a este detalle debemos incluir en el classpath del servidor las librerías correspondientes. Esto se logra en la consola de administración mediante la ruta [Arbol de tareas >> Configuraciones >> <server-config> >> Configuración JVM >> Pestaña "configuración de ruta" o classpath]. Alternativamente podemos editar el archivo domain.xml e incluir las librerías de forma manual en la propiedad classpath-suffix de la etiqueta java-config.

Conclusión

La reusabilidad no se limita sólo a nuestros componentes sino también a las librerías y frameworks que usamos entre diferentes aplicaciones y contextos. Por ello, con esta sencilla solución tendremos WARs y EARs con mayor limpieza y consistencia de código, aplicando security checks sólo a los componentes que lo necesitan y obteniendo deployments más ligeros que se desplegarán con mayor velocidad.

Responder

Introduce tus datos o haz clic en un icono para iniciar sesión:

Logo de WordPress.com

Estás comentando usando tu cuenta de WordPress.com. Cerrar sesión / Cambiar )

Imagen de Twitter

Estás comentando usando tu cuenta de Twitter. Cerrar sesión / Cambiar )

Foto de Facebook

Estás comentando usando tu cuenta de Facebook. Cerrar sesión / Cambiar )

Google+ photo

Estás comentando usando tu cuenta de Google+. Cerrar sesión / Cambiar )

Conectando a %s

A %d blogueros les gusta esto: