31.7.08

Seguridad en aplicaciones web y modelos de navegación

Saludos.

Recientemente, por motivos de trabajo, ha caído en mis manos un manual de buenas prácticas de seguridad para el desarrollo de aplicaciones. Después de ojearlo me han pedido unas ideas de cómo poder evaluar que, en el proceso de desarrollo de una aplicación, se está poniendo en práctica todo lo que viene en dicho manual.

Pensando en ello me ha vuelto a quedar patente la importancia, sobre todo en aplicaciones web, de contar con buenos modelos de referencia y, sobre todo, con un buen modelo navegacional. Un modelo navegacional representa (como no puede ser de otra manera) la navegación del sistema. Cuando hablo de navegación no hablo de en qué pantalla estoy y a qué otra pantalla puedo ir. Eso vendrá más adelante y es solo una parte de la navegación.

Los modelos de navegación con los que trabajo (más información en www.iwt2.org), y muchos otros propuestos por empresas e investigadores, son el pegamento de modelos de información, funcionales y de actores / roles, junto con algunos añadidos más.

Un buen modelo navegacional nos dice con precisión cuáles son los actores / roles que interactúan con la aplicación y qué funcionalidad (por ejemplo definida mediante casos de uso) tiene disponible cada uno, qué información y qué campos de dicha información es accesible para cada actor y qué información no lo es (por ejemplo definida mediante prototipos de visualización o diagramas de clases conceptuales), y, por supuesto, a qué otras secciones de la aplicación pueden acceder o no. Todo esto combinado con información sobre validaciones, permisos, etc. incluida en los requisitos funcionales (por ejemplo mediante los mecanismos de precondiciones y postcondicione sutilizados por muchos autores) nos proporcionan abundante información de seguridad
Por supuesto, luego habrá muchas más reglas a tener en cuenta en diseño y en codificación (verificación de parámetros y controles de seguridad en todas las capas, almacenamiento de información encriptada, etc.), pero ya contamos con una buena base de seguridad en nuestros modelos sin necesidad de realizar ninguna inversión en herramientas o técnicas específicas de seguridad.

A divertirse.

16.7.08

Extendiendo PMD con nuevos renderers

PMD es una herramienta de verificación que código Java que permite aplicar un conjunto de reglas (actualmente tiene aproximadamente 240 reglas) y generar un informe con los resultados. En una entrada anterior (http://rincew.blogspot.com/2008/02/escribiendo-reglas-en-pmd.html) conté como escribir una nueva regla. En esta entrada voy a dar unas ideas de cómo desarrollar un nuevo informe de resultados.

Los encargados de procesar los resultados de la verificación se llaman renderers. PMD trae un conjunto de renderers ya construidos para mostrar los resultados como texto, o como HTML, o CSV, o XML. Es útil crear un renderer propio cuando se quiere hacer un procesado adicional, cuando queremos generar un nuevo tipo de resultado, por ejemplo un informa en RTF o añadir el resultado a una BBDD, o cuando queremos ampliar alguno de los renderers ya existentes para incluya información adicional. Hay que recalcar que todas las acciones anteriores pueden hacerse e otra manera, por ejemplo utilizando transformaciones XSLT o las opciones de importación de CSV de la mayoría de sistemas de BBDD.

En PMD, un renderer es una clase que implementa la interfaz Renderer del paquete net.sourceforge.pmd.renderers. Esta interfaz permite que un rederer se comporte como una máquina de estados. Al inicializar el renderer se invoca el método start(), cada vez que se ha aplicado un nuevo conjunto de reglas se invoca al método renderFileReport(Report report) y una vez que se ha acabado el proceso se invoca al método end(). Existen más métodos en esta interfaz, sin embargo no será necesario utilizarlos en este ejemplo.

Como es habitual en muchas librerías y herramientas, PMD ya ofrece una implementación base de esta interfaz en la clase AbstractRenderer (que se mantiene por motivos de compatibilidad con versiones antiguas). A pesar de su nombre, esta clase no es abstracta ni ninguno de sus métodos son abstractos. Tampoco usaremos esta clase como base para los renderers, en su lugar utilizaremos su hija OnTheFlyRenderer, la cuál sí tiene tres métodos abstractos: start, renderFileViolations y end. El funcionamiento de start y end es el mismo que el definido anteriormente, sin embargo, para cada conjunto de reglas, el método invocado será el método renderFileViolations(Iterator violations)


Este método, recibe un iterador con todas las violaciones detectadas para un conjunto de reglas concreto. Una violación es un objetivo de una clase que implementa la interfaz IRuleViolation. A partir de los métodos get de esta interfaz podemos conocer toda la información que PMD maneja del error como el nombre del archivo (método getFilename), la clase y el método de la violación (getClassName y getMethodName), etc.
Además, también podemos obtener toda la información referente a la regla que se ha incumplido con el método getRule. Este método devuelve un objeto que implementa la interfaz Rule y que tiene varios métodos get para conocer el nombre de la regla (getName), su prioridad (getPriority), etc.
A modo de ejemplo, a continuación se muestra un nuevo renderer que también genera una salida de texto plano pero con una información distinta y un orden distinto al renderer de texto que viene de serie en PMD.


import net.sourceforge.pmd.IRuleViolation;
import net.sourceforge.pmd.PMD;
import net.sourceforge.pmd.renderers.OnTheFlyRenderer;
import java.io.IOException;
import java.io.Writer;
import java.util.Iterator;

public class RendererTexto extends OnTheFlyRenderer {


public void start() throws IOException {

}

public void renderFileViolations(Iterator violations)
throws IOException
{
Writer writer = getWriter();
StringBuffer buf = new StringBuffer();

while (violations.hasNext()) {
IRuleViolation rv = violations.next();
buf.append(PMD.EOL);
buf.append(rv.getFilename());
buf.append(':');
buf.append(Integer.toString(rv.getBeginLine()));
buf.append('\t');
buf.append(rv.getRule().getName());
buf.append(": ");
buf.append(rv.getDescription());

writer.write(buf.toString());
}
}

public void end() throws IOException {
getWriter().write("Ok.");
}

}



Como heredamos de OnTheFlyRenderer solo nos tenemos que preocupar de los tres métodos antes mencionados. En concreto, en el método start no hemos nada. En el método renderFileViolations recorremos cada una de las violaciones mostrando el nombre del fichero y la línea donde ocurre, el nombre de la regla y su descripción. En el método end escribimos la cadena de texto Ok para indicar que el proceso terminó con éxito.
Por último, será necesario indicar a PMD que utilice el nuevo renderer. Para ello es necesario que la clase esté disponible en el classpath del PMD (por ejemplo poniendo el nuevo renderer en una archivo jar y modificando el archivo pmd.bat para que añada dicho jar al classpath en cada ejecución).
Una vez hecho, solo es necesario indicar el nombre de la clase (indicando su paquete) como segundo parámetro. Por ejemplo, si la clase mostrada más arriba está guardada en el paquete pmdext, para utilizar habría que escribir:


PMD c:\src pmdext. RendererTexto basic



Con la línea anterior se verificarían todas las reglas de conjunto de regla basic en todo el código Java dentro de la carpeta src.
En verdad, el mundo de los renderes en PMD es un poco más complejo, ya que no hemos hablado de los writers (aunque se usan en el ejemplo de más arriba). Además, el report no solo nos informa de las violaciones de las reglas sino de los errores que han podido seguir a la hora de procesar un archivo o de las supresiones, es decir, bloques de código marcados para ser ignorados por PMD.
Sin embargo, con estas nociones básicas no es difícil estudiar el código de la clase OnTheFlyRenderer y ver los detalles que no hemos mencionado.
Como comentario final, quiero mencionar que el diseño del mecanismo de renders de PMD no es todo lo bueno y homogéneo que pudiera ser, por suerte es bastante sencillo de usar. Ya se ha anunciado que para la versión 5 se van a hacer cambios de código importantes y se va a romper la compatibilidad hacia atrás, por lo que tengo esperanzas de que mejoren este mecanismo.