File: test_sysaccount_plugin.py

package info (click to toggle)
freeipa 4.13.1-1
  • links: PTS, VCS
  • area: main
  • in suites: sid
  • size: 367,240 kB
  • sloc: javascript: 562,763; python: 310,289; ansic: 49,809; sh: 7,176; makefile: 2,589; xml: 343; sed: 16
file content (300 lines) | stat: -rw-r--r-- 11,856 bytes parent folder | download
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
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
# Copyright (C) 2025  Red Hat
# see file 'COPYING' for use and warranty information

"""
Test the `ipaserver/plugins/sysaccounts.py` module.
"""

from __future__ import print_function

import pytest

from ipalib import api, errors
from ipatests.test_xmlrpc.xmlrpc_test import XMLRPC_test
from ipatests.util import change_principal, unlock_principal_password
from ipatests.test_xmlrpc.xmlrpc_test import assert_attr_equal
from ipatests.test_xmlrpc.tracker.sysaccount_plugin import SysaccountTracker

NORMAL_USER = u'test-normal-user'
NORMAL_USER_PASSWORD = u'Secret123'
SECURITY_ARCHITECT_USER = u'test-security-architect'
SECURITY_ARCHITECT_PASSWORD = u'Secret123'
SECURITY_ARCHITECT_ROLE = u'Security Architect'

TEST_SYSACCOUNT_1 = u'test-sysaccount-1'
TEST_SYSACCOUNT_2 = u'test-sysaccount-2'
TEST_SYSACCOUNT_3 = u'test-sysaccount-3'


@pytest.fixture(scope='class')
def sysaccount_1(request, xmlrpc_setup):
    """Fixture for TEST_SYSACCOUNT_1"""
    tracker = SysaccountTracker(name=TEST_SYSACCOUNT_1)
    return tracker.make_fixture(request)


@pytest.fixture(scope='class')
def sysaccount_2(request, xmlrpc_setup):
    """Fixture for TEST_SYSACCOUNT_2"""
    tracker = SysaccountTracker(
        name=TEST_SYSACCOUNT_2,
        description=u'Test system account for show'
    )
    return tracker.make_fixture(request)


@pytest.fixture(scope='class')
def sysaccount_3(request, xmlrpc_setup):
    """Fixture for TEST_SYSACCOUNT_3"""
    tracker = SysaccountTracker(name=TEST_SYSACCOUNT_3)
    return tracker.make_fixture(request)


@pytest.mark.tier1
class TestSysaccountPermissions(XMLRPC_test):
    """
    Test system account permissions with different user roles.
    """

    def test_setup(self):
        api.Command.user_add(
            NORMAL_USER,
            givenname=u'Normal',
            sn=u'User',
            userpassword=NORMAL_USER_PASSWORD
        )
        unlock_principal_password(NORMAL_USER, NORMAL_USER_PASSWORD,
                                  NORMAL_USER_PASSWORD)

        # Create Security Architect user
        api.Command.user_add(
            SECURITY_ARCHITECT_USER,
            givenname=u'Security',
            sn=u'Architect',
            userpassword=SECURITY_ARCHITECT_PASSWORD
        )
        unlock_principal_password(SECURITY_ARCHITECT_USER,
                                  SECURITY_ARCHITECT_PASSWORD,
                                  SECURITY_ARCHITECT_PASSWORD)

        # Add Security Architect user to Security Architect role
        api.Command.role_add_member(SECURITY_ARCHITECT_ROLE,
                                    user=SECURITY_ARCHITECT_USER)

    def test_normal_user_cannot_add_sysaccount(self):
        """Test that a normal user cannot add a system account"""
        with change_principal(NORMAL_USER, NORMAL_USER_PASSWORD):
            with pytest.raises(errors.ACIError):
                api.Command.sysaccount_add(TEST_SYSACCOUNT_1, random=True)

    def test_normal_user_cannot_modify_sysaccount(self, sysaccount_1):
        """Test that a normal user cannot modify a system account"""
        # Create the sysaccount as admin
        sysaccount_1.create()

        with change_principal(NORMAL_USER, NORMAL_USER_PASSWORD):
            with pytest.raises(errors.ACIError):
                api.Command.sysaccount_mod(
                    TEST_SYSACCOUNT_1,
                    description=u'Modified description'
                )

    def test_normal_user_cannot_delete_sysaccount(self, sysaccount_1):
        """Test that a normal user cannot delete a system account"""
        # Create the sysaccount as admin
        sysaccount_1.create()

        with change_principal(NORMAL_USER, NORMAL_USER_PASSWORD):
            with pytest.raises(errors.ACIError):
                api.Command.sysaccount_del(TEST_SYSACCOUNT_1)

    def test_security_architect_can_add_sysaccount(self):
        """Test that a Security Architect user can add a system account"""
        with change_principal(SECURITY_ARCHITECT_USER,
                              SECURITY_ARCHITECT_PASSWORD):
            result = api.Command.sysaccount_add(
                TEST_SYSACCOUNT_2,
                random=True
            )
            assert result['value'] == TEST_SYSACCOUNT_2
            assert 'result' in result

        # Clean up
        try:
            api.Command.sysaccount_del(TEST_SYSACCOUNT_2)
        except Exception:
            pass

    def test_security_architect_can_modify_sysaccount(self, sysaccount_3):
        """Test that a Security Architect user can modify a system account"""
        # First create the sysaccount
        sysaccount_3.create()

        with change_principal(SECURITY_ARCHITECT_USER,
                              SECURITY_ARCHITECT_PASSWORD):
            result = api.Command.sysaccount_mod(
                TEST_SYSACCOUNT_3,
                description=u'Modified by Security Architect'
            )
            assert result['value'] == TEST_SYSACCOUNT_3

            # Verify the modification
            show_result = api.Command.sysaccount_show(TEST_SYSACCOUNT_3)
            assert_attr_equal(
                show_result['result'], 'description',
                'Modified by Security Architect'
            )

    def test_security_architect_can_delete_sysaccount(self, sysaccount_3):
        """Test that a Security Architect user can delete a system account"""
        # First create the sysaccount
        sysaccount_3.create()

        with change_principal(SECURITY_ARCHITECT_USER,
                              SECURITY_ARCHITECT_PASSWORD):
            result = api.Command.sysaccount_del(TEST_SYSACCOUNT_3)
            assert TEST_SYSACCOUNT_3 in result['value']

        # Mark the tracker as deleted so cleanup doesn't fail
        sysaccount_3.exists = False

        # Verify it's deleted
        with pytest.raises(errors.NotFound):
            api.Command.sysaccount_show(TEST_SYSACCOUNT_3)

    def test_security_architect_can_show_sysaccount(self, sysaccount_2):
        """Test that a Security Architect user can show a system account"""
        # First create the sysaccount as admin
        sysaccount_2.create()

        with change_principal(SECURITY_ARCHITECT_USER,
                              SECURITY_ARCHITECT_PASSWORD):
            result = api.Command.sysaccount_show(TEST_SYSACCOUNT_2)
            assert_attr_equal(
                result['result'], 'description',
                'Test system account for show'
            )

    def test_security_architect_can_find_sysaccount(self, sysaccount_2):
        """Test that a Security Architect user can find system accounts"""
        # First create a test sysaccount as admin with description
        # Use ensure_missing to clean up any existing entry first
        sysaccount_2.ensure_missing()
        api.Command.sysaccount_add(
            TEST_SYSACCOUNT_2,
            random=True,
            description=u'Test system account for find'
        )

        try:
            with change_principal(SECURITY_ARCHITECT_USER,
                                  SECURITY_ARCHITECT_PASSWORD):
                # Test find all sysaccounts
                result = api.Command.sysaccount_find()
                assert 'result' in result
                # Should find at least our test sysaccount
                found = False
                for entry in result['result']:
                    uid_value = entry.get('uid')
                    if isinstance(uid_value, tuple):
                        uid_value = list(uid_value)
                    elif not isinstance(uid_value, list):
                        uid_value = [uid_value]
                    if TEST_SYSACCOUNT_2 in uid_value:
                        found = True
                        # Description might not be in entry if it's None/empty
                        if 'description' in entry:
                            assert_attr_equal(
                                entry, 'description',
                                'Test system account for find'
                            )
                        break
                assert found, f"Test sysaccount {TEST_SYSACCOUNT_2} not found"

                # Test find with specific criteria
                result = api.Command.sysaccount_find(TEST_SYSACCOUNT_2)
                # Should find our test sysaccount
                found = False
                for entry in result['result']:
                    uid_value = entry.get('uid')
                    if isinstance(uid_value, tuple):
                        uid_value = list(uid_value)
                    elif not isinstance(uid_value, list):
                        uid_value = [uid_value]
                    if TEST_SYSACCOUNT_2 in uid_value:
                        found = True
                        break
                assert found, f"Test sysaccount {TEST_SYSACCOUNT_2} not found"
        finally:
            # Clean up
            try:
                api.Command.sysaccount_del(TEST_SYSACCOUNT_2)
            except Exception:
                pass

    def test_security_architect_can_disable_sysaccount(self, sysaccount_2):
        """Test that a Security Architect user can disable a system account"""
        # First create the sysaccount as admin
        sysaccount_2.create()

        with change_principal(SECURITY_ARCHITECT_USER,
                              SECURITY_ARCHITECT_PASSWORD):
            # Disable the sysaccount
            result = api.Command.sysaccount_disable(TEST_SYSACCOUNT_2)
            assert result['value'] == TEST_SYSACCOUNT_2
            assert result['result'] is True

            # Verify it's disabled
            show_result = api.Command.sysaccount_show(TEST_SYSACCOUNT_2)
            assert show_result['result']['nsaccountlock'] is True

    def test_security_architect_can_enable_sysaccount(self, sysaccount_2):
        """Test that a Security Architect user can enable a system account"""
        # First create the sysaccount as admin
        sysaccount_2.create()

        with change_principal(SECURITY_ARCHITECT_USER,
                              SECURITY_ARCHITECT_PASSWORD):
            # Enable the sysaccount
            result = api.Command.sysaccount_enable(TEST_SYSACCOUNT_2)
            assert result['value'] == TEST_SYSACCOUNT_2
            assert result['result'] is True

            # Verify it's enabled
            show_result = api.Command.sysaccount_show(TEST_SYSACCOUNT_2)
            assert show_result['result']['nsaccountlock'] is False

    def test_security_architect_can_set_sysaccount_policy(self, sysaccount_2):
        """Test that a Security Architect user can set sysaccount policy"""
        # First create the sysaccount as admin
        sysaccount_2.create()

        with change_principal(SECURITY_ARCHITECT_USER,
                              SECURITY_ARCHITECT_PASSWORD):
            # Set privileged policy to True
            result = api.Command.sysaccount_policy(
                TEST_SYSACCOUNT_2,
                privileged=True
            )
            assert result['value'] == TEST_SYSACCOUNT_2

            # Verify the policy is set
            show_result = api.Command.sysaccount_show(
                TEST_SYSACCOUNT_2, all=True
            )
            assert show_result['result'].get('privileged') is True

            # Set privileged policy to False
            result = api.Command.sysaccount_policy(
                TEST_SYSACCOUNT_2,
                privileged=False
            )
            assert result['value'] == TEST_SYSACCOUNT_2

            # Verify the policy is unset
            show_result = api.Command.sysaccount_show(
                TEST_SYSACCOUNT_2, all=True
            )
            # privileged=False means the attribute should not be present
            # or should be False
            assert show_result['result'].get('privileged') is not True