summaryrefslogtreecommitdiffstats
path: root/ipatests/test_integration/test_trust.py
blob: 68fc0285c58bf540bddbf1368bee1d0b28459ad1 (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
# Authors:
#   Tomas Babej <tbabej@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 re

from ipatests.test_integration.base import IntegrationTest
from ipatests.test_integration import tasks
from ipatests.test_integration import util


class ADTrustBase(IntegrationTest):
    """Provides common checks for the AD trust integration testing."""

    topology = 'line'
    num_ad_domains = 1

    @classmethod
    def install(cls):
        super(ADTrustBase, cls).install()
        cls.ad = cls.ad_domains[0].ads[0]
        cls.install_adtrust()
        cls.check_sid_generation()
        cls.configure_dns_and_time()

    @classmethod
    def install_adtrust(cls):
        """Test adtrust support installation"""

        tasks.install_adtrust(cls.master)

    @classmethod
    def check_sid_generation(cls):
        """Test SID generation"""

        command = ['ipa', 'user-show', 'admin', '--all', '--raw']

        # TODO: remove duplicate definition and import from common module
        _sid_identifier_authority = '(0x[0-9a-f]{1,12}|[0-9]{1,10})'
        sid_regex = 'S-1-5-21-%(idauth)s-%(idauth)s-%(idauth)s'\
                    % dict(idauth=_sid_identifier_authority)
        stdout_re = re.escape('  ipaNTSecurityIdentifier: ') + sid_regex

        util.run_repeatedly(cls.master, command,
                            test=lambda x: re.search(stdout_re, x))

    @classmethod
    def configure_dns_and_time(cls):
        tasks.configure_dns_for_trust(cls.master, cls.ad)
        tasks.sync_time(cls.master, cls.ad)


class TestBasicADTrust(ADTrustBase):
    """Basic Integration test for Active Directory"""

    def test_establish_trust(self):
        """Tests establishing trust with Active Directory"""

        tasks.establish_trust_with_ad(self.master, self.ad,
            extra_args=['--range-type', 'ipa-ad-trust'])

    def test_range_properties_in_nonposix_trust(self):
        """Check the properties of the created range"""

        range_name = self.ad.domain.name.upper() + '_id_range'
        result = self.master.run_command(['ipa', 'idrange-show', range_name,
                                          '--all', '--raw'])
        assert "  ipaRangeType: ipa-ad-trust" in result.stdout_text
        assert "  ipaIDRangeSize: 200000" in result.stdout_text

    def test_user_gid_uid_resolution_in_nonposix_trust(self):
        """Check that user has SID-generated UID"""

        # Using domain name since it is lowercased realm name for AD domains
        testuser = 'testuser@%s' % self.ad.domain.name
        result = self.master.run_command(['getent', 'passwd', testuser])

        # This regex checks that Test User does not have UID 10042 nor belongs
        # to the group with GID 10047
        testuser_regex = "^testuser@%s:\*:(?!10042)(\d+):(?!10047)(\d+):"\
                         "Test User:/home/testuser:/bin/sh$"\
                         % re.escape(self.ad.domain.name)

        assert re.search(testuser_regex, result.stdout_text)

    def test_remove_nonposix_trust(self):
        tasks.remove_trust_with_ad(self.master, self.ad)
        tasks.clear_sssd_cache(self.master)


class TestPosixADTrust(ADTrustBase):
    """Integration test for Active Directory with POSIX support"""

    def test_establish_trust_with_posix_attributes(self):
        # Not specifying the --range-type directly, it should be detected
        tasks.establish_trust_with_ad(self.master, self.ad)

    def test_range_properties_in_posix_trust(self):
        # Check the properties of the created range

        range_name = self.ad.domain.name.upper() + '_id_range'

        result = self.master.run_command(['ipa', 'idrange-show', range_name,
                                          '--all', '--raw'])

        # Check the range type and size
        assert "  ipaRangeType: ipa-ad-trust-posix" in result.stdout_text
        assert "  ipaIDRangeSize: 200000" in result.stdout_text

    def test_user_uid_gid_resolution_in_posix_trust(self):
        # Check that user has AD-defined UID

        # Using domain name since it is lowercased realm name for AD domains
        testuser = 'testuser@%s' % self.ad.domain.name
        result = self.master.run_command(['getent', 'passwd', testuser])

        testuser_stdout = "testuser@%s:*:10042:10047:"\
                          "Test User:/home/testuser:/bin/sh"\
                          % self.ad.domain.name

        assert testuser_stdout in result.stdout_text

    def test_user_without_posix_attributes_not_visible(self):
        # Check that user has AD-defined UID

        # Using domain name since it is lowercased realm name for AD domains
        nonposixuser = 'nonposixuser@%s' % self.ad.domain.name
        result = self.master.run_command(['getent', 'passwd', nonposixuser],
                                         raiseonerr=False)

        # Getent exits with 2 for non-existent user
        assert result.returncode == 2

    def test_remove_trust_with_posix_attributes(self):
        tasks.remove_trust_with_ad(self.master, self.ad)
        tasks.clear_sssd_cache(self.master)


class TestEnforcedPosixADTrust(TestPosixADTrust):
    """
    This test is intented to copycat PosixADTrust, since enforcing the POSIX
    trust type should not make a difference.
    """

    def test_establish_trust_with_posix_attributes(self):
        tasks.establish_trust_with_ad(self.master, self.ad,
            extra_args=['--range-type', 'ipa-ad-trust-posix'])


class TestInvalidRangeTypes(ADTrustBase):
    """
    Tests invalid values being put into trust-add command.
    """

    def test_invalid_range_types(self):

        invalid_range_types = ['ipa-local',
                               'ipa-ad-winsync',
                               'ipa-ipa-trust',
                               'random-invalid',
                               're@ll%ybad12!']

        for range_type in invalid_range_types:
            tasks.kinit_admin(self.master)

            result = self.master.run_command(
                               ['ipa', 'trust-add',
                               '--type', 'ad', self.ad.domain.name,
                               '--admin', 'Administrator',
                               '--range-type', range_type,
                               '--password'],
                               raiseonerr=False,
                               stdin_text=self.master.config.ad_admin_password)

            # The trust-add command is supposed to fail
            assert result.returncode == 1