4b8dd5
From 4fdab0c94c4e17e42e5f38a0e671bea39bcc9b74 Mon Sep 17 00:00:00 2001
4b8dd5
From: Anuja More <amore@redhat.com>
4b8dd5
Date: Mon, 9 Aug 2021 20:57:22 +0530
4b8dd5
Subject: [PATCH] ipatests: Test unsecure nsupdate.
4b8dd5
4b8dd5
The test configures an external bind server on the ipa-server
4b8dd5
(not the IPA-embedded DNS server) that allows unauthenticated nsupdates.
4b8dd5
4b8dd5
When the IPA client is registered using ipa-client-install,
4b8dd5
DNS records are added for the client in the bind server using nsupdate.
4b8dd5
The first try is using GSS-TIG but fails as expected, and the client
4b8dd5
installer then tries with unauthenticated nsupdate.
4b8dd5
4b8dd5
Related : https://pagure.io/freeipa/issue/8402
4b8dd5
4b8dd5
Signed-off-by: Anuja More <amore@redhat.com>
4b8dd5
Reviewed-By: Rob Crittenden <rcritten@redhat.com>
4b8dd5
Reviewed-By: Florence Blanc-Renaud <frenaud@redhat.com>
4b8dd5
---
4b8dd5
 .../test_installation_client.py               | 118 ++++++++++++++++++
4b8dd5
 1 file changed, 118 insertions(+)
4b8dd5
4b8dd5
diff --git a/ipatests/test_integration/test_installation_client.py b/ipatests/test_integration/test_installation_client.py
4b8dd5
index fa59a5255..014b0f6ab 100644
4b8dd5
--- a/ipatests/test_integration/test_installation_client.py
4b8dd5
+++ b/ipatests/test_integration/test_installation_client.py
4b8dd5
@@ -8,10 +8,15 @@ Module provides tests for various options of ipa-client-install.
4b8dd5
 
4b8dd5
 from __future__ import absolute_import
4b8dd5
 
4b8dd5
+import pytest
4b8dd5
+import re
4b8dd5
 import shlex
4b8dd5
+import textwrap
4b8dd5
 
4b8dd5
+from ipaplatform.paths import paths
4b8dd5
 from ipatests.test_integration.base import IntegrationTest
4b8dd5
 from ipatests.pytest_ipa.integration import tasks
4b8dd5
+from ipatests.pytest_ipa.integration.firewall import Firewall
4b8dd5
 
4b8dd5
 
4b8dd5
 class TestInstallClient(IntegrationTest):
4b8dd5
@@ -70,3 +75,116 @@ class TestInstallClient(IntegrationTest):
4b8dd5
                              extra_args=['--ssh-trust-dns'])
4b8dd5
         result = self.clients[0].run_command(['cat', '/etc/ssh/ssh_config'])
4b8dd5
         assert 'HostKeyAlgorithms' not in result.stdout_text
4b8dd5
+
4b8dd5
+
4b8dd5
+class TestClientInstallBind(IntegrationTest):
4b8dd5
+    """
4b8dd5
+    The test configures an external bind server on the ipa-server
4b8dd5
+    (not the IPA-embedded DNS server) that allows unauthenticated nsupdates.
4b8dd5
+    When the IPA client is registered using ipa-client-install,
4b8dd5
+    DNS records are added for the client in the bind server using nsupdate.
4b8dd5
+    The first try is using GSS-TIG but fails as expected, and the client
4b8dd5
+    installer then tries with unauthenticated nsupdate.
4b8dd5
+    """
4b8dd5
+
4b8dd5
+    num_clients = 1
4b8dd5
+
4b8dd5
+    @classmethod
4b8dd5
+    def install(cls, mh):
4b8dd5
+        cls.client = cls.clients[0]
4b8dd5
+
4b8dd5
+    @pytest.fixture
4b8dd5
+    def setup_bindserver(self):
4b8dd5
+        bindserver = self.master
4b8dd5
+        named_conf_backup = tasks.FileBackup(self.master, paths.NAMED_CONF)
4b8dd5
+        # create a zone in the BIND server that is identical to the IPA
4b8dd5
+        add_zone = textwrap.dedent("""
4b8dd5
+        zone "{domain}" IN {{ type master;
4b8dd5
+        file "{domain}.db"; allow-query {{ any; }};
4b8dd5
+        allow-update {{ any; }}; }};
4b8dd5
+        """).format(domain=bindserver.domain.name)
4b8dd5
+
4b8dd5
+        namedcfg = bindserver.get_file_contents(
4b8dd5
+            paths.NAMED_CONF, encoding='utf-8')
4b8dd5
+        namedcfg += '\n' + add_zone
4b8dd5
+        bindserver.put_file_contents(paths.NAMED_CONF, namedcfg)
4b8dd5
+
4b8dd5
+        def update_contents(path, pattern, replace):
4b8dd5
+            contents = bindserver.get_file_contents(path, encoding='utf-8')
4b8dd5
+            namedcfg_query = re.sub(pattern, replace, contents)
4b8dd5
+            bindserver.put_file_contents(path, namedcfg_query)
4b8dd5
+
4b8dd5
+        update_contents(paths.NAMED_CONF, 'localhost;', 'any;')
4b8dd5
+        update_contents(paths.NAMED_CONF, "listen-on port 53 { 127.0.0.1; };",
4b8dd5
+                        "#listen-on port 53 { 127.0.0.1; };")
4b8dd5
+        update_contents(paths.NAMED_CONF, "listen-on-v6 port 53 { ::1; };",
4b8dd5
+                        "#listen-on-v6 port 53 { ::1; };")
4b8dd5
+
4b8dd5
+        add_records = textwrap.dedent("""
4b8dd5
+        @   IN  SOA     {fqdn}. root.{domain}. (
4b8dd5
+        1001    ;Serial
4b8dd5
+        3H      ;Refresh
4b8dd5
+        15M     ;Retry
4b8dd5
+        1W      ;Expire
4b8dd5
+        1D      ;Minimum 1D
4b8dd5
+        )
4b8dd5
+        @      IN  NS      {fqdn}.
4b8dd5
+        ns1 IN  A       {bindserverip}
4b8dd5
+        _kerberos.{domain}. IN TXT {zoneupper}
4b8dd5
+        {fqdn}.    IN  A       {bindserverip}
4b8dd5
+        ipa-ca.{domain}.        IN  A       {bindserverip}
4b8dd5
+        _kerberos-master._tcp.{domain}. IN SRV 0 100 88 {fqdn}.
4b8dd5
+        _kerberos-master._udp.{domain}. IN SRV 0 100 88 {fqdn}.
4b8dd5
+        _kerberos._tcp.{domain}. 	IN SRV 0 100 88 {fqdn}.
4b8dd5
+        _kerberos._udp.{domain}. 	IN SRV 0 100 88 {fqdn}.
4b8dd5
+        _kpasswd._tcp.{domain}. 	IN SRV 0 100 464 {fqdn}.
4b8dd5
+        _kpasswd._udp.{domain}. 	IN SRV 0 100 464 {fqdn}.
4b8dd5
+        _ldap._tcp.{domain}. 		IN SRV 0 100 389 {fqdn}.
4b8dd5
+        """).format(
4b8dd5
+            fqdn=bindserver.hostname,
4b8dd5
+            domain=bindserver.domain.name,
4b8dd5
+            bindserverip=bindserver.ip,
4b8dd5
+            zoneupper=bindserver.domain.name.upper()
4b8dd5
+        )
4b8dd5
+        bindserverdb = "/var/named/{0}.db".format(bindserver.domain.name)
4b8dd5
+        bindserver.put_file_contents(bindserverdb, add_records)
4b8dd5
+        bindserver.run_command(['systemctl', 'start', 'named'])
4b8dd5
+        Firewall(bindserver).enable_services(["dns"])
4b8dd5
+        yield
4b8dd5
+        named_conf_backup.restore()
4b8dd5
+        bindserver.run_command(['rm', '-rf', bindserverdb])
4b8dd5
+
4b8dd5
+    def test_client_nsupdate(self, setup_bindserver):
4b8dd5
+        """Test secure nsupdate failed, then try unsecure nsupdate..
4b8dd5
+
4b8dd5
+        Test to verify when bind is configured with dynamic update policy,
4b8dd5
+        and during client-install 'nsupdate -g' fails then it should run with
4b8dd5
+        second call using unauthenticated nsupdate.
4b8dd5
+
4b8dd5
+        Related : https://pagure.io/freeipa/issue/8402
4b8dd5
+        """
4b8dd5
+        # with pre-configured bind server, install ipa-server without dns.
4b8dd5
+        tasks.install_master(self.master, setup_dns=False)
4b8dd5
+        self.client.resolver.backup()
4b8dd5
+        self.client.resolver.setup_resolver(
4b8dd5
+            self.master.ip, self.master.domain.name)
4b8dd5
+        try:
4b8dd5
+            self.client.run_command(['ipa-client-install', '-U',
4b8dd5
+                                     '--domain', self.client.domain.name,
4b8dd5
+                                     '--realm', self.client.domain.realm,
4b8dd5
+                                     '-p', self.client.config.admin_name,
4b8dd5
+                                     '-w', self.client.config.admin_password,
4b8dd5
+                                     '--server', self.master.hostname])
4b8dd5
+            # call unauthenticated nsupdate if GSS-TSIG nsupdate failed.
4b8dd5
+            str1 = "nsupdate (GSS-TSIG) failed"
4b8dd5
+            str2 = "'/usr/bin/nsupdate', '/etc/ipa/.dns_update.txt'"
4b8dd5
+            client_log = self.client.get_file_contents(
4b8dd5
+                paths.IPACLIENT_INSTALL_LOG, encoding='utf-8'
4b8dd5
+            )
4b8dd5
+            assert str1 in client_log and str2 in client_log
4b8dd5
+            dig_after = self.client.run_command(
4b8dd5
+                ['dig', '@{0}'.format(self.master.ip), self.client.hostname,
4b8dd5
+                 '-t', 'SSHFP'])
4b8dd5
+            assert "ANSWER: 0" not in dig_after.stdout_text.strip()
4b8dd5
+        finally:
4b8dd5
+            self.client.resolver.restore()
4b8dd5
-- 
4b8dd5
2.31.1
4b8dd5