When ipa-client-install is run without --server option, it tries to search SRV records for IPA/LDAP server hostname, but it returns only the first record found and when the LDAP server on that hostname is not available, the whole client installation fails.
Get all LDAP SRV records instead and fallback to next hostname when the current one is not available. https://fedorahosted.org/freeipa/ticket/3388
From 600b03a759f06a8bdcbf73c2d15ec4c5608a0015 Mon Sep 17 00:00:00 2001 From: Martin Kosek <mko...@redhat.com> Date: Mon, 4 Feb 2013 15:00:14 +0100 Subject: [PATCH] Add LDAP server fallback to client installer When ipa-client-install is run without --server option, it tries to search SRV records for IPA/LDAP server hostname, but it returns only the first record found and when the LDAP server on that hostname is not available, the whole client installation fails. Get all LDAP SRV records instead and fallback to next hostname when the current one is not available. https://fedorahosted.org/freeipa/ticket/3388 --- ipa-client/ipaclient/ipadiscovery.py | 67 +++++++++++++++++++++--------------- 1 file changed, 40 insertions(+), 27 deletions(-) diff --git a/ipa-client/ipaclient/ipadiscovery.py b/ipa-client/ipaclient/ipadiscovery.py index 18b77a684505a61b4958cde678fc58b66c6632fd..f94e62d9f20d85b50eb95d5b0135cbce8916602c 100644 --- a/ipa-client/ipaclient/ipadiscovery.py +++ b/ipa-client/ipaclient/ipadiscovery.py @@ -58,6 +58,7 @@ class IPADiscovery(object): def __init__(self): self.realm = None self.domain = None + self.servers = None self.server = None self.basedn = None @@ -129,9 +130,9 @@ class IPADiscovery(object): break tried.add(domain) - server = self.ipadns_search_srv(domain, '_ldap._tcp', 389) - if server: - return (server[0], domain) + servers = self.ipadns_search_srv(domain, '_ldap._tcp', 389, break_on_first=False) + if servers: + return (servers, domain) else: p = domain.find(".") if p == -1: #no ldap server found and last component of the domain already tested @@ -177,9 +178,9 @@ class IPADiscovery(object): domains = [(domain, 'domain of the hostname')] + domains tried = set() for domain, reason in domains: - server, domain = self.check_domain(domain, tried, reason) - if server: - self.server = server + servers, domain = self.check_domain(domain, tried, reason) + if servers: + self.servers = servers self.domain = domain self.server_source = self.domain_source = ( 'Discovered LDAP SRV records from %s (%s)' % @@ -190,14 +191,15 @@ class IPADiscovery(object): return NO_LDAP_SERVER else: root_logger.debug("Search for LDAP SRV record in %s", domain) - server = self.ipadns_search_srv(domain, '_ldap._tcp', 389) - if server: - self.server = server[0] + servers = self.ipadns_search_srv(domain, '_ldap._tcp', 389, + break_on_first=False) + if servers: + self.servers = servers self.domain = domain self.server_source = self.domain_source = ( 'Discovered LDAP SRV records from %s' % domain) else: - self.server = None + self.servers = None root_logger.debug('No LDAP server found') return NO_LDAP_SERVER @@ -205,7 +207,7 @@ class IPADiscovery(object): root_logger.debug("Server and domain forced") self.domain = domain - self.server = server + self.servers = [server] self.domain_source = self.server_source = 'Forced' #search for kerberos @@ -220,23 +222,34 @@ class IPADiscovery(object): 'Discovered Kerberos DNS records from %s' % self.domain) root_logger.debug("[LDAP server check]") - root_logger.debug('Verifying that %s (realm %s) is an IPA server', - self.server, self.realm) + root_logger.debug('Search for valid IPA server in %s (realm %s)', + self.servers, self.realm) # We may have received multiple servers corresponding to the domain # Iterate through all of those to check if it is IPA LDAP server ldapret = [NOT_IPA_SERVER] ldapaccess = True - if self.server: + if self.servers: # check ldap now - ldapret = self.ipacheckldap(self.server, self.realm, ca_cert_path=ca_cert_path) + for server in self.servers: + root_logger.error("Test if %s is an IPA server", server) + ldapret = self.ipacheckldap(server, self.realm, ca_cert_path=ca_cert_path) - if ldapret[0] == 0: - self.server = ldapret[1] - self.realm = ldapret[2] - self.server_source = self.realm_source = ( - 'Discovered from LDAP DNS records in %s' % self.server) - elif ldapret[0] == NO_ACCESS_TO_LDAP or ldapret[0] == NO_TLS_LDAP: - ldapaccess = False + if ldapret[0] == 0: + self.server = ldapret[1] + self.realm = ldapret[2] + self.server_source = self.realm_source = ( + 'Discovered from LDAP DNS records in %s' % self.server) + break + elif ldapret[0] == NO_ACCESS_TO_LDAP or ldapret[0] == NO_TLS_LDAP: + self.server = server + ldapaccess = False + self.server_soure = ( + 'Discovered from LDAP DNS records in %s (no LDAP access)', + self.server) + break + else: + root_logger.debug( + "Server %s is not available, try next", server) # If one of LDAP servers checked rejects access (maybe anonymous # bind is disabled), assume realm and basedn generated off domain. @@ -258,8 +271,8 @@ class IPADiscovery(object): root_logger.debug("Generated basedn from realm: %s" % self.basedn) root_logger.debug( - "Discovery result: %s; server=%s, domain=%s, kdc=%s, basedn=%s", - error_names.get(ldapret[0], ldapret[0]), + "Discovery result: %s; servers=%s, server=%s, domain=%s, kdc=%s, basedn=%s", + error_names.get(ldapret[0], ldapret[0]), self.servers, self.server, self.domain, self.kdc, self.basedn) return ldapret[0] @@ -339,11 +352,11 @@ class IPADiscovery(object): except LDAPError, err: if isinstance(err, ldap.TIMEOUT): - root_logger.error("LDAP Error: timeout") + root_logger.debug("LDAP Error: timeout") return [NO_LDAP_SERVER] if isinstance(err, ldap.INAPPROPRIATE_AUTH): - root_logger.debug("LDAP Error: Anonymous acces not allowed") + root_logger.debug("LDAP Error: Anonymous access not allowed") return [NO_ACCESS_TO_LDAP] # We should only get UNWILLING_TO_PERFORM if the remote LDAP server @@ -352,7 +365,7 @@ class IPADiscovery(object): root_logger.debug("LDAP server returned UNWILLING_TO_PERFORM. This likely means that minssf is enabled") return [NO_TLS_LDAP] - root_logger.error("LDAP Error: %s: %s" % + root_logger.debug("LDAP Error: %s: %s" % (err.args[0]['desc'], err.args[0].get('info', ''))) return [UNKNOWN_ERROR] -- 1.8.1
_______________________________________________ Freeipa-devel mailing list Freeipa-devel@redhat.com https://www.redhat.com/mailman/listinfo/freeipa-devel