How we proxyed OpenLDAP to AD via cn=config

I want to dedicate this post to a case from a large IT project that our company was doing. As part of the project, a large number of services were implemented, and for them it was necessary to provide LDAP authentication for the following operations:

– Access to GUI-interfaces of services

– Access via SSH to servers where services are running, with access restriction based on user membership in groups of the LDAP directory

The customer already had a Microsoft Active Directory directory service deployed. The requirement of the project was the absence of direct access between the implemented services and AD. On the service side, the parameters of AD service accounts should not have been written. Also, only one host was allowed network access to the MS AD controller.

Under the cut – details on how we solved this problem.

To solve this problem, we chose OpenLDAP in the mode of proxying authentication requests towards MS AD controllers. To enter the servers, we used the SSSD module, which processes LDAP(S) requests with additional filtering by MS Active Directory groups.

The task of proxying requests through OpenLDAP does not look like something difficult. There is enough information on the Internet on this subject. The catch was that they basically describe how the OpenLDAP configuration is done through the sladp.conf file. However, starting with OpenLDAP 2.4, configuration is not done using slapd.conf, but via the cn=config LDAP configuration context. The option to configure via slapd.conf has been deprecated and is no longer supported. There are very few similar examples of settings through cn=config in the public domain.

In the article I tried my best describe in detail the technique for configuring OpenLDAP 2.6 and SSSD via cn=config on Rocky Linux 8.5 and describe how we solved the problems that arose in the process.

Installing OpenLDAP

To install OpenLDAP, follow these steps:

1. Install dependencies:

# dnf install wget vim cyrus-sasl-devel libtool-ltdl-devel openssl-devel libdb-devel make libtool autoconf tar gcc perl perl-devel -y

2. Connect the Symas repository to download OpenLDAP from it:

#wget -q https://repo.symas.com/configs/SOFL/rhel8/sofl.repo -O /etc/yum.repos.d/sofl.repo

3. Install the server and client parts of OpenLDAP:

#dnf install symas-openldap-clients symas-openldap-servers -y

4. Add OpenLDAP (slapd.service) to startup and enable the service:

#systemctl enable slapd

#systemctl start slapd

Setting up OpenLDAP

On the OpenLDAP server (opld.test.local in our example), you need to do the following:

1. Add information about BASE and URI to the /etc/openldap file:

BASE    dc=test,dc=local

URI     ldap://opld.test.local ldaps://opld.test.local:636

2. When OpenLDAP is running in proxy mode, the Microsoft Active Directory domain controller will be the backend database of the LDAP type for OpenLDAP. To be able to connect OpenLDAP to a domain controller, the back_ldap module must be loaded.

For this:

a. Verify that the back_ldap.la file exists on the OpenLDAP server. If it is not present, then this library must be loaded onto the OpenLDAP server.

b. Create an ldif file like this:

dn: cn=module,cn=config

objectClass: olcModuleList

cn: module

olcModulePath: /usr/lib64/openldap

olcModuleLoad: back_ldap.la

c. Load back_ldap.ldif file into OpenLDAP server configuration:

#ldapadd -Y EXTERNAL -H ldapi:/// -f back_ldap.ldif

3. Create a backend database of the ldap type, which will be Active Directory:

a. Create ldap_db.ldif file as:

dn: olcDatabase=ldap,cn=config

objectClass: olcDatabaseConfig

objectClass: olcLDAPConfig

olcDatabase: ldap

olcDbIDAssertBind: bindmethod="simple" binddn="CN=tech_test_local,OU=Tech

 Accounts,DC=test,DC=local" credentials="password"

olcDbURI: ldaps://dc01.test.local

olcReadOnly: TRUE

olcRootDN: cn=openldap,dc=test,dc=local

olcRootPW: password

olcSuffix: dc=test,dc=local

olcDbChaseReferrals: FALSE

· olcDbIDAssertBind: Specifies the connection method, distinguishedName, and ID password to connect to the MS Active Directory controller.

· olcDbURI: AD controller URI

· olcReadOnly: Operating mode (read/write) with MS Active Directory.

· olcRootDN: OpenLDAP service root. With it, services will be connected to OpenLDAP.

· olcRootPW: OpenLDAP Service OZ Password

· olcSuffix: Domain suffix

· olcDbChaseReferrals: Determines whether the referral mechanism can be used

To encrypt the olcRootPW password, run the command:

# slappasswd -s password

and specify the generated hash value in the olcRootPW attribute.

b. Run the following command on the OpenLDAP server:

#ldapadd -Y EXTERNAL -H ldapi:/// -f ldap_db.ldif

  1. Set up a secure TLS connection between OpenLDAP and AD.

The certificate chains of the CAs that issued the certificates for the domain controller must be provided:

a. Put the certificate chain (cacerts.pem) on the OpenLDAP server (for example, in /etc/openldap/certs).

b. Specify the path to the certificate in the /etc/openldap/ldap.conf file:

TLS_CACERT      /etc/openldap/certs/cacerts.pem

5. Provide the ability to connect services to OpenLDAP via LDAPS:

a. Issue a key and certificate for the OpenLDAP server. Put the certificate (oldap.crt) and key (oldap.key) on the OpenLDAP server (for example, in /etc/openldap/certs).

b. Create opldcert.ldif file:

dn: cn=config

objectClass: olcDatabaseConfig

objectClass: olcLDAPConfig

olcDatabase: cn=config

changetype: add

olcTLSCertificateFile: /etc/openldap/certs/oldap.crt

olcTLSCertificateFileKey: /etc/openldap/certs/oldap.key

olcTLSVerifyClient: never

c. Run command:

#ldapadd -Y EXTERNAL -H ldapi:/// -f opldcert.ldif

This completes the configuration of OpenLDAP in proxy mode. After completing this configuration, the server can process incoming LDAP/LDAPS requests from clients and proxy requests to the MS Active Directory domain controller. A secure connection is configured between the OpenLDAP server and the MS Active Directory domain controller.

Below I will describe the implementation of setting up the SSSD module in terms of SSH authentication to client servers, taking into account filtering according to membership in MS Active Directory groups.

Setting up the SSSD service

  1. Install SSSD packages:

    # sudo yum install sssd-tools sssd oddjob oddjob-mkhomedir samba-common-tools

  2. Configure the ldap.conf file on the client servers. Download the OpenLDAP server certificate and set the path to it:

    URI   ldap://opld.test.local ldaps://opld.test.local:636

    BASE  dc=test,dc=local

    TLS_CACERT  /etc/openldap/certs/oldap.crt

    TLS_CACERTDIR /etc/openldap/certs

    <![if !supportLineBreakNewLine]>

    <![endif]>

  3. Create sssd.conf file. (etc/sssd/sssd.conf):

    [domain/test.local]

    ldap_schema = ad

    id_provider = ldap

    autofs_provider = ldap

    auth_provider = ldap

    chpass_provider = ldap

    ldap_uri = ldaps://opld.test.local:636

    ldap_search_base = dc=test,dc=local

    ldap_id_use_start_tls = True

    ldap_tls_cacertdir = /etc/openldap/certs

    cache_credentials = False

    ldap_tls_reqcert = allow

    ldap_default_bind_dn = cn=openldap,dc=test,dc=local

    ldap_default_authtok_type = obfuscated_password

    ldap_default_authtok = #зашифровать и ввести в следующем шаге

    ldap_access_order = filter

    ldap_id_mapping = True

    ldap_referrals = False

    access_provider = ldap

    ldap_access_filter = (|(memberOf= CN=Admins,DC=test,DC=local)(memberOf=CN=Support,DC=test,DC=local))

    use_fully_qualified_names = False

    # Object Mappings

    ldap_user_object_class = user

    ldap_user_name = sAMAccountName

    ldap_group_object_class = group

    ldap_group_name = cn

    # ID Mappings

    ldap_user_objectsid = objectSid

    ldap_group_objectsid = objectSid

    ldap_idmap_range_size = 1048576

    ldap_user_primary_group = primaryGroupID

    override_homedir = /mnt/home/%u

    default_shell = /bin/bash

    fallback_homedir = /home/%u@%d

    [sssd]

    config_file_version = 2

    services = nss, pam,autofs

    domains = test.local

    [nss]

    homedir_substring = /home

    In the example below, I used the ldap_access_filter parameter with AD groups (Admins, TechSupport). Only those users who are members of these MS AD groups will be able to connect to the server.

  4. Give permissions to the sssd.conf file:

    # chmod 600 /etc/sssd/sssd.conf

  5. To prevent the password from being stored in clear text, encrypt it:

    # sss_obfuscate -d test.local

  6. Add to the /etc/hosts file or configure the OpenLDAP address on your DNS server:

    # (IP OpenLDAP)  opld.test.local

  7. Restart sssd, test the service with the id command:

    # systemctl restart sssd.service

    #id {username}

    #User Found (id=1234567) # Пример вывода строки, найденного пользователя

  8. Switch Linux login profile to use sssd (LDAP authentication):

    # authselect select sssd --force

  9. Set up sudo rights for domain accounts:

    # echo "sudoers:    files sss" >> /etc/nsswitch.conf

  10. Ensure creation of home directories for domain users:

    # systemctl enable --now oddjobd

    # echo "session optional pam_oddjob_mkhomedir.so skel=/etc/skel/ umask=0022" >> /etc/pam.d/system-auth
    # systemctl restart oddjobd

  11. Check if SSSD is working:

    # sssctl domain-status test.local

  12. If you get this kind of output, then SSSD is configured correctly, you can try to authenticate to the server:

    # sssctl domain-status test.local

     Online status: Online

     Active servers:

    LDAP: test.local

     Discovered LDAP servers:

    - test.local

If you get Offline status, then you made a mistake at some stage above, check again.

Problems and solution

After connecting one of the systems and setting up LDAP authentication, we found a problem that authentication in the Web UI did not pass. The same problem was noticed when trying to authenticate via SSH. The authentication session was timed out. This behavior was found if the whole domain was searched. At the same time, if we narrowed the search boundaries, for example, to the level of only a certain OU, then the problem went away, and users could authenticate.

Client calls to OpenLDAP and OpenLDAP to MS AD were dumped. They found out that when searching the entire domain, in addition to the response to the request, there was an appeal to DomainDNSZones using the Referrals mechanism.

Referral is the process by which the LDAP server, instead of returning the result of the query, returns a link (referral) to another LDAP server or, in our case, a domain controller, which may contain additional information. When receiving a referral to DomainDNSZones, OpenLDAP made a request to MS AD domain controllers to which there was no network access. In this regard, the session from the OpenLDAP server to MS AD hung, and then it was interrupted by a timeout.

Accordingly, to solve the problem, it was necessary to find a way to manage referrals. Basically, all articles related to this problem described settings using the slapd.conf configuration file, and not cn=config.

Examining the OpenLDAP schema, the olcDbChaseReferrals parameter was found, which was precisely responsible for sending when accessing MS AD. If you use the value olcDbChaseReferrals=FALSE, then LDAP, when receiving a referral to DomainDNSZones, ignores this and does not contact other domain controllers.

In the documentation for SSSD, we also found a parameter responsible for sending – ldap_referrals. After applying this parameter with the value FALSE SSSD has stopped crashing and losing connection with the domain controller.

Another interesting point that we noticed was related to configuring access filtering based on membership in AD groups. We saw that after setting up the filter, users could not access the server. The problem was that when subtracting objects from SSSD, they were not assigned the correct unique ID. The ID was generated by the Linux machine itself, and should have been obtained in the objectSID attribute from MS Active Directory. Thus, SSSD could not obtain a correct list of the AD groups that the user is a member of (SSSD must match user and group IDs from the ldap_user_objectsid and ldap_group_objectsid attributes instead of relying on Linux-generated IDs). The solution to the problem was to use the parameter ldap_id_mapping with meaning TRUE.

I hope this post was helpful and helped solve problems faster. If someone has a similar experience in the settings, share your knowledge, I will be ready to update and supplement the article with fresh information.

Post author: senior presale engineer Vladislav Alyoshin

Similar Posts

Leave a Reply

Your email address will not be published. Required fields are marked *