On 28.4.2016 16:14, Martin Basti wrote:
> 
> 
> On 22.04.2016 14:35, Petr Spacek wrote:
>> On 12.4.2016 17:26, Martin Basti wrote:
>>>
>>> On 04.04.2016 17:37, Petr Spacek wrote:
>>>> On 31.3.2016 13:45, Martin Basti wrote:
>>>>> On 21.03.2016 16:51, Petr Spacek wrote:
>>>>>> On 10.3.2016 22:17, Lukas Slebodnik wrote:
>>>>>>> On (10/03/16 22:14), Petr Spacek wrote:
>>>>>>>> Hello,
>>>>>>>>
>>>>>>>> I forgot to send a patches before I leave, so here it is:
>>>>>>>>
>>>>>>>> Auto-detect default value for --forward-policy option in installers
>>>>>>>>
>>>>>>>> See
>>>>>>>> https://fedorahosted.org/freeipa/ticket/5710
>>>>>>>> commit messages, and design page
>>>>>>>> https://fedorahosted.org/bind-dyndb-ldap/wiki/BIND9/Design/AutomaticEmptyZones
>>>>>>>>
>>>>>>>>
>>>>>>>>
>>>>>>>>
>>>>>>>>
>>>>>>>> I did not have time to test it thoroughly but it LGTM :-D
>>>>>>>>
>>>>>>>> Please note that this is first part, it does not solve upgrade (yet) 
>>>>>>>> and
>>>>>>>> warnings in forwardzone-* interface.
>>>>>>>>
>>>>>>>> This can be solved in another patch set, this can be pushed if it 
>>>>>>>> passes
>>>>>>>> review.
>>>>>>>>
>>>>>>> ENOPATH
>>>>>> LOL, here it is.
>>>>>>
>>>>>>
>>>>>>
>>>>>    * Remove function ipapython.ipautil.host_exists() *
>>>>> ACK
>>>>>
>>>>>
>>>>> * Extend installers with --forward-policy option *
>>>>> 1)
>>>>> There is no --forward-policy option in ipa-dns-install
>>>>>
>>>>>
>>>>> * Move automatic empty zone list into ipapython.dnsutil and make it
>>>>> reusable *
>>>>> ACK
>>>>>
>>>>>
>>>>> * Add assert_absolute_dnsname() helper to ipapython.dnsutil *
>>>>> ACK
>>>>>
>>>>>
>>>>> * Move function is_auto_empty_zone() into ipapython.dnsutil *
>>>>> ACK
>>>>>
>>>>>
>>>>> * Use shared sanity check and tests 
>>>>> ipapython.dnsutil.is_auto_empty_zone() *
>>>>> ACK
>>>>>
>>>>> * Add function ipapython.dnsutil.inside_auto_empty_zone() *
>>>>> ACK
>>>>>
>>>>> * Auto-detect default value for --forward-policy option in installers *
>>>>> LGTM, but ipa-dns-install is missing option --forward-policy
>>>>>
>>>>> # ipa-dns-install
>>>>> ...
>>>>> Unexpected error - see /var/log/ipaserver-install.log for details:
>>>>> AttributeError: Values instance has no attribute 'forward_policy'
>>>>>
>>>>>
>>>>> Summary: 6 ACKs, 1 LGTM, 1 NACK => NACK
>>>> Thank you very much for review.
>>>>
>>>> Here is my second attempt :-)
>>>>
>>> Hello,
>>> code works as expected, but it is quite inconsistent with current behavior
>>>
>>> ipa-server-install --forward-policy should raise error without --setup-dns
>>> option
>>>
>>> Like here:
>>> [root@vm-058-134 ~]# ipa-server-install --forwarder=10.2.3.4
>>> Usage: ipa-server-install [options]
>>>
>>> ipa-server-install: error: You cannot specify a --forwarder option without 
>>> the
>>> --setup-dns option
>>> ipa.ipapython.install.cli.install_tool(Server): ERROR    The
>>> ipa-server-install command failed. See /var/log/ipaserver-install.log for 
>>> more
>>> information
>>>
>>> Martin
>> Fixed patches are attached. Thank you for your time!
>>
> almost ack but patches need rebase on  ipa-4-3

Here you go.

-- 
Petr^2 Spacek
From b23ec012a7adbc2a81775677eda6c901bfa21384 Mon Sep 17 00:00:00 2001
From: Petr Spacek <pspa...@redhat.com>
Date: Mon, 7 Mar 2016 10:52:35 +0100
Subject: [PATCH] Remove function ipapython.ipautil.host_exists()

The function duplicated ipalib.util.verify_host_resolvable() in slightly
incompatible way because it used NSS while rest of IPA is using only DNS.
---
 install/tools/ipa-replica-manage | 15 +++++++++------
 ipapython/ipautil.py             | 14 --------------
 2 files changed, 9 insertions(+), 20 deletions(-)

diff --git a/install/tools/ipa-replica-manage b/install/tools/ipa-replica-manage
index 8414fe9aeed50a20f142c7a29b6c7973adb62408..83fb9ab2ffbea195fc7f9b6549915dad99a092d3 100755
--- a/install/tools/ipa-replica-manage
+++ b/install/tools/ipa-replica-manage
@@ -38,9 +38,8 @@ from ipaserver.install import opendnssecinstance, dnskeysyncinstance
 from ipapython import version, ipaldap
 from ipalib import api, errors, util
 from ipalib.constants import CACERT
-from ipalib.util import (create_topology_graph,
-    get_topology_connection_errors, has_managed_topology)
-from ipapython.ipa_log_manager import *
+from ipalib.util import has_managed_topology, verify_host_resolvable
+from ipapython.ipa_log_manager import root_logger, standard_logging_setup
 from ipapython.dn import DN
 from ipapython.config import IPAOptionParser
 from ipaclient import ipadiscovery
@@ -744,10 +743,14 @@ def check_last_link(delrepl, realm, dirman_passwd, force):
 
 
 def enforce_host_existence(host, message=None):
-    if host is not None and not ipautil.host_exists(host):
+    if host is None:
+        return
+
+    try:
+        verify_host_resolvable(host, root_logger)
+    except errors.DNSNotARecordError as ex:
         if message is None:
-            message = "Unknown host %s" % host
-
+            message = "Unknown host %s: %s" % (host, ex)
         sys.exit(message)
 
 def ensure_last_services(conn, hostname, masters, options):
diff --git a/ipapython/ipautil.py b/ipapython/ipautil.py
index 878d51d26c08a5dce34e3095a830595b925c7cbe..6eac6679e0799139f7399e2965b0eefee1e9440f 100644
--- a/ipapython/ipautil.py
+++ b/ipapython/ipautil.py
@@ -1014,20 +1014,6 @@ def bind_port_responder(port, socket_type=socket.SOCK_STREAM, socket_timeout=Non
         raise last_socket_error # pylint: disable=E0702
 
 
-def host_exists(host):
-    """
-    Resolve the host to see if it exists.
-
-    Returns True/False
-    """
-    try:
-        socket.getaddrinfo(host, 80)
-    except socket.gaierror:
-        return False
-    else:
-        return True
-
-
 def reverse_record_exists(ip_address):
     """
     Checks if IP address have some reverse record somewhere.
-- 
2.5.5

From d9f6fad12fa52c6ce18fd4e6656baef18bf8bba4 Mon Sep 17 00:00:00 2001
From: Petr Spacek <pspa...@redhat.com>
Date: Tue, 1 Mar 2016 11:13:18 +0100
Subject: [PATCH] Extend installers with --forward-policy option

This option specified forward policy for global forwarders.
The value is put inside /etc/named.conf.

https://fedorahosted.org/freeipa/ticket/5710
---
 install/share/bind.named.conf.template  | 2 +-
 install/tools/ipa-dns-install           | 3 +++
 install/tools/man/ipa-dns-install.1     | 3 +++
 install/tools/man/ipa-replica-install.1 | 3 +++
 install/tools/man/ipa-server-install.1  | 3 +++
 ipaserver/install/bindinstance.py       | 7 +++++--
 ipaserver/install/dns.py                | 4 ++--
 ipaserver/install/server/common.py      | 9 +++++++++
 ipaserver/install/server/install.py     | 5 +++--
 9 files changed, 32 insertions(+), 7 deletions(-)

diff --git a/install/share/bind.named.conf.template b/install/share/bind.named.conf.template
index 3c19383c0dde4353b30b16240ec2b81d7ea65776..eb6d4ae278f8646a25e18ed95989b8b0c4d89d28 100644
--- a/install/share/bind.named.conf.template
+++ b/install/share/bind.named.conf.template
@@ -8,7 +8,7 @@ options {
 	statistics-file		"data/named_stats.txt";
 	memstatistics-file	"data/named_mem_stats.txt";
 
-	forward first;
+	forward $FORWARD_POLICY;
 	forwarders {$FORWARDERS};
 
 	// Any host is permitted to issue recursive queries
diff --git a/install/tools/ipa-dns-install b/install/tools/ipa-dns-install
index c4d32b449b34dd45781945ce65e95d49e1028fec..50547be7d8704ce6c2a18fd42566a05ca2e8f463 100755
--- a/install/tools/ipa-dns-install
+++ b/install/tools/ipa-dns-install
@@ -52,6 +52,9 @@ def parse_options():
     parser.add_option("--auto-forwarders", dest="auto_forwarders",
                       action="store_true", default=False,
                       help="Use DNS forwarders configured in /etc/resolv.conf")
+    parser.add_option("--forward-policy", dest="forward_policy",
+                      choices=("first", "only"), default="first",
+                      help="DNS forwarding policy for global forwarders")
     parser.add_option("--reverse-zone", dest="reverse_zones",
                       default=[], action="append", metavar="REVERSE_ZONE",
                       help="The reverse DNS zone to use. This option can be used multiple times")
diff --git a/install/tools/man/ipa-dns-install.1 b/install/tools/man/ipa-dns-install.1
index a997eb84153fd0b28a8fcbf6a475a3a0361429fe..e3739e2bbeeccfb24721faa0a5da5600ee145f7c 100644
--- a/install/tools/man/ipa-dns-install.1
+++ b/install/tools/man/ipa-dns-install.1
@@ -41,6 +41,9 @@ Do not add any DNS forwarders, send non\-resolvable addresses to the DNS root se
 \fB\-\-auto\-forwarders\fR
 Add DNS forwarders configured in /etc/resolv.conf to the list of forwarders used by IPA DNS.
 .TP
+\fB\-\-forward\-policy\fR=\fIfirst|only\fR
+DNS forwarding policy for global forwarders specified using other options. Defaults to first.
+.TP
 \fB\-\-reverse\-zone\fR=\fIREVERSE_ZONE\fR
 The reverse DNS zone to use. This option can be used multiple times to specify multiple reverse zones.
 .TP
diff --git a/install/tools/man/ipa-replica-install.1 b/install/tools/man/ipa-replica-install.1
index 68976e7f9d40e79df409d8ad61e38ea61fb292dd..6875f4e416adea502b7c3136060f231212e60ef1 100644
--- a/install/tools/man/ipa-replica-install.1
+++ b/install/tools/man/ipa-replica-install.1
@@ -149,6 +149,9 @@ Do not add any DNS forwarders. Root DNS servers will be used instead.
 \fB\-\-auto\-forwarders\fR
 Add DNS forwarders configured in /etc/resolv.conf to the list of forwarders used by IPA DNS.
 .TP
+\fB\-\-forward\-policy\fR=\fIfirst|only\fR
+DNS forwarding policy for global forwarders specified using other options. Defaults to first.
+.TP
 \fB\-\-reverse\-zone\fR=\fIREVERSE_ZONE\fR
 The reverse DNS zone to use. This option can be used multiple times to specify multiple reverse zones.
 .TP
diff --git a/install/tools/man/ipa-server-install.1 b/install/tools/man/ipa-server-install.1
index 242b41b774081b7b2ab2848bf3a2b872c8efce94..e5f6f760bf854f3e36a5372504e7c1b8c8acb9b1 100644
--- a/install/tools/man/ipa-server-install.1
+++ b/install/tools/man/ipa-server-install.1
@@ -158,6 +158,9 @@ Do not add any DNS forwarders. Root DNS servers will be used instead.
 \fB\-\-auto\-forwarders\fR
 Add DNS forwarders configured in /etc/resolv.conf to the list of forwarders used by IPA DNS.
 .TP
+\fB\-\-forward\-policy\fR=\fIfirst|only\fR
+DNS forwarding policy for global forwarders specified using other options. Defaults to first.
+.TP
 \fB\-\-reverse\-zone\fR=\fIREVERSE_ZONE\fR
 The reverse DNS zone to use. This option can be used multiple times to specify multiple reverse zones.
 .TP
diff --git a/ipaserver/install/bindinstance.py b/ipaserver/install/bindinstance.py
index f8ae9734218f1aacac57583ab7c1a6e9cbbada25..6de880644c7ddcf802f84607259ac0a22ea0bb0f 100644
--- a/ipaserver/install/bindinstance.py
+++ b/ipaserver/install/bindinstance.py
@@ -610,15 +610,17 @@ class BindInstance(service.Service):
 
     suffix = ipautil.dn_attribute_property('_suffix')
 
-    def setup(self, fqdn, ip_addresses, realm_name, domain_name, forwarders, ntp,
-              reverse_zones, named_user=constants.NAMED_USER, zonemgr=None,
+    def setup(self, fqdn, ip_addresses, realm_name, domain_name, forwarders,
+              forward_policy, ntp, reverse_zones,
+              named_user=constants.NAMED_USER, zonemgr=None,
               ca_configured=None, no_dnssec_validation=False):
         self.named_user = named_user
         self.fqdn = fqdn
         self.ip_addresses = ip_addresses
         self.realm = realm_name
         self.domain = domain_name
         self.forwarders = forwarders
+        self.forward_policy = forward_policy
         self.host = fqdn.split(".")[0]
         self.suffix = ipautil.realm_to_suffix(self.realm)
         self.ntp = ntp
@@ -776,6 +778,7 @@ class BindInstance(service.Service):
             REALM=self.realm,
             SERVER_ID=installutils.realm_to_serverid(self.realm),
             FORWARDERS=fwds,
+            FORWARD_POLICY=self.forward_policy,
             SUFFIX=self.suffix,
             OPTIONAL_NTP=optional_ntp,
             ZONEMGR=self.zonemgr,
diff --git a/ipaserver/install/dns.py b/ipaserver/install/dns.py
index dbeacaee804dacd102d47aa28e9600adedead884..cae8787a4e849b4700b08bf93d326215becc7be5 100644
--- a/ipaserver/install/dns.py
+++ b/ipaserver/install/dns.py
@@ -318,8 +318,8 @@ def install(standalone, replica, options, api=api):
     bind = bindinstance.BindInstance(fstore, ldapi=True, api=api,
                                      autobind=AUTOBIND_ENABLED)
     bind.setup(api.env.host, ip_addresses, api.env.realm, api.env.domain,
-               options.forwarders, conf_ntp, reverse_zones,
-               zonemgr=options.zonemgr,
+               options.forwarders, options.forward_policy, conf_ntp,
+               reverse_zones, zonemgr=options.zonemgr,
                no_dnssec_validation=options.no_dnssec_validation,
                ca_configured=options.setup_ca)
 
diff --git a/ipaserver/install/server/common.py b/ipaserver/install/server/common.py
index 2bf5a21ea67f7eff729118bb76ffe6147d137e3e..6d1e9df7cfe00c273a131c31f946e1573bd59832 100644
--- a/ipaserver/install/server/common.py
+++ b/ipaserver/install/server/common.py
@@ -170,6 +170,11 @@ class BaseServerDNS(common.Installable, core.Group, core.Composite):
         cli_name='forwarder',
     )
 
+    forward_policy = Knob(
+        {'only', 'first'}, 'first',
+        description=("DNS forwarding policy for global forwarders"),
+    )
+
     auto_forwarders = Knob(
         bool, False,
         description="Use DNS forwarders configured in /etc/resolv.conf",
@@ -432,6 +437,10 @@ class BaseServer(common.Installable, common.Interactive, core.Composite):
                 raise RuntimeError(
                     "You cannot specify a --no-forwarders option without the "
                     "--setup-dns option")
+            if self.dns.forward_policy:
+                raise RuntimeError(
+                    "You cannot specify a --forward-policy option without the "
+                    "--setup-dns option")
             if self.dns.reverse_zones:
                 raise RuntimeError(
                     "You cannot specify a --reverse-zone option without the "
diff --git a/ipaserver/install/server/install.py b/ipaserver/install/server/install.py
index 120113742dcca988846ae435412ffc5e331f8337..fad63894420e0a7e1966e8145369cb7083aab076 100644
--- a/ipaserver/install/server/install.py
+++ b/ipaserver/install/server/install.py
@@ -759,10 +759,11 @@ def install_check(installer):
 
     if options.setup_dns:
         print("BIND DNS server will be configured to serve IPA domain with:")
-        print("Forwarders:    %s" % (
+        print("Forwarders:       %s" % (
             "No forwarders" if not options.forwarders
             else ", ".join([str(ip) for ip in options.forwarders])
         ))
+        print('Forward policy:   %s' % options.forward_policy)
         print("Reverse zone(s):  %s" % (
             "No reverse zone" if options.no_reverse or not dns.reverse_zones
             else ", ".join(str(rz) for rz in dns.reverse_zones)
@@ -992,7 +993,7 @@ def install(installer):
         # Create a BIND instance
         bind = bindinstance.BindInstance(fstore, dm_password)
         bind.setup(host_name, ip_addresses, realm_name,
-                   domain_name, (), not options.no_ntp, (),
+                   domain_name, (), 'first', not options.no_ntp, (),
                    zonemgr=options.zonemgr, ca_configured=setup_ca,
                    no_dnssec_validation=options.no_dnssec_validation)
         bind.create_sample_bind_zone()
-- 
2.5.5

From 1434e640ecc8f3e721cf069302907dd9b4030428 Mon Sep 17 00:00:00 2001
From: Petr Spacek <pspa...@redhat.com>
Date: Mon, 7 Mar 2016 12:00:21 +0100
Subject: [PATCH] Move automatic empty zone list into ipapython.dnsutil and
 make it reusable

https://fedorahosted.org/freeipa/ticket/5710
---
 ipapython/dnsutil.py | 57 ++++++++++++++++++++++++++++++++++++++++++++++++++++
 ipapython/ipautil.py | 56 +++------------------------------------------------
 2 files changed, 60 insertions(+), 53 deletions(-)

diff --git a/ipapython/dnsutil.py b/ipapython/dnsutil.py
index 18141fa091b37c5e59a2efc1028812981bfd4884..0cab0f49709a94ae877db5b6aad7ae3bb5bdc947 100644
--- a/ipapython/dnsutil.py
+++ b/ipapython/dnsutil.py
@@ -109,3 +109,60 @@ DNSName.root = DNSName(dns.name.root)  # '.'
 DNSName.empty = DNSName(dns.name.empty)  # '@'
 DNSName.ip4_rev_zone = DNSName(('in-addr', 'arpa', ''))
 DNSName.ip6_rev_zone = DNSName(('ip6', 'arpa', ''))
+
+# Empty zones are defined in various RFCs. BIND is by default serving them.
+# This constat should contain everything listed in
+# IANA registry "Locally-Served DNS Zones"
+# URL: http://www.iana.org/assignments/locally-served-dns-zones
+# + AS112 zone defined in RFC 7534. It is not in the registry for some
+# reason but BIND 9.10 is serving it as automatic empty zones.
+EMPTY_ZONES = [DNSName(aez).make_absolute() for aez in [
+        # RFC 1918
+        "10.IN-ADDR.ARPA", "16.172.IN-ADDR.ARPA", "17.172.IN-ADDR.ARPA",
+        "18.172.IN-ADDR.ARPA", "19.172.IN-ADDR.ARPA", "20.172.IN-ADDR.ARPA",
+        "21.172.IN-ADDR.ARPA", "22.172.IN-ADDR.ARPA", "23.172.IN-ADDR.ARPA",
+        "24.172.IN-ADDR.ARPA", "25.172.IN-ADDR.ARPA", "26.172.IN-ADDR.ARPA",
+        "27.172.IN-ADDR.ARPA", "28.172.IN-ADDR.ARPA", "29.172.IN-ADDR.ARPA",
+        "30.172.IN-ADDR.ARPA", "31.172.IN-ADDR.ARPA", "168.192.IN-ADDR.ARPA",
+        # RFC 6598
+        "64.100.IN-ADDR.ARPA", "65.100.IN-ADDR.ARPA", "66.100.IN-ADDR.ARPA",
+        "67.100.IN-ADDR.ARPA", "68.100.IN-ADDR.ARPA", "69.100.IN-ADDR.ARPA",
+        "70.100.IN-ADDR.ARPA", "71.100.IN-ADDR.ARPA", "72.100.IN-ADDR.ARPA",
+        "73.100.IN-ADDR.ARPA", "74.100.IN-ADDR.ARPA", "75.100.IN-ADDR.ARPA",
+        "76.100.IN-ADDR.ARPA", "77.100.IN-ADDR.ARPA", "78.100.IN-ADDR.ARPA",
+        "79.100.IN-ADDR.ARPA", "80.100.IN-ADDR.ARPA", "81.100.IN-ADDR.ARPA",
+        "82.100.IN-ADDR.ARPA", "83.100.IN-ADDR.ARPA", "84.100.IN-ADDR.ARPA",
+        "85.100.IN-ADDR.ARPA", "86.100.IN-ADDR.ARPA", "87.100.IN-ADDR.ARPA",
+        "88.100.IN-ADDR.ARPA", "89.100.IN-ADDR.ARPA", "90.100.IN-ADDR.ARPA",
+        "91.100.IN-ADDR.ARPA", "92.100.IN-ADDR.ARPA", "93.100.IN-ADDR.ARPA",
+        "94.100.IN-ADDR.ARPA", "95.100.IN-ADDR.ARPA", "96.100.IN-ADDR.ARPA",
+        "97.100.IN-ADDR.ARPA", "98.100.IN-ADDR.ARPA", "99.100.IN-ADDR.ARPA",
+        "100.100.IN-ADDR.ARPA", "101.100.IN-ADDR.ARPA",
+        "102.100.IN-ADDR.ARPA", "103.100.IN-ADDR.ARPA",
+        "104.100.IN-ADDR.ARPA", "105.100.IN-ADDR.ARPA",
+        "106.100.IN-ADDR.ARPA", "107.100.IN-ADDR.ARPA",
+        "108.100.IN-ADDR.ARPA", "109.100.IN-ADDR.ARPA",
+        "110.100.IN-ADDR.ARPA", "111.100.IN-ADDR.ARPA",
+        "112.100.IN-ADDR.ARPA", "113.100.IN-ADDR.ARPA",
+        "114.100.IN-ADDR.ARPA", "115.100.IN-ADDR.ARPA",
+        "116.100.IN-ADDR.ARPA", "117.100.IN-ADDR.ARPA",
+        "118.100.IN-ADDR.ARPA", "119.100.IN-ADDR.ARPA",
+        "120.100.IN-ADDR.ARPA", "121.100.IN-ADDR.ARPA",
+        "122.100.IN-ADDR.ARPA", "123.100.IN-ADDR.ARPA",
+        "124.100.IN-ADDR.ARPA", "125.100.IN-ADDR.ARPA",
+        "126.100.IN-ADDR.ARPA", "127.100.IN-ADDR.ARPA",
+        # RFC 5735 and RFC 5737
+        "0.IN-ADDR.ARPA", "127.IN-ADDR.ARPA", "254.169.IN-ADDR.ARPA",
+        "2.0.192.IN-ADDR.ARPA", "100.51.198.IN-ADDR.ARPA",
+        "113.0.203.IN-ADDR.ARPA", "255.255.255.255.IN-ADDR.ARPA",
+        # Local IPv6 Unicast Addresses
+        "0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.IP6.ARPA",
+        "1.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.IP6.ARPA",
+        # LOCALLY ASSIGNED LOCAL ADDRESS SCOPE
+        "D.F.IP6.ARPA", "8.E.F.IP6.ARPA", "9.E.F.IP6.ARPA", "A.E.F.IP6.ARPA",
+        "B.E.F.IP6.ARPA",
+        # Example Prefix, RFC 3849.
+        "8.B.D.0.1.0.0.2.IP6.ARPA",
+        # RFC 7534
+        "EMPTY.AS112.ARPA",
+    ]]
diff --git a/ipapython/ipautil.py b/ipapython/ipautil.py
index 6eac6679e0799139f7399e2965b0eefee1e9440f..d9301ab46ff93c49e590993924db97697cbb2039 100644
--- a/ipapython/ipautil.py
+++ b/ipapython/ipautil.py
@@ -51,7 +51,7 @@ from ipapython import ipavalidate
 from ipapython import config
 from ipaplatform.paths import paths
 from ipapython.dn import DN
-from ipapython.dnsutil import DNSName
+from ipapython.dnsutil import DNSName, EMPTY_ZONES
 
 SHARE_DIR = paths.USR_SHARE_IPA_DIR
 PLUGINS_SHARE_DIR = paths.IPA_PLUGINS
@@ -1065,59 +1065,9 @@ def check_zone_overlap(zone, raise_on_error=True):
 
 
 def is_auto_empty_zone(zone):
+    """True if specified zone name exactly matches an automatic empty zone."""
     assert isinstance(zone, DNSName)
-
-    automatic_empty_zones = [DNSName(aez).make_absolute() for aez in [
-        # RFC 1918
-        "10.IN-ADDR.ARPA", "16.172.IN-ADDR.ARPA", "17.172.IN-ADDR.ARPA",
-        "18.172.IN-ADDR.ARPA", "19.172.IN-ADDR.ARPA", "20.172.IN-ADDR.ARPA",
-        "21.172.IN-ADDR.ARPA", "22.172.IN-ADDR.ARPA", "23.172.IN-ADDR.ARPA",
-        "24.172.IN-ADDR.ARPA", "25.172.IN-ADDR.ARPA", "26.172.IN-ADDR.ARPA",
-        "27.172.IN-ADDR.ARPA", "28.172.IN-ADDR.ARPA", "29.172.IN-ADDR.ARPA",
-        "30.172.IN-ADDR.ARPA", "31.172.IN-ADDR.ARPA", "168.192.IN-ADDR.ARPA",
-        # RFC 6598
-        "64.100.IN-ADDR.ARPA", "65.100.IN-ADDR.ARPA", "66.100.IN-ADDR.ARPA",
-        "67.100.IN-ADDR.ARPA", "68.100.IN-ADDR.ARPA", "69.100.IN-ADDR.ARPA",
-        "70.100.IN-ADDR.ARPA", "71.100.IN-ADDR.ARPA", "72.100.IN-ADDR.ARPA",
-        "73.100.IN-ADDR.ARPA", "74.100.IN-ADDR.ARPA", "75.100.IN-ADDR.ARPA",
-        "76.100.IN-ADDR.ARPA", "77.100.IN-ADDR.ARPA", "78.100.IN-ADDR.ARPA",
-        "79.100.IN-ADDR.ARPA", "80.100.IN-ADDR.ARPA", "81.100.IN-ADDR.ARPA",
-        "82.100.IN-ADDR.ARPA", "83.100.IN-ADDR.ARPA", "84.100.IN-ADDR.ARPA",
-        "85.100.IN-ADDR.ARPA", "86.100.IN-ADDR.ARPA", "87.100.IN-ADDR.ARPA",
-        "88.100.IN-ADDR.ARPA", "89.100.IN-ADDR.ARPA", "90.100.IN-ADDR.ARPA",
-        "91.100.IN-ADDR.ARPA", "92.100.IN-ADDR.ARPA", "93.100.IN-ADDR.ARPA",
-        "94.100.IN-ADDR.ARPA", "95.100.IN-ADDR.ARPA", "96.100.IN-ADDR.ARPA",
-        "97.100.IN-ADDR.ARPA", "98.100.IN-ADDR.ARPA", "99.100.IN-ADDR.ARPA",
-        "100.100.IN-ADDR.ARPA", "101.100.IN-ADDR.ARPA",
-        "102.100.IN-ADDR.ARPA", "103.100.IN-ADDR.ARPA",
-        "104.100.IN-ADDR.ARPA", "105.100.IN-ADDR.ARPA",
-        "106.100.IN-ADDR.ARPA", "107.100.IN-ADDR.ARPA",
-        "108.100.IN-ADDR.ARPA", "109.100.IN-ADDR.ARPA",
-        "110.100.IN-ADDR.ARPA", "111.100.IN-ADDR.ARPA",
-        "112.100.IN-ADDR.ARPA", "113.100.IN-ADDR.ARPA",
-        "114.100.IN-ADDR.ARPA", "115.100.IN-ADDR.ARPA",
-        "116.100.IN-ADDR.ARPA", "117.100.IN-ADDR.ARPA",
-        "118.100.IN-ADDR.ARPA", "119.100.IN-ADDR.ARPA",
-        "120.100.IN-ADDR.ARPA", "121.100.IN-ADDR.ARPA",
-        "122.100.IN-ADDR.ARPA", "123.100.IN-ADDR.ARPA",
-        "124.100.IN-ADDR.ARPA", "125.100.IN-ADDR.ARPA",
-        "126.100.IN-ADDR.ARPA", "127.100.IN-ADDR.ARPA",
-        # RFC 5735 and RFC 5737
-        "0.IN-ADDR.ARPA", "127.IN-ADDR.ARPA", "254.169.IN-ADDR.ARPA",
-        "2.0.192.IN-ADDR.ARPA", "100.51.198.IN-ADDR.ARPA",
-        "113.0.203.IN-ADDR.ARPA", "255.255.255.255.IN-ADDR.ARPA",
-        # Local IPv6 Unicast Addresses
-        "0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.IP6.ARPA",
-        "1.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.IP6.ARPA",
-        # LOCALLY ASSIGNED LOCAL ADDRESS SCOPE
-        "D.F.IP6.ARPA", "8.E.F.IP6.ARPA", "9.E.F.IP6.ARPA", "A.E.F.IP6.ARPA",
-        "B.E.F.IP6.ARPA",
-        # Example Prefix, RFC 3849.
-        "8.B.D.0.1.0.0.2.IP6.ARPA",
-        # RFC 7534
-        "EMPTY.AS112.ARPA",
-    ]]
-    return zone in automatic_empty_zones
+    return zone in EMPTY_ZONES
 
 
 def config_replace_variables(filepath, replacevars=dict(), appendvars=dict()):
-- 
2.5.5

From 0ca10332f604e60647869507ab4f6361c7916d2c Mon Sep 17 00:00:00 2001
From: Petr Spacek <pspa...@redhat.com>
Date: Mon, 7 Mar 2016 13:24:31 +0100
Subject: [PATCH] Add assert_absolute_dnsname() helper to ipapython.dnsutil

Sanity check for zone names and such should be the same everywhere.
This new function will be a replacement for ad-hoc checks.

https://fedorahosted.org/freeipa/ticket/5710
---
 ipapython/dnsutil.py | 19 +++++++++++++++++++
 1 file changed, 19 insertions(+)

diff --git a/ipapython/dnsutil.py b/ipapython/dnsutil.py
index 0cab0f49709a94ae877db5b6aad7ae3bb5bdc947..7f0a094f28d5226b58c5e751b5c1dae7bcf97d61 100644
--- a/ipapython/dnsutil.py
+++ b/ipapython/dnsutil.py
@@ -166,3 +166,22 @@ EMPTY_ZONES = [DNSName(aez).make_absolute() for aez in [
         # RFC 7534
         "EMPTY.AS112.ARPA",
     ]]
+
+
+def assert_absolute_dnsname(name):
+    """Raise AssertionError if name is not DNSName or is not absolute.
+
+    >>> assert_absolute_dnsname(DNSName('absolute.name.example.'))
+    >>> assert_absolute_dnsname(DNSName('relative.name.example'))
+    Traceback (most recent call last):
+      ...
+    AssertionError: name must be absolute, ...
+    >>> assert_absolute_dnsname('absolute.string.example.')
+    Traceback (most recent call last):
+      ...
+    AssertionError: name must be DNSName instance, ...
+    """
+
+    assert isinstance(name, DNSName), ("name must be DNSName instance, "
+                                       "got '%s'" % type(name))
+    assert name.is_absolute(), "name must be absolute, got '%s'" % name
-- 
2.5.5

From 68fe3000997efcfcf6c08731c82630bd3991cac5 Mon Sep 17 00:00:00 2001
From: Petr Spacek <pspa...@redhat.com>
Date: Mon, 7 Mar 2016 13:30:35 +0100
Subject: [PATCH] Move function is_auto_empty_zone() into ipapython.dnsutil

I'm going to extend this so it is better to have it in module.
At the same time it is now using shared assert_absolute_dnsname()
helper.

https://fedorahosted.org/freeipa/ticket/5710
---
 ipapython/dnsutil.py | 6 ++++++
 ipapython/ipautil.py | 8 +-------
 2 files changed, 7 insertions(+), 7 deletions(-)

diff --git a/ipapython/dnsutil.py b/ipapython/dnsutil.py
index 7f0a094f28d5226b58c5e751b5c1dae7bcf97d61..6ff500b220e81ce5a013392d9268a9740615eccf 100644
--- a/ipapython/dnsutil.py
+++ b/ipapython/dnsutil.py
@@ -185,3 +185,9 @@ def assert_absolute_dnsname(name):
     assert isinstance(name, DNSName), ("name must be DNSName instance, "
                                        "got '%s'" % type(name))
     assert name.is_absolute(), "name must be absolute, got '%s'" % name
+
+
+def is_auto_empty_zone(zone):
+    """True if specified zone name exactly matches an automatic empty zone."""
+    assert isinstance(zone, DNSName)
+    return zone in EMPTY_ZONES
diff --git a/ipapython/ipautil.py b/ipapython/ipautil.py
index d9301ab46ff93c49e590993924db97697cbb2039..c152990d2c57835eb51f0f8bc50136f173e54ef8 100644
--- a/ipapython/ipautil.py
+++ b/ipapython/ipautil.py
@@ -51,7 +51,7 @@ from ipapython import ipavalidate
 from ipapython import config
 from ipaplatform.paths import paths
 from ipapython.dn import DN
-from ipapython.dnsutil import DNSName, EMPTY_ZONES
+from ipapython.dnsutil import DNSName, is_auto_empty_zone
 
 SHARE_DIR = paths.USR_SHARE_IPA_DIR
 PLUGINS_SHARE_DIR = paths.IPA_PLUGINS
@@ -1064,12 +1064,6 @@ def check_zone_overlap(zone, raise_on_error=True):
         raise ValueError(msg)
 
 
-def is_auto_empty_zone(zone):
-    """True if specified zone name exactly matches an automatic empty zone."""
-    assert isinstance(zone, DNSName)
-    return zone in EMPTY_ZONES
-
-
 def config_replace_variables(filepath, replacevars=dict(), appendvars=dict()):
     """
     Take a key=value based configuration file, and write new version
-- 
2.5.5

From 558da7269da6059445d4784db79de5cb4ca2d250 Mon Sep 17 00:00:00 2001
From: Petr Spacek <pspa...@redhat.com>
Date: Mon, 7 Mar 2016 14:10:34 +0100
Subject: [PATCH] Use shared sanity check and tests
 ipapython.dnsutil.is_auto_empty_zone()

https://fedorahosted.org/freeipa/ticket/5710
---
 ipapython/dnsutil.py | 16 ++++++++++++++--
 1 file changed, 14 insertions(+), 2 deletions(-)

diff --git a/ipapython/dnsutil.py b/ipapython/dnsutil.py
index 6ff500b220e81ce5a013392d9268a9740615eccf..e8d2f6ff6bd4b6338db498fad70c1b3bf84e248f 100644
--- a/ipapython/dnsutil.py
+++ b/ipapython/dnsutil.py
@@ -188,6 +188,18 @@ def assert_absolute_dnsname(name):
 
 
 def is_auto_empty_zone(zone):
-    """True if specified zone name exactly matches an automatic empty zone."""
-    assert isinstance(zone, DNSName)
+    """True if specified zone name exactly matches an automatic empty zone.
+
+    >>> is_auto_empty_zone(DNSName('in-addr.arpa.'))
+    False
+    >>> is_auto_empty_zone(DNSName('10.in-addr.arpa.'))
+    True
+    >>> is_auto_empty_zone(DNSName('1.10.in-addr.arpa.'))
+    False
+    >>> is_auto_empty_zone(DNSName('10.in-addr.arpa'))
+    Traceback (most recent call last):
+      ...
+    AssertionError: ...
+    """
+    assert_absolute_dnsname(zone)
     return zone in EMPTY_ZONES
-- 
2.5.5

From 0f2ff17702e6e386b85fa11409139e7fbbc67970 Mon Sep 17 00:00:00 2001
From: Petr Spacek <pspa...@redhat.com>
Date: Mon, 7 Mar 2016 14:10:54 +0100
Subject: [PATCH] Add function ipapython.dnsutil.inside_auto_empty_zone()

It allows to test if given DNS name belongs to an automatic empty zone.

https://fedorahosted.org/freeipa/ticket/5710
---
 ipapython/dnsutil.py | 25 +++++++++++++++++++++++++
 1 file changed, 25 insertions(+)

diff --git a/ipapython/dnsutil.py b/ipapython/dnsutil.py
index e8d2f6ff6bd4b6338db498fad70c1b3bf84e248f..240b7c9cd2168db17b9fa673dc4eefcfa78fef45 100644
--- a/ipapython/dnsutil.py
+++ b/ipapython/dnsutil.py
@@ -203,3 +203,28 @@ def is_auto_empty_zone(zone):
     """
     assert_absolute_dnsname(zone)
     return zone in EMPTY_ZONES
+
+
+def inside_auto_empty_zone(name):
+    """True if specified absolute name is a subdomain of an automatic empty
+    zone.
+
+    DNS domain is a subdomain of itself so this function
+    returns True for zone apexes, too.
+
+    >>> inside_auto_empty_zone(DNSName('in-addr.arpa.'))
+    False
+    >>> inside_auto_empty_zone(DNSName('10.in-addr.arpa.'))
+    True
+    >>> inside_auto_empty_zone(DNSName('1.10.in-addr.arpa.'))
+    True
+    >>> inside_auto_empty_zone(DNSName('1.10.in-addr.arpa'))
+    Traceback (most recent call last):
+      ...
+    AssertionError: ...
+    """
+    assert_absolute_dnsname(name)
+    for aez in EMPTY_ZONES:
+        if name.is_subdomain(aez):
+            return True
+    return False
-- 
2.5.5

From 22bcaf329802f4e48da591e8024f283181d710db Mon Sep 17 00:00:00 2001
From: Petr Spacek <pspa...@redhat.com>
Date: Mon, 7 Mar 2016 14:37:31 +0100
Subject: [PATCH] Auto-detect default value for --forward-policy option in
 installers

Forward policy defaults to 'first' if no IP address belonging to a private
or reserved ranges is detected on local interfaces (RFC 6303).
Defaults to only if a private IP address is detected.

This prevents problems with BIND automatic empty zones because
conflicting zones cannot be disabled unless forwarding policy == only.

https://fedorahosted.org/freeipa/ticket/5710
---
 install/tools/ipa-dns-install           |  2 +-
 install/tools/man/ipa-dns-install.1     |  5 ++++-
 install/tools/man/ipa-replica-install.1 |  5 ++++-
 install/tools/man/ipa-server-install.1  |  5 ++++-
 ipaserver/install/dns.py                | 11 +++++++++++
 ipaserver/install/server/common.py      |  2 +-
 6 files changed, 25 insertions(+), 5 deletions(-)

diff --git a/install/tools/ipa-dns-install b/install/tools/ipa-dns-install
index 50547be7d8704ce6c2a18fd42566a05ca2e8f463..504d01e654960874e65c74104b54f4b7cdbc42f1 100755
--- a/install/tools/ipa-dns-install
+++ b/install/tools/ipa-dns-install
@@ -53,7 +53,7 @@ def parse_options():
                       action="store_true", default=False,
                       help="Use DNS forwarders configured in /etc/resolv.conf")
     parser.add_option("--forward-policy", dest="forward_policy",
-                      choices=("first", "only"), default="first",
+                      choices=("first", "only"), default=None,
                       help="DNS forwarding policy for global forwarders")
     parser.add_option("--reverse-zone", dest="reverse_zones",
                       default=[], action="append", metavar="REVERSE_ZONE",
diff --git a/install/tools/man/ipa-dns-install.1 b/install/tools/man/ipa-dns-install.1
index e3739e2bbeeccfb24721faa0a5da5600ee145f7c..ad937cc59bc0b1cff2dd73faa494a8121b6eb45d 100644
--- a/install/tools/man/ipa-dns-install.1
+++ b/install/tools/man/ipa-dns-install.1
@@ -42,7 +42,10 @@ Do not add any DNS forwarders, send non\-resolvable addresses to the DNS root se
 Add DNS forwarders configured in /etc/resolv.conf to the list of forwarders used by IPA DNS.
 .TP
 \fB\-\-forward\-policy\fR=\fIfirst|only\fR
-DNS forwarding policy for global forwarders specified using other options. Defaults to first.
+DNS forwarding policy for global forwarders specified using other options.
+Defaults to first if no IP address belonging to a private or reserved ranges is
+detected on local interfaces (RFC 6303). Defaults to only if a private
+IP address is detected.
 .TP
 \fB\-\-reverse\-zone\fR=\fIREVERSE_ZONE\fR
 The reverse DNS zone to use. This option can be used multiple times to specify multiple reverse zones.
diff --git a/install/tools/man/ipa-replica-install.1 b/install/tools/man/ipa-replica-install.1
index 6875f4e416adea502b7c3136060f231212e60ef1..0e9f51a645afeac63b0c87418cd1468db951c4ef 100644
--- a/install/tools/man/ipa-replica-install.1
+++ b/install/tools/man/ipa-replica-install.1
@@ -150,7 +150,10 @@ Do not add any DNS forwarders. Root DNS servers will be used instead.
 Add DNS forwarders configured in /etc/resolv.conf to the list of forwarders used by IPA DNS.
 .TP
 \fB\-\-forward\-policy\fR=\fIfirst|only\fR
-DNS forwarding policy for global forwarders specified using other options. Defaults to first.
+DNS forwarding policy for global forwarders specified using other options.
+Defaults to first if no IP address belonging to a private or reserved ranges is
+detected on local interfaces (RFC 6303). Defaults to only if a private
+IP address is detected.
 .TP
 \fB\-\-reverse\-zone\fR=\fIREVERSE_ZONE\fR
 The reverse DNS zone to use. This option can be used multiple times to specify multiple reverse zones.
diff --git a/install/tools/man/ipa-server-install.1 b/install/tools/man/ipa-server-install.1
index e5f6f760bf854f3e36a5372504e7c1b8c8acb9b1..55b49449e3c44aebfeefe5cb71d73e9abf07c5b2 100644
--- a/install/tools/man/ipa-server-install.1
+++ b/install/tools/man/ipa-server-install.1
@@ -159,7 +159,10 @@ Do not add any DNS forwarders. Root DNS servers will be used instead.
 Add DNS forwarders configured in /etc/resolv.conf to the list of forwarders used by IPA DNS.
 .TP
 \fB\-\-forward\-policy\fR=\fIfirst|only\fR
-DNS forwarding policy for global forwarders specified using other options. Defaults to first.
+DNS forwarding policy for global forwarders specified using other options.
+Defaults to first if no IP address belonging to a private or reserved ranges is
+detected on local interfaces (RFC 6303). Defaults to only if a private
+IP address is detected.
 .TP
 \fB\-\-reverse\-zone\fR=\fIREVERSE_ZONE\fR
 The reverse DNS zone to use. This option can be used multiple times to specify multiple reverse zones.
diff --git a/ipaserver/install/dns.py b/ipaserver/install/dns.py
index cae8787a4e849b4700b08bf93d326215becc7be5..ccb7760e3c835d195963e9338e4a5fab8cb608b0 100644
--- a/ipaserver/install/dns.py
+++ b/ipaserver/install/dns.py
@@ -259,6 +259,17 @@ def install_check(standalone, api, replica, options, hostname):
     ip_addresses = get_server_ip_address(hostname, options.unattended,
                                          True, options.ip_addresses)
 
+    if not options.forward_policy:
+        # user did not specify policy, derive it: default is 'first' but
+        # if any of local IP addresses belongs to private ranges use 'only'
+        options.forward_policy = 'first'
+        for ip in ip_addresses:
+            if dnsutil.inside_auto_empty_zone(dnsutil.DNSName(ip.reverse_dns)):
+                options.forward_policy = 'only'
+                root_logger.debug('IP address %s belongs to a private range, '
+                                  'using forward policy only', ip)
+                break
+
     if options.no_forwarders:
         options.forwarders = []
     elif options.forwarders or options.auto_forwarders:
diff --git a/ipaserver/install/server/common.py b/ipaserver/install/server/common.py
index 6d1e9df7cfe00c273a131c31f946e1573bd59832..fee0c6ab6e2f6f0bca3f92f0d114c5d4c27df346 100644
--- a/ipaserver/install/server/common.py
+++ b/ipaserver/install/server/common.py
@@ -171,7 +171,7 @@ class BaseServerDNS(common.Installable, core.Group, core.Composite):
     )
 
     forward_policy = Knob(
-        {'only', 'first'}, 'first',
+        {'only', 'first'}, None,
         description=("DNS forwarding policy for global forwarders"),
     )
 
-- 
2.5.5

-- 
Manage your subscription for the Freeipa-devel mailing list:
https://www.redhat.com/mailman/listinfo/freeipa-devel
Contribute to FreeIPA: http://www.freeipa.org/page/Contribute/Code

Reply via email to