diff --git a/tests/integration/targets/vyos_interface/aliases b/plugins/module_utils/network/vyos/argspec/firewall_global/__init__.py similarity index 100% rename from tests/integration/targets/vyos_interface/aliases rename to plugins/module_utils/network/vyos/argspec/firewall_global/__init__.py diff --git a/plugins/module_utils/network/vyos/argspec/firewall_global/firewall_global.py b/plugins/module_utils/network/vyos/argspec/firewall_global/firewall_global.py new file mode 100644 index 0000000..4c26773 --- /dev/null +++ b/plugins/module_utils/network/vyos/argspec/firewall_global/firewall_global.py @@ -0,0 +1,152 @@ +# +# -*- coding: utf-8 -*- +# Copyright 2019 Red Hat +# GNU General Public License v3.0+ +# (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) + +############################################# +# WARNING # +############################################# +# +# This file is auto generated by the resource +# module builder playbook. +# +# Do not edit this file manually. +# +# Changes to this file will be over written +# by the resource module builder. +# +# Changes should be made in the model used to +# generate this file or in the resource module +# builder template. +# +############################################# +""" +The arg spec for the vyos_firewall_global module +""" + +from __future__ import absolute_import, division, print_function + +__metaclass__ = type + + +class Firewall_globalArgs(object): # pylint: disable=R0903 + """The arg spec for the vyos_firewall_global module + """ + + def __init__(self, **kwargs): + pass + + argument_spec = { + "config": { + "options": { + "config_trap": {"type": "bool"}, + "group": { + "options": { + "address_group": { + "elements": "dict", + "options": { + "description": {"type": "str"}, + "members": { + "elements": "dict", + "options": {"address": {"type": "str"}}, + "type": "list", + }, + "name": {"required": True, "type": "str"}, + }, + "type": "list", + }, + "network_group": { + "elements": "dict", + "options": { + "description": {"type": "str"}, + "members": { + "elements": "dict", + "options": {"address": {"type": "str"}}, + "type": "list", + }, + "name": {"required": True, "type": "str"}, + }, + "type": "list", + }, + "port_group": { + "elements": "dict", + "options": { + "description": {"type": "str"}, + "members": { + "elements": "dict", + "options": {"port": {"type": "str"}}, + "type": "list", + }, + "name": {"required": True, "type": "str"}, + }, + "type": "list", + }, + }, + "type": "dict", + }, + "log_martians": {"type": "bool"}, + "ping": { + "options": { + "all": {"type": "bool"}, + "broadcast": {"type": "bool"}, + }, + "type": "dict", + }, + "route_redirects": { + "elements": "dict", + "options": { + "afi": { + "choices": ["ipv4", "ipv6"], + "required": True, + "type": "str", + }, + "icmp_redirects": { + "options": { + "receive": {"type": "bool"}, + "send": {"type": "bool"}, + }, + "type": "dict", + }, + "ip_src_route": {"type": "bool"}, + }, + "type": "list", + }, + "state_policy": { + "elements": "dict", + "options": { + "action": { + "choices": ["accept", "drop", "reject"], + "type": "str", + }, + "connection_type": { + "choices": ["established", "invalid", "related"], + "type": "str", + }, + "log": {"type": "bool"}, + }, + "type": "list", + }, + "syn_cookies": {"type": "bool"}, + "twa_hazards_protection": {"type": "bool"}, + "validation": { + "choices": ["strict", "loose", "disable"], + "type": "str", + }, + }, + "type": "dict", + }, + "running_config": {"type": "str"}, + "state": { + "choices": [ + "merged", + "replaced", + "deleted", + "gathered", + "rendered", + "parsed", + ], + "default": "merged", + "type": "str", + }, + } # pylint: disable=C0301 diff --git a/tests/integration/targets/vyos_l3_interface/aliases b/plugins/module_utils/network/vyos/config/firewall_global/__init__.py similarity index 100% rename from tests/integration/targets/vyos_l3_interface/aliases rename to plugins/module_utils/network/vyos/config/firewall_global/__init__.py diff --git a/plugins/module_utils/network/vyos/config/firewall_global/firewall_global.py b/plugins/module_utils/network/vyos/config/firewall_global/firewall_global.py new file mode 100644 index 0000000..afc9853 --- /dev/null +++ b/plugins/module_utils/network/vyos/config/firewall_global/firewall_global.py @@ -0,0 +1,810 @@ +# +# -*- coding: utf-8 -*- +# Copyright 2019 Red Hat +# GNU General Public License v3.0+ +# (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) +""" +The vyos_firewall_global class +It is in this file where the current configuration (as dict) +is compared to the provided configuration (as dict) and the command set +necessary to bring the current configuration to it's desired end-state is +created +""" +from __future__ import absolute_import, division, print_function + +__metaclass__ = type + +from copy import deepcopy +from ansible_collections.ansible.netcommon.plugins.module_utils.network.common.cfg.base import ( + ConfigBase, +) +from ansible_collections.ansible.netcommon.plugins.module_utils.network.common.utils import ( + to_list, + remove_empties, +) +from ansible_collections.vyos.vyos.plugins.module_utils.network.vyos.facts.facts import ( + Facts, +) +from ansible.module_utils.six import iteritems +from ansible_collections.vyos.vyos.plugins.module_utils.network.vyos.utils.utils import ( + list_diff_want_only, +) + + +class Firewall_global(ConfigBase): + """ + The vyos_firewall_global class + """ + + gather_subset = [ + "!all", + "!min", + ] + + gather_network_resources = [ + "firewall_global", + ] + + def __init__(self, module): + super(Firewall_global, self).__init__(module) + + def get_firewall_global_facts(self, data=None): + """ Get the 'facts' (the current configuration) + + :rtype: A dictionary + :returns: The current configuration as a dictionary + """ + facts, _warnings = Facts(self._module).get_facts( + self.gather_subset, self.gather_network_resources, data=data + ) + firewall_global_facts = facts["ansible_network_resources"].get( + "firewall_global" + ) + if not firewall_global_facts: + return [] + return firewall_global_facts + + def execute_module(self): + """ Execute the module + + :rtype: A dictionary + :returns: The result from module execution + """ + result = {"changed": False} + warnings = list() + commands = list() + + if self.state in self.ACTION_STATES: + existing_firewall_global_facts = self.get_firewall_global_facts() + else: + existing_firewall_global_facts = [] + + if self.state in self.ACTION_STATES or self.state == "rendered": + commands.extend(self.set_config(existing_firewall_global_facts)) + + if commands and self.state in self.ACTION_STATES: + if not self._module.check_mode: + self._connection.edit_config(commands) + result["changed"] = True + + if self.state in self.ACTION_STATES: + result["commands"] = commands + + if self.state in self.ACTION_STATES or self.state == "gathered": + changed_firewall_global_facts = self.get_firewall_global_facts() + elif self.state == "rendered": + result["rendered"] = commands + elif self.state == "parsed": + running_config = self._module.params["running_config"] + if not running_config: + self._module.fail_json( + msg="value of running_config parameter must not be empty for state parsed" + ) + result["parsed"] = self.get_firewall_global_facts( + data=running_config + ) + else: + changed_firewall_global_facts = [] + + if self.state in self.ACTION_STATES: + result["before"] = existing_firewall_global_facts + if result["changed"]: + result["after"] = changed_firewall_global_facts + elif self.state == "gathered": + result["gathered"] = changed_firewall_global_facts + + result["warnings"] = warnings + return result + + def set_config(self, existing_firewall_global_facts): + """ Collect the configuration from the args passed to the module, + collect the current configuration (as a dict from facts) + + :rtype: A list + :returns: the commands necessary to migrate the current configuration + to the desired configuration + """ + want = self._module.params["config"] + have = existing_firewall_global_facts + resp = self.set_state(want, have) + return to_list(resp) + + def set_state(self, w, h): + """ Select the appropriate function based on the state provided + + :param want: the desired configuration as a dictionary + :param have: the current configuration as a dictionary + :rtype: A list + :returns: the commands necessary to migrate the current configuration + to the desired configuration + """ + commands = [] + if self.state in ("merged", "replaced", "rendered") and not w: + self._module.fail_json( + msg="value of config parameter must not be empty for state {0}".format( + self.state + ) + ) + if self.state == "deleted": + commands.extend(self._state_deleted(want=None, have=h)) + elif w: + if self.state == "merged" or self.state == "rendered": + commands.extend(self._state_merged(w, h)) + elif self.state == "replaced": + commands.extend(self._state_replaced(w, h)) + return commands + + def _state_replaced(self, want, have): + """ The command generator when state is replaced + :rtype: A list + :returns: the commands necessary to migrate the current configuration + to the desired configuration + """ + commands = [] + if have: + commands.extend(self._state_deleted(have, want)) + commands.extend(self._state_merged(want, have)) + return commands + + def _state_merged(self, want, have): + """ The command generator when state is merged + + :rtype: A list + :returns: the commands necessary to merge the provided into + the current configuration + """ + commands = [] + commands.extend(self._add_global_attr(want, have)) + return commands + + def _state_deleted(self, want, have): + """ The command generator when state is deleted + + :rtype: A list + :returns: the commands necessary to remove the current configuration + of the provided objects + """ + commands = [] + b_set = ( + "config_trap", + "validation", + "log_martians", + "syn_cookies", + "twa_hazards_protection", + ) + if want: + for key, val in iteritems(want): + if val and key in b_set and not have: + commands.append(self._form_attr_cmd(attr=key, opr=False)) + elif ( + val + and key in b_set + and have + and key in have + and have[key] != val + ): + commands.append(self._form_attr_cmd(attr=key, opr=False)) + else: + commands.extend(self._render_attr_config(want, have, key)) + elif not want and have: + commands.append(self._compute_command(opr=False)) + elif have: + for key, val in iteritems(have): + if val and key in b_set: + commands.append(self._form_attr_cmd(attr=key, opr=False)) + else: + commands.extend(self._render_attr_config(want, have, key)) + return commands + + def _render_attr_config(self, w, h, key, opr=False): + """ + This function invoke the function to extend commands + based on the key. + :param w: the desired configuration. + :param h: the current configuration. + :param key: attribute name + :param opr: operation + :return: list of commands + """ + commands = [] + if key == "ping": + commands.extend(self._render_ping(key, w, h, opr=opr)) + elif key == "group": + commands.extend(self._render_group(key, w, h, opr=opr)) + elif key == "state_policy": + commands.extend(self._render_state_policy(key, w, h, opr=opr)) + elif key == "route_redirects": + commands.extend(self._render_route_redirects(key, w, h, opr=opr)) + return commands + + def _add_global_attr(self, w, h, opr=True): + """ + This function forms the set/delete commands based on the 'opr' type + for firewall_global attributes. + :param w: the desired config. + :param h: the target config. + :param opr: True/False. + :return: generated commands list. + """ + commands = [] + w_fg = deepcopy(remove_empties(w)) + l_set = ( + "config_trap", + "validation", + "log_martians", + "syn_cookies", + "twa_hazards_protection", + ) + if w_fg: + for key, val in iteritems(w_fg): + if ( + opr + and key in l_set + and not (h and self._is_w_same(w_fg, h, key)) + ): + commands.append( + self._form_attr_cmd( + attr=key, val=self._bool_to_str(val), opr=opr + ) + ) + elif not opr: + if key and self._is_del(l_set, h): + commands.append( + self._form_attr_cmd( + attr=key, key=self._bool_to_str(val), opr=opr + ) + ) + continue + elif ( + key in l_set + and not (h and self._in_target(h, key)) + and not self._is_del(l_set, h) + ): + commands.append( + self._form_attr_cmd( + attr=key, val=self._bool_to_str(val), opr=opr + ) + ) + else: + commands.extend( + self._render_attr_config(w_fg, h, key, opr) + ) + return commands + + def _render_ping(self, attr, w, h, opr): + """ + This function forms the commands for 'ping' attributes based on the 'opr'. + :param attr: attribute name. + :param w: the desired configuration. + :param h: the target config. + :param opr: True/False. + :return: generated list of commands. + """ + commands = [] + h_ping = {} + l_set = ("all", "broadcast") + if h: + h_ping = h.get(attr) or {} + if self._is_root_del(w[attr], h_ping, attr): + for item, value in iteritems(h[attr]): + if not opr and item in l_set: + commands.append(self._form_attr_cmd(attr=item, opr=opr)) + elif w[attr]: + if h and attr in h.keys(): + h_ping = h.get(attr) or {} + for item, value in iteritems(w[attr]): + if ( + opr + and item in l_set + and not (h_ping and self._is_w_same(w[attr], h_ping, item)) + ): + commands.append( + self._form_attr_cmd( + attr=item, val=self._bool_to_str(value), opr=opr + ) + ) + elif ( + not opr + and item in l_set + and not (h_ping and self._is_w_same(w[attr], h_ping, item)) + ): + commands.append(self._form_attr_cmd(attr=item, opr=opr)) + return commands + + def _render_group(self, attr, w, h, opr): + """ + This function forms the commands for 'group' attribute based on the 'opr'. + :param attr: attribute name. + :param w: base config. + :param h: target config. + :param opr: True/False. + :return: generated list of commands. + """ + commands = [] + h_grp = {} + if not opr and self._is_root_del(h, w, attr): + commands.append(self._form_attr_cmd(attr=attr, opr=opr)) + else: + if h: + h_grp = h.get("group") or {} + if w: + commands.extend( + self._render_grp_mem("port-group", w["group"], h_grp, opr) + ) + commands.extend( + self._render_grp_mem( + "address_group", w["group"], h_grp, opr + ) + ) + commands.extend( + self._render_grp_mem( + "network_group", w["group"], h_grp, opr + ) + ) + return commands + + def _render_grp_mem(self, attr, w, h, opr): + """ + This function forms the commands for group list/members attributes based on the 'opr'. + :param attr: attribute name. + :param w: the desired config. + :param h: the target config. + :param opr: True/False. + :return: generated list of commands. + """ + commands = [] + h_grp = [] + w_grp = [] + l_set = ("name", "description") + if w: + w_grp = w.get(attr) or [] + if h: + h_grp = h.get(attr) or [] + + if w_grp: + for want in w_grp: + cmd = self._compute_command(key="group", attr=attr, opr=opr) + h = self.search_attrib_in_have(h_grp, want, "name") + for key, val in iteritems(want): + if val: + if ( + opr + and key in l_set + and not (h and self._is_w_same(want, h, key)) + ): + if key == "name": + commands.append(cmd + " " + str(val)) + else: + commands.append( + cmd + + " " + + want["name"] + + " " + + key + + " '" + + str(want[key]) + + "'" + ) + elif not opr and key in l_set: + if key == "name" and self._is_grp_del( + h, want, key + ): + commands.append(cmd + " " + want["name"]) + continue + elif not ( + h and self._in_target(h, key) + ) and not self._is_grp_del(h, want, key): + commands.append( + cmd + " " + want["name"] + " " + key + ) + elif key == "members": + commands.extend( + self._render_ports_addrs( + key, want, h, opr, cmd, want["name"], attr + ) + ) + return commands + + def _render_ports_addrs(self, attr, w, h, opr, cmd, name, type): + """ + This function forms the commands for port/address/network group members + based on the 'opr'. + :param attr: attribute name. + :param w: the desired config. + :param h: the target config. + :param cmd: commands to be prepend. + :param name: name of group. + :param type: group type. + :return: generated list of commands. + """ + commands = [] + have = [] + if w: + want = w.get(attr) or [] + if h: + have = h.get(attr) or [] + + if want: + if opr: + members = list_diff_want_only(want, have) + for member in members: + commands.append( + cmd + + " " + + name + + " " + + self._grp_type(type) + + " " + + member[self._get_mem_type(type)] + ) + elif not opr and have: + members = list_diff_want_only(want, have) + for member in members: + commands.append( + cmd + + " " + + name + + " " + + self._grp_type(type) + + " " + + member[self._get_mem_type(type)] + ) + return commands + + def _get_mem_type(self, group): + """ + This function returns the member type + based on the type of group. + """ + return "port" if group == "port_group" else "address" + + def _render_state_policy(self, attr, w, h, opr): + """ + This function forms the commands for 'state-policy' attributes + based on the 'opr'. + :param attr: attribute name. + :param w: the desired config. + :param h: the target config. + :param opr: True/False. + :return: generated list of commands. + """ + commands = [] + have = [] + l_set = ("log", "action", "connection_type") + if not opr and self._is_root_del(h, w, attr): + commands.append(self._form_attr_cmd(attr=attr, opr=opr)) + else: + w_sp = deepcopy(remove_empties(w)) + want = w_sp.get(attr) or [] + if h: + have = h.get(attr) or [] + if want: + for w in want: + h = self.search_attrib_in_have(have, w, "connection_type") + for key, val in iteritems(w): + if val and key != "connection_type": + if ( + opr + and key in l_set + and not (h and self._is_w_same(w, h, key)) + ): + commands.append( + self._form_attr_cmd( + key=attr + " " + w["connection_type"], + attr=key, + val=self._bool_to_str(val), + opr=opr, + ) + ) + elif not opr and key in l_set: + if not ( + h and self._in_target(h, key) + ) and not self._is_del(l_set, h): + if key == "action": + commands.append( + self._form_attr_cmd( + attr=attr + + " " + + w["connection_type"], + opr=opr, + ) + ) + else: + commands.append( + self._form_attr_cmd( + attr=attr + + " " + + w["connection_type"], + val=self._bool_to_str(val), + opr=opr, + ) + ) + return commands + + def _render_route_redirects(self, attr, w, h, opr): + """ + This function forms the commands for 'route_redirects' attributes based on the 'opr'. + :param attr: attribute name. + :param w: the desired config. + :param h: the target config. + :param opr: True/False. + :return: generated list of commands. + """ + commands = [] + have = [] + l_set = ("afi", "ip_src_route") + + if w: + want = w.get(attr) or [] + if h: + have = h.get(attr) or [] + + if want: + for w in want: + h = self.search_attrib_in_have(have, w, "afi") + for key, val in iteritems(w): + if val and key != "afi": + if ( + opr + and key in l_set + and not (h and self._is_w_same(w, h, key)) + ): + commands.append( + self._form_attr_cmd( + attr=key, + val=self._bool_to_str(val), + opr=opr, + ) + ) + elif not opr and key in l_set: + if self._is_del(l_set, h): + commands.append( + self._form_attr_cmd( + attr=key, + val=self._bool_to_str(val), + opr=opr, + ) + ) + continue + elif not ( + h and self._in_target(h, key) + ) and not self._is_del(l_set, h): + commands.append( + self._form_attr_cmd( + attr=key, + val=self._bool_to_str(val), + opr=opr, + ) + ) + elif key == "icmp_redirects": + commands.extend( + self._render_icmp_redirects(key, w, h, opr) + ) + return commands + + def _render_icmp_redirects(self, attr, w, h, opr): + """ + This function forms the commands for 'icmp_redirects' attributes + based on the 'opr'. + :param attr: attribute name. + :param w: the desired config. + :param h: the target config. + :param opr: True/False. + :return: generated list of commands. + """ + commands = [] + h_red = {} + l_set = ("send", "receive") + if w[attr]: + if h and attr in h.keys(): + h_red = h.get(attr) or {} + for item, value in iteritems(w[attr]): + if ( + opr + and item in l_set + and not (h_red and self._is_w_same(w[attr], h_red, item)) + ): + commands.append( + self._form_attr_cmd( + attr=item, val=self._bool_to_str(value), opr=opr + ) + ) + elif ( + not opr + and item in l_set + and not (h_red and self._is_w_same(w[attr], h_red, item)) + ): + commands.append(self._form_attr_cmd(attr=item, opr=opr)) + return commands + + def search_attrib_in_have(self, have, want, attr): + """ + This function returns the attribute if it is present in target config. + :param have: the target config. + :param want: the desired config. + :param attr: attribute name . + :return: attribute/None + """ + if have: + for h in have: + if h[attr] == want[attr]: + return h + return None + + def _form_attr_cmd(self, key=None, attr=None, val=None, opr=True): + """ + This function forms the command for leaf attribute. + :param key: parent key. + :param attr: attribute name + :param value: value + :param opr: True/False. + :return: generated command. + """ + command = self._compute_command( + key=key, attr=self._map_attrib(attr), val=val, opr=opr + ) + return command + + def _compute_command( + self, key=None, attr=None, val=None, remove=False, opr=True + ): + """ + This function construct the add/delete command based on passed attributes. + :param key: parent key. + :param attr: attribute name + :param value: value + :param remove: True/False. + :param opr: True/False. + :return: generated command. + """ + if remove or not opr: + cmd = "delete firewall " + else: + cmd = "set firewall " + if key: + cmd += key.replace("_", "-") + " " + if attr: + cmd += attr.replace("_", "-") + if val and opr: + cmd += " '" + str(val) + "'" + return cmd + + def _bool_to_str(self, val): + """ + This function converts the bool value into string. + :param val: bool value. + :return: enable/disable. + """ + return ( + "enable" + if str(val) == "True" + else "disable" + if str(val) == "False" + else val + ) + + def _grp_type(self, val): + """ + This function returns the group member type based on value argument. + :param val: value. + :return: member type. + """ + return ( + "address" + if val == "address_group" + else "network" + if val == "network_group" + else "port" + ) + + def _is_w_same(self, w, h, key): + """ + This function checks whether the key value is same in desired and + target config dictionary. + :param w: base config. + :param h: target config. + :param key:attribute name. + :return: True/False. + """ + return True if h and key in h and h[key] == w[key] else False + + def _in_target(self, h, key): + """ + This function checks whether the target exist and key present in target config. + :param h: target config. + :param key: attribute name. + :return: True/False. + """ + return True if h and key in h else False + + def _is_grp_del(self, w, h, key): + """ + This function checks whether group needed to be deleted based on + desired and target configs. + :param w: the desired config. + :param h: the target config. + :param key: group name. + :return: True/False. + """ + return ( + True + if h and key in h and (not w or key not in w or not w[key]) + else False + ) + + def _is_root_del(self, w, h, key): + """ + This function checks whether a root attribute which can have + further child attributes needed to be deleted. + :param w: the desired config. + :param h: the target config. + :param key: attribute name. + :return: True/False. + """ + return ( + True + if h and key in h and (not w or key not in w or not w[key]) + else False + ) + + def _is_del(self, b_set, h, key="number"): + """ + This function checks whether attribute needs to be deleted + when operation is false and attribute present in present target config. + :param b_set: attribute set. + :param h: target config. + :param key: number. + :return: True/False. + """ + return key in b_set and not (h and self._in_target(h, key)) + + def _map_attrib(self, attrib, type=None): + """ + - This function construct the regex string. + - replace the underscore with hyphen. + :param attrib: attribute + :return: regex string + """ + regex = attrib.replace("_", "-") + if attrib == "send": + if type == "ipv6": + regex = "ipv6-send-redirects" + else: + regex = "send-redirects" + elif attrib == "ip_src_route": + if type == "ipv6": + regex = "ipv6-src-route" + elif attrib == "receive": + if type == "ipv6": + regex = "ipv6-receive-redirects" + else: + regex = "receive-redirects" + elif attrib == "disabled": + regex = "disable" + elif attrib == "all": + regex = "all-ping" + elif attrib == "broadcast": + regex = "broadcast-ping" + elif attrib == "validation": + regex = "source-validation" + return regex diff --git a/plugins/module_utils/network/vyos/facts/facts.py b/plugins/module_utils/network/vyos/facts/facts.py index 8f0a3bb..6e6a82b 100644 --- a/plugins/module_utils/network/vyos/facts/facts.py +++ b/plugins/module_utils/network/vyos/facts/facts.py @@ -1,83 +1,87 @@ # Copyright 2019 Red Hat # GNU General Public License v3.0+ # (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) """ The facts class for vyos this file validates each subset of facts and selectively calls the appropriate facts gathering function """ from __future__ import absolute_import, division, print_function __metaclass__ = type from ansible_collections.ansible.netcommon.plugins.module_utils.network.common.facts.facts import ( FactsBase, ) from ansible_collections.vyos.vyos.plugins.module_utils.network.vyos.facts.interfaces.interfaces import ( InterfacesFacts, ) from ansible_collections.vyos.vyos.plugins.module_utils.network.vyos.facts.l3_interfaces.l3_interfaces import ( L3_interfacesFacts, ) from ansible_collections.vyos.vyos.plugins.module_utils.network.vyos.facts.lag_interfaces.lag_interfaces import ( Lag_interfacesFacts, ) from ansible_collections.vyos.vyos.plugins.module_utils.network.vyos.facts.lldp_global.lldp_global import ( Lldp_globalFacts, ) from ansible_collections.vyos.vyos.plugins.module_utils.network.vyos.facts.lldp_interfaces.lldp_interfaces import ( Lldp_interfacesFacts, ) from ansible_collections.vyos.vyos.plugins.module_utils.network.vyos.facts.firewall_rules.firewall_rules import ( Firewall_rulesFacts, ) from ansible_collections.vyos.vyos.plugins.module_utils.network.vyos.facts.static_routes.static_routes import ( Static_routesFacts, ) +from ansible_collections.vyos.vyos.plugins.module_utils.network.vyos.facts.firewall_global.firewall_global import ( + Firewall_globalFacts, +) from ansible_collections.vyos.vyos.plugins.module_utils.network.vyos.facts.legacy.base import ( Default, Neighbors, Config, ) FACT_LEGACY_SUBSETS = dict(default=Default, neighbors=Neighbors, config=Config) FACT_RESOURCE_SUBSETS = dict( interfaces=InterfacesFacts, l3_interfaces=L3_interfacesFacts, lag_interfaces=Lag_interfacesFacts, lldp_global=Lldp_globalFacts, lldp_interfaces=Lldp_interfacesFacts, static_routes=Static_routesFacts, firewall_rules=Firewall_rulesFacts, + firewall_global=Firewall_globalFacts, ) class Facts(FactsBase): """ The fact class for vyos """ VALID_LEGACY_GATHER_SUBSETS = frozenset(FACT_LEGACY_SUBSETS.keys()) VALID_RESOURCE_SUBSETS = frozenset(FACT_RESOURCE_SUBSETS.keys()) def __init__(self, module): super(Facts, self).__init__(module) def get_facts( self, legacy_facts_type=None, resource_facts_type=None, data=None ): """ Collect the facts for vyos :param legacy_facts_type: List of legacy facts types :param resource_facts_type: List of resource fact types :param data: previously collected conf :rtype: dict :return: the facts gathered """ if self.VALID_RESOURCE_SUBSETS: self.get_network_resources_facts( FACT_RESOURCE_SUBSETS, resource_facts_type, data ) if self.VALID_LEGACY_GATHER_SUBSETS: self.get_network_legacy_facts( FACT_LEGACY_SUBSETS, legacy_facts_type ) return self.ansible_facts, self._warnings diff --git a/tests/integration/targets/vyos_linkagg/aliases b/plugins/module_utils/network/vyos/facts/firewall_global/__init__.py similarity index 100% rename from tests/integration/targets/vyos_linkagg/aliases rename to plugins/module_utils/network/vyos/facts/firewall_global/__init__.py diff --git a/plugins/module_utils/network/vyos/facts/firewall_global/firewall_global.py b/plugins/module_utils/network/vyos/facts/firewall_global/firewall_global.py new file mode 100644 index 0000000..0823259 --- /dev/null +++ b/plugins/module_utils/network/vyos/facts/firewall_global/firewall_global.py @@ -0,0 +1,388 @@ +# +# -*- coding: utf-8 -*- +# Copyright 2019 Red Hat +# GNU General Public License v3.0+ +# (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) +""" +The vyos firewall_global fact class +It is in this file the configuration is collected from the device +for a given resource, parsed, and the facts tree is populated +based on the configuration. +""" +from __future__ import absolute_import, division, print_function + +__metaclass__ = type + +from copy import deepcopy +from re import findall, search, M +from ansible_collections.ansible.netcommon.plugins.module_utils.network.common import ( + utils, +) +from ansible_collections.vyos.vyos.plugins.module_utils.network.vyos.argspec.firewall_global.firewall_global import ( + Firewall_globalArgs, +) + + +class Firewall_globalFacts(object): + """ The vyos firewall_global fact class + """ + + def __init__(self, module, subspec="config", options="options"): + self._module = module + self.argument_spec = Firewall_globalArgs.argument_spec + spec = deepcopy(self.argument_spec) + if subspec: + if options: + facts_argument_spec = spec[subspec][options] + else: + facts_argument_spec = spec[subspec] + else: + facts_argument_spec = spec + + self.generated_spec = utils.generate_dict(facts_argument_spec) + + def get_device_data(self, connection): + return connection.get_config() + + def populate_facts(self, connection, ansible_facts, data=None): + """ Populate the facts for firewall_global + :param connection: the device connection + :param ansible_facts: Facts dictionary + :param data: previously collected conf + :rtype: dictionary + :returns: facts + """ + if not data: + # typically data is populated from the current device configuration + # data = connection.get('show running-config | section ^interface') + # using mock data instead + data = self.get_device_data(connection) + objs = {} + firewalls = findall(r"^set firewall .*$", data, M) + if firewalls: + objs = self.render_config(firewalls) + facts = {} + params = utils.validate_config(self.argument_spec, {"config": objs}) + facts["firewall_global"] = utils.remove_empties(params["config"]) + ansible_facts["ansible_network_resources"].update(facts) + return ansible_facts + + def render_config(self, conf): + """ + Render config as dictionary structure and delete keys + from spec for null values + + :param spec: The facts tree, generated from the argspec + :param conf: The configuration + :rtype: dictionary + :returns: The generated config + """ + conf = "\n".join( + filter( + lambda x: ("firewall ipv6-name" and "firewall name" not in x), + conf, + ) + ) + + a_lst = [ + "config_trap", + "validation", + "log_martians", + "syn_cookies", + "twa_hazards_protection", + ] + firewall = self.parse_attr(conf, a_lst) + f_sub = { + "ping": self.parse_ping(conf), + "group": self.parse_group(conf), + "route_redirects": self.route_redirects(conf), + "state_policy": self.parse_state_policy(conf), + } + firewall.update(f_sub) + return firewall + + def route_redirects(self, conf): + """ + This function forms the regex to fetch the afi and invoke + functions to fetch route redirects and source routes + :param conf: configuration data. + :return: generated rule list configuration. + """ + rr_lst = [] + + v6_attr = findall( + r"^set firewall (?:ipv6-src-route|ipv6-receive-redirects) (\S+)", + conf, + M, + ) + if v6_attr: + obj = self.parse_rr_attrib(conf, "ipv6") + if obj: + rr_lst.append(obj) + + v4_attr = findall( + r"^set firewall (?:ip-src-route|receive-redirects|send-redirects) (\S+)", + conf, + M, + ) + if v4_attr: + obj = self.parse_rr_attrib(conf, "ipv4") + if obj: + rr_lst.append(obj) + return rr_lst + + def parse_rr_attrib(self, conf, attrib=None): + """ + This function fetches the 'ip_src_route' + invoke function to parse icmp redirects. + :param conf: configuration to be parsed. + :param attrib: 'ipv4/ipv6'. + :return: generated config dictionary. + """ + + cfg_dict = self.parse_attr(conf, ["ip_src_route"], type=attrib) + cfg_dict["icmp_redirects"] = self.parse_icmp_redirects(conf, attrib) + cfg_dict["afi"] = attrib + return cfg_dict + + def parse_icmp_redirects(self, conf, attrib=None): + """ + This function triggers the parsing of 'icmp_redirects' attributes. + :param conf: configuration to be parsed. + :param attrib: 'ipv4/ipv6'. + :return: generated config dictionary. + """ + a_lst = ["send", "receive"] + cfg_dict = self.parse_attr(conf, a_lst, type=attrib) + return cfg_dict + + def parse_ping(self, conf): + """ + This function triggers the parsing of 'ping' attributes. + :param conf: configuration to be parsed. + :return: generated config dictionary. + """ + a_lst = ["all", "broadcast"] + cfg_dict = self.parse_attr(conf, a_lst) + return cfg_dict + + def parse_state_policy(self, conf): + """ + This function fetched the connecton type and invoke + function to parse other state-policy attributes. + :param conf: configuration data. + :return: generated rule list configuration. + """ + sp_lst = [] + attrib = "state-policy" + policies = findall(r"^set firewall " + attrib + " (\\S+)", conf, M) + + if policies: + rules_lst = [] + for sp in set(policies): + sp_regex = r" %s .+$" % sp + cfg = "\n".join(findall(sp_regex, conf, M)) + obj = self.parse_policies(cfg, sp) + obj["connection_type"] = sp + if obj: + rules_lst.append(obj) + sp_lst = sorted(rules_lst, key=lambda i: i["connection_type"]) + return sp_lst + + def parse_policies(self, conf, attrib=None): + """ + This function triggers the parsing of policy attributes + action and log. + :param conf: configuration + :param attrib: connection type. + :return: generated rule configuration dictionary. + """ + a_lst = ["action", "log"] + cfg_dict = self.parse_attr(conf, a_lst, match=attrib) + return cfg_dict + + def parse_group(self, conf): + """ + This function triggers the parsing of 'group' attributes. + :param conf: configuration. + :return: generated config dictionary. + """ + cfg_dict = {} + cfg_dict["port_group"] = self.parse_group_lst(conf, "port-group") + cfg_dict["address_group"] = self.parse_group_lst(conf, "address-group") + cfg_dict["network_group"] = self.parse_group_lst(conf, "network-group") + return cfg_dict + + def parse_group_lst(self, conf, type): + """ + This function fetches the name of group and invoke function to + parse group attributes'. + :param conf: configuration data. + :param type: type of group. + :return: generated group list configuration. + """ + g_lst = [] + + groups = findall(r"^set firewall group " + type + " (\\S+)", conf, M) + if groups: + rules_lst = [] + for gr in set(groups): + gr_regex = r" %s .+$" % gr + cfg = "\n".join(findall(gr_regex, conf, M)) + obj = self.parse_groups(cfg, type, gr) + obj["name"] = gr.strip("'") + if obj: + rules_lst.append(obj) + g_lst = sorted(rules_lst, key=lambda i: i["name"]) + return g_lst + + def parse_groups(self, conf, type, name): + """ + This function fetches the description and invoke + the parsing of group members. + :param conf: configuration. + :param type: type of group. + :param name: name of group. + :return: generated configuration dictionary. + """ + a_lst = ["name", "description"] + group = self.parse_attr(conf, a_lst) + key = self.get_key(type) + r_sub = {key[0]: self.parse_address_port_lst(conf, name, key[1])} + group.update(r_sub) + return group + + def parse_address_port_lst(self, conf, name, key): + """ + This function forms the regex to fetch the + group members attributes. + :param conf: configuration data. + :param name: name of group. + :param key: key value. + :return: generated member list configuration. + """ + l_lst = [] + attribs = findall(r"^.*" + name + " " + key + " (\\S+)", conf, M) + if attribs: + for attr in attribs: + if key == "port": + l_lst.append({"port": attr.strip("'")}) + else: + l_lst.append({"address": attr.strip("'")}) + return l_lst + + def parse_attr(self, conf, attr_list, match=None, type=None): + """ + This function peforms the following: + - Form the regex to fetch the required attribute config. + - Type cast the output in desired format. + :param conf: configuration. + :param attr_list: list of attributes. + :param match: parent node/attribute name. + :return: generated config dictionary. + """ + config = {} + for attrib in attr_list: + regex = self.map_regex(attrib, type) + if match: + regex = match + " " + regex + if conf: + if self.is_bool(attrib): + attr = self.map_regex(attrib, type) + out = conf.find(attr.replace("_", "-")) + dis = conf.find(attr.replace("_", "-") + " 'disable'") + if out >= 1: + if dis >= 1: + config[attrib] = False + else: + config[attrib] = True + else: + out = search(r"^.*" + regex + " (.+)", conf, M) + if out: + val = out.group(1).strip("'") + if self.is_num(attrib): + val = int(val) + config[attrib] = val + return config + + def get_key(self, type): + """ + This function map the group type to + member type + :param type: + :return: + """ + key = () + if type == "port-group": + key = ("members", "port") + elif type == "address-group": + key = ("members", "address") + elif type == "network-group": + key = ("members", "network") + return key + + def map_regex(self, attrib, type=None): + """ + - This function construct the regex string. + - replace the underscore with hyphen. + :param attrib: attribute + :return: regex string + """ + regex = attrib.replace("_", "-") + if attrib == "all": + regex = "all-ping" + elif attrib == "disabled": + regex = "disable" + elif attrib == "broadcast": + regex = "broadcast-ping" + elif attrib == "send": + if type == "ipv6": + regex = "ipv6-send-redirects" + else: + regex = "send-redirects" + elif attrib == "ip_src_route": + if type == "ipv6": + regex = "ipv6-src-route" + elif attrib == "receive": + if type == "ipv6": + regex = "ipv6-receive-redirects" + else: + regex = "receive-redirects" + return regex + + def is_num(self, attrib): + """ + This function looks for the attribute in predefined integer type set. + :param attrib: attribute. + :return: True/false. + """ + num_set = ("time", "code", "type", "count", "burst", "number") + return True if attrib in num_set else False + + def get_src_route(self, attrib): + """ + This function looks for the attribute in predefined integer type set. + :param attrib: attribute. + :return: True/false. + """ + return "ipv6_src_route" if attrib == "ipv6" else "ip_src_route" + + def is_bool(self, attrib): + """ + This function looks for the attribute in predefined bool type set. + :param attrib: attribute. + :return: True/False + """ + bool_set = ( + "all", + "log", + "send", + "receive", + "broadcast", + "config_trap", + "log_martians", + "syn_cookies", + "ip_src_route", + "twa_hazards_protection", + ) + return True if attrib in bool_set else False diff --git a/plugins/modules/vyos_facts.py b/plugins/modules/vyos_facts.py index 19fb727..eec4c3b 100644 --- a/plugins/modules/vyos_facts.py +++ b/plugins/modules/vyos_facts.py @@ -1,174 +1,174 @@ #!/usr/bin/python # -*- coding: utf-8 -*- # Copyright 2019 Red Hat # GNU General Public License v3.0+ # (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) """ The module file for vyos_facts """ ANSIBLE_METADATA = { "metadata_version": "1.1", "status": [u"preview"], "supported_by": "network", } DOCUMENTATION = """module: vyos_facts short_description: Get facts about vyos devices. description: - Collects facts from network devices running the vyos operating system. This module places the facts gathered in the fact tree keyed by the respective resource name. The facts module will always collect a base set of facts from the device and can enable or disable collection of additional facts. author: - Nathaniel Case (@qalthos) - Nilashish Chakraborty (@Nilashishc) - Rohit Thakur (@rohitthakur2590) extends_documentation_fragment: - vyos.vyos.vyos notes: - Tested against VyOS 1.1.8 (helium). - This module works with connection C(network_cli). See L(the VyOS OS Platform Options,../network/user_guide/platform_vyos.html). options: gather_subset: description: - When supplied, this argument will restrict the facts collected to a given subset. Possible values for this argument include all, default, config, and neighbors. Can specify a list of values to include a larger subset. Values can also be used with an initial C(M(!)) to specify that a specific subset should not be collected. required: false default: '!config' gather_network_resources: description: - When supplied, this argument will restrict the facts collected to a given subset. Possible values for this argument include all and the resources like interfaces. Can specify a list of values to include a larger subset. Values can also be used with an initial C(M(!)) to specify that a specific subset should not be collected. Valid subsets are 'all', 'interfaces', 'l3_interfaces', 'lag_interfaces', - 'lldp_global', 'lldp_interfaces', 'static_routes', 'firewall_rules'. + 'lldp_global', 'lldp_interfaces', 'static_routes', 'firewall_rules', 'firewall_global'. required: false """ EXAMPLES = """ # Gather all facts - vyos_facts: gather_subset: all gather_network_resources: all # collect only the config and default facts - vyos_facts: gather_subset: config # collect everything exception the config - vyos_facts: gather_subset: "!config" # Collect only the interfaces facts - vyos_facts: gather_subset: - '!all' - '!min' gather_network_resources: - interfaces # Do not collect interfaces facts - vyos_facts: gather_network_resources: - "!interfaces" # Collect interfaces and minimal default facts - vyos_facts: gather_subset: min gather_network_resources: interfaces """ RETURN = """ ansible_net_config: description: The running-config from the device returned: when config is configured type: str ansible_net_commits: description: The set of available configuration revisions returned: when present type: list ansible_net_hostname: description: The configured system hostname returned: always type: str ansible_net_model: description: The device model string returned: always type: str ansible_net_serialnum: description: The serial number of the device returned: always type: str ansible_net_version: description: The version of the software running returned: always type: str ansible_net_neighbors: description: The set of LLDP neighbors returned: when interface is configured type: list ansible_net_gather_subset: description: The list of subsets gathered by the module returned: always type: list ansible_net_api: description: The name of the transport returned: always type: str ansible_net_python_version: description: The Python version Ansible controller is using returned: always type: str ansible_net_gather_network_resources: description: The list of fact resource subsets collected from the device returned: always type: list """ from ansible.module_utils.basic import AnsibleModule from ansible_collections.vyos.vyos.plugins.module_utils.network.vyos.argspec.facts.facts import ( FactsArgs, ) from ansible_collections.vyos.vyos.plugins.module_utils.network.vyos.facts.facts import ( Facts, ) from ansible_collections.vyos.vyos.plugins.module_utils.network.vyos.vyos import ( vyos_argument_spec, ) def main(): """ Main entry point for module execution :returns: ansible_facts """ argument_spec = FactsArgs.argument_spec argument_spec.update(vyos_argument_spec) module = AnsibleModule( argument_spec=argument_spec, supports_check_mode=True ) warnings = [] if module.params["gather_subset"] == "!config": warnings.append( "default value for `gather_subset` will be changed to `min` from `!config` v2.11 onwards" ) result = Facts(module).get_facts() ansible_facts, additional_warnings = result warnings.extend(additional_warnings) module.exit_json(ansible_facts=ansible_facts, warnings=warnings) if __name__ == "__main__": main() diff --git a/plugins/modules/vyos_firewall_global.py b/plugins/modules/vyos_firewall_global.py new file mode 100644 index 0000000..519725a --- /dev/null +++ b/plugins/modules/vyos_firewall_global.py @@ -0,0 +1,1204 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- +# Copyright 2019 Red Hat +# GNU General Public License v3.0+ +# (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) + +############################################# +# WARNING # +############################################# +# +# This file is auto generated by the resource +# module builder playbook. +# +# Do not edit this file manually. +# +# Changes to this file will be over written +# by the resource module builder. +# +# Changes should be made in the model used to +# generate this file or in the resource module +# builder template. +# +############################################# + +""" +The module file for vyos_firewall_global +""" + +from __future__ import absolute_import, division, print_function + +__metaclass__ = type + +ANSIBLE_METADATA = { + "metadata_version": "1.1", + "status": ["preview"], + "supported_by": "network", +} + +DOCUMENTATION = """module: vyos_firewall_global +short_description: Manage global policies or configurations for firewall on VyOS devices. +description: This module manage global policies or configurations for firewall on + VyOS devices. +notes: +- Tested against VyOS 1.1.8 (helium). +- This module works with connection C(network_cli). See L(the VyOS OS Platform Options,../network/user_guide/platform_vyos.html). +author: +- Rohit Thakur (@rohitthakur2590) +options: + config: + description: + - A dictionary of Firewall global configuration options. + type: dict + suboptions: + route_redirects: + description: -A dictionary of Firewall icmp redirect and source route global + configuration options. + type: list + elements: dict + suboptions: + afi: + description: + - Specifies IP address type + type: str + choices: + - ipv4 + - ipv6 + required: true + icmp_redirects: + description: + - Specifies whether to allow sending/receiving of IPv4/v6 ICMP redirect + messages. + type: dict + suboptions: + send: + description: + - Permits or denies transmitting packets ICMP redirect messages. + type: bool + receive: + description: + - Permits or denies receiving packets ICMP redirect messages. + type: bool + ip_src_route: + description: + - Specifies whether or not to process source route IP options. + type: bool + ping: + description: + - Policy for handling of all IPv4 ICMP echo requests. + type: dict + suboptions: + all: + description: + - Enables or disables response to all IPv4 ICMP Echo Request (ping) messages. + - The system responds to IPv4 ICMP Echo Request messages. + type: bool + broadcast: + description: + - Enables or disables response to broadcast IPv4 ICMP Echo Request and + Timestamp Request messages. + - IPv4 ICMP Echo and Timestamp Request messages are not processed. + type: bool + config_trap: + description: + - SNMP trap generation on firewall configuration changes. + type: bool + validation: + description: + - Specifies a policy for source validation by reversed path, as defined in + RFC 3704. + - (disable) No source validation is performed. + - (loose) Enable Loose Reverse Path Forwarding as defined in RFC3704. + - (strict) Enable Strict Reverse Path Forwarding as defined in RFC3704. + type: str + choices: + - strict + - loose + - disable + group: + description: + - Defines a group of objects for referencing in firewall rules. + type: dict + suboptions: + address_group: + description: + - Defines a group of IP addresses for referencing in firewall rules. + type: list + elements: dict + suboptions: + name: + description: + - Name of the firewall address group. + type: str + required: true + description: + description: + - Allows you to specify a brief description for the address group. + type: str + members: + description: + - Address-group members. + - IPv4 address to match. + - IPv4 range to match. + type: list + elements: dict + suboptions: + address: + description: IP address. + type: str + network_group: + description: + - Defines a group of networks for referencing in firewall rules. + type: list + elements: dict + suboptions: + name: + description: + - Name of the firewall network group. + type: str + required: true + description: + description: + - Allows you to specify a brief description for the network group. + type: str + members: + description: + - Adds an IPv4 network to the specified network group. + - The format is ip-address/prefix. + type: list + elements: dict + suboptions: + address: + description: IP address. + type: str + port_group: + description: + - Defines a group of ports for referencing in firewall rules. + type: list + elements: dict + suboptions: + name: + description: + - Name of the firewall port group. + type: str + required: true + description: + description: + - Allows you to specify a brief description for the port group. + type: str + members: + description: + - Port-group member. + type: list + elements: dict + suboptions: + port: + description: Defines the number. + type: str + log_martians: + description: + - Specifies whether or not to record packets with invalid addresses in the + log. + - (True) Logs packets with invalid addresses. + - (False) Does not log packets with invalid addresses. + type: bool + syn_cookies: + description: + - Specifies policy for using TCP SYN cookies with IPv4. + - (True) Enables TCP SYN cookies with IPv4. + - (False) Disables TCP SYN cookies with IPv4. + type: bool + twa_hazards_protection: + description: + - RFC1337 TCP TIME-WAIT assasination hazards protection. + type: bool + state_policy: + description: + - Specifies global firewall state-policy. + type: list + elements: dict + suboptions: + connection_type: + description: Specifies connection type. + type: str + choices: + - established + - invalid + - related + action: + description: + - Action for packets part of an established connection. + type: str + choices: + - accept + - drop + - reject + log: + description: + - Enable logging of packets part of an established connection. + type: bool + running_config: + description: + - The module, by default, will connect to the remote device and retrieve the current + running-config to use as a base for comparing against the contents of source. + There are times when it is not desirable to have the task get the current running-config + for every task in a playbook. The I(running_config) argument allows the implementer + to pass in the configuration to use as the base config for comparison. This + value of this option should be the output received from device by executing + command C(show configuration commands | grep 'firewall') + type: str + state: + description: + - The state the configuration should be left in. + type: str + choices: + - merged + - replaced + - deleted + - gathered + - rendered + - parsed + default: merged +""" +EXAMPLES = """ +# Using merged +# +# Before state: +# ------------- +# +# vyos@vyos# run show configuration commands | grep firewall +# +# +- name: Merge the provided configuration with the exisiting running configuration + vyos_firewall_global: + config: + validation: strict + config_trap: True + log_martians: True + syn_cookies: True + twa_hazards_protection: True + ping: + all: True + broadcast: True + state_policy: + - connection_type: 'established' + action: 'accept' + log: True + - connection_type: 'invalid' + action: 'reject' + route_redirects: + - afi: 'ipv4' + ip_src_route: True + icmp_redirects: + send: True + receive: False + group: + address_group: + - name: 'MGMT-HOSTS' + description: 'This group has the Management hosts address list' + members: + - address: 192.0.1.1 + - address: 192.0.1.3 + - address: 192.0.1.5 + network_group: + - name: 'MGMT' + description: 'This group has the Management network addresses' + members: + - address: 192.0.1.0/24 + state: merged +# +# +# ------------------------- +# Module Execution Result +# ------------------------- +# +# before": [] +# +# "commands": [ +# "set firewall group address-group MGMT-HOSTS address 192.0.1.1", +# "set firewall group address-group MGMT-HOSTS address 192.0.1.3", +# "set firewall group address-group MGMT-HOSTS address 192.0.1.5", +# "set firewall group address-group MGMT-HOSTS description 'This group has the Management hosts address list'", +# "set firewall group address-group MGMT-HOSTS", +# "set firewall group network-group MGMT network 192.0.1.0/24", +# "set firewall group network-group MGMT description 'This group has the Management network addresses'", +# "set firewall group network-group MGMT", +# "set firewall ip-src-route 'enable'", +# "set firewall receive-redirects 'disable'", +# "set firewall send-redirects 'enable'", +# "set firewall config-trap 'enable'", +# "set firewall state-policy established action 'accept'", +# "set firewall state-policy established log 'enable'", +# "set firewall state-policy invalid action 'reject'", +# "set firewall broadcast-ping 'enable'", +# "set firewall all-ping 'enable'", +# "set firewall log-martians 'enable'", +# "set firewall twa-hazards-protection 'enable'", +# "set firewall syn-cookies 'enable'", +# "set firewall source-validation 'strict'" +# ] +# +# "after": { +# "config_trap": true, +# "group": { +# "address_group": [ +# { +# "description": "This group has the Management hosts address list", +# "members": [ +# { +# "address": "192.0.1.1" +# }, +# { +# "address": "192.0.1.3" +# }, +# { +# "address": "192.0.1.5" +# } +# ], +# "name": "MGMT-HOSTS" +# } +# ], +# "network_group": [ +# { +# "description": "This group has the Management network addresses", +# "members": [ +# { +# "address": "192.0.1.0/24" +# } +# ], +# "name": "MGMT" +# } +# ] +# }, +# "log_martians": true, +# "ping": { +# "all": true, +# "broadcast": true +# }, +# "route_redirects": [ +# { +# "afi": "ipv4", +# "icmp_redirects": { +# "receive": false, +# "send": true +# }, +# "ip_src_route": true +# } +# ], +# "state_policy": [ +# { +# "action": "accept", +# "connection_type": "established", +# "log": true +# }, +# { +# "action": "reject", +# "connection_type": "invalid" +# } +# ], +# "syn_cookies": true, +# "twa_hazards_protection": true, +# "validation": "strict" +# } +# +# After state: +# ------------- +# +# vyos@192# run show configuration commands | grep firewall +# set firewall all-ping 'enable' +# set firewall broadcast-ping 'enable' +# set firewall config-trap 'enable' +# set firewall group address-group MGMT-HOSTS address '192.0.1.1' +# set firewall group address-group MGMT-HOSTS address '192.0.1.3' +# set firewall group address-group MGMT-HOSTS address '192.0.1.5' +# set firewall group address-group MGMT-HOSTS description 'This group has the Management hosts address list' +# set firewall group network-group MGMT description 'This group has the Management network addresses' +# set firewall group network-group MGMT network '192.0.1.0/24' +# set firewall ip-src-route 'enable' +# set firewall log-martians 'enable' +# set firewall receive-redirects 'disable' +# set firewall send-redirects 'enable' +# set firewall source-validation 'strict' +# set firewall state-policy established action 'accept' +# set firewall state-policy established log 'enable' +# set firewall state-policy invalid action 'reject' +# set firewall syn-cookies 'enable' +# set firewall twa-hazards-protection 'enable' +# +# +# Using parsed +# +# +- name: Render the commands for provided configuration + vyos_firewall_global: + running_config: + "set firewall all-ping 'enable' + set firewall broadcast-ping 'enable' + set firewall config-trap 'enable' + set firewall group address-group ENG-HOSTS address '192.0.3.1' + set firewall group address-group ENG-HOSTS address '192.0.3.2' + set firewall group address-group ENG-HOSTS description 'Sales office hosts address list' + set firewall group address-group SALES-HOSTS address '192.0.2.1' + set firewall group address-group SALES-HOSTS address '192.0.2.2' + set firewall group address-group SALES-HOSTS address '192.0.2.3' + set firewall group address-group SALES-HOSTS description 'Sales office hosts address list' + set firewall group network-group MGMT description 'This group has the Management network addresses' + set firewall group network-group MGMT network '192.0.1.0/24' + set firewall ip-src-route 'enable' + set firewall log-martians 'enable' + set firewall receive-redirects 'disable' + set firewall send-redirects 'enable' + set firewall source-validation 'strict' + set firewall state-policy established action 'accept' + set firewall state-policy established log 'enable' + set firewall state-policy invalid action 'reject' + set firewall syn-cookies 'enable' + set firewall twa-hazards-protection 'enable'" + state: parsed +# +# +# ------------------------- +# Module Execution Result +# ------------------------- +# +# +# "parsed": { +# "config_trap": true, +# "group": { +# "address_group": [ +# { +# "description": "Sales office hosts address list", +# "members": [ +# { +# "address": "192.0.3.1" +# }, +# { +# "address": "192.0.3.2" +# } +# ], +# "name": "ENG-HOSTS" +# }, +# { +# "description": "Sales office hosts address list", +# "members": [ +# { +# "address": "192.0.2.1" +# }, +# { +# "address": "192.0.2.2" +# }, +# { +# "address": "192.0.2.3" +# } +# ], +# "name": "SALES-HOSTS" +# } +# ], +# "network_group": [ +# { +# "description": "This group has the Management network addresses", +# "members": [ +# { +# "address": "192.0.1.0/24" +# } +# ], +# "name": "MGMT" +# } +# ] +# }, +# "log_martians": true, +# "ping": { +# "all": true, +# "broadcast": true +# }, +# "route_redirects": [ +# { +# "afi": "ipv4", +# "icmp_redirects": { +# "receive": false, +# "send": true +# }, +# "ip_src_route": true +# } +# ], +# "state_policy": [ +# { +# "action": "accept", +# "connection_type": "established", +# "log": true +# }, +# { +# "action": "reject", +# "connection_type": "invalid" +# } +# ], +# "syn_cookies": true, +# "twa_hazards_protection": true, +# "validation": "strict" +# } +# } +# +# +# Using deleted +# +# Before state +# ------------- +# +# vyos@192# run show configuration commands | grep firewall +# set firewall all-ping 'enable' +# set firewall broadcast-ping 'enable' +# set firewall config-trap 'enable' +# set firewall group address-group MGMT-HOSTS address '192.0.1.1' +# set firewall group address-group MGMT-HOSTS address '192.0.1.3' +# set firewall group address-group MGMT-HOSTS address '192.0.1.5' +# set firewall group address-group MGMT-HOSTS description 'This group has the Management hosts address list' +# set firewall group network-group MGMT description 'This group has the Management network addresses' +# set firewall group network-group MGMT network '192.0.1.0/24' +# set firewall ip-src-route 'enable' +# set firewall log-martians 'enable' +# set firewall receive-redirects 'disable' +# set firewall send-redirects 'enable' +# set firewall source-validation 'strict' +# set firewall state-policy established action 'accept' +# set firewall state-policy established log 'enable' +# set firewall state-policy invalid action 'reject' +# set firewall syn-cookies 'enable' +# set firewall twa-hazards-protection 'enable' +- name: Delete attributes of firewall. + vyos_firewall_global: + config: + state_policy: + config_trap: + log_martians: + syn_cookies: + twa_hazards_protection: + route_redirects: + ping: + group: + state: deleted +# +# +# ------------------------ +# Module Execution Results +# ------------------------ +# +# "before": { +# "config_trap": true, +# "group": { +# "address_group": [ +# { +# "description": "This group has the Management hosts address list", +# "members": [ +# { +# "address": "192.0.1.1" +# }, +# { +# "address": "192.0.1.3" +# }, +# { +# "address": "192.0.1.5" +# } +# ], +# "name": "MGMT-HOSTS" +# } +# ], +# "network_group": [ +# { +# "description": "This group has the Management network addresses", +# "members": [ +# { +# "address": "192.0.1.0/24" +# } +# ], +# "name": "MGMT" +# } +# ] +# }, +# "log_martians": true, +# "ping": { +# "all": true, +# "broadcast": true +# }, +# "route_redirects": [ +# { +# "afi": "ipv4", +# "icmp_redirects": { +# "receive": false, +# "send": true +# }, +# "ip_src_route": true +# } +# ], +# "state_policy": [ +# { +# "action": "accept", +# "connection_type": "established", +# "log": true +# }, +# { +# "action": "reject", +# "connection_type": "invalid" +# } +# ], +# "syn_cookies": true, +# "twa_hazards_protection": true, +# "validation": "strict" +# } +# "commands": [ +# "delete firewall source-validation", +# "delete firewall group", +# "delete firewall log-martians", +# "delete firewall ip-src-route", +# "delete firewall receive-redirects", +# "delete firewall send-redirects", +# "delete firewall config-trap", +# "delete firewall state-policy", +# "delete firewall syn-cookies", +# "delete firewall broadcast-ping", +# "delete firewall all-ping", +# "delete firewall twa-hazards-protection" +# ] +# +# "after": [] +# After state +# ------------ +# vyos@192# run show configuration commands | grep firewall +# set 'firewall' +# +# +# Using replaced +# +# Before state: +# ------------- +# +# vyos@vyos:~$ show configuration commands| grep firewall +# set firewall all-ping 'enable' +# set firewall broadcast-ping 'enable' +# set firewall config-trap 'enable' +# set firewall group address-group MGMT-HOSTS address '192.0.1.1' +# set firewall group address-group MGMT-HOSTS address '192.0.1.3' +# set firewall group address-group MGMT-HOSTS address '192.0.1.5' +# set firewall group address-group MGMT-HOSTS description 'This group has the Management hosts address list' +# set firewall group network-group MGMT description 'This group has the Management network addresses' +# set firewall group network-group MGMT network '192.0.1.0/24' +# set firewall ip-src-route 'enable' +# set firewall log-martians 'enable' +# set firewall receive-redirects 'disable' +# set firewall send-redirects 'enable' +# set firewall source-validation 'strict' +# set firewall state-policy established action 'accept' +# set firewall state-policy established log 'enable' +# set firewall state-policy invalid action 'reject' +# set firewall syn-cookies 'enable' +# set firewall twa-hazards-protection 'enable' +# +- name: Replace firewall global attributes configuration. + vyos_firewall_global: + config: + validation: strict + config_trap: True + log_martians: True + syn_cookies: True + twa_hazards_protection: True + ping: + all: True + broadcast: True + state_policy: + - connection_type: 'established' + action: 'accept' + log: True + - connection_type: 'invalid' + action: 'reject' + route_redirects: + - afi: 'ipv4' + ip_src_route: True + icmp_redirects: + send: True + receive: False + group: + address_group: + - name: 'SALES-HOSTS' + description: 'Sales office hosts address list' + members: + - address: 192.0.2.1 + - address: 192.0.2.2 + - address: 192.0.2.3 + - name: 'ENG-HOSTS' + description: 'Sales office hosts address list' + members: + - address: 192.0.3.1 + - address: 192.0.3.2 + network_group: + - name: 'MGMT' + description: 'This group has the Management network addresses' + members: + - address: 192.0.1.0/24 + state: replaced +# +# +# ------------------------- +# Module Execution Result +# ------------------------- +# +# "before": { +# "config_trap": true, +# "group": { +# "address_group": [ +# { +# "description": "This group has the Management hosts address list", +# "members": [ +# { +# "address": "192.0.1.1" +# }, +# { +# "address": "192.0.1.3" +# }, +# { +# "address": "192.0.1.5" +# } +# ], +# "name": "MGMT-HOSTS" +# } +# ], +# "network_group": [ +# { +# "description": "This group has the Management network addresses", +# "members": [ +# { +# "address": "192.0.1.0/24" +# } +# ], +# "name": "MGMT" +# } +# ] +# }, +# "log_martians": true, +# "ping": { +# "all": true, +# "broadcast": true +# }, +# "route_redirects": [ +# { +# "afi": "ipv4", +# "icmp_redirects": { +# "receive": false, +# "send": true +# }, +# "ip_src_route": true +# } +# ], +# "state_policy": [ +# { +# "action": "accept", +# "connection_type": "established", +# "log": true +# }, +# { +# "action": "reject", +# "connection_type": "invalid" +# } +# ], +# "syn_cookies": true, +# "twa_hazards_protection": true, +# "validation": "strict" +# } +# +# "commands": [ +# "delete firewall group address-group MGMT-HOSTS", +# "set firewall group address-group SALES-HOSTS address 192.0.2.1", +# "set firewall group address-group SALES-HOSTS address 192.0.2.2", +# "set firewall group address-group SALES-HOSTS address 192.0.2.3", +# "set firewall group address-group SALES-HOSTS description 'Sales office hosts address list'", +# "set firewall group address-group SALES-HOSTS", +# "set firewall group address-group ENG-HOSTS address 192.0.3.1", +# "set firewall group address-group ENG-HOSTS address 192.0.3.2", +# "set firewall group address-group ENG-HOSTS description 'Sales office hosts address list'", +# "set firewall group address-group ENG-HOSTS" +# ] +# +# "after": { +# "config_trap": true, +# "group": { +# "address_group": [ +# { +# "description": "Sales office hosts address list", +# "members": [ +# { +# "address": "192.0.3.1" +# }, +# { +# "address": "192.0.3.2" +# } +# ], +# "name": "ENG-HOSTS" +# }, +# { +# "description": "Sales office hosts address list", +# "members": [ +# { +# "address": "192.0.2.1" +# }, +# { +# "address": "192.0.2.2" +# }, +# { +# "address": "192.0.2.3" +# } +# ], +# "name": "SALES-HOSTS" +# } +# ], +# "network_group": [ +# { +# "description": "This group has the Management network addresses", +# "members": [ +# { +# "address": "192.0.1.0/24" +# } +# ], +# "name": "MGMT" +# } +# ] +# }, +# "log_martians": true, +# "ping": { +# "all": true, +# "broadcast": true +# }, +# "route_redirects": [ +# { +# "afi": "ipv4", +# "icmp_redirects": { +# "receive": false, +# "send": true +# }, +# "ip_src_route": true +# } +# ], +# "state_policy": [ +# { +# "action": "accept", +# "connection_type": "established", +# "log": true +# }, +# { +# "action": "reject", +# "connection_type": "invalid" +# } +# ], +# "syn_cookies": true, +# "twa_hazards_protection": true, +# "validation": "strict" +# } +# +# After state: +# ------------- +# +# vyos@192# run show configuration commands | grep firewall +# set firewall all-ping 'enable' +# set firewall broadcast-ping 'enable' +# set firewall config-trap 'enable' +# set firewall group address-group ENG-HOSTS address '192.0.3.1' +# set firewall group address-group ENG-HOSTS address '192.0.3.2' +# set firewall group address-group ENG-HOSTS description 'Sales office hosts address list' +# set firewall group address-group SALES-HOSTS address '192.0.2.1' +# set firewall group address-group SALES-HOSTS address '192.0.2.2' +# set firewall group address-group SALES-HOSTS address '192.0.2.3' +# set firewall group address-group SALES-HOSTS description 'Sales office hosts address list' +# set firewall group network-group MGMT description 'This group has the Management network addresses' +# set firewall group network-group MGMT network '192.0.1.0/24' +# set firewall ip-src-route 'enable' +# set firewall log-martians 'enable' +# set firewall receive-redirects 'disable' +# set firewall send-redirects 'enable' +# set firewall source-validation 'strict' +# set firewall state-policy established action 'accept' +# set firewall state-policy established log 'enable' +# set firewall state-policy invalid action 'reject' +# set firewall syn-cookies 'enable' +# set firewall twa-hazards-protection 'enable' +# +# +# Using gathered +# +# Before state: +# ------------- +# +# vyos@192# run show configuration commands | grep firewall +# set firewall all-ping 'enable' +# set firewall broadcast-ping 'enable' +# set firewall config-trap 'enable' +# set firewall group address-group ENG-HOSTS address '192.0.3.1' +# set firewall group address-group ENG-HOSTS address '192.0.3.2' +# set firewall group address-group ENG-HOSTS description 'Sales office hosts address list' +# set firewall group address-group SALES-HOSTS address '192.0.2.1' +# set firewall group address-group SALES-HOSTS address '192.0.2.2' +# set firewall group address-group SALES-HOSTS address '192.0.2.3' +# set firewall group address-group SALES-HOSTS description 'Sales office hosts address list' +# set firewall group network-group MGMT description 'This group has the Management network addresses' +# set firewall group network-group MGMT network '192.0.1.0/24' +# set firewall ip-src-route 'enable' +# set firewall log-martians 'enable' +# set firewall receive-redirects 'disable' +# set firewall send-redirects 'enable' +# set firewall source-validation 'strict' +# set firewall state-policy established action 'accept' +# set firewall state-policy established log 'enable' +# set firewall state-policy invalid action 'reject' +# set firewall syn-cookies 'enable' +# set firewall twa-hazards-protection 'enable' +# +- name: Gather firewall global config with provided configurations + vyos_firewall_global: + config: + state: gathered +# +# +# ------------------------- +# Module Execution Result +# ------------------------- +# +# "gathered": [ +# { +# "config_trap": true, +# "group": { +# "address_group": [ +# { +# "description": "Sales office hosts address list", +# "members": [ +# { +# "address": "192.0.3.1" +# }, +# { +# "address": "192.0.3.2" +# } +# ], +# "name": "ENG-HOSTS" +# }, +# { +# "description": "Sales office hosts address list", +# "members": [ +# { +# "address": "192.0.2.1" +# }, +# { +# "address": "192.0.2.2" +# }, +# { +# "address": "192.0.2.3" +# } +# ], +# "name": "SALES-HOSTS" +# } +# ], +# "network_group": [ +# { +# "description": "This group has the Management network addresses", +# "members": [ +# { +# "address": "192.0.1.0/24" +# } +# ], +# "name": "MGMT" +# } +# ] +# }, +# "log_martians": true, +# "ping": { +# "all": true, +# "broadcast": true +# }, +# "route_redirects": [ +# { +# "afi": "ipv4", +# "icmp_redirects": { +# "receive": false, +# "send": true +# }, +# "ip_src_route": true +# } +# ], +# "state_policy": [ +# { +# "action": "accept", +# "connection_type": "established", +# "log": true +# }, +# { +# "action": "reject", +# "connection_type": "invalid" +# } +# ], +# "syn_cookies": true, +# "twa_hazards_protection": true, +# "validation": "strict" +# } +# +# After state: +# ------------- +# +# vyos@192# run show configuration commands | grep firewall +# set firewall all-ping 'enable' +# set firewall broadcast-ping 'enable' +# set firewall config-trap 'enable' +# set firewall group address-group ENG-HOSTS address '192.0.3.1' +# set firewall group address-group ENG-HOSTS address '192.0.3.2' +# set firewall group address-group ENG-HOSTS description 'Sales office hosts address list' +# set firewall group address-group SALES-HOSTS address '192.0.2.1' +# set firewall group address-group SALES-HOSTS address '192.0.2.2' +# set firewall group address-group SALES-HOSTS address '192.0.2.3' +# set firewall group address-group SALES-HOSTS description 'Sales office hosts address list' +# set firewall group network-group MGMT description 'This group has the Management network addresses' +# set firewall group network-group MGMT network '192.0.1.0/24' +# set firewall ip-src-route 'enable' +# set firewall log-martians 'enable' +# set firewall receive-redirects 'disable' +# set firewall send-redirects 'enable' +# set firewall source-validation 'strict' +# set firewall state-policy established action 'accept' +# set firewall state-policy established log 'enable' +# set firewall state-policy invalid action 'reject' +# set firewall syn-cookies 'enable' +# set firewall twa-hazards-protection 'enable' + + +# Using rendered +# +# +- name: Render the commands for provided configuration + vyos_firewall_global: + config: + validation: strict + config_trap: True + log_martians: True + syn_cookies: True + twa_hazards_protection: True + ping: + all: True + broadcast: True + state_policy: + - connection_type: 'established' + action: 'accept' + log: True + - connection_type: 'invalid' + action: 'reject' + route_redirects: + - afi: 'ipv4' + ip_src_route: True + icmp_redirects: + send: True + receive: False + group: + address_group: + - name: 'SALES-HOSTS' + description: 'Sales office hosts address list' + members: + - address: 192.0.2.1 + - address: 192.0.2.2 + - address: 192.0.2.3 + - name: 'ENG-HOSTS' + description: 'Sales office hosts address list' + members: + - address: 192.0.3.1 + - address: 192.0.3.2 + network_group: + - name: 'MGMT' + description: 'This group has the Management network addresses' + members: + - address: 192.0.1.0/24 + state: rendered +# +# +# ------------------------- +# Module Execution Result +# ------------------------- +# +# +# "rendered": [ +# "set firewall group address-group SALES-HOSTS address 192.0.2.1", +# "set firewall group address-group SALES-HOSTS address 192.0.2.2", +# "set firewall group address-group SALES-HOSTS address 192.0.2.3", +# "set firewall group address-group SALES-HOSTS description 'Sales office hosts address list'", +# "set firewall group address-group SALES-HOSTS", +# "set firewall group address-group ENG-HOSTS address 192.0.3.1", +# "set firewall group address-group ENG-HOSTS address 192.0.3.2", +# "set firewall group address-group ENG-HOSTS description 'Sales office hosts address list'", +# "set firewall group address-group ENG-HOSTS", +# "set firewall group network-group MGMT network 192.0.1.0/24", +# "set firewall group network-group MGMT description 'This group has the Management network addresses'", +# "set firewall group network-group MGMT", +# "set firewall ip-src-route 'enable'", +# "set firewall receive-redirects 'disable'", +# "set firewall send-redirects 'enable'", +# "set firewall config-trap 'enable'", +# "set firewall state-policy established action 'accept'", +# "set firewall state-policy established log 'enable'", +# "set firewall state-policy invalid action 'reject'", +# "set firewall broadcast-ping 'enable'", +# "set firewall all-ping 'enable'", +# "set firewall log-martians 'enable'", +# "set firewall twa-hazards-protection 'enable'", +# "set firewall syn-cookies 'enable'", +# "set firewall source-validation 'strict'" +# ] +# +# +""" +RETURN = """ +before: + description: The configuration prior to the model invocation. + returned: always + type: list + sample: > + The configuration returned will always be in the same format + of the parameters above. +after: + description: The resulting configuration model invocation. + returned: when changed + type: list + sample: > + The configuration returned will always be in the same format + of the parameters above. +commands: + description: The set of commands pushed to the remote device. + returned: always + type: list + sample: ['set firewall group address-group ENG-HOSTS', + 'set firewall group address-group ENG-HOSTS address 192.0.3.1'] +""" + + +from ansible.module_utils.basic import AnsibleModule +from ansible_collections.vyos.vyos.plugins.module_utils.network.vyos.argspec.firewall_global.firewall_global import ( + Firewall_globalArgs, +) +from ansible_collections.vyos.vyos.plugins.module_utils.network.vyos.config.firewall_global.firewall_global import ( + Firewall_global, +) + + +def main(): + """ + Main entry point for module execution + + :returns: the result form module invocation + """ + required_if = [ + ("state", "merged", ("config",)), + ("state", "replaced", ("config",)), + ("state", "parsed", ("running_config",)), + ] + mutually_exclusive = [("config", "running_config")] + module = AnsibleModule( + argument_spec=Firewall_globalArgs.argument_spec, + required_if=required_if, + supports_check_mode=True, + mutually_exclusive=mutually_exclusive, + ) + + result = Firewall_global(module).execute_module() + module.exit_json(**result) + + +if __name__ == "__main__": + main() diff --git a/tests/integration/targets/vyos_banner/aliases b/tests/integration/targets/vyos_banner/aliases index 539d957..8071e1f 100644 --- a/tests/integration/targets/vyos_banner/aliases +++ b/tests/integration/targets/vyos_banner/aliases @@ -1 +1 @@ -shippable/network +shippable/vyos/group1 diff --git a/tests/integration/targets/vyos_command/aliases b/tests/integration/targets/vyos_command/aliases index 539d957..8071e1f 100644 --- a/tests/integration/targets/vyos_command/aliases +++ b/tests/integration/targets/vyos_command/aliases @@ -1 +1 @@ -shippable/network +shippable/vyos/group1 diff --git a/tests/integration/targets/vyos_config/aliases b/tests/integration/targets/vyos_config/aliases index 539d957..8071e1f 100644 --- a/tests/integration/targets/vyos_config/aliases +++ b/tests/integration/targets/vyos_config/aliases @@ -1 +1 @@ -shippable/network +shippable/vyos/group1 diff --git a/tests/integration/targets/vyos_facts/aliases b/tests/integration/targets/vyos_facts/aliases index 539d957..8071e1f 100644 --- a/tests/integration/targets/vyos_facts/aliases +++ b/tests/integration/targets/vyos_facts/aliases @@ -1 +1 @@ -shippable/network +shippable/vyos/group1 diff --git a/tests/integration/targets/vyos_firewall_global/defaults/main.yaml b/tests/integration/targets/vyos_firewall_global/defaults/main.yaml new file mode 100644 index 0000000..852a6be --- /dev/null +++ b/tests/integration/targets/vyos_firewall_global/defaults/main.yaml @@ -0,0 +1,3 @@ +--- +testcase: '[^_].*' +test_items: [] diff --git a/tests/integration/targets/vyos_firewall_global/meta/main.yaml b/tests/integration/targets/vyos_firewall_global/meta/main.yaml new file mode 100644 index 0000000..7413320 --- /dev/null +++ b/tests/integration/targets/vyos_firewall_global/meta/main.yaml @@ -0,0 +1,3 @@ +--- +dependencies: + - prepare_vyos_tests diff --git a/tests/integration/targets/vyos_firewall_global/tasks/cli.yaml b/tests/integration/targets/vyos_firewall_global/tasks/cli.yaml new file mode 100644 index 0000000..93eb2fe --- /dev/null +++ b/tests/integration/targets/vyos_firewall_global/tasks/cli.yaml @@ -0,0 +1,19 @@ +--- +- name: Collect all cli test cases + find: + paths: '{{ role_path }}/tests/cli' + patterns: '{{ testcase }}.yaml' + use_regex: true + register: test_cases + delegate_to: localhost + +- name: Set test_items + set_fact: test_items="{{ test_cases.files | map(attribute='path') | list }}" + +- name: Run test case (connection=ansible.netcommon.network_cli) + include: '{{ test_case_to_run }}' + vars: + ansible_connection: ansible.netcommon.network_cli + with_items: '{{ test_items }}' + loop_control: + loop_var: test_case_to_run diff --git a/tests/integration/targets/vyos_firewall_global/tasks/main.yaml b/tests/integration/targets/vyos_firewall_global/tasks/main.yaml new file mode 100644 index 0000000..a3db933 --- /dev/null +++ b/tests/integration/targets/vyos_firewall_global/tasks/main.yaml @@ -0,0 +1,4 @@ +--- +- include: cli.yaml + tags: + - cli diff --git a/tests/integration/targets/vyos_firewall_global/tests/cli/_parsed_config.cfg b/tests/integration/targets/vyos_firewall_global/tests/cli/_parsed_config.cfg new file mode 100644 index 0000000..45446bd --- /dev/null +++ b/tests/integration/targets/vyos_firewall_global/tests/cli/_parsed_config.cfg @@ -0,0 +1,19 @@ +set firewall all-ping 'enable' +set firewall broadcast-ping 'enable' +set firewall config-trap 'enable' +set firewall group address-group MGMT-HOSTS address '192.0.1.1' +set firewall group address-group MGMT-HOSTS address '192.0.1.3' +set firewall group address-group MGMT-HOSTS address '192.0.1.5' +set firewall group address-group MGMT-HOSTS description 'This group has the Management hosts address list' +set firewall group network-group MGMT description 'This group has the Management network addresses' +set firewall group network-group MGMT network '192.0.1.0/24' +set firewall ip-src-route 'enable' +set firewall log-martians 'enable' +set firewall receive-redirects 'disable' +set firewall send-redirects 'enable' +set firewall source-validation 'strict' +set firewall state-policy established action 'accept' +set firewall state-policy established log 'enable' +set firewall state-policy invalid action 'reject' +set firewall syn-cookies 'enable' +set firewall twa-hazards-protection 'enable' diff --git a/tests/integration/targets/vyos_firewall_global/tests/cli/_populate.yaml b/tests/integration/targets/vyos_firewall_global/tests/cli/_populate.yaml new file mode 100644 index 0000000..f79bb9a --- /dev/null +++ b/tests/integration/targets/vyos_firewall_global/tests/cli/_populate.yaml @@ -0,0 +1,18 @@ +--- +- name: Setup + vars: + lines: "set firewall all-ping 'enable'\nset firewall broadcast-ping 'enable'\n\ + set firewall config-trap 'enable'\nset firewall group address-group MGMT-HOSTS\ + \ address '192.0.1.1'\nset firewall group address-group MGMT-HOSTS address\ + \ '192.0.1.3'\nset firewall group address-group MGMT-HOSTS address '192.0.1.5'\n\ + set firewall group address-group MGMT-HOSTS description 'This group has the\ + \ Management hosts address list'\nset firewall group network-group MGMT description\ + \ 'This group has the Management network addresses'\nset firewall group network-group\ + \ MGMT network '192.0.1.0/24'\nset firewall ip-src-route 'enable'\nset firewall\ + \ log-martians 'enable'\nset firewall receive-redirects 'disable'\nset firewall\ + \ send-redirects 'enable'\nset firewall source-validation 'strict'\nset firewall\ + \ state-policy established action 'accept'\nset firewall state-policy established\ + \ log 'enable'\nset firewall state-policy invalid action 'reject'\nset firewall\ + \ syn-cookies 'enable'\nset firewall twa-hazards-protection 'enable'\n" + ansible.netcommon.cli_config: + config: '{{ lines }}' diff --git a/tests/integration/targets/vyos_firewall_global/tests/cli/_remove_config.yaml b/tests/integration/targets/vyos_firewall_global/tests/cli/_remove_config.yaml new file mode 100644 index 0000000..5c86924 --- /dev/null +++ b/tests/integration/targets/vyos_firewall_global/tests/cli/_remove_config.yaml @@ -0,0 +1,6 @@ +--- +- name: Remove Config + vars: + lines: "delete firewall\n" + ansible.netcommon.cli_config: + config: '{{ lines }}' diff --git a/tests/integration/targets/vyos_firewall_global/tests/cli/deleted.yaml b/tests/integration/targets/vyos_firewall_global/tests/cli/deleted.yaml new file mode 100644 index 0000000..44df47c --- /dev/null +++ b/tests/integration/targets/vyos_firewall_global/tests/cli/deleted.yaml @@ -0,0 +1,48 @@ +--- +- debug: + msg: Start vyos_firewall_global deleted integration tests ansible_connection={{ + ansible_connection }} + +- include_tasks: _populate.yaml + +- block: + + - name: Delete attributes of firewall. + register: result + vyos.vyos.vyos_firewall_global: &id001 + config: + state: deleted + + - name: Assert that the before dicts were correctly generated + assert: + that: + - "{{ populate == result['before'] }}" + + - name: Assert that the correct set of commands were generated + assert: + that: + - "{{ deleted['commands'] | symmetric_difference(result['commands']) |length\ + \ == 0 }}" + + - name: Assert that the after dicts were correctly generated + assert: + that: + - "{{ deleted['after'] == result['after'] }}" + + - name: Delete attributes of given interfaces (IDEMPOTENT) + register: result + vyos.vyos.vyos_firewall_global: *id001 + + - name: Assert that the previous task was idempotent + assert: + that: + - result.changed == false + - result.commands|length == 0 + + - name: Assert that the before dicts were correctly generated + assert: + that: + - "{{ deleted['after'] == result['before'] }}" + always: + + - include_tasks: _remove_config.yaml diff --git a/tests/integration/targets/vyos_firewall_global/tests/cli/empty_config.yaml b/tests/integration/targets/vyos_firewall_global/tests/cli/empty_config.yaml new file mode 100644 index 0000000..3910952 --- /dev/null +++ b/tests/integration/targets/vyos_firewall_global/tests/cli/empty_config.yaml @@ -0,0 +1,49 @@ +--- +- debug: + msg: START vyos_firewall_global empty_config integration tests on connection={{ + ansible_connection }} + +- name: Merged with empty config should give appropriate error message + register: result + ignore_errors: true + vyos.vyos.vyos_firewall_global: + config: + state: merged + +- assert: + that: + - result.msg == 'value of config parameter must not be empty for state merged' + +- name: Replaced with empty config should give appropriate error message + register: result + ignore_errors: true + vyos.vyos.vyos_firewall_global: + config: + state: replaced + +- assert: + that: + - result.msg == 'value of config parameter must not be empty for state replaced' + +- name: Parsed with empty running_config should give appropriate error message + register: result + ignore_errors: true + vyos.vyos.vyos_firewall_global: + running_config: + state: parsed + +- assert: + that: + - result.msg == 'value of running_config parameter must not be empty for state + parsed' + +- name: Rendered with empty config should give appropriate error message + register: result + ignore_errors: true + vyos.vyos.vyos_firewall_global: + config: + state: rendered + +- assert: + that: + - result.msg == 'value of config parameter must not be empty for state rendered' diff --git a/tests/integration/targets/vyos_firewall_global/tests/cli/gathered.yaml b/tests/integration/targets/vyos_firewall_global/tests/cli/gathered.yaml new file mode 100644 index 0000000..eda24fd --- /dev/null +++ b/tests/integration/targets/vyos_firewall_global/tests/cli/gathered.yaml @@ -0,0 +1,33 @@ +--- +- debug: + msg: START vyos_firewall_global gathered integration tests on connection={{ + ansible_connection }} + +- include_tasks: _remove_config.yaml + +- include_tasks: _populate.yaml + +- block: + + - name: Merge the provided configuration with the exisiting running configuration + register: result + vyos.vyos.vyos_firewall_global: &id001 + config: + state: gathered + + - name: Assert that gathered dicts was correctly generated + assert: + that: + - "{{ populate == result['gathered'] }}" + + - name: Gather the existing running configuration (IDEMPOTENT) + register: result + vyos.vyos.vyos_firewall_global: *id001 + + - name: Assert that the previous task was idempotent + assert: + that: + - result['changed'] == false + always: + + - include_tasks: _remove_config.yaml diff --git a/tests/integration/targets/vyos_firewall_global/tests/cli/merged.yaml b/tests/integration/targets/vyos_firewall_global/tests/cli/merged.yaml new file mode 100644 index 0000000..4f22660 --- /dev/null +++ b/tests/integration/targets/vyos_firewall_global/tests/cli/merged.yaml @@ -0,0 +1,89 @@ +--- +- debug: + msg: START vyos_firewall_global merged integration tests on connection={{ ansible_connection + }} + +- include_tasks: _remove_config.yaml + +- block: + + - name: Merge the provided configuration with the exisiting running configuration + register: result + vyos.vyos.vyos_firewall_global: &id001 + config: + validation: strict + config_trap: true + log_martians: true + syn_cookies: true + twa_hazards_protection: true + ping: + all: true + broadcast: true + state_policy: + + - connection_type: established + action: accept + log: true + + - connection_type: invalid + action: reject + route_redirects: + + - afi: ipv4 + ip_src_route: true + icmp_redirects: + send: true + receive: false + group: + address_group: + + - name: MGMT-HOSTS + description: This group has the Management hosts address list + members: + + - address: 192.0.1.1 + + - address: 192.0.1.3 + + - address: 192.0.1.5 + network_group: + + - name: MGMT + description: This group has the Management network addresses + members: + + - address: 192.0.1.0/24 + state: merged + + - name: Assert that before dicts were correctly generated + assert: + that: "{{ merged['before'] == result['before'] }}" + + - name: Assert that correct set of commands were generated + assert: + that: + - "{{ merged['commands'] | symmetric_difference(result['commands']) |length\ + \ == 0 }}" + + - name: Assert that after dicts was correctly generated + assert: + that: + - "{{ merged['after'] == result['after'] }}" + + - name: Merge the provided configuration with the existing running configuration + (IDEMPOTENT) + register: result + vyos.vyos.vyos_firewall_global: *id001 + + - name: Assert that the previous task was idempotent + assert: + that: + - result['changed'] == false + + - name: Assert that before dicts were correctly generated + assert: + that: + - "{{ merged['after'] == result['before'] }}" + always: + + - include_tasks: _remove_config.yaml diff --git a/tests/integration/targets/vyos_firewall_global/tests/cli/parsed.yaml b/tests/integration/targets/vyos_firewall_global/tests/cli/parsed.yaml new file mode 100644 index 0000000..b94d95e --- /dev/null +++ b/tests/integration/targets/vyos_firewall_global/tests/cli/parsed.yaml @@ -0,0 +1,41 @@ +--- +- debug: + msg: START vyos_firewall_global parsed integration tests on connection={{ ansible_connection + }} + +- include_tasks: _remove_config.yaml + +- include_tasks: _populate.yaml + +- block: + + - name: Gather firewall_global facts + register: firewall_global_facts + vyos.vyos.vyos_facts: + gather_subset: + - default + gather_network_resources: + - firewall_global + + - name: Provide the running configuration for parsing (config to be parsed) + register: result + vyos.vyos.vyos_firewall_global: &id001 + running_config: "{{ lookup('file', '_parsed_config.cfg') }}" + state: parsed + + - name: Assert that correct parsing done + assert: + that: "{{ ansible_facts['network_resources']['firewall_global'] == result['parsed']\ + \ }}" + + - name: Gather the existing running configuration (IDEMPOTENT) + register: result + vyos.vyos.vyos_firewall_global: *id001 + + - name: Assert that the previous task was idempotent + assert: + that: + - result['changed'] == false + always: + + - include_tasks: _remove_config.yaml diff --git a/tests/integration/targets/vyos_firewall_global/tests/cli/rendered.yaml b/tests/integration/targets/vyos_firewall_global/tests/cli/rendered.yaml new file mode 100644 index 0000000..528563e --- /dev/null +++ b/tests/integration/targets/vyos_firewall_global/tests/cli/rendered.yaml @@ -0,0 +1,84 @@ +--- +- debug: + msg: START vyos_firewall_global rendered integration tests on connection={{ + ansible_connection }} + +- include_tasks: _remove_config.yaml + +- include_tasks: _populate.yaml + +- block: + + - name: Structure provided configuration into device specific commands + register: result + vyos.vyos.vyos_firewall_global: &id001 + config: + validation: strict + config_trap: true + log_martians: true + syn_cookies: true + twa_hazards_protection: true + ping: + all: true + broadcast: true + state_policy: + + - connection_type: established + action: accept + log: true + + - connection_type: invalid + action: reject + route_redirects: + + - afi: ipv4 + ip_src_route: true + icmp_redirects: + send: true + receive: false + group: + address_group: + + - name: SALES-HOSTS + description: Sales office hosts address list + members: + + - address: 192.0.2.1 + + - address: 192.0.2.2 + + - address: 192.0.2.3 + + - name: ENG-HOSTS + description: Sales office hosts address list + members: + + - address: 192.0.3.1 + + - address: 192.0.3.2 + network_group: + + - name: MGMT + description: This group has the Management network addresses + members: + + - address: 192.0.1.0/24 + state: rendered + + - name: Assert that correct set of commands were generated + assert: + that: + - "{{ rendered['commands'] | symmetric_difference(result['rendered'])\ + \ |length == 0 }}" + + - name: Structure provided configuration into device specific commands (IDEMPOTENT) + register: result + vyos.vyos.vyos_firewall_global: *id001 + + - name: Assert that the previous task was idempotent + assert: + that: + - result['changed'] == false + always: + + - include_tasks: _remove_config.yaml diff --git a/tests/integration/targets/vyos_firewall_global/tests/cli/replaced.yaml b/tests/integration/targets/vyos_firewall_global/tests/cli/replaced.yaml new file mode 100644 index 0000000..31a7644 --- /dev/null +++ b/tests/integration/targets/vyos_firewall_global/tests/cli/replaced.yaml @@ -0,0 +1,100 @@ +--- +- debug: + msg: START vyos_firewall_global replaced integration tests on connection={{ + ansible_connection }} + +- include_tasks: _remove_config.yaml + +- include_tasks: _populate.yaml + +- block: + + - name: Replace device configurations of listed firewall with provided configurations + register: result + vyos.vyos.vyos_firewall_global: &id001 + config: + validation: strict + config_trap: true + log_martians: true + syn_cookies: true + twa_hazards_protection: true + ping: + all: true + broadcast: true + state_policy: + + - connection_type: established + action: accept + log: true + + - connection_type: invalid + action: reject + route_redirects: + + - afi: ipv4 + ip_src_route: true + icmp_redirects: + send: true + receive: false + group: + address_group: + + - name: SALES-HOSTS + description: Sales office hosts address list + members: + + - address: 192.0.2.1 + + - address: 192.0.2.2 + + - address: 192.0.2.3 + + - name: ENG-HOSTS + description: Sales office hosts address list + members: + + - address: 192.0.3.1 + + - address: 192.0.3.2 + network_group: + + - name: MGMT + description: This group has the Management network addresses + members: + + - address: 192.0.1.0/24 + state: replaced + + - name: Assert that correct set of commands were generated + assert: + that: + - "{{ replaced['commands'] | symmetric_difference(result['commands'])\ + \ |length == 0 }}" + + - name: Assert that before dicts are correctly generated + assert: + that: + - "{{ populate == result['before'] }}" + + - name: Assert that after dict is correctly generated + assert: + that: + - "{{ replaced['after'] == result['after'] }}" + + - name: Replace device configurations of listed firewall with provided configurarions + (IDEMPOTENT) + register: result + vyos.vyos.vyos_firewall_global: *id001 + + - name: Assert that task was idempotent + assert: + that: + - result['changed'] == false + + - name: Assert that before dict is correctly generated + assert: + that: + - "{{ replaced['after'] == result['before'] }}" + always: + + - include_tasks: _remove_config.yaml diff --git a/tests/integration/targets/vyos_firewall_global/tests/cli/rtt.yaml b/tests/integration/targets/vyos_firewall_global/tests/cli/rtt.yaml new file mode 100644 index 0000000..00c5635 --- /dev/null +++ b/tests/integration/targets/vyos_firewall_global/tests/cli/rtt.yaml @@ -0,0 +1,94 @@ +--- +- debug: + msg: START vyos_firewall_global round trip integration tests on connection={{ + ansible_connection }} + +- include_tasks: _remove_config.yaml + +- block: + + - name: Apply the provided configuration (base config) + register: base_config + vyos.vyos.vyos_firewall_global: + config: + validation: strict + config_trap: true + log_martians: true + syn_cookies: true + twa_hazards_protection: true + ping: + all: true + broadcast: true + state_policy: + + - connection_type: established + action: accept + log: true + + - connection_type: invalid + action: reject + route_redirects: + + - afi: ipv4 + ip_src_route: true + icmp_redirects: + send: true + receive: false + group: + address_group: + + - name: MGMT-HOSTS + description: This group has the Management hosts address list + members: + + - address: 192.0.1.1 + + - address: 192.0.1.3 + + - address: 192.0.1.5 + network_group: + + - name: MGMT + description: This group has the Management network addresses + members: + + - address: 192.0.1.0/24 + state: merged + + - name: Gather firewall_global facts + vyos.vyos.vyos_facts: + gather_subset: + - default + gather_network_resources: + - firewall_global + + - name: Apply the provided configuration (config to be reverted) + register: result + vyos.vyos.vyos_firewall_global: + config: + validation: strict + config_trap: false + log_martians: false + syn_cookies: false + twa_hazards_protection: false + ping: + all: false + broadcast: false + state: merged + + - name: Assert that changes were applied + assert: + that: "{{ round_trip['after'] == result['after'] }}" + + - name: Revert back to base config using facts round trip + register: revert + vyos.vyos.vyos_firewall_global: + config: "{{ ansible_facts['network_resources']['firewall_global'] }}" + state: replaced + + - name: Assert that config was reverted + assert: + that: "{{ base_config['after'] == revert['after']}}" + always: + + - include_tasks: _remove_config.yaml diff --git a/tests/integration/targets/vyos_firewall_global/vars/main.yaml b/tests/integration/targets/vyos_firewall_global/vars/main.yaml new file mode 100644 index 0000000..4a1e7a8 --- /dev/null +++ b/tests/integration/targets/vyos_firewall_global/vars/main.yaml @@ -0,0 +1,217 @@ +--- +merged: + before: [] + commands: + - set firewall group address-group MGMT-HOSTS address 192.0.1.1 + - set firewall group address-group MGMT-HOSTS address 192.0.1.3 + - set firewall group address-group MGMT-HOSTS address 192.0.1.5 + - set firewall group address-group MGMT-HOSTS description 'This group has the + Management hosts address list' + - set firewall group address-group MGMT-HOSTS + - set firewall group network-group MGMT network 192.0.1.0/24 + - set firewall group network-group MGMT description 'This group has the Management + network addresses' + - set firewall group network-group MGMT + - set firewall ip-src-route 'enable' + - set firewall receive-redirects 'disable' + - set firewall send-redirects 'enable' + - set firewall config-trap 'enable' + - set firewall state-policy established action 'accept' + - set firewall state-policy established log 'enable' + - set firewall state-policy invalid action 'reject' + - set firewall broadcast-ping 'enable' + - set firewall all-ping 'enable' + - set firewall log-martians 'enable' + - set firewall twa-hazards-protection 'enable' + - set firewall syn-cookies 'enable' + - set firewall source-validation 'strict' + after: + config_trap: true + group: + address_group: + - members: + - address: 192.0.1.1 + - address: 192.0.1.3 + - address: 192.0.1.5 + description: This group has the Management hosts address list + name: MGMT-HOSTS + network_group: + - members: + - address: 192.0.1.0/24 + description: This group has the Management network addresses + name: MGMT + log_martians: true + ping: + all: true + broadcast: true + route_redirects: + - afi: ipv4 + icmp_redirects: + receive: false + send: true + ip_src_route: true + syn_cookies: true + state_policy: + - action: accept + connection_type: established + log: true + - action: reject + connection_type: invalid + twa_hazards_protection: true + validation: strict +populate: + validation: strict + config_trap: true + log_martians: true + syn_cookies: true + twa_hazards_protection: true + ping: + all: true + broadcast: true + state_policy: + - connection_type: established + action: accept + log: true + - connection_type: invalid + action: reject + route_redirects: + - afi: ipv4 + ip_src_route: true + icmp_redirects: + send: true + receive: false + group: + address_group: + - name: MGMT-HOSTS + description: This group has the Management hosts address list + members: + - address: 192.0.1.1 + - address: 192.0.1.3 + - address: 192.0.1.5 + network_group: + - name: MGMT + description: This group has the Management network addresses + members: + - address: 192.0.1.0/24 +replaced: + commands: + - delete firewall group address-group MGMT-HOSTS + - set firewall group address-group SALES-HOSTS address 192.0.2.1 + - set firewall group address-group SALES-HOSTS address 192.0.2.2 + - set firewall group address-group SALES-HOSTS address 192.0.2.3 + - set firewall group address-group SALES-HOSTS description 'Sales office hosts + address list' + - set firewall group address-group SALES-HOSTS + - set firewall group address-group ENG-HOSTS address 192.0.3.1 + - set firewall group address-group ENG-HOSTS address 192.0.3.2 + - set firewall group address-group ENG-HOSTS description 'Sales office hosts address + list' + - set firewall group address-group ENG-HOSTS + after: + config_trap: true + group: + address_group: + - members: + - address: 192.0.3.1 + - address: 192.0.3.2 + description: Sales office hosts address list + name: ENG-HOSTS + - members: + - address: 192.0.2.1 + - address: 192.0.2.2 + - address: 192.0.2.3 + description: Sales office hosts address list + name: SALES-HOSTS + network_group: + - members: + - address: 192.0.1.0/24 + description: This group has the Management network addresses + name: MGMT + log_martians: true + ping: + all: true + broadcast: true + route_redirects: + - afi: ipv4 + icmp_redirects: + receive: false + send: true + ip_src_route: true + state_policy: + - action: accept + connection_type: established + log: true + - action: reject + connection_type: invalid + syn_cookies: true + twa_hazards_protection: true + validation: strict +rendered: + commands: + - set firewall group address-group SALES-HOSTS address 192.0.2.1 + - set firewall group address-group SALES-HOSTS address 192.0.2.2 + - set firewall group address-group SALES-HOSTS address 192.0.2.3 + - set firewall group address-group SALES-HOSTS description 'Sales office hosts + address list' + - set firewall group address-group SALES-HOSTS + - set firewall group address-group ENG-HOSTS address 192.0.3.1 + - set firewall group address-group ENG-HOSTS address 192.0.3.2 + - set firewall group address-group ENG-HOSTS description 'Sales office hosts address + list' + - set firewall group address-group ENG-HOSTS + - set firewall group network-group MGMT network 192.0.1.0/24 + - set firewall group network-group MGMT description 'This group has the Management + network addresses' + - set firewall group network-group MGMT + - set firewall ip-src-route 'enable' + - set firewall receive-redirects 'disable' + - set firewall send-redirects 'enable' + - set firewall config-trap 'enable' + - set firewall state-policy established action 'accept' + - set firewall state-policy established log 'enable' + - set firewall state-policy invalid action 'reject' + - set firewall broadcast-ping 'enable' + - set firewall all-ping 'enable' + - set firewall log-martians 'enable' + - set firewall twa-hazards-protection 'enable' + - set firewall syn-cookies 'enable' + - set firewall source-validation 'strict' +deleted: + commands: + - 'delete firewall ' + after: [] +round_trip: + after: + validation: strict + config_trap: false + log_martians: false + syn_cookies: false + twa_hazards_protection: false + ping: + all: false + broadcast: false + state_policy: + - connection_type: established + action: accept + log: true + - connection_type: invalid + action: reject + route_redirects: + - afi: ipv4 + ip_src_route: true + icmp_redirects: + send: true + receive: false + group: + address_group: + - name: MGMT-HOSTS + description: This group has the Management hosts address list + members: + - address: 192.0.1.1 + - address: 192.0.1.3 + - address: 192.0.1.5 + network_group: + - name: MGMT + description: This group has the Management network addresses + members: + - address: 192.0.1.0/24 diff --git a/tests/integration/targets/vyos_firewall_rules/aliases b/tests/integration/targets/vyos_firewall_rules/aliases new file mode 100644 index 0000000..8071e1f --- /dev/null +++ b/tests/integration/targets/vyos_firewall_rules/aliases @@ -0,0 +1 @@ +shippable/vyos/group1 diff --git a/tests/integration/targets/vyos_lldp/aliases b/tests/integration/targets/vyos_lldp/aliases index 539d957..8071e1f 100644 --- a/tests/integration/targets/vyos_lldp/aliases +++ b/tests/integration/targets/vyos_lldp/aliases @@ -1 +1 @@ -shippable/network +shippable/vyos/group1 diff --git a/tests/integration/targets/vyos_lldp_global/aliases b/tests/integration/targets/vyos_lldp_global/aliases new file mode 100644 index 0000000..8071e1f --- /dev/null +++ b/tests/integration/targets/vyos_lldp_global/aliases @@ -0,0 +1 @@ +shippable/vyos/group1 diff --git a/tests/integration/targets/vyos_lldp_interface/aliases b/tests/integration/targets/vyos_lldp_interface/aliases index e69de29..8071e1f 100644 --- a/tests/integration/targets/vyos_lldp_interface/aliases +++ b/tests/integration/targets/vyos_lldp_interface/aliases @@ -0,0 +1 @@ +shippable/vyos/group1 diff --git a/tests/integration/targets/vyos_lldp_interfaces/aliases b/tests/integration/targets/vyos_lldp_interfaces/aliases new file mode 100644 index 0000000..8071e1f --- /dev/null +++ b/tests/integration/targets/vyos_lldp_interfaces/aliases @@ -0,0 +1 @@ +shippable/vyos/group1 diff --git a/tests/integration/targets/vyos_logging/aliases b/tests/integration/targets/vyos_logging/aliases index e69de29..8071e1f 100644 --- a/tests/integration/targets/vyos_logging/aliases +++ b/tests/integration/targets/vyos_logging/aliases @@ -0,0 +1 @@ +shippable/vyos/group1 diff --git a/tests/integration/targets/vyos_static_route/aliases b/tests/integration/targets/vyos_static_route/aliases index 539d957..8071e1f 100644 --- a/tests/integration/targets/vyos_static_route/aliases +++ b/tests/integration/targets/vyos_static_route/aliases @@ -1 +1 @@ -shippable/network +shippable/vyos/group1 diff --git a/tests/integration/targets/vyos_static_routes/aliases b/tests/integration/targets/vyos_static_routes/aliases new file mode 100644 index 0000000..8071e1f --- /dev/null +++ b/tests/integration/targets/vyos_static_routes/aliases @@ -0,0 +1 @@ +shippable/vyos/group1 diff --git a/tests/integration/targets/vyos_system/aliases b/tests/integration/targets/vyos_system/aliases new file mode 100644 index 0000000..8071e1f --- /dev/null +++ b/tests/integration/targets/vyos_system/aliases @@ -0,0 +1 @@ +shippable/vyos/group1 diff --git a/tests/integration/targets/vyos_user/aliases b/tests/integration/targets/vyos_user/aliases deleted file mode 100644 index e69de29..0000000 diff --git a/tests/integration/targets/vyos_vlan/aliases b/tests/integration/targets/vyos_vlan/aliases deleted file mode 100644 index e69de29..0000000 diff --git a/tests/unit/modules/network/vyos/fixtures/vyos_firewall_global_config.cfg b/tests/unit/modules/network/vyos/fixtures/vyos_firewall_global_config.cfg new file mode 100644 index 0000000..2a2a8e8 --- /dev/null +++ b/tests/unit/modules/network/vyos/fixtures/vyos_firewall_global_config.cfg @@ -0,0 +1,6 @@ +set firewall group address-group RND-HOSTS address 192.0.2.1 +set firewall group address-group RND-HOSTS address 192.0.2.3 +set firewall group address-group RND-HOSTS address 192.0.2.5 +set firewall group address-group RND-HOSTS description 'This group has the Management hosts address lists' +set firewall group network-group RND network 192.0.2.0/24 +set firewall group network-group RND description 'This group has the Management network addresses' diff --git a/tests/unit/modules/network/vyos/test_vyos_firewall_global.py b/tests/unit/modules/network/vyos/test_vyos_firewall_global.py new file mode 100644 index 0000000..0697f6e --- /dev/null +++ b/tests/unit/modules/network/vyos/test_vyos_firewall_global.py @@ -0,0 +1,254 @@ +# (c) 2016 Red Hat Inc. +# +# 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 . + +# Make coding more python3-ish +from __future__ import absolute_import, division, print_function + +__metaclass__ = type + +from ansible_collections.vyos.vyos.tests.unit.compat.mock import patch +from ansible_collections.vyos.vyos.plugins.modules import vyos_firewall_global +from ansible_collections.vyos.vyos.tests.unit.modules.utils import ( + set_module_args, +) +from .vyos_module import TestVyosModule, load_fixture + + +class TestVyosFirewallRulesModule(TestVyosModule): + + module = vyos_firewall_global + + def setUp(self): + super(TestVyosFirewallRulesModule, self).setUp() + self.mock_get_config = patch( + "ansible_collections.ansible.netcommon.plugins.module_utils.network.common.network.Config.get_config" + ) + self.get_config = self.mock_get_config.start() + + self.mock_load_config = patch( + "ansible_collections.ansible.netcommon.plugins.module_utils.network.common.network.Config.load_config" + ) + self.load_config = self.mock_load_config.start() + + self.mock_get_resource_connection_config = patch( + "ansible_collections.ansible.netcommon.plugins.module_utils.network.common.cfg.base.get_resource_connection" + ) + self.get_resource_connection_config = ( + self.mock_get_resource_connection_config.start() + ) + + self.mock_get_resource_connection_facts = patch( + "ansible_collections.ansible.netcommon.plugins.module_utils.network.common.facts.facts.get_resource_connection" + ) + self.get_resource_connection_facts = ( + self.mock_get_resource_connection_facts.start() + ) + + self.mock_execute_show_command = patch( + "ansible_collections.vyos.vyos.plugins.module_utils.network.vyos.facts.firewall_global.firewall_global.Firewall_globalFacts.get_device_data" + ) + + self.execute_show_command = self.mock_execute_show_command.start() + + def tearDown(self): + super(TestVyosFirewallRulesModule, self).tearDown() + self.mock_get_resource_connection_config.stop() + self.mock_get_resource_connection_facts.stop() + self.mock_get_config.stop() + self.mock_load_config.stop() + self.mock_execute_show_command.stop() + + def load_fixtures(self, commands=None): + def load_from_file(*args, **kwargs): + return load_fixture("vyos_firewall_global_config.cfg") + + self.execute_show_command.side_effect = load_from_file + + def test_vyos_firewall_global_set_01_merged(self): + set_module_args( + dict( + config=dict( + validation="strict", + config_trap=True, + log_martians=True, + syn_cookies=True, + twa_hazards_protection=True, + ping=dict(all=True, broadcast=True), + state_policy=[ + dict( + connection_type="established", + action="accept", + log=True, + ), + dict(connection_type="invalid", action="reject"), + ], + route_redirects=[ + dict( + afi="ipv4", + ip_src_route=True, + icmp_redirects=dict(send=True, receive=False), + ) + ], + group=dict( + address_group=[ + dict( + name="MGMT-HOSTS", + description="This group has the Management hosts address lists", + members=[ + dict(address="192.0.1.1"), + dict(address="192.0.1.3"), + dict(address="192.0.1.5"), + ], + ) + ], + network_group=[ + dict( + name="MGMT", + description="This group has the Management network addresses", + members=[dict(address="192.0.1.0/24")], + ) + ], + ), + ), + state="merged", + ) + ) + commands = [ + "set firewall group address-group MGMT-HOSTS address 192.0.1.1", + "set firewall group address-group MGMT-HOSTS address 192.0.1.3", + "set firewall group address-group MGMT-HOSTS address 192.0.1.5", + "set firewall group address-group MGMT-HOSTS description 'This group has the Management hosts address lists'", + "set firewall group address-group MGMT-HOSTS", + "set firewall group network-group MGMT network 192.0.1.0/24", + "set firewall group network-group MGMT description 'This group has the Management network addresses'", + "set firewall group network-group MGMT", + "set firewall ip-src-route 'enable'", + "set firewall receive-redirects 'disable'", + "set firewall send-redirects 'enable'", + "set firewall config-trap 'enable'", + "set firewall state-policy established action 'accept'", + "set firewall state-policy established log 'enable'", + "set firewall state-policy invalid action 'reject'", + "set firewall broadcast-ping 'enable'", + "set firewall all-ping 'enable'", + "set firewall log-martians 'enable'", + "set firewall twa-hazards-protection 'enable'", + "set firewall syn-cookies 'enable'", + "set firewall source-validation 'strict'", + ] + self.execute_module(changed=True, commands=commands) + + def test_vyos_firewall_global_set_01_merged_idem(self): + set_module_args( + dict( + config=dict( + group=dict( + address_group=[ + dict( + name="RND-HOSTS", + description="This group has the Management hosts address lists", + members=[ + dict(address="192.0.2.1"), + dict(address="192.0.2.3"), + dict(address="192.0.2.5"), + ], + ) + ], + network_group=[ + dict( + name="RND", + description="This group has the Management network addresses", + members=[dict(address="192.0.2.0/24")], + ) + ], + ) + ), + state="merged", + ) + ) + self.execute_module(changed=False, commands=[]) + + def test_vyos_firewall_global_set_01_replaced(self): + set_module_args( + dict( + config=dict( + group=dict( + address_group=[ + dict( + name="RND-HOSTS", + description="This group has the Management hosts address lists", + members=[ + dict(address="192.0.2.1"), + dict(address="192.0.2.7"), + dict(address="192.0.2.9"), + ], + ) + ], + network_group=[ + dict( + name="RND", + description="This group has the Management network addresses", + members=[dict(address="192.0.2.0/24")], + ) + ], + ) + ), + state="replaced", + ) + ) + commands = [ + "delete firewall group address-group RND-HOSTS address 192.0.2.3", + "delete firewall group address-group RND-HOSTS address 192.0.2.5", + "set firewall group address-group RND-HOSTS address 192.0.2.7", + "set firewall group address-group RND-HOSTS address 192.0.2.9", + ] + self.execute_module(changed=True, commands=commands) + + def test_vyos_firewall_global_set_01_replaced_idem(self): + set_module_args( + dict( + config=dict( + group=dict( + address_group=[ + dict( + name="RND-HOSTS", + description="This group has the Management hosts address lists", + members=[ + dict(address="192.0.2.1"), + dict(address="192.0.2.3"), + dict(address="192.0.2.5"), + ], + ) + ], + network_group=[ + dict( + name="RND", + description="This group has the Management network addresses", + members=[dict(address="192.0.2.0/24")], + ) + ], + ) + ), + state="replaced", + ) + ) + self.execute_module(changed=False, commands=[]) + + def test_vyos_firewall_global_set_01_deleted(self): + set_module_args(dict(config=dict(), state="deleted")) + commands = ["delete firewall "] + self.execute_module(changed=True, commands=commands)