Add new feature to firewalld module allowing the default zone to be set.

This commit is contained in:
Gregory Furlong 2022-12-14 16:59:19 -05:00
parent 090706b581
commit 628a53eb1a
4 changed files with 176 additions and 3 deletions

View file

@ -222,6 +222,7 @@ from ansible_collections.ansible.posix.plugins.module_utils.firewalld import Fir
try: try:
from firewall.client import Rich_Rule from firewall.client import Rich_Rule
from firewall.client import FirewallClientZoneSettings from firewall.client import FirewallClientZoneSettings
from firewall.config import FALLBACK_ZONE
except ImportError: except ImportError:
# The import errors are handled via FirewallTransaction, don't need to # The import errors are handled via FirewallTransaction, don't need to
# duplicate that here # duplicate that here
@ -695,6 +696,45 @@ class ZoneTransaction(FirewallTransaction):
zone_obj = self.fw.config().getZoneByName(self.zone) zone_obj = self.fw.config().getZoneByName(self.zone)
zone_obj.remove() zone_obj.remove()
class DefaultZoneTransaction(FirewallTransaction):
"""
DefaultZoneTransaction
"""
def __init__(self, module, action_args=None, zone=None, desired_state=None, permanent=False, immediate=False):
super(DefaultZoneTransaction, self).__init__(
module, action_args=action_args, desired_state=desired_state, zone=zone, permanent=permanent, immediate=immediate
)
self.upstream_default_zone = FALLBACK_ZONE
self.enabled_msg = "Updated default zone to %s" % self.zone
self.disabled_msg = "Reverted default zone from %s to upstream default %s" % (self.zone, self.upstream_default_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):
self.module.fail_json(msg=self.tx_not_permanent_error_msg)
def get_enabled_permanent(self):
default_zone = self.fw.get_default_zone() if fw_offline else self.fw.getDefaultZone()
return self.zone == default_zone
def set_enabled_immediate(self):
self.module.fail_json(msg=self.tx_not_permanent_error_msg)
def set_enabled_permanent(self):
if fw_offline:
self.fw.set_default_zone(self.zone)
else:
self.fw.setDefaultZone(self.zone)
def set_disabled_immediate(self):
self.module.fail_json(msg=self.tx_not_permanent_error_msg)
def set_disabled_permanent(self):
if fw_offline:
self.fw.set_default_zone(self.upstream_default_zone)
else:
self.fw.setDefaultZone(self.upstream_default_zone)
class ForwardPortTransaction(FirewallTransaction): class ForwardPortTransaction(FirewallTransaction):
""" """
@ -732,7 +772,6 @@ class ForwardPortTransaction(FirewallTransaction):
fw_settings.removeForwardPort(port, proto, toport, toaddr) fw_settings.removeForwardPort(port, proto, toport, toaddr)
self.update_fw_settings(fw_zone, fw_settings) self.update_fw_settings(fw_zone, fw_settings)
def main(): def main():
module = AnsibleModule( module = AnsibleModule(
@ -751,6 +790,7 @@ def main():
timeout=dict(type='int', default=0), timeout=dict(type='int', default=0),
interface=dict(type='str'), interface=dict(type='str'),
masquerade=dict(type='str'), masquerade=dict(type='str'),
default=dict(type='bool'),
offline=dict(type='bool'), offline=dict(type='bool'),
target=dict(type='str', choices=['default', 'ACCEPT', 'DROP', '%%REJECT%%']), target=dict(type='str', choices=['default', 'ACCEPT', 'DROP', '%%REJECT%%']),
), ),
@ -758,11 +798,12 @@ def main():
required_by=dict( required_by=dict(
interface=('zone',), interface=('zone',),
target=('zone',), target=('zone',),
default=('zone',),
source=('permanent',), source=('permanent',),
), ),
mutually_exclusive=[ mutually_exclusive=[
['icmp_block', 'icmp_block_inversion', 'service', 'port', 'port_forward', 'rich_rule', ['icmp_block', 'icmp_block_inversion', 'service', 'port', 'port_forward', 'rich_rule',
'interface', 'masquerade', 'source', 'target'] 'interface', 'masquerade', 'source', 'target','default']
], ],
) )
@ -772,6 +813,7 @@ def main():
timeout = module.params['timeout'] timeout = module.params['timeout']
interface = module.params['interface'] interface = module.params['interface']
masquerade = module.params['masquerade'] masquerade = module.params['masquerade']
default = module.params['default']
# Sanity checks # Sanity checks
FirewallTransaction.sanity_check(module) FirewallTransaction.sanity_check(module)
@ -1008,6 +1050,20 @@ def main():
changed, transaction_msgs = transaction.run() changed, transaction_msgs = transaction.run()
msgs = msgs + transaction_msgs msgs = msgs + transaction_msgs
if default is not None:
expected_state = 'enabled' if (desired_state == 'enabled') == default else 'disabled'
transaction = DefaultZoneTransaction(
module,
action_args=(),
zone=zone,
desired_state=expected_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 not modification and desired_state in ['absent', 'present']: if not modification and desired_state in ['absent', 'present']:

View file

@ -40,6 +40,8 @@
state: stopped state: stopped
- import_tasks: run_all_tests.yml - import_tasks: run_all_tests.yml
# FIXME currently fails when the daemon is running AND executed inside a container
- import_tasks: zone_default_test_cases.yml
when: check_output.rc == 0 when: check_output.rc == 0
when: when:

View file

@ -82,4 +82,4 @@
assert: assert:
that: that:
- result is not changed - result is not changed
- "result.msg == 'parameters are mutually exclusive: icmp_block|icmp_block_inversion|service|port|port_forward|rich_rule|interface|masquerade|source|target'" - "result.msg == 'parameters are mutually exclusive: icmp_block|icmp_block_inversion|service|port|port_forward|rich_rule|interface|masquerade|source|target|default'"

View file

@ -0,0 +1,115 @@
# Test playbook for the firewalld module - zone default operations
# (c) 2022, Gregory Furlong <gnfzdz@fzdz.io>
# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
- name: Set default zone to trusted (default - true / state - enabled)
block:
- name: Update default zone to trusted
ansible.posix.firewalld:
zone: trusted
default: True
permanent: True
state: enabled
register: result
- name: Default zone is trusted
ansible.builtin.assert:
that:
- result is changed
- name: Update default zone to trusted (verify not changed)
ansible.posix.firewalld:
zone: trusted
default: True
permanent: True
state: enabled
register: result
- name: Default zone is trusted (verify not changed)
ansible.builtin.assert:
that:
- result is not changed
- name: Revert default zone to upstream default (default - false / state - enabled)
block:
- name: Revert default zone to upstream default
ansible.posix.firewalld:
zone: trusted
default: False
permanent: True
state: enabled
register: result
- name: Default zone is reverted
ansible.builtin.assert:
that:
- result is changed
- name: Revert default zone to upstream default (verify not changed)
ansible.posix.firewalld:
zone: trusted
default: False
permanent: True
state: enabled
register: result
- name: Default zone is reverted (verify not changed)
ansible.builtin.assert:
that:
- result is not changed
- name: Set default zone to trusted (default - false / state - disabled)
block:
- name: Update default zone to trusted
ansible.posix.firewalld:
zone: trusted
default: False
permanent: True
state: disabled
register: result
- name: Default zone is trusted
ansible.builtin.assert:
that:
- result is changed
- name: Update default zone to trusted (verify not changed)
ansible.posix.firewalld:
zone: trusted
default: False
permanent: True
state: disabled
register: result
- name: Default zone is trusted (verify not changed)
ansible.builtin.assert:
that:
- result is not changed
- name: Revert default zone to upstream default (default - true / state - disabled)
block:
- name: Revert default zone to upstream default
ansible.posix.firewalld:
zone: trusted
default: True
permanent: True
state: disabled
register: result
- name: Default zone is reverted
ansible.builtin.assert:
that:
- result is changed
- name: Revert default zone to upstream default (verify not changed)
ansible.posix.firewalld:
zone: trusted
default: True
permanent: True
state: disabled
register: result
- name: Default zone is reverted (verify not changed)
ansible.builtin.assert:
that:
- result is not changed