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.
This section describes the configuration and environment settings for auditing.
Configuration and environment | Details |
---|---|
Tomcat environment |
|
View the available web scripts and details | Use the following scripts:
|
HTTP client |
|
Sample files |
|
% 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].
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.
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"
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 '\'.
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
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
If you are using the Tomcat web application server, add the additional properties to the <tomcat>/shared/classes/alfresco-global.properties file.
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.
The following is an example audit trail.
The user actions from the Share interface were:
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
The audit trail of individual content may be viewed from within Alfresco Explorer.
The following is an example of some high level events.
This section describes how to enable auditing of these events and sub events
# 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
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.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:;.*
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.
/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 ...
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
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.
/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.
There are two customizations available:
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.
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.
<?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>
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
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.
To enable auditing permanently, add the following settings to the alfresco-global.properties file:
audit.alfresco-access.enabled=true
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.
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.
This section describes some auditing examples.
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.
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.
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.
Map: /MyApp/createStore/value = StoreRef[workspace://SpacesStore] /MyApp/createStore/rootNode = NodeRef[workspace://SpacesStore/fd123...]
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.
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> <DataExtractor name="simpleValue" class="org.alfresco.repo.audit.extractor.SimpleValueDataExtractor"/> ... </DataExtractors>
<DataExtractors> <DataExtractor name="simpleValue" registeredName="auditModel.extractor.simpleValue"/> ... </DataExtractors>
<DataGenerators> <DataGenerator name="currentUser" class="org.alfresco.repo.audit.generator.AuthenticatedUserDataGenerator"/> <DataGenerator name="personFullName" class="org.alfresco.repo.audit.generator.AuthenticatedPersonDataGenerator"/> </DataGenerators>
<DataGenerators> <DataGenerator name="currentUser" registeredName="auditModel.generator.user"/> <DataGenerator name="personFullName" registeredName="auditModel.generator.personFullName"/> </DataGenerators>
<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 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>
The following are built-in data producers.
It is possible for any server-side component to pass data to the auditComponent bean.
log4j.logger.org.alfresco.repo.audit.inbound=DEBUG
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
This section provides a description of DataExtractors and DataGenerators.
It is possible for any server-side component to pass data to the auditComponent bean.
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" } } ] }
log4j.logger.org.alfresco.repo.audit.AuditComponentImpl=DEBUG
org.alfresco.repo.audit.AuditComponentTest
org.alfresco.module.org_alfresco_module_dod5015.audit.*
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.
alfresco/extensions/audit/alfresco-audit-example-login.xml.sample
% 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 } ] }
% curl -u admin:admin -d "" "http://localhost:8080/alfresco/service/api/audit/control/CMISChangeLog/CMISChangeLog?enable=false" { "enabled" : false }
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.
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 } ] }
% 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": [ ] }
% 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
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
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.
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}
<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.
tail -f ../logs/catalina.out | grep -G "createNode" -A 200 -B 20
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
% 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.
% 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 } ] }
<?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>
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