mirror of
https://github.com/Alfresco/alfresco-community-repo.git
synced 2025-07-31 17:39:05 +00:00
MNT-17512 Add auditing of RM permission changes.
This commit is contained in:
@@ -14,4 +14,5 @@ rm.audit.audit-clear=Audit Clear
|
||||
rm.audit.audit-view=Audit View
|
||||
rm.audit.trail-file-fail=Can't generate audit report.
|
||||
rm.audit.audit-report=Audit Report
|
||||
rm.audit.set-permission=Set Permission
|
||||
recordable-version-config=Auto-Declare Options
|
@@ -454,6 +454,7 @@
|
||||
<property name="authorityService" ref="AuthorityService" />
|
||||
<property name="filePlanRoleService" ref="FilePlanRoleService" />
|
||||
<property name="filePlanService" ref="FilePlanService" />
|
||||
<property name="recordsManagementAuditService" ref="RecordsManagementAuditService" />
|
||||
</bean>
|
||||
|
||||
<bean id="FilePlanPermissionService" class="org.springframework.aop.framework.ProxyFactoryBean">
|
||||
|
@@ -39,18 +39,18 @@ import org.alfresco.service.namespace.QName;
|
||||
|
||||
/**
|
||||
* Records management audit service.
|
||||
*
|
||||
*
|
||||
* @author Gavin Cornwell
|
||||
*/
|
||||
public interface RecordsManagementAuditService extends RecordsManagementAuditServiceDeprecated
|
||||
{
|
||||
public enum ReportFormat { HTML, JSON }
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Retrieves a list of audit events.
|
||||
*
|
||||
*
|
||||
* @return List of audit events
|
||||
*/
|
||||
List<AuditEvent> getAuditEvents();
|
||||
@@ -60,49 +60,49 @@ public interface RecordsManagementAuditService extends RecordsManagementAuditSer
|
||||
* <p>
|
||||
* Creates an instance of a simple audit event and registers it with
|
||||
* the service.
|
||||
*
|
||||
*
|
||||
* @param name name of audit event
|
||||
* @param label display label of audit event
|
||||
*/
|
||||
void registerAuditEvent(String name, String label);
|
||||
|
||||
|
||||
/**
|
||||
* Register audit event.
|
||||
*
|
||||
*
|
||||
* @param auditEvent audit event
|
||||
*/
|
||||
void registerAuditEvent(AuditEvent auditEvent);
|
||||
|
||||
|
||||
/**
|
||||
* Audits an event, assumes no properties where modified and that the event should not be audited
|
||||
* immediately.
|
||||
*
|
||||
* immediately.
|
||||
*
|
||||
* @param nodeRef node reference
|
||||
* @param eventName event name
|
||||
*/
|
||||
void auditEvent(NodeRef nodeRef,
|
||||
void auditEvent(NodeRef nodeRef,
|
||||
String eventName);
|
||||
|
||||
|
||||
/**
|
||||
* Audits an event, assumes that the event should not be audited immediately and not be removed if no property is changed.
|
||||
*
|
||||
*
|
||||
* @param nodeRef node reference
|
||||
* @param eventName event name
|
||||
* @param before property values before event
|
||||
* @param after property values after event
|
||||
* @param before property values before event (this must be modifiable and may be changed by the method).
|
||||
* @param after property values after event (this must be modifiable and may be changed by the method).
|
||||
*/
|
||||
void auditEvent(NodeRef nodeRef,
|
||||
String eventName,
|
||||
Map<QName, Serializable> before,
|
||||
Map<QName, Serializable> after);
|
||||
|
||||
|
||||
/**
|
||||
* Audit event, assumes not to be removed if no property is changed.
|
||||
*
|
||||
*
|
||||
* @param nodeRef node reference
|
||||
* @param eventName event name
|
||||
* @param before property values before event
|
||||
* @param after property values after event
|
||||
* @param before property values before event (this must be modifiable and may be changed by the method).
|
||||
* @param after property values after event (this must be modifiable and may be changed by the method).
|
||||
* @param immediate true if event is to be audited immediately, false otherwise
|
||||
*/
|
||||
void auditEvent(NodeRef nodeRef,
|
||||
@@ -110,14 +110,14 @@ public interface RecordsManagementAuditService extends RecordsManagementAuditSer
|
||||
Map<QName, Serializable> before,
|
||||
Map<QName, Serializable> after,
|
||||
boolean immediate);
|
||||
|
||||
|
||||
/**
|
||||
* Audit event.
|
||||
*
|
||||
*
|
||||
* @param nodeRef node reference
|
||||
* @param eventName event name
|
||||
* @param before property values before event
|
||||
* @param after property values after event
|
||||
* @param before property values before event (this must be modifiable and may be changed by the method).
|
||||
* @param after property values after event (this must be modifiable and may be changed by the method).
|
||||
* @param immediate true if event is to be audited immediately, false otherwise
|
||||
* @param removeIfNoPropertyChanged true if event is not audited when there are no properties changed, false otherwise
|
||||
*/
|
||||
@@ -127,52 +127,52 @@ public interface RecordsManagementAuditService extends RecordsManagementAuditSer
|
||||
Map<QName, Serializable> after,
|
||||
boolean immediate,
|
||||
boolean removeIfNoPropertyChanged);
|
||||
|
||||
|
||||
/**
|
||||
* Determines whether the RM audit log is currently enabled.
|
||||
*
|
||||
*
|
||||
* @param filePlan file plan
|
||||
* @return true if RM auditing is active false otherwise
|
||||
*/
|
||||
boolean isAuditLogEnabled(NodeRef filePlan);
|
||||
|
||||
boolean isAuditLogEnabled(NodeRef filePlan);
|
||||
|
||||
/**
|
||||
* Start RM auditing.
|
||||
*
|
||||
*
|
||||
* @param filePlan file plan
|
||||
*/
|
||||
void startAuditLog(NodeRef filePlan);
|
||||
|
||||
|
||||
/**
|
||||
* Stop RM auditing.
|
||||
*
|
||||
*
|
||||
* @param filePlan file plan
|
||||
*/
|
||||
*/
|
||||
void stopAuditLog(NodeRef filePlan);
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Clears the RM audit.
|
||||
*
|
||||
*
|
||||
* @param filePlan file plan
|
||||
*/
|
||||
void clearAuditLog(NodeRef filePlan);
|
||||
|
||||
|
||||
/**
|
||||
* Returns the date the RM audit was last started.
|
||||
*
|
||||
* @param filePlan file plan
|
||||
*
|
||||
* @param filePlan file plan
|
||||
* @return Date the audit was last started
|
||||
*/
|
||||
Date getDateAuditLogLastStarted(NodeRef filePlan);
|
||||
|
||||
/**
|
||||
* Returns the date the RM audit was last stopped.
|
||||
*
|
||||
*
|
||||
* @return Date the audit was last stopped
|
||||
*/
|
||||
Date getDateAuditLogLastStopped(NodeRef filePlan);
|
||||
|
||||
|
||||
/**
|
||||
* Retrieves a list of audit log entries using the provided parameters
|
||||
* represented by the RecordsManagementAuditQueryParameters instance.
|
||||
@@ -181,13 +181,13 @@ public interface RecordsManagementAuditService extends RecordsManagementAuditSer
|
||||
* object will result in ALL audit log entries for the RM system being
|
||||
* returned. Setting the various parameters effectively filters the full
|
||||
* audit trail.
|
||||
*
|
||||
*
|
||||
* @param params Parameters to use to retrieve audit trail (never <tt>null</tt>)
|
||||
* @param format The format the report should be produced in
|
||||
* @return File containing JSON representation of audit trail
|
||||
*/
|
||||
File getAuditTrailFile(RecordsManagementAuditQueryParameters params, ReportFormat format);
|
||||
|
||||
|
||||
/**
|
||||
* Retrieves a list of audit log entries using the provided parameters
|
||||
* represented by the RecordsManagementAuditQueryParameters instance.
|
||||
@@ -196,23 +196,23 @@ public interface RecordsManagementAuditService extends RecordsManagementAuditSer
|
||||
* object will result in ALL audit log entries for the RM system being
|
||||
* returned. Setting the various parameters effectively filters the full
|
||||
* audit trail.
|
||||
*
|
||||
*
|
||||
* @param params Parameters to use to retrieve audit trail (never <tt>null</tt>)
|
||||
* @return All entries for the audit trail
|
||||
*/
|
||||
List<RecordsManagementAuditEntry> getAuditTrail(RecordsManagementAuditQueryParameters params);
|
||||
|
||||
|
||||
/**
|
||||
* Retrieves a list of audit log entries using the provided parameters
|
||||
* represented by the RecordsManagementAuditQueryParameters instance and
|
||||
* then files the resulting log as an undeclared record in the record folder
|
||||
* then files the resulting log as an undeclared record in the record folder
|
||||
* represented by the given NodeRef.
|
||||
* <p>
|
||||
* The parameters are all optional so an empty RecordsManagementAuditQueryParameters
|
||||
* object will result in ALL audit log entries for the RM system being
|
||||
* returned. Setting the various parameters effectively filters the full
|
||||
* audit trail.
|
||||
*
|
||||
*
|
||||
* @param params Parameters to use to retrieve audit trail (never <tt>null</tt>)
|
||||
* @param destination NodeRef representing a record folder in which to file the audit log
|
||||
* @param format The format the report should be produced in
|
||||
|
@@ -110,7 +110,7 @@ public class RecordsManagementAuditServiceImpl extends AbstractLifecycleBean
|
||||
private static Log logger = LogFactory.getLog(RecordsManagementAuditServiceImpl.class);
|
||||
|
||||
private static final String ACCESS_AUDIT_CAPABILITY = "AccessAudit";
|
||||
|
||||
|
||||
private static final String KEY_RM_AUDIT_NODE_RECORDS = "RMAUditNodeRecords";
|
||||
|
||||
protected static final String RM_AUDIT_EVENT_LOGIN_SUCCESS = "Login.Success";
|
||||
@@ -284,7 +284,7 @@ public class RecordsManagementAuditServiceImpl extends AbstractLifecycleBean
|
||||
{
|
||||
this.namespaceService = namespaceService;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param capabilityService capability service
|
||||
*/
|
||||
@@ -292,9 +292,9 @@ public class RecordsManagementAuditServiceImpl extends AbstractLifecycleBean
|
||||
{
|
||||
this.capabilityService = capabilityService;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @param ignoredAuditProperties
|
||||
@@ -506,6 +506,8 @@ public class RecordsManagementAuditServiceImpl extends AbstractLifecycleBean
|
||||
@Override
|
||||
public void auditEvent(NodeRef nodeRef, String eventName, Map<QName, Serializable> before, Map<QName, Serializable> after, boolean immediate, boolean removeIfNoPropertyChanged)
|
||||
{
|
||||
logger.error("DEBUGGING: " + String.valueOf(before));
|
||||
logger.error("ALSO : " + String.valueOf(after));
|
||||
// deal with immediate auditing if required
|
||||
if (immediate)
|
||||
{
|
||||
@@ -929,7 +931,7 @@ public class RecordsManagementAuditServiceImpl extends AbstractLifecycleBean
|
||||
// Skip it
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
if(nodeRef != null && nodeService.exists(nodeRef) &&
|
||||
!AccessStatus.ALLOWED.equals(
|
||||
capabilityService.getCapabilityAccessState(nodeRef, ACCESS_AUDIT_CAPABILITY)))
|
||||
|
@@ -27,6 +27,7 @@
|
||||
|
||||
package org.alfresco.module.org_alfresco_module_rm.security;
|
||||
|
||||
import static java.util.Collections.singletonMap;
|
||||
import static org.alfresco.module.org_alfresco_module_rm.security.ExtendedReaderDynamicAuthority.EXTENDED_READER;
|
||||
import static org.alfresco.module.org_alfresco_module_rm.security.ExtendedWriterDynamicAuthority.EXTENDED_WRITER;
|
||||
import static org.alfresco.repo.policy.Behaviour.NotificationFrequency.TRANSACTION_COMMIT;
|
||||
@@ -36,10 +37,15 @@ import static org.alfresco.service.cmr.security.OwnableService.NO_OWNER;
|
||||
import static org.alfresco.util.ParameterCheck.mandatory;
|
||||
import static org.apache.commons.lang.BooleanUtils.isTrue;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import org.alfresco.error.AlfrescoRuntimeException;
|
||||
import org.alfresco.module.org_alfresco_module_rm.audit.RecordsManagementAuditService;
|
||||
import org.alfresco.module.org_alfresco_module_rm.audit.event.AuditEvent;
|
||||
import org.alfresco.module.org_alfresco_module_rm.capability.RMPermissionModel;
|
||||
import org.alfresco.module.org_alfresco_module_rm.fileplan.FilePlanService;
|
||||
import org.alfresco.module.org_alfresco_module_rm.role.FilePlanRoleService;
|
||||
@@ -50,6 +56,7 @@ import org.alfresco.repo.policy.PolicyComponent;
|
||||
import org.alfresco.repo.policy.annotation.Behaviour;
|
||||
import org.alfresco.repo.policy.annotation.BehaviourBean;
|
||||
import org.alfresco.repo.security.authentication.AuthenticationUtil;
|
||||
import org.alfresco.repo.security.authentication.AuthenticationUtil.RunAsWork;
|
||||
import org.alfresco.service.cmr.repository.ChildAssociationRef;
|
||||
import org.alfresco.service.cmr.repository.NodeRef;
|
||||
import org.alfresco.service.cmr.security.AccessPermission;
|
||||
@@ -75,6 +82,11 @@ public class FilePlanPermissionServiceImpl extends ServiceBaseImpl
|
||||
RMPermissionModel,
|
||||
NodeServicePolicies.OnMoveNodePolicy
|
||||
{
|
||||
private static final String AUDIT_SET_PERMISSION = "set-permission";
|
||||
|
||||
/** An namespace to use when constructing QNames to use for auditing changes to permissions. */
|
||||
private static final String AUDIT_NAMESPACE = "audit://permissions/";
|
||||
|
||||
/** Permission service */
|
||||
private PermissionService permissionService;
|
||||
|
||||
@@ -93,6 +105,9 @@ public class FilePlanPermissionServiceImpl extends ServiceBaseImpl
|
||||
/** File plan service */
|
||||
private FilePlanService filePlanService;
|
||||
|
||||
/** The RM audit service. */
|
||||
private RecordsManagementAuditService recordsManagementAuditService;
|
||||
|
||||
/** Logger */
|
||||
private static final Log LOGGER = LogFactory.getLog(FilePlanPermissionServiceImpl.class);
|
||||
|
||||
@@ -113,6 +128,16 @@ public class FilePlanPermissionServiceImpl extends ServiceBaseImpl
|
||||
NodeServicePolicies.OnMoveNodePolicy.QNAME,
|
||||
TYPE_RECORD_CATEGORY,
|
||||
new JavaBehaviour(this, "onMoveNode", TRANSACTION_COMMIT));
|
||||
|
||||
AuthenticationUtil.runAsSystem(new RunAsWork<Void>()
|
||||
{
|
||||
@Override
|
||||
public Void doWork() throws Exception
|
||||
{
|
||||
recordsManagementAuditService.registerAuditEvent(new AuditEvent(AUDIT_SET_PERMISSION, "rm.audit.set-permission"));
|
||||
return null;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -229,6 +254,16 @@ public class FilePlanPermissionServiceImpl extends ServiceBaseImpl
|
||||
this.filePlanService = filePlanService;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the RM audit service.
|
||||
*
|
||||
* @param recordsManagementAuditService The RM audit service.
|
||||
*/
|
||||
public void setRecordsManagementAuditService(RecordsManagementAuditService recordsManagementAuditService)
|
||||
{
|
||||
this.recordsManagementAuditService = recordsManagementAuditService;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.alfresco.module.org_alfresco_module_rm.security.FilePlanPermissionService#setupRecordCategoryPermissions(org.alfresco.service.cmr.repository.NodeRef)
|
||||
*/
|
||||
@@ -342,6 +377,7 @@ public class FilePlanPermissionServiceImpl extends ServiceBaseImpl
|
||||
|
||||
final boolean hasUserPermission = authenticationUtil.runAs(new AuthenticationUtil.RunAsWork<Boolean>()
|
||||
{
|
||||
@Override
|
||||
public Boolean doWork()
|
||||
{
|
||||
return getPermissionService().hasPermission(nodeRef, RMPermissionModel.FILING) == AccessStatus.ALLOWED;
|
||||
@@ -352,6 +388,7 @@ public class FilePlanPermissionServiceImpl extends ServiceBaseImpl
|
||||
{
|
||||
authenticationUtil.runAsSystem(new AuthenticationUtil.RunAsWork<Void>()
|
||||
{
|
||||
@Override
|
||||
public Void doWork()
|
||||
{
|
||||
getPermissionService().setPermission(nodeRef, user, RMPermissionModel.FILING, true);
|
||||
@@ -367,6 +404,7 @@ public class FilePlanPermissionServiceImpl extends ServiceBaseImpl
|
||||
* @param parent parent node reference
|
||||
* @param nodeRef child node reference
|
||||
*/
|
||||
@Override
|
||||
public void setupPermissions(final NodeRef parent, final NodeRef nodeRef)
|
||||
{
|
||||
mandatory("parent", parent);
|
||||
@@ -376,6 +414,7 @@ public class FilePlanPermissionServiceImpl extends ServiceBaseImpl
|
||||
{
|
||||
authenticationUtil.runAsSystem(new AuthenticationUtil.RunAsWork<Object>()
|
||||
{
|
||||
@Override
|
||||
public Object doWork()
|
||||
{
|
||||
// set inheritance
|
||||
@@ -455,6 +494,7 @@ public class FilePlanPermissionServiceImpl extends ServiceBaseImpl
|
||||
|
||||
authenticationUtil.runAsSystem(new AuthenticationUtil.RunAsWork<Object>()
|
||||
{
|
||||
@Override
|
||||
public Object doWork()
|
||||
{
|
||||
if (nodeService.exists(record) && nodeService.hasAspect(record, aspectTypeQName))
|
||||
@@ -481,6 +521,7 @@ public class FilePlanPermissionServiceImpl extends ServiceBaseImpl
|
||||
|
||||
authenticationUtil.runAs(new AuthenticationUtil.RunAsWork<Void>()
|
||||
{
|
||||
@Override
|
||||
public Void doWork()
|
||||
{
|
||||
NodeRef record = sourceAssocRef.getChildRef();
|
||||
@@ -528,6 +569,7 @@ public class FilePlanPermissionServiceImpl extends ServiceBaseImpl
|
||||
/**
|
||||
* @see org.alfresco.module.org_alfresco_module_rm.security.RecordsManagementSecurityService#setPermission(org.alfresco.service.cmr.repository.NodeRef, java.lang.String, java.lang.String, boolean)
|
||||
*/
|
||||
@Override
|
||||
public void setPermission(final NodeRef nodeRef, final String authority, final String permission)
|
||||
{
|
||||
ParameterCheck.mandatory("nodeRef", nodeRef);
|
||||
@@ -536,12 +578,19 @@ public class FilePlanPermissionServiceImpl extends ServiceBaseImpl
|
||||
|
||||
authenticationUtil.runAsSystem(new AuthenticationUtil.RunAsWork<Object>()
|
||||
{
|
||||
@Override
|
||||
public Void doWork()
|
||||
{
|
||||
if (canPerformPermissionAction(nodeRef))
|
||||
{
|
||||
// Construct a QName so that the authority and permission are visible in the log.
|
||||
QName auditProperty = QName.createQName(AUDIT_NAMESPACE, authority + "_" + permission);
|
||||
Map<QName, Serializable> oldPermission = getCurrentPermissionForAuthority(nodeRef, authority, permission, auditProperty);
|
||||
// Set the permission on the node
|
||||
getPermissionService().setPermission(nodeRef, authority, permission, true);
|
||||
// Add an entry in the audit log.
|
||||
recordsManagementAuditService.auditEvent(nodeRef, AUDIT_SET_PERMISSION,
|
||||
oldPermission, new HashMap<>(singletonMap(auditProperty, (Serializable) true)));
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -556,9 +605,31 @@ public class FilePlanPermissionServiceImpl extends ServiceBaseImpl
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the current permission on a node for an authority.
|
||||
*
|
||||
* @param nodeRef The node.
|
||||
* @param authority The authority.
|
||||
* @param auditProperty The QName used as the key in the returned map.
|
||||
* @return A map from the audit property to true or false depending on whether the user currently has permission.
|
||||
*/
|
||||
private Map<QName, Serializable> getCurrentPermissionForAuthority(NodeRef nodeRef, String authority, String permission, QName auditProperty)
|
||||
{
|
||||
Set<AccessPermission> allSetPermissions = getPermissionService().getAllSetPermissions(nodeRef);
|
||||
for (AccessPermission setPermission : allSetPermissions)
|
||||
{
|
||||
if (setPermission.getAuthority().equals(authority) && setPermission.getPermission().equals(permission))
|
||||
{
|
||||
return new HashMap<>(singletonMap(auditProperty, true));
|
||||
}
|
||||
}
|
||||
return new HashMap<>(singletonMap(auditProperty, false));
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.alfresco.module.org_alfresco_module_rm.security.RecordsManagementSecurityService#deletePermission(org.alfresco.service.cmr.repository.NodeRef, java.lang.String, java.lang.String)
|
||||
*/
|
||||
@Override
|
||||
public void deletePermission(final NodeRef nodeRef, final String authority, final String permission)
|
||||
{
|
||||
ParameterCheck.mandatory("nodeRef", nodeRef);
|
||||
@@ -567,12 +638,19 @@ public class FilePlanPermissionServiceImpl extends ServiceBaseImpl
|
||||
|
||||
authenticationUtil.runAsSystem(new AuthenticationUtil.RunAsWork<Object>()
|
||||
{
|
||||
@Override
|
||||
public Void doWork()
|
||||
{
|
||||
if (canPerformPermissionAction(nodeRef))
|
||||
{
|
||||
// Construct a QName so that the authority and permission are visible in the log.
|
||||
QName auditProperty = QName.createQName(AUDIT_NAMESPACE, authority + "_" + permission);
|
||||
Map<QName, Serializable> oldPermission = getCurrentPermissionForAuthority(nodeRef, authority, permission, auditProperty);
|
||||
// Delete permission on this node
|
||||
getPermissionService().deletePermission(nodeRef, authority, permission);
|
||||
// Add an entry in the audit log.
|
||||
recordsManagementAuditService.auditEvent(nodeRef, AUDIT_SET_PERMISSION,
|
||||
oldPermission, new HashMap<>(singletonMap(auditProperty, (Serializable) false)));
|
||||
}
|
||||
else
|
||||
{
|
||||
|
Reference in New Issue
Block a user