LDAP security

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

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

This topic describes how to configure Release to use an LDAP repository to authenticate users and retrieve role, group, membership. In 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 Release JCR repository . 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.

Setup and configuration LDAP with Release

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: `

ignore

<security:authentication-manager alias=“authenticationManager”> <security:authentication-provider ref=“rememberMeAuthenticationProvider” /> <security:authentication-provider ref=“ldapProvider” /> <security:authentication-provider ref=“internalAuthenticationProvider”/> </security:authentication-manager>

`

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, and GROUP_EMAIL_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="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="ldapProvider" class="com.xebialabs.xlrelease.security.authentication.LdapAuthenticationProvider">
        <constructor-arg>
            <bean class="org.springframework.security.ldap.authentication.BindAuthenticator">
                <constructor-arg ref="ldapServer" />
                <property name="userSearch">
                    <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>
                </property>
            </bean>
        </constructor-arg>
        <constructor-arg ref="authoritiesPopulator"/>
        <constructor-arg>
            <bean 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>
        </constructor-arg>
    </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"/>

    <bean id="internalAuthenticationProvider" class="com.xebialabs.deployit.security.authentication.XlAuthenticationProvider"/>

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

</beans>

Update the security XML file

  1. Update xl-release-security.xml with information about your LDAP setup:
Placeholder Description Example
LDAP_SERVER_URL LDAP URL to connect to. ldap://localhost:1389/
MANAGER_DN Principal to perform the initial bind to the LDAP server. cn=admin,dc=example,dc=com
MANAGER_PASSWORD Credentials to perform the initial bind to the LDAP server. For more information, see configure custom passwords. secret
USER_SEARCH_FILTER LDAP 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_BASE LDAP filter to use as a basis for searching for users. dc=example,dc=com
GROUP_SEARCH_FILTER LDAP filter to determine the group memberships of the user; {0} will be replaced with the dn of the user. (memberUid={0})
GROUP_SEARCH_BASE LDAP filter to use as a basis for searching for groups. ou=groups,dc=example,dc=com
GROUP_EMAIL_SEARCH_BASE LDAP filter to use as a basis for searching for mailing groups. ou=groups,dc=example,dc=com
GROUP_EMAIL_SEARCH_FILTER LDAP filter to determine the mailing group; {0} will be replaced with the dn of the group. (cn={0})
GROUP_EMAIL_SEARCH_TIME_LIMIT_IN_MS LDAP request time limit in milliseconds. 1000
GROUP_EMAIL_ATTRIBUTE_NAME LDAP attribute to determine a mailing group mail. mail
  1. After you provide values, restart the Release server.
  2. Add the user and group as principals in the Release interface and assign them permission 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. Values that you must provide are highlighted.

Important: It is recommended that you add the highlighted items only, instead of copying the entire sample. 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.

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="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>
    <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="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="ldapUserSearch" 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="ldapProvider" class="com.xebialabs.xlrelease.security.authentication.LdapAuthenticationProvider">
        <constructor-arg>
            <bean class="org.springframework.security.ldap.authentication.BindAuthenticator">
                <constructor-arg ref="ldapServer" />
                <property name="userSearch" ref="ldapUserSearch"/>
            </bean>
        </constructor-arg>
        <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>

</beans>

Escaping special characters

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

Character Escape 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="internalAuthenticationProvider" class="com.xebialabs.deployit.security.authentication.XlAuthenticationProvider">
        <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.

Security XML example with Active Directory

The following setup example is specific to an Active Directory LDAP configuration:

<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="(&amp;(sAMAccountName={0})(objectClass=user))" />
        <constructor-arg index="2" ref="ldapServer" />
    </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="ldapProvider" class="com.xebialabs.xlrelease.security.authentication.LdapAuthenticationProvider">
        <constructor-arg>
            <bean class="org.springframework.security.ldap.authentication.BindAuthenticator">
                <constructor-arg ref="ldapServer" />
                <property name="userSearch" ref="userSearch"/>
            </bean>
        </constructor-arg>
        <constructor-arg ref="authoritiesPopulator"/>
        <constructor-arg>
            <bean 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="1000" />
                <property name="groupEmailAttribute" value="mail" />
            </bean>
        </constructor-arg>
    </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"/>

    <bean id="internalAuthenticationProvider" class="com.xebialabs.deployit.security.authentication.XlAuthenticationProvider"/>

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

</beans>