summaryrefslogtreecommitdiffstats
path: root/ipalib/plugins/dns.py
diff options
context:
space:
mode:
authorMartin Basti <mbasti@redhat.com>2015-04-24 13:37:07 +0200
committerPetr Vobornik <pvoborni@redhat.com>2015-06-11 13:12:31 +0200
commitf8c8c360f1957a39ce98df61752abbfa1df9864b (patch)
tree51759e4c4ce6e59dd782dcd8fde72a3279f4954d /ipalib/plugins/dns.py
parent9aa6124b39267148c4c1b9a8ee4209fb859b9c42 (diff)
downloadfreeipa-f8c8c360f1957a39ce98df61752abbfa1df9864b.tar.gz
freeipa-f8c8c360f1957a39ce98df61752abbfa1df9864b.tar.xz
freeipa-f8c8c360f1957a39ce98df61752abbfa1df9864b.zip
DNSSEC: validate forward zone forwarders
Show warning messages if DNSSEC validation is failing for particular FW zone or if the specified forwarders do not work https://fedorahosted.org/freeipa/ticket/4657 Reviewed-By: David Kupka <dkupka@redhat.com> Reviewed-By: Petr Spacek <pspacek@redhat.com>
Diffstat (limited to 'ipalib/plugins/dns.py')
-rw-r--r--ipalib/plugins/dns.py113
1 files changed, 112 insertions, 1 deletions
diff --git a/ipalib/plugins/dns.py b/ipalib/plugins/dns.py
index c9dc1e547..f47aa7494 100644
--- a/ipalib/plugins/dns.py
+++ b/ipalib/plugins/dns.py
@@ -26,6 +26,7 @@ import re
import binascii
import dns.name
import dns.exception
+import dns.rdatatype
import dns.resolver
import encodings.idna
@@ -45,7 +46,9 @@ from ipalib.util import (normalize_zonemgr,
get_reverse_zone_default, REVERSE_DNS_ZONES,
normalize_zone, validate_dnssec_global_forwarder,
DNSSECSignatureMissingError, UnresolvableRecordError,
- EDNS0UnsupportedError)
+ EDNS0UnsupportedError, DNSSECValidationError,
+ validate_dnssec_zone_forwarder_step1,
+ validate_dnssec_zone_forwarder_step2)
from ipapython.ipautil import CheckedIPAddress, is_host_resolvable
from ipapython.dnsutil import DNSName
@@ -4340,11 +4343,100 @@ class dnsforwardzone(DNSZoneBase):
_add_warning_fw_zone_is_not_effective(result, fwzone,
options['version'])
+ def _warning_if_forwarders_do_not_work(self, result, new_zone,
+ *keys, **options):
+ fwzone = keys[-1]
+ forwarders = options.get('idnsforwarders', [])
+ any_forwarder_work = False
+
+ for forwarder in forwarders:
+ try:
+ validate_dnssec_zone_forwarder_step1(forwarder, fwzone,
+ log=self.log)
+ except UnresolvableRecordError as e:
+ messages.add_message(
+ options['version'],
+ result, messages.DNSServerValidationWarning(
+ server=forwarder, error=e
+ )
+ )
+ except EDNS0UnsupportedError as e:
+ messages.add_message(
+ options['version'],
+ result, messages.DNSServerDoesNotSupportEDNS0Warning(
+ server=forwarder, error=e
+ )
+ )
+ else:
+ any_forwarder_work = True
+
+ if not any_forwarder_work:
+ # do not test DNSSEC validation if there is no valid forwarder
+ return
+
+ # resolve IP address of any DNS replica
+ # FIXME: https://fedorahosted.org/bind-dyndb-ldap/ticket/143
+ # we currenly should to test all IPA DNS replica, because DNSSEC
+ # validation is configured just in named.conf per replica
+
+ ipa_dns_masters = [normalize_zone(x) for x in
+ api.Object.dnsrecord.get_dns_masters()]
+
+ if not ipa_dns_masters:
+ # something very bad happened, DNS is installed, but no IPA DNS
+ # servers available
+ self.log.error("No IPA DNS server can be found, but integrated DNS "
+ "is installed")
+ return
+
+ ipa_dns_ip = None
+ for rdtype in (dns.rdatatype.A, dns.rdatatype.AAAA):
+ try:
+ ans = dns.resolver.query(ipa_dns_masters[0], rdtype)
+ except dns.exception.DNSException:
+ continue
+ else:
+ ipa_dns_ip = str(ans.rrset.items[0])
+ break
+
+ if not ipa_dns_ip:
+ self.log.error("Cannot resolve %s hostname", ipa_dns_masters[0])
+ return
+
+ # sleep a bit, adding new zone to BIND from LDAP may take a while
+ if new_zone:
+ time.sleep(5)
+
+ # Test if IPA is able to receive replies from forwarders
+ try:
+ validate_dnssec_zone_forwarder_step2(ipa_dns_ip, fwzone,
+ log=self.log)
+ except DNSSECValidationError as e:
+ messages.add_message(
+ options['version'],
+ result, messages.DNSSECValidationFailingWarning(error=e)
+ )
+ except UnresolvableRecordError as e:
+ messages.add_message(
+ options['version'],
+ result, messages.DNSServerValidationWarning(
+ server=ipa_dns_ip, error=e
+ )
+ )
@register()
class dnsforwardzone_add(DNSZoneBase_add):
__doc__ = _('Create new DNS forward zone.')
+ def interactive_prompt_callback(self, kw):
+ # show informative message on client side
+ # server cannot send messages asynchronous
+ if kw.get('idnsforwarders', False):
+ self.Backend.textui.print_plain(
+ _("Server will check DNS forwarder(s)."))
+ self.Backend.textui.print_plain(
+ _("This may take some time, please wait ..."))
+
def pre_callback(self, ldap, dn, entry_attrs, attrs_list, *keys, **options):
assert isinstance(dn, DN)
@@ -4364,6 +4456,10 @@ class dnsforwardzone_add(DNSZoneBase_add):
def execute(self, *keys, **options):
result = super(dnsforwardzone_add, self).execute(*keys, **options)
self.obj._warning_fw_zone_is_not_effective(result, *keys, **options)
+ if options.get('idnsforwarders'):
+ print result, keys, options
+ self.obj._warning_if_forwarders_do_not_work(
+ result, True, *keys, **options)
return result
@@ -4378,6 +4474,15 @@ class dnsforwardzone_del(DNSZoneBase_del):
class dnsforwardzone_mod(DNSZoneBase_mod):
__doc__ = _('Modify DNS forward zone.')
+ def interactive_prompt_callback(self, kw):
+ # show informative message on client side
+ # server cannot send messages asynchronous
+ if kw.get('idnsforwarders', False):
+ self.Backend.textui.print_plain(
+ _("Server will check DNS forwarder(s)."))
+ self.Backend.textui.print_plain(
+ _("This may take some time, please wait ..."))
+
def pre_callback(self, ldap, dn, entry_attrs, attrs_list, *keys, **options):
try:
entry = ldap.get_entry(dn)
@@ -4406,6 +4511,12 @@ class dnsforwardzone_mod(DNSZoneBase_mod):
return dn
+ def execute(self, *keys, **options):
+ result = super(dnsforwardzone_mod, self).execute(*keys, **options)
+ if options.get('idnsforwarders'):
+ self.obj._warning_if_forwarders_do_not_work(result, False, *keys,
+ **options)
+ return result
@register()
class dnsforwardzone_find(DNSZoneBase_find):