Skip to main content
Version: Release 23.3

LDAP Authentication

This topic describes how to configure Release to use an LDAP repository to authenticate users and retrieve role, group, membership.

Digital.ai Release has a role-based security system with two types of users:

  • Internal users that are managed by Digital.ai Release
  • External users that are maintained in an LDAP repository such as Active Directory

In Digital.ai Release, LDAP users and groups become principals that you can assign to roles. Global permissions are assigned at the role level. For more information, see configure permissions.

Role memberships and permissions that are assigned to roles are stored in the database. Release treats the LDAP repository as read-only, which means that it will use information from the LDAP repository, but that it cannot make changes to that information.

note

Release cookies store security information that is provided by the Spring Security framework. Release does not store any additional information in cookies.

Configure Release to use an LDAP repository

To configure Release to use an LDAP repository, you must modify the xl-release-security.xml security configuration file. The following is an example of an xl-release-security.xml file that uses LDAP. Values that you must provide are highlighted.

important

Do not copy the entire sample. We recommend that you add the following items only: LDAP_SERVER_URL, MANAGER_DN, MANAGER_PASSWORD, GROUP_SEARCH_BASE, GROUP_SEARCH_FILTER, USER_SEARCH_BASE, USER_SEARCH_FILTER, GROUP_EMAIL_SEARCH_BASE, GROUP_EMAIL_SEARCH_FILTER, GROUP_EMAIL_SEARCH_TIME_LIMIT_IN_MS, GROUP_EMAIL_ATTRIBUTE_NAME, and EXTERNAL_ID_ATTRIBUTE_NAME. This sample may differ from your xl-release-security.xml file, depending on your version of Release and any other customizations that you have made.

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:security="http://www.springframework.org/schema/security"
xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security.xsd">

<bean id="ldapServer" class="org.springframework.security.ldap.DefaultSpringSecurityContextSource">
<constructor-arg value="LDAP_SERVER_URL"/>
<property name="userDn" value="MANAGER_DN"/>
<property name="password" value="MANAGER_PASSWORD"/>
<property name="baseEnvironmentProperties">
<map>
<entry key="java.naming.referral">
<value>ignore</value>
</entry>
</map>
</property>
</bean>

<bean id="userSearch" class="org.springframework.security.ldap.search.FilterBasedLdapUserSearch">
<constructor-arg index="0" value="USER_SEARCH_BASE"/>
<constructor-arg index="1" value="USER_SEARCH_FILTER"/>
<constructor-arg index="2" ref="ldapServer"/>
</bean>

<bean id="bindAuthenticator" class="org.springframework.security.ldap.authentication.BindAuthenticator">
<constructor-arg ref="ldapServer"/>
<property name="userSearch" ref="userSearch"/>
</bean>

<bean id="authoritiesPopulator" class="org.springframework.security.ldap.userdetails.DefaultLdapAuthoritiesPopulator">
<constructor-arg ref="ldapServer"/>
<constructor-arg value="GROUP_SEARCH_BASE"/>
<property name="groupSearchFilter" value="GROUP_SEARCH_FILTER"/>
<property name="rolePrefix" value=""/>
<property name="searchSubtree" value="true"/>
<property name="convertToUpperCase" value="false"/>
</bean>

<bean id="ldapGroupEmailProvider" class="com.xebialabs.xlrelease.principaldata.LdapGroupEmailProvider">
<constructor-arg index="0" value="GROUP_EMAIL_SEARCH_BASE"/>
<constructor-arg index="1" value="GROUP_EMAIL_SEARCH_FILTER"/>
<constructor-arg index="2" ref="ldapServer"/>
<property name="searchSubtree" value="true"/>
<property name="searchTimeLimit" value="GROUP_EMAIL_SEARCH_TIME_LIMIT_IN_MS"/>
<property name="groupEmailAttribute" value="GROUP_EMAIL_ATTRIBUTE_NAME"/>
</bean>

<bean id="ldapProvider" class="com.xebialabs.xlrelease.security.authentication.LdapAuthenticationProvider">
<constructor-arg ref="bindAuthenticator"/>
<constructor-arg ref="authoritiesPopulator"/>
<constructor-arg ref="ldapGroupEmailProvider"/>
<!-- Set optional external id attribute if required -->
<property name="externalIdAttribute" value="EXTERNAL_ID_ATTRIBUTE_NAME"/>
</bean>

<bean id="userDetailsService" class="org.springframework.security.ldap.userdetails.LdapUserDetailsService">
<constructor-arg index="0" ref="userSearch"/>
<constructor-arg index="1" ref="authoritiesPopulator"/>
</bean>

<bean id="rememberMeAuthenticationProvider" class="com.xebialabs.deployit.security.authentication.RememberMeAuthenticationProvider"/>

<security:authentication-manager alias="authenticationManager">
<security:authentication-provider ref="rememberMeAuthenticationProvider"/>
<security:authentication-provider ref="xlAuthenticationProvider"/>
<security:authentication-provider ref="ldapProvider"/>
</security:authentication-manager>

</beans>

Update the security XML file

  1. Update xl-release-security.xml with information about your LDAP setup:
PlaceholderDescriptionExample
LDAP_SERVER_URLLDAP URL to connect to.ldap://localhost:389/
MANAGER_DNPrincipal to perform the initial bind to the LDAP server.cn=admin,dc=example,dc=com
MANAGER_PASSWORDCredentials to perform the initial bind to the LDAP server. For more information, see configure custom passwords.secret
USER_SEARCH_FILTERLDAP filter to determine the LDAP dn for the user who is logging in; {0} will be replaced with the user name.(&amp;(uid={0})(objectClass=inetOrgPerson))
USER_SEARCH_BASELDAP filter to use as a basis for searching for users.dc=example,dc=com
GROUP_SEARCH_FILTERLDAP filter to determine the group memberships of the user; {0} will be replaced with the dn of the user.(member={0})
GROUP_SEARCH_BASELDAP filter to use as a basis for searching for groups.ou=groups,dc=example,dc=com
GROUP_EMAIL_SEARCH_BASELDAP filter to use as a basis for searching for mailing groups.ou=groups,dc=example,dc=com
GROUP_EMAIL_SEARCH_FILTERLDAP filter to determine the mailing group; {0} will be replaced with the dn of the group.(cn={0})
GROUP_EMAIL_SEARCH_TIME_LIMIT_IN_MSLDAP request time limit in milliseconds.1000
GROUP_EMAIL_ATTRIBUTE_NAMELDAP attribute to determine a mailing group mail.mail
EXTERNAL_ID_ATTRIBUTE_NAMELDAP attribute to determine an external id.employeeId
  1. After you provide values, restart the Release server.
  2. Add the group as principals in the Release interface and assign the permission to group to log in.
  3. Use an LDAP browser such as JXplorer to verify that the credentials are correct.

Allow users of a certain group to login only

The following sample grants access to users of a certain group only.

Important: Do not copy the entire sample. We recommend that you add the following items only: ldap://192.168.0.1:389, cn=admin,dc=test,dc=com, myPassword, and (&(objectclass=posixAccount)(entryDN=cn={0},cn=MY_AD_GROUP,ou=Security,ou=Groups,ou=France,ou=Regions,dc=test,dc=com) only. This sample may differ from your xl-release-security.xml file, depending on your version of Release and any other customizations that you have made.

Note: This is based on an openldap implementation. Filter queries may differ based on your LDAP setup and vendor.

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:security="http://www.springframework.org/schema/security"
xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security.xsd
">

<bean id="ldapServer" class="org.springframework.security.ldap.DefaultSpringSecurityContextSource">
<constructor-arg value="ldap://192.168.0.1:389"/>
<property name="userDn" value="cn=admin,dc=test,dc=com"/>
<property name="password" value="myPassword"/>
<property name="baseEnvironmentProperties">
<map>
<entry key="java.naming.referral" value="ignore"/>
</map>
</property>
</bean>

<bean id="userSearch" class="org.springframework.security.ldap.search.FilterBasedLdapUserSearch">
<constructor-arg index="0" value="dc=test,dc=com"/>
<!-- Use this LDAP filter query to allow only users from a specific Organisational Unit -->
<constructor-arg index="1"
value="(&(objectclass=posixAccount)(entryDN=cn={0},cn=MY_AD_GROUP,ou=Security,ou=Groups,ou=France,ou=Regions,dc=test,dc=com)"/>
<constructor-arg index="2" ref="ldapServer"/>
</bean>

<bean id="bindAuthenticator" class="org.springframework.security.ldap.authentication.BindAuthenticator">
<constructor-arg ref="ldapServer"/>
<property name="userSearch" ref="userSearch"/>
</bean>

<bean id="authoritiesPopulator" class="org.springframework.security.ldap.userdetails.DefaultLdapAuthoritiesPopulator">
<constructor-arg ref="ldapServer"/>
<constructor-arg value="ou=users,o=mycorp"/>
<property name="groupSearchFilter" value="(&(objectclass=group)(member={0}))"/>
<property name="rolePrefix" value=""/>
<property name="searchSubtree" value="true"/>
<property name="convertToUpperCase" value="false"/>
</bean>

<bean id="ldapProvider" class="com.xebialabs.xlrelease.security.authentication.LdapAuthenticationProvider">
<constructor-arg ref="bindAuthenticator"/>
<constructor-arg ref="authoritiesPopulator"/>
</bean>

<bean id="userDetailsService" class="org.springframework.security.ldap.userdetails.LdapUserDetailsService">
<constructor-arg index="0" ref="userSearch"/>
<constructor-arg index="1" ref="authoritiesPopulator"/>
</bean>

<bean id="rememberMeAuthenticationProvider" class="com.xebialabs.deployit.security.authentication.RememberMeAuthenticationProvider"/>

<security:authentication-manager alias="authenticationManager">
<security:authentication-provider ref="rememberMeAuthenticationProvider"/>
<security:authentication-provider ref="xlAuthenticationProvider"/>
<security:authentication-provider ref="ldapProvider"/>
</security:authentication-manager>

</beans>

Escaping special characters

You must escape the following special characters in xl-release-security.xml:

CharacterEscape with
&&amp;
"&quot;
'&apos;
<&lt;
>&gt;

Assign a default role to all authenticated users

If you have an LDAP setup and do not have a group that contains all Release users, and want to use such a group in the default xlAuthenticationProvider, you can configure this in the xl-release-security.xml file.

The following example creates a group called everyone that is assigned to each authenticated user. You can then link this group to a Release role and assign a global permission to it. For more information, see configure permissions.

<beans>
...

<bean id="ldapProvider" class="com.xebialabs.xlrelease.security.authentication.LdapAuthenticationProvider">
<constructor-arg>
...
</constructor-arg>

<property name="authoritiesMapper" ref="additionalAuthoritiesMapper" />
</bean>

<bean id="xlAuthenticationProvider" autowire="constructor" class="com.xebialabs.xlrelease.security.authentication.ReleaseAuthenticationProvider">
<property name="authoritiesMapper" ref="additionalAuthoritiesMapper" />
</bean>

<bean id="additionalAuthoritiesMapper" class="com.xebialabs.deployit.security.AdditionalAuthoritiesMapper">
<property name="additionalAuthorities">
<list>
<value>everyone</value>
</list>
</property>
</bean>

</beans>

Setting up team security

To set up team security:

  1. Set up an LDAP/Active Directory group called devs. This group will be used by the members of a team in Release. Note: See your directory services documentation for details on how to configure a group.
  2. Assign the devs group to a role in Release called Developers.
    1. In the top navigation bar, click User management.
    2. Click Roles.
    3. Click New role.
    4. In the Role name field, type Developers.
    5. Click Save.
  3. At the folder or release level, add permissions for a team called Dev Team that contains the Release role Developers. This role contains the created LDAP/Active Directory group called devs.

When you log in as a user to the devs group using LDAP/Active Directory, you will have the permissions for the Developers role at the folder or release level.

LDAP data caching

To ensure a high level of performance, Release caches user data for 30 minutes and a group email for 1 minute. This can produce a small delay between updates in your LDAP repository when they appear in Release.

Sample setup and configuration with OpenLDAP

Follow the steps mentioned below to set up LDAP:

  1. Start Docker on your host.
  2. Start an OpenLDAP container. docker run -p 389:389 -p 636:636 --name ldap-service -h ldap-service -e LDAP_ORGANISATION="XL" -e LDAP_DOMAIN="xl.com" -e LDAP_ADMIN_PASSWORD="password" -d osixia/openldap:latest Tip: This exposes LDAP over port 389 and LDAPS over port 636. Both ports are configurable.
  3. Start a phpLDAPadmin container to serve the WebUI to the new LDAP. docker run -p 6443:443 --name phpldapadmin-service -h phpldapadmin-service --link ldap-service:ldap-host -e PHPLDAPADMIN_LDAP_HOSTS=ldap-host --detach osixia/phpldapadmin:latest Tip: This will run phpLDAPadmin at your host's port 6443 (configurable), which connects to the OpenLDAP service running in the container in step 2.
  4. Access the phpLDAPadmin WebUI at https://localhost:6443.
  5. Log in as admin with the right login DN (same as below if your LDAP domain name is xl.com as well). Login Credential: ID : cn=admin,dc=xl,dc=com Password: password
  6. Populate the LDAP server with the users and groups by the below steps:
    1. Select Create new entry here
    2. Select Generic: Organisational Unit and create OU name = users.
    3. Click users and click Create a child entry
    4. Select Default
    5. Select inetOrgPerson, organizationalPerson, person from the ObjectClasses dropdown and click proceed.
    6. Change RDN to cn (cn) and fill the rest of the information.
    7. Click proceed and commit to create users.
    8. Click admin and then click Create new entry here.
    9. Select Generic: Organisational Unit and create OU name = group.
    10. Click groups and then click Create new entry here.
    11. Click Default
    12. Select groupOfNames,mailGroup from the ObjectClasses dropdown and click proceed.
    13. Change RDN to cn (cn) and fill the rest of the information.
    14. Fill the name of the group in cn, email, add members by searching.
    15. Click proceed and commit to create a group.
  7. Configure conf/xl-release security.xml file with LDAP connection. Add the below LDAP connection string to your xl-release security.xml file:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:security="http://www.springframework.org/schema/security"
xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security.xsd
">

<bean id="ldapServer" class="org.springframework.security.ldap.DefaultSpringSecurityContextSource">
<constructor-arg value="ldap://localhost:389/"/>
<property name="userDn" value="cn=admin,dc=xl,dc=com"/>
<property name="password" value="password"/>
<property name="baseEnvironmentProperties">
<map>
<entry key="java.naming.referral">
<value>ignore</value>
</entry>
</map>
</property>
</bean>

<bean id="userSearch" class="org.springframework.security.ldap.search.FilterBasedLdapUserSearch">
<constructor-arg index="0" value="dc=xl,dc=com"/>
<constructor-arg index="1" value="(&amp;(uid={0})(objectClass=inetOrgPerson))"/>
<constructor-arg index="2" ref="ldapServer"/>
</bean>

<bean id="bindAuthenticator" class="org.springframework.security.ldap.authentication.BindAuthenticator">
<constructor-arg ref="ldapServer" />
<property name="userSearch" ref="userSearch"/>
</bean>

<bean id="authoritiesPopulator" class="org.springframework.security.ldap.userdetails.DefaultLdapAuthoritiesPopulator">
<constructor-arg ref="ldapServer"/>
<constructor-arg value="ou=groups,dc=xl,dc=com"/>
<property name="groupSearchFilter" value="(member={0})"/>
<property name="rolePrefix" value=""/>
<property name="searchSubtree" value="true"/>
<property name="convertToUpperCase" value="false"/>
</bean>

<bean id="ldapGroupEmailProvider" class="com.xebialabs.xlrelease.principaldata.LdapGroupEmailProvider">
<constructor-arg index="0" value="ou=groups,dc=example,dc=org" />
<constructor-arg index="1" value="(cn={0})" />
<constructor-arg index="2" ref="ldapServer" />
<property name="searchSubtree" value="true" />
<property name="searchTimeLimit" value="1000" />
<property name="groupEmailAttribute" value="mail" />
</bean>

<bean id="ldapProvider" class="com.xebialabs.xlrelease.security.authentication.LdapAuthenticationProvider">
<constructor-arg ref="bindAuthenticator"/>
<constructor-arg ref="authoritiesPopulator"/>
<constructor-arg ref="ldapGroupEmailProvider"/>
</bean>

<bean id="userDetailsService" class="org.springframework.security.ldap.userdetails.LdapUserDetailsService">
<constructor-arg index="0" ref="userSearch"/>
<constructor-arg index="1" ref="authoritiesPopulator"/>
</bean>

<bean id="rememberMeAuthenticationProvider" class="com.xebialabs.deployit.security.authentication.RememberMeAuthenticationProvider"/>

<security:authentication-manager alias="authenticationManager">
<security:authentication-provider ref="rememberMeAuthenticationProvider"/>
<security:authentication-provider ref="xlAuthenticationProvider"/>
<security:authentication-provider ref="ldapProvider"/>
</security:authentication-manager>

</beans>