Merge pull request #28181 from rallytime/fix-27454

Revamp firewalld state to be more stateful.
This commit is contained in:
Mike Place 2015-10-21 15:19:18 -06:00
commit a1a924f170
2 changed files with 167 additions and 123 deletions

View file

@ -1,5 +1,4 @@
# -*- coding: utf-8 -*-
'''
Support for firewalld.
@ -12,6 +11,7 @@ import logging
import re
# Import Salt Libs
from salt.exceptions import CommandExecutionError
import salt.utils
log = logging.getLogger(__name__)
@ -31,16 +31,18 @@ def __firewall_cmd(cmd):
'''
Return the firewall-cmd location
'''
out = __salt__['cmd.run']('{0} {1}'.format(
salt.utils.which('firewall-cmd'),
cmd))
firewall_cmd = '{0} {1}'.format(salt.utils.which('firewall-cmd'), cmd)
out = __salt__['cmd.run_all'](firewall_cmd)
if out == 'success':
return 'success'
elif 'Error' in out:
return out[5:-5]
return out
if out['retcode'] != 0:
if not out['stderr']:
msg = out['stdout']
else:
msg = out['stderr']
raise CommandExecutionError(
'firewall-cmd failed: {0}'.format(msg)
)
return out['stdout']
def __mgmt(name, _type, action):

View file

@ -11,15 +11,16 @@ masquerading, and allows ports 22/tcp and 25/tcp.
.. code-block:: yaml
public:
- name: public
- block_icmp
- echo-reply
- echo-request
- default: False
- masquerade: True
- ports:
- 22/tcp
- 25/tcp
firewalld.present:
- name: public
- block_icmp:
- echo-reply
- echo-request
- default: False
- masquerade: True
- ports:
- 22/tcp
- 25/tcp
The following example applies changes to the public zone, enables
masquerading and configures port forwarding TCP traffic from port 22
@ -35,10 +36,14 @@ to 2222, and forwards TCP traffic from port 80 to 443 at 192.168.0.1.
- 22:2222:tcp
- 80:443:tcp:192.168.0.1
'''
from __future__ import absolute_import
# Import Python Libs
from __future__ import absolute_import
import logging
import salt.exceptions
# Import Salt Libs
from salt.exceptions import CommandExecutionError
import salt.utils
log = logging.getLogger(__name__)
@ -61,92 +66,119 @@ def present(name,
port_fwd=None,
services=None):
'''
Ensure a zone has specific attributes
Ensure a zone has specific attributes.
'''
ret = {'name': name,
'result': True,
'changes': {'icmp_blocks': [],
'ports': [],
'port_fwd': [],
'services': []},
'comment': {'icmp_blocks': [],
'ports': [],
'port_fwd': [],
'services': []}}
'result': False,
'changes': {},
'comment': ''}
if name not in __salt__['firewalld.get_zones']():
if __opts__['test']:
ret['comment'][name] = '`{0}` will be created'.format(name)
else:
__salt__['firewalld.new_zone'](name)
ret['changes'][name] = '`{0}` zone has been successfully created'.format(name)
else:
ret['comment'][name] = '`{0}` zone already exists'.format(name)
try:
zones = __salt__['firewalld.get_zones']()
except CommandExecutionError as err:
ret['comment'] = 'Error: {0}'.format(err)
return ret
if name not in zones:
if not __opts__['test']:
try:
__salt__['firewalld.new_zone'](name)
except CommandExecutionError as err:
ret['comment'] = 'Error: {0}'.format(err)
return ret
ret['changes'].update({name:
{'old': zones,
'new': name}})
if block_icmp:
_valid_icmp_types = __salt__['firewalld.get_icmp_types']()
_current_icmp_blocks = __salt__['firewalld.list_icmp_block'](name)
new_icmp_types = []
try:
_valid_icmp_types = __salt__['firewalld.get_icmp_types']()
_current_icmp_blocks = __salt__['firewalld.list_icmp_block'](name)
except CommandExecutionError as err:
ret['comment'] = 'Error: {0}'.format(err)
return ret
for icmp_type in set(block_icmp):
if icmp_type in _valid_icmp_types:
if icmp_type in _current_icmp_blocks:
ret['comment']['icmp_blocks'].append(
'`{0}` already exists'.format(icmp_type)
)
else:
if __opts__['test']:
ret['comment']['icmp_blocks'].append(
'`{0}` will be blocked'.format(icmp_type)
)
else:
__salt__['firewalld.block_icmp'](name, icmp_type)
ret['changes']['icmp_blocks'].append(
'`{0}` has been blocked'.format(icmp_type)
)
if icmp_type not in _current_icmp_blocks:
new_icmp_types.append(icmp_type)
if not __opts__['test']:
try:
__salt__['firewalld.block_icmp'](name, icmp_type)
except CommandExecutionError as err:
ret['comment'] = 'Error: {0}'.format(err)
return ret
else:
log.error('{0} is an invalid ICMP type'.format(icmp_type))
if new_icmp_types:
ret['changes'].update({'icmp_blocks':
{'old': _current_icmp_blocks,
'new': new_icmp_types}})
if default:
if __salt__['firewalld.default_zone']() == name:
ret['comment']['default'] = '`{0}` is already the default zone'.format(name)
else:
if __opts__['test']:
ret['comment']['default'] = '`{0}` wll be set to the default zone'.format(name)
else:
__salt__['firewalld.set_default_zone'](name)
ret['changes']['default'] = '`{0}` has been set to the default zone'.format(name)
try:
default_zone = __salt__['firewalld.default_zone']()
except CommandExecutionError as err:
ret['comment'] = 'Error: {0}'.format(err)
return ret
if name != default_zone:
if not __opts__['test']:
try:
__salt__['firewalld.set_default_zone'](name)
except CommandExecutionError as err:
ret['comment'] = 'Error: {0}'.format(err)
return ret
ret['changes'].update({'default':
{'old': default_zone,
'new': name}})
if masquerade:
if __salt__['firewalld.get_masquerade'](name):
ret['comment']['masquerade'] = 'masquerading is already enabed'
else:
if __opts__['test']:
ret['comment']['masquerade'] = 'masquerading will be enabled'
else:
__salt__['firewalld.add_masquerade'](name)
ret['changes']['masquerade'] = 'masquerading successfully set'
try:
masquerade_ret = __salt__['firewalld.get_masquerade'](name)
except CommandExecutionError as err:
ret['comment'] = 'Error: {0}'.format(err)
return ret
if not masquerade_ret:
if not __opts__['test']:
try:
__salt__['firewalld.add_masquerade'](name)
except CommandExecutionError as err:
ret['comment'] = 'Error: {0}'.format(err)
return ret
ret['changes'].update({'masquerade':
{'old': '',
'new': 'Masquerading successfully set.'}})
if ports:
_current_ports = __salt__['firewalld.list_ports'](name)
new_ports = []
try:
_current_ports = __salt__['firewalld.list_ports'](name)
except CommandExecutionError as err:
ret['comment'] = 'Error: {0}'.format(err)
return ret
for port in ports:
if port in _current_ports:
ret['comment']['ports'].append(
'`{0}` already exists'.format(port)
)
else:
if __opts__['test']:
ret['comment']['ports'].append(
'{0} will be added'.format(port)
)
else:
__salt__['firewalld.add_port'](name, port)
ret['changes']['ports'].append(
'`{0}` has been added to the firewall'.format(port)
)
if port not in _current_ports:
new_ports.append(port)
if not __opts__['test']:
try:
__salt__['firewalld.add_port'](name, port)
except CommandExecutionError as err:
ret['comment'] = 'Error: {0}'.format(err)
return ret
if new_ports:
ret['changes'].update({'ports':
{'old': _current_ports,
'new': new_ports}})
if port_fwd:
_current_port_fwd = __salt__['firewalld.list_port_fwd'](name)
new_port_fwds = []
try:
_current_port_fwd = __salt__['firewalld.list_port_fwd'](name)
except CommandExecutionError as err:
ret['comment'] = 'Error: {0}'.format(err)
return ret
for port in port_fwd:
dstaddr = ''
@ -157,45 +189,55 @@ def present(name,
else:
(src, dest, protocol) = port.split(':')
for i in _current_port_fwd:
if (src == i['Source port'] and dest == i['Destination port'] and
protocol == i['Protocol'] and dstaddr == i['Destination address']):
for item in _current_port_fwd:
if (src == item['Source port'] and dest == item['Destination port'] and
protocol == item['Protocol'] and dstaddr == item['Destination address']):
rule_exists = True
if rule_exists:
ret['comment']['port_fwd'].append(
'`{0}` port forwarding already exists'.format(port)
)
else:
if __opts__['test']:
ret['comment']['port_fwd'].append(
'`{0}` port will be added'.format(port)
)
else:
__salt__['firewalld.add_port_fwd'](
name, src, dest, protocol, dstaddr
)
ret['changes']['port_fwd'].append(
'`{0}` port forwarding has been added'.format(port)
)
if rule_exists is False:
new_port_fwds.append(port)
if not __opts__['test']:
try:
__salt__['firewalld.add_port_fwd'](name, src, dest, protocol, dstaddr)
except CommandExecutionError as err:
ret['comment'] = 'Error: {0}'.format(err)
return ret
if new_port_fwds:
ret['changes'].update({'port_fwd':
{'old': _current_port_fwd,
'new': new_port_fwds}})
if services:
_current_services = __salt__['firewalld.list_services'](name)
new_services = []
try:
_current_services = __salt__['firewalld.list_services'](name)
except CommandExecutionError as err:
ret['comment'] = 'Error: {0}'.format(err)
return ret
for service in services:
if service in _current_services:
ret['comment']['services'].append(
'`{0}` service already exists'.format(service)
)
else:
if __opts__['test']:
ret['comment']['services'].append(
'`{0}` service will be added'.format(service)
)
else:
__salt__['firewalld.new_service'](service)
ret['changes']['services'].append(
'`{0}` has been successfully added'.format(service)
)
if service not in _current_services:
new_services.append(service)
if not __opts__['test']:
try:
__salt__['firewalld.new_service'](service)
except CommandExecutionError as err:
ret['comment'] = 'Error: {0}'.format(err)
return ret
if new_services:
ret['changes'].update({'services':
{'old': _current_services,
'new': new_services}})
ret['result'] = True
if ret['changes'] == {}:
ret['comment'] = '\'{0}\' is already in the desired state.'.format(name)
return ret
if __opts__['test']:
ret['result'] = None
ret['comment'] = 'Configuration for \'{0}\' will change.'.format(name)
return ret
ret['comment'] = '\'{0}\' was configured.'.format(name)
return ret