Hybris 6.6/6.7 Generic Audit Bug Explained


There is a new feature in hybris 6.6, Generic Audit. The new mechanism keeps track of modifications of attribute values of the auditable set of hybris objects. For this purpose, both the original value of the object and its new value are stored in the database for further inspection, if the needs arise. According to the documentation, you can turn on and off auditing for particular types. For frequently changed objects, there is a risk that the system may consume a lot of database space over time, and the database itself grows to a very large size over time. So if you keep auditing on, you should keep these things under control. Shortly after SAP hybris 6.6 is released I found that this mechanism doesn’t work well. Specifically, when all the audit.*.enabled=false settings are applied, there are still types that are being audited anyway. The examples are Employee, Customer and Product. Many people observed the same, and the issue was reported to SAP. The bug has already been fixed, and, as to my knowledge, SAP has released a patch. I haven’t received the patch yet. I decided to investigate the issue in detail. There is a global key “auditing.enabled” which turns the subsystem on and off. The issue is not reproduced if it is turned off via this key. However, if it is set to “true”, you may face the issue. By default, hybris comes with the following setup:
# Audit blacklist
auditing.blacklist=itemsynctimestamp,joblog,logfile,jobmedia,task,taskcondition,processtasklog,cronjob,CronJobHistory

# Audit enabled item types
audit.user.enabled=true
audit.principalgrouprelation.enabled=true
audit.abstractcontactinfo.enabled=true
audit.address.enabled=true
audit.cart.enabled=true
audit.cartentry.enabled=true
audit.country.enabled=true
audit.currency.enabled=true
audit.order.enabled=true
audit.orderentry.enabled=true
audit.paymentinfo.enabled=true
audit.paymentmode.enabled=true

audit.product.enabled=true
audit.quote.enabled=true
audit.quoteentry.enabled=true

audit.region.enabled=true
audit.title.enabled=true
audit.unit.enabled=true
audit.usergroup.enabled=true
audit.b2bunit.enabled=true
audit.sapb2bdocument.enabled=true
audit.partneraddress.enabled=true
audit.userpasswordchangeaudit.enabled=true
audit.cxusertosegment.enabled=true
audit.cxsegment.enabled=true
audit.btgsegmentresult.enabled=true
audit.btgsegment.enabled=true
audit.consent.enabled=true
audit.consenttemplate.enabled=true
audit.city.enabled=true
audit.district.enabled=true
audit.csticket.enabled=true
audit.comment.enabled=true
audit.employee.enabled=true
audit.csagentgroup.enabled=true
audit.basesite.enabled=true
audit.saporder.enabled=true
audit.customerreview.enabled=true
audit.language.enabled=true
For example, the last line says that any changes in Language will be stored. There is a table, languages32sn, which contains the operation details, such as operation type, two states of the object, before and after the operation, and user id, who made the change.  If you set audit.XXXXX.enabled=false, this mechanism should stop working for the type XXXXX. It is so for Language or BaseSite, but, as reported, “it won’t work for Employee, Customer and Product“. In fact, this statement is not 100% correct.

How it really works

If you decide to turn the auditing off for Employee, via the following configuration:
audit.Employee.enabled=false
the system checks all supertypes of Employee, and if it finds any, it checks if these types are in the configuration. This is both bad design and a bug at the same time. Bad design lies in the fact that
auditEnablementService.isAuditEnabledForType(<type>)
silently changes the configuration based on undocumented and non-transparent logic (checking the supertypes and returning true for some combinations). As a minimum, the system must report the inconsistency in the log rather than silently change the settings. As for the bug.. What is important is the settings for these supertypes are not taken into account, just its mere existence. For example, the following fragment will print “true true true false”:
//groovy script, try it in HAC
cs=configurationService.getConfiguration();
cs.setProperty("audit.User.enabled", "true");
cs.setProperty("audit.Employee.enabled", "false");
auditEnablementService.refreshConfiguredAuditTypes();
//next line is true
println(auditEnablementService.isAuditEnabledForType("Employee"));
cs=configurationService.getConfiguration();
cs.setProperty("audit.User.enabled", "false");
cs.setProperty("audit.Employee.enabled", "false");
auditEnablementService.refreshConfiguredAuditTypes();
//next line is true
println(auditEnablementService.isAuditEnabledForType("Employee"));
cs=configurationService.getConfiguration();
cs.setProperty("audit.User.enabled", "something");
cs.etProperty("audit.Employee.enabled", "false");
auditEnablementService.refreshConfiguredAuditTypes();
//next line is true
println(auditEnablementService.isAuditEnabledForType("Employee"));
cs=configurationService.getConfiguration();
cs.clearProperty("audit.User.enabled");
cs.setProperty("audit.Employee.enabled", "false");
auditEnablementService.refreshConfiguredAuditTypes();
//next line is true
println(auditEnablementService.isAuditEnabledForType("Employee"));
In this fragment, I demonstrate that audit.User.enabled affects audit.Employee.enabled without taking into account what value is specified for “User” auditing. The JIRA ticket from SAP also reports that there is an issue with Product object too. It is not completely true. The roots of the problem are the same. You will have issues with all subtypes of Product type, such as VariantType or ApparelProduct. Actually, it extends to any other subtypes of the types specified. The following example shows that VariantProduct (subtype of Product) won’t be audited only if Product setting is removed:
cs=configurationService.getConfiguration();
cs.setProperty("audit.Product.enabled", "false");
auditEnablementService.refreshConfiguredAuditTypes();
//next line is false
println(auditEnablementService.isAuditEnabledForType("Product"));
cs=configurationService.getConfiguration();
cs.setProperty("audit.Product.enabled", "true");
cs.setProperty("audit.VariantProduct.enabled", "false");
auditEnablementService.refreshConfiguredAuditTypes();
//next line is true
println(auditEnablementService.isAuditEnabledForType("VariantProduct"));
cs=configurationService.getConfiguration();
cs.setProperty("audit.Product.enabled", "false");
cs.setProperty("audit.VariantProduct.enabled", "false");
auditEnablementService.refreshConfiguredAuditTypes();
//next line is true
println(auditEnablementService.isAuditEnabledForType("VariantProduct"));
cs=configurationService.getConfiguration();
cs.setProperty("audit.Product.enabled", "something");
cs.setProperty("audit.VariantProduct.enabled", "false");
auditEnablementService.refreshConfiguredAuditTypes();
//next line is true
println(auditEnablementService.isAuditEnabledForType("VariantProduct"));
cs=configurationService.getConfiguration();
cs.clearProperty("audit.Product.enabled");
cs.setProperty("audit.VariantProduct.enabled", "false");
auditEnablementService.refreshConfiguredAuditTypes();
//next line is false
println(auditEnablementService.isAuditEnabledForType("VariantProduct")); //false

One Response

  1. Cristian Caprar

    Cristian Caprar

    Reply

    1 August 2018 at 20:43

    Hi Rauf,

    Good article as always. We were some of the unlucky ones to get hit by this as we upgraded to 6.6 and we are stuck (due to production upgrade restrictions) to the patch still having the issue.

    We had to solve it by overriding the hybris code that generate the silent behavior some months ago.

    An ugly side effect of audit reports is when we try to start a system on a schema version, then initialize from HAC. Hybris has a problem generating the Media item for the audit report and it stops the initialization. Only a new time consuming restart is making this work again…

    All the best,
    Cristi

Leave a Reply