At present (as of Knox-0.4.0), LDAP authentication in Knox infers the baseDN of the user using UserDNTemplate and the login id given by client user.
This does not work in enterprises where users could belong to multiple branches of LDAP tree.
This JIRA proposes adding LDAP search to find the bind DN.
Knox uses Apache Shiro for doing authentication of clients using LDAP userId and password.
Knox does this using either JNDILdapRealm bundled with Apache Shiro or KnoxLdapRealm implemented by Apache Knox.
Apache Knox KnoxLdapRealm is a subclass of Apache Shiro JNDILdapRealm, adding group lookup feature.
JNDILdapRealm and KnoxLdapRealm have a configuration parameter ldapRealm.userDnTemplate.
Typical value of userDNTemplate would look like uid={0},ou=people,dc=hadoop,dc=apache,dc=org.
To compute bind DN of the client, we swap the place holder {0} with login id provided by the client.
For example, if the login id provided by the client is "guest', the computed bind DN would be uid=guest,ou=people,dc=hadoop,dc=apache,dc=org.
This keeps configuration simple.
However, this does not work if users belong to different branches of LDAP DIT.
For example, if there are some users under ou=people,dc=hadoop,dc=apache,dc=org and some users under ou=contractors,dc=hadoop,dc=apache,dc=org, we can not come up with userDnTemplate that would work for all the users.
We would add following additional optional configuration parameters: ldapRealm.userSearchAttributeName, ldapRealm.userObjectClass
This is an optional parameter.
There is no default value for this parameter. If a value is specified for this parameter, we would find bind DN by doing ldapsearch.
If no value is specified for this parameter, we compute bind DN using userDnTemplate as we are already doing.
This is an optional parameter with default value of "person".
Assuming,
ldapRealm.userSearchAttributeName=uid
ldapRealm.userObjectClass=person
client specified login id = "guest"
LDAP Filter for doing a search to find the bind DN would be
(&(uid=guest)(objectclass=person))
System bind DN to search for client bind DN is specified by the property ldapRealm.contextFactory.systemUsername.
Password for system bind DN is specified by the property ldapRealm.contextFactory.systemPassword.
Value of ldapRealm.contextFactory.systemPassword can reference password alias using the format ${ALIAS=ldcSystemPassword}.
If the password alias reference is used, password is obtained from credential store at runtime.
Search scope for search to find the client bind DN can be specified with parameter ldapRealm.userSearchBase.
If no value is specified for ldapRealm.userSearchBase, it would default to the value of ldapRealm.searchBase.
New parameters added by this enhancement are shown in bold
<provider>
<role>authentication</role>
<name>ShiroProvider</name>
<enabled>true</enabled>
<param>
<!--
session timeout in minutes, this is really idle timeout,
defaults to 30mins, if the property value is not defined,,
current client authentication would expire if client idles contiuosly for more than this value
-->
<name>sessionTimeout</name>
<value>30</value>
</param>
<param>
<name>main.ldapRealm</name>
<value>org.apache.hadoop.gateway.shirorealm.KnoxLdapRealm</value>
</param>
<param>
<name>main.ldapRealm.contextFactory.url</name>
<value>ldap://localhost:33389</value>
</param>
<!-- optional, default value: simple -->
<param>
<name>main.ldapRealm.contextFactory.authenticationMechanism</name>
<value>simple</value>
</param>
<!-- optional, default value: null -->
<param>
<name>main.ldapRealm.contextFactory.systemUsername</name>
<value>uid=guest,ou=people,dc=hadoop,dc=apache,dc=org</value>
</param>
<!-- optional, default value: null -->
<param>
<name>main.ldapRealm.contextFactory.systemPassword</name>
<!--
<value>${ALIAS=ldcSystemPassword}</value>
-->
<value>guest-password</value>
</param>
<param>
<name>main.ldapRealm.searchBase</name>
<value>dc=hadoop,dc=apache,dc=org</value>
</param>
<!-- optional, default value: empty -->
<param>
<name>main.ldapRealm.userDnTemplate</name>
<value>uid={0},ou=people,dc=hadoop,dc=apache,dc=org</value>
</param>
<!-- optional, default value: null -->
<param>
<name>main.ldapRealm.userSearchAttributeName</name>
<value>uid</value>
</param>
<!-- optional, default value: person -->
<param>
<name>main.ldapRealm.userObjectClass</name>
<value>person</value>
</param>
<!-- optional, default value: value of main.ldapRealm.searchBasae -->
<param>
<name>main.ldapRealm.userSearchBase</name>
<value>ou=people,dc=hadoop,dc=apache,dc=org</value>
</param>
<!-- optional, default value: false -->
<param>
<name>main.ldapRealm.authorizationEnabled</name>
<value>true</value>
</param>
<!-- optional, default value: uid={0} -->
<param>
<name>main.ldapRealm.memberAttributeValueTemplate</name>
<value>uid={0},ou=people,dc=hadoop,dc=apache,dc=org</value>
</param>
<!-- optional, default value: value of main.ldapRealm.searchBasae -->
<param>
<name>main.ldapRealm.groupSearchBase</name>
<value>ou=people,dc=hadoop,dc=apache,dc=org</value>
</param>
<!-- optional, default value: groupOfNames -->
<param>
<name>main.ldapRealm.groupObjectClass</name>
<!--
<value>groupOfNames</value>
-->
<value>groupOfUrls</value>
</param>
<!-- optional, default value: member -->
<param>
<name>main.ldapRealm.memberAttribute</name>
<!--
<value>member</value>
-->
<value>memberUrl</value>
</param>
<!-- optional, default value: cn -->
<param>
<name>main.ldapRealm.groupIdAttribute</name>
<value>cn</value>
</param>
<param>
<name>urls./**</name>
<value>authcBasic</value>
</param>
</provider>