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.

miércoles, 6 de abril de 2011

Publicar el contenido de logs a través de tomcat

Se crea en $TOMCAT_HOME/conf/Catalina/localhost/ un xml para el nuevo contexto que se va a utilizar para acceder a los logs:

logs.xml:
<Context path="/logs" docBase="/ruta/de/logs" crossContext="false" debug="1" reloadable="true" >
</Context>


El docBase debe ser la ruta absoluta donde estén los logs que se quieran publicar.

Y en el direcotorio de los logs, creamos un direcotorio WEB-INF, y dentro un web.xml con el siguiente contenido:
<?xml version="1.0" encoding="ISO-8859-1"?>
<web-app xmlns="http://java.sun.com/xml/ns/j2ee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd" version="2.4">

<servlet>
<servlet-name>logs</servlet-name>
<servlet-class>org.apache.catalina.servlets.DefaultServlet</servlet-class>
<init-param>
<param-name>debug</param-name>
<param-value>0</param-value>
</init-param>
<init-param>
<param-name>listings</param-name>
<param-value>true</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>

<servlet-mapping>
<servlet-name>logs</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>

<security-constraint>
<web-resource-collection>
<web-resource-name>
Logs
</web-resource-name>
<url-pattern>/</url-pattern>
</web-resource-collection>
<auth-constraint>
<role-name>manager</role-name>
</auth-constraint>
</security-constraint>

<login-config>
<auth-method>BASIC</auth-method>
<realm-name>Logs</realm-name>
</login-config>
</web-app>



Se ha añadido autenticación básica con los usuarios pertencientes al rol manager.

Si no se quiere hacer esta configuración particular para el contexto logs, se puede hacer de forma genérica para todo el tomcat cambiando en el $TOMCAT_HOME/conf/web.xml la línea correpondiente al parámetro listings, en vez de false, pondríamos true:

   <servlet>
<servlet-name>default</servlet-name>
<servlet-class>org.apache.catalina.servlets.DefaultServlet</servlet-class>
<init-param>
<param-name>debug</param-name>
<param-value>0</param-value>
</init-param>
<init-param>
<param-name>listings</param-name>
<param-value>true</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>

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