domingo, 23 de octubre de 2011

Django y AJAX

Llevo unos meses utilizando el framework Django y me parece una maravilla. En la última aplicación que estoy realizando me he encontrado con un pequeño problema a la hora de utilizar en una plantilla tecnología AJAX. Concretamente el problema con el que me he topado ha sido para recoger unos datos mediante jQuery con un post. Tengo dos select combinados, de tal forma que al hacer la selección del primero, los datos del segundo se actualizan dependiendo del valor del primero.

Pues debido a la protección que trae Django para CSFR (Cross Site Request Forgery), la llamada post que hago para traerme los datos en JSON no es válida, ya que no estaba mandando el token válido para CSFR.

La solución, la propia documentación de Django te la da.

Básicamente se trata de meter este código en nuestro template:

$(document).ajaxSend(function(event, xhr, settings) {
    function getCookie(name) {
        var cookieValue = null;
        if (document.cookie && document.cookie != '') {
            var cookies = document.cookie.split(';');
            for (var i = 0; i < cookies.length; i++) {
                var cookie = jQuery.trim(cookies[i]);
                // Does this cookie string begin with the name we want?
                if (cookie.substring(0, name.length + 1) == (name + '=')) {
                    cookieValue = decodeURIComponent(cookie.substring(name.length + 1));
                    break;
                }
            }
        }
        return cookieValue;
    }
    function sameOrigin(url) {
        // url could be relative or scheme relative or absolute
        var host = document.location.host; // host + port
        var protocol = document.location.protocol;
        var sr_origin = '//' + host;
        var origin = protocol + sr_origin;
        // Allow absolute or scheme relative URLs to same origin
        return (url == origin || url.slice(0, origin.length + 1) == origin + '/') ||
            (url == sr_origin || url.slice(0, sr_origin.length + 1) == sr_origin + '/') ||
            // or any other URL that isn't scheme relative or absolute i.e relative.
            !(/^(\/\/|http:|https:).*/.test(url));
    }
    function safeMethod(method) {
        return (/^(GET|HEAD|OPTIONS|TRACE)$/.test(method));
    }

    if (!safeMethod(settings.type) && sameOrigin(settings.url)) {
        xhr.setRequestHeader("X-CSRFToken", getCookie('csrftoken'));
    }
}); 


Tengo pendiente escribir un post con un pequeño manual de Django, donde explicar las nociones más básicas y crear un pequeño proyecto.

miércoles, 21 de septiembre de 2011

Control de procesos

Gracias a supervisor, podremos controlar de manera fácil y precisa los procesos que queramos. Presentaré cómo instalarlo sobre Ubuntu y un pequeño ejemplo de uso.

Lo primero que haremos será instalarlo desde el repositorio:

sudo apt-get install supervisor

Lo más probable es que nos de un error al no encontrar una dependencia: elementtree. Por tanto lo que haremos es desinstalarlo:

sudo apt-get remove supervisor

e instalar la dependencia:

sudo easy_install elementtree

Tras esto ya podremos instalar supervisor

sudo apt-get install supervisor

Bien, ya lo tenemos instalado y ejecutando, pero sin hacer nada útil, así que vamos a modificar el fichero de configuración que trae por defecto y que se encuentra en /etc/supervisor/supervisord.conf, añadiendo las siguientes entradas:

;activamos la interfaz web
[inet_http_server] ; inet (TCP) server disabled by default
port=*:9001 ; (ip_address:port specifier, *:port for all iface)
username=admin ; (default is no username (open server))
password=admin ; (default is no password (open server))

;añadimos un proceso a controlar
[program:cat]
command=/bin/cat ; the program (relative uses PATH, can take args)
process_name=%(program_name)s ; process_name expr (default %(program_name)s)
numprocs=1 ; number of processes copies to start (def 1)
directory=/tmp ; directory to cwd to before exec (def no cwd)


Existen muchas más opciones, así que lo mejor es que echéis un vistazo a la página oficial.

Una vez hechos los cambios, reiniciaremos supervisor:

sudo /etc/init.d/supervisor stop; /etc/init.d/supervisor start

Y podremos comprobar su funcionamiento accediendo a la url: http://localhost:9001

Desde aquí podemos parar/arrancar el proceso o ver el log (si escribe algún log y lo hemos configurado en superfisord.conf).

Ahora veamos si funciona realmente. Comprobaremos si nuestro proceso (un simple cat) está arrancado por supervisor:


Efectivamente, ahí está activo, con PID 3702 (al igual que vimos en la interfaz web).

Matemos el proceso con un kill -9 3702 y volvamos a hacer un ps:



Y ahí lo volvemos a tener, con un PID nuevo, como podremos comprobar desde la interfaz web.


Además de esto, supervisor tiene un modo consola muy útil que nos permitirá ver el estado de nuestros procesos y hacer con ellos prácticamente de todo. Tan sólo tenemos que entrar supervisorctl:


Si escribimos help, tendremos todas las opciones que nos ofrece.


Pues nada más, ahora a buscarle utilidad a esta gran herramienta.

lunes, 12 de septiembre de 2011

Controla el estado de la memoria en aplicaciones Java

En muchas ocasiones nos encontramos con aplicaciones que tienen leak de memoria, y se va consumiendo este recurso sin que sea liberado adecuadamente. La solución: corregir el código, que suele ser el principal origen del problema. Pero cuando eso no depende de ti y tienes que ofrecer disponibilidad en dicha aplicación, una posible solución es controlar el consumo que hace la aplicación de la memoria, y en función de esta, realizar un reinicio antes de su degradación.

Aquí dejo un script que puede resultar útil. Se basa en controlar como se consume la memoria en las zonas Eden y Old Generation. Al haber una fuga de memoria, la zona Old Generation no se liberará como debe, y la zona Eden se consumirá también, imposibilitando la creación de nuevos objetos.

El script lo que hace es controlar estas zonas y cuando se alcance cierto umbral durante cierto número de ciclos consecutivos, reiniciar la aplicación (evitamos que la aplicación se acabe degradando y que al final la tengamos que reiniciar a mano):



#!/bin/bash

#Se obtiene el PID del proceso java utilizando jps y filtrando por Bootstrap
PID=`jps | grep Bootstrap | cut -d " " -f 1`
DATE=`date +%d-%m-%y----%H:%M:%S`
#Log para registrar las acciones del propio script
LOG="/scripts/reinicio_mem.log"
#Fichero temporal
TMP="/tmp/valores.txt"
#Se lanza el jmap -heap para obtener los valores del Eden y Old Generation
su - tomcat -c "jmap -heap $PID | grep -A4 -e Eden -e Old | grep % | cut -d '%' -f 1" > $TMP
CONT=1
FICH_CONTADOR="/tmp/contador"
FICH_SEGUIDO="/tmp/seguido"
#Script para levantar tomcat
SCRIPT_ARRANQUE="/scripts/arranque_tomcat.sh"
#Script para parar tomcat
SCRIPT_PARADA="/scripts/parada_tomcat.sh"
#Script para el envío de correo
SCRIPT_CORREO="/scripts/envia_correo.py"

#Función para reiniciar tomcat
reinicio () {
    $SCRIPT_PARADA &
    wait
    $SCRIPT_ARRANQUE &
    wait
    $SCRIPT_CORREO &
    wait
    return 0
}


#Función para controlar el conteo de veces seguidas que supera el valor umbral. 
#Tras 5 veces seguidas se procede a reiniciar tomcat
contador () {
    if [ -e $FICH_SEGUIDO ]; then
        VALOR_CONTADOR=`cat $FICH_CONTADOR`
        VALOR_CONTADOR=`expr $VALOR_CONTADOR + 1`
        if [ $VALOR_CONTADOR -eq 5 ]; then
            rm -rf $FICH_SEGUIDO
            echo "Se alcanzan valores por encima del 99% durante 5 veces consecutivas. Se reinicia tomcat." >> $LOG
            echo 0 > $FICH_CONTADOR
            reinicio
        else
            echo $VALOR_CONTADOR > $FICH_CONTADOR
        fi
    else
        touch $FICH_SEGUIDO
        echo 1 > $FICH_CONTADOR
    fi
}

#Se asigna de forma dinámica el nombre de la variable y su valor
for i in $( cat $TMP | tail -2); do
    eval export "VAR_${CONT}=`echo $i`"
    CONT=2
done

echo $DATE >> $LOG
echo "Eden: " $VAR_1"%" >> $LOG
echo "Old: " $VAR_2"%" >> $LOG
let EDEN=`echo $VAR_1 | cut -d "." -f 1`
let OLD=`echo $VAR_2 | cut -d "." -f 1`
if [ $EDEN -ge 99 ] && [ $OLD -ge 99 ]; then
    echo "Eden y Old Generation por encima del 99%" >> $LOG
    contador
else
    echo "Eden y Old Generation por debajo del 99%" >> $LOG
    rm -rf $FICH_SEGUIDO
fi

Para el envío de correo, podemos utilizar un script como este:


 #!/usr/bin/env python
# -*- coding: iso-8859-15 -*-

import os, string,smtplib, socket
from email.MIMEBase import MIMEBase
from email.MIMEText import MIMEText
from email.Utils import COMMASPACE, formatdate
from email import Encoders

maquina = socket.gethostbyaddr(socket.gethostname())[0]

#Funcion para el envio de correo
def sendMail(to, subject, text, server="servidor.domino.es"):
    assert type(to)==list
    fro = maquina + "@dominio.es"

    COMMASPACE = ', '
    msg = MIMEText(text)
    msg['From'] = fro
    msg['To'] = COMMASPACE.join(to)
    msg['Date'] = formatdate(localtime=True)
    msg['Subject'] = subject


    smtp = smtplib.SMTP(server)
    smtp.sendmail(fro, to, msg.as_string() )
    smtp.close()


sendMail(
        ["destinatario@dominio.es"],
        "Reinicio " + maquina,"Se ha reiniciado la " + maquina + " tras 5 ciclos seguidos con valores por encima del umbral de uso de memoria."
        )

jueves, 25 de agosto de 2011

Diangosticar y solucionar problemas de memoria en Java

Adjunto un documento que he traducido del artículo "Chuk-Munn Lee of Sun Microsystems Troubleshoots Java SE 6 Deployment" que me parece muy interesante.

Trata diversas formas de obtener información para analizar posibles problemas de memoria en aplicaciones Java.


Solución de problemas de memoria en java


Espero que sea de utilidad.

domingo, 14 de agosto de 2011

Material Defectuoso. Nuevo disco de Extremoduro.

Siempre he añadido entradas sobre temas de informática, pero hoy me apetece añadir una entrada musical.... Se trata del nuevo disco de Extremoduro. Es difícil no decir nada después de haberlo escuchado. Me ha sorprendido gratamente y creo que a todo aquel que le guste la música que hacen, también habrán disfrutado con esta joyita:


Letra de Tango Suicida


Sangre negra de esta herida brota,
no dejo de pensar que te deje marchar.

Nunca había estado un alma tan rota
desde que tu no estas no quiere recordar.

Se paso una vida entera
y yo solo guardo el recuerdo
de una pocas horas.

Era primavera,
el sol salió ese día
por ponerse a tu vera.

Y el olor de un día de enero,
estribadito en tu agujero,
sígue en mi cabeza.

Y un verano juntos de la mano,
y me pasao la noche fuera.

Ya todo el año me hace daño
y me vuelvo a llevar
a patadas con la primavera.

Junto a las hojas que el otoño vino a derribar
me deje llevar... me deje llevar.

Que te corre por las venas,
que te noto que te falta, nena,
temperatura, ¿que algo te hiela?
eso me apura, toda una vela.

Deja que te diga, nena,
que lo nuestro no es equitativo,
todas las noches que estoy contigo
tu eres quien come, yo soy comido.

Deja que te diga la razón
si tu imaginación
no encuentra una sola respuesta.

Tu deja que te clave en un arpón,
justo en el corazón,
así lo mismo te contesta.

Morir, sin mas, pues nadie me ha venido a despertar.
No estas, me abrí, y nadie me ha venido a despedir.

Sin nada mejor, que andar por dentro hurgándome,
sin nada mejor que hacer, tostándome al sol,
hurgando en el recuerdo y no lo entiendo mejor que ayer.

-Dinos que te pasa
-Estoy jodido, perdí la conciencia,
y ahora ando siempre sumergido
en montones de mierda.

-No ha dormido bien el señorito
-Iros a la mierda
-Que no se acostumbra a estar solito
en esa cabeza.

Dices que te hago daño,
¿es que no entiendes que te extraño a mi manera?

Ya que preguntas, pa' ahogar mis penas,
me fui de putas la noche entera.

Dijiste que nunca mintiera,
que dijera la verdad aunque duela.
¿Por que me miras de esa manera?
Después te fuiste,
y "adiós muy buenas"

Deja que te diga la razón
si tu imaginación
no encuentra una sola respuesta.

Tu deja que te clave en un arpón,
justo en el corazón,
así lo mismo te contesta.

Morir, sin mas, pues nadie me ha venido a despertar.
No estás, me abrí, y nadie me ha venido a despedir.

Hoy noto que no,
que no me da la gana, yo la vida doy por saber
si un mundo mejor esta esperándome mañana,
un mundo mejor que ayer.

Anda y cuéntale a tu diosecito que aquí huele a mierda.
Y dijo Judas: "solo necesito un trozo de cuerda"

-No ha dormido bien el señorito
-Iros a la mierda
-Que no se acostumbra a estar solito en esa cabeza.

Python + Jython. Cómo cambiar el estado de Alfresco 3.2r

Ante la necesidad de cambiar el estado de lectura/escritura de Alfresco de forma automática (para realizar los backup) he realizado unos scripts basándome en el jythonJmxClient.py de matthew@thebitsource.com.

La idea consiste en conectarme vía JMX a la instancia de alfresco para cambiar el atributo server.transaction.allow-writes del mbean Alfresco:Type=Configuration,Category=sysAdmin,id1=default.

Para esto me valgo del script jythonJmxClient.py, pero añadiéndole un nuevo método, def do_setAttribute(self, line). Este método será el que nos permita cambiar el valor del atributo:

def do_setAttribute(self, line):
                """setAttribute -m|--mbeanpath <path to mbeanr> -a|--attribute <name of attribute>
                Set the mbean server for a specific attribute"""

                #annoying option parsing stuff - need cmd2
                parser = optparse.OptionParser(conflict_handler="error")
                parser.add_option('-m', '--mbeanpath', dest='mbp', type='string')
                parser.add_option('-a', '--attribute', dest='attr')
                parser.add_option('-v', '--value', dest='val')
                (options, args) = parser.parse_args(line.split())
        
                value = javax.management.Attribute(options.attr,options.val)
                obn =  javax.management.ObjectName(options.mbp);
                remote.setAttribute(obn, value);

Antes que nada, debemos activar la conexión JMX en nuestro servidor de aplicaciones (tomcat en mi caso) añadiendo las siguientes opciones:

CATALINA_OPTS="-Dcom.sun.management.jmxremote -Dcom.sun.management.jmxremote.port=9696 -Dcom.sun.management.jmxremote.authenticate=true -Dcom.sun.management.jmxremote.password.file=/opt/alfresco/jmxremote.password -Dcom.sun.management.jmxremote.access.file=/opt/alfresco/jmxremote.access -Dcom.sun.management.jmxremote.ssl=false"


Estos son los scripts que vamos a utilizar:

- estado_alfresco.py (encargado de llamar al script jython de conexion jmx y de pasarle los parámetros adecuados).
- jythonJmxClientAlfresco.py (script en jython para la conexión jmx).
- read_only.txt (fichero de texto con parámetros para conexión y valores a cambiar para poner alfresco en sólo lectura).
- read_write.txt (fichero de texto con parámetros para conexión y valores a cambiar para poner alfresco en lectura/escritura).
- ver_estado.txt (fichero de texto con parámetros para conexión y valores a consultar para ver su estado).

De este modo, si queremos poner alfresco en sólo lectura, haremos la siguiente llamada:

estado_alfresco.py read_only

para ponerlo en lectura/escritura:

estado_alfresco.py read_write

y para ver su estado:

estado_alfresco.py ver_estado

En cada caso imprimirá por pantalla el cambio realizado y su resultado.

Nota: No lo he comentado, pero para que funcione hay que tener instalado jython en el sistema.

lunes, 9 de mayo de 2011

Codificación de caracteres

Si necesitamos cambiar la codificación de caracteres de un fichero, podemos hacerlo de esta manera (por ejemplo, pasar de UTF-8 a ISO-8859-1):

iconv -f UTF-8 -t ISO-8859-1 fichero_origen > fichero_destino

Obtener informacion de repositorios a través de los metadatos .git publicados por error

 A raiz de CTF realizado recientemente, me ha parecido interesante publicar este post sobre los errores de seguridad que se encuentran en mu...