03-01-2017 05:01 PM
I know that I can capture the event of a user being manually added to Alfresco though the Admin Tools page in Share by auditing for a PathMap source of "/alfresco-api/post/PersonService/createPerson".
Users are typically added by an AD LDAP synchronization, however, and I can't see what event is being triggered.
An Alfresco user IS getting created after a synch. Should I be looking for something else, like membership add to a group?
I am setting the log setting of 'org.alfresco.repo.audit.inbound' to DEBUG, but am not seeing anything for that user. Any other log settings to try?
Thanks All!
03-02-2017 04:54 AM
The same kind of API is also used during synchronisation, e.g. createPerson call is being made. Unfortunately, the person service is used in such a way that Auditing is circumvented in this use case (by using "personService" bean reference instead of "PersonService").
You could still react to the event of a person being created by using a policy which is unaffected by the choice of bean reference. A policy can be used to record your own data for Auditing. That is e.g. the way that alfresco-access works.
03-02-2017 04:54 AM
The same kind of API is also used during synchronisation, e.g. createPerson call is being made. Unfortunately, the person service is used in such a way that Auditing is circumvented in this use case (by using "personService" bean reference instead of "PersonService").
You could still react to the event of a person being created by using a policy which is unaffected by the choice of bean reference. A policy can be used to record your own data for Auditing. That is e.g. the way that alfresco-access works.
03-06-2017 10:17 AM
Axel,
I have created a policy that identifies when people (ContentModel.TYPE_PERSON) are created (overriding OnCreateNodePolicy.onCreateNode), and that works fine.
Within the onCreateNode method I am trying to call 'auditComponent.recordAuditValues' to register the event, but I am not seeing anything in my audit query.
I suspect that it is because I am misunderstanding what the argument 'rootPath' is in the call:
recordAuditValues(String rootPath, Map<String,Serializable> values)
The API makes it sound like the rootPath and the values Map are combined to be what would be evaluated by the audit path mapper, but I can't seem to get the audit call to show up in audit trail.
Should the rootpath be the Audit application key? the pathmappings target?
Thanks!
Dan
03-06-2017 10:27 AM
The rootPath should be the common base path for your audit event (and data) including the name of the "source audit producer" as the first path fragment to help differentiate it from other audit producers. You can use any of number of path fragments as the "source" in a PathMap within your audit configuration.
E.g. the two default Alfresco audit producers are alfresco-api and alfresco-access, so their rootPath will always begin with /alfresco-api/ and /alfresco-access/ specifically. The alfresco-api producer will include additional path fragments in the root path to differentiate the type of event, e.g. if it is a pre- or post-invocation audit, which service and which operation it refers.
I recommend NOT using the audit application key as the first path fragment in the rootPath, just to avoid the confusion / misconception that the producer + application are the same. If Alfresco had chosen this for alfresco-access there might not have been confusion about how audit filters work (e.g. what part of the data they apply to) or they would have implemented it correctly, instead of half-assed.
03-06-2017 11:30 AM
Thanks for the reply, and my apologies for the smallness of my brain...
I have an audit app defined as:
<?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-api/post/PersonService/createPerson" target="/auditcreateperson/create"/>
</PathMappings><Application name="auditcreateperson" key="auditcreateperson">
<AuditPath key="create">
<AuditPath key="args">
<AuditPath key="properties">
<RecordValue key="properties" dataExtractor="simpleValue" />
</AuditPath>
</AuditPath>
</AuditPath>
</Application></Audit>
, and I can query for (manually) created users with the query:
https://myserver/alfresco/service/api/audit/query/auditcreateperson?verbose=true&forward=false
which returns something like:
...
{
"id": 2262417,
"application": "auditcreateperson",
"user": "DBiggins",
"time": "2017-03-06T10:56:22.273-05:00",
"values": {
"/auditcreateperson/create/args/properties/properties": "{{http://www.alfresco.org/model/content/1.0}sizeCurrent=0, {http://www.alfresco.org/model/content/1.0}userName=asd, {http://www.alfresco.org/model/content/1.0//www.alfresco.org/model/content/1.0}email=dbiggins@myemail.com, {http://www.alfresco.org/model/content/1.0}lastName=asd, {http://www.alfresco.org/model/content/1.0}firstName=asd}"
}
}...
so that would mean that my rootpath would be:
/alfresco-api/post/PersonService/createPerson
, and my map would be something like the values value?
Thanks again!
Dan
03-06-2017 11:45 AM
For the event that you capture with this PathMap example the rootPath is indeed "/alfresco-api/post/PersonService/createPerson" which is composed of the individual elements that refer to:
The map in this example is all the data associated with the event. In fact, the map is the structure that contains the "args" key that you use to map the audit event in your audit application. In its entirety the map contains:
In your audit application you are actually disecting the map by using the AuditPath and RecordValue to only handle a subset of the data.
The "values" object in your audit query is the sum of all the data you configured to be persisted via RecordValue and/or GenerateValue.
Coming back to your policy, you should NOT use the same "/alfresco-api/..." path as the rootPath - doing so could cause errors in other audit applications that expect the data to have a certain structure. Instead you should pick a unique, custom name. You also do not need to include all the path elements that alfresco-api includes. It would be perfectly valid to only use a path "/acme-audit-policies/createPerson" and provide a map that contains the data you need for recording - based on your example it might be enough for the map to contain the "properties" entry with all the current persons node properties.
03-07-2017 12:25 PM
Coming back to your policy, you should NOT use the same "/alfresco-api/..." path as the rootPath - doing so could cause errors in other audit applications that expect the data to have a certain structure. Instead you should pick a unique, custom name. You also do not need to include all the path elements that alfresco-api includes. It would be perfectly valid to only use a path "/acme-audit-policies/createPerson" and provide a map that contains the data you need for recording - based on your example it might be enough for the map to contain the "properties" entry with all the current persons node properties.
Thanks Axel!
I was hung up on exactly that: creating a basic audit application was the right way to approach it:
<?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="/custom-api/createPerson" target="/auditpersoncreate"/>
<PathMap source="/custom-api/deletePerson" target="/auditpersondelete"/>
</PathMappings><Application name="auditpersoncreate" key="auditpersoncreate">
<RecordValue key="lastName" dataExtractor="simpleValue" dataSource="/auditpersoncreate/lastName" dataTrigger="/auditpersoncreate/lastName"/>
<RecordValue key="firstName" dataExtractor="simpleValue" dataSource="/auditpersoncreate/firstName" dataTrigger="/auditpersoncreate/firstName"/>
<RecordValue key="userName" dataExtractor="simpleValue" dataSource="/auditpersoncreate/userName" dataTrigger="/auditpersoncreate/userName"/>
<RecordValue key="email" dataExtractor="simpleValue" dataSource="/auditpersoncreate/email" dataTrigger="/auditpersoncreate/email"/>
</Application><Application name="auditpersondelete" key="auditpersondelete">
<RecordValue key="lastName" dataExtractor="simpleValue" dataSource="/auditpersondelete/lastName" dataTrigger="/auditpersondelete/lastName"/>
<RecordValue key="firstName" dataExtractor="simpleValue" dataSource="/auditpersondelete/firstName" dataTrigger="/auditpersondelete/firstName"/>
<RecordValue key="userName" dataExtractor="simpleValue" dataSource="/auditpersondelete/userName" dataTrigger="/auditpersondelete/userName"/>
<RecordValue key="email" dataExtractor="simpleValue" dataSource="/auditpersondelete/email" dataTrigger="/auditpersondelete/email"/>
</Application></Audit>
So now I can see via a log call when a person is created manually or via LDAP synch, and I can see an audit item created when items are manually created or deleted.
I am NOT seeing an audit item created when a person is created or deleted via LDAP synch, which is strange, since I can see that the policy code is being executed because of the logger result in the alfresco.log. The same policy code is being run for manual and for LDAP synchs.
I was thinking that it has something to do with NotificationFrequency, though I have tried this with EVERY_EVENT, FIRST_EVENT, and TRANSACTION_COMMIT.
Is there anything that I need to be aware of when calling AuditComponent.recordAuditValues that would be different in these two scenarios?
Thanks again for your time and expertise!
03-07-2017 01:53 PM
*sigh*
I believe the "UserAuditFilter" that Alfresco has added in one of the 4.x release cycles eliminates those audit entries. This relates to the "audit.filter.alfresco-access.transaction.user" configuration property you can set in alfresco-global.properties. Due to the (piss-poor) implementation that was done, the name is misleading - instead of filtering only the audit events from the audit producer "alfresco-access" it actually filters data from ALL audit producers.
By default, the value of this setting is "~System;~null;.*" which means that all events with the system user and no user are suppressed. For the synchronisation you'd have to override this setting with just "~null;.*" so system user is no longer filtered. Be aware though, that this may increase the amount of data collected in other audit applications.
03-07-2017 03:45 PM
Gotcha.
Thanks for all of the help and the additional information.
I'll take a look at that vs using some other vehicle for this particular kind of auditing information.
I hate to drive people to *sigh*ing, but again, you have been very helpful!!!!!
Dan
03-07-2017 04:56 PM
Axel,
I hope this improves your day a LITTLE, but I am looking at the method:
recordAuditValuesWithUserFilter([rootpath],[map],[userfilterboolean])
After a few tests of setting that last param to false, it APPEARS to ignore the user filter in the global.properties file....
Appreciate your help again!
Dan
Explore our Alfresco products with the links below. Use labels to filter content by product module.