summaryrefslogtreecommitdiffstats
path: root/ipatests/test_integration/test_authselect.py
blob: 5ce56fa21e7cf0d2e3144ff3f4a98c657bbbc7c4 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
#
# Copyright (C) 2018  FreeIPA Contributors see COPYING for license
#

"""
Module provides tests to verify that the authselect code works.
"""

from __future__ import absolute_import

import os
import pytest

from ipaplatform.paths import paths
from ipatests.test_integration.base import IntegrationTest
from ipatests.pytest_ipa.integration import tasks

default_profile = 'sssd'
preconfigured_profile = 'winbind'
preconfigured_options = ('with-fingerprint',)


def check_authselect_profile(host, expected_profile, expected_options=()):
    """
    Checks that the current authselect profile on the host
    matches expected one
    """
    cmd = host.run_command(
        ['cat', '/etc/authselect/authselect.conf'])
    lines = cmd.stdout_text.splitlines()
    assert lines[0] == expected_profile
    options = lines[1::]
    for option in expected_options:
        assert option in options


def apply_authselect_profile(host, profile, options=()):
    """
    Apply the specified authselect profile and options with --force
    """
    cmd = ['authselect', 'select', profile]
    cmd.extend(options)
    cmd.append('--force')
    host.run_command(cmd)


@pytest.mark.skipif(
    paths.AUTHSELECT is None,
    reason="Authselect is only available in fedora-like distributions")
class TestClientInstallation(IntegrationTest):
    """
    Tests the client installation with authselect profile.

    When the system is a fresh installation, authselect tool is available
    and the default profile 'sssd' without any option is set by default.
    But when the system has been upgraded from older version, even though
    authselect tool is available, no profile is set (authselect current would
    return 'No existing configuration detected').
    This test ensures that both scenarios are properly handled by the client
    installer.
    """
    num_clients = 1
    msg_warn_install = (
        "WARNING: The configuration pre-client installation "
        "is not managed by authselect and cannot be backed up. "
        "Uninstallation may not be able to revert to the original state.")
    msg_warn_uninstall = (
        "WARNING: Unable to revert to the pre-installation "
        "state ('authconfig' tool has been deprecated in favor of "
        "'authselect'). The default sssd profile will be used instead.")

    @classmethod
    def install(cls, mh):
        tasks.install_master(cls.master, setup_dns=False)
        cls.client = cls.clients[0]

    def _install_client(self, extraargs=[]):
        cmd = ['ipa-client-install', '-U',
               '--domain', self.client.domain.name,
               '--realm', self.client.domain.realm,
               '-p', self.client.config.admin_name,
               '-w', self.client.config.admin_password,
               '--server', self.master.hostname]
        cmd.extend(extraargs)
        return self.client.run_command(cmd, raiseonerr=False)

    def _uninstall_client(self):
        return self.client.run_command(
            ['ipa-client-install', '--uninstall', '-U'],
            raiseonerr=False)

    @pytest.mark.skip(reason="Option --no-sssd has been removed")
    def test_install_client_no_sssd(self):
        """
        Test client installation with --no-sssd option.
        This must be rejected as this option is incompatible with authselect.
        """
        result = self._install_client(extraargs=['--no-sssd'])
        assert result.returncode == 1
        msg = "Option '--no-sssd' is incompatible with the 'authselect' tool"
        assert msg in result.stderr_text

    @pytest.mark.skip(reason="Option --noac has been removed")
    def test_install_client_no_ac(self):
        """
        Test client installation with --noac option.
        This must be rejected as this option is incompatible with authselect.
        """
        result = self._install_client(extraargs=['--noac'])
        assert result.returncode == 1
        msg = "Option '--noac' is incompatible with the 'authselect' tool"
        assert msg in result.stderr_text

    def test_install_client_no_preconfigured_profile(self):
        """
        Test client installation on an upgraded system.
        """
        # On a machine upgraded from authconfig, there is no profile
        # To simulate this use case, remove /etc/authselect/authselect.conf
        # before launching client installation
        self.client.run_command(
            ['rm', '-f', '/etc/authselect/authselect.conf'])
        result = self._install_client()
        assert result.returncode == 0
        assert self.msg_warn_install in result.stderr_text
        # Client installation must configure the 'sssd' profile
        # with sudo
        check_authselect_profile(self.client, default_profile, ('with-sudo',))

    def test_uninstall_client_no_preconfigured_profile(self):
        """
        Test client un-installation when there was no authselect profile
        """
        # As the client did not have any authselect profile before install,
        # uninstall must print a warning about restoring 'sssd' profile
        # by default
        result = self._uninstall_client()
        assert result.returncode == 0
        check_authselect_profile(self.client, default_profile)

    def test_install_client_preconfigured_profile(self):
        """
        Test client installation when a different profile was present
        before client configuration
        """
        # Configure a profile winbind with feature with-fingerprint
        apply_authselect_profile(
            self.client, preconfigured_profile, preconfigured_options)
        # Make sure that oddjobd is disabled and stopped
        self.client.run_command(["systemctl", "disable", "oddjobd", "--now"])

        # Call the installer, must succeed and store the winbind profile
        # in the statestore, but install sssd profile with-mkhomedir
        result = self._install_client(extraargs=['-f', '--mkhomedir'])
        assert result.returncode == 0
        assert self.msg_warn_install not in result.stderr_text
        # Client installation must configure the 'sssd' profile
        # with mkhomedir (because of extraargs) and with sudo
        check_authselect_profile(
            self.client, default_profile, ('with-mkhomedir', 'with-sudo'))

        # Test for ticket 7604:
        # ipa-client-install --mkhomedir doesn't enable oddjobd
        # Check that oddjobd has been enabled and started
        # because --mkhomedir was used
        status = self.client.run_command(["systemctl", "status", "oddjobd"])
        assert "active (running)" in status.stdout_text

    def test_uninstall_client_preconfigured_profile(self):
        """
        Test client un-installation when a different profile was present
        before client configuration
        """
        # Uninstall must revert to the preconfigured profile with options
        result = self._uninstall_client()
        assert result.returncode == 0
        assert self.msg_warn_uninstall not in result.stderr_text
        check_authselect_profile(
            self.client, preconfigured_profile, preconfigured_options)

    def test_install_client_no_sudo(self):
        """
        Test client installation with --no-sudo option
        """
        result = self._install_client(extraargs=['-f', '--no-sudo'])
        assert result.returncode == 0
        assert self.msg_warn_install not in result.stderr_text
        # Client installation must configure the 'sssd' profile
        # but not with sudo (because of extraargs)
        check_authselect_profile(self.client, default_profile, ())

    def test_uninstall_wrong_sysrestore(self):
        """
        Test client uninstallation when sysrestore.state is incomplete
        Test for issue 7657
        """
        # Remove the keys 'profile' and 'features_list' from sysrestore.state
        def keep(line):
            if line.startswith('profile') or line.startswith('features_list'):
                return False
            return True

        sysrestore_state_file = os.path.join(paths.IPA_CLIENT_SYSRESTORE,
                                             "sysrestore.state")
        content = self.client.get_file_contents(sysrestore_state_file,
                                                encoding='utf-8')
        lines = [line.rstrip() for line in content.split('\n') if keep(line)]
        new_content = '\n'.join(lines)
        self.client.put_file_contents(sysrestore_state_file, new_content)

        result = self._uninstall_client()
        assert result.returncode == 0

    @classmethod
    def uninstall(cls, mh):
        super(TestClientInstallation, cls).uninstall(mh)
        # Clean-up the authselect profile and re-use the default 'sssd'
        apply_authselect_profile(cls.client, default_profile)


@pytest.mark.skipif(
    paths.AUTHSELECT is None,
    reason="Authselect is only available in fedora-like distributions")
class TestServerInstallation(IntegrationTest):
    """
    Tests the server installation with authselect profile.

    When the system is a fresh installation, authselect tool is available
    and the default profile 'sssd' without any option is set by default.
    But when the system has been upgraded from older version, even though
    authselect tool is available, no profile is set (authselect current would
    return 'No existing configuration detected').
    This test ensures that both scenarios are properly handled by the server
    installer.
    """

    @classmethod
    def install(cls, mh):
        pass

    def test_install(self):
        """
        Test server installation when a different profile was present
        before server configuration
        """
        # Configure a profile winbind with feature with-fingerprint
        apply_authselect_profile(
            self.master, preconfigured_profile, preconfigured_options)
        tasks.install_master(self.master, setup_dns=False)
        check_authselect_profile(self.master, default_profile, ('with-sudo',))

    def test_uninstall(self):
        """
        Test server uninstallation when a different profile was present
        before server installation
        """
        # uninstall must revert to the preconfigured profile
        tasks.uninstall_master(self.master)
        check_authselect_profile(
            self.master, preconfigured_profile, preconfigured_options)

    @classmethod
    def uninstall(cls, mh):
        # Clean-up the authselect profile and re-use the default 'sssd'
        apply_authselect_profile(cls.master, default_profile)