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.
Programación en general y tonterías en particular.
31.7.08
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.
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:
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.
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
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(Iteratorviolations)
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.
21.3.08
Como aplicar inclusiones y extensiones a las plantillas de casos de uso
Saludos.
Muchos de nosotros utilizamos diagramas UML de casos de uso (ver más abajo) y, además, definimos cada caso de uso con plantillas de texto (ver más abajo). Sin embargo, en más de una ocasión ambas representaciones no son consistentes, es decir, hay una información en una de las representaciones que no está en la otra. Esto pasa, por ejemplo, a la hora de definir relaciones de inclusión y extensión. Ambas se definen en los diagramas de casos de uso pero casi nunca se incluyen en las plantillas.
A continuación expongo cómo incluyo yo dichas relaciones en mis plantillas para que sean consistentes con lo que se cuenta en el diagrama de casos de uso.
Como una inclusión debe realizarse siempre, la coloco en la secuencia principal, esto es, en los pasos que se ejecutan salvo algún error o circunstancia anómala. Con esto, además, estoy indicando en qué momento debe realizarse otro caso de uso.
Una excepción, por el contrario, puede realizarse o no dependiendo de una condición (llamada punto de extensión). Si bien los puntos de extensión pueden añadirse a los diagramas de casos de uso en la mayoría de herramientas, yo no suelo hacerlo porque, en cuanto hay más de uno, ya no se sabe qué punto de extensión corresponde a cada extensión. En cambio, añadirlo a la plantilla es muy sencillo. Sólo hay que colocar el punto de extensión y el caso de uso a realizar como un paso de la secuencia alternativa. Si los pasos de la secuencia alternativa están asociados a pasos de la secuencia principal entonces, además, estamos indicando en qué momento concreto debe evaluarse el punto de extensión para decidir si se realiza la extensión o no.
Veamos un ejemplo imaginario. Teneos el caso de uso dar de alta nuevo proyecto, en el cuál, además de introducir la información de cada proyecto, debemos indicar el supervisor del proyecto y el grupo de trabajo encargado. Un proyecto debe tener siempre un encargado, y el comportamiento para seleccionar uno lo definiremos en otro caso de uso. Además, si no encontramos un grupo de trabajo adecuado, podremos crear un nuevo grupo sobre la marcha (mediante otro caso de uso). Con todo esto tenemos tres casos de uso, una inclusión y una extensión. El diagrama correspondiente se muestra a continuación.
Veamos ahora la plantilla del caso de uso dar de alta un nuevo proyecto. Esta plantilla ha sido simplificada al máximo para este ejemplo.
Como se puede observar, las inclusiones y extensiones indicadas en el diagrama de casos de uso también están en la plantilla. Además, se ha indicado información adicional (cuando aparecen las relaciones, cuál es el punto de extensión de la extensión) de manera clara y sencilla sin necesidad de complicar el diagrama de casos de uso.
Feliz semana.
Muchos de nosotros utilizamos diagramas UML de casos de uso (ver más abajo) y, además, definimos cada caso de uso con plantillas de texto (ver más abajo). Sin embargo, en más de una ocasión ambas representaciones no son consistentes, es decir, hay una información en una de las representaciones que no está en la otra. Esto pasa, por ejemplo, a la hora de definir relaciones de inclusión y extensión. Ambas se definen en los diagramas de casos de uso pero casi nunca se incluyen en las plantillas.
A continuación expongo cómo incluyo yo dichas relaciones en mis plantillas para que sean consistentes con lo que se cuenta en el diagrama de casos de uso.
Como una inclusión debe realizarse siempre, la coloco en la secuencia principal, esto es, en los pasos que se ejecutan salvo algún error o circunstancia anómala. Con esto, además, estoy indicando en qué momento debe realizarse otro caso de uso.
Una excepción, por el contrario, puede realizarse o no dependiendo de una condición (llamada punto de extensión). Si bien los puntos de extensión pueden añadirse a los diagramas de casos de uso en la mayoría de herramientas, yo no suelo hacerlo porque, en cuanto hay más de uno, ya no se sabe qué punto de extensión corresponde a cada extensión. En cambio, añadirlo a la plantilla es muy sencillo. Sólo hay que colocar el punto de extensión y el caso de uso a realizar como un paso de la secuencia alternativa. Si los pasos de la secuencia alternativa están asociados a pasos de la secuencia principal entonces, además, estamos indicando en qué momento concreto debe evaluarse el punto de extensión para decidir si se realiza la extensión o no.
Veamos un ejemplo imaginario. Teneos el caso de uso dar de alta nuevo proyecto, en el cuál, además de introducir la información de cada proyecto, debemos indicar el supervisor del proyecto y el grupo de trabajo encargado. Un proyecto debe tener siempre un encargado, y el comportamiento para seleccionar uno lo definiremos en otro caso de uso. Además, si no encontramos un grupo de trabajo adecuado, podremos crear un nuevo grupo sobre la marcha (mediante otro caso de uso). Con todo esto tenemos tres casos de uso, una inclusión y una extensión. El diagrama correspondiente se muestra a continuación.
Veamos ahora la plantilla del caso de uso dar de alta un nuevo proyecto. Esta plantilla ha sido simplificada al máximo para este ejemplo.
Como se puede observar, las inclusiones y extensiones indicadas en el diagrama de casos de uso también están en la plantilla. Además, se ha indicado información adicional (cuando aparecen las relaciones, cuál es el punto de extensión de la extensión) de manera clara y sencilla sin necesidad de complicar el diagrama de casos de uso.
Feliz semana.
22.2.08
Uso de ant y CPD
La herramienta de detección de copy&paste de PMD (http://pmd.sourceforge.net/) permite detectar fragmentos de código copiados. Esta herramienta, al igual que PMD, también incorpora una tarea ant para poder ser invocada desde dicha herramienta. Sin embargo, no está tan documentada como la tarea ant para CPD. Un ejemplo de su uso se muestra a continuación.
Como cuenta de tokens se ha elegido 50 para que detecte bloques de código repetido de entre 5 o 6 líneas ( si tienen muchos caracteres) hasta 10 u 11 líneas (si tienen pocos caracteres).
(La captura de pantalla está tomada de Microsoft Word, por eso aparecen algunas palabras subralladas).
Como cuenta de tokens se ha elegido 50 para que detecte bloques de código repetido de entre 5 o 6 líneas ( si tienen muchos caracteres) hasta 10 u 11 líneas (si tienen pocos caracteres).
(La captura de pantalla está tomada de Microsoft Word, por eso aparecen algunas palabras subralladas).
14.2.08
Escribiendo reglas en PMD
Saludos.
PMD (http://pmd.sourceforge.net/) es un programa para la verificación estática de código Java. PMD contiene bastantes reglas de programación (como no utilizar variables ni muy cortas ni muy largas o no anidar una sentencia if dentro de otra) y su función es buscar qué fragmentos de código incumplen dichas reglas.
A continuación veremos cómo añadir una nueva regla a PMD. Esta herramienta ofrece dos alternativas para las nuevas reglas: implementarlas como código Java o mediante XPath. En este ejemplo usaremos la segunda alternativa. La regla a implementar será: no se permiten genéricos de tipo Object, es decir, no se permiten declaraciones como List[Object] o Set[Object] (uso corchetes en vez de los símbolos de mayor y menor). Puede que esta regla no sea muy útil ya que el declarar genéricos que contienen Objects es tan poco práctico que difícilmente alguien lo va a usar, pero es un buen ejemplo.
Lo primero que tenemos que hacer es ejecutar la herramienta de diseño de reglas que viene con PMD (la propia herramienta viene con un script para ejecutarla). Después, escribimos un fragmento de código que incumpla la regla (como el de la figura 1) y generamos su árbol de sintaxis abstracta (muy similar a un documento XML).
Figura 1.
Ahora, tenemos que escribir una expresión XPath que encuentre sólo aquellos nodos del árbol que incumplen la regla. Para ello, tenemos que buscar aquellas declaraciones de tipo clase o interfaz con un argumento que es un tipo clase object (se puede ver un ejemplo en la figura 1)
Una posible expresión en XPath se muestra a continuación: //ReferenceType/ClassOrInterfaceType/TypeArguments/TypeArgument/ReferenceType/ClassOrInterfaceType[@Image='Object']
Para probarla, la escribimos en el cuadro de la parte superior derecha y la ejecutamos. En el cuadro que está justo debajo vemos las líneas del código Java que incumplen la regla. En la figura 1 se puede observar como la expresión detecta toda las líneas que declaran un genérico de tipo Object.
Para poder utilizar esta regla debemos incluirla en un ruleset, el cuál es un archivo XML que define un conjunto de reglas a verificar. Para no modificar ninguno de los archivos de PMD vamos a crear un nuevo ruleset. La cabecera se muestra a continuación.
[ruleset name="My custom rules" xmlns="http://pmd.sf.net/ruleset/1.0.0" nonamespaceschemalocation="http://pmd.sf.net/ruleset_xml_schema.xsd" schemalocation="http://pmd.sf.net/ruleset/1.0.0 http://pmd.sf.net/ruleset_xml_schema.xsd" xsi="http://www.w3.org/2001/XMLSchema-instance"]
….
[/ruleset]
(De nuevo uso corchetes en vez de los símbolos de mayor y menor).
La propia herramienta de diseño de reglas es capaz de generar el código XML de la regla. Dicho código (figura 2) debe incluirse entre las etiquetas ruleset.
Figura 2.
Ahora, ya es posible utilizar nuestro ruleset como parámetro de PMD para que aplique la regla que hemos definido.
PMD (http://pmd.sourceforge.net/) es un programa para la verificación estática de código Java. PMD contiene bastantes reglas de programación (como no utilizar variables ni muy cortas ni muy largas o no anidar una sentencia if dentro de otra) y su función es buscar qué fragmentos de código incumplen dichas reglas.
A continuación veremos cómo añadir una nueva regla a PMD. Esta herramienta ofrece dos alternativas para las nuevas reglas: implementarlas como código Java o mediante XPath. En este ejemplo usaremos la segunda alternativa. La regla a implementar será: no se permiten genéricos de tipo Object, es decir, no se permiten declaraciones como List[Object] o Set[Object] (uso corchetes en vez de los símbolos de mayor y menor). Puede que esta regla no sea muy útil ya que el declarar genéricos que contienen Objects es tan poco práctico que difícilmente alguien lo va a usar, pero es un buen ejemplo.
Lo primero que tenemos que hacer es ejecutar la herramienta de diseño de reglas que viene con PMD (la propia herramienta viene con un script para ejecutarla). Después, escribimos un fragmento de código que incumpla la regla (como el de la figura 1) y generamos su árbol de sintaxis abstracta (muy similar a un documento XML).
Figura 1.
Ahora, tenemos que escribir una expresión XPath que encuentre sólo aquellos nodos del árbol que incumplen la regla. Para ello, tenemos que buscar aquellas declaraciones de tipo clase o interfaz con un argumento que es un tipo clase object (se puede ver un ejemplo en la figura 1)
Una posible expresión en XPath se muestra a continuación: //ReferenceType/ClassOrInterfaceType/TypeArguments/TypeArgument/ReferenceType/ClassOrInterfaceType[@Image='Object']
Para probarla, la escribimos en el cuadro de la parte superior derecha y la ejecutamos. En el cuadro que está justo debajo vemos las líneas del código Java que incumplen la regla. En la figura 1 se puede observar como la expresión detecta toda las líneas que declaran un genérico de tipo Object.
Para poder utilizar esta regla debemos incluirla en un ruleset, el cuál es un archivo XML que define un conjunto de reglas a verificar. Para no modificar ninguno de los archivos de PMD vamos a crear un nuevo ruleset. La cabecera se muestra a continuación.
[ruleset name="My custom rules" xmlns="http://pmd.sf.net/ruleset/1.0.0" nonamespaceschemalocation="http://pmd.sf.net/ruleset_xml_schema.xsd" schemalocation="http://pmd.sf.net/ruleset/1.0.0 http://pmd.sf.net/ruleset_xml_schema.xsd" xsi="http://www.w3.org/2001/XMLSchema-instance"]
….
[/ruleset]
(De nuevo uso corchetes en vez de los símbolos de mayor y menor).
La propia herramienta de diseño de reglas es capaz de generar el código XML de la regla. Dicho código (figura 2) debe incluirse entre las etiquetas ruleset.
Figura 2.
Ahora, ya es posible utilizar nuestro ruleset como parámetro de PMD para que aplique la regla que hemos definido.
Subscribe to:
Posts (Atom)