LDAPS: Mailcow <-> LM7.1 mit selbst signiertem Zertifikat

Liebe Kollegen,

ich nutze Mailcow mit der Linuxmustererweiterung (Link).

Mein LDAP Dienst ist von aussen erreichbar und leistet bei Moodle und Nextcloud gute Dienste. Allerdings noch nicht bei Mailcow.

Laut den Logdateien beklagt Mailcow das selbstsignierte Zertifikat des LDAPS Dienstes.

mailcowcustomized_linuxmuster-mailcow  | 2023-07-30 18:22:49 - [INFO] === Starting sync ===
mailcowcustomized_linuxmuster-mailcow  | 2023-07-30 18:22:49 - [INFO] Step 1: Loading current Data from AD
mailcowcustomized_linuxmuster-mailcow  | 2023-07-30 18:22:49 - [INFO]     * Binding to ldap
mailcowcustomized_linuxmuster-mailcow  | 2023-07-30 18:22:49 - [CRITICAL] !!! Error binding to ldap! {'result': -1, 'desc': "Can't contact LDAP server", 'ctrls': [], 'info': 'error:0A000086:SSL routines::certificate verify failed (unable to get local issuer certificate)'} !!!
mailcowcustomized_linuxmuster-mailcow  | 2023-07-30 18:22:49 - [CRITICAL] !!! The sync failed, see above errors !!!
mailcowcustomized_linuxmuster-mailcow  | 2023-07-30 18:22:49 - [INFO] sleeping 30 seconds before next cycle

Bei Moodle und Nextcloud kann man ja Einstellen, dass die Vertrauenswürdigkeit des Zertifikats nicht geprüft werden soll. Bei der Mailcow-Erweiterung geht das wohl nicht, oder? Kann ich alternativ den LDAPS Dienst mit einem gültigen Zertifikat betreiben? Wenn ja, wo fummelt man das ein?

Hallo Heiko,

Bei Moodle und Nextcloud kann man ja Einstellen, dass die
Vertrauenswürdigkeit des Zertifikats nicht geprüft werden soll.

…ich sage es indirekt dem php_ldap Modul, es solle solche Certs
akzeptieren durch den Eintrag von

TLS_REQCERT never

in der Datei /etc/ldap/ldap.conf
(einfach am Ende anfügen).

Bei der
Mailcow-Erweiterung geht das wohl nicht, oder?

mach das oben beschrieben mal und teste dann (vielleicht nach einem
reboot?).
Ansonsten such mal nach
mailcow ldap selfsigned

Kann ich alternativ den
LDAPS Dienst mit einem gültigen Zertifikat betreiben? Wenn ja, wo
fummelt man das ein?

… da gehen die Meinungen darüber, was eine gute Idee ist, auseinander.
Wenn du mich fragst: faß den ldap nicht an: der ist wie er ist und das
ist gut so und dann bekommst du keine seltsamen Nebeneffekte und keine
Probleme beim updaten.
Außerdem weiß ich nicht, ob das nachträglich geht.

Was du machen kannst (was ich auch gemacht habe) und was erschreckend
einfach ist, wenn du irgend wo einen Server mit nginx hast: einen LDAPs
Proxy einrichten.

LG

Holger

Hallo Holger,

wie setzt man den LDAP Proxy um?

LG Heiko

Ich bin einen großen Schritt weiter!

Die LDAPS Verbindung des Linuxmuster-Mailcow Containers funktioniert! Man muss eine Zeile Code in die Pythonscripte einschleusen.

Was muss man tun:

  1. Linuxmuster-Mailcow Container starten
docker-compose up -d linuxmuster-mailcow
  1. Konsolenverbindung zum Container herstellen
docker exec -it <containerID> sh
  1. Mit Vi die Datei ldapHelper.py öffnen
vi ldapHelper.py
  1. Die Codezeile
ldap.set_option(ldap.OPT_X_TLS_REQUIRE_CERT, ldap.OPT_X_TLS_NEVER)

bitte hier einfügen:

import ldap, logging

class LdapHelper:
    def __init__(self, ldapUri, ldapBindDn, ldapBindPassword, ldapBaseDn):
        self._uri = ldapUri
        self._bindDn = ldapBindDn
        self._bindPassword = ldapBindPassword
        self._baseDn = ldapBaseDn


    def bind(self):
        try:
            ldap.set_option(ldap.OPT_X_TLS_REQUIRE_CERT, ldap.OPT_X_TLS_NEVER)
            self._ldapConnection = ldap.initialize(f"{self._uri}")
            self._ldapConnection.set_option(ldap.OPT_REFERRALS, 0)
            self._ldapConnection.simple_bind_s(self._bindDn, self._bindPassword)
            return True
        except Exception as e:
            logging.critical("!!! Error binding to ldap! {} !!!".format(e))
            return False

    def unbind(self):
        if self._ldapConnection != None:
            self._ldapConnection.unbind_s()
            self._ldapConnection = None

    def search(self, filter, attrlist=None):
        if self._ldapConnection == None:
            logging.critical("Cannot talk to LDAP")
            return False, None

        try:
            rawResults = self._ldapConnection.search_s(
                    self._baseDn,
                    ldap.SCOPE_SUBTREE,
                    filter,
                    attrlist
                    )
        except Exception as e:
            logging.critical("Error executing LDAP search!")
            print(e)
            return False, None

        try:
            processedResults =  []

            if len(rawResults) <= 0 or rawResults[0][0] == None:
                return False, None

            for dn, rawResult in rawResults:
                if not dn:
                    continue

                processedResult = {}

                for attribute, rawValue in rawResult.items():
                    try:
                        if len(rawValue) == 1:
                            processedResult[attribute] = str(rawValue[0].decode())
                        elif len(rawValue) > 0:
                            processedResult[attribute] = []
                            for rawItem in rawValue:
                                processedResult[attribute].append(str(rawItem.decode()))

                    except UnicodeDecodeError:
                        continue

                processedResults.append(processedResult)

            return True, processedResults

        except Exception as e:
            print(e)
            return False, None
  1. Den container verlassen. Und ein neues Docker Image für Linuxmuster-Mailcow erzeugen
docker commit <containerID> linuxmuster-mailcow-selfcert:latest
  1. Die Datei docker-compose.override.yml abändern, dass das neue Image verwendet wird.
version: "2.1"
services:
  linuxmuster-mailcow:
#    image: ghcr.io/linuxmuster/linuxmuster-mailcow:latest
#    container_name: mailcowcustomized_linuxmuster-mailcow
    image: linuxmuster-mailcow-selfcert:latest
    container_name: mailcowcustomized_linuxmuster-mailcow
...

  1. Container neustarten:
docker-compose up -d linuxmuster-mailcow
1 „Gefällt mir“