Solving a -614 Error in User App

0 Likes
One of the interesting features added to Novell Identity Manager (first in version 3, I think) is the User Application.

User App is basically another iteration of Novell's latest portal product, in this case eXtend, which they got as part of the Silver Stream acquisition. You might remember previous examples of this, with NPS (Novell Portal Services) being the previous portal application from Novell. This became the basic underlying infrastructure for iManager. It's clearly a powerful one, as iManager is an impressive example of a web application.

(Yes, I know that iManager is a royal pain at times. I used to joke in the 2.02 version time frame that we need a RAIIS (like RAID, but Redundant Array of Independent iManager Servers). I once challenged the Novell product manager for iManager to provide a publicly available iManager server, that we could use when our servers were all hosed - to fix iManager, there are times you need iManager. He never took me up on it, alas. Thankfully with the release of iManager 2.5 much of these issues went away and things are getting better with each release). Regardless of the issues you may have run into with iManager, you need to be fair and concede that it is truly an impressive example of a web application. Some of the cool stuff they do in the interface is really impressive. Not the least is that it works in Firefox and Internet Explorer (which is effectively writing it twice!). So kudos to the iManager team for great work.

The more you learn about User App, the more you will realize that this aspect of Novell's Identity Manager suite is possibly as big and complex as the part we more traditionally think of as Identity Manager! Sit in on a Brainshare presentation on Provisioning or User App, and you will realize how powerful and complex it really is. As a consequence there is a fairly big learning curve, and it will take some time to figure out the vagaries of this solution.

Note: We ran into a very interesting problem, that is basically a bug that should be fixed soon, with a relatively easy workaround, that only occurs in rare cases. The rest of this article explains the problem and solution.

Password Self Service

For most users, the first implementation of User App will be the simplest case, which is Password Self Service. This replaces the various previous versions Novell has supported (there was something before the NPS version, but I forget what it was called) over the years. In the grand scheme of things, this is probably a good thing. The new User App is very powerful, and once you sneak it in, adding more features is an easier sell.

Basically, this uses the stripped down version that does not allow for much beyond eGuide style functionality (address book with reporting structure) and some basic User object self manipulation. If you buy the full Provisioning license, then you can start to do work flows with complex reporting patterns and approvals flows, and it gets really busy after that! The power is quite impressive, Designer has an entire other side to it, that you might never have seen, that supports designing these kind of features.

In our case, we had a connected system that we had no access to beyond sending password change events to a custom shim. We needed to send the old password and the new password on change events. Well this is easy enough to do; eDirectory and Identity manager do this almost automatically. (There is an Engine Control Value you need to enable to tell it to send old password values on nspmDistributionPassword changes. The Lotus Notes driver requires this as well, for example. The Engine Control Value is "Use password event values' (ecnm_pevvl), set 'true'").

But what do you do in the case of a mismatch, where this connected system and the current eDirectory password are out of sync? Well one approach is get them back in synchrony. Hopefully this is a one-time event, but it pretty much needs to be initiated by the user, since they know their passwords (we hope!). We could just set their eDirectory password to the same as their password in the connected system. This would work, unless we run into password history issues - this will be a big problem, since people like to use and reuse the same passwords or patterns on them.

What we decided to do was to use the User App and the Details portlet, which are designed to let users change some of their attributes. We added an attribute acmeOldPassword in an aux class called acme_idm_aux. In Designer > Provisioning view > Directory Abstraction Layer, we added the attribute as editable, single-valued. Then we deployed this to the User App via Designer (which updates the XMLData of the User.EntityDefs.DirectoryModel.AppConfig.UserAppIDM.treename object) as an XML segment that looks something like this:

<pre class="code">
<attribute
editable="true" enabled="true" hideable="false"
multivalue="false" protected="false" readable="true"
required="false" searchable="false"
viewable="true">
<key>acmeOldPassword</key>
<ldap-name>acmeOldPassword</ldap-name>
<nds-name>acmeOldPassword</nds-name>
<aux-class>acme_idm_aux</aux-class>
<display xml:lang="en">
<label>Set Corporate Password (only if different from IDM Password)</label>
</display><type>String</type>
</attribute>



Troubleshooting

Now in principle this should work fine, and in fact, it did work fine for a while. In our test lab it just plain worked. Once we rolled it out to production, however, we started to get an odd -614 Duplicate Value error.

When the client clicks Save after entering a value, UserApp returns the error to the client. You need to look at DSTRACE with the LDAP options on to see the error. You can enable this any number of ways; probably the easiest is to use iMonitor to connect to the eDirectory server. This would be via a web browser to http://ServerIp.address:PORT, where ServerIP.address is the IP Address of the server User App is using to connect. This is probably the server running the Identity Manager driver for User Application. I am sure you can configure it to point somewhere else for LDAP, but I do not know where that is set. PORT will depend on the platform you are running eDirectory on. On Netware it is 8008 for HTTP and 8009 for HTTPS; on Windows it is usually 8010 for HTTP and 8011 for HTTPS. On SLES and other Unixes it is usually 8028 for HTTP and 8030 for HTTPS connectivity.

1. Once in iMonitor, click on the lightning bolt icon to get to the Dstrace configuration page.

2. Clear all settings, select LDAP, and turn on trace.

The problem trace looks like this:


08:48:04 AF612BB0 LDAP: (10.42.42.42:32864)(0x03f8:0x63) Sending
operation result 0:"":"" to connection 0x83e89a8
08:48:04 AF211BB0 LDAP: (10.42.42.42:32865)(0x0338:0x63) DoSearch on
connection 0x88866d8
08:48:04 AF211BB0 LDAP: (10.42.42.42:32865)(0x0338:0x63) Search request:
base: "cn=jsmith,ou=active,ou=employees,o=acmeny"
scope:0 dereference:0 sizelimit:0 timelimit:0 attrsonly:0
filter: "(objectClass=*)"
attribute: "srvprvQueryList"
attribute: "srvprvNotificationPrefs"
attribute: "ou"
attribute: "acmeOWAoldPassword"
attribute: "srvprvHideAttributes"
attribute: "title"
attribute: "directReports"
attribute: "VPNUser"
attribute: "employeeID"
attribute: "mail"
attribute: "manager"
attribute: "l"
attribute: "sn"
attribute: "ADUser"
attribute: "CSGUser"
attribute: "NOVUser"
attribute: "groupMembership"
attribute: "givenName"
attribute: "telephoneNumber"
attribute: "SOLUser"
attribute: "srvprvHideUser"
attribute: "srvprvHideAttributes"
attribute: "modifyTimeStamp"
attribute: "objectClass"
08:48:04 AF211BB0 LDAP: (10.42.42.42:32865)(0x0338:0x63) Sending search result entry "cn=jsmith,ou=active,ou=employees,o=acmeny" to connection 0x88866d8
08:48:04 AF211BB0 LDAP: (10.42.42.42:32865)(0x0338:0x63) Sending operation result 0:"":"" to connection 0x88866d8
08:48:04 A8905BB0 LDAP: (10.42.42.42:32856)(0x0376:0x66) DoModify on connection 0x84022d8
08:48:04 A8905BB0 LDAP: (10.42.42.42:32856)(0x0376:0x66) modify: dn (cn=jsmith,ou=active,ou=employees,o=acmeny)
08:48:04 A8905BB0 LDAP: (10.42.42.42:32856)(0x0376:0x66) modifications:
08:48:04 A8905BB0 LDAP: (10.42.42.42:32856)(0x0376:0x66) add: objectClass
08:48:04 A8905BB0 LDAP: (10.42.42.42:32856)(0x0376:0x66) DDCModifyEntry failed, err = duplicate value (-614)
08:48:04 A8905BB0 LDAP: (10.42.42.42:32856)(0x0376:0x66) Sending operation result 20:"":"NDS error: duplicate value (-614)" to connection
0x84022d8



Here is the search event for the user to allow User App to populate the fields as the user logins in.


08:48:04 AF211BB0 LDAP: (10.42.42.42:32865)(0x0338:0x63) DoSearch on
connection 0x88866d8
08:48:04 AF211BB0 LDAP: (10.42.42.42:32865)(0x0338:0x63) Search request:
base: "cn=jsmith,ou=active,ou=employees,o=acmeny"
scope:0 dereference:0 sizelimit:0 timelimit:0 attrsonly:0
filter: "(objectClass=*)"
attribute: "srvprvQueryList"
attribute: "srvprvNotificationPrefs"
attribute: "ou"
attribute: "acmeOWAoldPassword"
attribute: "srvprvHideAttributes"
attribute: "title"
attribute: "directReports"
attribute: "VPNUser"
attribute: "employeeID"
attribute: "mail"
attribute: "manager"
attribute: "l"
attribute: "sn"
attribute: "ADUser"
attribute: "CSGUser"
attribute: "NOVUser"
attribute: "groupMembership"
attribute: "givenName"
attribute: "telephoneNumber"
attribute: "SOLUser"
attribute: "srvprvHideUser"
attribute: "srvprvHideAttributes"
attribute: "modifyTimeStamp"
attribute: "objectClass"



Then we get the success message - all good, so far.


08:48:04 AF211BB0 LDAP: (10.42.42.42:32865)(0x0338:0x63) Sending search result entry "cn=jsmith,ou=active,ou=employees,o=acmeny" to connection 0x88866d8
08:48:04 AF211BB0 LDAP: (10.42.42.42:32865)(0x0338:0x63) Sending operation result 0:"":"" to connection 0x88866d8



Next the user is ready to set the value, and we see this:


08:48:04 A8905BB0 LDAP: (10.42.42.42:32856)(0x0376:0x66) DoModify on connection 0x84022d8
08:48:04 A8905BB0 LDAP: (10.42.42.42:32856)(0x0376:0x66) modify: dn (cn=jsmith,ou=active,ou=employees,o=acmeny)
08:48:04 A8905BB0 LDAP: (10.42.42.42:32856)(0x0376:0x66) modifications:
08:48:04 A8905BB0 LDAP: (10.42.42.42:32856)(0x0376:0x66) add: objectClass



But it does not succeed. We get the 614 error:


08:48:04 A8905BB0 LDAP: (10.42.42.42:32856)(0x0376:0x66) DDCModifyEntry failed, err = duplicate value (-614)
08:48:04 A8905BB0 LDAP: (10.42.42.42:32856)(0x0376:0x66) Sending operation result 20:"":"NDS error: duplicate value (-614)" to connection
0x84022d8



There are some hints that something is not right in this trace. First of all, why is the modify adding to objectClass?

That was the first avenue we pursued. It turns out in Designer, when you add an attribute to the Directory Abstraction Layer (DAL) to be available, Designer is 'smart' and resolves the object class it belongs to. Additionally, it decides if the default class contains it (User, for example) or if it is only in an auxiliary class. This is shown in the configuration in the object as follows:


<attribute
editable="true" enabled="true" hideable="false"
multivalue="false" protected="false" readable="true"
required="false" searchable="false"
viewable="true">
<key>acmeOldPassword</key>
<ldap-name>acmeOldPassword</ldap-name>
<nds-name>acmeOldPassword</nds-name>
<aux-class>acme_idm_aux</aux-class>
<display xml:lang="en">
<label>Set Corporate Password (only if different from IDM Password)</label>
</display><type>String</type>
</attribute>



The line:
<aux-class>acme_idm_aux</aux-class>

shows that the class has been selected.

What ends up being the problem is that Designer is quite smart and talks NCP over JClient to eDirectory. User App uses LDAP to talk to eDirectory. Names in eDirectory for schema can have a different name in LDAP. (The LDAP server object contains attribute and class mappings so you can control it on a per server basis).

You can see this wisdom in the tags:


<ldap-name>acmeOldPassword</ldap-name>
<nds-name>acmeOldPassword</nds-name>



Here we see that it is all architected to handle an NDS schema name that is different from the LDAP schema name. So if you have two different names, it is all set to handle that. It turns out there is no such extension of this model to handle object classes with different NDS and LDAP names.

So when User App tries to test the Object Class of my test user, it reads the list of Object Classes to be sure the user has the correct extension. Because LDAP in eDirectory does not like underscores, it reads back the list as including "acmeidmaux" instead of the NDS name of acme_idm_aux, so it goes to add it via LDAP.

That is why the error is this:



08:48:04 A8905BB0 LDAP: (10.42.42.42:32856)(0x0376:0x66) DoModify on connection 0x84022d8
08:48:04 A8905BB0 LDAP: (10.42.42.42:32856)(0x0376:0x66) modify: dn (cn=jsmith,ou=active,ou=employees,o=acmeny)
08:48:04 A8905BB0 LDAP: (10.42.42.42:32856)(0x0376:0x66) modifications:
08:48:04 A8905BB0 LDAP: (10.42.42.42:32856)(0x0376:0x66) add: objectClass
08:48:04 A8905BB0 LDAP: (10.42.42.42:32856)(0x0376:0x66) DDCModifyEntry failed, err = duplicate value (-614)



It is trying to add acmeidmaux to the Object Class, but eDirectory gets that and says, oh you mean add acme_idm_aux, which is already there, so it gets a 614 error. The best solution is not to use underscores in your aux classes. Ultimately this is a bug that Novell needs to fix (it is being worked on) to handle this correctly.

If you already have an aux class in use, you should be able to create a new one, add the attributes to the new underscore-less class, and use that instead. The problem will remain in how "smart" Designer is, and what it does when it sees an attribute that belongs to two classes. We know what the Identity Manager engine does; it adds both Object Classes. I have not tested to see what Designer will do yet with two object classes. In worst case, to get it running you could edit the attribute itself each time you deploy it, until the real fix is ready.

Labels:

How To-Best Practice
Comment List
Related
Recommended