JNDI Service DN Design
| Issue 168 The details in the page describe the issue and proposed options for resolution |
The JNDI Service is configured with the following values in the openptk.xml file (only applicable properties are shown below):
Current Context Configuration
<Context id="Employees-OpenDS-JNDI" enabled="true" definition="Person" connection="OpenDS" association="JNDI">
<Properties>
<Property name="key" value="uniqueid" />
<Property name="rdn" value="uid=${uniqueid}" />
<Property name="basedn" value="%{jndi.basedn.employees}" />
<Property name="objectclass" value="inetOrgPerson" />
<Property name="search.default.order" value="lastname,firstname,uniqueid,email" />
<Property name="search.operators" value="AND,OR,CONTAINS,EQ" />
</Properties>
Current Definition Configuration
<Definition id="Person">
<Properties>
<Property name="definition.authenid" value="id,email" />
<Property name="definition.password" value="password" />
JndiOperations Current Implementation
The existing Service: JndiOperations uses the method: getEntryDN(RequestIF request) to determine the DN of the subject. The following statements controls how the DN us constructed for each of the relevant operations:
getEntryDN
switch (operation)
{
case CREATE:
entryDN = this.getMapData(_mapRDN, request) + ","
+ this.getMapData(_mapBaseDN, request);
break;
case UPDATE:
case DELETE:
case PWDCHANGE:
case PWDRESET:
case AUTHENTICATE:
keySrvc = request.getKey();
keyValue = request.getSubject().getUniqueId();
entryDN = keySrvc + "=" + keyValue + ","
+ this.getMapData(_mapBaseDN, request);
break;
default:
break;
}
doRead(RequestIF request, ResponseIF response)
* The full EntryDN is equal to the RDN + "," + BaseDN
* searchString = keyName + "=" + uniqueId + "," + BaseDN
doSearch: not applicable since it is not using a dn
doUpdate(RequestIF request, ResponseIF response)
entryDN = this.getEntryDN(request);
doDelete(RequestIF request, ResponseIF response)
entryDN = this.getEntryDN(request);
doPasswordChange(RequestIF request, ResponseIF response)
this.doUpdate(request, response);
doPasswordReset(RequestIF request, ResponseIF response)
this.doUpdate(request, response);
doAuthenticate(RequestIF request, ResponseIF response)
entryDN = this.getEntryDN(request);
loadMap(Map<String, Boolean> map, String template)
* example:
* EntryDn = "uid=${uniqueid}, ou=People, o=${dept}, dc=openptk, dc=org"
*
* LinkedHashMap<String, Boolean>
* ["uid=", FALSE] // literal
* ["uid", TRUE] // attribute name
* [", ou=People, o=", FALSE] // literal
* ["dept", TRUE] // attribure name
* [", dc=openptk, dc=org", FALSE] // literal
Recommendations
The following are recommendations for resolving issue 168
1) Use a consistent method for creating the entryDN for all operations
2) Use a more logical dn construction "template" rather that rdn + "," + basedn
3) Allow the entrydn to be passed in as a variable, if desired (or at least allow control of portions of the dn, like ou's, etc.)
4) For all operations other than CREATE, perform an LDAP search to determine the entrydn (rather than attempting to derive it and potentially being wrong)
Proposed Context Properties for DN creation and dn retrieval:
Example for using the uid as the top level of the dn (org is a variable in the request)
<Property name="basedn" value="%{jndi.basedn.employees}" />
<Property name="template.create" value="uid=${uniqueid},ou=People,ou=${org},%{jndi.basedn.employees}" />
Example for using the cn as the top level of the dn
<Property name="basedn" value="%{jndi.basedn.employees}" />
<Property name="template.create" value="cn=${fullname},ou=People,ou=Employees,%{jndi.basedn.employees}" />
When a create operation is performed the dn will be constructed based on the template.create.
If any other operation is performed, the service will get the actual DN of the record by searching the directory. If a single record is returned it will use the DN of that record for the operation. If no records or more than one record are returned, it will be an error (since the entry is not found or not unique).
A new property will be added to determine which attributes are used to provide uniqueness of the subjects. This is expected to be a list of attributes whose value is unique within the basedn for the context where it is configured. One or more attributes must be present in this property.
<Property name="dn.attributes.unique.value" value="uid,mail,employeenumber" />
In the example above a search would be performed against the directory to determine if a single record can be returned to obtain the entrydn. The values of this property are references to the association in the context being used. The result is a query will be constructed to the ldap server similar to:
(uid=${uniqueid} || mail = ${email} || employeenumber = $employeenumber} )
|