This chapter describes how to setup LDAP support in JBoss Portal
We'll describe here the simple steps that you will need to perform to enable LDAP support in JBoss Portal. For additional information you need to read more about configuration of identity and specific implementations of identity modules
There are two ways to achieve this:
jboss-porta.sar/META-INF/jboss-service.xml in section:
<mbean code="org.jboss.portal.identity.IdentityServiceControllerImpl" name="portal:service=Module,type=IdentityServiceController" xmbean-dd="" xmbean-code="org.jboss.portal.jems.as.system.JBossServiceModelMBean"> <xmbean/> <depends>portal:service=Hibernate</depends> <attribute name="JndiName">java:/portal/IdentityServiceController</attribute> <attribute name="RegisterMBeans">true</attribute> <attribute name="ConfigFile">conf/identity/identity-config.xml</attribute> <attribute name="DefaultConfigFile">conf/identity/standardidentity-config.xml</attribute> </mbean>
change identity-config.xml to ldap_identity-config.xml
Swap the names or content of files in jboss-porta.sar/conf/identity/identity-config.xml and jboss-porta.sar/conf/identity/ldap_identity-config.xml
After doing one of the above changes you need to edit configuration file that you choose to use (identity-config.xml or ldap_identity-config.xml) and configure LDAP connection options in section:
<datasource> <name>LDAP</name> <config> <option> <name>host</name> <value>jboss.com</value> </option> <option> <name>port</name> <value>10389</value> </option> <option> <name>adminDN</name> <value>cn=Directory Manager</value> </option> <option> <name>adminPassword</name> <value>qpq123qpq</value> </option> </config> </datasource>
You also need to specify options for your LDAP tree (described in configuration documentation) like those:
<option-group> <group-name>common</group-name> <option> <name>userCtxDN</name> <value>ou=People,dc=portal26,dc=jboss,dc=com</value> </option> <option> <name>roleCtxDN</name> <value>ou=Roles,dc=portal26,dc=jboss,dc=com</value> </option> </option-group>
The setup is very similar to the one described in LdapLoginModule wiki page
You need to modify your identity configuration file and add "protocol"
<datasource> <name>LDAP</name> <config> ... <option> <name>protocol</name> <value>ssl</value> </option> ... </config> </datasource>
Then you need to have LDAP server certificate imported into your keystore. You can use following command:
keytool -import -file ldapcert.der -keystore ldap.truststore
Now you need to change the settings to use the alternative truststore. That can be done in the properties-service.xml in deploy directory:
<attribute name="Properties"> javax.net.ssl.trustStore=../some/path/to/ldap.truststore javax.net.ssl.trustStorePassword=somepw </attribute>
Instead of configuring your own connection you can use JNDI context federation mechanism in JBoss Application Server. Configuration of ExternalContext is described in JBoss Application Server documentation
When you have ExternalContext configured you can use it in JBoss Portal by providing proper JNDI name in the configuration:
<datasource> <name>LDAP</name> <config> <option> <name>externalContextJndiName</name> <value>external/ldap/jboss</value> </option> </config> </datasource>
JBoss Portal comes with base LDAP implementation of all identity modules.
For all modules you can set two config options:
Table 16.1. Comparision of UserModule implementations
Features | UserModule | |
---|---|---|
LDAPUserModuleImpl | LDAPExtUserModuleImpl | |
User creation | X | - |
User removal | X | - |
User search | Flat - one level scope | Flexible filter - sub tree scope |
This is the base implementation of LDAP UserModule. It supports user creation, but will retrieve users and create them in strictly specified place in LDAP tree.
To enable it in your configuration you should have:
<module> <!--type used to correctly map in IdentityContext registry--> <type>User</type> <implementation>LDAP</implementation> <config/> </module>
org.jboss.portal.identity.ldap.LDAPUserModuleImpl configuration option-groups options:
Example configuration:
<option-group> <group-name>common</group-name> <option> <name>userCtxDN</name> <value>ou=People,o=portal,dc=my-domain,dc=com</value> </option> <option> <name>uidAttributeID</name> <value>uid</value> </option> <option> <name>passwordAttributeID</name> <value>userPassword</value> </option> </option-group> <option-group> <group-name>userCreateAttibutes</group-name> <option> <name>objectClass</name> <!--This objectclasses should work with Red Hat Directory--> <value>top</value> <value>person</value> <value>inetOrgPerson</value> </option> <!--Schema requires those to have initial value--> <option> <name>cn</name> <value>none</value> </option> <option> <name>sn</name> <value>none</value> </option> </option-group>
Aim of this implementation is to give more flexibility for users retrieval. You can specify LDAP filter that will be used for searches. This module doesn't support user creation and removal
To enable it in your configuration you should have:
<module> <!--type used to correctly map in IdentityContext registry--> <type>User</type> <implementation>LDAP</implementation> <class>org.jboss.portal.identity.ldap.LDAPExtUserModuleImpl</class> <config/> </module
org.jboss.portal.identity.ldap.LDAPExtUserModuleImpl configuration option-groups options:
Table 16.2. Comparision of RoleModule implementations
Features | RoleModule | |
---|---|---|
LDAPRoleModuleImpl | LDAPExtRoleModuleImpl | |
Role creation | X | - |
Role removal | X | - |
Role search | Flat - one level scope | Flexible filter - sub tree scope |
This is the base implementation of LDAP RoleModule. It supports user creation, but will retrieve roles and create them in strictly specified place in LDAP tree.
To enable it in your configuration you should have:
<module> <!--type used to correctly map in IdentityContext registry--> <type>Role</type> <implementation>LDAP</implementation> <config/> </module>
org.jboss.portal.identity.ldap.LDAPRoleModuleImpl configuration option-groups options:
Aim of this implementation is to give more flexibility for roless retrieval. You can specify LDAP filter that will be used for searches. This module doesn't support role creation and removal
This module doesn't support role creation and removal
To enable it in your configuration you should have:
<module> <!--type used to correctly map in IdentityContext registry--> <type>Role</type> <implementation>LDAP</implementation> <class>org.jboss.portal.identity.ldap.LDAPExtRoleModuleImpl</class> <config/> </module>
org.jboss.portal.identity.ldap.LDAPExtRoleModuleImpl configuration option-groups options:
/** Get a range of users.*/ Set findUsers(int offset, int limit) throws IdentityException, IllegalArgumentException; /** Get a range of users.*/ Set findUsersFilteredByUserName(String filter, int offset, int limit) throws IdentityException, IllegalArgumentException;Pagination support is not widely implemented in LDAP servers. Because UserModule implementations rely on JNDI and are targetted to be LDAP server agnostic those methods aren't very effecient. As long as you don't rely on portal user management and use dedicated tools for user provisioning it shouldn't bother you. Otherwise you should consider extending the implementation and providing solution dedicated to your LDAP server.
Table 16.3. Comparision of MembershipModule implementations
Features | MembershipModule | |
---|---|---|
LDAPStaticGroupMembershipModuleImpl | LDAPStaticRoleMembershipModuleImpl | |
Role assignment stored in LDAP role entry | X | - |
Role assignment stored in LDAP user entry | - | X |
User/Role relationship creation | X | X |
This module support tree shape where role entries keep information about users that are their members.
To enable it in your configuration you should have:
<module> <!--type used to correctly map in IdentityContext registry--> <type>Membership</type> <implementation>LDAP</implementation> <config/> </module>
org.jboss.portal.identity.ldap.LDAPStaticGroupMembershipModuleImpl configuration option-groups options:
This module support tree shape where user entries keep information about roles that they belong to.
To enable it in your configuration you should have:
<module> <!--type used to correctly map in IdentityContext registry--> <type>Membership</type> <implementation>LDAP</implementation> <class>org.jboss.portal.identity.ldap.LDAPStaticRoleMembershipModuleImpl</class> <config/> </module>
org.jboss.portal.identity.ldap.LDAPStaticRoleMembershipModuleImpl configuration option-groups options:
This is standard implementation that enables to retrieve user properties from atributes in LDAP entries.
To enable it in your configuration you should have:
<module> <type>UserProfile</type> <implementation>DELEGATING</implementation> <config> <option> <name>ldapModuleJNDIName</name> <value>java:/portal/LDAPUserProfileModule</value> </option> </config> </module> <module> <type>DBDelegateUserProfile</type> <implementation>DB</implementation> <config> <option> <name>randomSynchronizePassword</name> <value>true</value> </option> </config> </module> <module> <type>LDAPDelegateUserProfile</type> <implementation>LDAP</implementation> <config/> </module>
org.jboss.portal.identity.ldap.LDAPUserModuleImpl configuration option-groups options:
JBoss Portal supports full user/role management for simple LDAP tree shapes. Some more flexible trees can be supported by LdapExtUserModuleImpl and LdapExtRoleModuleImpl - but without user/role creation and removal capabilities. However if you have complex LDAP tree you should consider using SynchronizingLoginModule described in Authentication chapter along with dedicated tools for user provisioning provided with LDAP server.
In following subsections we will describe two base LDAP tree shapes along with example LDIFs and portal identity modules configurations. Those two examples differ only by using different MembershipModule implementations and describe only tree shapes with supported user/role creation and removal capabilities.
In this example, information about users/roles assignment is stored in roles entries using LDAP "member". Of course any other attribute that comes with schema can be used for this.
Example tree shape in LDAP browser
dn: dc=example,dc=com objectclass: top objectclass: dcObject objectclass: organization dc: example o: example dn: ou=People,dc=example,dc=com objectclass: top objectclass: organizationalUnit ou: People dn: uid=user,ou=People,dc=example,dc=com objectclass: top objectclass: inetOrgPerson objectclass: person uid: user cn: JBoss Portal user sn: user userPassword: user mail: [email protected] dn: uid=admin,ou=People,dc=example,dc=com objectclass: top objectclass: inetOrgPerson objectclass: person uid: admin cn: JBoss Portal admin sn: admin userPassword: admin mail: [email protected] dn: ou=Roles,dc=example,dc=com objectclass: top objectclass: organizationalUnit ou: Roles dn: cn=User,ou=Roles,dc=example,dc=com objectClass: top objectClass: groupOfNames cn: User description: the JBoss Portal user group member: uid=user,ou=People,dc=example,dc=com dn: cn=Admin,ou=Roles,dc=example,dc=com objectClass: top objectClass: groupOfNames cn: Echo description: the JBoss Portal admin group member: uid=admin,ou=People,dc=example,dc=com
<modules> <module> <!--type used to correctly map in IdentityContext registry--> <type>User</type> <implementation>LDAP</implementation> <config/> </module> <module> <type>Role</type> <implementation>LDAP</implementation> <config/> </module> <module> <type>Membership</type> <implementation>LDAP</implementation> <config/> </module> <module> <type>UserProfile</type> <implementation>DELEGATING</implementation> <config> <option> <name>ldapModuleJNDIName</name> <value>java:/portal/LDAPUserProfileModule</value> </option> </config> </module> <module> <type>DBDelegateUserProfile</type> <implementation>DB</implementation> <config> <option> <name>randomSynchronizePassword</name> <value>true</value> </option> </config> </module> <module> <type>LDAPDelegateUserProfile</type> <implementation>LDAP</implementation> <config/> </module> </modules> <options> <option-group> <group-name>common</group-name> <option> <name>userCtxDN</name> <value>ou=People,dc=example,dc=com</value> </option> <option> <name>roleCtxDN</name> <value>ou=Roles,dc=example,dc=com</value> </option> </option-group> <option-group> <group-name>userCreateAttibutes</group-name> <option> <name>objectClass</name> <!--This objectclasses should work with Red Hat Directory--> <value>top</value> <value>person</value> <value>inetOrgPerson</value> </option> <!--Schema requires those to have initial value--> <option> <name>cn</name> <value>none</value> </option> <option> <name>sn</name> <value>none</value> </option> </option-group> <option-group> <group-name>roleCreateAttibutes</group-name> <!--Schema requires those to have initial value--> <option> <name>cn</name> <value>none</value> </option> <!--Some directory servers require this attribute to be valid DN--> <!--For safety reasons point to the admin user here--> <option> <name>member</name> <value>uid=admin,ou=People,dc=example,dc=com</value> </option> </option-group> </options>
In this example, information about users/roles assignment is stored in user entries using LDAP "memberOf". Of course any other attribute that comes with schema can be used for this.
Example tree shape in LDAP browser
dn: dc=example,dc=com objectclass: top objectclass: dcObject objectclass: organization dc: example o: example dn: o=example2,dc=example,dc=com objectclass: top objectclass: organization o: example2 dn: ou=People,o=example2,dc=example,dc=com objectclass: top objectclass: organizationalUnit ou: People dn: uid=admin,ou=People,o=example2,dc=example,dc=com objectclass: top objectclass: inetOrgPerson objectclass: inetUser uid: admin cn: JBoss Portal admin sn: admin userPassword: admin mail: [email protected] memberOf: cn=Admin,ou=Roles,o=example2,dc=example,dc=com dn: uid=user,ou=People,o=example2,dc=example,dc=com objectclass: top objectclass: inetOrgPerson objectclass: inetUser uid: user cn: JBoss Portal user sn: user userPassword: user mail: [email protected] memberOf: cn=User,ou=Roles,o=example2,dc=example,dc=com dn: ou=Roles,o=example2,dc=example,dc=com objectclass: top objectclass: organizationalUnit ou: Roles dn: cn=User,ou=Roles,o=example2,dc=example,dc=com objectClass: top objectClass: organizationalRole cn: User description: the JBoss Portal user group dn: cn=Admin,ou=Roles,o=example2,dc=example,dc=com objectClass: top objectClass: organizationalRole cn: Echo description: the JBoss Portal admin group
<modules> <module> <!--type used to correctly map in IdentityContext registry--> <type>User</type> <implementation>LDAP</implementation> <config/> </module> <module> <type>Role</type> <implementation>LDAP</implementation> <config/> </module> <module> <type>Membership</type> <implementation>LDAP</implementation> <class>org.jboss.portal.identity.ldap.LDAPStaticRoleMembershipModuleImpl</class> <config/> </module> <module> <type>UserProfile</type> <implementation>DELEGATING</implementation> <config> <option> <name>ldapModuleJNDIName</name> <value>java:/portal/LDAPUserProfileModule</value> </option> </config> </module> <module> <type>DBDelegateUserProfile</type> <implementation>DB</implementation> <config> <option> <name>randomSynchronizePassword</name> <value>true</value> </option> </config> </module> <module> <type>LDAPDelegateUserProfile</type> <implementation>LDAP</implementation> <config/> </module> </modules> <options> <option-group> <group-name>common</group-name> <option> <name>userCtxDN</name> <value>ou=People,dc=example,dc=com</value> </option> <option> <name>roleCtxDN</name> <value>ou=Roles,dc=example,dc=com</value> </option> <option> <name>membershipAttributeID</name> <value>memberOf</value> </option> </option-group> <option-group> <group-name>userCreateAttibutes</group-name> <option> <name>objectClass</name> <!--This objectclasses should work with Red Hat Directory--> <value>top</value> <value>person</value> <value>inetOrgPerson</value> </option> <!--Schema requires those to have initial value--> <option> <name>cn</name> <value>none</value> </option> <option> <name>sn</name> <value>none</value> </option> </option-group> <option-group> <group-name>roleCreateAttibutes</group-name> <!--Schema requires those to have initial value--> <option> <name>cn</name> <value>none</value> </option> <!--Some directory servers require this attribute to be valid DN--> <!--For safety reasons point to the admin user here--> <option> <name>member</name> <value>uid=admin,ou=People,dc=example,dc=com</value> </option> </option-group> </options>
Like it was described in previous section, you can meet some limitations in identity modules support for more complex LDAP tree shapes. To workaround this you can use identity synchronization on JAAS level. JBoss Portal comes with SynchronizingLoginModule that can be easily configured with other authentication solutions that support JAAS framework. Here we want to provide a simple example on how it can be integrated with LdapExtLoginModule from JBossSX framework.
First of all portal identity modules should be configured to work with portal database - default configuration. This is important as we will leverage them, and we want to synchronize users identity into default portal storage mechanism. So lets look at simple configuration that should take place in jboss-portal.sar/conf/login-config.xml
<policy> <!-- For the JCR CMS --> <application-policy name="cms"> <authentication> <login-module code="org.apache.jackrabbit.core.security.SimpleLoginModule" flag="required"/> </authentication> </application-policy> <application-policy name="portal"> <authentication> <login-module code="org.jboss.security.auth.spi.LdapExtLoginModule" flag="required"> <module-option name="java.naming.factory.initial">com.sun.jndi.ldap.LdapCtxFactory </module-option> <module-option name="java.naming.provider.url">ldap://example.com:10389/ </module-option> <module-option name="java.naming.security.authentication">simple</module-option> <module-option name="bindDN">cn=Directory Manager</module-option> <module-option name="bindCredential">lolo</module-option> <module-option name="baseCtxDN">ou=People,dc=example,dc=com</module-option> <module-option name="baseFilter">(uid={0})</module-option> <module-option name="rolesCtxDN">ou=Roles,dc=example,dc=com</module-option> <module-option name="roleFilter">(member={1})</module-option> <module-option name="roleAttributeID">cn</module-option> <module-option name="roleRecursion">-1</module-option> <module-option name="searchTimeLimit">10000</module-option> <module-option name="searchScope">SUBTREE_SCOPE</module-option> <module-option name="allowEmptyPasswords">false</module-option> </login-module> <login-module code="org.jboss.portal.identity.auth.SynchronizingLoginModule" flag="optional"> <module-option name="synchronizeIdentity">true</module-option> <module-option name="synchronizeRoles">true</module-option> <module-option name="additionalRole">Authenticated</module-option> <module-option name="defaultAssignedRole">User</module-option> <module-option name="userModuleJNDIName">java:/portal/UserModule</module-option> <module-option name="roleModuleJNDIName">java:/portal/RoleModule</module-option> <module-option name="membershipModuleJNDIName">java:/portal/MembershipModule </module-option> <module-option name="userProfileModuleJNDIName">java:/portal/UserProfileModule </module-option> </login-module> </authentication> </application-policy> </policy>
Few things are important in this configuration:
LDAP servers support depends on few conditions. In most cases they differ in schema support - various objectClass objects are not present by default in server schema. Sometimes it can be workarounded by manually extending schema.
Servers can be
Table 16.4. Support of identity modules with different LDAP servers
LDAP Server | UserModule | RoleModule | MembershipModule | UserProfileModule | |||
---|---|---|---|---|---|---|---|
LDAPUserModuleImpl | LDAPExtUserModuleImpl | LDAPRoleModuleImpl | LDAPExtRoleModuleImpl | LDAPStaticGroupMembershipModuleImpl | LDAPStaticRoleMembershipModuleImpl | LDAPUserProfileModuleImpl | |
Red Hat Directory Server | Supported | Supported | Supported | Supported | Supported | Supported | Supported |
OpenDS | Supported | Supported | Supported | Supported | Supported | Not Supported | Supported |
OpenLDAP | Supported | Supported | Supported | Supported | Supported | Not Supported | Supported |