From f2ee4a5d6b02fb9e005b0dc3bfc861129a12b569 Mon Sep 17 00:00:00 2001 From: Nausherwan Khan Date: Fri, 30 Aug 2024 17:38:52 +0100 Subject: [PATCH] Add support for connecting to multiple LDAP hosts by iterating over space-separated host strings This update enhances the LDAP client by allowing it to connect to multiple LDAP servers. The 'Host' field now accepts a space-separated string of LDAP host addresses. The `Connect` method iterates over these hosts, attempting to establish a connection with each one until a successful connection is made. Key changes: - Split the 'Host' field into individual host addresses. - Iterated over each host to attempt a connection. - Implemented error handling to try the next host if a connection fails. - Updated the connection logic to support both non-SSL and SSL connections, including handling TLS upgrades. This change improves the robustness of the LDAP client by ensuring that the application can failover to another LDAP server if the primary server is unavailable. --- utils/ldap/ldap.go | 67 +++++++++++++++++++++++++++++----------------- 1 file changed, 42 insertions(+), 25 deletions(-) diff --git a/utils/ldap/ldap.go b/utils/ldap/ldap.go index 5acf0242..9f58eb35 100644 --- a/utils/ldap/ldap.go +++ b/utils/ldap/ldap.go @@ -82,39 +82,56 @@ type LDAPClient struct { // Connect connects to the ldap backend. func (lc *LDAPClient) Connect() error { if lc.Conn == nil { + // Split the space-separated host string into a slice of hosts + hosts := strings.Split(lc.Host, " ") + var l *ldap.Conn var err error - address := fmt.Sprintf("%s:%d", lc.Host, lc.Port) - if !lc.UseSSL { - l, err = ldap.Dial("tcp", address) - if err != nil { - return err - } - - // Reconnect with TLS - if !lc.SkipTLS { - err = l.StartTLS(&tls.Config{InsecureSkipVerify: true}) + + + // Iterate over each host and attempt to connect + for _, host := range hosts { + address := fmt.Sprintf("%s:%d", host, lc.Port) + if !lc.UseSSL { + l, err = ldap.Dial("tcp", address) if err != nil { - return err + continue // Try the next host + } + + // Reconnect with TLS + if !lc.SkipTLS { + err = l.StartTLS(&tls.Config{InsecureSkipVerify: true}) + if err != nil { + l.Close() // Close the connection before trying the next host + continue // Try the next host + } + } + } else { + config := &tls.Config{ + InsecureSkipVerify: lc.InsecureSkipVerify, + ServerName: lc.ServerName, + } + if lc.ClientCertificates != nil && len(lc.ClientCertificates) > 0 { + config.Certificates = lc.ClientCertificates + } + l, err = ldap.DialTLS("tcp", address, config) + if err != nil { + continue // Try the next host } } - } else { - config := &tls.Config{ - InsecureSkipVerify: lc.InsecureSkipVerify, - ServerName: lc.ServerName, - } - if lc.ClientCertificates != nil && len(lc.ClientCertificates) > 0 { - config.Certificates = lc.ClientCertificates - } - l, err = ldap.DialTLS("tcp", address, config) - if err != nil { - return err - } + + lc.Conn = l + return nil // Successfully connected to a host } - lc.Conn = l + // If no connection was successful, return the last error encountered + if err != nil { + return err + } + return errors.New("failed to connect to any LDAP server") } - return nil + + return nil // Already connected } // Close closes the ldap backend connection.