Merge branch '2018.3' into 41342_beacon_state_module_fixes

This commit is contained in:
Gareth J. Greenaway 2018-11-02 12:08:19 -07:00 committed by GitHub
commit 8885d1ff3d
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 549 additions and 18 deletions

View file

@ -2605,8 +2605,8 @@ class _policy_info(object):
userSid = '{0}'.format(userSid[0])
# TODO: This needs to be more specific
except Exception:
log.exception('Handle this explicitly')
userSid = win32security.ConvertSidToStringSid(_sid)
log.warning('Unable to convert SID "%s" to a friendly name. The SID will be disaplayed instead of a user/group name.', userSid)
usernames.append(userSid)
return usernames
@ -2925,8 +2925,8 @@ def _findOptionValueInSeceditFile(option):
return True, _line.split('=')[1].strip()
return True, 'Not Defined'
# TODO: This needs to be more specific
except Exception:
log.exception('error occurred while trying to get secedit data')
except Exception as e:
log.exception('error %s occurred while trying to get secedit data', e)
return False, None
@ -3094,9 +3094,9 @@ def _getAdmlPresentationRefId(adml_data, ref_id):
else:
if etree.QName(p_item.tag).localname == 'text':
if prepended_text:
prepended_text = ' '.join([prepended_text, p_item.text.rstrip()])
prepended_text = ' '.join((text for text in (prepended_text, getattr(p_item, 'text', '').rstrip()) if text))
else:
prepended_text = p_item.text.rstrip()
prepended_text = getattr(p_item, 'text', '').rstrip()
else:
prepended_text = ''
if prepended_text.endswith('.'):
@ -3491,7 +3491,7 @@ def _processValueItem(element, reg_key, reg_valuename, policy, parent_element,
encoded_semicolon,
chr(registry.vtype[this_vtype]).encode('utf-32-le'),
encoded_semicolon,
chr(len(' {0}'.format(chr(0)).encode('utf-16-le'))).encode('utf-32-le'),
six.unichr(len(' {0}'.format(chr(0)).encode('utf-16-le'))).encode('utf-32-le'),
encoded_semicolon,
' '.encode('utf-16-le'),
encoded_null,
@ -3552,7 +3552,7 @@ def _processValueItem(element, reg_key, reg_valuename, policy, parent_element,
encoded_semicolon,
chr(registry.vtype[this_vtype]).encode('utf-32-le'),
encoded_semicolon,
chr(len(' {0}'.format(chr(0)))).encode('utf-32-le'),
six.unichr(len(' {0}'.format(chr(0)).encode('utf-16-le'))).encode('utf-32-le'),
encoded_semicolon,
' '.encode('utf-16-le'),
encoded_null,
@ -4179,7 +4179,9 @@ def _regexSearchKeyValueCombo(policy_data, policy_regpath, policy_regkey):
b'\00;'])
match = re.search(_thisSearch, policy_data, re.IGNORECASE)
if match:
return policy_data[match.start():(policy_data.index(']', match.end())) + 1]
# add 2 so we get the ']' and the \00
# to return the full policy entry
return policy_data[match.start():(policy_data.index(b']', match.end())) + 2]
return None
@ -4683,8 +4685,8 @@ def _writeAdminTemplateRegPolFile(admtemplate_data,
policy_data.admx_registry_classes[registry_class]['gpt_extension_location'],
policy_data.admx_registry_classes[registry_class]['gpt_extension_guid'])
# TODO: This needs to be more specific or removed
except Exception:
log.exception('Unhandled exception %s occurred while attempting to write Adm Template Policy File')
except Exception as e:
log.exception('Unhandled exception %s occurred while attempting to write Adm Template Policy File', e)
return False
return True
@ -4832,12 +4834,14 @@ def _lookup_admin_template(policy_name,
suggested_policies = ''
adml_to_remove = []
if len(adml_search_results) > 1:
log.debug('multiple ADML entries found matching the policy name %s', policy_name)
multiple_adml_entries = True
for adml_search_result in adml_search_results:
if not getattr(adml_search_result, 'text', '').strip() == policy_name:
adml_to_remove.append(adml_search_result)
else:
if hierarchy:
log.debug('we have hierarchy of %s', hierarchy)
display_name_searchval = '$({0}.{1})'.format(
adml_search_result.tag.split('}')[1],
adml_search_result.attrib['id'])
@ -4847,8 +4851,11 @@ def _lookup_admin_template(policy_name,
display_name_searchval,
policy_class)
admx_results = []
admx_search_results = admx_policy_definitions.xpath(policy_search_string, namespaces=adml_search_result.nsmap)
for search_result in admx_search_results:
these_admx_search_results = admx_policy_definitions.xpath(policy_search_string, namespaces=adml_search_result.nsmap)
if not these_admx_search_results:
log.debug('No admx was found for the adml entry %s, it will be removed', display_name_searchval)
adml_to_remove.append(adml_search_result)
for search_result in these_admx_search_results:
log.debug('policy_name == %s', policy_name)
this_hierarchy = _build_parent_list(search_result,
admx_policy_definitions,
@ -4856,11 +4863,29 @@ def _lookup_admin_template(policy_name,
adml_policy_resources)
this_hierarchy.reverse()
if hierarchy != this_hierarchy:
adml_to_remove.append(adml_search_result)
msg = 'hierarchy %s does not match this item\'s hierarchy of %s'
log.debug(msg, hierarchy, this_hierarchy)
if len(these_admx_search_results) == 1:
log.debug('only 1 admx was found and it does not match this adml, it is safe to remove from the list')
adml_to_remove.append(adml_search_result)
else:
log.debug('hierarchy %s matches item\'s hierarchy of %s', hierarchy, this_hierarchy)
log.debug('search_result %s added to results', search_result)
admx_results.append(search_result)
if len(admx_results) == 1:
admx_search_results = admx_results
admx_search_results.append(admx_results[0])
else:
# verify the ADMX correlated to this ADML is in the same class
# that we are looking for
display_name_searchval = '$({0}.{1})'.format(
adml_search_result.tag.split('}')[1],
adml_search_result.attrib['id'])
these_admx_search_results = ADMX_DISPLAYNAME_SEARCH_XPATH(
admx_policy_definitions,
display_name=display_name_searchval,
registry_class=policy_class)
if not these_admx_search_results:
adml_to_remove.append(adml_search_result)
for adml in adml_to_remove:
if adml in adml_search_results:
adml_search_results.remove(adml)
@ -4875,12 +4900,15 @@ def _lookup_admin_template(policy_name,
adml_search_result.attrib['id'])
log.debug('searching for displayName == %s', display_name_searchval)
if not admx_search_results:
log.debug('search for an admx entry matching display_name %s and registry_class %s', display_name_searchval, policy_class)
admx_search_results = ADMX_DISPLAYNAME_SEARCH_XPATH(
admx_policy_definitions,
display_name=display_name_searchval,
registry_class=policy_class)
if admx_search_results:
if len(admx_search_results) == 1 or hierarchy and not multiple_adml_entries:
log.debug('processing admx_search_results of {0}'.format(admx_search_results))
log.debug('multiple_adml_entries is {0}'.format(multiple_adml_entries))
if (len(admx_search_results) == 1 or hierarchy) and not multiple_adml_entries:
found = False
for search_result in admx_search_results:
found = False
@ -4936,9 +4964,6 @@ def _lookup_admin_template(policy_name,
'\\'.join(this_parent_list)])
else:
suggested_policies = '\\'.join(this_parent_list)
else:
msg = 'Unable to find a policy with the name "{0}".'.format(policy_name)
return (False, None, [], msg)
if suggested_policies:
msg = ('ADML policy name "{0}" is used as the display name'
' for multiple policies.'

View file

@ -0,0 +1,506 @@
# -*- coding: utf-8 -*-
# Import Python libs
from __future__ import absolute_import, print_function, unicode_literals
import os
import re
import io
import logging
# Import Salt Testing libs
from tests.support.case import ModuleCase
from tests.support.unit import skipIf
from tests.support.helpers import destructiveTest, generate_random_name
from tests.support.runtests import RUNTIME_VARS
# Import Salt libs
import salt.utils.files
import salt.utils.platform
import salt.utils.win_reg as reg
log = logging.getLogger(__name__)
@skipIf(not salt.utils.platform.is_windows(), 'windows test only')
class WinLgpoTest(ModuleCase):
'''
Tests for salt.modules.win_lgpo
'''
osrelease = None
def _testRegistryPolicy(self,
policy_name,
policy_config,
registry_value_hive,
registry_value_path,
registry_value_vname,
expected_value_data):
'''
Takes a registry based policy name and config and validates taht the
expected registry value exists and has the correct data
policy_name
name of the registry based policy to configure
policy_config
the configuration of the policy
registry_value_hive
the registry hive that the policy registry path is in
registry_value_path
the registry value path that the policy updates
registry_value_vname
the registry value name
expected_value_data
the expected data that the value will contain
'''
ret = self.run_function('lgpo.set_computer_policy',
(policy_name, policy_config))
self.assertTrue(ret)
val = reg.read_value(
registry_value_hive,
registry_value_path,
registry_value_vname)
self.assertTrue(val['success'], msg='Failed to obtain the registry data for policy {0}'.format(policy_name))
if val['success']:
self.assertEqual(val['vdata'], expected_value_data, 'The registry value data {0} does not match the expected value {1} for policy {2}'.format(
val['vdata'],
expected_value_data,
policy_name))
def _testSeceditPolicy(self,
policy_name,
policy_config,
expected_regexes,
cumulative_rights_assignments=True):
'''
Takes a secedit policy name and config and validates that the expected
output is returned from secedit
policy_name
name of the secedit policy to configure
policy_config
the configuration of the policy
expected_regexes
the expected regexes to be found in the secedit output file
'''
ret = self.run_function('lgpo.set_computer_policy',
(policy_name, policy_config),
cumulative_rights_assignments=cumulative_rights_assignments)
self.assertTrue(ret)
secedit_output_file = os.path.join(RUNTIME_VARS.TMP, generate_random_name('secedit-output-'))
secedit_output = self.run_function(
'cmd.run',
(),
cmd='secedit /export /cfg {0}'.format(secedit_output_file))
secedit_file_content = None
if secedit_output:
with io.open(secedit_output_file, encoding='utf-16') as _reader:
secedit_file_content = _reader.read()
for expected_regex in expected_regexes:
match = re.search(
expected_regex,
secedit_file_content,
re.IGNORECASE | re.MULTILINE)
self.assertIsNotNone(match, 'Failed validating policy "{0}" configuration, regex "{1}" not found in secedit output'.format(policy_name, expected_regex))
def _testComputerAdmxPolicy(self,
policy_name,
policy_config,
expected_regexes,
assert_true=True):
'''
Takes a ADMX policy name and config and validates that the expected
output is returned from lgpo looking at the Registry.pol file
policy_name
name of the ADMX policy to configure
policy_config
the configuration of the policy
expected_regexes
the expected regexes to be found in the lgpo parse output
assert_true
set to false if expecting the module run to fail
'''
ret = self.run_function('lgpo.set_computer_policy',
(policy_name, policy_config))
log.debug('lgpo set_computer_policy ret == %s', ret)
if assert_true:
self.assertTrue(ret)
lgpo_output = self.run_function(
'cmd.run',
(),
cmd='lgpo.exe /parse /m c:\\Windows\\System32\\GroupPolicy\\Machine\\Registry.pol')
# validate that the lgpo output doesn't say the format is invalid
self.assertIsNone(
re.search(
r'Invalid file format\.',
lgpo_output,
re.IGNORECASE), 'Failed validating Registry.pol file format')
# validate that the regexes we expect are in the output
for expected_regex in expected_regexes:
match = re.search(
expected_regex,
lgpo_output,
re.IGNORECASE)
self.assertIsNotNone(match, 'Failed validating policy "{0}" configuration, regex "{1}" not found in lgpo output'.format(policy_name, expected_regex))
else:
# expecting it to fail
self.assertNotEqual(ret, True)
def runTest(self):
'''
runTest method
'''
pass
@classmethod
def setUpClass(cls):
'''
class setup function, only runs once
downloads and extracts the lgpo.exe tool into c:/windows/system32
for use in validating the registry.pol files
gets osrelease grain for tests that are only applicable to certain
windows versions
'''
osrelease_grains = cls().run_function('grains.item', ['osrelease'])
if 'osrelease' in osrelease_grains:
cls.osrelease = osrelease_grains['osrelease']
else:
log.debug('Unable to get osrelease grain')
if not os.path.exists(r'c:\windows\system32\lgpo.exe'):
log.debug('lgpo.exe does not exist, attempting to download/extract')
ret = cls().run_function('state.single',
('archive.extracted', r'c:\windows\system32'),
source='https://download.microsoft.com/download/8/5/C/85C25433-A1B0-4FFA-9429-7E023E7DA8D8/LGPO.zip',
archive_format='zip',
source_hash='sha256=6ffb6416366652993c992280e29faea3507b5b5aa661c33ba1af31f48acea9c4',
enforce_toplevel=False)
log.debug('ret from archive.unzip == %s', ret)
@destructiveTest
def test_set_computer_policy_NTP_Client(self):
'''
Test setting/unsetting/changing NTP Client policies
'''
# Disable Configure NTP Client
self._testComputerAdmxPolicy(r'System\Windows Time Service\Time Providers\Configure Windows NTP Client',
'Disabled',
[
r'Computer[\s]*Software\\Policies\\Microsoft\\W32time\\Parameters[\s]*NtpServer[\s]*DELETE',
r'Computer[\s]*Software\\Policies\\Microsoft\\W32time\\Parameters[\s]*Type[\s]*DELETE',
r'Computer[\s]*Software\\Policies\\Microsoft\\W32time\\TimeProviders\\NtpClient[\s]*CrossSiteSyncFlags[\s]*DELETE',
r'Computer[\s]*Software\\Policies\\Microsoft\\W32time\\TimeProviders\\NtpClient[\s]*ResolvePeerBackoffMinutes[\s]*DELETE',
r'Computer[\s]*Software\\Policies\\Microsoft\\W32time\\TimeProviders\\NtpClient[\s]*ResolvePeerBackoffMaxTimes[\s]*DELETE',
r'Computer[\s]*Software\\Policies\\Microsoft\\W32time\\TimeProviders\\NtpClient[\s]*SpecialPollInterval[\s]*DELETE',
r'Computer[\s]*Software\\Policies\\Microsoft\\W32time\\TimeProviders\\NtpClient[\s]*EventLogFlags[\s]*DELETE'
])
# Enable Configure NTP Client
self._testComputerAdmxPolicy(r'System\Windows Time Service\Time Providers\Configure Windows NTP Client',
{
'NtpServer': 'time.windows.com,0x9',
'Type': 'NT5DS',
'CrossSiteSyncFlags': 2,
'ResolvePeerBackoffMinutes': 15,
'ResolvePeerBackoffMaxTimes': 7,
'W32TIME_SpecialPollInterval': 3600,
'W32TIME_NtpClientEventLogFlags': 0
},
[
r'Computer[\s]*Software\\Policies\\Microsoft\\W32time\\Parameters[\s]*NtpServer[\s]*SZ:time.windows.com,0x9',
r'Computer[\s]*Software\\Policies\\Microsoft\\W32time\\Parameters[\s]*Type[\s]*SZ:NT5DS',
r'Computer[\s]*Software\\Policies\\Microsoft\\W32time\\TimeProviders\\NtpClient[\s]*CrossSiteSyncFlags[\s]*DWORD:2',
r'Computer[\s]*Software\\Policies\\Microsoft\\W32time\\TimeProviders\\NtpClient[\s]*ResolvePeerBackoffMinutes[\s]*DWORD:15',
r'Computer[\s]*Software\\Policies\\Microsoft\\W32time\\TimeProviders\\NtpClient[\s]*ResolvePeerBackoffMaxTimes[\s]*DWORD:7',
r'Computer[\s]*Software\\Policies\\Microsoft\\W32time\\TimeProviders\\NtpClient[\s]*SpecialPollInterval[\s]*DWORD:3600',
r'Computer[\s]*Software\\Policies\\Microsoft\\W32time\\TimeProviders\\NtpClient[\s]*EventLogFlags[\s]*DWORD:0',
])
# set Configure NTP Client to 'Not Configured'
self._testComputerAdmxPolicy(r'System\Windows Time Service\Time Providers\Configure Windows NTP Client',
'Not Configured',
[r'; Source file: c:\\windows\\system32\\grouppolicy\\machine\\registry.pol[\s]*; PARSING COMPLETED.'])
@destructiveTest
def test_set_computer_policy_RA_Unsolicit(self):
'''
Test setting/unsetting/changing RA_Unsolicit policy
'''
# Disable RA_Unsolicit
log.debug('Attempting to disable RA_Unsolicit')
self._testComputerAdmxPolicy('RA_Unsolicit',
'Disabled',
[
r'Computer[\s]*Software\\policies\\Microsoft\\Windows NT\\Terminal Services[\s]*fAllowUnsolicited[\s]*DWORD:0',
r'Computer[\s]*Software\\policies\\Microsoft\\Windows NT\\Terminal Services[\s]*fAllowUnsolicitedFullControl[\s]*DELETE',
r'Computer[\s]*Software\\policies\\Microsoft\\Windows NT\\Terminal Services\\RAUnsolicit[\s]*\*[\s]*DELETEALLVALUES',
])
# configure RA_Unsolicit
log.debug('Attempting to configure RA_Unsolicit')
self._testComputerAdmxPolicy('RA_Unsolicit',
{
'Configure Offer Remote Access': 'Enabled',
'Permit remote control of this computer': 'Allow helpers to remotely control the computer',
'Helpers': ['administrators', 'user1']
},
[
r'Computer[\s]*Software\\policies\\Microsoft\\Windows NT\\Terminal Services\\RAUnsolicit[\s]*user1[\s]*SZ:user1[\s]*',
r'Computer[\s]*Software\\policies\\Microsoft\\Windows NT\\Terminal Services\\RAUnsolicit[\s]*administrators[\s]*SZ:administrators[\s]*',
r'Computer[\s]*Software\\policies\\Microsoft\\Windows NT\\Terminal Services[\s]*fAllowUnsolicited[\s]*DWORD:1',
r'Computer[\s]*Software\\policies\\Microsoft\\Windows NT\\Terminal Services[\s]*fAllowUnsolicitedFullControl[\s]*DWORD:1',
])
# Not Configure RA_Unsolicit
log.debug('Attempting to set RA_Unsolicit to Not Configured')
self._testComputerAdmxPolicy('RA_Unsolicit',
'Not Configured',
[r'; Source file: c:\\windows\\system32\\grouppolicy\\machine\\registry.pol[\s]*; PARSING COMPLETED.'])
@destructiveTest
def test_set_computer_policy_WindowsUpdate(self):
'''
Test setting/unsetting/changing WindowsUpdate policy
'''
# disable Configure Automatic Updates
self._testComputerAdmxPolicy(r'Windows Components\Windows Update\Configure Automatic Updates',
'Disabled',
[
r'Computer[\s]*Software\\Policies\\Microsoft\\Windows\\WindowsUpdate\\AU[\s]*NoAutoUpdate[\s]*DWORD:1',
r'Computer[\s]*Software\\Policies\\Microsoft\\Windows\\WindowsUpdate\\AU[\s]*AUOptions[\s]*DELETE',
r'Computer[\s]*Software\\Policies\\Microsoft\\Windows\\WindowsUpdate\\AU[\s]*AutomaticMaintenanceEnabled[\s]*DELETE',
r'Computer[\s]*Software\\Policies\\Microsoft\\Windows\\WindowsUpdate\\AU[\s]*ScheduledInstallDay[\s]*DELETE',
r'Computer[\s]*Software\\Policies\\Microsoft\\Windows\\WindowsUpdate\\AU[\s]*ScheduledInstallTime[\s]*DELETE',
r'Computer[\s]*Software\\Policies\\Microsoft\\Windows\\WindowsUpdate\\AU[\s]*AllowMUUpdateService[\s]*DELETE'
])
# set Configure Automatic Updates to 'Not Configured'
self._testComputerAdmxPolicy(r'Windows Components\Windows Update\Configure Automatic Updates',
'Not Configured',
[r'; Source file: c:\\windows\\system32\\grouppolicy\\machine\\registry.pol[\s]*; PARSING COMPLETED.'])
@destructiveTest
def test_set_computer_policy_ClipboardRedirection(self):
'''
Test setting/unsetting/changing ClipboardRedirection policy
'''
# Enable/Disable/Not Configured "Do not allow Clipboard redirection"
self._testComputerAdmxPolicy(r'Windows Components\Remote Desktop Services\Remote Desktop Session Host\Device and Resource Redirection\Do not allow Clipboard redirection',
'Enabled',
[r'Computer[\s]*Software\\Policies\\Microsoft\\Windows NT\\Terminal Services[\s]*fDisableClip[\s]*DWORD:1'])
self._testComputerAdmxPolicy(r'Windows Components\Remote Desktop Services\Remote Desktop Session Host\Device and Resource Redirection\Do not allow Clipboard redirection',
'Disabled',
[r'Computer[\s]*Software\\Policies\\Microsoft\\Windows NT\\Terminal Services[\s]*fDisableClip[\s]*DWORD:0'])
self._testComputerAdmxPolicy(r'Windows Components\Remote Desktop Services\Remote Desktop Session Host\Device and Resource Redirection\Do not allow Clipboard redirection',
'Not Configured',
[r'; Source file: c:\\windows\\system32\\grouppolicy\\machine\\registry.pol[\s]*; PARSING COMPLETED.'])
@destructiveTest
def test_set_computer_policy_PasswordComplexity(self):
'''
Test setting/unsetting/changing PasswordComplexity
'''
# disable PasswordComplexity
self._testSeceditPolicy('Password must meet complexity requirements',
'Disabled',
[r'^PasswordComplexity = 0'])
# enable PasswordComplexity
self._testSeceditPolicy('PasswordComplexity',
'Enabled',
[r'^PasswordComplexity = 1'])
@destructiveTest
def test_set_computer_policy_PasswordLen(self):
'''
Test setting/unsetting/changing PasswordLength
'''
# set Minimum password length
self._testSeceditPolicy('Minimum password length',
10,
[r'^MinimumPasswordLength = 10'])
# set MinimumPasswordLength = 0
self._testSeceditPolicy('MinPasswordLen',
0,
[r'^MinimumPasswordLength = 0'])
@destructiveTest
def test_set_computer_policy_SeNetworkLogonRight(self):
'''
Test setting/unsetting/changing PasswordLength
'''
# set SeNetworkLogonRight to only Administrators
self._testSeceditPolicy('Access this computer from the network',
['Administrators'],
[r'^SeNetworkLogonRight = \*S-1-5-32-544'],
cumulative_rights_assignments=False)
# set SeNetworkLogonRight back to the default
self._testSeceditPolicy('SeNetworkLogonRight',
['Everyone', 'Administrators', 'Users', 'Backup Operators'],
[r'^SeNetworkLogonRight = \*S-1-1-0,\*S-1-5-32-544,\*S-1-5-32-545,\*S-1-5-32-551'])
@destructiveTest
def test_set_computer_policy_multipleAdmxPolicies(self):
'''
Tests setting several ADMX policies in succession and validating the configuration w/lgop
'''
# set one policy
self._testComputerAdmxPolicy(r'Windows Components\Remote Desktop Services\Remote Desktop Session Host\Device and Resource Redirection\Do not allow Clipboard redirection',
'Disabled',
[r'Computer[\s]*Software\\Policies\\Microsoft\\Windows NT\\Terminal Services[\s]*fDisableClip[\s]*DWORD:0'])
# set another policy and make sure both this policy and the previous are okay
self._testComputerAdmxPolicy('RA_Unsolicit',
{
'Configure Offer Remote Access': 'Enabled',
'Permit remote control of this computer': 'Allow helpers to remotely control the computer',
'Helpers': ['administrators', 'user1']
},
[
r'Computer[\s]*Software\\Policies\\Microsoft\\Windows NT\\Terminal Services[\s]*fDisableClip[\s]*DWORD:0',
r'Computer[\s]*Software\\policies\\Microsoft\\Windows NT\\Terminal Services\\RAUnsolicit[\s]*user1[\s]*SZ:user1[\s]*',
r'Computer[\s]*Software\\policies\\Microsoft\\Windows NT\\Terminal Services\\RAUnsolicit[\s]*administrators[\s]*SZ:administrators[\s]*',
r'Computer[\s]*Software\\policies\\Microsoft\\Windows NT\\Terminal Services[\s]*fAllowUnsolicited[\s]*DWORD:1',
r'Computer[\s]*Software\\policies\\Microsoft\\Windows NT\\Terminal Services[\s]*fAllowUnsolicitedFullControl[\s]*DWORD:1',
])
# Configure Automatic Updates and validate everything is still okay
self._testComputerAdmxPolicy(r'Windows Components\Windows Update\Configure Automatic Updates',
'Disabled',
[
r'Computer[\s]*Software\\Policies\\Microsoft\\Windows NT\\Terminal Services[\s]*fDisableClip[\s]*DWORD:0',
r'Computer[\s]*Software\\policies\\Microsoft\\Windows NT\\Terminal Services\\RAUnsolicit[\s]*user1[\s]*SZ:user1[\s]*',
r'Computer[\s]*Software\\policies\\Microsoft\\Windows NT\\Terminal Services\\RAUnsolicit[\s]*administrators[\s]*SZ:administrators[\s]*',
r'Computer[\s]*Software\\policies\\Microsoft\\Windows NT\\Terminal Services[\s]*fAllowUnsolicited[\s]*DWORD:1',
r'Computer[\s]*Software\\policies\\Microsoft\\Windows NT\\Terminal Services[\s]*fAllowUnsolicitedFullControl[\s]*DWORD:1',
r'Computer[\s]*Software\\Policies\\Microsoft\\Windows\\WindowsUpdate\\AU[\s]*NoAutoUpdate[\s]*DWORD:1',
r'Computer[\s]*Software\\Policies\\Microsoft\\Windows\\WindowsUpdate\\AU[\s]*AUOptions[\s]*DELETE',
r'Computer[\s]*Software\\Policies\\Microsoft\\Windows\\WindowsUpdate\\AU[\s]*AutomaticMaintenanceEnabled[\s]*DELETE',
r'Computer[\s]*Software\\Policies\\Microsoft\\Windows\\WindowsUpdate\\AU[\s]*ScheduledInstallDay[\s]*DELETE',
r'Computer[\s]*Software\\Policies\\Microsoft\\Windows\\WindowsUpdate\\AU[\s]*ScheduledInstallTime[\s]*DELETE',
r'Computer[\s]*Software\\Policies\\Microsoft\\Windows\\WindowsUpdate\\AU[\s]*AllowMUUpdateService[\s]*DELETE'
])
@destructiveTest
def test_set_computer_policy_DisableDomainCreds(self):
'''
Tests Enable/Disable of DisableDomainCreds policy
'''
self._testRegistryPolicy('DisableDomainCreds',
'Enabled',
'HKEY_LOCAL_MACHINE',
'SYSTEM\\CurrentControlSet\\Control\\Lsa',
'DisableDomainCreds',
1)
self._testRegistryPolicy(
'Network access: Do not allow storage of passwords and credentials for network authentication',
'Disabled',
'HKEY_LOCAL_MACHINE',
'SYSTEM\\CurrentControlSet\\Control\\Lsa',
'DisableDomainCreds',
0)
@destructiveTest
def test_set_computer_policy_ForceGuest(self):
'''
Tests changing ForceGuest policy
'''
self._testRegistryPolicy('ForceGuest',
'Guest only - local users authenticate as Guest',
'HKEY_LOCAL_MACHINE',
'SYSTEM\\CurrentControlSet\\Control\\Lsa',
'ForceGuest',
1)
self._testRegistryPolicy(
'Network access: Sharing and security model for local accounts',
'Classic - local users authenticate as themselves',
'HKEY_LOCAL_MACHINE',
'SYSTEM\\CurrentControlSet\\Control\\Lsa',
'ForceGuest',
0)
@destructiveTest
def test_set_computer_policy_DisableUXWUAccess(self):
'''
Tests changing DisableUXWUAccess
#50079 shows using the 'Remove access to use all Windows Update features' failed
Policy only exists on 2016
'''
valid_osreleases = ['2016Server']
if self.osrelease not in valid_osreleases:
self.skipTest('DisableUXWUAccess policy is only applicable if the osrelease grain is {0}'.format(' or '.join(valid_osreleases)))
else:
self._testComputerAdmxPolicy(r'DisableUXWUAccess',
'Enabled',
[r'Computer[\s]*Software\\Policies\\Microsoft\\Windows\\WindowsUpdate[\s]*SetDisableUXWUAccess[\s]*DWORD:1'])
self._testComputerAdmxPolicy(r'Remove access to use all Windows Update features',
'Disabled',
[r'Computer[\s]*Software\\Policies\\Microsoft\\Windows\\WindowsUpdate[\s]*SetDisableUXWUAccess[\s]*DWORD:0'])
self._testComputerAdmxPolicy(r'Windows Components\Windows Update\Remove access to use all Windows Update features',
'Not Configured',
[r'; Source file: c:\\windows\\system32\\grouppolicy\\machine\\registry.pol[\s]*; PARSING COMPLETED.'])
@destructiveTest
def test_set_computer_policy_Access_data_sources_across_domains(self):
'''
Tests that a policy that has multiple names
'''
self._testComputerAdmxPolicy(r'Access data sources across domains',
'Enabled',
[],
assert_true=False)
self._testComputerAdmxPolicy(r'Windows Components\Internet Explorer\Internet Control Panel\Security Page\Internet Zone\Access data sources across domains',
{'Access data sources across domains': 'Prompt'},
[r'Computer[\s]*Software\\Policies\\Microsoft\\Windows\\CurrentVersion\\Internet Settings\\Zones\\3[\s]*1406[\s]*DWORD:1'])
self._testComputerAdmxPolicy(r'Windows Components\Internet Explorer\Internet Control Panel\Security Page\Internet Zone\Access data sources across domains',
{'Access data sources across domains': 'Enable'},
[r'Computer[\s]*Software\\Policies\\Microsoft\\Windows\\CurrentVersion\\Internet Settings\\Zones\\3[\s]*1406[\s]*DWORD:0'])
self._testComputerAdmxPolicy(r'Windows Components\Internet Explorer\Internet Control Panel\Security Page\Internet Zone\Access data sources across domains',
'Disabled',
[r'Computer[\s]*Software\\Policies\\Microsoft\\Windows\\CurrentVersion\\Internet Settings\\Zones\\3[\s]*1406[\s]*DELETE'])
@destructiveTest
def test_set_computer_policy_ActiveHours(self):
'''
Test configuring the ActiveHours policy, #47784
Only applies to 2016Server
# activehours.sls
active_hours_policy:
lgpo.set:
- computer_policy:
'ActiveHours':
'ActiveHoursStartTime': '8 AM'
'ActiveHoursEndTime': '7 PM'
'''
valid_osreleases = ['2016Server']
if self.osrelease not in valid_osreleases:
self.skipTest('ActiveHours policy is only applicable if the osrelease grain is {0}'.format(' or '.join(valid_osreleases)))
else:
self._testComputerAdmxPolicy(r'ActiveHours',
{'ActiveHoursStartTime': '8 AM', 'ActiveHoursEndTime': '7 PM'},
[
r'Computer[\s]*Software\\Policies\\Microsoft\\Windows\\WindowsUpdate[\s]*SetActiveHours[\s]*DWORD:1',
r'Computer[\s]*Software\\Policies\\Microsoft\\Windows\\WindowsUpdate[\s]*ActiveHoursStart[\s]*DWORD:8',
r'Computer[\s]*Software\\Policies\\Microsoft\\Windows\\WindowsUpdate[\s]*ActiveHoursEnd[\s]*DWORD:19'
])
self._testComputerAdmxPolicy(r'ActiveHours',
{'ActiveHoursStartTime': '5 AM', 'ActiveHoursEndTime': '10 PM'},
[
r'Computer[\s]*Software\\Policies\\Microsoft\\Windows\\WindowsUpdate[\s]*SetActiveHours[\s]*DWORD:1',
r'Computer[\s]*Software\\Policies\\Microsoft\\Windows\\WindowsUpdate[\s]*ActiveHoursStart[\s]*DWORD:5',
r'Computer[\s]*Software\\Policies\\Microsoft\\Windows\\WindowsUpdate[\s]*ActiveHoursEnd[\s]*DWORD:22'
])
self._testComputerAdmxPolicy('Turn off auto-restart for updates during active hours',
'Disabled',
[
r'Computer[\s]*Software\\Policies\\Microsoft\\Windows\\WindowsUpdate[\s]*SetActiveHours[\s]*DWORD:0',
r'Computer[\s]*Software\\Policies\\Microsoft\\Windows\\WindowsUpdate[\s]*ActiveHoursStart[\s]*DELETE',
r'Computer[\s]*Software\\Policies\\Microsoft\\Windows\\WindowsUpdate[\s]*ActiveHoursEnd[\s]*DELETE'
])
self._testComputerAdmxPolicy(r'Windows Components\Windows Update\Turn off auto-restart for updates during active hours',
'Not Configured',
[r'; Source file: c:\\windows\\system32\\grouppolicy\\machine\\registry.pol[\s]*; PARSING COMPLETED.'])
def tearDown(self):
'''
tearDown method, runs after each test
'''
ret = self.run_function('state.single',
('file.absent', 'c:\\windows\\system32\\grouppolicy\\machine\\registry.pol'))
ret = self.run_function('state.single',
('file.absent', 'c:\\windows\\system32\\grouppolicy\\user\\registry.pol'))