%PDF- %PDF-
Direktori : /lib/python2.7/site-packages/salt/states/ |
Current File : //lib/python2.7/site-packages/salt/states/win_lgpo.py |
# -*- coding: utf-8 -*- ''' Manage Windows Local Group Policy ================================= .. versionadded:: 2016.11.0 This state allows configuring local Windows Group Policy The state can be used to ensure the setting of a single policy or multiple policies in one pass. Single policies must specify the policy name, the setting, and the policy class (Machine/User/Both) Example single policy configuration .. code-block:: yaml Ensure Account Lockout Duration: lgpo.set: - name: Account lockout duration - setting: 90 - policy_class: Machine .. code-block:: yaml Account lockout duration: gpo.set: - setting: 120 - policy_class: Machine Multiple policy configuration .. code-block:: yaml Company Local Group Policy: lgpo.set: - computer_policy: Deny logon locally: Guest Account lockout duration: 120 Account lockout threshold: 10 Reset account lockout counter after: 1440 Enforce password history: 24 Maximum password age: 60 Minimum password age: 1 Minimum password length: 14 Password must meet complexity requirements: Enabled Store passwords using reversible encryption: Disabled Configure Automatic Updates: Configure automatic updating: 4 - Auto download and schedule the intsall Scheduled install day: 7 - Every Saturday Scheduled install time: 17:00 Specify intranet Microsoft update service location: Set the intranet update service for detecting updates: http://mywsus Set the intranet statistics server: http://mywsus - user_policy: Do not process the legacy run list: Enabled .. code-block:: text server_policy: lgpo.set: - computer_policy: Maximum password age: 60 Minimum password age: 1 Minimum password length: 14 Account lockout duration: 1440 Account lockout threshold: 10 Reset account lockout counter after: 1440 Manage auditing and security log: - "BUILTIN\\Administrators" Replace a process level token: - "NT AUTHORITY\\NETWORK SERVICE" - "NT AUTHORITY\\LOCAL SERVICE" "Accounts: Guest account status": Disabled "Accounts: Rename guest account": Not_4_U "Audit: Audit the use of Backup and Restore privilege": Enabled "Interactive logon: Do not display last user name": Enabled "Network\\DNS Client\\Dynamic update": Disabled "System\\Logon\\Do not display the Getting Started welcome screen at logon": Enabled "Windows Components\\Remote Desktop Services\\Remote Desktop Session Host\\Connections\\Select RDP transport protocols": "Select Transport Type": "Use both UDP and TCP" "Windows Components\\Windows Update\\Allow Automatic Updates immediate installation": Enabled "Windows Components\\Windows Update\\Allow non-administrators to receive update notifications": Disabled "Windows Components\\Windows Update\\Always automatically restart at the scheduled time": "The restart timer will give users this much time to save their work (minutes)": 15 "Windows Components\\Windows Update\\Automatic Updates detection frequency": "Check for updates at the following interval (hours)": 1 "Windows Components\\Windows Update\\Configure Automatic Updates": "Configure automatic updating": 4 - Auto download and schedule the install "Install during automatic maintenance": False "Scheduled install day": 7 - Every Saturday "Scheduled install time": "17:00" "Windows Components\\Windows Update\\Delay Restart for scheduled installations": "Wait the following period before proceeding with a scheduled restart (minutes)": 1 "Windows Components\\Windows Update\\No auto-restart with logged on users for scheduled automatic updates installations": Disabled "Windows Components\\Windows Update\\Re-prompt for restart with scheduled installations": "Wait the following period before prompting again with a scheduled restart (minutes)": 30 "Windows Components\\Windows Update\\Reschedule Automatic Updates scheduled installations": Disabled "Windows Components\\Windows Update\\Specify intranet Microsoft update service location": "Set the intranet update service for detecting updates": http://mywsus "Set the intranet statistics server": http://mywsus - cumulative_rights_assignments: True ''' # Import python libs from __future__ import absolute_import, unicode_literals, print_function import logging # Import salt libs import salt.utils.data import salt.utils.dictdiffer import salt.utils.json # Import 3rd party libs from salt.ext import six log = logging.getLogger(__name__) __virtualname__ = 'lgpo' __func_alias__ = {'set_': 'set'} def __virtual__(): ''' load this state if the win_lgpo module exists ''' return __virtualname__ if 'lgpo.set' in __salt__ else False def _compare_policies(new_policy, current_policy): ''' Helper function that returns ``True`` if the policies are the same, otherwise ``False`` ''' # Compared dicts, lists, and strings if isinstance(new_policy, six.string_types): return new_policy == current_policy elif isinstance(new_policy, list): if isinstance(current_policy, list): return salt.utils.data.compare_lists(new_policy, current_policy) == {} else: return False elif isinstance(new_policy, dict): if isinstance(current_policy, dict): return salt.utils.data.compare_dicts(new_policy, current_policy) == {} else: return False def set_(name, setting=None, policy_class=None, computer_policy=None, user_policy=None, cumulative_rights_assignments=True, adml_language='en-US'): ''' Ensure the specified policy is set name the name of a single policy to configure setting the configuration setting for the single named policy if this argument is used the computer_policy/user_policy arguments will be ignored policy_class the policy class of the single named policy to configure this can "machine", "user", or "both" computer_policy a dict of policyname: value pairs of a set of computer policies to configure if this argument is used, the name/setting/policy_class arguments will be ignored user_policy a dict of policyname: value pairs of a set of user policies to configure if this argument is used, the name/setting/policy_class arguments will be ignored cumulative_rights_assignments determine if any user right assignment policies specified will be cumulative or explicit adml_language the adml language to use for AMDX policy data/display conversions ''' ret = {'name': name, 'result': True, 'changes': {}, 'comment': ''} policy_classes = ['machine', 'computer', 'user', 'both'] if not setting and not computer_policy and not user_policy: msg = 'At least one of the parameters setting, computer_policy, or user_policy' msg = msg + ' must be specified.' ret['result'] = False ret['comment'] = msg return ret if setting and not policy_class: msg = 'A single policy setting was specified but the policy_class was not specified.' ret['result'] = False ret['comment'] = msg return ret if setting and (computer_policy or user_policy): msg = 'The setting and computer_policy/user_policy parameters are mutually exclusive. Please' msg = msg + ' specify either a policy name and setting or a computer_policy and/or user_policy' msg = msg + ' dict' ret['result'] = False ret['comment'] = msg return ret if policy_class and policy_class.lower() not in policy_classes: msg = 'The policy_class parameter must be one of the following: {0}' ret['result'] = False ret['comment'] = msg return ret if not setting: if computer_policy and user_policy: policy_class = 'both' elif computer_policy: policy_class = 'machine' elif user_policy: policy_class = 'user' if computer_policy and not isinstance(computer_policy, dict): msg = 'The computer_policy must be specified as a dict.' ret['result'] = False ret['comment'] = msg return ret if user_policy and not isinstance(user_policy, dict): msg = 'The user_policy must be specified as a dict.' ret['result'] = False ret['comment'] = msg return ret else: user_policy = {} computer_policy = {} if policy_class.lower() == 'both': user_policy[name] = setting computer_policy[name] = setting elif policy_class.lower() == 'user': user_policy[name] = setting elif policy_class.lower() == 'machine' or policy_class.lower() == 'computer': computer_policy[name] = setting pol_data = {} pol_data['user'] = {'output_section': 'User Configuration', 'requested_policy': user_policy, 'policy_lookup': {}} pol_data['machine'] = {'output_section': 'Computer Configuration', 'requested_policy': computer_policy, 'policy_lookup': {}} for p_class, p_data in six.iteritems(pol_data): if p_data['requested_policy']: for policy_name, policy_setting in six.iteritems(p_data['requested_policy']): lookup = __salt__['lgpo.get_policy_info'](policy_name, p_class, adml_language=adml_language) if lookup['policy_found']: pol_data[p_class]['policy_lookup'][policy_name] = lookup else: ret['comment'] = ' '.join([ret['comment'], lookup['message']]) ret['result'] = False if not ret['result']: return ret current_policy = __salt__['lgpo.get'](policy_class=policy_class, adml_language=adml_language, hierarchical_return=False) log.debug('current policy == %s', current_policy) # compare policies policy_changes = [] for policy_section, policy_data in six.iteritems(pol_data): pol_id = None if policy_data and policy_data['output_section'] in current_policy: for policy_name, policy_setting in six.iteritems(policy_data['requested_policy']): currently_set = False # Check Case sensitive first (faster) if policy_name in current_policy[policy_data['output_section']]: currently_set = True pol_id = policy_name # Check case insensitive elif policy_name.lower() in (k.lower() for k in current_policy[policy_data['output_section']]): for p_name in current_policy[policy_data['output_section']]: if policy_name.lower() == p_name.lower(): currently_set = True pol_id = p_name break # Check aliases else: for alias in policy_data['policy_lookup'][policy_name]['policy_aliases']: log.debug('checking alias %s', alias) if alias in current_policy[policy_data['output_section']]: currently_set = True pol_id = alias break if currently_set: # compare log.debug('need to compare %s from ' 'current/requested policy', policy_name) changes = False requested_policy_json = salt.utils.json.dumps(policy_data['requested_policy'][policy_name], sort_keys=True).lower() current_policy_json = salt.utils.json.dumps(current_policy[policy_data['output_section']][pol_id], sort_keys=True).lower() requested_policy_check = salt.utils.json.loads(requested_policy_json) current_policy_check = salt.utils.json.loads(current_policy_json) # Are the requested and current policies identical policies_are_equal = _compare_policies( requested_policy_check, current_policy_check) if not policies_are_equal: additional_policy_comments = [] if policy_data['policy_lookup'][policy_name]['rights_assignment'] and cumulative_rights_assignments: for user in policy_data['requested_policy'][policy_name]: if user not in current_policy[policy_data['output_section']][pol_id]: changes = True else: additional_policy_comments.append('"{0}" is already granted the right'.format(user)) else: changes = True if changes: log.debug('%s current policy != requested policy', policy_name) log.debug( 'we compared %s to %s', requested_policy_json, current_policy_json ) policy_changes.append(policy_name) else: if additional_policy_comments: ret['comment'] = '"{0}" is already set ({1})\n'.format(policy_name, ', '.join(additional_policy_comments)) else: ret['comment'] = '"{0}" is already set\n'.format(policy_name) + ret['comment'] else: log.debug('%s current setting matches ' 'the requested setting', policy_name) ret['comment'] = '"{0}" is already set\n'.format(policy_name) + ret['comment'] else: policy_changes.append(policy_name) log.debug('policy %s is not set, we will configure it', policy_name) if __opts__['test']: if policy_changes: ret['result'] = None ret['comment'] = 'The following policies are set to change:\n{0}'.format( '\n'.join(policy_changes)) else: ret['comment'] = 'All specified policies are properly configured' else: if policy_changes: _ret = __salt__['lgpo.set'](computer_policy=computer_policy, user_policy=user_policy, cumulative_rights_assignments=cumulative_rights_assignments, adml_language=adml_language) if _ret: ret['result'] = _ret ret['changes'] = salt.utils.dictdiffer.deep_diff( current_policy, __salt__['lgpo.get'](policy_class=policy_class, adml_language=adml_language, hierarchical_return=False)) if ret['changes']: ret['comment'] = 'The following policies changed:\n{0}' \ ''.format('\n'.join(policy_changes)) else: ret['comment'] = 'The following policies are in the correct state:\n{0}' \ ''.format('\n'.join(policy_changes)) else: ret['result'] = False ret['comment'] = 'Errors occurred while attempting to configure policies: {0}'.format(_ret) return ret