summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPetr Spacek <pspacek@redhat.com>2016-05-17 17:26:20 +0200
committerMartin Basti <mbasti@redhat.com>2016-05-30 20:14:32 +0200
commitdc405005f537cf278fd6ddfe6b87060bd13d9a67 (patch)
treee77d279876f8be3e0ead4c298ed32a7cd0da05f7
parentec49130b94d2aa195c6b704a30fe6c3137fabdbf (diff)
downloadfreeipa-dc405005f537cf278fd6ddfe6b87060bd13d9a67.tar.gz
freeipa-dc405005f537cf278fd6ddfe6b87060bd13d9a67.tar.xz
freeipa-dc405005f537cf278fd6ddfe6b87060bd13d9a67.zip
Move IP address resolution from ipaserver.install.installutils to ipapython.dnsutil
This is to make it reusable from other modules and to avoid future code duplication. https://fedorahosted.org/freeipa/ticket/5710 Reviewed-By: Martin Basti <mbasti@redhat.com>
-rw-r--r--ipapython/dnsutil.py59
-rw-r--r--ipaserver/install/bindinstance.py16
-rw-r--r--ipaserver/install/installutils.py26
3 files changed, 76 insertions, 25 deletions
diff --git a/ipapython/dnsutil.py b/ipapython/dnsutil.py
index 6287e3eef..7fa7646d9 100644
--- a/ipapython/dnsutil.py
+++ b/ipapython/dnsutil.py
@@ -24,6 +24,9 @@ import copy
import six
+from ipapython.ipautil import CheckedIPAddress
+from ipapython.ipa_log_manager import root_logger
+
if six.PY3:
unicode = str
@@ -231,6 +234,62 @@ def inside_auto_empty_zone(name):
return False
+def resolve_rrsets(fqdn, rdtypes):
+ """
+ Get Resource Record sets for given FQDN.
+ CNAME chain is followed during resolution
+ but CNAMEs are not returned in the resulting rrset.
+
+ :returns:
+ set of dns.rrset.RRset objects, can be empty
+ if the FQDN does not exist or if none of rrtypes exist
+ """
+ # empty set of rdtypes would always return empty set of rrsets
+ assert rdtypes, "rdtypes must not be empty"
+
+ if not isinstance(fqdn, DNSName):
+ fqdn = DNSName(fqdn)
+
+ fqdn = fqdn.make_absolute()
+ rrsets = set()
+ for rdtype in rdtypes:
+ try:
+ answer = dns.resolver.query(fqdn, rdtype)
+ root_logger.debug('found %d %s records for %s: %s',
+ len(answer), rdtype, fqdn, ' '.join(
+ str(rr) for rr in answer))
+ rrsets.add(answer.rrset)
+ except dns.resolver.NXDOMAIN as ex:
+ root_logger.debug(ex)
+ break # no such FQDN, do not iterate
+ except dns.resolver.NoAnswer as ex:
+ root_logger.debug(ex) # record type does not exist for given FQDN
+ except dns.exception.DNSException as ex:
+ root_logger.error('DNS query for %s %s failed: %s',
+ fqdn, rdtype, ex)
+ raise
+
+ return rrsets
+
+
+def resolve_ip_addresses(fqdn):
+ """Get IP addresses from DNS A/AAAA records for given host.
+ :returns:
+ list of IP addresses as CheckedIPAddress objects
+ """
+ rrsets = resolve_rrsets(fqdn, ['A', 'AAAA'])
+ ip_addresses = set()
+ for rrset in rrsets:
+ ip_addresses.update({CheckedIPAddress(ip, # accept whatever is in DNS
+ parse_netmask=False,
+ allow_network=True,
+ allow_loopback=True,
+ allow_broadcast=True,
+ allow_multicast=True)
+ for ip in rrset})
+ return ip_addresses
+
+
def check_zone_overlap(zone, raise_on_error=True):
root_logger.info("Checking DNS domain %s, please wait ..." % zone)
if not isinstance(zone, DNSName):
diff --git a/ipaserver/install/bindinstance.py b/ipaserver/install/bindinstance.py
index 2a642422a..ec8526a8e 100644
--- a/ipaserver/install/bindinstance.py
+++ b/ipaserver/install/bindinstance.py
@@ -908,7 +908,9 @@ class BindInstance(service.Service):
if fqdn == self.fqdn:
continue
- addrs = installutils.resolve_host(fqdn)
+ addrs = dnsutil.resolve_ip_addresses(fqdn)
+ # hack, will go away with locations
+ addrs = [str(addr) for addr in addrs]
root_logger.debug("Adding DNS records for master %s" % fqdn)
self.__add_master_records(fqdn, addrs)
@@ -964,7 +966,9 @@ class BindInstance(service.Service):
if dns_zone_exists(zone, self.api):
addrs = get_fwd_rr(zone, host, api=self.api)
else:
- addrs = installutils.resolve_host(fqdn)
+ addrs = dnsutil.resolve_ip_addresses(fqdn)
+ # hack, will go away with locations
+ addrs = [str(addr) for addr in addrs]
self.__add_ipa_ca_records(fqdn, addrs, True)
@@ -1084,7 +1088,9 @@ class BindInstance(service.Service):
if dns_zone_exists(zone, self.api):
addrs = get_fwd_rr(zone, host, api=self.api)
else:
- addrs = installutils.resolve_host(fqdn)
+ addrs = dnsutil.resolve_ip_addresses(fqdn)
+ # hack, will go away with locations
+ addrs = [str(addr) for addr in addrs]
self.domain = domain_name
@@ -1172,7 +1178,9 @@ class BindInstance(service.Service):
if dns_zone_exists(zone, self.api):
addrs = get_fwd_rr(zone, host, api=self.api)
else:
- addrs = installutils.resolve_host(fqdn)
+ addrs = dnsutil.resolve_ip_addresses(fqdn)
+ # hack, will go away with locations
+ addrs = [str(addr) for addr in addrs]
for addr in addrs:
del_fwd_rr(domain_name, IPA_CA_RECORD, addr, api=self.api)
diff --git a/ipaserver/install/installutils.py b/ipaserver/install/installutils.py
index 179909543..2a71ef7ac 100644
--- a/ipaserver/install/installutils.py
+++ b/ipaserver/install/installutils.py
@@ -55,6 +55,7 @@ from ipaserver.install import certs, service, sysupgrade
from ipaplatform import services
from ipaplatform.paths import paths
from ipaplatform.tasks import tasks
+from ipapython import dnsutil
if six.PY3:
unicode = str
@@ -444,24 +445,6 @@ def create_keytab(path, principal):
kadmin("ktadd -k " + path + " " + principal)
-def resolve_host(host_name):
- try:
- addrinfos = socket.getaddrinfo(host_name, None,
- socket.AF_UNSPEC, socket.SOCK_STREAM)
-
- ip_list = []
-
- for ai in addrinfos:
- ip = ai[4][0]
- if ip == "127.0.0.1" or ip == "::1":
- raise HostnameLocalhost("The hostname resolves to the localhost address")
-
- ip_list.append(ip)
-
- return ip_list
- except socket.error:
- return []
-
def get_host_name(no_host_dns):
"""
Get the current FQDN from the socket and verify that it is valid.
@@ -477,9 +460,10 @@ def get_host_name(no_host_dns):
def get_server_ip_address(host_name, unattended, setup_dns, ip_addresses):
# Check we have a public IP that is associated with the hostname
- try:
- hostaddr = resolve_host(host_name)
- except HostnameLocalhost:
+ hostaddr = dnsutil.resolve_ip_addresses(host_name)
+ if hostaddr.intersection(
+ {ipautil.CheckedIPAddress(ip, allow_loopback=True)
+ for ip in ['127.0.0.1', '::1']}):
print("The hostname resolves to the localhost address (127.0.0.1/::1)", file=sys.stderr)
print("Please change your /etc/hosts file so that the hostname", file=sys.stderr)
print("resolves to the ip address of your network interface.", file=sys.stderr)