test_win_lgpo.py 43 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946
  1. # -*- coding: utf-8 -*-
  2. from __future__ import absolute_import, print_function, unicode_literals
  3. import io
  4. import logging
  5. import os
  6. import re
  7. import salt.utils.files
  8. import salt.utils.platform
  9. import salt.utils.win_reg as reg
  10. from tests.support.case import ModuleCase
  11. from tests.support.helpers import destructiveTest, random_string
  12. from tests.support.runtests import RUNTIME_VARS
  13. from tests.support.unit import skipIf
  14. log = logging.getLogger(__name__)
  15. @skipIf(not salt.utils.platform.is_windows(), "windows test only")
  16. class WinLgpoTest(ModuleCase):
  17. """
  18. Tests for salt.modules.win_lgpo
  19. """
  20. osrelease = None
  21. def _testRegistryPolicy(
  22. self,
  23. policy_name,
  24. policy_config,
  25. registry_value_hive,
  26. registry_value_path,
  27. registry_value_vname,
  28. expected_value_data,
  29. ):
  30. """
  31. Takes a registry based policy name and config and validates that the
  32. expected registry value exists and has the correct data
  33. policy_name
  34. name of the registry based policy to configure
  35. policy_config
  36. the configuration of the policy
  37. registry_value_hive
  38. the registry hive that the policy registry path is in
  39. registry_value_path
  40. the registry value path that the policy updates
  41. registry_value_vname
  42. the registry value name
  43. expected_value_data
  44. the expected data that the value will contain
  45. """
  46. ret = self.run_function(
  47. "lgpo.set_computer_policy", (policy_name, policy_config)
  48. )
  49. self.assertTrue(ret)
  50. val = reg.read_value(
  51. hive=registry_value_hive,
  52. key=registry_value_path,
  53. vname=registry_value_vname,
  54. )
  55. self.assertTrue(
  56. val["success"],
  57. msg="Failed to obtain the registry data for policy {0}".format(policy_name),
  58. )
  59. if val["success"]:
  60. self.assertEqual(
  61. val["vdata"],
  62. expected_value_data,
  63. "The registry value data {0} does not match the expected value {1} for policy {2}".format(
  64. val["vdata"], expected_value_data, policy_name
  65. ),
  66. )
  67. def _testSeceditPolicy(
  68. self,
  69. policy_name,
  70. policy_config,
  71. expected_regexes,
  72. cumulative_rights_assignments=True,
  73. ):
  74. """
  75. Takes a secedit policy name and config and validates that the expected
  76. output is returned from secedit
  77. policy_name
  78. name of the secedit policy to configure
  79. policy_config
  80. the configuration of the policy
  81. expected_regexes
  82. the expected regexes to be found in the secedit output file
  83. """
  84. ret = self.run_function(
  85. "lgpo.set_computer_policy",
  86. (policy_name, policy_config),
  87. cumulative_rights_assignments=cumulative_rights_assignments,
  88. )
  89. self.assertTrue(ret)
  90. secedit_output_file = os.path.join(
  91. RUNTIME_VARS.TMP, random_string("secedit-output-")
  92. )
  93. secedit_output = self.run_function(
  94. "cmd.run", (), cmd="secedit /export /cfg {0}".format(secedit_output_file)
  95. )
  96. secedit_file_content = None
  97. if secedit_output:
  98. with io.open(secedit_output_file, encoding="utf-16") as _reader:
  99. secedit_file_content = _reader.read()
  100. for expected_regex in expected_regexes:
  101. match = re.search(
  102. expected_regex, secedit_file_content, re.IGNORECASE | re.MULTILINE
  103. )
  104. self.assertIsNotNone(
  105. match,
  106. 'Failed validating policy "{0}" configuration, regex "{1}" not found in secedit output'.format(
  107. policy_name, expected_regex
  108. ),
  109. )
  110. def _testAdmxPolicy(
  111. self,
  112. policy_name,
  113. policy_config,
  114. expected_regexes,
  115. assert_true=True,
  116. policy_class="Machine",
  117. ):
  118. """
  119. Takes a ADMX policy name and config and validates that the expected
  120. output is returned from lgpo looking at the Registry.pol file
  121. policy_name
  122. name of the ADMX policy to configure
  123. policy_config
  124. the configuration of the policy
  125. expected_regexes
  126. the expected regexes to be found in the lgpo parse output
  127. assert_true
  128. set to false if expecting the module run to fail
  129. policy_class
  130. the policy class this policy belongs to, either Machine or User
  131. """
  132. lgpo_function = "set_computer_policy"
  133. lgpo_class = "/m"
  134. lgpo_folder = "Machine"
  135. if policy_class.lower() == "user":
  136. lgpo_function = "set_user_policy"
  137. lgpo_class = "/u"
  138. lgpo_folder = "User"
  139. ret = self.run_function(
  140. "lgpo.{0}".format(lgpo_function), (policy_name, policy_config)
  141. )
  142. log.debug("lgpo set_computer_policy ret == %s", ret)
  143. cmd = [
  144. "lgpo.exe",
  145. "/parse",
  146. lgpo_class,
  147. r"c:\Windows\System32\GroupPolicy\{}\Registry.pol".format(lgpo_folder),
  148. ]
  149. if assert_true:
  150. self.assertTrue(ret)
  151. lgpo_output = self.run_function("cmd.run", (), cmd=" ".join(cmd))
  152. # validate that the lgpo output doesn't say the format is invalid
  153. self.assertIsNone(
  154. re.search(r"Invalid file format\.", lgpo_output, re.IGNORECASE),
  155. msg="Failed validating Registry.pol file format",
  156. )
  157. # validate that the regexes we expect are in the output
  158. for expected_regex in expected_regexes:
  159. match = re.search(expected_regex, lgpo_output, re.IGNORECASE)
  160. self.assertIsNotNone(
  161. match,
  162. msg='Failed validating policy "{0}" configuration, regex '
  163. '"{1}" not found in lgpo output:\n{2}'
  164. "".format(policy_name, expected_regex, lgpo_output),
  165. )
  166. else:
  167. # expecting it to fail
  168. self.assertNotEqual(ret, True)
  169. def runTest(self):
  170. """
  171. runTest method
  172. """
  173. @classmethod
  174. def setUpClass(cls):
  175. """
  176. class setup function, only runs once
  177. downloads and extracts the lgpo.exe tool into c:/windows/system32
  178. for use in validating the registry.pol files
  179. gets osrelease grain for tests that are only applicable to certain
  180. windows versions
  181. """
  182. osrelease_grains = cls().run_function("grains.item", ["osrelease"])
  183. if "osrelease" in osrelease_grains:
  184. cls.osrelease = osrelease_grains["osrelease"]
  185. else:
  186. log.debug("Unable to get osrelease grain")
  187. if not os.path.exists(r"c:\windows\system32\lgpo.exe"):
  188. log.debug("lgpo.exe does not exist, attempting to download/extract")
  189. ret = cls().run_function(
  190. "state.single",
  191. ("archive.extracted", r"c:\windows\system32"),
  192. source="https://download.microsoft.com/download/8/5/C/85C25433-A1B0-4FFA-9429-7E023E7DA8D8/LGPO.zip",
  193. archive_format="zip",
  194. source_hash="sha256=6ffb6416366652993c992280e29faea3507b5b5aa661c33ba1af31f48acea9c4",
  195. enforce_toplevel=False,
  196. )
  197. log.debug("ret from archive.unzip == %s", ret)
  198. @destructiveTest
  199. def test_set_user_policy_point_and_print_restrictions(self):
  200. """
  201. Test setting/unsetting/changing the PointAndPrint_Restrictions user policy
  202. """
  203. # Disable Point and Print Restrictions
  204. self._testAdmxPolicy(
  205. r"Control Panel\Printers\Point and Print Restrictions",
  206. "Disabled",
  207. [
  208. r"User[\s]*Software\\Policies\\Microsoft\\Windows NT\\Printers\\PointAndPrint[\s]*Restricted[\s]*DWORD:0",
  209. r"User[\s]*Software\\Policies\\Microsoft\\Windows NT\\Printers\\PointAndPrint[\s]*TrustedServers[\s]*DELETE",
  210. r"User[\s]*Software\\Policies\\Microsoft\\Windows NT\\Printers\\PointAndPrint[\s]*ServerList[\s]*DELETE",
  211. r"User[\s]*Software\\Policies\\Microsoft\\Windows NT\\Printers\\PointAndPrint[\s]*InForest[\s]*DELETE",
  212. r"User[\s]*Software\\Policies\\Microsoft\\Windows NT\\Printers\\PointAndPrint[\s]*NoWarningNoElevationOnInstall[\s]*DELETE",
  213. r"User[\s]*Software\\Policies\\Microsoft\\Windows NT\\Printers\\PointAndPrint[\s]*UpdatePromptSettings[\s]*DELETE",
  214. ],
  215. policy_class="User",
  216. )
  217. # Enable Point and Print Restrictions
  218. self._testAdmxPolicy(
  219. r"Point and Print Restrictions",
  220. {
  221. "Users can only point and print to these servers": True,
  222. "Enter fully qualified server names separated by semicolons": "fakeserver1;fakeserver2",
  223. "Users can only point and print to machines in their forest": True,
  224. "When installing drivers for a new connection": "Show warning and elevation prompt",
  225. "When updating drivers for an existing connection": "Show warning only",
  226. },
  227. [
  228. r"User[\s]*Software\\Policies\\Microsoft\\Windows NT\\Printers\\PointAndPrint[\s]*Restricted[\s]*DWORD:1",
  229. r"User[\s]*Software\\Policies\\Microsoft\\Windows NT\\Printers\\PointAndPrint[\s]*TrustedServers[\s]*DWORD:1",
  230. r"User[\s]*Software\\Policies\\Microsoft\\Windows NT\\Printers\\PointAndPrint[\s]*ServerList[\s]*SZ:fakeserver1;fakeserver2",
  231. r"User[\s]*Software\\Policies\\Microsoft\\Windows NT\\Printers\\PointAndPrint[\s]*InForest[\s]*DWORD:1",
  232. r"User[\s]*Software\\Policies\\Microsoft\\Windows NT\\Printers\\PointAndPrint[\s]*NoWarningNoElevationOnInstall[\s]*DWORD:0",
  233. r"User[\s]*Software\\Policies\\Microsoft\\Windows NT\\Printers\\PointAndPrint[\s]*UpdatePromptSettings[\s]*DWORD:1",
  234. ],
  235. policy_class="User",
  236. )
  237. # set Point and Print Restrictions to 'Not Configured'
  238. self._testAdmxPolicy(
  239. r"Control Panel\Printers\Point and Print Restrictions",
  240. "Not Configured",
  241. [
  242. r"; Source file: c:\\windows\\system32\\grouppolicy\\user\\registry.pol[\s]*; PARSING COMPLETED."
  243. ],
  244. policy_class="User",
  245. )
  246. @destructiveTest
  247. def test_set_computer_policy_NTP_Client(self):
  248. """
  249. Test setting/unsetting/changing NTP Client policies
  250. """
  251. # Disable Configure NTP Client
  252. self._testAdmxPolicy(
  253. r"System\Windows Time Service\Time Providers\Configure Windows NTP Client",
  254. "Disabled",
  255. [
  256. r"Computer[\s]*Software\\Policies\\Microsoft\\W32time\\Parameters[\s]*NtpServer[\s]*DELETE",
  257. r"Computer[\s]*Software\\Policies\\Microsoft\\W32time\\Parameters[\s]*Type[\s]*DELETE",
  258. r"Computer[\s]*Software\\Policies\\Microsoft\\W32time\\TimeProviders\\NtpClient[\s]*CrossSiteSyncFlags[\s]*DELETE",
  259. r"Computer[\s]*Software\\Policies\\Microsoft\\W32time\\TimeProviders\\NtpClient[\s]*ResolvePeerBackoffMinutes[\s]*DELETE",
  260. r"Computer[\s]*Software\\Policies\\Microsoft\\W32time\\TimeProviders\\NtpClient[\s]*ResolvePeerBackoffMaxTimes[\s]*DELETE",
  261. r"Computer[\s]*Software\\Policies\\Microsoft\\W32time\\TimeProviders\\NtpClient[\s]*SpecialPollInterval[\s]*DELETE",
  262. r"Computer[\s]*Software\\Policies\\Microsoft\\W32time\\TimeProviders\\NtpClient[\s]*EventLogFlags[\s]*DELETE",
  263. ],
  264. )
  265. # Enable Configure NTP Client
  266. self._testAdmxPolicy(
  267. r"System\Windows Time Service\Time Providers\Configure Windows NTP Client",
  268. {
  269. "NtpServer": "time.windows.com,0x9",
  270. "Type": "NT5DS",
  271. "CrossSiteSyncFlags": 2,
  272. "ResolvePeerBackoffMinutes": 15,
  273. "ResolvePeerBackoffMaxTimes": 7,
  274. "W32TIME_SpecialPollInterval": 3600,
  275. "W32TIME_NtpClientEventLogFlags": 0,
  276. },
  277. [
  278. r"Computer[\s]*Software\\Policies\\Microsoft\\W32time\\Parameters[\s]*NtpServer[\s]*SZ:time.windows.com,0x9",
  279. r"Computer[\s]*Software\\Policies\\Microsoft\\W32time\\Parameters[\s]*Type[\s]*SZ:NT5DS",
  280. r"Computer[\s]*Software\\Policies\\Microsoft\\W32time\\TimeProviders\\NtpClient[\s]*CrossSiteSyncFlags[\s]*DWORD:2",
  281. r"Computer[\s]*Software\\Policies\\Microsoft\\W32time\\TimeProviders\\NtpClient[\s]*ResolvePeerBackoffMinutes[\s]*DWORD:15",
  282. r"Computer[\s]*Software\\Policies\\Microsoft\\W32time\\TimeProviders\\NtpClient[\s]*ResolvePeerBackoffMaxTimes[\s]*DWORD:7",
  283. r"Computer[\s]*Software\\Policies\\Microsoft\\W32time\\TimeProviders\\NtpClient[\s]*SpecialPollInterval[\s]*DWORD:3600",
  284. r"Computer[\s]*Software\\Policies\\Microsoft\\W32time\\TimeProviders\\NtpClient[\s]*EventLogFlags[\s]*DWORD:0",
  285. ],
  286. )
  287. # set Configure NTP Client to 'Not Configured'
  288. self._testAdmxPolicy(
  289. r"System\Windows Time Service\Time Providers\Configure Windows NTP Client",
  290. "Not Configured",
  291. [
  292. r"; Source file: c:\\windows\\system32\\grouppolicy\\machine\\registry.pol[\s]*; PARSING COMPLETED."
  293. ],
  294. )
  295. @destructiveTest
  296. def test_set_computer_policy_RA_Unsolicit(self):
  297. """
  298. Test setting/unsetting/changing RA_Unsolicit policy
  299. """
  300. # Disable RA_Unsolicit
  301. log.debug("Attempting to disable RA_Unsolicit")
  302. self._testAdmxPolicy(
  303. "RA_Unsolicit",
  304. "Disabled",
  305. [
  306. r"Computer[\s]*Software\\policies\\Microsoft\\Windows NT\\Terminal Services[\s]*fAllowUnsolicited[\s]*DWORD:0",
  307. r"Computer[\s]*Software\\policies\\Microsoft\\Windows NT\\Terminal Services[\s]*fAllowUnsolicitedFullControl[\s]*DELETE",
  308. r"Computer[\s]*Software\\policies\\Microsoft\\Windows NT\\Terminal Services\\RAUnsolicit[\s]*\*[\s]*DELETEALLVALUES",
  309. ],
  310. )
  311. # configure RA_Unsolicit
  312. log.debug("Attempting to configure RA_Unsolicit")
  313. self._testAdmxPolicy(
  314. "RA_Unsolicit",
  315. {
  316. "Configure Offer Remote Access": "Enabled",
  317. "Permit remote control of this computer": "Allow helpers to remotely control the computer",
  318. "Helpers": ["administrators", "user1"],
  319. },
  320. [
  321. r"Computer[\s]*Software\\policies\\Microsoft\\Windows NT\\Terminal Services\\RAUnsolicit[\s]*user1[\s]*SZ:user1[\s]*",
  322. r"Computer[\s]*Software\\policies\\Microsoft\\Windows NT\\Terminal Services\\RAUnsolicit[\s]*administrators[\s]*SZ:administrators[\s]*",
  323. r"Computer[\s]*Software\\policies\\Microsoft\\Windows NT\\Terminal Services[\s]*fAllowUnsolicited[\s]*DWORD:1",
  324. r"Computer[\s]*Software\\policies\\Microsoft\\Windows NT\\Terminal Services[\s]*fAllowUnsolicitedFullControl[\s]*DWORD:1",
  325. ],
  326. )
  327. # Not Configure RA_Unsolicit
  328. log.debug("Attempting to set RA_Unsolicit to Not Configured")
  329. self._testAdmxPolicy(
  330. "RA_Unsolicit",
  331. "Not Configured",
  332. [
  333. r"; Source file: c:\\windows\\system32\\grouppolicy\\machine\\registry.pol[\s]*; PARSING COMPLETED."
  334. ],
  335. )
  336. @destructiveTest
  337. def test_set_computer_policy_Pol_HardenedPaths(self):
  338. # Disable Pol_HardenedPaths
  339. log.debug("Attempting to disable Pol_HardenedPaths")
  340. self._testAdmxPolicy(
  341. "Pol_HardenedPaths",
  342. "Disabled",
  343. [
  344. r"Computer[\s]*Software\\policies\\Microsoft\\Windows\\NetworkProvider\\HardenedPaths[\s]*\*[\s]*DELETEALLVALUES"
  345. ],
  346. )
  347. # Configure Pol_HardenedPaths
  348. log.debug("Attempting to configure Pol_HardenedPaths")
  349. self._testAdmxPolicy(
  350. "Pol_HardenedPaths",
  351. {
  352. "Hardened UNC Paths": {
  353. r"\\*\NETLOGON": "RequireMutualAuthentication=1, RequireIntegrity=1",
  354. r"\\*\SYSVOL": "RequireMutualAuthentication=1, RequireIntegrity=1",
  355. }
  356. },
  357. [
  358. r"Computer[\s]*Software\\policies\\Microsoft\\Windows\\NetworkProvider\\HardenedPaths[\s]*\\\\\*\\NETLOGON[\s]*SZ:RequireMutualAuthentication=1, RequireIntegrity=1[\s]*",
  359. r"Computer[\s]*Software\\policies\\Microsoft\\Windows\\NetworkProvider\\HardenedPaths[\s]*\\\\\*\\SYSVOL[\s]*SZ:RequireMutualAuthentication=1, RequireIntegrity=1[\s]*",
  360. ],
  361. )
  362. # Not Configure Pol_HardenedPaths
  363. log.debug("Attempting to set Pol_HardenedPaths to Not Configured")
  364. self._testAdmxPolicy(
  365. "Pol_HardenedPaths",
  366. "Not Configured",
  367. [
  368. r"; Source file: c:\\windows\\system32\\grouppolicy\\machine\\registry.pol[\s]*; PARSING COMPLETED."
  369. ],
  370. )
  371. @destructiveTest
  372. def test_set_computer_policy_WindowsUpdate(self):
  373. """
  374. Test setting/unsetting/changing WindowsUpdate policy
  375. """
  376. # Configure Automatic Updates has different options in different builds
  377. # and releases of Windows, so we'll get the elements and add them if
  378. # they are present. Newer elements will need to be added manually as
  379. # they are released by Microsoft
  380. result = self.run_function(
  381. "lgpo.get_policy_info",
  382. ["Configure Automatic Updates"],
  383. policy_class="machine",
  384. )
  385. the_policy = {}
  386. the_policy_check_enabled = [
  387. r"Computer[\s]*Software\\Policies\\Microsoft\\Windows\\WindowsUpdate\\AU[\s]*NoAutoUpdate[\s]*DWORD:0",
  388. ]
  389. the_policy_check_disabled = [
  390. r"Computer[\s]*Software\\Policies\\Microsoft\\Windows\\WindowsUpdate\\AU[\s]*NoAutoUpdate[\s]*DWORD:1",
  391. ]
  392. for item in result["policy_elements"]:
  393. if "Configure automatic updating" in item["element_aliases"]:
  394. the_policy.update(
  395. {
  396. "Configure automatic updating": "4 - Auto download and schedule the install",
  397. }
  398. )
  399. the_policy_check_enabled.append(
  400. r"Computer[\s]*Software\\Policies\\Microsoft\\Windows\\WindowsUpdate\\AU[\s]*AUOptions[\s]*DWORD:4",
  401. )
  402. the_policy_check_disabled.append(
  403. r"Computer[\s]*Software\\Policies\\Microsoft\\Windows\\WindowsUpdate\\AU[\s]*AUOptions[\s]*DELETE",
  404. )
  405. elif "Install during automatic maintenance" in item["element_aliases"]:
  406. the_policy.update({"Install during automatic maintenance": True})
  407. the_policy_check_enabled.append(
  408. r"Computer[\s]*Software\\Policies\\Microsoft\\Windows\\WindowsUpdate\\AU[\s]*AutomaticMaintenanceEnabled[\s]*DWORD:1\s*",
  409. )
  410. the_policy_check_disabled.append(
  411. r"Computer[\s]*Software\\Policies\\Microsoft\\Windows\\WindowsUpdate\\AU[\s]*AutomaticMaintenanceEnabled[\s]*DELETE",
  412. )
  413. elif "Scheduled install day" in item["element_aliases"]:
  414. the_policy.update({"Scheduled install day": "7 - Every Saturday"})
  415. the_policy_check_enabled.append(
  416. r"Computer[\s]*Software\\Policies\\Microsoft\\Windows\\WindowsUpdate\\AU[\s]*ScheduledInstallDay[\s]*DWORD:7",
  417. )
  418. the_policy_check_disabled.append(
  419. r"Computer[\s]*Software\\Policies\\Microsoft\\Windows\\WindowsUpdate\\AU[\s]*ScheduledInstallDay[\s]*DELETE",
  420. )
  421. elif "Scheduled install time" in item["element_aliases"]:
  422. the_policy.update({"Scheduled install time": "17:00"})
  423. the_policy_check_enabled.append(
  424. r"Computer[\s]*Software\\Policies\\Microsoft\\Windows\\WindowsUpdate\\AU[\s]*ScheduledInstallTime[\s]*DWORD:17",
  425. )
  426. the_policy_check_disabled.append(
  427. r"Computer[\s]*Software\\Policies\\Microsoft\\Windows\\WindowsUpdate\\AU[\s]*ScheduledInstallTime[\s]*DELETE",
  428. )
  429. elif (
  430. "Install updates for other Microsoft products"
  431. in item["element_aliases"]
  432. ):
  433. the_policy.update(
  434. {"Install updates for other Microsoft products": True}
  435. )
  436. the_policy_check_enabled.append(
  437. r"Computer[\s]*Software\\Policies\\Microsoft\\Windows\\WindowsUpdate\\AU[\s]*AllowMUUpdateService[\s]*DWORD:1\s*"
  438. )
  439. the_policy_check_disabled.append(
  440. r"Computer[\s]*Software\\Policies\\Microsoft\\Windows\\WindowsUpdate\\AU[\s]*AllowMUUpdateService[\s]*DELETE"
  441. )
  442. elif "AutoUpdateSchEveryWeek" in item["element_aliases"]:
  443. the_policy.update({"AutoUpdateSchEveryWeek": True})
  444. the_policy_check_enabled.append(
  445. r"Computer[\s]*Software\\Policies\\Microsoft\\Windows\\WindowsUpdate\\AU[\s]*ScheduledInstallEveryWeek[\s]*DWORD:1\s*"
  446. )
  447. the_policy_check_disabled.append(
  448. r"Computer[\s]*Software\\Policies\\Microsoft\\Windows\\WindowsUpdate\\AU[\s]*ScheduledInstallEveryWeek[\s]*DELETE"
  449. )
  450. elif "First week of the month" in item["element_aliases"]:
  451. the_policy.update({"First week of the month": True})
  452. the_policy_check_enabled.append(
  453. r"Computer[\s]*Software\\Policies\\Microsoft\\Windows\\WindowsUpdate\\AU[\s]*ScheduledInstallFirstWeek[\s]*DWORD:1\s*"
  454. )
  455. the_policy_check_disabled.append(
  456. r"Computer[\s]*Software\\Policies\\Microsoft\\Windows\\WindowsUpdate\\AU[\s]*ScheduledInstallFirstWeek[\s]*DELETE"
  457. )
  458. elif "Second week of the month" in item["element_aliases"]:
  459. the_policy.update({"Second week of the month": True})
  460. the_policy_check_enabled.append(
  461. r"Computer[\s]*Software\\Policies\\Microsoft\\Windows\\WindowsUpdate\\AU[\s]*ScheduledInstallSecondWeek[\s]*DWORD:1\s*"
  462. )
  463. the_policy_check_disabled.append(
  464. r"Computer[\s]*Software\\Policies\\Microsoft\\Windows\\WindowsUpdate\\AU[\s]*ScheduledInstallSecondWeek[\s]*DELETE"
  465. )
  466. elif "Third week of the month" in item["element_aliases"]:
  467. the_policy.update({"Third week of the month": True})
  468. the_policy_check_enabled.append(
  469. r"Computer[\s]*Software\\Policies\\Microsoft\\Windows\\WindowsUpdate\\AU[\s]*ScheduledInstallThirdWeek[\s]*DWORD:1\s*"
  470. )
  471. the_policy_check_disabled.append(
  472. r"Computer[\s]*Software\\Policies\\Microsoft\\Windows\\WindowsUpdate\\AU[\s]*ScheduledInstallThirdWeek[\s]*DELETE"
  473. )
  474. elif "Fourth week of the month" in item["element_aliases"]:
  475. the_policy.update({"Fourth week of the month": True})
  476. the_policy_check_enabled.append(
  477. r"Computer[\s]*Software\\Policies\\Microsoft\\Windows\\WindowsUpdate\\AU[\s]*ScheduledInstallFourthWeek[\s]*DWORD:1\s*"
  478. )
  479. the_policy_check_disabled.append(
  480. r"Computer[\s]*Software\\Policies\\Microsoft\\Windows\\WindowsUpdate\\AU[\s]*ScheduledInstallFourthWeek[\s]*DELETE"
  481. )
  482. # enable Automatic Updates
  483. self._testAdmxPolicy(
  484. r"Windows Components\Windows Update\Configure Automatic Updates",
  485. the_policy,
  486. the_policy_check_enabled,
  487. )
  488. # disable Configure Automatic Updates
  489. self._testAdmxPolicy(
  490. r"Windows Components\Windows Update\Configure Automatic Updates",
  491. "Disabled",
  492. the_policy_check_disabled,
  493. )
  494. # set Configure Automatic Updates to 'Not Configured'
  495. self._testAdmxPolicy(
  496. r"Windows Components\Windows Update\Configure Automatic Updates",
  497. "Not Configured",
  498. [
  499. r"; Source file: c:\\windows\\system32\\grouppolicy\\machine\\registry.pol[\s]*; PARSING COMPLETED."
  500. ],
  501. )
  502. @destructiveTest
  503. def test_set_computer_policy_ClipboardRedirection(self):
  504. """
  505. Test setting/unsetting/changing ClipboardRedirection policy
  506. """
  507. # Enable/Disable/Not Configured "Do not allow Clipboard redirection"
  508. self._testAdmxPolicy(
  509. r"Windows Components\Remote Desktop Services\Remote Desktop Session Host\Device and Resource Redirection\Do not allow Clipboard redirection",
  510. "Enabled",
  511. [
  512. r"Computer[\s]*Software\\Policies\\Microsoft\\Windows NT\\Terminal Services[\s]*fDisableClip[\s]*DWORD:1"
  513. ],
  514. )
  515. self._testAdmxPolicy(
  516. r"Windows Components\Remote Desktop Services\Remote Desktop Session Host\Device and Resource Redirection\Do not allow Clipboard redirection",
  517. "Disabled",
  518. [
  519. r"Computer[\s]*Software\\Policies\\Microsoft\\Windows NT\\Terminal Services[\s]*fDisableClip[\s]*DWORD:0"
  520. ],
  521. )
  522. self._testAdmxPolicy(
  523. r"Windows Components\Remote Desktop Services\Remote Desktop Session Host\Device and Resource Redirection\Do not allow Clipboard redirection",
  524. "Not Configured",
  525. [
  526. r"; Source file: c:\\windows\\system32\\grouppolicy\\machine\\registry.pol[\s]*; PARSING COMPLETED."
  527. ],
  528. )
  529. @destructiveTest
  530. def test_set_computer_policy_LockoutDuration(self):
  531. """
  532. Test setting LockoutDuration
  533. """
  534. # For LockoutDuration to be meaningful, first configure
  535. # LockoutThreshold
  536. self._testSeceditPolicy("LockoutThreshold", 3, [r"^LockoutBadCount = 3"])
  537. # Next set the LockoutDuration non-zero value, as this is required
  538. # before setting LockoutWindow
  539. self._testSeceditPolicy("LockoutDuration", 60, [r"^LockoutDuration = 60"])
  540. # Now set LockoutWindow to a valid value <= LockoutDuration. If this
  541. # is not set, then the LockoutDuration zero value is ignored by the
  542. # Windows API (leading to a false sense of accomplishment)
  543. self._testSeceditPolicy("LockoutWindow", 60, [r"^ResetLockoutCount = 60"])
  544. # set LockoutDuration zero value, the secedit zero value is -1
  545. self._testSeceditPolicy("LockoutDuration", 0, [r"^LockoutDuration = -1"])
  546. @destructiveTest
  547. def test_set_computer_policy_GuestAccountStatus(self):
  548. """
  549. Test setting/unsetting/changing GuestAccountStatus
  550. """
  551. # disable GuestAccountStatus
  552. self._testSeceditPolicy(
  553. "GuestAccountStatus", "Disabled", [r"^EnableGuestAccount = 0"]
  554. )
  555. # enable GuestAccountStatus
  556. self._testSeceditPolicy(
  557. "GuestAccountStatus", "Enabled", [r"^EnableGuestAccount = 1"]
  558. )
  559. @destructiveTest
  560. def test_set_computer_policy_PasswordComplexity(self):
  561. """
  562. Test setting/unsetting/changing PasswordComplexity
  563. """
  564. # disable PasswordComplexity
  565. self._testSeceditPolicy(
  566. "Password must meet complexity requirements",
  567. "Disabled",
  568. [r"^PasswordComplexity = 0"],
  569. )
  570. # enable PasswordComplexity
  571. self._testSeceditPolicy(
  572. "PasswordComplexity", "Enabled", [r"^PasswordComplexity = 1"]
  573. )
  574. @destructiveTest
  575. def test_set_computer_policy_PasswordLen(self):
  576. """
  577. Test setting/unsetting/changing PasswordLength
  578. """
  579. # set Minimum password length
  580. self._testSeceditPolicy(
  581. "Minimum password length", 10, [r"^MinimumPasswordLength = 10"]
  582. )
  583. # set MinimumPasswordLength = 0
  584. self._testSeceditPolicy("MinPasswordLen", 0, [r"^MinimumPasswordLength = 0"])
  585. @destructiveTest
  586. def test_set_computer_policy_SeNetworkLogonRight(self):
  587. """
  588. Test setting/unsetting/changing PasswordLength
  589. """
  590. # set SeNetworkLogonRight to only Administrators
  591. self._testSeceditPolicy(
  592. "Access this computer from the network",
  593. ["Administrators"],
  594. [r"^SeNetworkLogonRight = \*S-1-5-32-544"],
  595. cumulative_rights_assignments=False,
  596. )
  597. # set SeNetworkLogonRight back to the default
  598. self._testSeceditPolicy(
  599. "SeNetworkLogonRight",
  600. ["Everyone", "Administrators", "Users", "Backup Operators"],
  601. [
  602. r"^SeNetworkLogonRight = \*S-1-1-0,\*S-1-5-32-544,\*S-1-5-32-545,\*S-1-5-32-551"
  603. ],
  604. )
  605. @destructiveTest
  606. def test_set_computer_policy_multipleAdmxPolicies(self):
  607. """
  608. Tests setting several ADMX policies in succession and validating the configuration w/lgop
  609. """
  610. # set one policy
  611. self._testAdmxPolicy(
  612. r"Windows Components\Remote Desktop Services\Remote Desktop Session Host\Device and Resource Redirection\Do not allow Clipboard redirection",
  613. "Disabled",
  614. [
  615. r"Computer[\s]*Software\\Policies\\Microsoft\\Windows NT\\Terminal Services[\s]*fDisableClip[\s]*DWORD:0"
  616. ],
  617. )
  618. # set another policy and make sure both this policy and the previous are okay
  619. self._testAdmxPolicy(
  620. "RA_Unsolicit",
  621. {
  622. "Configure Offer Remote Access": "Enabled",
  623. "Permit remote control of this computer": "Allow helpers to remotely control the computer",
  624. "Helpers": ["administrators", "user1"],
  625. },
  626. [
  627. r"Computer[\s]*Software\\Policies\\Microsoft\\Windows NT\\Terminal Services[\s]*fDisableClip[\s]*DWORD:0",
  628. r"Computer[\s]*Software\\policies\\Microsoft\\Windows NT\\Terminal Services\\RAUnsolicit[\s]*user1[\s]*SZ:user1[\s]*",
  629. r"Computer[\s]*Software\\policies\\Microsoft\\Windows NT\\Terminal Services\\RAUnsolicit[\s]*administrators[\s]*SZ:administrators[\s]*",
  630. r"Computer[\s]*Software\\policies\\Microsoft\\Windows NT\\Terminal Services[\s]*fAllowUnsolicited[\s]*DWORD:1",
  631. r"Computer[\s]*Software\\policies\\Microsoft\\Windows NT\\Terminal Services[\s]*fAllowUnsolicitedFullControl[\s]*DWORD:1",
  632. ],
  633. )
  634. # Configure Automatic Updates and validate everything is still okay
  635. self._testAdmxPolicy(
  636. r"Windows Components\Windows Update\Configure Automatic Updates",
  637. "Disabled",
  638. [
  639. r"Computer[\s]*Software\\Policies\\Microsoft\\Windows NT\\Terminal Services[\s]*fDisableClip[\s]*DWORD:0",
  640. r"Computer[\s]*Software\\policies\\Microsoft\\Windows NT\\Terminal Services\\RAUnsolicit[\s]*user1[\s]*SZ:user1[\s]*",
  641. r"Computer[\s]*Software\\policies\\Microsoft\\Windows NT\\Terminal Services\\RAUnsolicit[\s]*administrators[\s]*SZ:administrators[\s]*",
  642. r"Computer[\s]*Software\\policies\\Microsoft\\Windows NT\\Terminal Services[\s]*fAllowUnsolicited[\s]*DWORD:1",
  643. r"Computer[\s]*Software\\policies\\Microsoft\\Windows NT\\Terminal Services[\s]*fAllowUnsolicitedFullControl[\s]*DWORD:1",
  644. r"Computer[\s]*Software\\Policies\\Microsoft\\Windows\\WindowsUpdate\\AU[\s]*NoAutoUpdate[\s]*DWORD:1",
  645. r"Computer[\s]*Software\\Policies\\Microsoft\\Windows\\WindowsUpdate\\AU[\s]*AUOptions[\s]*DELETE",
  646. r"Computer[\s]*Software\\Policies\\Microsoft\\Windows\\WindowsUpdate\\AU[\s]*AutomaticMaintenanceEnabled[\s]*DELETE",
  647. r"Computer[\s]*Software\\Policies\\Microsoft\\Windows\\WindowsUpdate\\AU[\s]*ScheduledInstallDay[\s]*DELETE",
  648. r"Computer[\s]*Software\\Policies\\Microsoft\\Windows\\WindowsUpdate\\AU[\s]*ScheduledInstallTime[\s]*DELETE",
  649. r"Computer[\s]*Software\\Policies\\Microsoft\\Windows\\WindowsUpdate\\AU[\s]*AllowMUUpdateService[\s]*DELETE",
  650. ],
  651. )
  652. @destructiveTest
  653. def test_set_computer_policy_DisableDomainCreds(self):
  654. """
  655. Tests Enable/Disable of DisableDomainCreds policy
  656. """
  657. self._testRegistryPolicy(
  658. policy_name="DisableDomainCreds",
  659. policy_config="Enabled",
  660. registry_value_hive="HKEY_LOCAL_MACHINE",
  661. registry_value_path="SYSTEM\\CurrentControlSet\\Control\\Lsa",
  662. registry_value_vname="DisableDomainCreds",
  663. expected_value_data=1,
  664. )
  665. self._testRegistryPolicy(
  666. policy_name="Network access: Do not allow storage of passwords and credentials for network authentication",
  667. policy_config="Disabled",
  668. registry_value_hive="HKEY_LOCAL_MACHINE",
  669. registry_value_path="SYSTEM\\CurrentControlSet\\Control\\Lsa",
  670. registry_value_vname="DisableDomainCreds",
  671. expected_value_data=0,
  672. )
  673. @destructiveTest
  674. def test_set_computer_policy_ForceGuest(self):
  675. """
  676. Tests changing ForceGuest policy
  677. """
  678. self._testRegistryPolicy(
  679. policy_name="ForceGuest",
  680. policy_config="Guest only - local users authenticate as Guest",
  681. registry_value_hive="HKEY_LOCAL_MACHINE",
  682. registry_value_path="SYSTEM\\CurrentControlSet\\Control\\Lsa",
  683. registry_value_vname="ForceGuest",
  684. expected_value_data=1,
  685. )
  686. self._testRegistryPolicy(
  687. policy_name="Network access: Sharing and security model for local accounts",
  688. policy_config="Classic - local users authenticate as themselves",
  689. registry_value_hive="HKEY_LOCAL_MACHINE",
  690. registry_value_path="SYSTEM\\CurrentControlSet\\Control\\Lsa",
  691. registry_value_vname="ForceGuest",
  692. expected_value_data=0,
  693. )
  694. @destructiveTest
  695. def test_set_computer_policy_DisableUXWUAccess(self):
  696. """
  697. Tests changing DisableUXWUAccess
  698. #50079 shows using the 'Remove access to use all Windows Update features' failed
  699. Policy only exists on 2016
  700. """
  701. valid_osreleases = ["2016Server"]
  702. if self.osrelease not in valid_osreleases:
  703. self.skipTest(
  704. "DisableUXWUAccess policy is only applicable if the osrelease grain is {0}".format(
  705. " or ".join(valid_osreleases)
  706. )
  707. )
  708. else:
  709. self._testAdmxPolicy(
  710. r"DisableUXWUAccess",
  711. "Enabled",
  712. [
  713. r"Computer[\s]*Software\\Policies\\Microsoft\\Windows\\WindowsUpdate[\s]*SetDisableUXWUAccess[\s]*DWORD:1"
  714. ],
  715. )
  716. self._testAdmxPolicy(
  717. r"Remove access to use all Windows Update features",
  718. "Disabled",
  719. [
  720. r"Computer[\s]*Software\\Policies\\Microsoft\\Windows\\WindowsUpdate[\s]*SetDisableUXWUAccess[\s]*DWORD:0"
  721. ],
  722. )
  723. self._testAdmxPolicy(
  724. r"Windows Components\Windows Update\Remove access to use all Windows Update features",
  725. "Not Configured",
  726. [
  727. r"; Source file: c:\\windows\\system32\\grouppolicy\\machine\\registry.pol[\s]*; PARSING COMPLETED."
  728. ],
  729. )
  730. @destructiveTest
  731. def test_set_computer_policy_Access_data_sources_across_domains(self):
  732. """
  733. Tests that a policy that has multiple names
  734. """
  735. self._testAdmxPolicy(
  736. r"Access data sources across domains", "Enabled", [], assert_true=False
  737. )
  738. self._testAdmxPolicy(
  739. r"Windows Components\Internet Explorer\Internet Control Panel\Security Page\Internet Zone\Access data sources across domains",
  740. {"Access data sources across domains": "Prompt"},
  741. [
  742. r"Computer[\s]*Software\\Policies\\Microsoft\\Windows\\CurrentVersion\\Internet Settings\\Zones\\3[\s]*1406[\s]*DWORD:1"
  743. ],
  744. )
  745. self._testAdmxPolicy(
  746. r"Windows Components\Internet Explorer\Internet Control Panel\Security Page\Internet Zone\Access data sources across domains",
  747. {"Access data sources across domains": "Enable"},
  748. [
  749. r"Computer[\s]*Software\\Policies\\Microsoft\\Windows\\CurrentVersion\\Internet Settings\\Zones\\3[\s]*1406[\s]*DWORD:0"
  750. ],
  751. )
  752. self._testAdmxPolicy(
  753. r"Windows Components\Internet Explorer\Internet Control Panel\Security Page\Internet Zone\Access data sources across domains",
  754. "Disabled",
  755. [
  756. r"Computer[\s]*Software\\Policies\\Microsoft\\Windows\\CurrentVersion\\Internet Settings\\Zones\\3[\s]*1406[\s]*DELETE"
  757. ],
  758. )
  759. @destructiveTest
  760. def test_set_computer_policy_ActiveHours(self):
  761. """
  762. Test configuring the ActiveHours policy, #47784
  763. Only applies to 2016Server
  764. # activehours.sls
  765. active_hours_policy:
  766. lgpo.set:
  767. - computer_policy:
  768. 'ActiveHours':
  769. 'ActiveHoursStartTime': '8 AM'
  770. 'ActiveHoursEndTime': '7 PM'
  771. """
  772. valid_osreleases = ["2016Server"]
  773. if self.osrelease not in valid_osreleases:
  774. self.skipTest(
  775. "ActiveHours policy is only applicable if the osrelease grain is {0}".format(
  776. " or ".join(valid_osreleases)
  777. )
  778. )
  779. else:
  780. self._testAdmxPolicy(
  781. r"ActiveHours",
  782. {"ActiveHoursStartTime": "8 AM", "ActiveHoursEndTime": "7 PM"},
  783. [
  784. r"Computer[\s]*Software\\Policies\\Microsoft\\Windows\\WindowsUpdate[\s]*SetActiveHours[\s]*DWORD:1",
  785. r"Computer[\s]*Software\\Policies\\Microsoft\\Windows\\WindowsUpdate[\s]*ActiveHoursStart[\s]*DWORD:8",
  786. r"Computer[\s]*Software\\Policies\\Microsoft\\Windows\\WindowsUpdate[\s]*ActiveHoursEnd[\s]*DWORD:19",
  787. ],
  788. )
  789. self._testAdmxPolicy(
  790. r"ActiveHours",
  791. {"ActiveHoursStartTime": "5 AM", "ActiveHoursEndTime": "10 PM"},
  792. [
  793. r"Computer[\s]*Software\\Policies\\Microsoft\\Windows\\WindowsUpdate[\s]*SetActiveHours[\s]*DWORD:1",
  794. r"Computer[\s]*Software\\Policies\\Microsoft\\Windows\\WindowsUpdate[\s]*ActiveHoursStart[\s]*DWORD:5",
  795. r"Computer[\s]*Software\\Policies\\Microsoft\\Windows\\WindowsUpdate[\s]*ActiveHoursEnd[\s]*DWORD:22",
  796. ],
  797. )
  798. self._testAdmxPolicy(
  799. "Turn off auto-restart for updates during active hours",
  800. "Disabled",
  801. [
  802. r"Computer[\s]*Software\\Policies\\Microsoft\\Windows\\WindowsUpdate[\s]*SetActiveHours[\s]*DWORD:0",
  803. r"Computer[\s]*Software\\Policies\\Microsoft\\Windows\\WindowsUpdate[\s]*ActiveHoursStart[\s]*DELETE",
  804. r"Computer[\s]*Software\\Policies\\Microsoft\\Windows\\WindowsUpdate[\s]*ActiveHoursEnd[\s]*DELETE",
  805. ],
  806. )
  807. self._testAdmxPolicy(
  808. r"Windows Components\Windows Update\Turn off auto-restart for updates during active hours",
  809. "Not Configured",
  810. [
  811. r"; Source file: c:\\windows\\system32\\grouppolicy\\machine\\registry.pol[\s]*; PARSING COMPLETED."
  812. ],
  813. )
  814. @destructiveTest
  815. def test_set_computer_policy_AllowTelemetry(self):
  816. """
  817. Tests that a the AllowTelemetry policy is applied correctly and that it
  818. doesn't appear in subsequent group policy states as having changed
  819. """
  820. valid_osreleases = ["10", "2016Server", "2019Server"]
  821. if self.osrelease not in valid_osreleases:
  822. self.skipTest(
  823. "Allow Telemetry policy is only applicable if the "
  824. "osrelease grain is {0}".format(" or ".join(valid_osreleases))
  825. )
  826. else:
  827. self._testAdmxPolicy(
  828. "Allow Telemetry",
  829. {"AllowTelemetry": "1 - Basic"},
  830. [
  831. r"Software\\Policies\\Microsoft\\Windows\\DataCollection[\s]*AllowTelemetry[\s]*DWORD:1"
  832. ],
  833. assert_true=True,
  834. )
  835. # This policy does not exist on newer Windows builds
  836. result = self.run_function(
  837. "lgpo.get_policy_info",
  838. ["Disable pre-release features or settings"],
  839. policy_class="machine",
  840. )
  841. if result["policy_found"]:
  842. result = self.run_function(
  843. "state.single",
  844. ["lgpo.set"],
  845. name="state",
  846. computer_policy={
  847. "Disable pre-release features or settings": "Disabled"
  848. },
  849. )
  850. name = "lgpo_|-state_|-state_|-set"
  851. expected = {
  852. "new": {
  853. "Computer Configuration": {
  854. "Disable pre-release features or settings": "Disabled"
  855. }
  856. },
  857. "old": {
  858. "Computer Configuration": {
  859. "Disable pre-release features or settings": "Not Configured"
  860. }
  861. },
  862. }
  863. self.assertDictEqual(result[name]["changes"], expected)
  864. else:
  865. result = self.run_function(
  866. "lgpo.get_policy_info",
  867. ["Manage preview builds"],
  868. policy_class="machine",
  869. )
  870. if result["policy_found"]:
  871. result = self.run_function(
  872. "state.single",
  873. ["lgpo.set"],
  874. name="state",
  875. computer_policy={"Manage preview builds": "Disabled"},
  876. )
  877. name = "lgpo_|-state_|-state_|-set"
  878. expected = {
  879. "new": {
  880. "Computer Configuration": {
  881. "Manage preview builds": "Disabled"
  882. }
  883. },
  884. "old": {
  885. "Computer Configuration": {
  886. "Manage preview builds": "Not Configured"
  887. }
  888. },
  889. }
  890. self.assertDictEqual(result[name]["changes"], expected)
  891. def tearDown(self):
  892. """
  893. tearDown method, runs after each test
  894. """
  895. self.run_state(
  896. "file.absent",
  897. name="c:\\windows\\system32\\grouppolicy\\machine\\registry.pol",
  898. )
  899. self.run_state(
  900. "file.absent", name="c:\\windows\\system32\\grouppolicy\\user\\registry.pol"
  901. )