V1
This commit is contained in:
@@ -0,0 +1,392 @@
|
||||
#!/usr/bin/python
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# Copyright: (c) 2021, Hideki Saito <saito@fgrep.org>
|
||||
# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
|
||||
|
||||
from __future__ import (absolute_import, division, print_function)
|
||||
__metaclass__ = type
|
||||
|
||||
DOCUMENTATION = r'''
|
||||
---
|
||||
module: firewalld_info
|
||||
short_description: Gather information about firewalld
|
||||
description:
|
||||
- This module gathers information about firewalld rules.
|
||||
options:
|
||||
active_zones:
|
||||
description: Gather information about active zones.
|
||||
type: bool
|
||||
default: no
|
||||
zones:
|
||||
description:
|
||||
- Gather information about specific zones.
|
||||
- If only works if C(active_zones) is set to C(false).
|
||||
required: false
|
||||
type: list
|
||||
elements: str
|
||||
requirements:
|
||||
- firewalld >= 0.2.11
|
||||
- python-firewall
|
||||
- python-dbus
|
||||
author:
|
||||
- Hideki Saito (@saito-hideki)
|
||||
'''
|
||||
|
||||
EXAMPLES = r'''
|
||||
- name: Gather information about active zones
|
||||
ansible.posix.firewalld_info:
|
||||
active_zones: yes
|
||||
|
||||
- name: Gather information about specific zones
|
||||
ansible.posix.firewalld_info:
|
||||
zones:
|
||||
- public
|
||||
- external
|
||||
- internal
|
||||
'''
|
||||
|
||||
RETURN = r'''
|
||||
active_zones:
|
||||
description:
|
||||
- Gather active zones only if turn it C(true).
|
||||
returned: success
|
||||
type: bool
|
||||
sample: false
|
||||
collected_zones:
|
||||
description:
|
||||
- A list of collected zones.
|
||||
returned: success
|
||||
type: list
|
||||
sample: [external, internal]
|
||||
undefined_zones:
|
||||
description:
|
||||
- A list of undefined zones in C(zones) option.
|
||||
- C(undefined_zones) will be ignored for gathering process.
|
||||
returned: success
|
||||
type: list
|
||||
sample: [foo, bar]
|
||||
firewalld_info:
|
||||
description:
|
||||
- Returns various information about firewalld configuration.
|
||||
returned: success
|
||||
type: complex
|
||||
contains:
|
||||
version:
|
||||
description:
|
||||
- The version information of firewalld.
|
||||
returned: success
|
||||
type: str
|
||||
sample: 0.8.2
|
||||
default_zones:
|
||||
description:
|
||||
- The zone name of default zone.
|
||||
returned: success
|
||||
type: str
|
||||
sample: public
|
||||
zones:
|
||||
description:
|
||||
- A dict of zones to gather information.
|
||||
returned: success
|
||||
type: complex
|
||||
contains:
|
||||
zone:
|
||||
description:
|
||||
- The zone name registered in firewalld.
|
||||
returned: success
|
||||
type: complex
|
||||
sample: external
|
||||
contains:
|
||||
target:
|
||||
description:
|
||||
- A list of services in the zone.
|
||||
returned: success
|
||||
type: str
|
||||
sample: ACCEPT
|
||||
icmp_block_inversion:
|
||||
description:
|
||||
- The ICMP block inversion to block
|
||||
all ICMP requests.
|
||||
returned: success
|
||||
type: bool
|
||||
sample: false
|
||||
interfaces:
|
||||
description:
|
||||
- A list of network interfaces.
|
||||
returned: success
|
||||
type: list
|
||||
sample:
|
||||
- 'eth0'
|
||||
- 'eth1'
|
||||
sources:
|
||||
description:
|
||||
- A list of source network address.
|
||||
returned: success
|
||||
type: list
|
||||
sample:
|
||||
- '172.16.30.0/24'
|
||||
- '172.16.31.0/24'
|
||||
services:
|
||||
description:
|
||||
- A list of network services.
|
||||
returned: success
|
||||
type: list
|
||||
sample:
|
||||
- 'dhcp'
|
||||
- 'dns'
|
||||
- 'ssh'
|
||||
ports:
|
||||
description:
|
||||
- A list of network port with protocol.
|
||||
returned: success
|
||||
type: list
|
||||
sample:
|
||||
- - "22"
|
||||
- "tcp"
|
||||
- - "80"
|
||||
- "tcp"
|
||||
protocols:
|
||||
description:
|
||||
- A list of network protocol.
|
||||
returned: success
|
||||
type: list
|
||||
sample:
|
||||
- "icmp"
|
||||
- "ipv6-icmp"
|
||||
forward:
|
||||
description:
|
||||
- The network interface forwarding.
|
||||
- This parameter supports on python-firewall
|
||||
0.9.0(or later) and is not collected in earlier
|
||||
versions.
|
||||
returned: success
|
||||
type: bool
|
||||
sample: false
|
||||
masquerade:
|
||||
description:
|
||||
- The network interface masquerading.
|
||||
returned: success
|
||||
type: bool
|
||||
sample: false
|
||||
forward_ports:
|
||||
description:
|
||||
- A list of forwarding port pair with protocol.
|
||||
returned: success
|
||||
type: list
|
||||
sample:
|
||||
- "icmp"
|
||||
- "ipv6-icmp"
|
||||
source_ports:
|
||||
description:
|
||||
- A list of network source port with protocol.
|
||||
returned: success
|
||||
type: list
|
||||
sample:
|
||||
- - "30000"
|
||||
- "tcp"
|
||||
- - "30001"
|
||||
- "tcp"
|
||||
icmp_blocks:
|
||||
description:
|
||||
- A list of blocking icmp protocol.
|
||||
returned: success
|
||||
type: list
|
||||
sample:
|
||||
- "echo-request"
|
||||
rich_rules:
|
||||
description:
|
||||
- A list of rich language rule.
|
||||
returned: success
|
||||
type: list
|
||||
sample:
|
||||
- "rule protocol value=\"icmp\" reject"
|
||||
- "rule priority=\"32767\" reject"
|
||||
'''
|
||||
|
||||
from ansible.module_utils.basic import AnsibleModule, missing_required_lib
|
||||
from ansible.module_utils.six import raise_from
|
||||
from ansible.module_utils._text import to_native
|
||||
from ansible_collections.ansible.posix.plugins.module_utils.version import StrictVersion
|
||||
|
||||
|
||||
try:
|
||||
import dbus
|
||||
HAS_DBUS = True
|
||||
except ImportError:
|
||||
HAS_DBUS = False
|
||||
|
||||
try:
|
||||
import firewall.client as fw_client
|
||||
import firewall.config as fw_config
|
||||
HAS_FIREWALLD = True
|
||||
except ImportError:
|
||||
HAS_FIREWALLD = False
|
||||
|
||||
|
||||
def get_version():
|
||||
return fw_config.VERSION
|
||||
|
||||
|
||||
def get_active_zones(client):
|
||||
return client.getActiveZones().keys()
|
||||
|
||||
|
||||
def get_all_zones(client):
|
||||
return client.getZones()
|
||||
|
||||
|
||||
def get_default_zone(client):
|
||||
return client.getDefaultZone()
|
||||
|
||||
|
||||
def get_zone_settings(client, zone):
|
||||
return client.getZoneSettings(zone)
|
||||
|
||||
|
||||
def get_zone_target(zone_settings):
|
||||
return zone_settings.getTarget()
|
||||
|
||||
|
||||
def get_zone_icmp_block_inversion(zone_settings):
|
||||
return zone_settings.getIcmpBlockInversion()
|
||||
|
||||
|
||||
def get_zone_interfaces(zone_settings):
|
||||
return zone_settings.getInterfaces()
|
||||
|
||||
|
||||
def get_zone_sources(zone_settings):
|
||||
return zone_settings.getSources()
|
||||
|
||||
|
||||
def get_zone_services(zone_settings):
|
||||
return zone_settings.getServices()
|
||||
|
||||
|
||||
def get_zone_ports(zone_settings):
|
||||
return zone_settings.getPorts()
|
||||
|
||||
|
||||
def get_zone_protocols(zone_settings):
|
||||
return zone_settings.getProtocols()
|
||||
|
||||
|
||||
# This function supports python-firewall 0.9.0(or later).
|
||||
def get_zone_forward(zone_settings):
|
||||
return zone_settings.getForward()
|
||||
|
||||
|
||||
def get_zone_masquerade(zone_settings):
|
||||
return zone_settings.getMasquerade()
|
||||
|
||||
|
||||
def get_zone_forward_ports(zone_settings):
|
||||
return zone_settings.getForwardPorts()
|
||||
|
||||
|
||||
def get_zone_source_ports(zone_settings):
|
||||
return zone_settings.getSourcePorts()
|
||||
|
||||
|
||||
def get_zone_icmp_blocks(zone_settings):
|
||||
return zone_settings.getIcmpBlocks()
|
||||
|
||||
|
||||
def get_zone_rich_rules(zone_settings):
|
||||
return zone_settings.getRichRules()
|
||||
|
||||
|
||||
def main():
|
||||
module_args = dict(
|
||||
active_zones=dict(required=False, type='bool', default=False),
|
||||
zones=dict(required=False, type='list', elements='str'),
|
||||
)
|
||||
|
||||
module = AnsibleModule(
|
||||
argument_spec=module_args,
|
||||
supports_check_mode=True,
|
||||
)
|
||||
|
||||
firewalld_info = dict()
|
||||
result = dict(
|
||||
changed=False,
|
||||
active_zones=module.params['active_zones'],
|
||||
collected_zones=list(),
|
||||
undefined_zones=list(),
|
||||
warnings=list(),
|
||||
)
|
||||
|
||||
# Exit with failure message if requirements modules are not installed.
|
||||
if not HAS_DBUS:
|
||||
module.fail_json(msg=missing_required_lib('python-dbus'))
|
||||
if not HAS_FIREWALLD:
|
||||
module.fail_json(msg=missing_required_lib('python-firewall'))
|
||||
|
||||
# If you want to show warning messages in the task running process,
|
||||
# you can append the message to the 'warn' list.
|
||||
warn = list()
|
||||
|
||||
try:
|
||||
client = fw_client.FirewallClient()
|
||||
|
||||
# Gather general information of firewalld.
|
||||
firewalld_info['version'] = get_version()
|
||||
firewalld_info['default_zone'] = get_default_zone(client)
|
||||
|
||||
# Gather information for zones.
|
||||
zones_info = dict()
|
||||
collect_zones = list()
|
||||
ignore_zones = list()
|
||||
if module.params['active_zones']:
|
||||
collect_zones = get_active_zones(client)
|
||||
elif module.params['zones']:
|
||||
all_zones = get_all_zones(client)
|
||||
specified_zones = module.params['zones']
|
||||
collect_zones = list(set(specified_zones) & set(all_zones))
|
||||
ignore_zones = list(set(specified_zones) - set(collect_zones))
|
||||
warn.append(
|
||||
'Please note: zone:(%s) have been ignored in the gathering process.' % ','.join(ignore_zones))
|
||||
else:
|
||||
collect_zones = get_all_zones(client)
|
||||
|
||||
for zone in collect_zones:
|
||||
# Gather settings for each zone based on the output of
|
||||
# 'firewall-cmd --info-zone=<ZONE>' command.
|
||||
zone_info = dict()
|
||||
zone_settings = get_zone_settings(client, zone)
|
||||
zone_info['target'] = get_zone_target(zone_settings)
|
||||
zone_info['icmp_block_inversion'] = get_zone_icmp_block_inversion(zone_settings)
|
||||
zone_info['interfaces'] = get_zone_interfaces(zone_settings)
|
||||
zone_info['sources'] = get_zone_sources(zone_settings)
|
||||
zone_info['services'] = get_zone_services(zone_settings)
|
||||
zone_info['ports'] = get_zone_ports(zone_settings)
|
||||
zone_info['protocols'] = get_zone_protocols(zone_settings)
|
||||
zone_info['masquerade'] = get_zone_masquerade(zone_settings)
|
||||
zone_info['forward_ports'] = get_zone_forward_ports(zone_settings)
|
||||
zone_info['source_ports'] = get_zone_source_ports(zone_settings)
|
||||
zone_info['icmp_blocks'] = get_zone_icmp_blocks(zone_settings)
|
||||
zone_info['rich_rules'] = get_zone_rich_rules(zone_settings)
|
||||
|
||||
# The 'forward' parameter supports on python-firewall 0.9.0(or later).
|
||||
if StrictVersion(firewalld_info['version']) >= StrictVersion('0.9.0'):
|
||||
zone_info['forward'] = get_zone_forward(zone_settings)
|
||||
|
||||
zones_info[zone] = zone_info
|
||||
firewalld_info['zones'] = zones_info
|
||||
except AttributeError as e:
|
||||
module.fail_json(msg=('firewalld probably not be running, Or the following method '
|
||||
'is not supported with your python-firewall version. (Error: %s)') % to_native(e))
|
||||
except dbus.exceptions.DBusException as e:
|
||||
module.fail_json(msg=('Unable to gather firewalld settings.'
|
||||
' You may need to run as the root user or'
|
||||
' use become. (Error: %s)' % to_native(e)))
|
||||
|
||||
result['collected_zones'] = collect_zones
|
||||
result['undefined_zones'] = ignore_zones
|
||||
result['firewalld_info'] = firewalld_info
|
||||
result['warnings'] = warn
|
||||
module.exit_json(**result)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
Reference in New Issue
Block a user