cancel
Showing results for 
Search instead for 
Did you mean: 

New Auditing Mechanism in Ent3.2, Comm. 3.2r

simon_white
Champ in-the-making
Champ in-the-making
Hello all,

I've been trying to do some work for an Alfresco Enterprise customer that involves the evaluation and configuring of auditing behaviour.  The customer will mostly be using Alfresco Share.

As the customer will soon be migrating to Enterprise 3.2, I've been trying to look at evaluating the configure-ability, richness and performance of the new auditing mechanism in E3.2.

I've been running into some problems working out how to configure the new auditing mechanism.

I understand that data is passed to the audit component, keyed by some "path", that this is filtered through a path mapper to bring together related input paths into an "Application" and that an individual Application is then configured to store specific values using data extractors.  What I'm struggling to understand is what the input paths actually are.  They don't look like FQCNs.  I've tried looking at the Wiki, the RM source code and the unit test for the 5015 auditing mechanism but haven't found anything to indicate how to find out what input paths are available and how they relate to the Alfresco source code.

Can anyone help me with this?  Or does anyone have a sample audit configuration file they can pass me that audits a the core Alfresco repository, or Share, using the new mechanism?

I've found another thread on this forum discussing auditing in 3.2, but it seems to focus on the "old" auditing mechanism.

Thanks in advance,

Simon
21 REPLIES 21

derek
Star Contributor
Star Contributor
Hi, Simon

Thanks for starting the new thread; it's definitely the right thing to do.  I have updated the Wiki page (http://wiki.alfresco.com/wiki/Auditing_(from_V3.2r)) and given a reference the code that produces the API-based data.  I'm aware that the documentation is nascent; I was hoping to drive it from samples and code until the framework had been tested a bit.  It's been functionally tested, of course, but I'd like to see what comes out of community and customer use.

The paths (by which the produced data is keyed) are arbitrary.  There are some shortcuts that allow the paths in the produced map to be shortened when data is audited.  If you're consuming the data, the only thing that matters is the full path.

Let me know if you need any more direction.

Regards

simon_white
Champ in-the-making
Champ in-the-making
Derek,

Thanks for getting back to me.  The following example is all community 3.2r, MySQL, Share and Alfresco Repository co-located in Tomcat:

I've made the following change to tomcat/shared/classes/alfresco-global.properties, and to tomcat/webapps/alfresco/WEB-INF/classes/alfresco/repository.properties for good measure:

audit.enabled=true
audit.useNewConfig=true

I've then replaced alfresco-audit-repository.xml with:


<?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" class="org.alfresco.repo.audit.extractor.SimpleValueDataExtractor"/>
    </DataExtractors>

    <DataGenerators>
       <DataGenerator name="transactionId" class="org.alfresco.repo.audit.generator.TransactionIdDataGenerator"/>
    </DataGenerators>

    <PathMappings>
        <PathMap source="/repository" target="/repository"/>
    </PathMappings>

    <Application name="Alfresco Repository" key="repository">
        <AuditPath key="services">
            <GenerateValue key="txn" dataGenerator="transactionId"/>
            <AuditPath key="contentservice">
                <AuditPath key="getreader">
                    <AuditPath key="return">
                        <RecordValue key="value" dataExtractor="simpleValue"/>
                    </AuditPath>
                </AuditPath>
            </AuditPath>
        </AuditPath>
    </Application>

</Audit>


I then added the following to the top of my tomcat/webapps/alfresco/WEB-INF/classes/log4j.properties


# Audit debugging
log4j.logger.org.alfresco.repo.audit.PublicServiceIdentifierImpl=INFO, Audit
log4j.logger.org.alfresco.repo.audit=DEBUG, Audit
log4j.logger.org.alfresco.repo.audit.AuditMethodInterceptor=DEBUG, Audit
log4j.appender.Audit=org.apache.log4j.DailyRollingFileAppender
log4j.appender.Audit.File=audit.log
log4j.appender.Audit.Append=true
log4j.appender.Audit.DatePattern='.'yyyy-MM-dd
log4j.appender.Audit.layout=org.apache.log4j.PatternLayout
log4j.appender.Audit.layout.ConversionPattern=%d{ABSOLUTE} %-5p [%c] %m%n

I then start Alfresco Share, navigate to an existing Site, read an existing Wiki page and create a new Wiki page.  I'm expecting to see entries in alf_audit_faq, or at least my new audit.log about the use of ContentService.getReader(), but I can't see anything.

What have I missed?

Simon

derek
Star Contributor
Star Contributor
Thanks for the feedback, Simon.

For starters, I should point out that the new audit persists the data completely differently as well.  Part of the problem with the old data storage was the inability to persist arbitrary data (so important for a generic auditing mechanism) and the inability to efficiently search the data; the latter was missing completely.

Tables: http://wiki.alfresco.com/wiki/Auditing_%28from_V3.2r%29#Architecture
Logging: http://wiki.alfresco.com/wiki/Auditing_%28from_V3.2r%29#DEBUG_Logging

I hope that will clear things up a bit.  At any rate, you should see entries appearing in alf_audit_entry.  The queries to see the persisted values are somewhat complicated BUT there is a search API on AuditService.
    /**
     * Issue an audit query using the given parameters and consuming results in the callback.
     *
     * @param callback          the callback that will handle results
     * @param parameters        the parameters for the query (may not be <tt>null</tt>)
     * @param maxResults        the maximum number of results to retrieve (zero or negative to ignore)
     *
     * @since 3.3
     */
    void auditQuery(AuditQueryCallback callback, AuditQueryParameters parameters, int maxResults);
That should say "@since 3.2", though 😞

evgenyww
Champ in-the-making
Champ in-the-making
I had the same problem and what I have discovered about new auditing mechanism (correct me if I'm wrong somewhere):
1. though auditConfig.xml is read by alfresco it is not used anymore
2. auditing is configured mostly in alfresco-audit-repository.xml. Here you should set patches to services that you want to audit

My alfresco-audit-repository.xml:

    <DataExtractors>
       <DataExtractor name="simpleValue" class="org.alfresco.repo.audit.extractor.SimpleValueDataExtractor"/>
    </DataExtractors>

    <DataGenerators>
       <DataGenerator name="transactionId" class="org.alfresco.repo.audit.generator.TransactionIdDataGenerator"/>
    </DataGenerators>

    <PathMappings>
        <PathMap source="/alfresco-api" target="/alfresco-api"/>
    </PathMappings>

    <Application name="Alfresco Api" key="alfresco-api">
        <AuditPath key="post">
            <GenerateValue key="txn" dataGenerator="transactionId"/>
            <AuditPath key="NodeService">
                <AuditPath key="createNode">
                    <AuditPath key="result">
                        <RecordValue key="value" dataExtractor="simpleValue"/>
                    </AuditPath>
                </AuditPath>
            </AuditPath>
        </AuditPath>
    </Application>


This configuration means that I want to register all requests to /alfresco-api/post/NodeService/createNode/result
1. Every "AuditPath" key is a section in the service path
2. Most requests starts by "/alfresco-api/". To find exact service path that you need to audit set breakpoint in AuditComponentImp in the method "audit" at the line

        // Generate data
        Map<String, DataGenerator> generators = application.getDataGenerators(values.keySet());
and watch the values passed to this method.
3. service path is case sensitive
4. path should be fully defined in Application: it means that in my case /alfresco-api/post/NodeService/createNode/xxx won't be registered
5. created auditing items are stored in the table "alf_audit_entry"

derek
Star Contributor
Star Contributor
Hi,

You would not modify the internal audit file or any other audit config file.  Rather, define your own and load it in e.g.:

    <bean id="auditModel.mine" class="org.alfresco.repo.audit.model.AuditModelReader">
        <property name="auditModelUrl">
           <value>classpath:alfresco/extension/alfresco-audit-mine.xml</value>
        </property>
        <property name="auditModelRegistry" ref="auditModel.modelRegistry"/>
    </bean>
Your config file must define a new application e.g.:

    <PathMappings>
        <PathMap source="/alfresco-api" target="/mine"/>
    </PathMappings>

    <Application name="Mine" key="mine">
        <AuditPath key="post">
            <GenerateValue key="txn" dataGenerator="transactionId"/>
            <AuditPath key="NodeService">
                <AuditPath key="createNode">
                    <AuditPath key="result">
                        <RecordValue key="value" dataExtractor="simpleValue"/>
                    </AuditPath>
                </AuditPath>
            </AuditPath>
        </AuditPath>
    </Application>

Data producers can produce data against any path (hence the need to remap).  The AuditMethodInterceptor's JavaDoc gives details on what it produces.

fgruska
Champ in-the-making
Champ in-the-making
Hello,
Not sure if there is a easy way to configure an eventually view audit data.
Can I do this by just changing the global properties? IWhat needs to be done to view any audit logs (e.g. similar to the template in pre 3.2).

Any help is very much appreciated.

Thank, Frank

evgenyww
Champ in-the-making
Champ in-the-making
If you set useNewConfig to false you'll activate old variant of auditing:

audit.enabled=true
audit.useNewConfig=false

pchoe
Champ in-the-making
Champ in-the-making
I have been trying to get auditing to work on Alfresco Enterprise 3.2.  I tried following the outline in this thread as well as http://aboutalfresco.blogspot.com/2009/12/audit-configuration-in-alfresco.html.  But I don't see any audit when I create new content (node).  I do see logging in the alf_audit_fact table in the database for AuthenticationService.getNewTicket.

Listed are the configuration files for auditing
<?xml version='1.0' encoding='UTF-8'?>
<!DOCTYPE beans PUBLIC '-//SPRING//DTD BEAN//EN' 'http://www.springframework.org/dtd/spring-beans.dtd'>

<beans>   
    <!– The configuration of the audit model –>
   
    <bean id="auditConfiguration" class="org.alfresco.repo.audit.AuditConfigurationImpl">
        <property name="config">
            <value>alfresco/extension/auditConfig.xml</value>
        </property>
    </bean>   

    <bean id="auditModel.custom" class="org.alfresco.repo.audit.model.AuditModelReader">
        <property name="auditModelUrl">
           <value>classpath:alfresco/extension/custom-alfresco-audit-repository.xml</value>
        </property>
        <property name="auditModelRegistry" ref="auditModel.modelRegistry"/>
    </bean>
</beans>

<?xml version='1.0' encoding='UTF-8'?>

<!– Default Audit Configuration –>

<Audit xmlns="http://www.alfresco.org/model/audit/1.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" enabled="true" auditInternal="true" mode="all">
   
    <!–                –>
    <!– Global options –>
    <!–                –>
   
    <!– Do not record any additional information –>
   
    <RecordOptions>
        <recordPath>true</recordPath>
        <recordFilters>true</recordFilters>
        <recordSerializedReturnValue>true</recordSerializedReturnValue>
        <recordSerializedExceptions>true</recordSerializedExceptions>
        <recordSerializedMethodArguments>true</recordSerializedMethodArguments>
        <recordSerializedKeyPropertiesBeforeInvocation>true</recordSerializedKeyPropertiesBeforeInvocation>
        <recordSerializedKeyPropertiesAferInvocation>true</recordSerializedKeyPropertiesAferInvocation>
    </RecordOptions>
   
    <!–                          –>
    <!– Specific service options –>
    <!–                          –>
   
    <Service name="ServiceRegistry" mode="none" enabled="true"/>
   
    <!– The action service –>
   
    <Service name="ActionService" mode="none">
        <Method name="executeAction" mode="all" auditInternal="true"/>
        <Method name="saveAction" mode="all"/>
        <Method name="removeAction" mode="all"/>
        <Method name="removeAllActions" mode="all"/>
    </Service>
   
    <!– The COCI Service –>
   
    <Service name="CheckoutCheckinService">
        <Method name="getWorkingCopy" mode="none"/>
    </Service>
   
    <!– The DictionaryService –>
    <!– There are no audtiable methods in the data dictionary service –>
    <Service name="DictionaryService" mode="none" enabled="true"/>
   
    <!– The Lock Service –>
   
    <Service name="LockService">
        <Method name="getLockStatus" mode="none"/>
        <Method name="getLockType" mode="none"/>
        <Method name="getLocks" mode="none"/>
    </Service>
   
    <!– The File/Folder Service –>
   
    <Service name="FileFolderService" mode="none">
        <Method name="rename" mode="all"/>
        <Method name="move" mode="all"/>
        <Method name="copy" mode="all" auditInternal="true"/>
        <Method name="create" mode="all"/>
        <Method name="delete" mode="all"/>
        <Method name="makeFolders" mode="all"/>
        <Method name="getWriter" mode="all"/>
    </Service>
   
    <Service name="ContentService" mode="none">
        <Method name="getWriter" mode="all"/>
        <Method name="transform" mode="all"/>
    </Service>
   
    <Service name="CopyService" mode="none">
        <Method name="copy" mode="all" auditInternal="true"/>
    </Service>
   
    <!– The MimetypeService –>
    <!– There are no audtiable methods in the mime type service –>
    <Service name="MimetypeService" mode="none" enabled="false"/>
   
<!– The ContentFilterLanguagesService –>
    <Service name="ContentFilterLanguagesService" mode="none" >
        <Method name="getFilterLanguages" mode="all"/>
        <Method name="getMissingLanguages" mode="all"/>
        <Method name="getDefaultLanguage" mode="all"/>
    </Service>
    <Service name="NodeService" mode="none">
        <Method name="createStore" mode="all"/>
        <Method name="createNode" mode="all"/>
        <Method name="moveNode" mode="all"/>
        <Method name="setChildAssociationIndex" mode="all"/>
        <Method name="setType" mode="all"/>
        <Method name="addAspect" mode="all"/>
        <Method name="removeAspect" mode="all"/>
        <Method name="deleteNode" mode="all"/>
        <Method name="addChild" mode="all"/>
        <Method name="removeChild" mode="all"/>
        <Method name="setProperties" mode="all"/>
        <Method name="setProperty" mode="all"/>
        <Method name="createAssociation" mode="all"/>
        <Method name="removeAssociation" mode="all"/>
        <Method name="restoreNode" mode="all"/>
    </Service>
   
    <Service name="ScriptService" auditInternal="true"/>
   
    <Service name="TemplateService" auditInternal="true">
        <Method name="getTemplateProcessor" mode="none"/>
    </Service>
   
    <Service name="RuleService" mode="none" auditInternal="true">
        <Method name="disableRules" mode="all"/>
        <Method name="enableRules" mode="all"/>
        <Method name="disableRule" mode="all"/>
        <Method name="enableRule" mode="all"/>
        <Method name="createRule" mode="all"/>
        <Method name="saveRule" mode="all"/>
        <Method name="removeRule" mode="all"/>
        <Method name="removeAllRules" mode="all"/>
    </Service>
   
    <Service name="CategoryService" mode="none">
        <Method name="createClassifiction" mode="all"/>
        <Method name="createRootCategory" mode="all"/>
        <Method name="createCategory" mode="all"/>
        <Method name="deleteClassification" mode="all"/>
        <Method name="deleteCategory" mode="all"/>
    </Service>
   
    <Service name="SearchService" mode="none" enabled="true"/>
   
    <Service name="AuthenticationService" mode="none">
        <Method name="createAuthentication" mode="all"/>
        <Method name="updateAuthentication" mode="all"/>
        <Method name="setAuthentication" mode="all"/>
        <Method name="deleteAuthentication" mode="all"/>
        <Method name="setAuthenticationEnabled" mode="all"/>
        <Method name="authenticate" mode="all" auditInternal="true"/>
        <Method name="authenticateAsGuest" mode="all"/>
        <Method name="authenticationExists" mode="all"/>
        <Method name="invalidateUserSession" mode="all"/>
        <Method name="invalidateTicket" mode="all"/>
        <Method name="validate" mode="all"/>
        <Method name="clearCurrentSecurityContext" mode="all"/>
        <!– audit the creation of new tickets to follow SSO –>
        <Method name="getNewTicket" mode="all" />
        <Method name="getCurrentTicket" mode="none" auditInternal="true"/>
    </Service>
   
    <Service name="AuthorityService" mode="none">
        <Method name="createAuthority" mode="all"/>
        <Method name="addAuthority" mode="all"/>
        <Method name="removeAuthority" mode="all"/>
        <Method name="deleteAuthority" mode="all"/>
    </Service>
   
    <Service name="OwnableService" mode="none">
        <Method name="setOwner" mode="all"/>
        <Method name="takeOwnership" mode="all"/>
    </Service>
   
    <Service name="PermissionService" mode="none">
        <Method name="deletePermissions" mode="all"/>
        <Method name="clearPermission" mode="all"/>
        <Method name="deletePermission" mode="all"/>
        <Method name="setPermission" mode="all"/>
        <Method name="setInheritParentPermissions" mode="all"/>
    </Service>
   
    <Service name="PersonService" mode="none">
        <Method name="setCreateMissingPeople" mode="all"/>
        <Method name="setPersonProperties" mode="all"/>
        <Method name="createPerson" mode="all"/>
        <Method name="deletePerson" mode="all"/>
    </Service>
   
    <Service name="VersionService" mode="none">
        <Method name="createVersion" mode="all"/>
        <Method name="revert" mode="all"/>
        <Method name="restore" mode="all"/>
        <Method name="deleteVersionHistory" mode="all"/>
    </Service>
   
    <Service name="ExporterService"/>
   
    <Service name="ImporterService"/>
   
    <Service name="RepositoryExporterService"/>
   
    <Service name="DescriptorService" mode="none" enabled="true"/>
   
    <Service name="LicenseService" mode="none" enabled="true"/>
   
    <Service name="NamespaceService" mode="none" enabled="true"/>
   
    <Service name="TransactionService" mode="none" enabled="true"/>
   
    <Service name="WorkflowService" auditInternal="true">
        <Method name="isDefinitionDeployed" mode="none"/>
        <Method name="getDefinitions" mode="none"/>
        <Method name="getDefinitionById" mode="none"/>
        <Method name="getDefinitionByName" mode="none"/>
        <Method name="getActiveWorkflows" mode="none"/>
        <Method name="getWorkflowPaths" mode="none"/>
        <Method name="getTasksForWorkflowPath" mode="none"/>
        <Method name="getTaskById" mode="none"/>
        <Method name="getAssignedTasks" mode="none"/>
        <Method name="getPooledTasks" mode="none"/>
    </Service>
   
</Audit>


<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"
         class="org.alfresco.repo.audit.extractor.SimpleValueDataExtractor" />
      <!–
         <DataExtractor name="stackTrace"
         class="org.alfresco.repo.audit.extractor.StackTraceDataExtractor"/>
         <DataExtractor name="storeRootNode"
         class="org.alfresco.repo.audit.extractor.StoreRootNodeDataExtractor"/>
      –>
   </DataExtractors>

   <DataGenerators>
      <DataGenerator name="transactionId"
         class="org.alfresco.repo.audit.generator.TransactionIdDataGenerator" />
   </DataGenerators>

   <PathMappings>
      <PathMap source="/alfresco-api" target="/custom" />
   </PathMappings>

   <Application name="Custom" key="custom">
      <AuditPath key="post">
         <GenerateValue key="txn" dataGenerator="transactionId" />
         <AuditPath key="NodeService">
            <AuditPath key="createNode">
               <AuditPath key="result">
                  <RecordValue key="value" dataExtractor="simpleValue" />
               </AuditPath>
            </AuditPath>
         </AuditPath>
      </AuditPath>
   </Application>

</Audit>

I am missing something or something not configured correctly?

I am able to programmatically set the audits
            auditService.audit("AuditLogMigration", "Audit log migration",
                  nodeRef, logs);

derek
Star Contributor
Star Contributor
Hi,
You're mixing the pre-3.2 config with the post-3.2 config.  You can still use the pre-3.2 audit if you want.
Regards