mysqld --skip-grant-tables --user=root &
3. Entrar en la bd mysql: mysql mysql
4. UPDATE user SET Password=PASSWORD('clavenueva') WHERE user='root';
flush privileges;
exit;
5. Arrancar MySQL
mysqld --skip-grant-tables --user=root &
3. Entrar en la bd mysql: mysql mysql
4. UPDATE user SET Password=PASSWORD('clavenueva') WHERE user='root';
flush privileges;
exit;
5. Arrancar MySQL
En algunas empresas es necesario quitar las llamadas “desktop actions” o acciones de escritorio que se visualizan en los recursos compartidos cuando se activa el protocolo CIFS. Estas acciones son en algunas ocasiones muy útiles pero en otras, además de producir un mal conteo de ficheros en las carpetas, en muchas otras ocasiones lo único que pueden derivar es en la “contaminación” de las propias acciones por virus ya que son programas ejecutables.
Para eliminar/ocultar estas acciones se puede proceder como sigue:
Copiar el fichero:
${ALF_HOME}/tomcat/webapps/alfresco/WEB-INF/classes/alfresco/subsystems/fileServers/default/file-servers-context.xml
En:
${ALF_HOME}/tomcat/shared/classes/alfresco/extension/subsystems/fileServers/default/default
Y comentar las siguientes líneas:
[…]
<!–
__Alfresco.url
–>
[…]
<!–
alfresco/desktop/Alfresco.exe
CheckInOut
__CheckInOut.exe
JavaScriptURL
__ShowDetails.exe
alfresco/desktop/showDetails.js
anyFiles
copyToTarget
–>
<!–
Echo __AlfrescoEcho.exe
<property
name=”name”> URL
__AlfrescoURL.exe <bean
class=”org.alfresco.filesys.repo.desk.CmdLineDesktopAction”>
CmdLine __AlfrescoCmd.exe
JavaScript
__AlfrescoScript.exe
alfresco/desktop/dumpRequest.js
anyFiles, multiplePaths, allowNoParams
confirm, copyToTarget
–>
<!–
–>
[…]
${ALF_HOME} hace referencia al “path” o directorio donde está instalado Alfresco.
En el artículo sobre la compilación de la versión Community de Alfresco bajada desde del SVN oficial:
Hay un caso en el que hay que configurar algo más; cuando estemos en un sitio donde haya un proxy por medio, habrá que configurar el SVN para que pueda salir a través de dicho proxy.
Para configurarlo hay que descomentar las líneas de proxy necesarias así como la autenticación utilizada, en mi caso he usado solamente 3 de dichas líneas. El fichero de configuración se llama “servers” y se encuentra en el perfil del usuario o dentro del directorio Subclipse respectivo.
Por ejemplo, en una máquina Windows XP podríamos encontrarlo en:
En una máquina con Linux generalmente estará dentro del “home” del usuario, como:
Y las líneas principales para hacerlo funcionar:
Además, hay que tener en cuenta que es necesario bajarse un cliente de SVN en el caso de windows, como puede ser Slik o TortoiseSVN:
http://www.sliksvn.com/en/download/
http://tortoisesvn.net/downloads.html
Así mismo, subclipse utiliza JavaHL (JNI) por defecto, por tanto, si es una distribución Linux/Ubuntu tendrémos que cargar lal librerías correspondientes, como:
sudo apt-get install libsvn-java
Y poner la referencia (pe. -Djava.library.path=/usr/lib/jni) en eclipse.ini
Un ejemplo:
-showsplash
org.eclipse.platform
-framework
plugins/org.eclipse.osgi_3.4.0.v20080605-1900.jar
-vmargs
-Djava.library.path=/usr/lib/jni
-Dosgi.requiredJavaVersion=1.5
-Xms40m
-Xmx512m
-XX:MaxPermSize=256m
El escenario propuesto es el siguiente:
SAMBA: 3.0.33
Nombre de la máquina: alfpru
Primero hay que preparar el Active Directory para Kerberos, y sobre todo para que funcione la aplicación share de Alfresco.
Si se tiene alguna duda se puede consultar la siguiente dirección: http://wiki.alfresco.com/wiki/Alfresco_Authentication_Subsystems#Kerberos
Se crean en Active Directory dos usuarios:
Nombre: Alfresco HTTP
Usuario: alfrescohttp
Passwd: laquesea
Nombre: Alfresco CIFS
Usuario: alfrescocifs
Passwd: laquesea
En ambos, después de la contraseña, se desmarca la casilla de “El usuario debe cambiar la contraseña en el siguiente inicio de sesión”, y se marcan las casillas “La contraseña nunca caduca” y “No pedir la autenticación Kerberos previa”. Así mismo, si estuviera marcada, hay que desmarcar la casilla “Usar tipos de cifrado DES para esta cuenta”. Estas casillas se encuentran en las propiedades del usuario dentro de “Usuarios y equipos de Active Directory”, en la pestaña “Cuenta”.
Bien, ahora hay que usar un comando que está dentro del Kit de Recursos de Windows 2003 Server, dentro de “Utilidades de soporte”. Este comando se llama ktpass.exe y es el que genera las tablas de claves para poder identificar el servicio.
Aquí es donde me he encontrado problemas, las mayores dificultades para configurar Alfresco con AD-Kerberos está en la generación de estos ficheros, ya que existen varias versiones de la utilidad ktpass.exe. En mi caso tengo dos comandos ktpass.exe, uno del 24/03/2005 y otro del 17/02/2007. Finalmente he creado los ficheros con la última versión.
Los comandos son:
ktpass -princ cifs/alfpru.in2pruebas@IN2PRUEBAS -pass elquesea -mapuser IN2PRUEBASalfrescocifs -crypto RC4-HMAC-NT -ptype KRB5_NT_PRINCIPAL -out c:tempalfrescocifs.keytab
ktpass -princ HTTP/alfpru.in2pruebas@IN2PRUEBAS -pass elquesea -mapuser IN2PRUEBASalfrescohttp -crypto RC4-HMAC-NT -ptype KRB5_NT_PRINCIPAL -out c:tempalfrescohttp.keytab
Luego hay que crearlos como servicios dentro del Active Directory como sigue:
setspn -a cifs/alfpru alfrescocifs
setspn -a cifs/alfpru.in2pruebas alfrescocifs
setspn -a HTTP/alfpru alfrescohttp
setspn -a HTTP/alfpru.in2pruebas alfrescohttp
Y se copian los ficheros (alfrescocifs.keytab y alfrescohttp.keytab) creados en la máquina Linux en, por ejemplo, /etc/alfresco.
Seguidamente vamos a unir la máquina Linux al dominio de Windows 2003 (PDC) ya que si no, sería imposible establecer una “confianza” para realizar la autenticación para que los administradores de Windows tengan constancia de esta máquina, además este proceso también modifica el DNS de Windows 2003 Server para tener acceso vía TCP/IP aunque como bien me ha señalado iblanco no es necesario este paso para realizar simplemente la autenticación con Active Directory Kerberos.
Para ello se usa SAMBA, se instala:
…se configura el fichero /etc/samba/smb.conf como:
…se arranca:
…se utiliza el comando “net” para unir la máquina al dominio de la seguiente forma:
…y ya se puede parar el servicio de SAMBA:
service smb stop
(Nota: Hay que repasar el fichero /etc/hosts y que las IPs apunten a los host y dominio correspondiente)
Se configura el fichero /etc/krb5.conf como:
[logging]
default = FILE:/var/log/krb5libs.log
kdc = FILE:/var/log/krb5kdc.log
admin_server = FILE:/var/log/kadmind.log
[libdefaults]
default_realm = IN2PRUEBAS
default_tkt_enctypes = rc4-hmac
default_tgs_enctypes = rc4-hmac
dns_lookup_realm = false
dns_lookup_kdc = true
[realms]
IN2PRUEBAS = {
kdc = winsrv.in2pruebas:88
admin_server = winwrv.in2pruebas
}
[domain_realm]
.winsrv.in2pruebas = IN2PRUEBAS
winsrv.in2pruebas = IN2PRUEBAS
[appdefaults]
forward=true
forwardable=true
proxiable=true
Dentro de la máquina virtual (JVM de Sun), concretamente en la parte de la JRE y en una ruta parecida a la siguiente: /usr/java/jre/lib/security existen dos ficheros que hay que configurar. El primero es java.login.config y se configurará como sigue:
Alfresco {
com.sun.security.auth.module.Krb5LoginModule sufficient;
};
AlfrescoCIFS {
com.sun.security.auth.module.Krb5LoginModule required
storeKey=true
useKeyTab=true
keyTab=”/etc/alfresco/alfrescocifs.keytab”
principal=”cifs/alfpru.in2pruebas”;
};
AlfrescoHTTP {
com.sun.security.auth.module.Krb5LoginModule required
storeKey=true
useKeyTab=true
keyTab=”/etc/alfresco/alfrescohttp.keytab”
principal=”HTTP/alfpru.in2pruebas”;
};
ShareHTTP {
com.sun.security.auth.module.Krb5LoginModule required
storeKey=true
useKeyTab=true
keyTab=”/etc/alfresco/alfrescohttp.keytab”
principal=”HTTP/alfpru.in2pruebas”;
};
com.sun.net.ssl.client {
com.sun.security.auth.module.Krb5LoginModule sufficient;
};
other {
com.sun.security.auth.module.Krb5LoginModule sufficient;
};
Y el fichero java.security también hay que editarlo para indicarle donde está el fichero de configuración anterior, en la línea siguiente:
Como se observa, en el fichero java.login.config se establecen a su vez los directorios donde se encuentran los ficheros keytab.
Para la instalación de Alfresco se ha utilizado el fichero alfresco-enterprise-3.4.0.zip, se descomprime y se copian los directorios que hay dentro de web-server de forma recursiva dentro del servidor de aplicaciones que ya tengamos instalado.
Por ejemplo:
Se crea la base de datos:
Se realiza la configuración global o general de Alfresco en el fichero alfresco-global.properties:
Lo primero es comentar la línea “authentication.chain” y arrancar la instancia de Alfresco para comprobar su funcionamiento y su despliegue. Una vez desplegado ya podemos usar el subsistema “Authentication” para poder establecer la configuración de Kerberos.
Hay que copiar desde webapps/alfresco/WEB-INF/classes/alfresco/subsystems/Authentication/kerberos a shared/classes/alfresco/extension/subsystems/Authentication/kerberos/, quedando finalmente como: shared/classes/alfresco/extension/subsystems/Authentication/kerberos/kerberos y dentro habrá cuatro ficheros que son:
kerberos-authentication-context.xml
kerberos-authentication.properties
kerberos-filter-context.xml
kerberos-filter.properties
De estos, los ficheros con extensión “properties” son los que hay que configurar como sigue:
El fichero kerberos-authentication.properties:
El fichero kerberos-filter.properties:
kerberos.authentication.http.configEntryName=AlfrescoHTTP
kerberos.authentication.http.password=laquesea
kerberos.authentication.sso.enabled=true
kerberos.authentication.browser.ticketLogons=true
Ahora, para tener acceso a CIFS vía Kerberos hay que copiar también la rama webapps/alfresco/WEB-INF/classes/alfresco/subsystems/fileServers/default a shared/classes/alfresco/extension/subsystems/fileServers/default/default (igualmente debe haber dos niveles de directorio llamados default), y se modifica el fichero file-servers.properties como sigue:
filesystem.name=alfpru
filesystem.acl.global.defaultAccessLevel=
cifs.enabled=true
cifs.serverName=alfpru
cifs.domain=in2pruebas
cifs.broadcast=255.255.255.255
cifs.bindto=
cifs.ipv6.enabled=false
cifs.hostannounce=true
cifs.disableNIO=false
cifs.disableNativeCode=false
cifs.sessionTimeout=900
cifs.urlfile.prefix=http://alfpru
cifs.tcpipSMB.port=445
cifs.netBIOSSMB.sessionPort=139
cifs.netBIOSSMB.namePort=137
cifs.netBIOSSMB.datagramPort=138
cifs.WINS.autoDetectEnabled=false
cifs.WINS.primary=1.2.3.4
cifs.WINS.secondary=5.6.7.8
Además recomiendo desconectar tanto FTP como NFS dentro del mismo fichero como:
Ya solo queda la configuración de la parte “share”, esta se encuentra en: shared/classes/alfresco/extension/web-extension en el fichero share-config-custom.xml.sample, hay que renombrar este fichero como share-config-custom.xml y configurar la sección “KerberosDisabled”, eliminando la palabra Disabled y descomentando el bloque que viene a continuación con la condición “Remote”. Ambos bloques se configuran como sigue:
<!–
Password for HTTP service account.
The account name *must* be built from the HTTP server name, in the format :
HTTP/@
(NB this is because the web browser requests an ST for the
HTTP/ principal in the current realm, so if we’re to decode
that ST, it has to match.)
–>
Poli1970
<!–
Kerberos realm and KDC address.
–>
IN2PRUEBAS
<!–
Service Principal Name to use on the repository tier.
This must be like: HTTP/host.name@REALM
–>
HTTP/alfpru.in2pruebas@IN2PRUEBAS
<!–
JAAS login configuration entry name.
–>
ShareHTTP
<!–
Overriding endpoints to reference an Alfresco server with external SSO enabled
NOTE: If utilising a load balancer between web-tier and repository cluster, the “sticky
sessions” feature of your load balancer must be used.
NOTE: If alfresco server location is not localhost:8080 then also combine changes from the
“example port config” section below.
*Optional* keystore contains SSL client certificate + trusted CAs.
Used to authenticate share to an external SSO system such as CAS
Remove the keystore section if not required i.e. for NTLM.
NOTE: For Kerberos SSO rename the “KerberosDisabled” condition above to “Kerberos”
–>
alfresco/web-extension/alfresco-system.p12
pkcs12
alfresco-system
alfrescoCookie
Alfresco Connector
Connects to an Alfresco instance using cookie-based authentication
org.springframework.extensions.webscripts.connector.AlfrescoConnector
alfresco
Alfresco – user access
Access to Alfresco Repository WebScripts that require user authentication
alfrescoCookie
http://localhost:8080/alfresco/wcs
user
true
Una parte importante para poder realizar SSO Kerberos con Alfresco Share, es que hay que darle al usuario alfrescohttp la posibilidad de obtener la delegación de permisos por parte del otro servicio, en este caso, Alfresco (repositorio). Esto se obtiene dentro de Usuarios y equipos de Active Directory, en la rama Users y encima del usuario “Alfresco HTTP” pulsamos botón derecho y propiedades.
Aquí, en la pestaña “Delegación” hay que activar “Confiar en este usuario para la delegación a cualquier servicio (solo Kerberos)”.
Si esta pestaña no está visible habrá que “elevar el nivel funcional del dominio…”. Esto se consigue en la raíz del dominio (en nuestro caso in2pruebas de “Usuarios y equipos de Active Directory”, se pulsa botón derecho del ratón y se selecciona “Elevar el nivel funcional del dominio”). Se encuentra más información en: http://technet.microsoft.com/en-us/library/cc757194%28WS.10%29.aspx
Para poder depurar correctamente, recomiendo usar las siguientes líneas en los ficheros log4j.properties:
Al igual, también se puede activar la depuración de Kerberos a nivel de la JVM añadiendo los parámetros a la línea que ya se tenga de JAVA_OPTS como:
export JAVA_OPTS=”${JAVA_OPTS} -Dsun.security.krb5.debug=true -Dsun.security.jgss.debug=true”
Bien, ahora vamos a la parte cliente, el Windows XP que estemos usando, el Linux o el mismo Windows 2003 Server que puede servir para probar al final si todo funciona correctamente desde el navegador Internet Explorer o Firefox.
En el caso de Internet Explorer hay que indicarle en Herramientas->Opciones de Internet->Seguridad->Intranet Local la URL a la que vamos a acceder para que funcione el SSO. En este caso se ha incluido http://alfpru.in2pruebas que es el servidor donde está instalado Alfresco. Además en Herramientas->Opciones de Internet->Seguridad->Nivel Personalizado hay que comprobar que está seleccionada la opción “Inicio de sesión automático sólo en la zona de Intranet” en “Autenticación de Usuario”.
Si no tenémos infraestructura suficiente usando DNS para resolución de nombres, podemos usar el fichero hosts de C:WindowsSystem32driversetc e incluir la línea “IP host host.dominio”, por ejemplo:
192.168.1.12 alfpru alfpru.in2pruebas
Para el caso de Firefox, hay que poner en este (en el campo URL) about:config y confirmar que deseamos entrar en la configuración. Buscamos las siguientes opciones y le damos los valores aquí señalados o los que correspondan según la configuración de dominio del Active Directory:
network.negotiate-auth.delegation-uris = http://alfpru.in2pruebas:8080/share
network.negotiate-auth.trusted-uris = http://alfpru.in2pruebas:8080/alfresco
network.negotiate-auth.using-native-gsslib = false
(Nota: Actualmente en la versión 3.4.0, el SSO en Alfresco no funciona con Firefox en Linux; tampoco Alfresco Share con máquinas JVM de IBM).
Ya solo queda realizar los ajustes que se necesiten, poner los nombres correctos según la configuración de cada uno y probar su funcionamiento.
Más información de como configurar este escenario en:
http://wiki.alfresco.com/wiki/Alfresco_Authentication_Subsystems#Kerberos
http://www.bdat.com/documentos/samba/html/domain-member.html
http://technet.microsoft.com/en-us/library/cc757194%28WS.10%29.aspx
En algunas ocasiones, como migraciones, reindexaciones completas, etc. pueden salir determinados avisos como el siguiente:
… WARN [org.alfresco.repo.cache.TransactionalCache.org.alfresco.storeAndNodeIdTransactionalCache] Transactional update cache ‘org.alfresco.storeAndNodeIdTransactionalCache’ is full (10000).
Este tipo de avisos se refiere a que se ha llenado la memoria de intercambio o caché de segundo nivel (también llamada L2 Cache).
** SOLUCIÓN **
La solución pasa por agrandar el tamaño de esta tocando los parámetros del fichero cache-context.xml
Unos valores más acorde con situaciones de instalaciones en producción podrían ser los siguientes:
[…]
org.alfresco.userToAuthorityTransactionalCache
10000
[…]
org.alfresco.personTransactionalCache
25000
[…]
org.alfresco.storeAndNodeIdTransactionalCache
100000
[…]
Cada uno de estos valores hay que adaptarlo al número de elementos que tengamos, como son asignaciones de autorizaciones (roles en espacios de trabajo), usuarios y ficheros o documentos.
** CONSIDERACIONES **
Esto juega negativamente sobre el recolector de basura (GC) de la máquina Java (JVM) ya que tardará más en intentar recoger los objetos obsoletos.
Para esto podemos usar dos soluciones alternativas y parciales pero que impactarán sobre nuestra instalación, una es desactivar directamente la caché.
Para desconectar la caché de segundo nivel (L2 cache) podemos poner el siguiente valor en alfresco-global.properties:
hibernate.cache.use_second_level_cache=false
La otra forma de intentar resolver el tiempo de ralentización será hacer que se guarden los valores de la cache de forma más continuada. Para ello podemos reajustar los valores de los beans sessionSizeResourceInterceptor y sessionSizeResourceManager en el fichero hibernate-context.xml como sigue:
[…]
10000
100
100
100
0
[…]
Esta última opción solo es recomendable para usarla durante una actualización, una reindexación completa, y cualquier operación que conlleve mucha carga de memoria de intercambio o cache. Una vez finalizada la operación, deberían restaurarse los valores originales.
No hay que olvidarse de hacer copia de estos ficheros para poder restaurarlos posteriormente a los valores originales.
Es recomendable además que se copien los ficheros ehcache-context.xml y hibernate-context.xml del directorio de despliegue al de configuración (extension) como custom-ehcache-context.xml y custom-hibernate-context.xml. De esta forma se pueden dejar los ficheros originales.
Más información y otras fuentes:
http://wiki.alfresco.com/wiki/Repository_Cache_Configuration
http://issues.alfresco.com/jira/browse/ETHREEOH-3294
La siguiente web es muy recomendable, tiene una serie de artículos sobre migraciones en los que se trata este tema.
http://alfrescoshare.wordpress.com/category/alfresco-dm/
Revisiones:
17/08/2011: En el caso de cluster, al usar ehcache-custom.xml en /extension, hay que modificar los valores ahí, no hace falta copiar el fichero ehcache.xml
—
Swithun Crowe ha realizado una “custom action” para poder escanear un documento a petición. Es otra idea más y esta es totalmente “bajo demanda” ya que es mediante una acción. Como es otra posibilidad se podría adaptar perfectamente a “Alfresco Virus Alert” y tenerla como otra posibilidad más dentro del marco de seguridad y protección de antivirus para Alfresco.
La entrada en la wiki es: http://wiki.alfresco.com/wiki/Antivirus
Interface
|
Method
|
org.alfresco.repo.content.ContentServicePolicies
|
onContentUpdate
|
onContentRead
|
Primero definimos los beans que usamos en el “behavior”: alfviral-behavior-context.xml
true
property>
classpath:alfresco/extension/alfviral-behavior.properties
<bean id="AlfViralBehavior" class="com.fegor.alfresco.behavior.OnUpdateReadScan"
init-method=”init”>
${alfviral.command}
${dir.contentstore}
bean>
Seguidamente del fichero de propiedades: alfviral-behavior.properties
alfviral.command=/usr/bin/clamscan
Montamos el modelo de datos: alfviral-model-context.xml
alfresco/extension/alfviralModel.xml
El modelo: alfviralModel.xml
Alfresco Virus Alarm Model
Fernando González Ruano (twitter://fegorara)
1.0
Infected
d:date
false
d:boolean
false
La parte para el cliente web del browser: web-client-config-custom.xml
El fichero de propiedades para las etiquetas: webclient.properties
ava_date=Fecha de detecciu00F3n
ava_clean=u00BFDesinfectado?
Y por último la clase java: OnUpdateReadScan.java
package com.fegor.alfresco.behavior;
import java.io.IOException;
import java.io.Serializable;
import java.util.*;
import org.alfresco.service.cmr.repository.ContentService;
import org.alfresco.service.cmr.repository.NodeService;
import org.alfresco.repo.content.ContentServicePolicies;
import org.alfresco.repo.policy.Behaviour;
import org.alfresco.repo.policy.Behaviour.NotificationFrequency;
import org.alfresco.repo.policy.JavaBehaviour;
import org.alfresco.repo.policy.PolicyComponent;
import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.namespace.NamespaceService;
import org.alfresco.service.namespace.QName;
import org.apache.log4j.Logger;
import org.alfresco.model.ContentModel;
import org.alfresco.service.cmr.repository.ContentReader;
/**
* Integrates antivirus scanning documents for alfresco
*
* Implements the policies of “OnContentUpdate” and “OnContentRead”.
*
* @author Fernando González Ruano (fegor)
*/
public class OnUpdateReadScan
implements ContentServicePolicies.OnContentUpdatePolicy,
ContentServicePolicies.OnContentReadPolicy
{
private Logger logger = Logger.getLogger(OnUpdateReadScan.class);
// behaviours
private Behaviour onContentUpdate;
private Behaviour onContentRead;
// dependencias
private PolicyComponent policyComponent;
private ContentService contentService;
private NodeService nodeService;
// configuration
private List command;
private String store;
private final String NAMESPACE_ALFVIRAL_CONTENT_MODEL = “alfviral.model”;
private final QName ASPECT_INFECTED = QName.createQName(NAMESPACE_ALFVIRAL_CONTENT_MODEL, “infected”);
private final QName PROP_INFECTED_DATE = QName.createQName(NAMESPACE_ALFVIRAL_CONTENT_MODEL, “date”);
private final QName PROP_INFECTED_CLEAN = QName.createQName(NAMESPACE_ALFVIRAL_CONTENT_MODEL, “clean”);
Map aspectValues = new HashMap();
// método de inicio
public void init ()
{
if (logger.isDebugEnabled()) logger.debug(“Start OnUpdateReadScan.”);
// crear behaviours
this.onContentUpdate = new JavaBehaviour(this,
“onContentUpdate”,
NotificationFrequency.TRANSACTION_COMMIT);
this.onContentRead = new JavaBehaviour(this,
“onContentRead”,
NotificationFrequency.TRANSACTION_COMMIT);
// binding “policies”
this.policyComponent.bindClassBehaviour(QName.createQName
(NamespaceService.ALFRESCO_URI,
“onContentUpdate”),
“cm:content”, this.onContentUpdate);
this.policyComponent.bindClassBehaviour(QName.createQName
(NamespaceService.ALFRESCO_URI,
“onContentRead”),
“cm:content”, this.onContentRead);
}
@Override
public void onContentUpdate (NodeRef nodeRef, boolean flag)
{
ContentReader contentReader = this.contentService.getReader(nodeRef, ContentModel.PROP_CONTENT);
// full path of file
String contentUrl = contentReader.getContentUrl();
String contentPath = contentUrl.replaceFirst(“store:/”, this.store);
if (logger.isDebugEnabled())
{
logger.debug(“(Update) “+this.command+” “+contentPath);
}
else if (logger.isInfoEnabled())
{
logger.info(“(Update) Llamando al script de escaneo de virus para “+nodeRef.getId());
}
try
{
// execute command “antivir contentPath”
this.command.add(contentPath);
ProcessBuilder pb = new ProcessBuilder(this.command);
Process process = pb.start();
int intResult = process.waitFor();
logger.debug(“(Update) Resultado del escaneo: “+intResult);
// if result is not 0, file is infected
if (intResult != 0)
{
logger.info(“ALERTA ** El fichero: “+contentReader.getContentUrl()+” está infectado. **”);
// add aspect Infected is not assigned
if (!nodeService.hasAspect(nodeRef, this.ASPECT_INFECTED))
{
this.aspectValues.put(this.PROP_INFECTED_DATE, new Date());
this.aspectValues.put(this.PROP_INFECTED_CLEAN, false);
nodeService.addAspect(nodeRef, this.ASPECT_INFECTED, this.aspectValues);
// TODO Other actions… quarantine, delete, send email, etc.
}
else
{
logger.debug(“Este fichero se detectó como infectado anteriormente.”);
}
}
}
catch (IOException e)
{
e.printStackTrace();
}
catch (InterruptedException e)
{
e.printStackTrace();
}
}
@Override
public void onContentRead (NodeRef nodeRef)
{
// TODO Actions for read content
}
// Setters…
public void setPolicyComponent(PolicyComponent policyComponent)
{
this.policyComponent = policyComponent;
}
public void setContentService(ContentService contentService)
{
this.contentService = contentService;
}
public void setNodeService(NodeService nodeService)
{
this.nodeService = nodeService;
}
public void setStore(String store)
{
this.store = store;
}
public void setCommand(List command)
{
this.command = command;
}
}
A partir de aquí…
Esto es solo un ejemplo de la multitud de acciones y configuraciones que pueden realizarse en este sentido, por ejemplo, falta el código para el evento OnContentRead, falta alguna acción de mover los documentos infectados a algún espacio de cuarentena, avisar al administrador y al usuario de la detección, internacionalizar, etc. pero creo que es un buen punto de partida para que cada cual adapte esta solución a su manera. No os lo voy a dar todo hecho ¿verdad?… 😉
Finalmente dos capturas de pantalla:
Un extracto del log (poniendo en el log4j.properties el valor log4j.logger.com.fegor=debug):
10:44:16,141 User:admin DEBUG [alfresco.behavior.OnUpdateReadScan] (Update) [/usr/local/bin/clamscan, /home/alfresco/enterprise/alf_data/contentstore/2010/12/30/8/3/30a7961f-cdef-4410-9ba0-ca94a8542d03.bin, /home/alfresco/enterprise/alf_data/contentstore/2010/12/30/10/42/4a6a4884-c14e-4b24-ae22-c1e2a9839593.bin, /home/alfresco/enterprise/alf_data/contentstore/2010/12/30/10/42/4a6a4884-c14e-4b24-ae22-c1e2a9839593.bin] /home/alfresco/enterprise/alf_data/contentstore/2010/12/30/10/44/b9b5c69c-cff5-400e-9f63-4888ca745749.bin
10:44:20,125 User:admin DEBUG [alfresco.behavior.OnUpdateReadScan] (Update) Resultado del escaneo: 1
10:44:20,126 User:admin INFO [alfresco.behavior.OnUpdateReadScan] ALERTA ** El fichero: store://2010/12/30/10/44/b9b5c69c-cff5-400e-9f63-4888ca745749.bin está infectado. **
Y algo de bibliografía que podéis consultar:
Libro: Alfresco Developer Guide
Autor: Jeff Potts
ISBN: 978-1-847193-11-7
Web de Jeff Potts: http://ecmarchitect.com/
Wiki de Alfresco: http://wiki.alfresco.com/wiki/Policy_Component
Web de ClamAV: http://www.clamav.net/lang/en/
SELECT alf_node.uuid
FROM alf_node_properties
INNER JOIN alf_node
ON alf_node.id = alf_node_properties.node_id
INNER JOIN alf_qname
ON alf_qname.id = alf_node_properties.qname_id
WHERE alf_node_properties.node_id =
(SELECT alf_node_properties.node_id
FROM alf_content_url
INNER JOIN alf_content_data
ON alf_content_url.id = alf_content_data.content_url_id
INNER JOIN alf_node_properties
ON alf_content_data.id = alf_node_properties.long_value
INNER JOIN alf_qname
ON alf_qname.id = alf_node_properties.qname_id
WHERE alf_content_url.content_url = ‘${FUID}’
AND alf_qname.local_name = ‘content’)
AND alf_qname.local_name = ‘name’;
# Variables de configuración
#
PROG=$0
PROGDIR=`dirname “$PROG”`
SCANRES_FILE=scanres.txt
NODEREFS_FILE=noderefs.txt
DOCNAMES_FILE=docnames.txt
# Crea lista de ficheros infectados
#
echo “Creando lista de ficheros infectados…”
rm -f ${PROGDIR}/${SCANRES_FILE} 2>/dev/null
CONTENTSTORE=${DIR_ROOT}/contentstore
clamscan -i -r ${CONTENTSTORE} | awk -F: ‘$1~/.bin/{print “store:/”$1}’ | sed s:${CONTENTSTORE}::g >${PROGDIR}/${SCANRES_FILE}
if [ ! -s ${PROGDIR}/${SCANRES_FILE} ]
then
echo “No hay ficheros infectados.”
exit 0
fi
# Crea lista de NodeRefs de los ficheros
#
echo “Creando referencias NodeRefs de los FUID…”
rm -f ${PROGDIR}/${NODEREFS_FILE} 2>/dev/null
for FUID in $(cat ${PROGDIR}/${SCANRES_FILE})
do
mysql -u${USERNAME} -p${PASSWD} -D${DATABASE} -h${HOST} -P${PORT} –skip-column-names –raw –silent >>${PROGDIR}/${NODEREFS_FILE} <
SELECT alf_node.uuid
FROM alf_node_properties
INNER JOIN alf_node
ON alf_node.id = alf_node_properties.node_id
INNER JOIN alf_qname
ON alf_qname.id = alf_node_properties.qname_id
WHERE alf_node_properties.node_id =
(SELECT alf_node_properties.node_id
FROM alf_content_url
INNER JOIN alf_content_data
ON alf_content_url.id = alf_content_data.content_url_id
INNER JOIN alf_node_properties
ON alf_content_data.id = alf_node_properties.long_value
INNER JOIN alf_qname
ON alf_qname.id = alf_node_properties.qname_id
WHERE alf_content_url.content_url = ‘${FUID}’
AND alf_qname.local_name = ‘content’)
AND alf_qname.local_name = ‘name’;
q
STOP
done
if [ ! -s ${PROGDIR}/${NODEREFS_FILE} ]
then
echo “¡No se han encontrado referencias a los ficheros!”
exit 1
fi
# Lanza las llamadas a Alfresco hacia el webscript
#
echo “Llamando a Alfresco…”
rm -f ${PROGDIR}/${DOCNAMES_FILE} 2>/dev/null
ALF_TICKET=`curl “http://localhost:8080/alfresco/service/api/login?u=${ALFUSER}&pw=${ALFPASSWD}” | grep TICKET_ | sed ‘s:::g’ | sed ‘s:::g’`
for NODEREF in $(cat ${PROGDIR}/${NODEREFS_FILE})
do
curl “${ALFRESCO_URL}/service/protect/alfviral?nref=${NODEREF}&alf_ticket=${ALF_TICKET}” >>${PROGDIR}/${DOCNAMES_FILE}
echo “” >>${PROGDIR}/${DOCNAMES_FILE}
done
// renombrar el documento
var name_infected = “”;
name_infected = nodes[0].name;
if (name_infected.indexOf(“_INFECTADO”) == -1)
{
nodes[0].name = name_infected + “_INFECTADO”;
nodes[0].save();
if (logger.isLoggingEnabled())
logger.log(“El documento: ” + nodes[0].name + ” ha sido renombrado por estar infectado.”);
}
model.name_infected = nodes[0].name;
}
${status.message}
body>
html>
¡Ah!, y FELIZ NAVIDAD A TODOS
Hoy he visto la noticia de la liberación de alfresco Community en su versión 3.4.a (lo de la letra “a” es debido a la nueva nomenclatura de que adopta Alfresco para su versión Community).
¿Donde he visto la noticia?, en los foros de Alfresco evidentemente y en el blog de Toni de la Fuente (blyx.com). Para saber más sobre esta nueva versión os remito a su blog: “Liberada Alfresco Community versión 3.4.a”
Una de las cosas que más me ha gustado ha sido la inclusión de iBatis y la eliminación de Hibernate, evidentemente solo para la parte del repositorio ya que jBPM usa también como capa de persistencia esta última y no puede eliminarse (todavía).
iBatis es un marco de trabajo para usar persistencia ayudado por SGBDs (Sistemas Gestores de Bases de Datos) al igual que Hibernate.
iBatis está dentro del proyecto Apache y lo que más destaca es su facilidad para “mapear” clases de Java y sus respectivos comandos en SQL, o sea, mapeo de campos y paso de parámetros principalmente. Personalmente creo que es un acierto que Alfresco incluya a iBatis en su sistema (al igual que otros productos que iré comentando en otras publicaciones).
Además cuenta con una herramienta llamada ibator y que no es más que un generador de código para ayudar al programador a obtener:
Esta herramienta contiene también un plugin para Eclipse.
Si queréis saber más sobre el proyecto iBatis podéis ir a su web oficial: http://ibatis.apache.org/
Leyendo un artículo de Fernando Moreno-Torres en su blog “Cómo clasificar documentos” sobre el problema que existe a la hora de clasificar documentos en una organización me gustaría comentar algunas cosas y de paso completar su artículo.
Tengo que decir que Fernando da una visión perfecta de la doble posibilidad de clasificación que puede darse en muchas organizaciones, de hecho no es ninguna mejor ni peor, cada cual elegirá la que más le guste.
Lo que sí puede ser útil para la clasificación puede ser la inclusión de, no solo la parte estructural de organización u orden en al que se representa la información, si no, lo que los gestores documentales utilizan muy a menudo y que les define, entre otras capacidades:
1. Los metadatos
2. Las categorías
3. Las etiquetas
1. Por una lado, la asignación de metadatos, en Alfresco a través de la extensión del modelo de datos (tipos y/o aspectos) es una manera fantástica para mantener una organización documental así como la mejor manera de realizar búsquedas directas de forma rápida. Podemos luego ordenar por los valores de esos metadatos como la edad, fecha de creación, etc. Tambén podríamos navegar por valores de algunos metadatos, lo que nos daría otra visión o estructura del almacén, si bien es algo complicado, quedando por tanto las búsquedas como mejor opción.
2. Las categorías son muy parecidas a estos metadatos solo que digamos que son valores genéricos y no sobre campos específicos. Estas categorías de hecho pueden incluirse en un metadato de multivalor como es el caso de Alfresco o de cualquier otra forma en otros gestores documentales. Estas están más indicadas para categorizar la información en base a información estructurada. También es posible navegar entre las categorías de una forma más sencilla que a través de valores de metadatos.
3. Por último, las etiquetas son una mezcla de valor de metadato y categoría. Si bien, las categorías generalmente están definidas en base a topologías, estructuras, etc. las etiquetas sin embargo se van creando directamente y de forma libre. Son muy famosas las etiquetas usadas en Flickr (http://www.flickr.com) para definir “propiedades” a las fotos. También es posible la navegación a través de estas etiquetas y por tanto su catalogación, si bien sigue siendo la búsqueda el mejor ambiente para encontrar los documentos.
Así pues, como vemos, existen muchas formas de estructurar los documentos de forma lógica a la que podremos llegar de una forma u otra. Dependerá de la imaginación y conocimientos de la persona encargada de guardar la información así como de las posibilidades de estructurar, asignar y navegar del producto encargado de guardar la información.