salt/states/win_firewall.py
# -*- coding: utf-8 -*-
'''
State for configuring Windows Firewall
'''
from __future__ import absolute_import, unicode_literals, print_function
# Import Salt libs
from salt.exceptions import CommandExecutionError, SaltInvocationError
def __virtual__():
'''
Load if the module firewall is loaded
'''
return 'win_firewall' if 'firewall.get_config' in __salt__ else False
def disabled(name='allprofiles'):
'''
Disable all the firewall profiles (Windows only)
Args:
profile (Optional[str]): The name of the profile to disable. Default is
``allprofiles``. Valid options are:
- allprofiles
- domainprofile
- privateprofile
- publicprofile
Example:
.. code-block:: yaml
# To disable the domain profile
disable_domain:
win_firewall.disabled:
- name: domainprofile
# To disable all profiles
disable_all:
win_firewall.disabled:
- name: allprofiles
'''
ret = {'name': name,
'result': True,
'changes': {},
'comment': ''}
profile_map = {'domainprofile': 'Domain',
'privateprofile': 'Private',
'publicprofile': 'Public',
'allprofiles': 'All'}
# Make sure the profile name is valid
if name not in profile_map:
raise SaltInvocationError('Invalid profile name: {0}'.format(name))
current_config = __salt__['firewall.get_config']()
if name != 'allprofiles' and profile_map[name] not in current_config:
ret['result'] = False
ret['comment'] = 'Profile {0} does not exist in firewall.get_config' \
''.format(name)
return ret
for key in current_config:
if current_config[key]:
if name == 'allprofiles' or key == profile_map[name]:
ret['changes'][key] = 'disabled'
if __opts__['test']:
ret['result'] = not ret['changes'] or None
ret['comment'] = ret['changes']
ret['changes'] = {}
return ret
# Disable it
if ret['changes']:
try:
ret['result'] = __salt__['firewall.disable'](name)
except CommandExecutionError:
ret['comment'] = 'Firewall Profile {0} could not be disabled' \
''.format(profile_map[name])
else:
if name == 'allprofiles':
msg = 'All the firewall profiles are disabled'
else:
msg = 'Firewall profile {0} is disabled'.format(name)
ret['comment'] = msg
return ret
def add_rule(name,
localport,
protocol='tcp',
action='allow',
dir='in',
remoteip='any'):
'''
Add a new inbound or outbound rule to the firewall policy
Args:
name (str): The name of the rule. Must be unique and cannot be "all".
Required.
localport (int): The port the rule applies to. Must be a number between
0 and 65535. Can be a range. Can specify multiple ports separated by
commas. Required.
protocol (Optional[str]): The protocol. Can be any of the following:
- A number between 0 and 255
- icmpv4
- icmpv6
- tcp
- udp
- any
action (Optional[str]): The action the rule performs. Can be any of the
following:
- allow
- block
- bypass
dir (Optional[str]): The direction. Can be ``in`` or ``out``.
remoteip (Optional [str]): The remote IP. Can be any of the following:
- any
- localsubnet
- dns
- dhcp
- wins
- defaultgateway
- Any valid IPv4 address (192.168.0.12)
- Any valid IPv6 address (2002:9b3b:1a31:4:208:74ff:fe39:6c43)
- Any valid subnet (192.168.1.0/24)
- Any valid range of IP addresses (192.168.0.1-192.168.0.12)
- A list of valid IP addresses
Can be combinations of the above separated by commas.
.. versionadded:: 2016.11.6
Example:
.. code-block:: yaml
open_smb_port:
win_firewall.add_rule:
- name: SMB (445)
- localport: 445
- protocol: tcp
- action: allow
'''
ret = {'name': name,
'result': True,
'changes': {},
'comment': ''}
# Check if rule exists
if not __salt__['firewall.rule_exists'](name):
ret['changes'] = {'new rule': name}
else:
ret['comment'] = 'A rule with that name already exists'
return ret
if __opts__['test']:
ret['result'] = not ret['changes'] or None
ret['comment'] = ret['changes']
ret['changes'] = {}
return ret
# Add rule
try:
__salt__['firewall.add_rule'](
name, localport, protocol, action, dir, remoteip)
except CommandExecutionError:
ret['comment'] = 'Could not add rule'
return ret
def delete_rule(name,
localport=None,
protocol=None,
dir=None,
remoteip=None):
'''
Delete an existing firewall rule identified by name and optionally by ports,
protocols, direction, and remote IP.
.. versionadded:: Neon
Args:
name (str): The name of the rule to delete. If the name ``all`` is used
you must specify additional parameters.
localport (Optional[str]): The port of the rule. If protocol is not
specified, protocol will be set to ``tcp``
protocol (Optional[str]): The protocol of the rule. Default is ``tcp``
when ``localport`` is specified
dir (Optional[str]): The direction of the rule.
remoteip (Optional[str]): The remote IP of the rule.
Example:
.. code-block:: yaml
delete_smb_port_rule:
win_firewall.delete_rule:
- name: SMB (445)
'''
ret = {'name': name,
'result': True,
'changes': {},
'comment': ''}
# Check if rule exists
if __salt__['firewall.rule_exists'](name):
ret['changes'] = {'delete rule': name}
else:
ret['comment'] = 'A rule with that name does not exist'
return ret
if __opts__['test']:
ret['result'] = not ret['changes'] or None
ret['comment'] = ret['changes']
ret['changes'] = {}
return ret
# Delete rule
try:
__salt__['firewall.delete_rule'](
name, localport, protocol, dir, remoteip)
except CommandExecutionError:
ret['comment'] = 'Could not delete rule'
return ret
def enabled(name='allprofiles'):
'''
Enable all the firewall profiles (Windows only)
Args:
profile (Optional[str]): The name of the profile to enable. Default is
``allprofiles``. Valid options are:
- allprofiles
- domainprofile
- privateprofile
- publicprofile
Example:
.. code-block:: yaml
# To enable the domain profile
enable_domain:
win_firewall.enabled:
- name: domainprofile
# To enable all profiles
enable_all:
win_firewall.enabled:
- name: allprofiles
'''
ret = {'name': name,
'result': True,
'changes': {},
'comment': ''}
profile_map = {'domainprofile': 'Domain',
'privateprofile': 'Private',
'publicprofile': 'Public',
'allprofiles': 'All'}
# Make sure the profile name is valid
if name not in profile_map:
raise SaltInvocationError('Invalid profile name: {0}'.format(name))
current_config = __salt__['firewall.get_config']()
if name != 'allprofiles' and profile_map[name] not in current_config:
ret['result'] = False
ret['comment'] = 'Profile {0} does not exist in firewall.get_config' \
''.format(name)
return ret
for key in current_config:
if not current_config[key]:
if name == 'allprofiles' or key == profile_map[name]:
ret['changes'][key] = 'enabled'
if __opts__['test']:
ret['result'] = not ret['changes'] or None
ret['comment'] = ret['changes']
ret['changes'] = {}
return ret
# Enable it
if ret['changes']:
try:
ret['result'] = __salt__['firewall.enable'](name)
except CommandExecutionError:
ret['comment'] = 'Firewall Profile {0} could not be enabled' \
''.format(profile_map[name])
else:
if name == 'allprofiles':
msg = 'All the firewall profiles are enabled'
else:
msg = 'Firewall profile {0} is enabled'.format(name)
ret['comment'] = msg
return ret