Alfresco Documentation
Published on Alfresco Documentation (https://docs.alfresco.com)

Home > Alfresco One 4.2.8 > Administering > Auditing Alfresco

Auditing Alfresco

Alfresco provides the ability to audit activity. This section describes how Alfresco generates, stores, and retrieves auditing information.
Note: The auditing mechanism prior to Version 3.4.0 has been removed but the old tables remain in the system. You can access the previous audit data but any new audit data will be directed to the new tables. Any customizations of the auditing feature must be rewritten using the new configuration files. All SQL-based queries used previously must be replaced by calls to the supplied APIs. The use of low-level SQL statements to retrieve data is not supported.

The architecture of the auditing features comprises the following components:

Data Producers defines the components that produce data that might be audited. Data producers do not need to know anything about how the data is stored. Data is generated and sent to the AuditComponent.recordAuditValues component. The only requirement is that each packet of data is a Map of data keyed by logical path names, which are specific to the producers.

The AuditService search should be used for data retrieval; however, for completeness, the following tables are used:
  • Tables exclusive to the new audit (AlfrescoPostCreate-3.2-AuditTables.sql)
    • alf_audit_model: Contains the record of the audit configuration files.
    • alf_audit_application: Contains an entry for each logical application. There may be several audit applications defined in a single audit model.
    • alf_audit_entry: Contains an entry for each call to AuditComponent.recordAuditValues. There is a reference to a property.
  • Shared tables (AlfrescoPostCreate-3.2-PropertyValueTables.sql)
    • alf_prop_root: Entry point for properties: shared values are fully indexed; arbitrarily-deep collections; quick data query and reconstruction.
  • Audit configuration and environment [1] This section describes the configuration and environment settings for auditing.
  • Audit filters [2] This section describes how to use Alfresco global properties to filter audit data generated by any audit data producer.
  • Content auditing [3] This section describes how to use Alfresco to audit actions performed on your content and folders, including a technical overview, and also examples of how to customize the standard configuration.
  • Sample files [4] Audit sample files are distributed in the <TOMCAT_HOME>/classes/alfresco/extension/audit directory.
  • Enabling auditing [5] Generation of audit data is disabled by default. To enable auditing permanently, settings must be added to the Alfresco global properties file as shown in the following text.
  • Auditing examples [6] This section describes some auditing examples.
  • Audit configuration files [7] This section describes the location and basic structure of the audit configuration files.
  • Built-in data producers [8] The following are built-in data producers.
  • DataExtractors and DataGenerators [9] This section provides a description of DataExtractors and DataGenerators.
  • Locating the audit code [10] This section describes the location of audit code.
  • Defining the audit application [11] This section describes the audit applications.
  • Simple audit query [12] This section describes a simple audit query example.
  • Advanced audit query [13] This section describes an advanced audit query example.
  • Understanding PathMappings [14] To create an audit configuration file, it is necessary to know which data can be audited and how the data is mapped onto your application.
  • Audit recording values [15] The RecordValue element makes use of the DataExtractor definitions, but specifies when to be activated (dataTrigger) and where to get the data from (dataSource). Both the dataTrigger and dataSource attributes default to the path of the RecordValue element. Data is always written to the path where the RecordValue is declared. So, it is possible to trigger the RecordValue when a data path is present (such as a null value) and then to read a value from a completely different location.
  • Using values that have changed in a post method call [16] When using the org.alfresco.repo.audit.AuditMethodInterceptor Data Producer, which generates audit data for all public service API calls, it is sometimes useful to be able to audit before and after values in a 'post' call application, or to include values from before the call.
Parent topic: Administering [17]

Audit configuration and environment

This section describes the configuration and environment settings for auditing.

Configuration and environment Details
Tomcat environment
  • Set the configuration properties in the alfresco-global.properties file.
  • Log4J settings can be added in a file <tomcat>/shared/classes/alfresco/extension/audit-log4j.properties.
View the available web scripts and details Use the following scripts:
  • Script index: http://localhost:8080/alfresco/service/ [18]
  • Audit scripts: http://localhost:8080/alfresco/service/index/package/org/alfresco/repository/audit [19]
HTTP client
  • curl will be used as the HTTP client
Sample files
  • Audit sample files are distributed in the <extension>/audit directory. Activate the sample files by removing the .sample extension.
Check the state of auditing on the server:
% curl -u admin:admin "http://localhost:8080/alfresco/service/api/audit/control"
{
   "enabled" : false,
   "applications": 
   [
   ]
}
For information on how to clean up the audit tables, see Scheduling cleanup of database tables [20].
Parent topic: Auditing Alfresco [21]

Audit filters

This section describes how to use Alfresco global properties to filter audit data generated by any audit data producer.

Audit data producers call AuditComponent.recordAuditValues(rootPath, auditMap) once for each event to be audited. Filters are applied to reject events so that their values are never used by audit configurations. The rootPath identifies the data producer and the auditMap is the event data. The rootPath value and keys in the map represent a tree structure.

  • Example rootPath and auditMap [22] The last component in the rootPath is considered by the AuditFilter to be the event action. The keys in an audit map identify each audit value. Global properties may be defined to accept or reject each value. If any value in an audit map is rejected, the whole map is rejected. So that one does not have to define too many properties, a default event action property may be defined. This will be inherited by all actions unless a property is defined for a particular event action.
  • Example filter [23] Each property value defines a list of regular expressions that will be used to match the actual audit map values.
  • Redirected properties [24] It is possible for one property to reference another property.
  • Debug information [25] The PropertyAuditFilter provides log4j debug information (in the alfresco.log file) when it rejects values. Turning on this debug can generate large volumes of output. 
  • Audit filter customizations [26] You can define additional filter properties and override predefined filter values.
Parent topic: Auditing Alfresco [21]

Example rootPath and auditMap

The last component in the rootPath is considered by the AuditFilter to be the event action. The keys in an audit map identify each audit value. Global properties may be defined to accept or reject each value. If any value in an audit map is rejected, the whole map is rejected. So that one does not have to define too many properties, a default event action property may be defined. This will be inherited by all actions unless a property is defined for a particular event action.
rootPath:
    /alfresco-access/transaction

auditMap:
    "action"         => "MOVE"
    "node"           => "workspace://SpacesStore/90a398d1-8e0d-462a-8c3b-f0b17a2d1143"
    "move/from/node" => "workspace://SpacesStore/a82446e9-4dca-49d2-9ce0-4526687fb310"
    "move/from/path" => "/app:company_home/st:sites/cm:fred/cm:documentLibrary/cm:folder1"
    "move/from/type" => "cm:folder"
    "move/to/node"   => "workspace://SpacesStore/517bd4d0-99bc-47ad-8cd7-5d425f94c7db"
    "move/to/path"   => "/app:company_home/st:sites/cm:fred/cm:documentLibrary"
    "move/to/type"   => "cm:folder"
    "path"           => "/app:company_home/st:sites/cm:fred/cm:documentLibrary/cm:Word 123.docx"
    "sub-actions"    => "moveNode readContent"
    "type"           => "cm:content"
    "user"           => "admin"
Parent topic: Audit filters [2]

Example filter

Each property value defines a list of regular expressions that will be used to match the actual audit map values.
audit.filter.alfresco-access.default.enabled=true
audit.filter.alfresco-access.default.user=~System;.*
audit.filter.alfresco-access.default.type=cm:folder;cm:content
audit.filter.alfresco-access.default.path=/app:company_home/.*
audit.filter.alfresco-access.transaction.user=
audit.filter.alfresco-access.login.user=jblogs
... 

In the above example, events created by any user except for the internal user "System" will be recorded by default for all event actions. However the property for the transaction event action overrides this to record even "System" events.

For any filters to be applied to an event action, that action's filters must be enabled with an "enabled" property set to "true". However this may also be done by using the default event action, as shown above. Property names have a "audit.filter." prefix and use '.' as a separator where as components of rootPath and keys in the audit map use '/'.

Lists are evaluated from left to right allowing one flexibility to accept or reject different combinations of values. If no match is made by the end of the list the value is rejected. If there is not a property for a given value or an empty list is defined (as above for the "user" value on a "transaction" action) any value is accepted. Each regular expression in the list is separated by a semicolon (';'). Expressions that include a semicolon may be escaped using a '\'. An expression that starts with a '~' indicates that any matching value should be rejected. If the first character of an expression needs to be a '~', it too may be escaped with a '\'.

A property value may be a reference to another property, which saves having multiple copies of the same regular expression. This is indicated by a '$' as the first character of the property value. If the first character of an expression needs to be a '$' it too may be escaped with a '\'.

Parent topic: Audit filters [2]

Redirected properties

It is possible for one property to reference another property.

A property value may be a reference to another property, which saves having multiple copies of the same regular expression. This is indicated by a '$' as the first character of the property value. If the first character of an expression needs to be a '$' it too may be escaped with a '\'. An example of this is shown below:

audit.filter.alfresco-access.transaction.type=$transaction.content.types

transaction.content.types=$general.content.types
general.content.types=cm:folder;cm:content
Parent topic: Audit filters [2]

Debug information

The PropertyAuditFilter provides log4j debug information (in the alfresco.log file) when it rejects values. Turning on this debug can generate large volumes of output. 

Enable debug

# Change file appender to include debug from any source
log4j.appender.File.Threshold=debug

# Enable debug from the PropertyAuditFilter
log4j.logger.org.alfresco.repo.audit.PropertyAuditFilter=debug
Parent topic: Audit filters [2]

Audit filter customizations

You can define additional filter properties and override predefined filter values.

If you are using the Tomcat web application server, add the additional properties to the <tomcat>/shared/classes/alfresco-global.properties file.

Parent topic: Audit filters [2]

Content auditing

This section describes how to use Alfresco to audit actions performed on your content and folders, including a technical overview, and also examples of how to customize the standard configuration.

  • Content auditing technical overview [27] The data producer org.alfresco.repo.audit.access.AccessAuditor gathers together lower events into user recognizable events. For example, the download or preview of content are recorded as a single read. Similarly the upload of a new version of a document is recorded as a single create version. By contrast the AuditMethodInterceptor data producer typically would record multiple events.
  • Content auditing customizations [28] There are two customizations available:
Parent topic: Auditing Alfresco [21]

Content auditing technical overview

The data producer org.alfresco.repo.audit.access.AccessAuditor gathers together lower events into user recognizable events. For example, the download or preview of content are recorded as a single read. Similarly the upload of a new version of a document is recorded as a single create version. By contrast the AuditMethodInterceptor data producer typically would record multiple events.

A default audit configuration file located at <alfresco.war>/WEB-INF/classes/alfresco/audit/alfresco-audit-access.xml is provided that persists audit data for general use. This may be enhanced to extract additional data of interest to specific installations. For ease of use, login success, login failure and logout events are also persisted by the default configuration.

Default audit filter settings are also provided for the AccessAuditor data producer, so that internal events are not reported. These settings may be customized (by setting global properties) to include or exclude auditing of specific areas of the repository, users or some other value included in the audit data created by AccessAuditor.

No additional functionality is provided for the retrieval of persisted audit data, as all data is stored in the standard way, and so is accessible using the AuditService search, audit web scripts, database queries, and Alfresco Explorer show_audit.ftl preview.

  • Example audit trail [29] The following is an example audit trail.
  • Using Alfresco Explorer to view the example audit trail [30] The audit trail of individual content may be viewed from within Alfresco Explorer.
  • Enabling auditing of content [31] This section describes how to enable auditing of these events and sub events
  • Default audit filter settings [32] The following properties are set by default to discard events where the user is null or "System", the content or folder path is under "/sys:archivedItem" or under "/ver:" or the node type is not "cm:folder", "cm:content" or "st:site".
  • Audit data generated by AccessAuditor [33] Folder and content changes generate the following audit data structure. Elements are omitted if not changed by the transaction.
  • Persisted audit data [34] The default audit configuration file alfresco-audit-access.xml only copies the following audit data elements. It also adds login, loginFailure and logout persisted data.
Parent topic: Content auditing [3]
Related concepts
Audit filters [35]

Example audit trail

The following is an example audit trail.

The user actions from the Share interface were:

  1. Create a new folder called My Documents.
  2. Upload a document (The fox.odt).
  3. Preview of the document.
  4. Update the meta data.
  5. Upload a new version.
  6. Copy the document to a folder called MyPictures.
  7. Delete the copy of the document.

    In the example, the property values show "..." to indication that they are truncated.

    1. /alfresco-access/transaction/action=CREATE
       /alfresco-access/transaction/aspects/add=[cm:titled]
       /alfresco-access/transaction/path=/app:company_home/st:sites/cm:mysite/cm:documentLibrary/cm:My Documents
       /alfresco-access/transaction/properties/add=...
       /alfresco-access/transaction/sub-actions=createNode updateNodeProperties addNodeAspect
       /alfresco-access/transaction/type=cm:folder
       /alfresco-access/transaction/user=admin
    
    2. /alfresco-access/transaction/action=CREATE
       /alfresco-access/transaction/aspects/add=[cm:titled, cm:author]
       /alfresco-access/transaction/path=/app:company_home/st:sites/cm:mysite/cm:documentLibrary/cm:My Documents/cm:The fox.odt
       /alfresco-access/transaction/properties/add=...
       /alfresco-access/transaction/sub-actions=createNode  updateNodeProperties readContent createContent updateContent  addNodeAspect
       /alfresco-access/transaction/type=cm:content
       /alfresco-access/transaction/user=admin
    
    3. /alfresco-access/transaction/action=READ
       /alfresco-access/transaction/path=/app:company_home/st:sites/cm:mysite/cm:documentLibrary/cm:My Documents/cm:The fox.odt
       /alfresco-access/transaction/sub-actions=readContent
       /alfresco-access/transaction/type=cm:content
       /alfresco-access/transaction/user=admin
    
    4. /alfresco-access/transaction/action=updateNodeProperties
       /alfresco-access/transaction/aspects/add=[cm:taggable]
       /alfresco-access/transaction/path=/app:company_home/st:sites/cm:mysite/cm:documentLibrary/cm:My Documents/cm:The fox.odt
       /alfresco-access/transaction/properties/add=...
       /alfresco-access/transaction/properties/from={cm:modified=Mon Jun 13 15:34:05 BST 2011}
       /alfresco-access/transaction/properties/to={cm:modified=Mon Jun 13 15:39:35 BST 2011}
       /alfresco-access/transaction/sub-actions=updateNodeProperties addNodeAspect readContent
       /alfresco-access/transaction/type=cm:content
       /alfresco-access/transaction/user=admin
    
    5. /alfresco-access/transaction/action=CHECK IN
       /alfresco-access/transaction/aspects/add=[cm:versionable]
       /alfresco-access/transaction/copy/from/path=/app:company_home/st:sites/cm:mysite/cm:documentLibrary/cm:My  Documents/cm:The fox (Working Copy).odt
       /alfresco-access/transaction/path=/app:company_home/st:sites/cm:mysite/cm:documentLibrary/cm:My Documents/cm:The fox.odt
       /alfresco-access/transaction/properties/add=...
       /alfresco-access/transaction/properties/from=...
       /alfresco-access/transaction/properties/to=...
       /alfresco-access/transaction/sub-actions=updateNodeProperties  addNodeAspect createVersion readContent deleteNodeAspect updateContent  copyNode checkIn
       /alfresco-access/transaction/type=cm:content
       /alfresco-access/transaction/user=admin
       /alfresco-access/transaction/version=2.0
    
    6. /alfresco-access/transaction/action=COPY
       /alfresco-access/transaction/aspects/add=[cm:titled, cm:copiedfrom, cm:author, cm:taggable]
       /alfresco-access/transaction/copy/from/path=/app:company_home/st:sites/cm:mysite/cm:documentLibrary/cm:My  Documents/cm:The fox.odt
       /alfresco-access/transaction/path=/app:company_home/st:sites/cm:mysite/cm:documentLibrary/cm:My Pictures/cm:The fox.odt
       /alfresco-access/transaction/properties/add=...
       /alfresco-access/transaction/sub-actions=createNode readContent createContent updateNodeProperties addNodeAspect copyNode
       /alfresco-access/transaction/type=cm:content
       /alfresco-access/transaction/user=admin
    
    7. /alfresco-access/transaction/action=DELETE
       /alfresco-access/transaction/path=/app:company_home/st:sites/cm:mysite/cm:documentLibrary/cm:My Pictures/cm:The fox.odt
       /alfresco-access/transaction/sub-actions=deleteNode
       /alfresco-access/transaction/type=cm:content
       /alfresco-access/transaction/user=admin
Parent topic: Content auditing technical overview [27]

Using Alfresco Explorer to view the example audit trail

The audit trail of individual content may be viewed from within Alfresco Explorer.

  1. Locate the content.
  2. Select Preview in Template, using the show_audit.ftl preview.

    The following is an example of some high level events.

Parent topic: Content auditing technical overview [27]

Enabling auditing of content

This section describes how to enable auditing of these events and sub events

  1. Open the alfresco-global.properties file.
  2. Add the following properties:

    # Enable audit in general
    audit.enabled=true
    
    # Enable the alfresco-access audit application
    audit.alfresco-access.enabled=true
    
    # Enable the auditing of sub-actions. Normally disabled as these values are
    # not normally needed by audit configurations, but may be useful to
    # developers
    #audit.alfresco-access.sub-actions.enabled=true
Parent topic: Content auditing technical overview [27]

Default audit filter settings

The following properties are set by default to discard events where the user is null or "System", the content or folder path is under "/sys:archivedItem" or under "/ver:" or the node type is not "cm:folder", "cm:content" or "st:site".

These values result in events only being recorded for common actions initiated by users of the system. These values may be overridden if required.
audit.filter.alfresco-access.default.enabled=true
audit.filter.alfresco-access.transaction.user=~System;~null;.*
audit.filter.alfresco-access.transaction.type=cm:folder;cm:content;st:site
audit.filter.alfresco-access.transaction.path=~/sys:archivedItem;~/ver:;.*
Parent topic: Content auditing technical overview [27]

Audit data generated by AccessAuditor

Folder and content changes generate the following audit data structure. Elements are omitted if not changed by the transaction.

The /sub-action/<sequence> structure holds cut down details of each sub-action, but are only included if the global property audit.alfresco-access.sub-actions.enabled=true.

The structure of the audit data is shown as follows:
/alfresco-access
      /transaction
        /action=<actionNamegt
        /sub-actions=<sub action listgt
        /path=<prefixPathgt
        /type=<prefixTypegt
        /node=<nodeRefgt
        /user=<usergt
        /copy
          /from
            /node=<nodeRefgt
            /path=<prefixPathgt
            /type=<prefixTypegt
        /move
          /from
            /node=<nodeRefgt
            /path=<prefixPathgt
            /type=<prefixTypegt
        /properties
           /from=<mapOfValuesgt
             /<propertyNamegt=<propertyValuegt
             ...
           /to=<mapOfValuesgt
             /<propertyNamegt=<propertyValuegt
             ...
           /add=<mapOfValuesgt
             /<propertyNamegt=<propertyValuegt
             ...
           /delete=<mapOfValuesgt
             /<propertyNamegt=<propertyValuegt
             ...
         /aspects
           /add=<mapOfNamesgt
             /<aspectNamegt=null
             ...
           /delete=<mapOfNamesgt
             /<aspectNamegt=null
             ...
         /version-properties=<mapOfValuesgt
         /sub-action/<sequencegt
           /action=<actionNamegt
           /copy
             ...
           /move
             ...
           /properties
             ...
           /aspects
             ...
An example of audit data is shown as follows:
Inbound audit values:
    /alfresco-access/transaction/action=MOVE
     /alfresco-access/transaction/node=workspace://SpacesStore/74a5985a-45dd-4698-82db-8eaeff9df8d7
     /alfresco-access/transaction/move/from/node=workspace://SpacesStore/d8a0dfd8-fe45-47da-acc2-fd8df9ea2b2e
     /alfresco-access/transaction/move/from/path=/app:company_home/st:sites/cm:abc/cm:documentLibrary/cm:folder1/cm:Word 123.docx
     /alfresco-access/transaction/move/from/type=cm:folder
     /alfresco-access/transaction/path=/app:company_home/st:sites/cm:abc/cm:documentLibrary/cm:folder2/cm:Word 123.docx
     /alfresco-access/transaction/sub-actions=moveNode readContent
     /alfresco-access/transaction/type=cm:content
     /alfresco-access/transaction/user=admin
     /alfresco-access/transaction/sub-action/00/action=moveNode
     /alfresco-access/transaction/sub-action/00/move/from/node=workspace://SpacesStore/d8a0dfd8-fe45-47da-acc2-fd8df9ea2b2e
     /alfresco-access/transaction/sub-action/00/move/from/path=/app:company_home/st:sites/cm:abc/cm:documentLibrary/cm:folder1/cm:folder1/cm:Word 123.docx
     /alfresco-access/transaction/sub-action/00/move/from/type=cm:folder
     /alfresco-access/transaction/sub-action/01/action=readContent 
Parent topic: Content auditing technical overview [27]

Persisted audit data

The default audit configuration file alfresco-audit-access.xml only copies the following audit data elements. It also adds login, loginFailure and logout persisted data.

The default structure of the persisted audit data is shown as follows:
/alfresco-access
  /login/user=<usergt
  /loginFailure/user=<usergt
  /logout/user=<usergt
  /transaction/
   /action=<actionNamegt
   /sub-actions=<sub action listgt
   /path=<prefixPathgt
   /type=<prefixTypegt
   /user=<usergt
   /version=<versiongt
   /copy/from/path=<prefixPathgt
   /move
     /from/path=<prefixPathgt
   /properties
      /from=<mapOfValuesgt
      /to=<mapOfValuesgt
      /add=<mapOfValuesgt
      /delete=<mapOfValuesgt
      /fromName=<oldNamegt
      /toName=<newNamegt
    /aspects
      /add=<mapOfNamesgt
      /delete=<mapOfNamesgt

The version value is sourced from either the add/cm:versionLabel or to/cm:versionLabel values.

The exception is the property name, individual property and aspect changes are not included, as it is not possible to know all possible names. The map values of all changes is however included. The individual property name value is included as it is a well known property, which changes if content or a folder is renamed within the same parent folder.

Parent topic: Content auditing technical overview [27]

Content auditing customizations

There are two customizations available:

  • Creating a custom audit filter
  • Creating a custom configuration
  • Custom audit filter [36] The most common customization is to change the default audit filter values.
  • Custom audit configuration [37] The most common reason to customize the audit configuration is if there is a need to extract individual property or aspect values that have special meaning to a particular Alfresco installation.
Parent topic: Content auditing [3]

Custom audit filter

The most common customization is to change the default audit filter values.

These filter values are used to include or exclude selected events. Global property names identifies elements in the generated audit data. Each property value is a list of regular expressions that either accept or reject the generated data value. If any value is rejected in a set of data the whole set is rejected. For example, to audit the users "jblogs" and any user that starts with "temp" other than "tempmanager", override the following global property value. If using tomcat, add a value to the <tomcat>/shared/classes/alfresco-global.properties file.

The following is an example custom filter:

audit.filter.alfresco-access.transaction.user=~tempManager;temp.*;jblogs 

The list is semicolon separated. Any regular expression that starts with a '~' indicates that a matching value should be rejected. The list is evaluated from left to right until there is a match. If no match is made the value is rejected. If the list is empty (zero length) all values are accepted. It is possible to filter on any of the generated data values. Refer to the audit filtering section for a more detailed description of filter properties.

Parent topic: Content auditing customizations [28]

Custom audit configuration

The most common reason to customize the audit configuration is if there is a need to extract individual property or aspect values that have special meaning to a particular Alfresco installation.

For example, a security clearance level has been added to content and it is important to include that clearly in the persisted audit data, rather than having to find it deep within a map of all properties. The default configuration includes an example. It extracts the name property. It is generally a good idea to create a new audit configuration file that includes a mapped path to avoid confusion with the default. If running under Tomcat place the audit configuration file in the <tomcat>/shared/classes/alfresco/extension/audit directory. The following example is simply a cut down version of the default with the path mapped to a new value.

The following is an example of the myApp.xml file.
<?xml version="1.0" encoding="UTF-8"?>
<Audit xmlns="http://www.alfresco.org/repo/audit/model/3.2"
     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
     xsi:schemaLocation="http://www.alfresco.org/repo/audit/model/3.2
    alfresco-audit-3.2.xsd">

  <DataExtractors>
    <DataExtractor name="simpleValue"
        registeredName="auditModel.extractor.simpleValue"/>
  </DataExtractors>

  <PathMappings>
    <PathMap source="/alfresco-access" target="/my-app" />
  </PathMappings>

  <Application name="my-app" key="my-app">
    <RecordValue
        key="action" dataExtractor="simpleValue"
        dataSource="/my-app/transaction/action"
        dataTrigger="/my-app/transaction/action" />
    <RecordValue
        key="user" dataExtractor="simpleValue"
        dataSource="/my-app/transaction/user"
        dataTrigger="/my-app/transaction/user" />
    <RecordValue
        key="path" dataExtractor="simpleValue"
        dataSource="/my-app/transaction/path"
        dataTrigger="/my-app/transaction/path" />
  </Application>

</Audit>
The following shows the AccessAuditor debug for a move action.
Audit data:
    /my-app/action=MOVE
    /my-app/path=/app:company_home/st:sites/cm:fred/cm:documentLibrary/cm:Word 123.docx
    /my-app/user=admin

Inbound audit values:
    /alfresco-access/transaction/action=MOVE
    /alfresco-access/transaction/node=workspace://SpacesStore/90a398d1-8e0d-462a-8c3b-f0b17a2d1143
    /alfresco-access/transaction/move/from/node=workspace://SpacesStore/a82446e9-4dca-49d2-9ce0-4526687fb310
    /alfresco-access/transaction/move/from/path=/app:company_home/st:sites/cm:fred/cm:documentLibrary/cm:folder1/cm:Word 123.docx
    /alfresco-access/transaction/move/from/type=cm:folder
    /alfresco-access/transaction/path=/app:company_home/st:sites/cm:fred/cm:documentLibrary/cm:Word 123.docx
    /alfresco-access/transaction/sub-action/00/action=moveNode
    /alfresco-access/transaction/sub-action/00/move/from/node=workspace://SpacesStore/a82446e9-4dca-49d2-9ce0-4526687fb310
    /alfresco-access/transaction/sub-action/00/move/from/path=/app:company_home/st:sites/cm:fred/cm:documentLibrary/cm:folder1/cm:Word 123.docx
    /alfresco-access/transaction/sub-action/00/move/from/type=cm:folder
    /alfresco-access/transaction/sub-action/01/action=readContent
    /alfresco-access/transaction/sub-actions=moveNode readContent
    /alfresco-access/transaction/type=cm:content
    /alfresco-access/transaction/user=admin
Parent topic: Content auditing customizations [28]

Sample files

Audit sample files are distributed in the <TOMCAT_HOME>/classes/alfresco/extension/audit directory.

Samples can also be downloaded directly from the following location in svn:

http://svn.alfresco.com/repos/alfresco-open-mirror/alfresco/HEAD/root/projects/repository/config/alfresco/extension/audit/

When using a sample file, remove the .sample extension.

Parent topic: Auditing Alfresco [21]

Enabling auditing

Generation of audit data is disabled by default. To enable auditing permanently, settings must be added to the Alfresco global properties file as shown in the following text.

To enable auditing permanently, add the following settings to the alfresco-global.properties file:

audit.alfresco-access.enabled=true  
Note:

Auditing is enabled by default. The audit.enabled property provides a way to globally enable or disable the auditing framework. However, enabling this property does not necessarily result in the generation of audit data.

To enable generation of audit data that you can view in Explorer or Share, you will need to enable the audit.alfresco-access.enabled property.

Once changes to the global properties file have been saved, you will need to restart the Alfresco server, for auditing to be fully enabled.

You can check the status of auditing conveniently from the command line by using a tool such as curl to access the Audit Control web script.

To check the global status of auditing issue a command such as:

curl -u admin:password "http://localhost:8080/alfresco/service/api/audit/control"      

This invokes the web script with a GET request. This will result in a JSON response such as the following if auditing is currently enabled:

{
   "enabled" : true,
   "applications": 
   [
      {
         "name": "Alfresco Tagging Service",
         "path" : "/tagging",
         "enabled" : true
      }
         ,
      {
         "name": "alfresco-access",
         "path" : "/alfresco-access",
         "enabled" : true
      }
         
   ]
}
    

While this does return the global status of the auditing framework, audit data will only be generated if audit.alfresco-access.enabled is enabled.

If auditing is currently disabled the response will be:

{
   "enabled" : false
}  

In this case no audit data will be generated as the audit framework is disabled.

Auditing can also be globally enabled or disabled using the control web script. To do this a POST request is sent to the web script. For example, using curl, auditing can be enabled using the following command:

curl -u admin:password -d "" "http://localhost:8080/alfresco/service/api/audit/control?enable=true"

This results in the following response:

{
   "enabled" : true
}  

To disable auditing issue the following command:

curl -u admin:password -d "" "http://localhost:8080/alfresco/service/api/audit/control?enable=false"

This results in the following response:

{
   "enabled" : false
}  

While the global status of the auditing framework can be switched on and off in this manner, audit data will only be generated if audit.alfresco-access.enabled is enabled in the global properties file.

Note: Enabling or disabling auditing using the Audit Control web script only remains valid in force while the server is running; the setting will not be retained following a server restart, but will subsequently be set according to the values in alfresco-global.properties.

Using JMX to control auditing

A JMX client can be used to access global properties. The properties can be modified using the JMX client. A server restart will be required for changes to properties to take effect.

Parent topic: Auditing Alfresco [21]

Auditing examples

This section describes some auditing examples.

Audit data passed to recordAuditValues():
Root path:
   /alfresco-api/post/NodeService/createStore
Map:
   args/protocol = "workspace"
   args/identifier = "SpacesStore"
   result = StoreRef[workspace://SpacesStore]

If the root path passes the initial filtration phase - there is at least one component interested in auditing the information - then the map is expanded.

Expanded audit data:
Map:
   /alfresco-api/post/NodeService/createStore/args/protocol = "workspace"
   /alfresco-api/post/NodeService/createStore/args/identifier = "SpacesStore"
   /alfresco-api/post/NodeService/createStore/result = StoreRef[workspace://SpacesStore]

The filtered data is then passed through the path mappings, generating a new ''Map'' of data for each application.

Path-mapped audit data:
Map:
   /MyApp/createStore = StoreRef[workspace://SpacesStore]

This data is then passed to any extractors and generators to produce a final ''Map'' of data that will be persisted.

Persisted audit data:
Map:
   /MyApp/createStore/value = StoreRef[workspace://SpacesStore]
   /MyApp/createStore/rootNode = NodeRef[workspace://SpacesStore/fd123...]
Parent topic: Auditing Alfresco [21]

Audit configuration files

This section describes the location and basic structure of the audit configuration files.

Audit configuration files are picked up automatically using the following search paths.

  • classpath*:alfresco/audit/*.xml
  • classpath*:alfresco/enterprise/audit/*.xml
  • classpath*:alfresco/module/*/audit/*.xml
  • classpath*:alfresco/extension/audit/*.xml

The XML schema is located at <configRoot>/classes/alfresco/audit/alfresco-audit-3.2.xsd.

The configuration file structure is divided into four basic sections:

<DataExtractors>
In this section, DataExtractors are declared for use in the <Application> sections of the configuration files. A DataExtractor is a component that uses input data to produce some output, either transforming the data or outputting the data verbatim. The simplest extractor is the SimpleValueDataExtractor, which returns whatever data is passed in. A more complex extractor is the NodeNameDataExtractor, which is able to produce the cm:name value of a node, assuming the data passed in is a NodeRef. For the complete set of built-in generators, see the org.alfresco.repo.audit.extractor package, or the auditModel.extractor.* beans, which are declared in alfresco/audit-services-context.xml.
The extractors can be declared in-line, for example:
    <DataExtractors>
       <DataExtractor name="simpleValue" class="org.alfresco.repo.audit.extractor.SimpleValueDataExtractor"/>
       ...
    </DataExtractors>
Or they can be declared in Spring configuration and referenced in the audit configuration (see the alfresco/audit-services-context.xml file), for example:
    <DataExtractors>
       <DataExtractor name="simpleValue" registeredName="auditModel.extractor.simpleValue"/>
       ...
    </DataExtractors>
<DataGenerators>
In this section, DataGenerators are declared for use in the <Application> sections of the configuration files. A DataGenerator is a component that produces data without any input, that is, data is produced when a data path is active, but is independent of the values at that path. Examples of generators are the AuthenticatedUserDataGenerator component, which produces the name of the currently-authenticated user (user in context) and the AuthenticatedPersonDataGenerator component, which produces the full name of the currently-authenticated user (person in context). For the complete set of built-in generators, see the org.alfresco.repo.audit.generator package or the auditModel.generator.* beans, which are declared in the alfresco/audit-services-context.xml file.
The generators can be declared in-line, for example:
    <DataGenerators>
       <DataGenerator name="currentUser" class="org.alfresco.repo.audit.generator.AuthenticatedUserDataGenerator"/>
       <DataGenerator name="personFullName" class="org.alfresco.repo.audit.generator.AuthenticatedPersonDataGenerator"/>
    </DataGenerators>
Or they can be declared in Spring configuration and referenced in the audit configuration (see the alfresco/audit-services-context.xml file), for example:
    <DataGenerators>
       <DataGenerator name="currentUser" registeredName="auditModel.generator.user"/>
       <DataGenerator name="personFullName" registeredName="auditModel.generator.personFullName"/>
    </DataGenerators>
<PathMappings>
The expanded map coming from the Data Producers is passed through the path mappings. This is a raw remapping of the input data based on the path names in the data map.
    <PathMappings>
        <PathMap source="/DOD5015" target="/DOD5015"/>
        <!-- Force the fullName generator to trigger -->
        <PathMap source="/DOD5015/event/node" target="/DOD5015/event/person"/>
        <PathMap source="/alfresco-api/post/AuthenticationService/authenticate" target="/DOD5015/login"/>
    </PathMappings>

In this example, all paths starting with /DOD5015 are mapped verbatim, but without the declaration, the data paths starting with /DOD5015 are discarded. A small subset of the Alfresco API data is used (only the AuthenticationService.authenticate call) by mapping all values starting with that path to /DOD5015/login.

<Application>
This section defines how the mapped data is to be used by DataGenerators or by DataExtractors.
    <Application name="DOD5015" key="DOD5015">
        <AuditPath key="login">
            <AuditPath key="args">
                <AuditPath key="userName">
                    <RecordValue key="value" dataExtractor="simpleValue"/>
                </AuditPath>
            </AuditPath>
            <AuditPath key="no-error">
                <GenerateValue key="fullName" dataGenerator="personFullName"/>
            </AuditPath>
            <AuditPath key="error">
                <RecordValue key="value" dataExtractor="nullValue"/>
            </AuditPath>
        </AuditPath>
    </Application>
Parent topic: Auditing Alfresco [21]

Built-in data producers

The following are built-in data producers.

  • org.alfresco.repo.audit.AuditMethodInterceptor: Generates audit data for all public service API calls. Refer to the javadocs for the data structure.
  • org.alfresco.repo.node.NodeAuditor: Generates audit data for beforeDeleteNode

It is possible for any server-side component to pass data to the auditComponent bean.

To see what information is available to audit, enable the following logging:
log4j.logger.org.alfresco.repo.audit.inbound=DEBUG
The following is an example of output generated when a node is deleted from Alfresco Explorer:
15:55:26,590 User:admin DEBUG [repo.audit.inbound] 
Inbound audit values:
	/alfresco-node/beforeDeleteNode/node=workspace://SpacesStore/c4728f24-4a11-40f7-9062-315edf959d79
15:55:26,748 User:admin DEBUG [repo.audit.inbound] 
Inbound audit values:
	/alfresco-api/post/NodeService/deleteNode/no-error=null
	/alfresco-api/post/NodeService/deleteNode/args/nodeRef=workspace://SpacesStore/c4728f24-4a11-40f7-9062-315edf959d79
Parent topic: Auditing Alfresco [21]

DataExtractors and DataGenerators

This section provides a description of DataExtractors and DataGenerators.

It is possible for any server-side component to pass data to the auditComponent bean.

DataExtractor
Uses an inbound mapped value as the source of the data. AuditExampleLogin1 records values quite literally using the simpleValue data extractor.
DataGenerator
Activates when an inbound mapped path is present, but is not dependent on the value on that path. AuditExampleLogin2 triggers the personFullName generator when the authenticate/no-error path is present; this records the full name of the currently-authenticated user even though the inbound data for authenticate/no-error is null.

Look at the data recorded for the two sample applications:

% curl -u admin:admin "http://localhost:8080/alfresco/service/api/audit/query/AuditExampleLogin1?verbose=true&forward=false&limit=1"
{
   "count":1,
   "entries": 
   [
      {
         "id":137,
         "application":AuditExampleLogin1,
         "user":admin,
         "time":"2010-09-20T17:37:14.699+01:00",
         "values":
         {
                     "\/auditexamplelogin1\/login\/no-error\/user":"admin"
         }
         
      }
   ]
}
% curl -u admin:admin "http://localhost:8080/alfresco/service/api/audit/query/AuditExampleLogin2?verbose=true&forward=false&limit=1"
{
   "count":1,
   "entries": 
   [
      {
         "id":138,
         "application":AuditExampleLogin2,
         "user":admin,
         "time":"2010-09-20T17:37:23.101+01:00",
         "values":
         {
                     "\/auditexamplelogin2\/login\/user":"Administrator"
         }
         
      }
   ]
}
Parent topic: Auditing Alfresco [21]

Locating the audit code

This section describes the location of audit code.
  1. For DEBUG logging, to see which data is being produced, rejected, or recorded, enable DEBUG for:

    log4j.logger.org.alfresco.repo.audit.AuditComponentImpl=DEBUG
  2. For JUnit code, the unit test code demonstrates use of the Audit APIs and configuration:

    org.alfresco.repo.audit.AuditComponentTest
    • alfresco-audit-test-authenticationservice.xml: This is used by the test to capture both successful and unsuccessful login attempts in the audit data.
    • testAuditAuthenticationService: This demonstrates the use of the auditSearch method.
  3. For Records Management (DOD5015) and auditing, the module pulls in audit data from the 'AuthenticationService' but adds more data around the individual actions that take place during Records Management processes.

    org.alfresco.module.org_alfresco_module_dod5015.audit.*
    • RecordsManagementAuditServiceImpl$RMAuditTxnListener: This transaction listener generates Records Management-specific data for events (it is a Data Producer). It generates node property deltas.
    • config/alfresco/module/org_alfresco_module_dod5015/audit/rm-audit.xml: This defines how the data produced by the AuthenticationService and the Records Management module is persisted. There are some custom DataGenerators and DataRecorders.
    • RecordsManagementAuditServiceImpl.getAuditTrailImpl: This method demonstrates how the Records Management use-case searches the audit data. Further query extensions are required to extend the search filters available using the auditQuery API.
Parent topic: Auditing Alfresco [21]

Defining the audit application

This section describes the audit applications.
Data producers have no knowledge of how or whether data will be stored. Different use cases need to store or modify inbound data independently, therefore the use cases are separated into audit applications. Each application defines how data is mapped, extracted, and recorded without affecting data required by other applications.

For example, the Records Management module records before and after values when specific nodes are modified, whereas the CMIS standard requires a slightly different set of data to be recorded. Additionally, each of the audit logs can be enabled and disabled independently within the same server. Usually, each audit application is defined in its own configuration file, but for demonstration purposes, multiple application definitions can be defined in one configuration file.

  1. Enable the sample file by removing the .sample extension.

    alfresco/extensions/audit/alfresco-audit-example-login.xml.sample

  2. Restart the Alfresco server.
  3. Ensure that the applications have been registered properly and are enabled:

    % curl -u admin:admin "http://localhost:8080/alfresco/service/api/audit/control"
    {
       "enabled" : true,
       "applications": 
       [
          {
             "name": "AuditExampleLogin1",
             "path" : "/auditexamplelogin1",
             "enabled" : true
          }
             ,
          {
             "name": "AuditExampleLogin2",
             "path" : "/auditexamplelogin2",
             "enabled" : true
          }
             ,
          {
             "name": "CMISChangeLog",
             "path" : "/CMISChangeLog",
             "enabled" : true
          }
             
       ]
    }
  4. At an application level, auditing is enabled or disabled for specific paths; changes made to an application's audit state are persisted. To disable all auditing for an application, disable the root path; in this case, disable the root path for the CMISChangeLog application. If you restart the server you will see that the application remains disabled.

    % curl -u admin:admin -d "" "http://localhost:8080/alfresco/service/api/audit/control/CMISChangeLog/CMISChangeLog?enable=false"
    {
       "enabled" : false
    }
Parent topic: Auditing Alfresco [21]

Simple audit query

This section describes a simple audit query example.
  1. Generate some auditing data for the sample applications.
  2. Connect to the Alfresco Explorer client.
  3. Login as the admin user.
  4. Logout of Alfresco.
  5. Login as the admin user but use an illegal password.

    The following examples are two queries to return results: without and with full-audited values respectively. Some entries have been replaced with a (...) for brevity.

    % curl -u admin:admin "http://localhost:8080/alfresco/service/api/audit/query/AuditExampleLogin1"
    {
       "count":4,
       "entries": 
       [
          {
             "id":69,
             "application":AuditExampleLogin1,
             "user":admin,
             "time":"2010-09-20T14:45:28.998+01:00",
             "values":
    null
          },
          ...
       ]
    }
    % curl -u admin:admin "http://localhost:8080/alfresco/service/api/audit/query/AuditExampleLogin1?verbose=true"
    {
       "count":5,
       "entries": 
       [
          ...
          {
             "id":72,
             "application":AuditExampleLogin1,
             "user":null,
             "time":"2010-09-20T14:45:43.884+01:00",
             "values":
             {
                         "\/auditexamplelogin1\/login\/error\/user":"admin"
             }
             
          },
          ...
          {
             "id":76,
             "application":AuditExampleLogin1,
             "user":admin,
             "time":"2010-09-20T14:46:23.319+01:00",
             "values":
             {
                         "\/auditexamplelogin1\/login\/no-error\/user":"admin"
             }
             
          }
       ]
    }

    There is no count function in the search API. This is by design; use the limit parameter instead.

  6. Assume that a client wants to see the details of the latest two results but knows of the existence of the next eight results. In this case, it would be pointless pulling back full (verbose=true) results for the latest 10 entries. Instead, pull back the last two results with values and then pull back the next eight results without values.

    Notice that the response contains a count of the number of entries returned; the individual entries are provided so that the entry IDs can be used for further result retrieval.

    % curl -u admin:admin "http://localhost:8080/alfresco/service/api/audit/query/AuditExampleLogin1?verbose=true&limit=2&forward=false"
    {
       "count":2,
       "entries": 
       [
          {
             "id":98,
             "application":AuditExampleLogin1,
             "user":admin,
             "time":"2010-09-20T15:10:04.043+01:00",
             "values":
             {
                         "\/auditexamplelogin1\/login\/no-error\/user":"admin"
             }
             
          },
          {
             "id":96,
             "application":AuditExampleLogin1,
             "user":admin,
             "time":"2010-09-20T15:09:50.117+01:00",
             "values":
             {
                         "\/auditexamplelogin1\/login\/no-error\/user":"admin"
             }
             
          }
       ]
    }
    % curl -u admin:admin "http://localhost:8080/alfresco/service/api/audit/query/AuditExampleLogin1?verbose=false&limit=8&forward=false&toId=96"
    {
       "count":8,
       "entries": 
       [
          {
             "id":94,
             "application":AuditExampleLogin1,
             "user":admin,
             "time":"2010-09-20T15:09:47.606+01:00",
             "values":
    null
          },
          ...
          {
             "id":80,
             "application":AuditExampleLogin1,
             "user":admin,
             "time":"2010-09-20T14:58:34.305+01:00",
             "values":
    null
          }
       ]
    }
Parent topic: Auditing Alfresco [21]

Advanced audit query

This section describes an advanced audit query example.
This type of query URL makes use of a data path within the audit application. This allows entries to be found that match specific audited values. By default, query values are treated as case-sensitive string types, but it is possible to specify the type to query against.
  1. Generate some audit data.
  2. Connect to the Alfresco Explorer client.
  3. Attempt a failed login as joe.

    % curl -u admin:admin "http://localhost:8080/alfresco/service/api/audit/query/AuditExampleLogin1/auditexamplelogin1/login/error/user?verbose=true&value=joe"
    {
       "count":1,
       "entries": 
       [
          {
             "id":101,
             "application":AuditExampleLogin1,
             "user":null,
             "time":"2010-09-20T15:13:57.947+01:00",
             "values":
             {
                         "\/auditexamplelogin1\/login\/error\/user":"joe"
             }
             
          }
       ]
    }
    % curl -u admin:admin "http://localhost:8080/alfresco/service/api/audit/query/AuditExampleLogin1/auditexamplelogin1/login/error/user?verbose=true&value=JOE"
    {
       "count":0,
       "entries": 
       [
       ]
    }
Parent topic: Auditing Alfresco [21]

Understanding PathMappings

To create an audit configuration file, it is necessary to know which data can be audited and how the data is mapped onto your application.
  1. Turn on debugging for the inbound data. For a better understanding, you can turn on debug logging for the mapping components as well, although this is more verbose.

    % cat <tomcatgt/shared/classes/alfresco/extension/audit-log4j.properties 
    log4j.logger.org.alfresco.repo.audit.AuditComponentImpl=DEBUG
    log4j.logger.org.alfresco.repo.audit.inbound=DEBUG
  2. Tail the log file and watch the output.
    1. Login as admin.

      16:47:37,434  DEBUG [repo.audit.inbound] 
      Inbound audit values:
      	/alfresco-api/pre/AuthenticationService/authenticate/args/userName=admin
      16:47:37,443 User:admin DEBUG [repo.audit.inbound] 
      Inbound audit values:
      	/alfresco-api/post/AuthenticationService/authenticate/no-error=null
      	/alfresco-api/post/AuthenticationService/authenticate/args/userName=admin
    2. From the inbound values (and if you have the AuditComponentImpl debugging on):

      16:47:37,445 User:System DEBUG [repo.audit.AuditComponentImpl] Extracted audit data: 
         Application: AuditApplication[ name=AuditExampleLogin2, id=7, disabledPathsId=7]
         Raw values:  {/auditexamplelogin2/login=null}
         Extracted:   {}
      16:47:37,447 User:admin DEBUG [repo.audit.AuditComponentImpl] New audit entry: 
         Application ID: 7
         Entry ID:       130
         Values:         {/auditexamplelogin2/login=null}
         Audit Data:     {/auditexamplelogin2/login/user=Administrator}
      16:47:37,447 User:System DEBUG [repo.audit.AuditComponentImpl] Extracted audit data: 
         Application: AuditApplication[ name=AuditExampleLogin1, id=6, disabledPathsId=6]
         Raw values:  {/auditexamplelogin1/login/no-error=null, /auditexamplelogin1/login/args/userName=admin}
         Extracted:   {/auditexamplelogin1/login/no-error/user=admin}
      16:47:37,449 User:admin DEBUG [repo.audit.AuditComponentImpl] New audit entry: 
         Application ID: 6
         Entry ID:       131
         Values:         {/auditexamplelogin1/login/no-error=null, /auditexamplelogin1/login/args/userName=admin}
         Audit Data:     {/auditexamplelogin1/login/no-error/user=admin}

      You can see that the AuthenticationService.authenticate method generate two sets of "inbound" data: the /alfresco-api/pre/AuthenticationService/authenticate data is passed through before the service call is processed; the /alfresco-api/post/AuthenticationService/authenticate data is passed through after the service call has been processed. When logging in successfully, the post-call data is generated with a no-error path.

    3. Perform a failed login with user joe.

      17:02:09,697  DEBUG [repo.audit.inbound] 
      Inbound audit values:
      	/alfresco-api/pre/AuthenticationService/authenticate/args/userName=joe
      17:02:09,704  DEBUG [repo.audit.inbound] 
      Inbound audit values:
      	/alfresco-api/post/AuthenticationService/authenticate/error=08200014 Failed to authenticate 
         Started at: 
            org.alfresco.repo.security.authentication.AbstractChainingAuthenticationService.authenticate(AbstractChainingAuthenticationService.java:188)
            ...

      This is translated and recorded:

      17:02:09,704 User:System DEBUG [repo.audit.AuditComponentImpl] Extracted audit data: 
         Application: AuditApplication[ name=AuditExampleLogin1, id=6, disabledPathsId=6]
         Raw values:  {/auditexamplelogin1/login/error=08200014 Failed to authenticate 
         Started at: 
            org.alfresco.repo.security.authentication.AbstractChainingAuthenticationService.authenticate(AbstractChainingAuthenticationService.java:188)
            ...
      17:02:09,704  DEBUG [repo.audit.AuditComponentImpl] New audit entry: 
         Application ID: 6
         E6try ID:       135
         Values:         {/auditexamplelogin1/login/error=08200016 Failed to authenticate 
         Started at: 
            org.alfresco.repo.security.authentication.AbstractChainingAuthenticationService.authenticate(AbstractChainingAuthenticationService.java:188)
            ...
         Audit Data:     {/auditexamplelogin1/login/error/user=joe}
    4. Notice that the failed login did not generate any data for audit application AuditExampleLogin2. To understand this, look at the PathMappings section of the example:

      <PathMappings>
              <PathMap source="/alfresco-api/post/AuthenticationService/authenticate" target="/auditexamplelogin1/login"/>
              <PathMap source="/alfresco-api/post/AuthenticationService/authenticate/no-error" target="/auditexamplelogin2/login"/>
          </PathMappings>

      Before any data is considered for persistence, the inbound data paths are remapped using the PathMappings configuration. The /auditexamplelogin2/login path is mapped onto .../no-error only, so failed logins were not recorded for the AuditExampleLogin2 audit application, while the AuditExampleLogin1 application recorded both successful and failed logins.

Parent topic: Auditing Alfresco [21]

Audit recording values

The RecordValue element makes use of the DataExtractor definitions, but specifies when to be activated (dataTrigger) and where to get the data from (dataSource). Both the dataTrigger and dataSource attributes default to the path of the RecordValue element. Data is always written to the path where the RecordValue is declared. So, it is possible to trigger the RecordValue when a data path is present (such as a null value) and then to read a value from a completely different location.
  1. Activate sample /audit/alfresco-audit-example-extractors.xml file.
  2. Restart Alfresco (or restart the Audit subsystem).
  3. Tail the log to capture createNode calls:

    tail -f ../logs/catalina.out | grep -G "createNode" -A 200 -B 20
  4. Login to explorer and add some content under Company Home.

    20:18:52,817 User:admin DEBUG [repo.audit.AuditComponentImpl] 
    New audit entry: 
    	Application ID: 8
    	Entry ID:       177
    	Values:         
    		/auditexampleextractors/args/properties=...
    		/auditexampleextractors/args/assocQName={http://www.alfresco.org/model/content/1.0}alfresco.log
    		/auditexampleextractors/args/parentRef=workspace://SpacesStore/37884669-0607-4527-940d-cb34b4f07d75
    		/auditexampleextractors/no-error=null
    		/auditexampleextractors/args/assocTypeQName={http://www.alfresco.org/model/content/1.0}contains
    		/auditexampleextractors/args/nodeTypeQName={http://www.alfresco.org/model/content/1.0}content
    		/auditexampleextractors/result=workspace://SpacesStore/37884669-0607-4527-940d-cb34b4f07d75|workspace://SpacesStore/c0fabc6d-903f-4317-87d1-ec62de37089c|...
    	Audit Data: 
    		/auditexampleextractors/create/out/a=workspace://SpacesStore/37884669-0607-4527-940d-cb34b4f07d75|workspace://SpacesStore/c0fabc6d-903f-4317-87d1-ec62de37089c|...
    		/auditexampleextractors/create/derived/parent-node-name=Company Home
    		/auditexampleextractors/create/derived/parent-node-null=null
    		/auditexampleextractors/create/in/c={http://www.alfresco.org/model/content/1.0}contains
    		/auditexampleextractors/create/in/d={http://www.alfresco.org/model/content/1.0}alfresco.log
    		/auditexampleextractors/create/in/a=workspace://SpacesStore/37884669-0607-4527-940d-cb34b4f07d75
    		/auditexampleextractors/create/derived/parent-node-type={http://www.alfresco.org/model/content/1.0}folder
    		/auditexampleextractors/create/in/b={http://www.alfresco.org/model/content/1.0}content
  5. View the audited data using the query API:

    % curl -u admin:admin "http://localhost:8080/alfresco/service/api/audit/query/AuditExampleExtractors?limit=1&forward=false&verbose=true"
    {
       "count":1,
       "entries": 
       [
          {
             "id":177,
             "application":AuditExampleExtractors,
             "user":admin,
             "time":"2010-09-20T20:18:52.761+01:00",
             "values":
             {
                         "\/auditexampleextractors\/create\/out\/a":"workspace:\/\/SpacesStore\/37884669-0607-4527-940d-cb34b4f07d75|workspace:\/\/SpacesStore\/c0fabc6d-903f-4317-87d1-ec62de37089c|...
                         ,"\/auditexampleextractors\/create\/derived\/parent-node-name":"Company Home"
                         ,"\/auditexampleextractors\/create\/in\/c":"{http:\/\/www.alfresco.org\/model\/content\/1.0}contains"
                         ,"\/auditexampleextractors\/create\/in\/d":"{http:\/\/www.alfresco.org\/model\/content\/1.0}alfresco.log"
                         ,"\/auditexampleextractors\/create\/in\/a":"workspace:\/\/SpacesStore\/37884669-0607-4527-940d-cb34b4f07d75"
                         ,"\/auditexampleextractors\/create\/derived\/parent-node-type":"{http:\/\/www.alfresco.org\/model\/content\/1.0}folder"
                         ,"\/auditexampleextractors\/create\/in\/b":"{http:\/\/www.alfresco.org\/model\/content\/1.0}content"
             }
             
          }
       ]
    }

    The /no-error path was used as the dataTrigger to activate all the RecordValue elements, that is, the presence of the path triggered the data rather than any specific value. /create/derived/... audit values show how the parent node reference was used to record values that were not part of the inbound data set.

Using the example, to search for values that are not strings, use the following:
% curl -u admin:admin "http://localhost:8080/alfresco/service/api/audit/query/AuditExampleExtractors/ \
                 auditexampleextractors/create/derived/parent-node-type?                              \
                 valueType=org.alfresco.service.namespace.QName&                                      \
                 value=%7Bhttp://www.alfresco.org/model/content/1.0%7Dfolder"
{
   "count":1,
   "entries": 
   [
      {
         "id":177,
         "application":AuditExampleExtractors,
         "user":admin,
         "time":"2010-09-20T20:18:52.761+01:00",
         "values":
null
      }
   ]
}

% curl -u admin:admin "http://localhost:8080/alfresco/service/api/audit/query/AuditExampleExtractors/ \
                 auditexampleextractors/create/in/a?                                                  \
                 valueType=org.alfresco.service.cmr.repository.NodeRef&                               \
                 value=workspace://SpacesStore/37884669-0607-4527-940d-cb34b4f07d75"
{
   "count":1,
   "entries": 
   [
      {
         "id":177,
         "application":AuditExampleExtractors,
         "user":admin,
         "time":"2010-09-20T20:18:52.761+01:00",
         "values":
null
      }
   ]
}
Note: It is not possible to restrict results to a specific value path. The path AND the value are enough to return a result. This does not usually yield duplicate results but it is not as restrictive as it should be. For example, generate the audit data and query for verbose output. Choose to search based on a path and a value and check that you get the correct number of results. Now choose a different path in the value list and query with that, that is, use a path and value that are not related.
Parent topic: Auditing Alfresco [21]

Using values that have changed in a post method call

When using the org.alfresco.repo.audit.AuditMethodInterceptor Data Producer, which generates audit data for all public service API calls, it is sometimes useful to be able to audit before and after values in a 'post' call application, or to include values from before the call.
For example, the nodeName data extractor may only be called on a node that exists, so calling it after a delete has no effect.
The output of 'pre' call applications is available to 'post' call applications, which can be seen in the following example. The example shows auditing the deletion of nodes and includes the node name. The nodeName is evaluated in the 'pre' call application and copied in the 'post' call application.
<?xml version='1.0' encoding='UTF-8'?>
<Audit
  xmlns="http://www.alfresco.org/repo/audit/model/3.2"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://www.alfresco.org/repo/audit/model/3.2 alfresco-audit-3.2.xsd" >

  <DataExtractors>
    <DataExtractor name="simpleValue" registeredName="auditModel.extractor.simpleValue"/>
    <DataExtractor name="nodeNameValue" registeredName="auditModel.extractor.nodeName"/>
  </DataExtractors>

  <PathMappings>
    <PathMap source="/alfresco-api/pre/NodeService/deleteNode" target="/preDelete" />
    <PathMap source="/alfresco-api/post/NodeService/deleteNode" target="/postDelete" />
  </PathMappings>

  <Application name="PreCallDataDelete" key="preDelete">
    <RecordValue key="nodeName" dataExtractor="nodeNameValue" dataSource="/preDelete/args/nodeRef" dataTrigger="/preDelete/args/nodeRef" />
  </Application>

  <Application name="PostDelete" key="postDelete">
    <RecordValue key="error" dataExtractor="simpleValue" dataSource="/postDelete/error" dataTrigger="/postDelete/error" />
    <AuditPath key="deleteDetails">
      <RecordValue key="deletedNodeRef" dataExtractor="simpleValue" dataSource="/postDelete/args/nodeRef" dataTrigger="/postDelete/args/nodeRef" />
      <RecordValue key="nodeName" dataExtractor="simpleValue" dataSource="/postDelete/preCallData/preDelete/nodeName" dataTrigger="/postDelete/preCallData/preDelete/nodeName" />
    </AuditPath>
  </Application>

</Audit>
        
Note: The dataSource attribute of the final <RecordValue> element includes the output path of the 'pre' call application ("preDelete/nodeName"). This is prefixed by preCallData/ much like the args/ prefix for method arguments. To avoid 'pre' call applications from generating audit records themselves, rather than just generating output for the 'post' call applications, give them a name that starts with PreCallData.
Parent topic: Auditing Alfresco [21]

Source URL: https://docs.alfresco.com/4.2/concepts/audit-intro.html

Links:
[1] https://docs.alfresco.com/../concepts/audit-config-env.html
[2] https://docs.alfresco.com/../concepts/audit-filters.html
[3] https://docs.alfresco.com/../concepts/audit-content.html
[4] https://docs.alfresco.com/../concepts/audit-worked-samples.html
[5] https://docs.alfresco.com/../tasks/audit-config.html
[6] https://docs.alfresco.com/../concepts/audit-examples.html
[7] https://docs.alfresco.com/../concepts/audit-config-files.html
[8] https://docs.alfresco.com/../concepts/audit-builtin-dataproducers.html
[9] https://docs.alfresco.com/../concepts/audit-extract-gens.html
[10] https://docs.alfresco.com/../tasks/audit-builtin-dataprod.html
[11] https://docs.alfresco.com/../tasks/audit-application.html
[12] https://docs.alfresco.com/../tasks/audit-simple-query.html
[13] https://docs.alfresco.com/../tasks/audit-advanced-query.html
[14] https://docs.alfresco.com/../tasks/audit-pathmappings.html
[15] https://docs.alfresco.com/../tasks/audit-recording-values.html
[16] https://docs.alfresco.com/../tasks/audit-post-method-call.html
[17] https://docs.alfresco.com/../concepts/ch-administering.html
[18] http://localhost:8080/alfresco/service/
[19] http://localhost:8080/alfresco/service/index/package/org/alfresco/repository/audit
[20] https://docs.alfresco.com/prop-tables.html
[21] https://docs.alfresco.com/../concepts/audit-intro.html
[22] https://docs.alfresco.com/../concepts/audit-40-example-rootpath.html
[23] https://docs.alfresco.com/../concepts/audit-40-example-filter.html
[24] https://docs.alfresco.com/../concepts/audit-40-redirected-props.html
[25] https://docs.alfresco.com/../concepts/audit-40-debug-info.html
[26] https://docs.alfresco.com/../concepts/audit-40-custom.html
[27] https://docs.alfresco.com/../concepts/audit-content-techdesc.html
[28] https://docs.alfresco.com/../concepts/audit-cust.html
[29] https://docs.alfresco.com/../tasks/audit-content-example.html
[30] https://docs.alfresco.com/../tasks/audit-content-explorer.html
[31] https://docs.alfresco.com/../tasks/audit-enable.html
[32] https://docs.alfresco.com/../concepts/audit-filter-settings.html
[33] https://docs.alfresco.com/../concepts/audit-accessauditer.html
[34] https://docs.alfresco.com/../concepts/audit-persisted.html
[35] https://docs.alfresco.com/audit-filters.html
[36] https://docs.alfresco.com/../concepts/audit-cust-auditfilter.html
[37] https://docs.alfresco.com/../concepts/audit-cutom-audit-config.html