mirror of
https://github.com/Alfresco/alfresco-community-repo.git
synced 2025-08-07 17:49:17 +00:00
Merged HEAD-BUG-FIX (4.3/Cloud) to HEAD (4.3/Cloud)
67735: Merged V4.2-BUG-FIX (4.2.3) to HEAD-BUG-FIX (4.3/Cloud) 65767: Merged DEV to V4.2-BUG-FIX 65559 : MNT-10807 : Auditing does not take into account audit.filter.alfresco-access.transaction.user Added UserAuditFilter class, inject an instance into AuditComponentImpl. Added unit test. 65671 : MNT-10807 : Auditing does not take into account audit.filter.alfresco-access.transaction.user Fixed some code problem. Reverted test from AuditComponentTest and created new UserAuditFilterTest. 65754 : MNT-10807 : Auditing does not take into account audit.filter.alfresco-access.transaction.user Included 'UserAuditFilterTest' test in a test suite. git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/alfresco/HEAD/root@68374 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261
This commit is contained in:
@@ -30,6 +30,7 @@
|
|||||||
<property name="auditDAO" ref="auditDAO"/>
|
<property name="auditDAO" ref="auditDAO"/>
|
||||||
<property name="auditModelRegistry" ref="Audit"/>
|
<property name="auditModelRegistry" ref="Audit"/>
|
||||||
<property name="propertyValueDAO" ref="propertyValueDAO"/>
|
<property name="propertyValueDAO" ref="propertyValueDAO"/>
|
||||||
|
<property name="userAuditFilter" ref="userAuditFilter"/>
|
||||||
<property name="auditFilter">
|
<property name="auditFilter">
|
||||||
<bean class="org.alfresco.repo.audit.PropertyAuditFilter">
|
<bean class="org.alfresco.repo.audit.PropertyAuditFilter">
|
||||||
<property name="properties" ref="global-properties" />
|
<property name="properties" ref="global-properties" />
|
||||||
@@ -37,6 +38,14 @@
|
|||||||
</property>
|
</property>
|
||||||
</bean>
|
</bean>
|
||||||
|
|
||||||
|
<!-- User Audit Filter -->
|
||||||
|
|
||||||
|
<bean id="userAuditFilter" class="org.alfresco.repo.audit.UserAuditFilter">
|
||||||
|
<property name="userFilterPattern">
|
||||||
|
<value>${audit.filter.alfresco-access.transaction.user}</value>
|
||||||
|
</property>
|
||||||
|
</bean>
|
||||||
|
|
||||||
<!-- Access Auditor -->
|
<!-- Access Auditor -->
|
||||||
|
|
||||||
<bean id="accessAuditor" class="org.alfresco.repo.audit.access.AccessAuditor">
|
<bean id="accessAuditor" class="org.alfresco.repo.audit.access.AccessAuditor">
|
||||||
|
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (C) 2005-2010 Alfresco Software Limited.
|
* Copyright (C) 2005-2014 Alfresco Software Limited.
|
||||||
*
|
*
|
||||||
* This file is part of Alfresco
|
* This file is part of Alfresco
|
||||||
*
|
*
|
||||||
@@ -53,6 +53,13 @@ public interface AuditComponent
|
|||||||
*/
|
*/
|
||||||
public void setAuditEnabled(boolean enable);
|
public void setAuditEnabled(boolean enable);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param userAuditFilter
|
||||||
|
*
|
||||||
|
* @since 4.2
|
||||||
|
*/
|
||||||
|
public void setUserAuditFilter(UserAuditFilter userAuditFilter);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get all registered audit applications, whether active or not.
|
* Get all registered audit applications, whether active or not.
|
||||||
*
|
*
|
||||||
|
@@ -75,6 +75,7 @@ public class AuditComponentImpl implements AuditComponent
|
|||||||
private AuditDAO auditDAO;
|
private AuditDAO auditDAO;
|
||||||
private TransactionService transactionService;
|
private TransactionService transactionService;
|
||||||
private AuditFilter auditFilter;
|
private AuditFilter auditFilter;
|
||||||
|
private UserAuditFilter userAuditFilter;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Default constructor
|
* Default constructor
|
||||||
@@ -126,6 +127,11 @@ public class AuditComponentImpl implements AuditComponent
|
|||||||
this.auditFilter = auditFilter;
|
this.auditFilter = auditFilter;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void setUserAuditFilter(UserAuditFilter userAuditFilter)
|
||||||
|
{
|
||||||
|
this.userAuditFilter = userAuditFilter;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* {@inheritDoc}
|
* {@inheritDoc}
|
||||||
* @since 3.2
|
* @since 3.2
|
||||||
@@ -499,7 +505,8 @@ public class AuditComponentImpl implements AuditComponent
|
|||||||
ParameterCheck.mandatory("rootPath", rootPath);
|
ParameterCheck.mandatory("rootPath", rootPath);
|
||||||
AuditApplication.checkPathFormat(rootPath);
|
AuditApplication.checkPathFormat(rootPath);
|
||||||
|
|
||||||
if (values == null || values.isEmpty() || !areAuditValuesRequired() || !auditFilter.accept(rootPath, values))
|
String username = AuthenticationUtil.getFullyAuthenticatedUser();
|
||||||
|
if (values == null || values.isEmpty() || !areAuditValuesRequired() || !userAuditFilter.acceptUser(username) || !auditFilter.accept(rootPath, values))
|
||||||
{
|
{
|
||||||
return Collections.emptyMap();
|
return Collections.emptyMap();
|
||||||
}
|
}
|
||||||
|
109
source/java/org/alfresco/repo/audit/UserAuditFilter.java
Normal file
109
source/java/org/alfresco/repo/audit/UserAuditFilter.java
Normal file
@@ -0,0 +1,109 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2005-2014 Alfresco Software Limited.
|
||||||
|
*
|
||||||
|
* This file is part of Alfresco
|
||||||
|
*
|
||||||
|
* Alfresco is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU Lesser General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* Alfresco is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public License
|
||||||
|
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
package org.alfresco.repo.audit;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.regex.Pattern;
|
||||||
|
import java.util.regex.PatternSyntaxException;
|
||||||
|
|
||||||
|
import org.alfresco.error.AlfrescoRuntimeException;
|
||||||
|
import org.alfresco.util.Pair;
|
||||||
|
import org.alfresco.util.PropertyCheck;
|
||||||
|
import org.springframework.beans.factory.InitializingBean;
|
||||||
|
|
||||||
|
public class UserAuditFilter implements InitializingBean
|
||||||
|
{
|
||||||
|
private static final char NOT = '~';
|
||||||
|
private static final String REG_EXP_SEPARATOR = ";";
|
||||||
|
private static final char ESCAPE = '\\';
|
||||||
|
private static final String ESCAPED_NOT = ""+ESCAPE+NOT;
|
||||||
|
|
||||||
|
private String userFilterPattern;
|
||||||
|
private List<Pair<Boolean, Pattern>> listOfPairValue = new ArrayList<Pair<Boolean, Pattern>>();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Default constructor
|
||||||
|
*/
|
||||||
|
public UserAuditFilter()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Set user audit pattern. For example "audit.filter.alfresco-access.transaction.user=~user1;user2;.*"
|
||||||
|
*
|
||||||
|
* @param userFilterPattern 'userFilterPattern' is String type. The value of 'userFilterPattern' couldn't empty
|
||||||
|
* or have 0 length value. An expression that starts with a '~' indicates that any
|
||||||
|
* matching value should be rejected. Each regular expression in the list is separated
|
||||||
|
* by a semicolon (';').
|
||||||
|
*/
|
||||||
|
public void setUserFilterPattern(String userFilterPattern)
|
||||||
|
{
|
||||||
|
this.userFilterPattern = userFilterPattern;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void afterPropertiesSet()
|
||||||
|
{
|
||||||
|
parseProperties();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void parseProperties()
|
||||||
|
{
|
||||||
|
String userPropertyValue = userFilterPattern;
|
||||||
|
if (!PropertyCheck.isValidPropertyString(userPropertyValue))
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
String[] arrValues = userPropertyValue.split(REG_EXP_SEPARATOR);
|
||||||
|
for (String prop : arrValues)
|
||||||
|
{
|
||||||
|
boolean includeExp = prop.charAt(0) != NOT;
|
||||||
|
|
||||||
|
if (!includeExp || prop.startsWith(ESCAPED_NOT))
|
||||||
|
{
|
||||||
|
prop = prop.substring(1);
|
||||||
|
}
|
||||||
|
try
|
||||||
|
{
|
||||||
|
listOfPairValue.add(new Pair<Boolean, Pattern>(includeExp, Pattern.compile(prop)));
|
||||||
|
}
|
||||||
|
catch (PatternSyntaxException ex)
|
||||||
|
{
|
||||||
|
throw new AlfrescoRuntimeException("The 'audit.filter.alfresco-access.transaction.user' property parse exception; see property 'audit.filter.alfresco-access.transaction.user'.", ex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean acceptUser(String value)
|
||||||
|
{
|
||||||
|
if (value == null)
|
||||||
|
{
|
||||||
|
value = "null";
|
||||||
|
}
|
||||||
|
for (Pair<Boolean, Pattern> val : listOfPairValue)
|
||||||
|
{
|
||||||
|
if (val.getSecond().matcher(value).matches())
|
||||||
|
{
|
||||||
|
return val.getFirst();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
@@ -932,8 +932,6 @@ public class AuditComponentTest extends TestCase
|
|||||||
AuthenticationUtil.runAs(testRunAs, "SomeOtherUser");
|
AuthenticationUtil.runAs(testRunAs, "SomeOtherUser");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Clearn the audit log as 'admin'
|
* Clearn the audit log as 'admin'
|
||||||
*/
|
*/
|
||||||
|
@@ -40,6 +40,7 @@ public class AuditTestSuite extends TestSuite
|
|||||||
suite.addTestSuite(AuditableAspectTest.class);
|
suite.addTestSuite(AuditableAspectTest.class);
|
||||||
suite.addTestSuite(AuditBootstrapTest.class);
|
suite.addTestSuite(AuditBootstrapTest.class);
|
||||||
suite.addTestSuite(AuditComponentTest.class);
|
suite.addTestSuite(AuditComponentTest.class);
|
||||||
|
suite.addTestSuite(UserAuditFilterTest.class);
|
||||||
|
|
||||||
suite.addTest(new JUnit4TestAdapter(PropertyAuditFilterTest.class));
|
suite.addTest(new JUnit4TestAdapter(PropertyAuditFilterTest.class));
|
||||||
suite.addTest(new JUnit4TestAdapter(AccessAuditorTest.class));
|
suite.addTest(new JUnit4TestAdapter(AccessAuditorTest.class));
|
||||||
|
@@ -0,0 +1,136 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2005-2014 Alfresco Software Limited.
|
||||||
|
*
|
||||||
|
* This file is part of Alfresco
|
||||||
|
*
|
||||||
|
* Alfresco is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU Lesser General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* Alfresco is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public License
|
||||||
|
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
package org.alfresco.repo.audit;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
import java.net.URL;
|
||||||
|
import java.util.Date;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
import junit.framework.TestCase;
|
||||||
|
|
||||||
|
import org.alfresco.error.AlfrescoRuntimeException;
|
||||||
|
import org.alfresco.repo.audit.model.AuditModelRegistryImpl;
|
||||||
|
import org.alfresco.repo.security.authentication.AuthenticationUtil;
|
||||||
|
import org.alfresco.repo.security.authentication.AuthenticationUtil.RunAsWork;
|
||||||
|
import org.alfresco.repo.transaction.RetryingTransactionHelper.RetryingTransactionCallback;
|
||||||
|
import org.alfresco.service.ServiceRegistry;
|
||||||
|
import org.alfresco.service.transaction.TransactionService;
|
||||||
|
import org.alfresco.util.ApplicationContextHelper;
|
||||||
|
import org.springframework.context.ApplicationContext;
|
||||||
|
import org.springframework.util.ResourceUtils;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tests user filter.
|
||||||
|
*
|
||||||
|
* @see UserAuditFilter
|
||||||
|
*
|
||||||
|
* @author Vasily Olhin
|
||||||
|
* @since 4.2
|
||||||
|
*/
|
||||||
|
public class UserAuditFilterTest extends TestCase
|
||||||
|
{
|
||||||
|
private static ApplicationContext ctx = ApplicationContextHelper.getApplicationContext();
|
||||||
|
|
||||||
|
private AuditModelRegistryImpl auditModelRegistry;
|
||||||
|
private AuditComponent auditComponent;
|
||||||
|
private ServiceRegistry serviceRegistry;
|
||||||
|
private TransactionService transactionService;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setUp() throws Exception
|
||||||
|
{
|
||||||
|
auditModelRegistry = (AuditModelRegistryImpl) ctx.getBean("auditModel.modelRegistry");
|
||||||
|
auditComponent = (AuditComponent) ctx.getBean("auditComponent");
|
||||||
|
serviceRegistry = (ServiceRegistry) ctx.getBean(ServiceRegistry.SERVICE_REGISTRY);
|
||||||
|
transactionService = serviceRegistry.getTransactionService();
|
||||||
|
|
||||||
|
// Register the test model
|
||||||
|
URL testModelUrl = ResourceUtils.getURL("classpath:alfresco/testaudit/alfresco-audit-test.xml");
|
||||||
|
auditModelRegistry.registerModel(testModelUrl);
|
||||||
|
auditModelRegistry.loadAuditModels();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void tearDown() throws Exception
|
||||||
|
{
|
||||||
|
AuthenticationUtil.clearCurrentSecurityContext();
|
||||||
|
// Throw away the reconfigured registry state
|
||||||
|
auditModelRegistry.destroy();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testUserFilter()
|
||||||
|
{
|
||||||
|
Map<Boolean, String> userArr = new HashMap<Boolean, String>();
|
||||||
|
userArr.put(false, "user1");
|
||||||
|
userArr.put(true, "user2");
|
||||||
|
userArr.put(true, "bob");
|
||||||
|
UserAuditFilter userAuditFilter = new UserAuditFilter();
|
||||||
|
userAuditFilter.setUserFilterPattern("~user1;user2;.*");
|
||||||
|
userAuditFilter.afterPropertiesSet();
|
||||||
|
auditComponent.setUserAuditFilter(userAuditFilter);
|
||||||
|
|
||||||
|
final RetryingTransactionCallback<Map<String, Serializable>> testCallback = new RetryingTransactionCallback<Map<String, Serializable>>()
|
||||||
|
{
|
||||||
|
public Map<String, Serializable> execute() throws Throwable
|
||||||
|
{
|
||||||
|
Map<String, Serializable> values = new HashMap<String, Serializable>(13);
|
||||||
|
values.put("/3.1/4.1", new Long(41));
|
||||||
|
values.put("/3.1/4.2", "42");
|
||||||
|
values.put("/3.1/4.3", new Date());
|
||||||
|
values.put("/3.1/4.4", "");
|
||||||
|
values.put("/3.1/4.5", null);
|
||||||
|
|
||||||
|
return auditComponent.recordAuditValues("/test/one.one/two.one", values);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
RunAsWork<Map<String, Serializable>> testRunAs = new RunAsWork<Map<String, Serializable>>()
|
||||||
|
{
|
||||||
|
public Map<String, Serializable> doWork() throws Exception
|
||||||
|
{
|
||||||
|
return transactionService.getRetryingTransactionHelper().doInTransaction(testCallback);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
// record audit values using different users
|
||||||
|
Map<String, Serializable> result;
|
||||||
|
Set<Map.Entry<Boolean, String>> userSet = userArr.entrySet();
|
||||||
|
for(Map.Entry<Boolean, String> entry : userSet)
|
||||||
|
{
|
||||||
|
result = AuthenticationUtil.runAs(testRunAs, entry.getValue());
|
||||||
|
assertEquals((boolean) entry.getKey(), !result.isEmpty());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testUserFilterParseRedirectProperty()
|
||||||
|
{
|
||||||
|
UserAuditFilter userAuditFilter = new UserAuditFilter();
|
||||||
|
userAuditFilter.setUserFilterPattern("~user1;${audit.test.user};.*");
|
||||||
|
try
|
||||||
|
{
|
||||||
|
userAuditFilter.afterPropertiesSet();
|
||||||
|
fail("UserAuditFilter shouldn't parse property with redirect '$'");
|
||||||
|
}
|
||||||
|
catch (AlfrescoRuntimeException ex)
|
||||||
|
{
|
||||||
|
// Expected
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Reference in New Issue
Block a user