%PDF- %PDF-
Direktori : /lib/python2.7/site-packages/salt/utils/ |
Current File : //lib/python2.7/site-packages/salt/utils/win_lgpo_netsh.py |
# -*- coding: utf-8 -*- r''' A salt util for modifying firewall settings. .. versionadded:: 2018.3.4 .. versionadded:: 2019.2.0 This util allows you to modify firewall settings in the local group policy in addition to the normal firewall settings. Parameters are taken from the netsh advfirewall prompt. .. note:: More information can be found in the advfirewall context in netsh. This can be access by opening a netsh prompt. At a command prompt type the following: c:\>netsh netsh>advfirewall netsh advfirewall>set help netsh advfirewall>set domain help Usage: .. code-block:: python import salt.utils.win_lgpo_netsh # Get the inbound/outbound firewall settings for connections on the # local domain profile salt.utils.win_lgpo_netsh.get_settings(profile='domain', section='firewallpolicy') # Get the inbound/outbound firewall settings for connections on the # domain profile as defined by local group policy salt.utils.win_lgpo_netsh.get_settings(profile='domain', section='firewallpolicy', store='lgpo') # Get all firewall settings for connections on the domain profile salt.utils.win_lgpo_netsh.get_all_settings(profile='domain') # Get all firewall settings for connections on the domain profile as # defined by local group policy salt.utils.win_lgpo_netsh.get_all_settings(profile='domain', store='lgpo') # Get all firewall settings for all profiles salt.utils.win_lgpo_netsh.get_all_settings() # Get all firewall settings for all profiles as defined by local group # policy salt.utils.win_lgpo_netsh.get_all_settings(store='lgpo') # Set the inbound setting for the domain profile to block inbound # connections salt.utils.win_lgpo_netsh.set_firewall_settings(profile='domain', inbound='blockinbound') # Set the outbound setting for the domain profile to allow outbound # connections salt.utils.win_lgpo_netsh.set_firewall_settings(profile='domain', outbound='allowoutbound') # Set inbound/outbound settings for the domain profile in the group # policy to block inbound and allow outbound salt.utils.win_lgpo_netsh.set_firewall_settings(profile='domain', inbound='blockinbound', outbound='allowoutbound', store='lgpo') ''' # Import Python libs from __future__ import absolute_import, unicode_literals, print_function from textwrap import dedent import logging import os import re import socket import tempfile import salt.modules.cmdmod from salt.exceptions import CommandExecutionError from salt.ext.six.moves import zip log = logging.getLogger(__name__) __hostname__ = socket.gethostname() __virtualname__ = 'netsh' # Although utils are often directly imported, it is also possible to use the # loader. def __virtual__(): ''' Only load if on a Windows system ''' if not salt.utils.platform.is_windows(): return False, 'This utility only available on Windows' return __virtualname__ def _netsh_file(content): ''' helper function to get the results of ``netsh -f content.txt`` Running ``netsh`` will drop you into a ``netsh`` prompt where you can issue ``netsh`` commands. You can put a series of commands in an external file and run them as if from a ``netsh`` prompt using the ``-f`` switch. That's what this function does. Args: content (str): The contents of the file that will be run by the ``netsh -f`` command Returns: str: The text returned by the netsh command ''' with tempfile.NamedTemporaryFile(mode='w', prefix='salt-', suffix='.netsh', delete=False) as fp: fp.write(content) try: log.debug('{0}:\n{1}'.format(fp.name, content)) return salt.modules.cmdmod.run('netsh -f {0}'.format(fp.name), python_shell=True) finally: os.remove(fp.name) def _netsh_command(command, store): if store.lower() not in ('local', 'lgpo'): raise ValueError('Incorrect store: {0}'.format(store)) # set the store for local or lgpo if store.lower() == 'local': netsh_script = dedent('''\ advfirewall set store local {0} '''.format(command)) else: netsh_script = dedent('''\ advfirewall set store gpo = {0} {1} '''.format(__hostname__, command)) return _netsh_file(content=netsh_script).splitlines() def get_settings(profile, section, store='local'): ''' Get the firewall property from the specified profile in the specified store as returned by ``netsh advfirewall``. Args: profile (str): The firewall profile to query. Valid options are: - domain - public - private section (str): The property to query within the selected profile. Valid options are: - firewallpolicy : inbound/outbound behavior - logging : firewall logging settings - settings : firewall properties - state : firewalls state (on | off) store (str): The store to use. This is either the local firewall policy or the policy defined by local group policy. Valid options are: - lgpo - local Default is ``local`` Returns: dict: A dictionary containing the properties for the specified profile Raises: CommandExecutionError: If an error occurs ValueError: If the parameters are incorrect ''' # validate input if profile.lower() not in ('domain', 'public', 'private'): raise ValueError('Incorrect profile: {0}'.format(profile)) if section.lower() not in ('state', 'firewallpolicy', 'settings', 'logging'): raise ValueError('Incorrect section: {0}'.format(section)) if store.lower() not in ('local', 'lgpo'): raise ValueError('Incorrect store: {0}'.format(store)) command = 'show {0}profile {1}'.format(profile, section) # run it results = _netsh_command(command=command, store=store) # sample output: # Domain Profile Settings: # ---------------------------------------------------------------------- # LocalFirewallRules N/A (GPO-store only) # LocalConSecRules N/A (GPO-store only) # InboundUserNotification Disable # RemoteManagement Disable # UnicastResponseToMulticast Enable # if it's less than 3 lines it failed if len(results) < 3: raise CommandExecutionError('Invalid results: {0}'.format(results)) ret = {} # Skip the first 2 lines. Add everything else to a dictionary for line in results[3:]: ret.update(dict(list(zip(*[iter(re.split(r"\s{2,}", line))]*2)))) # Remove spaces from the values so that `Not Configured` is detected # correctly for item in ret: ret[item] = ret[item].replace(' ', '') # special handling for firewallpolicy if section == 'firewallpolicy': inbound, outbound = ret['Firewall Policy'].split(',') return {'Inbound': inbound, 'Outbound': outbound} return ret def get_all_settings(profile, store='local'): ''' Gets all the properties for the specified profile in the specified store Args: profile (str): The firewall profile to query. Valid options are: - domain - public - private store (str): The store to use. This is either the local firewall policy or the policy defined by local group policy. Valid options are: - lgpo - local Default is ``local`` Returns: dict: A dictionary containing the specified settings ''' ret = dict() ret.update(get_settings(profile=profile, section='state', store=store)) ret.update(get_settings(profile=profile, section='firewallpolicy', store=store)) ret.update(get_settings(profile=profile, section='settings', store=store)) ret.update(get_settings(profile=profile, section='logging', store=store)) return ret def get_all_profiles(store='local'): ''' Gets all properties for all profiles in the specified store Args: store (str): The store to use. This is either the local firewall policy or the policy defined by local group policy. Valid options are: - lgpo - local Default is ``local`` Returns: dict: A dictionary containing the specified settings for each profile ''' return { 'Domain Profile': get_all_settings(profile='domain', store=store), 'Private Profile': get_all_settings(profile='private', store=store), 'Public Profile': get_all_settings(profile='public', store=store) } def set_firewall_settings(profile, inbound=None, outbound=None, store='local'): ''' Set the firewall inbound/outbound settings for the specified profile and store Args: profile (str): The firewall profile to configure. Valid options are: - domain - public - private inbound (str): The inbound setting. If ``None`` is passed, the setting will remain unchanged. Valid values are: - blockinbound - blockinboundalways - allowinbound - notconfigured Default is ``None`` outbound (str): The outbound setting. If ``None`` is passed, the setting will remain unchanged. Valid values are: - allowoutbound - blockoutbound - notconfigured Default is ``None`` store (str): The store to use. This is either the local firewall policy or the policy defined by local group policy. Valid options are: - lgpo - local Default is ``local`` Returns: bool: ``True`` if successful Raises: CommandExecutionError: If an error occurs ValueError: If the parameters are incorrect ''' # Input validation if profile.lower() not in ('domain', 'public', 'private'): raise ValueError('Incorrect profile: {0}'.format(profile)) if inbound and inbound.lower() not in ('blockinbound', 'blockinboundalways', 'allowinbound', 'notconfigured'): raise ValueError('Incorrect inbound value: {0}'.format(inbound)) if outbound and outbound.lower() not in ('allowoutbound', 'blockoutbound', 'notconfigured'): raise ValueError('Incorrect outbound value: {0}'.format(outbound)) if not inbound and not outbound: raise ValueError('Must set inbound or outbound') # You have to specify inbound and outbound setting at the same time # If you're only specifying one, you have to get the current setting for the # other if not inbound or not outbound: ret = get_settings(profile=profile, section='firewallpolicy', store=store) if not inbound: inbound = ret['Inbound'] if not outbound: outbound = ret['Outbound'] command = 'set {0}profile firewallpolicy {1},{2}' \ ''.format(profile, inbound, outbound) results = _netsh_command(command=command, store=store) if results: raise CommandExecutionError('An error occurred: {0}'.format(results)) return True def set_logging_settings(profile, setting, value, store='local'): ''' Configure logging settings for the Windows firewall. Args: profile (str): The firewall profile to configure. Valid options are: - domain - public - private setting (str): The logging setting to configure. Valid options are: - allowedconnections - droppedconnections - filename - maxfilesize value (str): The value to apply to the setting. Valid values are dependent upon the setting being configured. Valid options are: allowedconnections: - enable - disable - notconfigured droppedconnections: - enable - disable - notconfigured filename: - Full path and name of the firewall log file - notconfigured maxfilesize: - 1 - 32767 (Kb) - notconfigured store (str): The store to use. This is either the local firewall policy or the policy defined by local group policy. Valid options are: - lgpo - local Default is ``local`` Returns: bool: ``True`` if successful Raises: CommandExecutionError: If an error occurs ValueError: If the parameters are incorrect ''' # Input validation if profile.lower() not in ('domain', 'public', 'private'): raise ValueError('Incorrect profile: {0}'.format(profile)) if setting.lower() not in ('allowedconnections', 'droppedconnections', 'filename', 'maxfilesize'): raise ValueError('Incorrect setting: {0}'.format(setting)) if setting.lower() in ('allowedconnections', 'droppedconnections'): if value.lower() not in ('enable', 'disable', 'notconfigured'): raise ValueError('Incorrect value: {0}'.format(value)) # TODO: Consider adding something like the following to validate filename # https://stackoverflow.com/questions/9532499/check-whether-a-path-is-valid-in-python-without-creating-a-file-at-the-paths-ta if setting.lower() == 'maxfilesize': if value.lower() != 'notconfigured': # Must be a number between 1 and 32767 try: int(value) except ValueError: raise ValueError('Incorrect value: {0}'.format(value)) if not 1 <= int(value) <= 32767: raise ValueError('Incorrect value: {0}'.format(value)) # Run the command command = 'set {0}profile logging {1} {2}'.format(profile, setting, value) results = _netsh_command(command=command, store=store) # A successful run should return an empty list if results: raise CommandExecutionError('An error occurred: {0}'.format(results)) return True def set_settings(profile, setting, value, store='local'): ''' Configure firewall settings. Args: profile (str): The firewall profile to configure. Valid options are: - domain - public - private setting (str): The firewall setting to configure. Valid options are: - localfirewallrules - localconsecrules - inboundusernotification - remotemanagement - unicastresponsetomulticast value (str): The value to apply to the setting. Valid options are - enable - disable - notconfigured store (str): The store to use. This is either the local firewall policy or the policy defined by local group policy. Valid options are: - lgpo - local Default is ``local`` Returns: bool: ``True`` if successful Raises: CommandExecutionError: If an error occurs ValueError: If the parameters are incorrect ''' # Input validation if profile.lower() not in ('domain', 'public', 'private'): raise ValueError('Incorrect profile: {0}'.format(profile)) if setting.lower() not in ('localfirewallrules', 'localconsecrules', 'inboundusernotification', 'remotemanagement', 'unicastresponsetomulticast'): raise ValueError('Incorrect setting: {0}'.format(setting)) if value.lower() not in ('enable', 'disable', 'notconfigured'): raise ValueError('Incorrect value: {0}'.format(value)) # Run the command command = 'set {0}profile settings {1} {2}'.format(profile, setting, value) results = _netsh_command(command=command, store=store) # A successful run should return an empty list if results: raise CommandExecutionError('An error occurred: {0}'.format(results)) return True def set_state(profile, state, store='local'): ''' Configure the firewall state. Args: profile (str): The firewall profile to configure. Valid options are: - domain - public - private state (str): The firewall state. Valid options are: - on - off - notconfigured store (str): The store to use. This is either the local firewall policy or the policy defined by local group policy. Valid options are: - lgpo - local Default is ``local`` Returns: bool: ``True`` if successful Raises: CommandExecutionError: If an error occurs ValueError: If the parameters are incorrect ''' # Input validation if profile.lower() not in ('domain', 'public', 'private'): raise ValueError('Incorrect profile: {0}'.format(profile)) if state.lower() not in ('on', 'off', 'notconfigured'): raise ValueError('Incorrect state: {0}'.format(state)) # Run the command command = 'set {0}profile state {1}'.format(profile, state) results = _netsh_command(command=command, store=store) # A successful run should return an empty list if results: raise CommandExecutionError('An error occurred: {0}'.format(results)) return True