On 08/30/2013 03:28 PM, Petr Viktorin wrote:
> On 08/28/2013 03:04 PM, Ana Krivokapic wrote:
>> Hello,
>>
>> This patch adds integration tests for the forced client re-enrollment
>> feature, according to the test plan at:
>> http://www.freeipa.org/page/V3/Forced_client_re-enrollment#Test_Plan
>>
>>
>> https://fedorahosted.org/freeipa/ticket/3832
>
> Thank you! The tests are good. As expected I have some nitpicks below.
>
>
> I recommend putting the test case names from the wiki in the method 
> docstrings.
>
> [...]
>> +    def restore_client(self):
>> +        client = self.clients[0]
>
> I'll ask you to allow SSH here, because the controller can theoretically also
> act as one of the test hosts:
>
> iptables -A INPUT -p tcp --dport 22 -j ACCEPT
>
>> +        client.run_command([
>> +            'iptables',
>> +            '-A', 'INPUT',
>> +            '-j', 'REJECT',
>> +            '-p', 'all',
>> +            '--source', self.master.ip
>> +        ])
>> +        self.uninstall_client()
>> +        client.run_command(['iptables', '-F'])
>
> [...]
>> +    def backup_keytab(self):
>> +        self.clients[0].get_file(CLIENT_KEYTAB, TEMP_KEYTAB)
>> +        self.master.put_file(TEMP_KEYTAB, BACKUP_KEYTAB)
>
> Please use get_file_contents & put_file_contents. There might be more tests
> running on the controller machine, we don't want to use a shared file.
> For BACKUP_KEYTAB and EMPTY_KEYTAB please use a file inside
> master.config.test_dir; we don't want to leave files on the testing machines.
> The test_dir gets cleaned up.
>

Thanks for the review!

All issues are fixed in the updated patch.

-- 
Regards,

Ana Krivokapic
Associate Software Engineer
FreeIPA team
Red Hat Inc.

From 3afc75d270e6e899acf98b20a1f65f48811ca8fa Mon Sep 17 00:00:00 2001
From: Ana Krivokapic <akriv...@redhat.com>
Date: Wed, 28 Aug 2013 14:58:44 +0200
Subject: [PATCH] Add integration tests for forced client re-enrollment

Add integration tests for the forced client re-enrollment feature:
http://www.freeipa.org/page/V3/Forced_client_re-enrollment#Test_Plan

https://fedorahosted.org/freeipa/ticket/3832
---
 .../test_forced_client_reenrollment.py             | 278 +++++++++++++++++++++
 1 file changed, 278 insertions(+)
 create mode 100644 ipatests/test_integration/test_forced_client_reenrollment.py

diff --git a/ipatests/test_integration/test_forced_client_reenrollment.py b/ipatests/test_integration/test_forced_client_reenrollment.py
new file mode 100644
index 0000000000000000000000000000000000000000..4ba4cda1d4fe509110fffa91e1c13d78b457f64d
--- /dev/null
+++ b/ipatests/test_integration/test_forced_client_reenrollment.py
@@ -0,0 +1,278 @@
+# Authors:
+#   Ana Krivokapic <akriv...@redhat.com>
+#
+# Copyright (C) 2013  Red Hat
+# see file 'COPYING' for use and warranty information
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+import os
+import subprocess
+
+from ipatests.test_integration.base import IntegrationTest
+from ipatests.test_integration import tasks
+
+CLIENT_KEYTAB = '/etc/krb5.keytab'
+
+
+class TestForcedClientReenrollment(IntegrationTest):
+    """
+    Forced client re-enrollment
+    http://www.freeipa.org/page/V3/Forced_client_re-enrollment#Test_Plan
+    """
+    num_replicas = 1
+    num_clients = 1
+
+    @classmethod
+    def install(cls):
+        super(TestForcedClientReenrollment, cls).install()
+        tasks.install_master(cls.master)
+        tasks.install_replica(cls.master, cls.replicas[0], setup_ca=False)
+        cls.BACKUP_KEYTAB = os.path.join(
+            cls.master.config.test_dir,
+            'krb5.keytab'
+        )
+
+    def setUp(self):
+        tasks.prepare_host(self.clients[0])
+        tasks.install_client(self.master, self.clients[0])
+
+    def tearDown(self):
+        tasks.uninstall_client(self.clients[0])
+        self.delete_client_host_entry()
+
+    def test_reenroll_with_force_join(self):
+        """
+        Client re-enrollment using admin credentials (--force-join)
+        """
+        sshfp_record_pre = self.get_sshfp_record()
+        self.restore_client()
+        self.check_client_host_entry()
+        self.reenroll_client(force_join=True)
+        sshfp_record_post = self.get_sshfp_record()
+        assert sshfp_record_pre == sshfp_record_post
+
+    def test_reenroll_with_keytab(self):
+        """
+        Client re-enrollment using keytab
+        """
+        self.backup_keytab()
+        sshfp_record_pre = self.get_sshfp_record()
+        self.restore_client()
+        self.check_client_host_entry()
+        self.restore_keytab()
+        self.reenroll_client(keytab=self.BACKUP_KEYTAB)
+        sshfp_record_post = self.get_sshfp_record()
+        assert sshfp_record_pre == sshfp_record_post
+
+    def test_reenroll_with_both_force_join_and_keytab(self):
+        """
+        Client re-enrollment using both --force-join and --keytab options
+        """
+        self.backup_keytab()
+        sshfp_record_pre = self.get_sshfp_record()
+        self.restore_client()
+        self.check_client_host_entry()
+        self.restore_keytab()
+        self.reenroll_client(force_join=True, keytab=self.BACKUP_KEYTAB)
+        sshfp_record_post = self.get_sshfp_record()
+        assert sshfp_record_pre == sshfp_record_post
+
+    def test_reenroll_to_replica(self):
+        """
+        Client re-enrollment using keytab, to a replica
+        """
+        self.backup_keytab()
+        sshfp_record_pre = self.get_sshfp_record()
+        self.restore_client()
+        self.check_client_host_entry()
+        self.restore_keytab()
+        self.reenroll_client(keytab=self.BACKUP_KEYTAB, to_replica=True)
+        sshfp_record_post = self.get_sshfp_record()
+        assert sshfp_record_pre == sshfp_record_post
+
+    def test_try_to_reenroll_with_disabled_host(self):
+        """
+        Client re-enrollment using keytab, with disabled host
+        """
+        self.backup_keytab()
+        self.disable_client_host_entry()
+        self.restore_client()
+        self.check_client_host_entry(enabled=False)
+        self.restore_keytab()
+        self.reenroll_client(keytab=self.BACKUP_KEYTAB, expect_fail=True)
+
+    def test_try_to_reenroll_with_uninstalled_host(self):
+        """
+        Client re-enrollment using keytab, with uninstalled host
+        """
+        self.backup_keytab()
+        self.uninstall_client()
+        self.restore_client()
+        self.check_client_host_entry(enabled=False)
+        self.restore_keytab()
+        self.reenroll_client(keytab=self.BACKUP_KEYTAB, expect_fail=True)
+
+    def test_try_to_reenroll_with_deleted_host(self):
+        """
+        Client re-enrollment using keytab, with deleted host
+        """
+        self.backup_keytab()
+        self.delete_client_host_entry()
+        self.restore_client()
+        self.check_client_host_entry(not_found=True)
+        self.restore_keytab()
+        self.reenroll_client(keytab=self.BACKUP_KEYTAB, expect_fail=True)
+
+    def test_try_to_reenroll_with_incorrect_keytab(self):
+        """
+        Client re-enrollment using keytab, with incorrect keytab file
+        """
+        EMPTY_KEYTAB = os.path.join(
+            self.clients[0].config.test_dir,
+            'empty.keytab'
+        )
+        self.restore_client()
+        self.check_client_host_entry()
+        self.clients[0].run_command(['touch', EMPTY_KEYTAB])
+        self.reenroll_client(keytab=EMPTY_KEYTAB, expect_fail=True)
+
+    def uninstall_client(self):
+        self.clients[0].run_command(
+            ['ipa-client-install', '--uninstall', '-U'],
+            set_env=False,
+            raiseonerr=False
+        )
+
+    def restore_client(self):
+        client = self.clients[0]
+
+        client.run_command([
+            'iptables',
+            '-A', 'INPUT',
+            '-j', 'ACCEPT',
+            '-p', 'tcp',
+            '--dport', '22'
+        ])
+        client.run_command([
+            'iptables',
+            '-A', 'INPUT',
+            '-j', 'REJECT',
+            '-p', 'all',
+            '--source', self.master.ip
+        ])
+        self.uninstall_client()
+        client.run_command(['iptables', '-F'])
+
+    def reenroll_client(self, keytab=None, to_replica=False, force_join=False,
+                        expect_fail=False):
+        server = self.replicas[0] if to_replica else self.master
+        client = self.clients[0]
+
+        self.fix_resolv_conf(client, server)
+
+        args = [
+            'ipa-client-install', '-U',
+            '--server', server.hostname,
+            '--domain', server.domain.name
+        ]
+        if force_join:
+            args.append('--force-join')
+        if keytab:
+            args.extend(['--keytab', keytab])
+        else:
+            args.extend([
+                '-p', client.config.admin_name,
+                '-w', client.config.admin_password
+            ])
+
+        result = client.run_command(
+            args,
+            set_env=False,
+            raiseonerr=not expect_fail
+        )
+        assert 'IPA Server: %s' % server.hostname in result.stderr_text
+
+        if expect_fail:
+            err_msg = 'Kerberos authentication failed using keytab'
+            assert result.returncode == 1
+            assert err_msg in result.stderr_text
+        elif force_join and keytab:
+            warn_msg = ("Option 'force-join' has no additional effect "
+                        "when used with together with option 'keytab'.")
+            assert warn_msg in result.stderr_text
+
+    def check_client_host_entry(self, enabled=True, not_found=False):
+        result = self.master.run_command(
+            ['ipa', 'host-show', self.clients[0].hostname],
+            raiseonerr=not not_found
+        )
+
+        if not_found:
+            assert result.returncode == 2
+            assert 'host not found' in result.stderr_text
+        elif enabled:
+            assert 'Certificate:' in result.stdout_text
+            assert 'Keytab: True' in result.stdout_text
+        else:
+            assert 'Certificate:' not in result.stdout_text
+            assert 'Keytab: False' in result.stdout_text
+
+    def disable_client_host_entry(self):
+        self.master.run_command(
+            ['ipa', 'host-disable', self.clients[0].hostname]
+        )
+
+    def delete_client_host_entry(self):
+        try:
+            self.master.run_command(
+                ['ipa', 'host-del', self.clients[0].hostname]
+            )
+        except subprocess.CalledProcessError as e:
+            if e.returncode != 2:
+                raise
+
+    def get_sshfp_record(self):
+        sshfp_record = ''
+        client_host = self.clients[0].hostname.split('.')[0]
+
+        result = self.master.run_command(
+            ['ipa', 'dnsrecord-show', self.master.domain.name, client_host]
+        )
+
+        lines = result.stdout_text.splitlines()
+        for line in lines:
+            if 'SSHFP record:' in line:
+                sshfp_record = line.replace('SSHFP record:', '').strip()
+
+        assert sshfp_record, 'SSHFP record not found'
+        return sshfp_record
+
+    def backup_keytab(self):
+        contents = self.clients[0].get_file_contents(CLIENT_KEYTAB)
+        self.master.put_file_contents(self.BACKUP_KEYTAB, contents)
+
+    def restore_keytab(self):
+        contents = self.master.get_file_contents(self.BACKUP_KEYTAB)
+        self.clients[0].put_file_contents(self.BACKUP_KEYTAB, contents)
+
+    def fix_resolv_conf(self, client, server):
+        """
+        Put server's ip address at the top of resolv.conf
+        """
+        contents = client.get_file_contents('/etc/resolv.conf')
+        nameserver = 'nameserver %s\n' % server.ip
+
+        if not contents.startswith(nameserver):
+            contents = nameserver + contents.replace(nameserver, '')
+            client.put_file_contents('/etc/resolv.conf', contents)
-- 
1.8.3.1

_______________________________________________
Freeipa-devel mailing list
Freeipa-devel@redhat.com
https://www.redhat.com/mailman/listinfo/freeipa-devel

Reply via email to