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:
- Whether to run this module even when firewalld is offline.
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:
- Not tested on any Debian based system.
- Requires the python2 bindings of firewalld, which may not be installed by default.
@ -161,6 +168,12 @@ EXAMPLES = r'''
permanent: yes
icmp_block: echo-request
- firewalld:
zone: internal
state: present
permanent: yes
target: ACCEPT
- name: Redirect port 443 to 8443 with Rich Rule
firewalld:
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)
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):
"""
ZoneTransaction
@ -633,10 +693,12 @@ def main():
interface=dict(type='str'),
masquerade=dict(type='str'),
offline=dict(type='bool'),
target=dict(type='str', required=False, choices=['default', 'ACCEPT', 'DROP', 'REJECT']),
),
supports_check_mode=True,
required_by=dict(
interface=('zone',),
target=('zone',),
source=('permanent',),
),
)
@ -668,6 +730,7 @@ def main():
rich_rule = module.params['rich_rule']
source = module.params['source']
zone = module.params['zone']
target = module.params['target']
if module.params['port'] is not None:
if '/' in module.params['port']:
@ -696,12 +759,14 @@ def main():
modification_count += 1
if source is not None:
modification_count += 1
if target is not None:
modification_count += 1
if modification_count > 1:
module.fail_json(
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(
msg='absent and present state can only be used in zone level operations'
)
@ -832,6 +897,20 @@ def main():
changed, transaction_msgs = transaction.run()
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 modification_count == 0 and desired_state in ['absent', 'present']:

View file

@ -33,3 +33,6 @@
# firewalld source operation test cases
- 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