diff options
42 files changed, 3659 insertions, 7 deletions
| diff --git a/tests/integration/targets/vyos_interface/aliases b/plugins/module_utils/network/vyos/argspec/firewall_global/__init__.py index e69de29..e69de29 100644 --- a/tests/integration/targets/vyos_interface/aliases +++ b/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 index e69de29..e69de29 100644 --- a/tests/integration/targets/vyos_l3_interface/aliases +++ b/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 @@ -33,6 +33,9 @@ from ansible_collections.vyos.vyos.plugins.module_utils.network.vyos.facts.firew  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, @@ -49,6 +52,7 @@ FACT_RESOURCE_SUBSETS = dict(      lldp_interfaces=Lldp_interfacesFacts,      static_routes=Static_routesFacts,      firewall_rules=Firewall_rulesFacts, +    firewall_global=Firewall_globalFacts,  ) diff --git a/tests/integration/targets/vyos_linkagg/aliases b/plugins/module_utils/network/vyos/facts/firewall_global/__init__.py index e69de29..e69de29 100644 --- a/tests/integration/targets/vyos_linkagg/aliases +++ b/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 @@ -47,7 +47,7 @@ options:        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  """ 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 --- a/tests/integration/targets/vyos_user/aliases +++ /dev/null diff --git a/tests/integration/targets/vyos_vlan/aliases b/tests/integration/targets/vyos_vlan/aliases deleted file mode 100644 index e69de29..0000000 --- a/tests/integration/targets/vyos_vlan/aliases +++ /dev/null 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 <http://www.gnu.org/licenses/>. + +# 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) | 
