mirror of
https://github.com/saltstack/salt.git
synced 2025-04-17 10:10:20 +00:00
Merge pull request #53900 from twangboy/fix_lgpo
Fix inconsistent full names in LGPO
This commit is contained in:
commit
c0e49d9125
2 changed files with 91 additions and 13 deletions
|
@ -47,6 +47,7 @@ import re
|
|||
import locale
|
||||
import ctypes
|
||||
import tempfile
|
||||
import time
|
||||
import uuid
|
||||
|
||||
# Import Salt libs
|
||||
|
@ -70,6 +71,7 @@ __func_alias__ = {'set_': 'set'}
|
|||
|
||||
UUID = uuid.uuid4().hex
|
||||
adm_policy_name_map = {True: {}, False: {}}
|
||||
adm_policy_key_map = {}
|
||||
HAS_WINDOWS_MODULES = False
|
||||
# define some global XPATH variables that we'll set assuming all our imports are
|
||||
# good
|
||||
|
@ -84,6 +86,7 @@ VALUE_XPATH = None
|
|||
TRUE_LIST_XPATH = None
|
||||
FALSE_LIST_XPATH = None
|
||||
REGKEY_XPATH = None
|
||||
REGKEY_XPATH_MAPPED = None
|
||||
POLICY_ANCESTOR_XPATH = None
|
||||
ALL_CLASS_POLICY_XPATH = None
|
||||
ADML_DISPLAY_NAME_XPATH = None
|
||||
|
@ -114,6 +117,7 @@ try:
|
|||
TRUE_LIST_XPATH = etree.XPath('.//*[local-name() = "trueList"]')
|
||||
FALSE_LIST_XPATH = etree.XPath('.//*[local-name() = "falseList"]')
|
||||
REGKEY_XPATH = etree.XPath('//*[translate(@*[local-name() = "key"], "ABCDEFGHIJKLMNOPQRSTUVWXYZ", "abcdefghijklmnopqrstuvwxyz") = $keyvalue]')
|
||||
REGKEY_XPATH_MAPPED = etree.XPath('//*[@key = $keyvalue]')
|
||||
POLICY_ANCESTOR_XPATH = etree.XPath('ancestor::*[local-name() = "policy"]')
|
||||
ALL_CLASS_POLICY_XPATH = etree.XPath('//*[local-name() = "policy" and (@*[local-name() = "class"] = "Both" or @*[local-name() = "class"] = $registry_class)]')
|
||||
ADML_DISPLAY_NAME_XPATH = etree.XPath('//*[local-name() = $displayNameType and @*[local-name() = "id"] = $displayNameId]')
|
||||
|
@ -4861,6 +4865,7 @@ def _load_policy_definitions(path='c:\\Windows\\PolicyDefinitions',
|
|||
temp_pol = _updateNamespace(temp_pol, this_namespace)
|
||||
if 'key' in temp_pol.attrib:
|
||||
temp_pol = _updatePolicyElements(temp_pol, temp_pol.attrib['key'])
|
||||
adm_policy_key_map[temp_pol.attrib['key'].lower()] = temp_pol.attrib['key']
|
||||
policydefs_policies_xpath(t_policy_definitions)[0].append(temp_pol)
|
||||
policy_namespaces = xmltree.xpath(
|
||||
'/{0}policyDefinitions/{0}policyNamespaces/{0}*'.format(namespace_string),
|
||||
|
@ -5547,9 +5552,9 @@ def _getFullPolicyName(policy_item,
|
|||
'''
|
||||
helper function to retrieve the full policy name if needed
|
||||
'''
|
||||
adml_data = _get_policy_resources(language=adml_language)
|
||||
if policy_name in adm_policy_name_map[return_full_policy_names]:
|
||||
return adm_policy_name_map[return_full_policy_names][policy_name]
|
||||
adml_data = _get_policy_resources(language=adml_language)
|
||||
if return_full_policy_names and 'displayName' in policy_item.attrib:
|
||||
fullPolicyName = _getAdmlDisplayName(adml_data, policy_item.attrib['displayName'])
|
||||
if fullPolicyName:
|
||||
|
@ -6084,21 +6089,41 @@ def _checkAllAdmxPolicies(policy_class,
|
|||
re.sub(re.escape(module_policy_data.reg_pol_header.encode('utf-16-le')),
|
||||
b'',
|
||||
policy_file_data))).split(']['.encode('utf-16-le'))
|
||||
log.debug('Parsing %s policies...', len(policy_filedata_split))
|
||||
start_time = time.time()
|
||||
# Get the policy for each item defined in Registry.pol
|
||||
for policy_item in policy_filedata_split:
|
||||
policy_item_key = policy_item.split('{0};'.format(chr(0)).encode('utf-16-le'))[0].decode('utf-16-le').lower()
|
||||
if policy_item_key:
|
||||
for admx_item in REGKEY_XPATH(admx_policy_definitions, keyvalue=policy_item_key):
|
||||
# Find the policy definitions with this key
|
||||
if policy_item_key in adm_policy_key_map:
|
||||
# Use the faster method if possible
|
||||
admx_items = REGKEY_XPATH_MAPPED(admx_policy_definitions,
|
||||
keyvalue=adm_policy_key_map[policy_item_key])
|
||||
log.debug('Found %s policies using the mapped method',
|
||||
len(admx_items))
|
||||
else:
|
||||
# Fall back to this when the faster method is not feasible
|
||||
admx_items = REGKEY_XPATH(admx_policy_definitions,
|
||||
keyvalue=policy_item_key)
|
||||
log.warning('%s not mapped', policy_item_key)
|
||||
log.warning('Found %s policies using the original method',
|
||||
len(admx_items))
|
||||
for admx_item in admx_items:
|
||||
# If this is a policy, append it to admx_policies
|
||||
if etree.QName(admx_item).localname == 'policy':
|
||||
if admx_item not in admx_policies:
|
||||
admx_policies.append(admx_item)
|
||||
else:
|
||||
# If this is not a policy, find the parent policy for this item
|
||||
for policy_item in POLICY_ANCESTOR_XPATH(admx_item):
|
||||
if policy_item not in admx_policies:
|
||||
admx_policies.append(policy_item)
|
||||
log.debug('Parsing complete: %s seconds', time.time() - start_time)
|
||||
|
||||
log.debug('%s policies to examine', len(admx_policies))
|
||||
if return_not_configured:
|
||||
log.debug('returning non configured policies')
|
||||
log.debug('Gathering non configured policies')
|
||||
start_time = time.time()
|
||||
not_configured_policies = ALL_CLASS_POLICY_XPATH(admx_policy_definitions, registry_class=policy_class)
|
||||
for policy_item in admx_policies:
|
||||
if policy_item in not_configured_policies:
|
||||
|
@ -6125,6 +6150,10 @@ def _checkAllAdmxPolicies(policy_class,
|
|||
policy_definition=not_configured_policy,
|
||||
return_full_policy_names=return_full_policy_names,
|
||||
adml_language=adml_language)
|
||||
log.debug('Gathering complete: %s seconds', time.time() - start_time)
|
||||
|
||||
log.debug('Examining %s policies...', len(admx_policies))
|
||||
start_time = time.time()
|
||||
for admx_policy in admx_policies:
|
||||
this_valuename = None
|
||||
this_policy_setting = 'Not Configured'
|
||||
|
@ -6449,6 +6478,16 @@ def _checkAllAdmxPolicies(policy_class,
|
|||
policy_name=admx_policy.attrib['name'],
|
||||
return_full_policy_names=return_full_policy_names,
|
||||
adml_language=adml_language)
|
||||
# Make sure the we're passing the full policy name
|
||||
# This issue was found when setting the `Allow Telemetry` setting
|
||||
# All following states would show a change in this setting
|
||||
# When the state does it's first `lgpo.get` it would return `AllowTelemetry`
|
||||
# On the second run, it would return `Allow Telemetry`
|
||||
# This makes sure we're always returning the full_name when required
|
||||
if admx_policy.attrib['name'] in policy_vals[this_policynamespace][this_policyname]:
|
||||
full_name = full_names[this_policynamespace][this_policyname]
|
||||
setting = policy_vals[this_policynamespace][this_policyname].pop(admx_policy.attrib['name'])
|
||||
policy_vals[this_policynamespace][this_policyname][full_name] = setting
|
||||
if this_policynamespace in policy_vals and this_policyname in policy_vals[this_policynamespace]:
|
||||
if this_policynamespace not in hierarchy:
|
||||
hierarchy[this_policynamespace] = {}
|
||||
|
@ -6456,7 +6495,10 @@ def _checkAllAdmxPolicies(policy_class,
|
|||
policy_definition=admx_policy,
|
||||
return_full_policy_names=return_full_policy_names,
|
||||
adml_language=adml_language)
|
||||
log.debug('Examination complete: %s seconds', time.time() - start_time)
|
||||
if policy_vals and return_full_policy_names and not hierarchical_return:
|
||||
log.debug('Compiling non hierarchical return...')
|
||||
start_time = time.time()
|
||||
unpathed_dict = {}
|
||||
pathed_dict = {}
|
||||
for policy_namespace in list(policy_vals):
|
||||
|
@ -6481,11 +6523,14 @@ def _checkAllAdmxPolicies(policy_class,
|
|||
full_path_list.append(path_needed)
|
||||
log.debug('full_path_list == %s', full_path_list)
|
||||
policy_vals['\\'.join(full_path_list)] = policy_vals[policy_namespace].pop(path_needed)
|
||||
log.debug('Compilation complete: %s seconds', time.time() - start_time)
|
||||
for policy_namespace in list(policy_vals):
|
||||
if policy_vals[policy_namespace] == {}:
|
||||
policy_vals.pop(policy_namespace)
|
||||
if policy_vals and hierarchical_return:
|
||||
if hierarchy:
|
||||
log.debug('Compiling hierarchical return...')
|
||||
start_time = time.time()
|
||||
for policy_namespace in hierarchy:
|
||||
for hierarchy_item in hierarchy[policy_namespace]:
|
||||
if hierarchy_item in policy_vals[policy_namespace]:
|
||||
|
@ -6506,11 +6551,10 @@ def _checkAllAdmxPolicies(policy_class,
|
|||
policy_vals = dictupdate.update(policy_vals, tdict)
|
||||
if policy_namespace in policy_vals and policy_vals[policy_namespace] == {}:
|
||||
policy_vals.pop(policy_namespace)
|
||||
log.debug('Compilation complete: %s seconds', time.time() - start_time)
|
||||
policy_vals = {
|
||||
module_policy_data.admx_registry_classes[policy_class]['lgpo_section']: {
|
||||
'Administrative Templates': policy_vals
|
||||
}
|
||||
}
|
||||
module_policy_data.admx_registry_classes[policy_class]['lgpo_section']: {
|
||||
'Administrative Templates': policy_vals}}
|
||||
return policy_vals
|
||||
|
||||
|
||||
|
|
|
@ -36,7 +36,7 @@ class WinLgpoTest(ModuleCase):
|
|||
registry_value_vname,
|
||||
expected_value_data):
|
||||
'''
|
||||
Takes a registry based policy name and config and validates taht the
|
||||
Takes a registry based policy name and config and validates that the
|
||||
expected registry value exists and has the correct data
|
||||
|
||||
policy_name
|
||||
|
@ -638,11 +638,45 @@ class WinLgpoTest(ModuleCase):
|
|||
'Not Configured',
|
||||
[r'; Source file: c:\\windows\\system32\\grouppolicy\\machine\\registry.pol[\s]*; PARSING COMPLETED.'])
|
||||
|
||||
@destructiveTest
|
||||
def test_set_computer_policy_AllowTelemetry(self):
|
||||
'''
|
||||
Tests that a the AllowTelemetry policy is applied correctly and that it
|
||||
doesn't appear in subsequent group policy states as having changed
|
||||
'''
|
||||
valid_osreleases = ['10', '2016Server', '2019Server']
|
||||
if self.osrelease not in valid_osreleases:
|
||||
self.skipTest('Allow Telemetry policy is only applicable if the '
|
||||
'osrelease grain is {0}'.format(' or '.join(valid_osreleases)))
|
||||
else:
|
||||
self._testAdmxPolicy(
|
||||
'Allow Telemetry',
|
||||
{'AllowTelemetry': '1 - Basic'},
|
||||
[r'Software\\Policies\\Microsoft\\Windows\\DataCollection[\s]*AllowTelemetry[\s]*DWORD:1'],
|
||||
assert_true=True)
|
||||
result = self.run_function(
|
||||
'state.single',
|
||||
['lgpo.set'],
|
||||
name='state',
|
||||
computer_policy={
|
||||
'Disable pre-release features or settings': 'Disabled'
|
||||
}
|
||||
)
|
||||
name = 'lgpo_|-state_|-state_|-set'
|
||||
expected = {
|
||||
'new': {
|
||||
'Computer Configuration': {
|
||||
'Windows Components\\Data Collection and Preview Builds\\Disable pre-release features or settings': 'Disabled'}},
|
||||
'old': {'Computer Configuration': {}}}
|
||||
self.assertDictEqual(result[name]['changes'], expected)
|
||||
|
||||
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'))
|
||||
self.run_state(
|
||||
'file.absent',
|
||||
name='c:\\windows\\system32\\grouppolicy\\machine\\registry.pol')
|
||||
self.run_state(
|
||||
'file.absent',
|
||||
name='c:\\windows\\system32\\grouppolicy\\user\\registry.pol')
|
||||
|
|
Loading…
Add table
Reference in a new issue