This commit is contained in:
Gregory Furlong 2023-02-26 04:52:04 +00:00 committed by GitHub
commit 3cec20e656
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 190 additions and 2 deletions

View file

@ -106,6 +106,11 @@ options:
description: description:
- The masquerade setting you would like to enable/disable to/from zones within firewalld. - The masquerade setting you would like to enable/disable to/from zones within firewalld.
type: str type: str
default:
description:
- Indicates that the targeted zone should be set as firewalld's default zone.
- This change must always be both immediate (when firewalld is running) and permanent.
type: bool
offline: offline:
description: description:
- Whether to run this module even when firewalld is offline. - Whether to run this module even when firewalld is offline.
@ -213,6 +218,13 @@ EXAMPLES = r'''
permanent: true permanent: true
immediate: true immediate: true
state: enabled state: enabled
- name: Set the default zone to 'trusted'
ansible.builtin.firewalld:
zone: trusted
permanent: true
default: true
state: enabled
''' '''
from ansible.module_utils.basic import AnsibleModule from ansible.module_utils.basic import AnsibleModule
@ -222,6 +234,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
@ -704,6 +717,47 @@ class ZoneTransaction(FirewallTransaction):
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)
if (not permanent) or not (fw_offline or immediate):
self.module.fail_json(msg="Default zone changes must be permanent and when daemon is online must also be immediate")
def get_enabled_immediate(self):
return self.fw.getDefaultZone() == self.zone
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):
pass # permanent default zone change will also apply immediately to a running daemon
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):
pass # permanent default zone change will also apply immediately to a running daemon
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):
""" """
ForwardPortTransaction ForwardPortTransaction
@ -759,6 +813,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%%']),
), ),
@ -766,11 +821,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']
], ],
) )
@ -780,6 +836,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)
@ -1016,6 +1073,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