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/