test_win_lgpo.py 39 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684
  1. # -*- coding: utf-8 -*-
  2. # Import Python libs
  3. from __future__ import absolute_import, print_function, unicode_literals
  4. import os
  5. import re
  6. import io
  7. import logging
  8. import pytest
  9. # Import Salt Testing libs
  10. from tests.support.case import ModuleCase
  11. from tests.support.unit import skipIf
  12. from tests.support.helpers import generate_random_name
  13. from tests.support.runtests import RUNTIME_VARS
  14. # Import Salt libs
  15. import salt.utils.files
  16. import salt.utils.platform
  17. import salt.utils.win_reg as reg
  18. log = logging.getLogger(__name__)
  19. @skipIf(not salt.utils.platform.is_windows(), 'windows test only')
  20. class WinLgpoTest(ModuleCase):
  21. '''
  22. Tests for salt.modules.win_lgpo
  23. '''
  24. osrelease = None
  25. def _testRegistryPolicy(self,
  26. policy_name,
  27. policy_config,
  28. registry_value_hive,
  29. registry_value_path,
  30. registry_value_vname,
  31. expected_value_data):
  32. '''
  33. Takes a registry based policy name and config and validates that the
  34. expected registry value exists and has the correct data
  35. policy_name
  36. name of the registry based policy to configure
  37. policy_config
  38. the configuration of the policy
  39. registry_value_hive
  40. the registry hive that the policy registry path is in
  41. registry_value_path
  42. the registry value path that the policy updates
  43. registry_value_vname
  44. the registry value name
  45. expected_value_data
  46. the expected data that the value will contain
  47. '''
  48. ret = self.run_function('lgpo.set_computer_policy',
  49. (policy_name, policy_config))
  50. self.assertTrue(ret)
  51. val = reg.read_value(
  52. registry_value_hive,
  53. registry_value_path,
  54. registry_value_vname)
  55. self.assertTrue(val['success'], msg='Failed to obtain the registry data for policy {0}'.format(policy_name))
  56. if val['success']:
  57. self.assertEqual(val['vdata'], expected_value_data, 'The registry value data {0} does not match the expected value {1} for policy {2}'.format(
  58. val['vdata'],
  59. expected_value_data,
  60. policy_name))
  61. def _testSeceditPolicy(self,
  62. policy_name,
  63. policy_config,
  64. expected_regexes,
  65. cumulative_rights_assignments=True):
  66. '''
  67. Takes a secedit policy name and config and validates that the expected
  68. output is returned from secedit
  69. policy_name
  70. name of the secedit policy to configure
  71. policy_config
  72. the configuration of the policy
  73. expected_regexes
  74. the expected regexes to be found in the secedit output file
  75. '''
  76. ret = self.run_function('lgpo.set_computer_policy',
  77. (policy_name, policy_config),
  78. cumulative_rights_assignments=cumulative_rights_assignments)
  79. self.assertTrue(ret)
  80. secedit_output_file = os.path.join(RUNTIME_VARS.TMP, generate_random_name('secedit-output-'))
  81. secedit_output = self.run_function(
  82. 'cmd.run',
  83. (),
  84. cmd='secedit /export /cfg {0}'.format(secedit_output_file))
  85. secedit_file_content = None
  86. if secedit_output:
  87. with io.open(secedit_output_file, encoding='utf-16') as _reader:
  88. secedit_file_content = _reader.read()
  89. for expected_regex in expected_regexes:
  90. match = re.search(
  91. expected_regex,
  92. secedit_file_content,
  93. re.IGNORECASE | re.MULTILINE)
  94. self.assertIsNotNone(match, 'Failed validating policy "{0}" configuration, regex "{1}" not found in secedit output'.format(policy_name, expected_regex))
  95. def _testAdmxPolicy(self,
  96. policy_name,
  97. policy_config,
  98. expected_regexes,
  99. assert_true=True,
  100. policy_class='Machine'):
  101. '''
  102. Takes a ADMX policy name and config and validates that the expected
  103. output is returned from lgpo looking at the Registry.pol file
  104. policy_name
  105. name of the ADMX policy to configure
  106. policy_config
  107. the configuration of the policy
  108. expected_regexes
  109. the expected regexes to be found in the lgpo parse output
  110. assert_true
  111. set to false if expecting the module run to fail
  112. policy_class
  113. the policy class this policy belongs to, either Machine or User
  114. '''
  115. lgpo_function = 'set_computer_policy'
  116. lgpo_class = '/m'
  117. lgpo_folder = 'Machine'
  118. if policy_class.lower() == 'user':
  119. lgpo_function = 'set_user_policy'
  120. lgpo_class = '/u'
  121. lgpo_folder = 'User'
  122. ret = self.run_function('lgpo.{0}'.format(lgpo_function),
  123. (policy_name, policy_config))
  124. log.debug('lgpo set_computer_policy ret == %s', ret)
  125. cmd = ['lgpo.exe',
  126. '/parse',
  127. lgpo_class,
  128. r'c:\Windows\System32\GroupPolicy\{}\Registry.pol'.format(lgpo_folder)]
  129. if assert_true:
  130. self.assertTrue(ret)
  131. lgpo_output = self.run_function('cmd.run', (), cmd=' '.join(cmd))
  132. # validate that the lgpo output doesn't say the format is invalid
  133. self.assertIsNone(
  134. re.search(r'Invalid file format\.', lgpo_output, re.IGNORECASE),
  135. msg='Failed validating Registry.pol file format')
  136. # validate that the regexes we expect are in the output
  137. for expected_regex in expected_regexes:
  138. match = re.search(expected_regex, lgpo_output, re.IGNORECASE)
  139. self.assertIsNotNone(
  140. match,
  141. msg='Failed validating policy "{0}" configuration, regex '
  142. '"{1}" not found in lgpo output:\n{2}'
  143. ''.format(policy_name, expected_regex, lgpo_output))
  144. else:
  145. # expecting it to fail
  146. self.assertNotEqual(ret, True)
  147. def runTest(self):
  148. '''
  149. runTest method
  150. '''
  151. pass
  152. @classmethod
  153. def setUpClass(cls):
  154. '''
  155. class setup function, only runs once
  156. downloads and extracts the lgpo.exe tool into c:/windows/system32
  157. for use in validating the registry.pol files
  158. gets osrelease grain for tests that are only applicable to certain
  159. windows versions
  160. '''
  161. osrelease_grains = cls().run_function('grains.item', ['osrelease'])
  162. if 'osrelease' in osrelease_grains:
  163. cls.osrelease = osrelease_grains['osrelease']
  164. else:
  165. log.debug('Unable to get osrelease grain')
  166. if not os.path.exists(r'c:\windows\system32\lgpo.exe'):
  167. log.debug('lgpo.exe does not exist, attempting to download/extract')
  168. ret = cls().run_function('state.single',
  169. ('archive.extracted', r'c:\windows\system32'),
  170. source='https://download.microsoft.com/download/8/5/C/85C25433-A1B0-4FFA-9429-7E023E7DA8D8/LGPO.zip',
  171. archive_format='zip',
  172. source_hash='sha256=6ffb6416366652993c992280e29faea3507b5b5aa661c33ba1af31f48acea9c4',
  173. enforce_toplevel=False)
  174. log.debug('ret from archive.unzip == %s', ret)
  175. @pytest.mark.destructive_test
  176. def test_set_user_policy_point_and_print_restrictions(self):
  177. '''
  178. Test setting/unsetting/changing the PointAndPrint_Restrictions user policy
  179. '''
  180. # Disable Point and Print Restrictions
  181. self._testAdmxPolicy(
  182. r'Control Panel\Printers\Point and Print Restrictions',
  183. 'Disabled',
  184. [
  185. r'User[\s]*Software\\Policies\\Microsoft\\Windows NT\\Printers\\PointAndPrint[\s]*Restricted[\s]*DWORD:0',
  186. r'User[\s]*Software\\Policies\\Microsoft\\Windows NT\\Printers\\PointAndPrint[\s]*TrustedServers[\s]*DELETE',
  187. r'User[\s]*Software\\Policies\\Microsoft\\Windows NT\\Printers\\PointAndPrint[\s]*ServerList[\s]*DELETE',
  188. r'User[\s]*Software\\Policies\\Microsoft\\Windows NT\\Printers\\PointAndPrint[\s]*InForest[\s]*DELETE',
  189. r'User[\s]*Software\\Policies\\Microsoft\\Windows NT\\Printers\\PointAndPrint[\s]*NoWarningNoElevationOnInstall[\s]*DELETE',
  190. r'User[\s]*Software\\Policies\\Microsoft\\Windows NT\\Printers\\PointAndPrint[\s]*UpdatePromptSettings[\s]*DELETE',
  191. ],
  192. policy_class='User')
  193. # Enable Point and Print Restrictions
  194. self._testAdmxPolicy(
  195. r'Control Panel\Printers\Point and Print Restrictions',
  196. {
  197. 'Users can only point and print to these servers': True,
  198. 'Enter fully qualified server names separated by semicolons': 'fakeserver1;fakeserver2',
  199. 'Users can only point and print to machines in their forest': True,
  200. 'Security Prompts: When installing drivers for a new connection': 'Show warning and elevation prompt',
  201. 'When updating drivers for an existing connection': 'Do not show warning or elevation prompt',
  202. },
  203. [
  204. r'User[\s]*Software\\Policies\\Microsoft\\Windows NT\\Printers\\PointAndPrint[\s]*Restricted[\s]*DWORD:1',
  205. r'User[\s]*Software\\Policies\\Microsoft\\Windows NT\\Printers\\PointAndPrint[\s]*TrustedServers[\s]*DWORD:1',
  206. r'User[\s]*Software\\Policies\\Microsoft\\Windows NT\\Printers\\PointAndPrint[\s]*ServerList[\s]*SZ:fakeserver1;fakeserver2',
  207. r'User[\s]*Software\\Policies\\Microsoft\\Windows NT\\Printers\\PointAndPrint[\s]*InForest[\s]*DWORD:1',
  208. r'User[\s]*Software\\Policies\\Microsoft\\Windows NT\\Printers\\PointAndPrint[\s]*NoWarningNoElevationOnInstall[\s]*DWORD:0',
  209. r'User[\s]*Software\\Policies\\Microsoft\\Windows NT\\Printers\\PointAndPrint[\s]*UpdatePromptSettings[\s]*DWORD:2',
  210. ],
  211. policy_class='User')
  212. # set Point and Print Restrictions to 'Not Configured'
  213. self._testAdmxPolicy(
  214. r'Control Panel\Printers\Point and Print Restrictions',
  215. 'Not Configured',
  216. [
  217. r'; Source file: c:\\windows\\system32\\grouppolicy\\user\\registry.pol[\s]*; PARSING COMPLETED.'],
  218. policy_class='User')
  219. @pytest.mark.destructive_test
  220. def test_set_computer_policy_NTP_Client(self):
  221. '''
  222. Test setting/unsetting/changing NTP Client policies
  223. '''
  224. # Disable Configure NTP Client
  225. self._testAdmxPolicy(r'System\Windows Time Service\Time Providers\Configure Windows NTP Client',
  226. 'Disabled',
  227. [
  228. r'Computer[\s]*Software\\Policies\\Microsoft\\W32time\\Parameters[\s]*NtpServer[\s]*DELETE',
  229. r'Computer[\s]*Software\\Policies\\Microsoft\\W32time\\Parameters[\s]*Type[\s]*DELETE',
  230. r'Computer[\s]*Software\\Policies\\Microsoft\\W32time\\TimeProviders\\NtpClient[\s]*CrossSiteSyncFlags[\s]*DELETE',
  231. r'Computer[\s]*Software\\Policies\\Microsoft\\W32time\\TimeProviders\\NtpClient[\s]*ResolvePeerBackoffMinutes[\s]*DELETE',
  232. r'Computer[\s]*Software\\Policies\\Microsoft\\W32time\\TimeProviders\\NtpClient[\s]*ResolvePeerBackoffMaxTimes[\s]*DELETE',
  233. r'Computer[\s]*Software\\Policies\\Microsoft\\W32time\\TimeProviders\\NtpClient[\s]*SpecialPollInterval[\s]*DELETE',
  234. r'Computer[\s]*Software\\Policies\\Microsoft\\W32time\\TimeProviders\\NtpClient[\s]*EventLogFlags[\s]*DELETE'
  235. ])
  236. # Enable Configure NTP Client
  237. self._testAdmxPolicy(r'System\Windows Time Service\Time Providers\Configure Windows NTP Client',
  238. {
  239. 'NtpServer': 'time.windows.com,0x9',
  240. 'Type': 'NT5DS',
  241. 'CrossSiteSyncFlags': 2,
  242. 'ResolvePeerBackoffMinutes': 15,
  243. 'ResolvePeerBackoffMaxTimes': 7,
  244. 'W32TIME_SpecialPollInterval': 3600,
  245. 'W32TIME_NtpClientEventLogFlags': 0
  246. },
  247. [
  248. r'Computer[\s]*Software\\Policies\\Microsoft\\W32time\\Parameters[\s]*NtpServer[\s]*SZ:time.windows.com,0x9',
  249. r'Computer[\s]*Software\\Policies\\Microsoft\\W32time\\Parameters[\s]*Type[\s]*SZ:NT5DS',
  250. r'Computer[\s]*Software\\Policies\\Microsoft\\W32time\\TimeProviders\\NtpClient[\s]*CrossSiteSyncFlags[\s]*DWORD:2',
  251. r'Computer[\s]*Software\\Policies\\Microsoft\\W32time\\TimeProviders\\NtpClient[\s]*ResolvePeerBackoffMinutes[\s]*DWORD:15',
  252. r'Computer[\s]*Software\\Policies\\Microsoft\\W32time\\TimeProviders\\NtpClient[\s]*ResolvePeerBackoffMaxTimes[\s]*DWORD:7',
  253. r'Computer[\s]*Software\\Policies\\Microsoft\\W32time\\TimeProviders\\NtpClient[\s]*SpecialPollInterval[\s]*DWORD:3600',
  254. r'Computer[\s]*Software\\Policies\\Microsoft\\W32time\\TimeProviders\\NtpClient[\s]*EventLogFlags[\s]*DWORD:0',
  255. ])
  256. # set Configure NTP Client to 'Not Configured'
  257. self._testAdmxPolicy(r'System\Windows Time Service\Time Providers\Configure Windows NTP Client',
  258. 'Not Configured',
  259. [r'; Source file: c:\\windows\\system32\\grouppolicy\\machine\\registry.pol[\s]*; PARSING COMPLETED.'])
  260. @pytest.mark.destructive_test
  261. def test_set_computer_policy_RA_Unsolicit(self):
  262. '''
  263. Test setting/unsetting/changing RA_Unsolicit policy
  264. '''
  265. # Disable RA_Unsolicit
  266. log.debug('Attempting to disable RA_Unsolicit')
  267. self._testAdmxPolicy('RA_Unsolicit',
  268. 'Disabled',
  269. [
  270. r'Computer[\s]*Software\\policies\\Microsoft\\Windows NT\\Terminal Services[\s]*fAllowUnsolicited[\s]*DWORD:0',
  271. r'Computer[\s]*Software\\policies\\Microsoft\\Windows NT\\Terminal Services[\s]*fAllowUnsolicitedFullControl[\s]*DELETE',
  272. r'Computer[\s]*Software\\policies\\Microsoft\\Windows NT\\Terminal Services\\RAUnsolicit[\s]*\*[\s]*DELETEALLVALUES',
  273. ])
  274. # configure RA_Unsolicit
  275. log.debug('Attempting to configure RA_Unsolicit')
  276. self._testAdmxPolicy('RA_Unsolicit',
  277. {
  278. 'Configure Offer Remote Access': 'Enabled',
  279. 'Permit remote control of this computer': 'Allow helpers to remotely control the computer',
  280. 'Helpers': ['administrators', 'user1']
  281. },
  282. [
  283. r'Computer[\s]*Software\\policies\\Microsoft\\Windows NT\\Terminal Services\\RAUnsolicit[\s]*user1[\s]*SZ:user1[\s]*',
  284. r'Computer[\s]*Software\\policies\\Microsoft\\Windows NT\\Terminal Services\\RAUnsolicit[\s]*administrators[\s]*SZ:administrators[\s]*',
  285. r'Computer[\s]*Software\\policies\\Microsoft\\Windows NT\\Terminal Services[\s]*fAllowUnsolicited[\s]*DWORD:1',
  286. r'Computer[\s]*Software\\policies\\Microsoft\\Windows NT\\Terminal Services[\s]*fAllowUnsolicitedFullControl[\s]*DWORD:1',
  287. ])
  288. # Not Configure RA_Unsolicit
  289. log.debug('Attempting to set RA_Unsolicit to Not Configured')
  290. self._testAdmxPolicy('RA_Unsolicit',
  291. 'Not Configured',
  292. [r'; Source file: c:\\windows\\system32\\grouppolicy\\machine\\registry.pol[\s]*; PARSING COMPLETED.'])
  293. @pytest.mark.destructive_test
  294. def test_set_computer_policy_Pol_HardenedPaths(self):
  295. # Disable Pol_HardenedPaths
  296. log.debug('Attempting to disable Pol_HardenedPaths')
  297. self._testAdmxPolicy(
  298. 'Pol_HardenedPaths',
  299. 'Disabled',
  300. [r'Computer[\s]*Software\\policies\\Microsoft\\Windows\\NetworkProvider\\HardenedPaths[\s]*\*[\s]*DELETEALLVALUES'])
  301. # Configure Pol_HardenedPaths
  302. log.debug('Attempting to configure Pol_HardenedPaths')
  303. self._testAdmxPolicy(
  304. 'Pol_HardenedPaths',
  305. {
  306. 'Hardened UNC Paths': {
  307. r'\\*\NETLOGON': 'RequireMutualAuthentication=1, RequireIntegrity=1',
  308. r'\\*\SYSVOL': 'RequireMutualAuthentication=1, RequireIntegrity=1'
  309. }
  310. },
  311. [
  312. r'Computer[\s]*Software\\policies\\Microsoft\\Windows\\NetworkProvider\\HardenedPaths[\s]*\\\\\*\\NETLOGON[\s]*SZ:RequireMutualAuthentication=1, RequireIntegrity=1[\s]*',
  313. r'Computer[\s]*Software\\policies\\Microsoft\\Windows\\NetworkProvider\\HardenedPaths[\s]*\\\\\*\\SYSVOL[\s]*SZ:RequireMutualAuthentication=1, RequireIntegrity=1[\s]*',
  314. ])
  315. # Not Configure Pol_HardenedPaths
  316. log.debug('Attempting to set Pol_HardenedPaths to Not Configured')
  317. self._testAdmxPolicy(
  318. 'Pol_HardenedPaths',
  319. 'Not Configured',
  320. [r'; Source file: c:\\windows\\system32\\grouppolicy\\machine\\registry.pol[\s]*; PARSING COMPLETED.'])
  321. @pytest.mark.destructive_test
  322. def test_set_computer_policy_WindowsUpdate(self):
  323. '''
  324. Test setting/unsetting/changing WindowsUpdate policy
  325. '''
  326. the_policy = {
  327. 'Configure automatic updating': '4 - Auto download and schedule the install',
  328. 'Install during automatic maintenance': False,
  329. 'Scheduled install day': '7 - Every Saturday',
  330. 'Scheduled install time': '17:00',
  331. 'Install updates for other Microsoft products': True
  332. }
  333. the_policy_check = [
  334. r'Computer[\s]*Software\\Policies\\Microsoft\\Windows\\WindowsUpdate\\AU[\s]*NoAutoUpdate[\s]*DWORD:0',
  335. r'Computer[\s]*Software\\Policies\\Microsoft\\Windows\\WindowsUpdate\\AU[\s]*AUOptions[\s]*DWORD:4',
  336. r'Computer[\s]*Software\\Policies\\Microsoft\\Windows\\WindowsUpdate\\AU[\s]*AutomaticMaintenanceEnabled[\s]*DELETE',
  337. r'Computer[\s]*Software\\Policies\\Microsoft\\Windows\\WindowsUpdate\\AU[\s]*ScheduledInstallDay[\s]*DWORD:7',
  338. r'Computer[\s]*Software\\Policies\\Microsoft\\Windows\\WindowsUpdate\\AU[\s]*ScheduledInstallTime[\s]*DWORD:17',
  339. r'Computer[\s]*Software\\Policies\\Microsoft\\Windows\\WindowsUpdate\\AU[\s]*AllowMUUpdateService[\s]*DWORD:1\s*'
  340. ]
  341. # Configure Automatic Updates has different options in 2016 than in 2012
  342. # and has only one boolean item, so we'll test it "False" in this block
  343. # and then "True" in next block
  344. if self.osrelease in ['2012Server', '2012ServerR2']:
  345. the_policy = {
  346. 'Configure automatic updating': '4 - Auto download and schedule the install',
  347. 'Install during automatic maintenance': False,
  348. 'Schedule install day': '7 - Every Saturday',
  349. 'Schedule install time': '17:00',
  350. }
  351. the_policy_check = [
  352. r'Computer[\s]*Software\\Policies\\Microsoft\\Windows\\WindowsUpdate\\AU[\s]*NoAutoUpdate[\s]*DWORD:0',
  353. r'Computer[\s]*Software\\Policies\\Microsoft\\Windows\\WindowsUpdate\\AU[\s]*AUOptions[\s]*DWORD:4',
  354. r'Computer[\s]*Software\\Policies\\Microsoft\\Windows\\WindowsUpdate\\AU[\s]*AutomaticMaintenanceEnabled[\s]*DELETE',
  355. r'Computer[\s]*Software\\Policies\\Microsoft\\Windows\\WindowsUpdate\\AU[\s]*ScheduledInstallDay[\s]*DWORD:7',
  356. r'Computer[\s]*Software\\Policies\\Microsoft\\Windows\\WindowsUpdate\\AU[\s]*ScheduledInstallTime[\s]*DWORD:17',
  357. ]
  358. # test as False
  359. self._testAdmxPolicy(r'Windows Components\Windows Update\Configure Automatic Updates',
  360. the_policy,
  361. the_policy_check)
  362. # configure as True for "enable Automatic Updates" test below
  363. the_policy = {
  364. 'Configure automatic updating': '4 - Auto download and schedule the install',
  365. 'Install during automatic maintenance': True,
  366. 'Schedule install day': '7 - Every Saturday',
  367. 'Schedule install time': '17:00',
  368. }
  369. the_policy_check = [
  370. r'Computer[\s]*Software\\Policies\\Microsoft\\Windows\\WindowsUpdate\\AU[\s]*NoAutoUpdate[\s]*DWORD:0',
  371. r'Computer[\s]*Software\\Policies\\Microsoft\\Windows\\WindowsUpdate\\AU[\s]*AUOptions[\s]*DWORD:4',
  372. r'Computer[\s]*Software\\Policies\\Microsoft\\Windows\\WindowsUpdate\\AU[\s]*AutomaticMaintenanceEnabled[\s]*DWORD:1\s*',
  373. r'Computer[\s]*Software\\Policies\\Microsoft\\Windows\\WindowsUpdate\\AU[\s]*ScheduledInstallDay[\s]*DWORD:7',
  374. r'Computer[\s]*Software\\Policies\\Microsoft\\Windows\\WindowsUpdate\\AU[\s]*ScheduledInstallTime[\s]*DWORD:17',
  375. ]
  376. # enable Automatic Updates
  377. self._testAdmxPolicy(r'Windows Components\Windows Update\Configure Automatic Updates',
  378. the_policy,
  379. the_policy_check)
  380. # disable Configure Automatic Updates
  381. self._testAdmxPolicy(r'Windows Components\Windows Update\Configure Automatic Updates',
  382. 'Disabled',
  383. [
  384. r'Computer[\s]*Software\\Policies\\Microsoft\\Windows\\WindowsUpdate\\AU[\s]*NoAutoUpdate[\s]*DWORD:1',
  385. r'Computer[\s]*Software\\Policies\\Microsoft\\Windows\\WindowsUpdate\\AU[\s]*AUOptions[\s]*DELETE',
  386. r'Computer[\s]*Software\\Policies\\Microsoft\\Windows\\WindowsUpdate\\AU[\s]*AutomaticMaintenanceEnabled[\s]*DELETE',
  387. r'Computer[\s]*Software\\Policies\\Microsoft\\Windows\\WindowsUpdate\\AU[\s]*ScheduledInstallDay[\s]*DELETE',
  388. r'Computer[\s]*Software\\Policies\\Microsoft\\Windows\\WindowsUpdate\\AU[\s]*ScheduledInstallTime[\s]*DELETE',
  389. r'Computer[\s]*Software\\Policies\\Microsoft\\Windows\\WindowsUpdate\\AU[\s]*AllowMUUpdateService[\s]*DELETE'
  390. ])
  391. # set Configure Automatic Updates to 'Not Configured'
  392. self._testAdmxPolicy(r'Windows Components\Windows Update\Configure Automatic Updates',
  393. 'Not Configured',
  394. [r'; Source file: c:\\windows\\system32\\grouppolicy\\machine\\registry.pol[\s]*; PARSING COMPLETED.'])
  395. @pytest.mark.destructive_test
  396. def test_set_computer_policy_ClipboardRedirection(self):
  397. '''
  398. Test setting/unsetting/changing ClipboardRedirection policy
  399. '''
  400. # Enable/Disable/Not Configured "Do not allow Clipboard redirection"
  401. self._testAdmxPolicy(r'Windows Components\Remote Desktop Services\Remote Desktop Session Host\Device and Resource Redirection\Do not allow Clipboard redirection',
  402. 'Enabled',
  403. [r'Computer[\s]*Software\\Policies\\Microsoft\\Windows NT\\Terminal Services[\s]*fDisableClip[\s]*DWORD:1'])
  404. self._testAdmxPolicy(r'Windows Components\Remote Desktop Services\Remote Desktop Session Host\Device and Resource Redirection\Do not allow Clipboard redirection',
  405. 'Disabled',
  406. [r'Computer[\s]*Software\\Policies\\Microsoft\\Windows NT\\Terminal Services[\s]*fDisableClip[\s]*DWORD:0'])
  407. self._testAdmxPolicy(r'Windows Components\Remote Desktop Services\Remote Desktop Session Host\Device and Resource Redirection\Do not allow Clipboard redirection',
  408. 'Not Configured',
  409. [r'; Source file: c:\\windows\\system32\\grouppolicy\\machine\\registry.pol[\s]*; PARSING COMPLETED.'])
  410. @pytest.mark.destructive_test
  411. def test_set_computer_policy_PasswordComplexity(self):
  412. '''
  413. Test setting/unsetting/changing PasswordComplexity
  414. '''
  415. # disable PasswordComplexity
  416. self._testSeceditPolicy('Password must meet complexity requirements',
  417. 'Disabled',
  418. [r'^PasswordComplexity = 0'])
  419. # enable PasswordComplexity
  420. self._testSeceditPolicy('PasswordComplexity',
  421. 'Enabled',
  422. [r'^PasswordComplexity = 1'])
  423. @pytest.mark.destructive_test
  424. def test_set_computer_policy_PasswordLen(self):
  425. '''
  426. Test setting/unsetting/changing PasswordLength
  427. '''
  428. # set Minimum password length
  429. self._testSeceditPolicy('Minimum password length',
  430. 10,
  431. [r'^MinimumPasswordLength = 10'])
  432. # set MinimumPasswordLength = 0
  433. self._testSeceditPolicy('MinPasswordLen',
  434. 0,
  435. [r'^MinimumPasswordLength = 0'])
  436. @pytest.mark.destructive_test
  437. def test_set_computer_policy_SeNetworkLogonRight(self):
  438. '''
  439. Test setting/unsetting/changing PasswordLength
  440. '''
  441. # set SeNetworkLogonRight to only Administrators
  442. self._testSeceditPolicy('Access this computer from the network',
  443. ['Administrators'],
  444. [r'^SeNetworkLogonRight = \*S-1-5-32-544'],
  445. cumulative_rights_assignments=False)
  446. # set SeNetworkLogonRight back to the default
  447. self._testSeceditPolicy('SeNetworkLogonRight',
  448. ['Everyone', 'Administrators', 'Users', 'Backup Operators'],
  449. [r'^SeNetworkLogonRight = \*S-1-1-0,\*S-1-5-32-544,\*S-1-5-32-545,\*S-1-5-32-551'])
  450. @pytest.mark.destructive_test
  451. def test_set_computer_policy_multipleAdmxPolicies(self):
  452. '''
  453. Tests setting several ADMX policies in succession and validating the configuration w/lgop
  454. '''
  455. # set one policy
  456. self._testAdmxPolicy(r'Windows Components\Remote Desktop Services\Remote Desktop Session Host\Device and Resource Redirection\Do not allow Clipboard redirection',
  457. 'Disabled',
  458. [r'Computer[\s]*Software\\Policies\\Microsoft\\Windows NT\\Terminal Services[\s]*fDisableClip[\s]*DWORD:0'])
  459. # set another policy and make sure both this policy and the previous are okay
  460. self._testAdmxPolicy('RA_Unsolicit',
  461. {
  462. 'Configure Offer Remote Access': 'Enabled',
  463. 'Permit remote control of this computer': 'Allow helpers to remotely control the computer',
  464. 'Helpers': ['administrators', 'user1']
  465. },
  466. [
  467. r'Computer[\s]*Software\\Policies\\Microsoft\\Windows NT\\Terminal Services[\s]*fDisableClip[\s]*DWORD:0',
  468. r'Computer[\s]*Software\\policies\\Microsoft\\Windows NT\\Terminal Services\\RAUnsolicit[\s]*user1[\s]*SZ:user1[\s]*',
  469. r'Computer[\s]*Software\\policies\\Microsoft\\Windows NT\\Terminal Services\\RAUnsolicit[\s]*administrators[\s]*SZ:administrators[\s]*',
  470. r'Computer[\s]*Software\\policies\\Microsoft\\Windows NT\\Terminal Services[\s]*fAllowUnsolicited[\s]*DWORD:1',
  471. r'Computer[\s]*Software\\policies\\Microsoft\\Windows NT\\Terminal Services[\s]*fAllowUnsolicitedFullControl[\s]*DWORD:1',
  472. ])
  473. # Configure Automatic Updates and validate everything is still okay
  474. self._testAdmxPolicy(r'Windows Components\Windows Update\Configure Automatic Updates',
  475. 'Disabled',
  476. [
  477. r'Computer[\s]*Software\\Policies\\Microsoft\\Windows NT\\Terminal Services[\s]*fDisableClip[\s]*DWORD:0',
  478. r'Computer[\s]*Software\\policies\\Microsoft\\Windows NT\\Terminal Services\\RAUnsolicit[\s]*user1[\s]*SZ:user1[\s]*',
  479. r'Computer[\s]*Software\\policies\\Microsoft\\Windows NT\\Terminal Services\\RAUnsolicit[\s]*administrators[\s]*SZ:administrators[\s]*',
  480. r'Computer[\s]*Software\\policies\\Microsoft\\Windows NT\\Terminal Services[\s]*fAllowUnsolicited[\s]*DWORD:1',
  481. r'Computer[\s]*Software\\policies\\Microsoft\\Windows NT\\Terminal Services[\s]*fAllowUnsolicitedFullControl[\s]*DWORD:1',
  482. r'Computer[\s]*Software\\Policies\\Microsoft\\Windows\\WindowsUpdate\\AU[\s]*NoAutoUpdate[\s]*DWORD:1',
  483. r'Computer[\s]*Software\\Policies\\Microsoft\\Windows\\WindowsUpdate\\AU[\s]*AUOptions[\s]*DELETE',
  484. r'Computer[\s]*Software\\Policies\\Microsoft\\Windows\\WindowsUpdate\\AU[\s]*AutomaticMaintenanceEnabled[\s]*DELETE',
  485. r'Computer[\s]*Software\\Policies\\Microsoft\\Windows\\WindowsUpdate\\AU[\s]*ScheduledInstallDay[\s]*DELETE',
  486. r'Computer[\s]*Software\\Policies\\Microsoft\\Windows\\WindowsUpdate\\AU[\s]*ScheduledInstallTime[\s]*DELETE',
  487. r'Computer[\s]*Software\\Policies\\Microsoft\\Windows\\WindowsUpdate\\AU[\s]*AllowMUUpdateService[\s]*DELETE'
  488. ])
  489. @pytest.mark.destructive_test
  490. def test_set_computer_policy_DisableDomainCreds(self):
  491. '''
  492. Tests Enable/Disable of DisableDomainCreds policy
  493. '''
  494. self._testRegistryPolicy('DisableDomainCreds',
  495. 'Enabled',
  496. 'HKEY_LOCAL_MACHINE',
  497. 'SYSTEM\\CurrentControlSet\\Control\\Lsa',
  498. 'DisableDomainCreds',
  499. 1)
  500. self._testRegistryPolicy(
  501. 'Network access: Do not allow storage of passwords and credentials for network authentication',
  502. 'Disabled',
  503. 'HKEY_LOCAL_MACHINE',
  504. 'SYSTEM\\CurrentControlSet\\Control\\Lsa',
  505. 'DisableDomainCreds',
  506. 0)
  507. @pytest.mark.destructive_test
  508. def test_set_computer_policy_ForceGuest(self):
  509. '''
  510. Tests changing ForceGuest policy
  511. '''
  512. self._testRegistryPolicy('ForceGuest',
  513. 'Guest only - local users authenticate as Guest',
  514. 'HKEY_LOCAL_MACHINE',
  515. 'SYSTEM\\CurrentControlSet\\Control\\Lsa',
  516. 'ForceGuest',
  517. 1)
  518. self._testRegistryPolicy(
  519. 'Network access: Sharing and security model for local accounts',
  520. 'Classic - local users authenticate as themselves',
  521. 'HKEY_LOCAL_MACHINE',
  522. 'SYSTEM\\CurrentControlSet\\Control\\Lsa',
  523. 'ForceGuest',
  524. 0)
  525. @pytest.mark.destructive_test
  526. def test_set_computer_policy_DisableUXWUAccess(self):
  527. '''
  528. Tests changing DisableUXWUAccess
  529. #50079 shows using the 'Remove access to use all Windows Update features' failed
  530. Policy only exists on 2016
  531. '''
  532. valid_osreleases = ['2016Server']
  533. if self.osrelease not in valid_osreleases:
  534. self.skipTest('DisableUXWUAccess policy is only applicable if the osrelease grain is {0}'.format(' or '.join(valid_osreleases)))
  535. else:
  536. self._testAdmxPolicy(r'DisableUXWUAccess',
  537. 'Enabled',
  538. [r'Computer[\s]*Software\\Policies\\Microsoft\\Windows\\WindowsUpdate[\s]*SetDisableUXWUAccess[\s]*DWORD:1'])
  539. self._testAdmxPolicy(r'Remove access to use all Windows Update features',
  540. 'Disabled',
  541. [r'Computer[\s]*Software\\Policies\\Microsoft\\Windows\\WindowsUpdate[\s]*SetDisableUXWUAccess[\s]*DWORD:0'])
  542. self._testAdmxPolicy(r'Windows Components\Windows Update\Remove access to use all Windows Update features',
  543. 'Not Configured',
  544. [r'; Source file: c:\\windows\\system32\\grouppolicy\\machine\\registry.pol[\s]*; PARSING COMPLETED.'])
  545. @pytest.mark.destructive_test
  546. def test_set_computer_policy_Access_data_sources_across_domains(self):
  547. '''
  548. Tests that a policy that has multiple names
  549. '''
  550. self._testAdmxPolicy(r'Access data sources across domains',
  551. 'Enabled',
  552. [],
  553. assert_true=False)
  554. self._testAdmxPolicy(r'Windows Components\Internet Explorer\Internet Control Panel\Security Page\Internet Zone\Access data sources across domains',
  555. {'Access data sources across domains': 'Prompt'},
  556. [r'Computer[\s]*Software\\Policies\\Microsoft\\Windows\\CurrentVersion\\Internet Settings\\Zones\\3[\s]*1406[\s]*DWORD:1'])
  557. self._testAdmxPolicy(r'Windows Components\Internet Explorer\Internet Control Panel\Security Page\Internet Zone\Access data sources across domains',
  558. {'Access data sources across domains': 'Enable'},
  559. [r'Computer[\s]*Software\\Policies\\Microsoft\\Windows\\CurrentVersion\\Internet Settings\\Zones\\3[\s]*1406[\s]*DWORD:0'])
  560. self._testAdmxPolicy(r'Windows Components\Internet Explorer\Internet Control Panel\Security Page\Internet Zone\Access data sources across domains',
  561. 'Disabled',
  562. [r'Computer[\s]*Software\\Policies\\Microsoft\\Windows\\CurrentVersion\\Internet Settings\\Zones\\3[\s]*1406[\s]*DELETE'])
  563. @pytest.mark.destructive_test
  564. def test_set_computer_policy_ActiveHours(self):
  565. '''
  566. Test configuring the ActiveHours policy, #47784
  567. Only applies to 2016Server
  568. # activehours.sls
  569. active_hours_policy:
  570. lgpo.set:
  571. - computer_policy:
  572. 'ActiveHours':
  573. 'ActiveHoursStartTime': '8 AM'
  574. 'ActiveHoursEndTime': '7 PM'
  575. '''
  576. valid_osreleases = ['2016Server']
  577. if self.osrelease not in valid_osreleases:
  578. self.skipTest('ActiveHours policy is only applicable if the osrelease grain is {0}'.format(' or '.join(valid_osreleases)))
  579. else:
  580. self._testAdmxPolicy(r'ActiveHours',
  581. {'ActiveHoursStartTime': '8 AM', 'ActiveHoursEndTime': '7 PM'},
  582. [
  583. r'Computer[\s]*Software\\Policies\\Microsoft\\Windows\\WindowsUpdate[\s]*SetActiveHours[\s]*DWORD:1',
  584. r'Computer[\s]*Software\\Policies\\Microsoft\\Windows\\WindowsUpdate[\s]*ActiveHoursStart[\s]*DWORD:8',
  585. r'Computer[\s]*Software\\Policies\\Microsoft\\Windows\\WindowsUpdate[\s]*ActiveHoursEnd[\s]*DWORD:19'
  586. ])
  587. self._testAdmxPolicy(r'ActiveHours',
  588. {'ActiveHoursStartTime': '5 AM', 'ActiveHoursEndTime': '10 PM'},
  589. [
  590. r'Computer[\s]*Software\\Policies\\Microsoft\\Windows\\WindowsUpdate[\s]*SetActiveHours[\s]*DWORD:1',
  591. r'Computer[\s]*Software\\Policies\\Microsoft\\Windows\\WindowsUpdate[\s]*ActiveHoursStart[\s]*DWORD:5',
  592. r'Computer[\s]*Software\\Policies\\Microsoft\\Windows\\WindowsUpdate[\s]*ActiveHoursEnd[\s]*DWORD:22'
  593. ])
  594. self._testAdmxPolicy('Turn off auto-restart for updates during active hours',
  595. 'Disabled',
  596. [
  597. r'Computer[\s]*Software\\Policies\\Microsoft\\Windows\\WindowsUpdate[\s]*SetActiveHours[\s]*DWORD:0',
  598. r'Computer[\s]*Software\\Policies\\Microsoft\\Windows\\WindowsUpdate[\s]*ActiveHoursStart[\s]*DELETE',
  599. r'Computer[\s]*Software\\Policies\\Microsoft\\Windows\\WindowsUpdate[\s]*ActiveHoursEnd[\s]*DELETE'
  600. ])
  601. self._testAdmxPolicy(r'Windows Components\Windows Update\Turn off auto-restart for updates during active hours',
  602. 'Not Configured',
  603. [r'; Source file: c:\\windows\\system32\\grouppolicy\\machine\\registry.pol[\s]*; PARSING COMPLETED.'])
  604. @pytest.mark.destructive_test
  605. def test_set_computer_policy_AllowTelemetry(self):
  606. '''
  607. Tests that a the AllowTelemetry policy is applied correctly and that it
  608. doesn't appear in subsequent group policy states as having changed
  609. '''
  610. valid_osreleases = ['10', '2016Server', '2019Server']
  611. if self.osrelease not in valid_osreleases:
  612. self.skipTest('Allow Telemetry policy is only applicable if the '
  613. 'osrelease grain is {0}'.format(' or '.join(valid_osreleases)))
  614. else:
  615. self._testAdmxPolicy(
  616. 'Allow Telemetry',
  617. {'AllowTelemetry': '1 - Basic'},
  618. [r'Software\\Policies\\Microsoft\\Windows\\DataCollection[\s]*AllowTelemetry[\s]*DWORD:1'],
  619. assert_true=True)
  620. result = self.run_function(
  621. 'state.single',
  622. ['lgpo.set'],
  623. name='state',
  624. computer_policy={
  625. 'Disable pre-release features or settings': 'Disabled'
  626. }
  627. )
  628. name = 'lgpo_|-state_|-state_|-set'
  629. expected = {
  630. 'new': {
  631. 'Computer Configuration': {
  632. 'Windows Components\\Data Collection and Preview Builds\\Disable pre-release features or settings': 'Disabled'}},
  633. 'old': {'Computer Configuration': {}}}
  634. self.assertDictEqual(result[name]['changes'], expected)
  635. def tearDown(self):
  636. '''
  637. tearDown method, runs after each test
  638. '''
  639. self.run_state(
  640. 'file.absent',
  641. name='c:\\windows\\system32\\grouppolicy\\machine\\registry.pol')
  642. self.run_state(
  643. 'file.absent',
  644. name='c:\\windows\\system32\\grouppolicy\\user\\registry.pol')