From b28632c3e581371f3b0d670d376ab409a4b8fa0e Mon Sep 17 00:00:00 2001 From: Andrew Gunnerson <accounts+github@chiller3.com> Date: Fri, 25 Feb 2022 13:28:54 -0500 Subject: firewall_rules: Fix incorrect behavior when IPv4 and IPv6 rule sets have the same name (#236) firewall_rules: Fix incorrect behavior when IPv4 and IPv6 rule sets have the same name SUMMARY VyOS supports IPv4 and IPv6 rule sets having the same name, but there are a couple places in the Ansible module that don't handle this situation. The fact gathering for ansible_network_resources.firewall_rules has been updated to look for name <name> or ipv6-name <name> instead of just <name>. The vyos_firewall_rules module has been updated to take the afi into consideration when comparing the have and want states. V4-EGRESS and V6-EGRESS have been renamed to just EGRESS in the tests. The existing tests seem to be complete enough to test this same-name situation. (V4-INGRESS and V6-INGRESS were not renamed.) ISSUE TYPE Bugfix Pull Request COMPONENT NAME vyos_facts and vyos_firewall_rules ADDITIONAL INFORMATION An example of a configuration that was originally causing an issue: (Click to expand): name wan-lan { default-action drop rule 1 { action accept state { established enable related enable } } rule 2 { action drop log enable state { invalid enable } } } ipv6-name wan-lan { default-action drop rule 1 { action accept state { established enable related enable } } rule 2 { action drop log enable state { invalid enable } } rule 10 { action accept protocol icmpv6 } } With this configuration, ansible_network_resources.firewall_rules would show the icmpv6 rule under both ipv4 and ipv6: (Click to expand): [ { "afi": "ipv4", "rule_sets": [ { "default_action": "drop", "name": "wan-lan", "rules": [ { "action": "accept", "number": 1, "state": { "established": true, "related": true } }, { "action": "drop", "number": 2, "state": { "invalid": true } }, { "action": "accept", "number": 10, "protocol": "icmpv6" } ] }, ] }, { "afi": "ipv6", "rule_sets": [ { "default_action": "drop", "name": "wan-lan", "rules": [ { "action": "accept", "number": 1, "state": { "established": true, "related": true } }, { "action": "drop", "number": 2, "state": { "invalid": true } }, { "action": "accept", "number": 10, "protocol": "icmpv6" } ] }, ] } ] A similar issue would happen when using vyos_firewall_rules as well, where it would attempt to change rules for the wrong afi. Reviewed-by: GomathiselviS <None> Reviewed-by: None <None> --- .../vyos/config/firewall_rules/firewall_rules.py | 24 ++++++++++++++-------- .../vyos/facts/firewall_rules/firewall_rules.py | 3 ++- 2 files changed, 17 insertions(+), 10 deletions(-) (limited to 'plugins') diff --git a/plugins/module_utils/network/vyos/config/firewall_rules/firewall_rules.py b/plugins/module_utils/network/vyos/config/firewall_rules/firewall_rules.py index 1f1536c5..22973bd7 100644 --- a/plugins/module_utils/network/vyos/config/firewall_rules/firewall_rules.py +++ b/plugins/module_utils/network/vyos/config/firewall_rules/firewall_rules.py @@ -176,7 +176,7 @@ class Firewall_rules(ConfigBase): # already have (to be replaced by our desired # configuration's rule set). wanted_rule_set = self.search_r_sets_in_have( - want, rs["name"], "r_list" + want, rs["name"], "r_list", h["afi"] ) if wanted_rule_set is not None: # Remove the rules that we already have if the wanted @@ -205,7 +205,9 @@ class Firewall_rules(ConfigBase): for h in have: r_sets = self._get_r_sets(h) for rs in r_sets: - w = self.search_r_sets_in_have(want, rs["name"], "r_list") + w = self.search_r_sets_in_have( + want, rs["name"], "r_list", h["afi"] + ) if not w: commands.append( self._compute_command( @@ -230,7 +232,9 @@ class Firewall_rules(ConfigBase): for w in want: r_sets = self._get_r_sets(w) for rs in r_sets: - h = self.search_r_sets_in_have(have, rs["name"], "r_list") + h = self.search_r_sets_in_have( + have, rs["name"], "r_list", w["afi"] + ) commands.extend(self._add_r_sets(w["afi"], rs, h)) return commands @@ -248,7 +252,7 @@ class Firewall_rules(ConfigBase): if r_sets: for rs in r_sets: h = self.search_r_sets_in_have( - have, rs["name"], "r_list" + have, rs["name"], "r_list", w["afi"] ) if h: commands.append( @@ -842,12 +846,13 @@ class Firewall_rules(ConfigBase): ) return commands - def search_r_sets_in_have(self, have, w_name, type="rule_sets"): + def search_r_sets_in_have(self, have, w_name, type="rule_sets", afi=None): """ This function returns the rule-set/rule if it is present in target config. :param have: target config. :param w_name: rule-set name. :param type: rule_sets/rule/r_list. + :param afi: address family (when type is r_list). :return: rule-set/rule. """ if have: @@ -859,10 +864,11 @@ class Firewall_rules(ConfigBase): return r elif type == "r_list": for h in have: - r_sets = self._get_r_sets(h) - for rs in r_sets: - if rs[key] == w_name: - return rs + if h["afi"] == afi: + r_sets = self._get_r_sets(h) + for rs in r_sets: + if rs[key] == w_name: + return rs else: for rs in have: if rs[key] == w_name: diff --git a/plugins/module_utils/network/vyos/facts/firewall_rules/firewall_rules.py b/plugins/module_utils/network/vyos/facts/firewall_rules/firewall_rules.py index 8e29dbd7..f1c080f6 100644 --- a/plugins/module_utils/network/vyos/facts/firewall_rules/firewall_rules.py +++ b/plugins/module_utils/network/vyos/facts/firewall_rules/firewall_rules.py @@ -100,7 +100,8 @@ class Firewall_rulesFacts(object): r_v4 = [] r_v6 = [] for r in set(rules): - rule_regex = r" %s .+$" % r.strip("'") + name_key = "ipv6-name" if type == "ipv6" else "name" + rule_regex = r" %s %s .+$" % (name_key, r.strip("'")) cfg = findall(rule_regex, data, M) fr = self.render_config(cfg, r.strip("'")) fr["name"] = r.strip("'") -- cgit v1.2.3