diff options
author | Martin Basti <mbasti@redhat.com> | 2015-04-24 13:37:07 +0200 |
---|---|---|
committer | Petr Vobornik <pvoborni@redhat.com> | 2015-06-11 13:12:31 +0200 |
commit | f8c8c360f1957a39ce98df61752abbfa1df9864b (patch) | |
tree | 51759e4c4ce6e59dd782dcd8fde72a3279f4954d /ipalib/plugins | |
parent | 9aa6124b39267148c4c1b9a8ee4209fb859b9c42 (diff) | |
download | freeipa-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')
-rw-r--r-- | ipalib/plugins/dns.py | 113 |
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): |