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

martes, 26 de abril de 2011

Pantalla de Administración para Alfresco

En otras ocasiones, he posteado algunos scripts para facilitar la administración de usuarios/grupos en alfresco.

El inconveniente que le encuentro a trabajar directamente con los scripts, es que para pasarle los datos (usuarios, grupos, listas,...) hay que editar directamente el js, lo que hace perder tiempo y añade la posibilidad de introducir errores en el script.

He estado investigando un poco el tema de los WebScripts, y es precisamente lo que estaba buscando. Con ellos podemos interactuar con los scripts a través de amigables formularios.

He creado una serie de ellos basándome en los js que ya tenía (con algunas modificaciones) y este ha sido el resultado.

Añado algunas imágenes para que veáis cómo queda:

- Pantalla principal de administración:

- Ver grupos por usuario. Dado un usuario, te muestra los grupos a los que pertenece:













- Inserta un usuario en varios grupos.
Dado un usuario y una lista de grupos, añade este usuario a los grupos indicados:














- Copia los permisos de un usuario origen a un usuario destino:




















- Consulta los usuarios de un grupo:
















Aquí os dejo los webscripts.

Tras subir los fichero al espacio Web Scripts, habrá que activarlos. Para ello nos vamos a /alfresco/service/index y pinchamos en "Refresh Web Scripts". Una vez terminado, ya podemos dirigirnos a la nueva ventana de administración: /alfresco/service/sample/administracion

Sólo los usuarios con rol administrador podrán logarse.

Un saludo y espero que os sirva.

martes, 19 de abril de 2011

Administración de usuarios/grupos en alfresco (II)

Siguiendo con los scripts para la administración de usuario y grupos en alfresco, añado algunos más que pueden resultar útiles:

- grupos_por_usuario.js:

Su propio nombre ya es bastante descriptivo, se trata de un script que dado un usuario, nos devuelve los grupos a los que este usuario está añadido. Y digo añadido y no pertenece, puesto que no nos da el listado de grupos padres-hijos a los que pertenece por herencia, sino directamente los grupos a los que este usuario ha sido añadido.

//Variable a rellenar
var usuario="";
//Funcion que comprueba si un usuario dado existe como hijo de un grupo dado
function comprueba_grupo_usuario (grupo, usuario) {
scr_grupo = groups.getGroup(grupo);
var usuarios = scr_grupo.getChildUsers();
var encontrado = false;

var i = 0;
while ( i<usuarios.length && !encontrado) {
if ( usuarios[i].getFullName() == usuario ){
encontrado = true;
}
i++;
}
return encontrado;
}

//Creamos el log que devolveremos
var logFile = space.childByNamePath("documento_salida.txt");
if (logFile == null) {
logFile = space.createFile("documento_salida.txt");
}
logFile.content ="";
//Comprobamos si el usuario existe
var authority = people.getPerson(usuario);
if (authority){
lista = people.getContainerGroups(people.getPerson(usuario));
var log = "";
log+="El usuario: " + usuario + " pertenece a los siguientes grupos.\n";
for(var i=0;i<lista.length;i++)
{
grupo = (lista[i]).properties.authorityName;
grupo = grupo.substring(6,grupo.length);
if (comprueba_grupo_usuario(grupo,usuario)){
log+="Grupo: " + grupo + " \n";
}
}
}
logFile.content += log;


- grupos_por_lista_usuarios.js:

En este caso, lo que le pasamos al script es un conjunto de usuarios de los cuales queremos obtener los grupos a los que están asignados.


//Variable a rellenar
var usuarios = new Array ('usuario1','usuario2','usuario3');

//Funcion que comprueba si un usuario dado existe como hijo de un grupo dado
function comprueba_grupo_usuario (grupo, usuario) {
scr_grupo = groups.getGroup(grupo);
var usuarios = scr_grupo.getChildUsers();
var encontrado = false;

var i = 0;
while ( i<usuarios.length && !encontrado) {
if ( usuarios[i].getFullName() == usuario ){
encontrado = true;
}
i++;
}
return encontrado;
}

var logFile = space.childByNamePath("documento_salida.txt");
if (logFile == null)
{
logFile = space.createFile("documento_salida.txt");
}
logFile.content ="";
var log = "";

for (var j=0;j<usuarios.length;j++)
{
var authority = people.getPerson(usuarios[j]);
if(authority)
{
lista = people.getContainerGroups(people.getPerson(usuarios[j]));

log+="El usuario: " + usuarios[j] + " pertenece a los siguientes grupos.\n";
for(var i=0;i<lista.length;i++)
{
grupo = (lista[i]).properties.authorityName;
grupo = grupo.substring(6,grupo.length);
if (comprueba_grupo_usuario(grupo,usuario)){
log+="Grupo: " + grupo + " \n";
}
}
}
}
logFile.content += log;

- copia_permisos_usuario.js:

El último script de esta tanda resulta bastante útil si tienes que asignar los mismos grupos de un usuario origen a otro usuario destino.


//Variables a completar
var usuario_origen="usuario1";
var usuario_destino="usuario2";
var exclusivo = true;

//Log
var logFile = space.childByNamePath("documento_salida.txt");
if (logFile == null)
{
logFile = space.createFile("documento_salida.txt");
}
logFile.content ="";
var log = "";

//Funcion que comprueba si un usuario dado existe como hijo de un grupo dado
function comprueba_grupo_usuario (grupo, usuario) {
scr_grupo = groups.getGroup(grupo);
var usuarios = scr_grupo.getChildUsers();
var encontrado = false;

var i = 0;
while ( i<usuarios.length && !encontrado) {
if ( usuarios[i].getFullName() == usuario ){
encontrado = true;
}
i++;
}
return encontrado;
}

//Obtenemos los grupos del usuario
function obtiene_permisos (usuario){
var grupos = [];
var authority = people.getPerson(usuario);
if (authority){
lista = people.getContainerGroups(people.getPerson(usuario));
log+="El usuario: " + usuario + " pertenece a los siguientes grupos.\n";
for(var i=0;i<lista.length;i++)
{
grupo = (lista[i]).properties.authorityName;
grupo = grupo.substring(6,grupo.length);
if (comprueba_grupo_usuario(grupo,usuario)){
log+="Grupo: " + grupo + " \n";
grupos.push(grupo);
}
}
}
return grupos;
}

var groupPrefix="GROUP_";

if (exclusivo){
var grupos_destino = obtiene_permisos(usuario_destino);
var authority_destino = people.getPerson(usuario_destino);
for (var i=0;i<grupos_destino.length;i++){
var srcGrpNode_destino=people.getGroup(groupPrefix+grupos_destino[i]);
people.removeAuthority(srcGrpNode_destino,authority_destino);
}
}
//Metemos al usuario destino en los mismos grupos que el usuario origen
var authority = people.getPerson(usuario_destino);
if(authority)
{
var grupos_origen = obtiene_permisos(usuario_origen);
for(var i=0;i<grupos_origen.length;i++)
{
var srcGrpNode=people.getGroup(groupPrefix+grupos_origen[i]);
if (srcGrpNode)
{
var listado = people.getMembers(srcGrpNode);
var array_usuarios = [];
for (var j=0;j<listado.length;j++)
{
array_usuarios[j]=(listado[j]).properties["{http://www.alfresco.org/model/content/1.0}userName"];
}
if (array_usuarios.indexOf(usuario_destino)== -1) //Si el usuario no existe en el grupo, lo insertamos
{
people.addAuthority(srcGrpNode,authority);
log+="- añadido usuario:" + usuario_destino + " al grupo " + grupos_origen[i] + " \n";
}
else
{
log+="- El usuario: " + usuario_destino + " ya esta en el grupo " + grupos_origen[i] + "\n";
}
}
else
{
log+="- El grupo: " + grupos_origen[i] + " no existe.\n";
}
}//final for
}
else
{
log+="- No existe usuario:" + usuario_destino + "\n";
}
logFile.content += log;

En este script, además de tener que pasarle el usuario origen y destino, le debemos indicar el valor a una variable "exclusivo", que determinará si la copia se hace sobre los grupos que ya disponga el usuario destino (false), o si por el contrario, se deben eliminar previamente (true).

miércoles, 13 de abril de 2011

Parsear un fichero de configuración

Con frecuencia necesitamos cambiar ciertas variables o campos de un fichero de configuración para adaptarlo a nuestro sistema. Cuando esto se convierte en una tarea repetitiva y sobre todo cuando son muchos los valores a cambiar, se hace interesante automatizar este proceso.

Una forma de hacerlo es a través de algún script, en mi caso lo he hecho en python.

En dicho script definimos las variables a buscar y los nuevos valores a tomar. Recorrerá el fichero buscando coincidencias con las variables y les pondrá los valores que hemos indicado (independientemente de si tienen o no ya un valor). Sería algo así:
#!/usr/bin/env python
# -*- coding: iso-8859-15 -*-
"""
USO:
sustituye.py fichero_origen > fichero_destino
Este script toma un argumento por la linea de comandos: el nombre del fichero a parsear.

El resultado lo podemos redirigir a un nuevo fichero o ver como quedaría por pantalla.
"""
from cStringIO import StringIO
import re, sys
#Conjunto de variables a parsear
var1 = re.compile(r'(variable_1=)(\s+)?(\S+)')
var2 = re.compile(r'(variable_2=)(\s+)?(\S+)')
#Nuevos valores que deben tomar las variables
nuevo_valor_var1 = 'nuevo valor'
nuevo_valor_var2 = 'nuevo valor 2'
def cambia_variables(fichero):
conf_file = StringIO(fichero)
for line in conf_file:
match = var1.search(line)
match2 = var2.search(line)
if match:
sub_line = var1.sub(r'\1%s' % nuevo_valor_var1, line)
line = sub_line
if match2:
sub_line = var2.sub(r'\1%s' % nuevo_valor_var2, line)
line = sub_line
yield line
if __name__ == '__main__':
if not len(sys.argv) > 1:
print __doc__
sys.exit(1)
infile_name = sys.argv[1]
try:
infile = open(infile_name, 'r')
except IOError:
print "Debe especificar un fichero valido a parsear."
print __doc__
sys.exit(1)
fichero = sys.argv[1]
cadena_fichero = open(fichero).read()
for line in cambia_variables(cadena_fichero):
print line,



Como argumento recibe el nombre del fichero a parsear, y mostrará por la salida estandar cómo quedaría el fichero. Se puede redirigir la salida a un nuevo fichero.

En el ejemplo (muy básico) busca las siguientes variables:

variable_1=
y
variable_2=

y les otorga los valores:

nuevo valor
y
nuevo valor2

respectivamente.

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...