Blob Blame History Raw
From 85bc681683a8a5d71b9cfaf9c70e0f388732f285 Mon Sep 17 00:00:00 2001
From: Justin Stephenson <jstephen@redhat.com>
Date: Wed, 27 Dec 2017 16:32:47 -0500
Subject: [PATCH] Skip zone overlap check with auto-reverse

Skip the existing reverse zone overlap check during DNS installation
when both --auto-reverse and --allow-zone-overlap arguments are
provided.

https://pagure.io/freeipa/issue/7239

Reviewed-By: Rob Crittenden <rcritten@redhat.com>
Reviewed-By: Alexander Bokovoy <abokovoy@redhat.com>
Reviewed-By: Christian Heimes <cheimes@redhat.com>
---
 ipaserver/install/bindinstance.py             | 18 ++--
 .../test_integration/test_installation.py     | 95 +++++++++++++++++++
 2 files changed, 105 insertions(+), 8 deletions(-)

diff --git a/ipaserver/install/bindinstance.py b/ipaserver/install/bindinstance.py
index 940667db9c40559d5369188395bb18f2d1eac025..4de2c6442175a64f4048a93b2006a6d5c6b2a045 100644
--- a/ipaserver/install/bindinstance.py
+++ b/ipaserver/install/bindinstance.py
@@ -304,7 +304,7 @@ def read_reverse_zone(default, ip_address, allow_zone_overlap=False):
     return normalize_zone(zone)
 
 
-def get_auto_reverse_zones(ip_addresses):
+def get_auto_reverse_zones(ip_addresses, allow_zone_overlap=False):
     auto_zones = []
     for ip in ip_addresses:
         if ipautil.reverse_record_exists(ip):
@@ -312,12 +312,13 @@ def get_auto_reverse_zones(ip_addresses):
             logger.info("Reverse record for IP address %s already exists", ip)
             continue
         default_reverse = get_reverse_zone_default(ip)
-        try:
-            dnsutil.check_zone_overlap(default_reverse)
-        except ValueError:
-            logger.info("Reverse zone %s for IP address %s already exists",
-                        default_reverse, ip)
-            continue
+        if not allow_zone_overlap:
+            try:
+                dnsutil.check_zone_overlap(default_reverse)
+            except ValueError:
+                logger.info("Reverse zone %s for IP address %s already exists",
+                            default_reverse, ip)
+                continue
         auto_zones.append((ip, default_reverse))
     return auto_zones
 
@@ -488,7 +489,8 @@ def check_reverse_zones(ip_addresses, reverse_zones, options, unattended,
             ips_missing_reverse.append(ip)
 
     # create reverse zone for IP addresses that does not have one
-    for (ip, rz) in get_auto_reverse_zones(ips_missing_reverse):
+    for (ip, rz) in get_auto_reverse_zones(ips_missing_reverse,
+                                           options.allow_zone_overlap):
         if options.auto_reverse:
             logger.info("Reverse zone %s will be created", rz)
             checked_reverse_zones.append(rz)
diff --git a/ipatests/test_integration/test_installation.py b/ipatests/test_integration/test_installation.py
index 4cd8a3e33927b7522e9b2a8908a8c179daaa1280..7e6c728102e29753ec7b56cedea734dd18b8bb8c 100644
--- a/ipatests/test_integration/test_installation.py
+++ b/ipatests/test_integration/test_installation.py
@@ -9,6 +9,7 @@ installed.
 
 from __future__ import absolute_import
 
+import os
 import pytest
 from ipalib.constants import DOMAIN_LEVEL_0
 from ipaplatform.constants import constants
@@ -16,9 +17,46 @@ from ipaplatform.paths import paths
 from ipatests.pytest_ipa.integration.env_config import get_global_config
 from ipatests.test_integration.base import IntegrationTest
 from ipatests.pytest_ipa.integration import tasks
+from ipatests.test_integration.test_caless import CALessBase, ipa_certs_cleanup
 
 config = get_global_config()
 
+
+def create_broken_resolv_conf(master):
+    # Force a broken resolv.conf to simulate a bad response to
+    # reverse zone lookups
+    master.run_command([
+        '/usr/bin/mv',
+        paths.RESOLV_CONF,
+        '%s.sav' % paths.RESOLV_CONF
+    ])
+
+    contents = "# Set as broken by ipatests\nnameserver 127.0.0.2\n"
+    master.put_file_contents(paths.RESOLV_CONF, contents)
+
+
+def restore_resolv_conf(master):
+    if os.path.exists('%s.sav' % paths.RESOLV_CONF):
+        master.run_command([
+            '/usr/bin/mv',
+            '%s.sav' % paths.RESOLV_CONF,
+            paths.RESOLV_CONF
+        ])
+
+
+def server_install_setup(func):
+    def wrapped(*args):
+        master = args[0].master
+        create_broken_resolv_conf(master)
+        try:
+            func(*args)
+        finally:
+            tasks.uninstall_master(master, clean=False)
+            restore_resolv_conf(master)
+            ipa_certs_cleanup(master)
+    return wrapped
+
+
 class InstallTestBase1(IntegrationTest):
 
     num_replicas = 3
@@ -226,6 +264,63 @@ class TestInstallWithCA_DNS2(InstallTestBase2):
         super(TestInstallWithCA_DNS2, self).test_replica2_ipa_kra_install()
 
 
+class TestInstallWithCA_DNS3(CALessBase):
+    """
+    Test an install with a bad DNS resolver configured to force a
+    timeout trying to verify the existing zones. In the case of a reverse
+    zone it is skipped unless --allow-zone-overlap is set regardless of
+    the value of --auto-reverse. Confirm that --allow-zone-overlap
+    lets the reverse zone be created.
+
+    ticket 7239
+    """
+
+    @server_install_setup
+    def test_number_of_zones(self):
+        """There should be two zones: one forward, one reverse"""
+
+        self.create_pkcs12('ca1/server')
+        self.prepare_cacert('ca1')
+
+        self.install_server(extra_args=['--allow-zone-overlap'])
+
+        result = self.master.run_command([
+            'ipa', 'dnszone-find'])
+
+        assert "in-addr.arpa." in result.stdout_text
+
+        assert "returned 2" in result.stdout_text
+
+
+class TestInstallWithCA_DNS4(CALessBase):
+    """
+    Test an install with a bad DNS resolver configured to force a
+    timeout trying to verify the existing zones. In the case of a reverse
+    zone it is skipped unless --allow-zone-overlap is set regardless of
+    the value of --auto-reverse. Confirm that without --allow-reverse-zone
+    only the forward zone is created.
+
+    ticket 7239
+    """
+
+    @server_install_setup
+    def test_number_of_zones(self):
+        """There should be one zone, a forward because rev timed-out"""
+
+        self.create_pkcs12('ca1/server')
+        self.prepare_cacert('ca1')
+
+        # no zone overlap by default
+        self.install_server()
+
+        result = self.master.run_command([
+            'ipa', 'dnszone-find'])
+
+        assert "in-addr.arpa." not in result.stdout_text
+
+        assert "returned 1" in result.stdout_text
+
+
 @pytest.mark.cs_acceptance
 class TestInstallWithCA_KRA_DNS1(InstallTestBase1):
 
-- 
2.20.1