1
0
Fork 0
mirror of https://github.com/ansible-collections/community.general.git synced 2024-09-14 20:13:21 +02:00

firewalld: add zone target set (#526)

* firewalld: add zone target set

Fixes https://github.com/ansible/ansible/issues/49232

Signed-off-by: Adam Miller <admiller@redhat.com>

* fix sanity tests, add example of zone target setting

Signed-off-by: Adam Miller <admiller@redhat.com>

* test different zone/target combination as we're not hitting default settings

Signed-off-by: Adam Miller <admiller@redhat.com>

* fix enabled values for zone operations

Signed-off-by: Adam Miller <admiller@redhat.com>

* Apply suggestions from code review

Co-authored-by: Felix Fontein <felix@fontein.de>

Co-authored-by: Felix Fontein <felix@fontein.de>
This commit is contained in:
Adam Miller 2020-06-19 16:04:17 -05:00 committed by GitHub
parent 42a43586f1
commit 42c5cdf01a
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 154 additions and 1 deletions

View file

@ -0,0 +1,2 @@
minor_changes:
- firewalld - new feature, can now set ``target`` for a ``zone`` (https://github.com/ansible-collections/community.general/pull/526).

View file

@ -83,6 +83,13 @@ options:
description: description:
- Whether to run this module even when firewalld is offline. - Whether to run this module even when firewalld is offline.
type: bool type: bool
target:
description:
- firewalld Zone target
- If state is set to C(absent), this will reset the target to default
choices: [ default, ACCEPT, DROP, REJECT ]
type: str
version_added: 0.2.0
notes: notes:
- Not tested on any Debian based system. - Not tested on any Debian based system.
- Requires the python2 bindings of firewalld, which may not be installed by default. - Requires the python2 bindings of firewalld, which may not be installed by default.
@ -161,6 +168,12 @@ EXAMPLES = r'''
permanent: yes permanent: yes
icmp_block: echo-request icmp_block: echo-request
- firewalld:
zone: internal
state: present
permanent: yes
target: ACCEPT
- name: Redirect port 443 to 8443 with Rich Rule - name: Redirect port 443 to 8443 with Rich Rule
firewalld: firewalld:
rich_rule: rule family=ipv4 forward-port port=443 protocol=tcp to-port=8443 rich_rule: rule family=ipv4 forward-port port=443 protocol=tcp to-port=8443
@ -568,6 +581,53 @@ class SourceTransaction(FirewallTransaction):
self.update_fw_settings(fw_zone, fw_settings) self.update_fw_settings(fw_zone, fw_settings)
class ZoneTargetTransaction(FirewallTransaction):
"""
ZoneTargetTransaction
"""
def __init__(self, module, action_args=None, zone=None, desired_state=None,
permanent=True, immediate=False, enabled_values=None, disabled_values=None):
super(ZoneTargetTransaction, self).__init__(
module, action_args=action_args, desired_state=desired_state, zone=zone,
permanent=permanent, immediate=immediate,
enabled_values=enabled_values or ["present", "enabled"],
disabled_values=disabled_values or ["absent", "disabled"])
self.enabled_msg = "Set zone %s target to %s" % \
(self.zone, action_args[0])
self.disabled_msg = "Reset zone %s target to default" % \
(self.zone)
self.tx_not_permanent_error_msg = "Zone operations must be permanent. " \
"Make sure you didn't set the 'permanent' flag to 'false' or the 'immediate' flag to 'true'."
def get_enabled_immediate(self, target):
self.module.fail_json(msg=self.tx_not_permanent_error_msg)
def get_enabled_permanent(self, target):
fw_zone, fw_settings = self.get_fw_zone_settings()
current_target = fw_settings.getTarget()
return (current_target == target)
def set_enabled_immediate(self, target):
self.module.fail_json(msg=self.tx_not_permanent_error_msg)
def set_enabled_permanent(self, target):
fw_zone, fw_settings = self.get_fw_zone_settings()
fw_settings.setTarget(target)
self.update_fw_settings(fw_zone, fw_settings)
def set_disabled_immediate(self, target):
self.module.fail_json(msg=self.tx_not_permanent_error_msg)
def set_disabled_permanent(self, target):
fw_zone, fw_settings = self.get_fw_zone_settings()
fw_settings.setTarget("default")
self.update_fw_settings(fw_zone, fw_settings)
class ZoneTransaction(FirewallTransaction): class ZoneTransaction(FirewallTransaction):
""" """
ZoneTransaction ZoneTransaction
@ -633,10 +693,12 @@ def main():
interface=dict(type='str'), interface=dict(type='str'),
masquerade=dict(type='str'), masquerade=dict(type='str'),
offline=dict(type='bool'), offline=dict(type='bool'),
target=dict(type='str', required=False, choices=['default', 'ACCEPT', 'DROP', 'REJECT']),
), ),
supports_check_mode=True, supports_check_mode=True,
required_by=dict( required_by=dict(
interface=('zone',), interface=('zone',),
target=('zone',),
source=('permanent',), source=('permanent',),
), ),
) )
@ -668,6 +730,7 @@ def main():
rich_rule = module.params['rich_rule'] rich_rule = module.params['rich_rule']
source = module.params['source'] source = module.params['source']
zone = module.params['zone'] zone = module.params['zone']
target = module.params['target']
if module.params['port'] is not None: if module.params['port'] is not None:
if '/' in module.params['port']: if '/' in module.params['port']:
@ -696,12 +759,14 @@ def main():
modification_count += 1 modification_count += 1
if source is not None: if source is not None:
modification_count += 1 modification_count += 1
if target is not None:
modification_count += 1
if modification_count > 1: if modification_count > 1:
module.fail_json( module.fail_json(
msg='can only operate on port, service, rich_rule, masquerade, icmp_block, icmp_block_inversion, interface or source at once' msg='can only operate on port, service, rich_rule, masquerade, icmp_block, icmp_block_inversion, interface or source at once'
) )
elif modification_count > 0 and desired_state in ['absent', 'present']: elif (modification_count > 0) and (desired_state in ['absent', 'present']) and (target is None):
module.fail_json( module.fail_json(
msg='absent and present state can only be used in zone level operations' msg='absent and present state can only be used in zone level operations'
) )
@ -832,6 +897,20 @@ def main():
changed, transaction_msgs = transaction.run() changed, transaction_msgs = transaction.run()
msgs = msgs + transaction_msgs msgs = msgs + transaction_msgs
if target is not None:
transaction = ZoneTargetTransaction(
module,
action_args=(target,),
zone=zone,
desired_state=desired_state,
permanent=permanent,
immediate=immediate,
)
changed, transaction_msgs = transaction.run()
msgs = msgs + transaction_msgs
''' If there are no changes within the zone we are operating on the zone itself ''' ''' If there are no changes within the zone we are operating on the zone itself '''
if modification_count == 0 and desired_state in ['absent', 'present']: if modification_count == 0 and desired_state in ['absent', 'present']:

View file

@ -33,3 +33,6 @@
# firewalld source operation test cases # firewalld source operation test cases
- import_tasks: source_test_cases.yml - import_tasks: source_test_cases.yml
# firewalld zone target operation test cases
- import_tasks: zone_target_test_cases.yml

View file

@ -0,0 +1,69 @@
# Test playbook for the firewalld module - source operations
# (c) 2020, Adam Miller <admiller@redhat.com>
# This file is part of Ansible
#
# Ansible is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# Ansible is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with Ansible. If not, see <http://www.gnu.org/licenses/>.
- name: firewalld dmz zone target DROP
firewalld:
zone: dmz
permanent: True
state: present
target: DROP
register: result
- name: assert firewalld dmz zone target DROP present worked
assert:
that:
- result is changed
- name: firewalld dmz zone target DROP rerun (verify not changed)
firewalld:
zone: dmz
permanent: True
state: present
target: DROP
register: result
- name: assert firewalld dmz zone target DROP present worked (verify not changed)
assert:
that:
- result is not changed
- name: firewalld dmz zone target DROP absent
firewalld:
zone: dmz
permanent: True
state: absent
target: DROP
register: result
- name: assert firewalld dmz zone target DROP absent worked
assert:
that:
- result is changed
- name: firewalld dmz zone target DROP rerun (verify not changed)
firewalld:
zone: dmz
permanent: True
state: absent
target: DROP
register: result
- name: assert firewalld dmz zone target DROP present worked (verify not changed)
assert:
that:
- result is not changed