1import pytest
2from tests.support.mock import patch
3
4try:
5    import salt.states.reg as reg
6    import salt.utils.win_dacl as win_dacl
7    import salt.utils.win_functions as win_functions
8    import salt.utils.win_reg as reg_util
9
10    HAS_WIN_LIBS = True
11except ImportError:
12    HAS_WIN_LIBS = False
13
14pytestmark = [
15    pytest.mark.skip_unless_on_windows,
16    pytest.mark.skipif(HAS_WIN_LIBS is False, reason="Windows Libraries not available"),
17    pytest.mark.windows_whitelisted,
18]
19
20
21class RegVars:
22    """
23    Class for tests that require shared variables
24    """
25
26    def __init__(self):
27        self.hive = "HKEY_CURRENT_USER"
28        self.key = "SOFTWARE\\Salt-Testing"
29        self.hive = self.hive
30        self.key = self.key
31        self.name = "{}\\{}".format(self.hive, self.key)
32        self.vname = "version"
33        self.vdata = "0.15.3"
34        self.current_user = win_functions.get_current_user(with_domain=False)
35
36
37@pytest.fixture(scope="module")
38def configure_loader_modules():
39    return {
40        reg: {
41            "__opts__": {"test": False},
42            "__salt__": {},
43            "__utils__": {
44                "reg.cast_vdata": reg_util.cast_vdata,
45                "reg.delete_value": reg_util.delete_value,
46                "reg.read_value": reg_util.read_value,
47                "reg.set_value": reg_util.set_value,
48                "dacl.check_perms": win_dacl.check_perms,
49            },
50        },
51        win_dacl: {"__opts__": {"test": False}},
52    }
53
54
55@pytest.fixture(scope="function")
56def reg_vars():
57    return RegVars()
58
59
60@pytest.fixture(scope="function")
61def clean(reg_vars):
62    """
63    Make sure the key does NOT exist
64    """
65    try:
66        if reg_util.key_exists(hive=reg_vars.hive, key=reg_vars.key):
67            reg_util.delete_key_recursive(hive=reg_vars.hive, key=reg_vars.key)
68        yield
69    finally:
70        if reg_util.key_exists(hive=reg_vars.hive, key=reg_vars.key):
71            reg_util.delete_key_recursive(hive=reg_vars.hive, key=reg_vars.key)
72
73
74@pytest.fixture(scope="function")
75def reset(reg_vars):
76    """
77    Create an existing key for testing
78    """
79    try:
80        if not reg_util.value_exists(
81            hive=reg_vars.hive, key=reg_vars.key, vname=reg_vars.vname
82        ):
83            reg_util.set_value(
84                hive=reg_vars.hive,
85                key=reg_vars.key,
86                vname=reg_vars.vname,
87                vdata=reg_vars.vdata,
88            )
89        yield
90    finally:
91        if reg_util.key_exists(hive=reg_vars.hive, key=reg_vars.key):
92            reg_util.delete_key_recursive(hive=reg_vars.hive, key=reg_vars.key)
93
94
95def test_present(reg_vars):
96    """
97    Test reg.present
98    """
99    expected = {
100        "comment": "Added {} to {}".format(reg_vars.vname, reg_vars.name),
101        "changes": {
102            "reg": {
103                "Added": {
104                    "Inheritance": True,
105                    "Perms": {"Deny": None, "Grant": None},
106                    "Value": reg_vars.vdata,
107                    "Key": reg_vars.name,
108                    "Owner": None,
109                    "Entry": reg_vars.vname,
110                }
111            }
112        },
113        "name": reg_vars.name,
114        "result": True,
115    }
116    assert (
117        reg.present(name=reg_vars.name, vname=reg_vars.vname, vdata=reg_vars.vdata)
118        == expected
119    )
120    permissions = win_dacl.get_permissions(obj_name=reg_vars.name, obj_type="registry")
121    assert permissions["Not Inherited"] == {}
122
123
124def test_present_set_owner(reg_vars, clean):
125    """
126    Test reg.present
127    """
128    reg.present(
129        name=reg_vars.name,
130        vname=reg_vars.vname,
131        vdata=reg_vars.vdata,
132        win_owner=reg_vars.current_user,
133    )
134    assert (
135        win_dacl.get_owner(obj_name=reg_vars.name, obj_type="registry")
136        == reg_vars.current_user
137    )
138
139
140def test_present_perms_no_inherit(reg_vars, clean):
141    reg.present(
142        name=reg_vars.name,
143        vname=reg_vars.vname,
144        vdata=reg_vars.vdata,
145        win_inheritance=False,
146    )
147    assert not win_dacl.get_inheritance(obj_name=reg_vars.name, obj_type="registry")
148    permissions = win_dacl.get_permissions(obj_name=reg_vars.name, obj_type="registry")
149    assert permissions["Inherited"] == {}
150
151
152def test_present_perms(reg_vars, clean):
153    reg.present(
154        name=reg_vars.name,
155        vname=reg_vars.vname,
156        vdata=reg_vars.vdata,
157        win_perms={"Backup Operators": {"perms": "full_control"}},
158        win_deny_perms={"Guest": {"perms": "full_control"}},
159    )
160    permissions = win_dacl.get_permissions(obj_name=reg_vars.name, obj_type="registry")
161    expected = {
162        "deny": {"permissions": "Full Control", "applies to": "This key and subkeys"}
163    }
164    assert permissions["Not Inherited"].get("Guest") == expected
165    expected = {
166        "grant": {"permissions": "Full Control", "applies to": "This key and subkeys"}
167    }
168    assert permissions["Not Inherited"].get("Backup Operators") == expected
169
170
171def test_present_perms_reset(reg_vars, clean):
172    reg.present(
173        name=reg_vars.name,
174        vname=reg_vars.vname,
175        vdata=reg_vars.vdata,
176        win_perms={"Everyone": {"perms": "full_control"}},
177        win_deny_perms={"Guest": {"perms": "full_control"}},
178        win_perms_reset=True,
179    )
180    permissions = win_dacl.get_permissions(obj_name=reg_vars.name, obj_type="registry")
181    expected = {
182        "Guest": {
183            "deny": {
184                "permissions": "Full Control",
185                "applies to": "This key and subkeys",
186            }
187        },
188        "Everyone": {
189            "grant": {
190                "permissions": "Full Control",
191                "applies to": "This key and subkeys",
192            }
193        },
194    }
195    assert permissions["Not Inherited"] == expected
196
197
198def test_present_perms_reset_no_inherit(reg_vars, clean):
199    reg.present(
200        name=reg_vars.name,
201        vname=reg_vars.vname,
202        vdata=reg_vars.vdata,
203        win_perms={"Everyone": {"perms": "full_control"}},
204        win_deny_perms={"Guest": {"perms": "full_control"}},
205        win_perms_reset=True,
206        win_inheritance=False,
207    )
208    permissions = win_dacl.get_permissions(obj_name=reg_vars.name, obj_type="registry")
209    expected = {
210        "Guest": {
211            "deny": {
212                "permissions": "Full Control",
213                "applies to": "This key and subkeys",
214            }
215        },
216        "Everyone": {
217            "grant": {
218                "permissions": "Full Control",
219                "applies to": "This key and subkeys",
220            }
221        },
222    }
223    assert permissions["Not Inherited"] == expected
224    assert not win_dacl.get_inheritance(obj_name=reg_vars.name, obj_type="registry")
225    assert permissions["Inherited"] == {}
226
227
228def test_present_string_dword(reg_vars, clean):
229    """
230    Test to set a registry entry.
231    """
232    vname = "dword_data"
233    vdata = "00000001"
234    vtype = "REG_DWORD"
235    expected_vdata = 1
236    expected = {
237        "comment": "Added {} to {}".format(vname, reg_vars.name),
238        "changes": {
239            "reg": {
240                "Added": {
241                    "Inheritance": True,
242                    "Perms": {"Deny": None, "Grant": None},
243                    "Value": expected_vdata,
244                    "Key": reg_vars.name,
245                    "Owner": None,
246                    "Entry": vname,
247                }
248            }
249        },
250        "name": reg_vars.name,
251        "result": True,
252    }
253    assert (
254        reg.present(name=reg_vars.name, vname=vname, vdata=vdata, vtype=vtype)
255        == expected
256    )
257
258
259def test_present_string_dword_existing(reg_vars, clean):
260    """
261    Test to set a registry entry.
262    """
263    vname = "dword_data"
264    vdata = "0000001"
265    vtype = "REG_DWORD"
266    # Set it first
267    reg_util.set_value(
268        hive=reg_vars.hive, key=reg_vars.key, vname=vname, vdata=vdata, vtype=vtype
269    )
270    expected = {
271        "comment": "{} in {} is already present".format(vname, reg_vars.name),
272        "changes": {},
273        "name": reg_vars.name,
274        "result": True,
275    }
276    assert (
277        reg.present(name=reg_vars.name, vname=vname, vdata=vdata, vtype=vtype)
278        == expected
279    )
280
281
282def test_present_test_true(reg_vars, clean):
283    expected = {
284        "comment": "",
285        "changes": {
286            "reg": {
287                "Will add": {
288                    "Inheritance": True,
289                    "Perms": {"Deny": None, "Grant": None},
290                    "Value": reg_vars.vdata,
291                    "Key": reg_vars.name,
292                    "Owner": None,
293                    "Entry": "version",
294                }
295            }
296        },
297        "name": reg_vars.name,
298        "result": None,
299    }
300    with patch.dict(reg.__opts__, {"test": True}):
301        ret = reg.present(reg_vars.name, vname=reg_vars.vname, vdata=reg_vars.vdata)
302    assert ret == expected
303
304
305def test_present_existing(reg_vars, reset):
306    expected = {
307        "comment": "{} in {} is already present".format(reg_vars.vname, reg_vars.name),
308        "changes": {},
309        "name": reg_vars.name,
310        "result": True,
311    }
312    assert (
313        reg.present(name=reg_vars.name, vname=reg_vars.vname, vdata=reg_vars.vdata)
314        == expected
315    )
316
317
318def test_present_existing_key_only(reg_vars, clean):
319    """
320    Test setting only a key with no value name
321    """
322    # Create the reg key for testing
323    reg_util.set_value(hive=reg_vars.hive, key=reg_vars.key)
324
325    expected = {
326        "comment": "(Default) in {} is already present".format(reg_vars.name),
327        "changes": {},
328        "name": reg_vars.name,
329        "result": True,
330    }
331    assert reg.present(reg_vars.name) == expected
332
333
334def test_present_existing_test_true(reg_vars, reset):
335    expected = {
336        "comment": "{} in {} is already present".format(reg_vars.vname, reg_vars.name),
337        "changes": {},
338        "name": reg_vars.name,
339        "result": True,
340    }
341    with patch.dict(reg.__opts__, {"test": True}):
342        ret = reg.present(
343            name=reg_vars.name, vname=reg_vars.vname, vdata=reg_vars.vdata
344        )
345    assert ret == expected
346
347
348def test_absent(reg_vars, reset):
349    """
350    Test to remove a registry entry.
351    """
352    expected = {
353        "comment": "Removed {} from {}".format(reg_vars.key, reg_vars.hive),
354        "changes": {
355            "reg": {"Removed": {"Entry": reg_vars.vname, "Key": reg_vars.name}}
356        },
357        "name": reg_vars.name,
358        "result": True,
359    }
360    assert reg.absent(reg_vars.name, reg_vars.vname) == expected
361
362
363def test_absent_test_true(reg_vars, reset):
364    expected = {
365        "comment": "",
366        "changes": {
367            "reg": {"Will remove": {"Entry": reg_vars.vname, "Key": reg_vars.name}}
368        },
369        "name": reg_vars.name,
370        "result": None,
371    }
372    with patch.dict(reg.__opts__, {"test": True}):
373        ret = reg.absent(reg_vars.name, reg_vars.vname)
374    assert ret == expected
375
376
377def test_absent_already_absent(reg_vars, clean):
378    """
379    Test to remove a registry entry.
380    """
381    expected = {
382        "comment": "{} is already absent".format(reg_vars.name),
383        "changes": {},
384        "name": reg_vars.name,
385        "result": True,
386    }
387    assert reg.absent(reg_vars.name, reg_vars.vname) == expected
388
389
390def test_absent_already_absent_test_true(reg_vars, clean):
391    """
392    Test to remove a registry entry.
393    """
394    expected = {
395        "comment": "{} is already absent".format(reg_vars.name),
396        "changes": {},
397        "name": reg_vars.name,
398        "result": True,
399    }
400    with patch.dict(reg.__opts__, {"test": True}):
401        ret = reg.absent(reg_vars.name, reg_vars.vname)
402    assert ret == expected
403