diff --git a/changelogs/fragments/143-add-extra-attributes-to-firewall-rules.yml b/changelogs/fragments/143-add-extra-attributes-to-firewall-rules.yml
new file mode 100644
index 00000000..615c7d6b
--- /dev/null
+++ b/changelogs/fragments/143-add-extra-attributes-to-firewall-rules.yml
@@ -0,0 +1,3 @@
+---
+bugfixes:
+ - firewall_rules_utils - Handle additional XML attributes fo the firewall rule objects from the config.
\ No newline at end of file
diff --git a/molecule/firewall_rules/converge.yml b/molecule/firewall_rules/converge.yml
index 5255d0f0..fbda4709 100644
--- a/molecule/firewall_rules/converge.yml
+++ b/molecule/firewall_rules/converge.yml
@@ -3,1037 +3,269 @@
hosts: all
become: true
tasks:
- # Test basic functionality with different actions
- - name: "Action: Test pass action"
- puzzle.opnsense.firewall_rules:
- interface: 'lan'
- action: 'pass'
- description: "New Test pass Rule"
- source:
- destination:
-
- - name: "Action: Test block action"
- puzzle.opnsense.firewall_rules:
- interface: 'lan'
- action: 'block'
- description: "New Test block Rule"
-
- - name: "Action: Test reject action"
- puzzle.opnsense.firewall_rules:
- interface: 'lan'
- action: 'reject'
- description: "New Test reject Rule"
-
- # Test basic functionality of the disabled button
- - name: "Disabled: Test disabled button"
- puzzle.opnsense.firewall_rules:
- interface: 'lan'
- action: 'pass'
- description: "New Test disabled pass Rule"
- disabled: true
-
- # Test basic functionality of the disabled quick button
- - name: "Quick: Test pass Rule with quick disabled"
- puzzle.opnsense.firewall_rules:
- interface: 'lan'
- action: 'pass'
- quick: false
- description: "New Test pass Rule with quick disabled"
-
- # Test different Interfaces
- - name: "Interface: Test pass Rule"
- puzzle.opnsense.firewall_rules:
- interface: 'lan'
- action: 'pass'
- description: "New Test pass Rule of Interface lan"
-
- - name: "Interface: Test pass Rule"
- puzzle.opnsense.firewall_rules:
- interface: 'lo0'
- action: 'pass'
- description: "New Test pass Rule of Interface Loopback"
-
- - name: "Interface: Test pass Rule"
- puzzle.opnsense.firewall_rules:
- interface: 'openvpn'
- action: 'pass'
- description: "New Test pass Rule of Interface OpenVPN"
-
- - name: "Interface: Test pass Rule"
- puzzle.opnsense.firewall_rules:
- interface: 'opt2'
- action: 'pass'
- description: "New Test pass Rule of Interface VAGRANT"
-
- # Test different Directions
- - name: "Direction: Test pass Rule with Direction in"
- puzzle.opnsense.firewall_rules:
- interface: 'lan'
- action: 'pass'
- direction: in
- description: "New Test pass Rule with Direction in"
-
- - name: "Direction: Test pass Rule with Direction out"
- puzzle.opnsense.firewall_rules:
- interface: 'lan'
- action: 'pass'
- direction: out
- description: "New Test pass Rule with Direction out"
-
- # Test different IPProtocols
- - name: "IPProtocol: Test pass Rule with IPProtocol IPv4"
- puzzle.opnsense.firewall_rules:
- interface: 'lan'
- action: 'pass'
- ipprotocol: 'inet'
- description: "New Test pass Rule with IPv4"
-
- - name: "IPProtocol: Test pass Rule with IPProtocol IPv6"
- puzzle.opnsense.firewall_rules:
- interface: 'lan'
- action: 'pass'
- ipprotocol: 'inet6'
- description: "New Test pass Rule with IPProtocol IPv6"
-
- - name: "IPProtocol: Test pass Rule with IPProtocol IPv4 + IPv6"
- puzzle.opnsense.firewall_rules:
- interface: 'lan'
- action: 'pass'
- ipprotocol: 'inet46'
- description: "New Test pass Rule with IPProtocol IPv4 + IPv6"
-
- # Test different Protocols
- - name: "Protocol: Test pass Rule with Protocol any"
- puzzle.opnsense.firewall_rules:
- interface: 'lan'
- action: 'pass'
- protocol: 'any'
- description: "New Test pass Rule with Protocol any"
-
- - name: "Protocol: Test pass Rule with Protocol tcp"
- puzzle.opnsense.firewall_rules:
- interface: 'lan'
- action: 'pass'
- protocol: 'tcp'
- description: "New Test pass Rule with Protocol tcp"
-
- - name: "Protocol: Test pass Rule with Protocol udp"
- puzzle.opnsense.firewall_rules:
- interface: 'lan'
- action: 'pass'
- protocol: 'udp'
- description: "New Test pass Rule with Protocol udp"
-
- - name: "Protocol: Test pass Rule with Protocol tcp/udp"
- puzzle.opnsense.firewall_rules:
- interface: 'lan'
- action: 'pass'
- protocol: 'tcp/udp'
- description: "New Test pass Rule with Protocol tcp/udp"
-
- - name: "Protocol: Test pass Rule with Protocol icmp"
- puzzle.opnsense.firewall_rules:
- interface: 'lan'
- action: 'pass'
- protocol: 'icmp'
- description: "New Test pass Rule with Protocol icmp"
-
- - name: "Protocol: Test pass Rule with Protocol esp"
- puzzle.opnsense.firewall_rules:
- interface: 'lan'
- action: 'pass'
- protocol: 'esp'
- description: "New Test pass Rule with Protocol esp"
-
- - name: "Protocol: Test pass Rule with Protocol ah"
- puzzle.opnsense.firewall_rules:
- interface: 'lan'
- action: 'pass'
- protocol: 'ah'
- description: "New Test pass Rule with Protocol ah"
-
- - name: "Protocol: Test pass Rule with Protocol gre"
- puzzle.opnsense.firewall_rules:
- interface: 'lan'
- action: 'pass'
- protocol: 'gre'
- description: "New Test pass Rule with Protocol gre"
-
- - name: "Protocol: Test pass Rule with Protocol igmp"
- puzzle.opnsense.firewall_rules:
- interface: 'lan'
- action: 'pass'
- protocol: 'igmp'
- description: "New Test pass Rule with Protocol igmp"
-
- - name: "Protocol: Test pass Rule with Protocol pim"
- puzzle.opnsense.firewall_rules:
- interface: 'lan'
- action: 'pass'
- protocol: 'pim'
- description: "New Test pass Rule with Protocol pim"
-
- - name: "Protocol: Test pass Rule with Protocol ospf"
- puzzle.opnsense.firewall_rules:
- interface: 'lan'
- action: 'pass'
- protocol: 'ospf'
- description: "New Test pass Rule with Protocol ospf"
-
- - name: "Protocol: Test pass Rule with Protocol ggp"
- puzzle.opnsense.firewall_rules:
- interface: 'lan'
- action: 'pass'
- protocol: 'ggp'
- description: "New Test pass Rule with Protocol ggp"
-
- - name: "Protocol: Test pass Rule with Protocol ipencap"
- puzzle.opnsense.firewall_rules:
- interface: 'lan'
- action: 'pass'
- protocol: 'ipencap'
- description: "New Test pass Rule with Protocol ipencap"
-
- - name: "Protocol: Test pass Rule with Protocol st2"
- puzzle.opnsense.firewall_rules:
- interface: 'lan'
- action: 'pass'
- protocol: 'st2'
- description: "New Test pass Rule with Protocol st2"
-
- - name: "Protocol: Test pass Rule with Protocol cbt"
- puzzle.opnsense.firewall_rules:
- interface: 'lan'
- action: 'pass'
- protocol: 'cbt'
- description: "New Test pass Rule with Protocol cbt"
-
- - name: "Protocol: Test pass Rule with Protocol egp"
- puzzle.opnsense.firewall_rules:
- interface: 'lan'
- action: 'pass'
- protocol: 'egp'
- description: "New Test pass Rule with Protocol egp"
-
- - name: "Protocol: Test pass Rule with Protocol igp"
- puzzle.opnsense.firewall_rules:
- interface: 'lan'
- action: 'pass'
- protocol: 'igp'
- description: "New Test pass Rule with Protocol igp"
-
- - name: "Protocol: Test pass Rule with Protocol bbn-rcc"
- puzzle.opnsense.firewall_rules:
- interface: 'lan'
- action: 'pass'
- protocol: 'bbn-rcc'
- description: "New Test pass Rule with Protocol bbn-rcc"
-
- - name: "Protocol: Test pass Rule with Protocol nvp"
- puzzle.opnsense.firewall_rules:
- interface: 'lan'
- action: 'pass'
- protocol: 'nvp'
- description: "New Test pass Rule with Protocol nvp"
-
- - name: "Protocol: Test pass Rule with Protocol pup"
- puzzle.opnsense.firewall_rules:
- interface: 'lan'
- action: 'pass'
- protocol: 'pup'
- description: "New Test pass Rule with Protocol pup"
-
- - name: "Protocol: Test pass Rule with Protocol argus"
- puzzle.opnsense.firewall_rules:
- interface: 'lan'
- action: 'pass'
- protocol: 'argus'
- description: "New Test pass Rule with Protocol argus"
-
- - name: "Protocol: Test pass Rule with Protocol emcon"
- puzzle.opnsense.firewall_rules:
- interface: 'lan'
- action: 'pass'
- protocol: 'emcon'
- description: "New Test pass Rule with Protocol emcon"
-
- - name: "Protocol: Test pass Rule with Protocol xnet"
- puzzle.opnsense.firewall_rules:
- interface: 'lan'
- action: 'pass'
- protocol: 'xnet'
- description: "New Test pass Rule with Protocol xnet"
-
- - name: "Protocol: Test pass Rule with Protocol chaos"
- puzzle.opnsense.firewall_rules:
- interface: 'lan'
- action: 'pass'
- protocol: 'chaos'
- description: "New Test pass Rule with Protocol chaos"
-
- - name: "Protocol: Test pass Rule with Protocol mux"
- puzzle.opnsense.firewall_rules:
- interface: 'lan'
- action: 'pass'
- protocol: 'mux'
- description: "New Test pass Rule with Protocol mux"
-
- - name: "Protocol: Test pass Rule with Protocol dcn"
- puzzle.opnsense.firewall_rules:
- interface: 'lan'
- action: 'pass'
- protocol: 'dcn'
- description: "New Test pass Rule with Protocol dcn"
-
- - name: "Protocol: Test pass Rule with Protocol hmp"
- puzzle.opnsense.firewall_rules:
- interface: 'lan'
- action: 'pass'
- protocol: 'hmp'
- description: "New Test pass Rule with Protocol hmp"
-
- - name: "Protocol: Test pass Rule with Protocol prm"
- puzzle.opnsense.firewall_rules:
- interface: 'lan'
- action: 'pass'
- protocol: 'prm'
- description: "New Test pass Rule with Protocol prm"
-
- - name: "Protocol: Test pass Rule with Protocol xns-idp"
- puzzle.opnsense.firewall_rules:
- interface: 'lan'
- action: 'pass'
- protocol: 'xns-idp'
- description: "New Test pass Rule with Protocol xns-idp"
-
- - name: "Protocol: Test pass Rule with Protocol trunk-1"
- puzzle.opnsense.firewall_rules:
- interface: 'lan'
- action: 'pass'
- protocol: 'trunk-1'
- description: "New Test pass Rule with Protocol trunk-1"
-
- - name: "Protocol: Test pass Rule with Protocol trunk-2"
- puzzle.opnsense.firewall_rules:
- interface: 'lan'
- action: 'pass'
- protocol: 'trunk-2'
- description: "New Test pass Rule with Protocol trunk-2"
-
- - name: "Protocol: Test pass Rule with Protocol leaf-1"
- puzzle.opnsense.firewall_rules:
- interface: 'lan'
- action: 'pass'
- protocol: 'leaf-1'
- description: "New Test pass Rule with Protocol leaf-1"
-
- - name: "Protocol: Test pass Rule with Protocol leaf-2"
- puzzle.opnsense.firewall_rules:
- interface: 'lan'
- action: 'pass'
- protocol: 'leaf-2'
- description: "New Test pass Rule with Protocol leaf-2"
-
- - name: "Protocol: Test pass Rule with Protocol rdp"
- puzzle.opnsense.firewall_rules:
- interface: 'lan'
- action: 'pass'
- protocol: 'rdp'
- description: "New Test pass Rule with Protocol rdp"
-
- - name: "Protocol: Test pass Rule with Protocol irtp"
- puzzle.opnsense.firewall_rules:
- interface: 'lan'
- action: 'pass'
- protocol: 'irtp'
- description: "New Test pass Rule with Protocol irtp"
-
- - name: "Protocol: Test pass Rule with Protocol iso-tp4"
- puzzle.opnsense.firewall_rules:
- interface: 'lan'
- action: 'pass'
- protocol: 'iso-tp4'
- description: "New Test pass Rule with Protocol iso-tp4"
-
- - name: "Protocol: Test pass Rule with Protocol netblt"
- puzzle.opnsense.firewall_rules:
- interface: 'lan'
- action: 'pass'
- protocol: 'netblt'
- description: "New Test pass Rule with Protocol netblt"
-
- - name: "Protocol: Test pass Rule with Protocol mfe-nsp"
- puzzle.opnsense.firewall_rules:
- interface: 'lan'
- action: 'pass'
- protocol: 'mfe-nsp'
- description: "New Test pass Rule with Protocol mfe-nsp"
-
- - name: "Protocol: Test pass Rule with Protocol merit-inp"
- puzzle.opnsense.firewall_rules:
- interface: 'lan'
- action: 'pass'
- protocol: 'merit-inp'
- description: "New Test pass Rule with Protocol merit-inp"
-
- - name: "Protocol: Test pass Rule with Protocol dccp"
- puzzle.opnsense.firewall_rules:
- interface: 'lan'
- action: 'pass'
- protocol: 'dccp'
- description: "New Test pass Rule with Protocol dccp"
-
- - name: "Protocol: Test pass Rule with Protocol 3pc"
- puzzle.opnsense.firewall_rules:
- interface: 'lan'
- action: 'pass'
- protocol: '3pc'
- description: "New Test pass Rule with Protocol 3pc"
-
- - name: "Protocol: Test pass Rule with Protocol idpr"
- puzzle.opnsense.firewall_rules:
- interface: 'lan'
- action: 'pass'
- protocol: 'idpr'
- description: "New Test pass Rule with Protocol idpr"
-
- - name: "Protocol: Test pass Rule with Protocol xtp"
- puzzle.opnsense.firewall_rules:
- interface: 'lan'
- action: 'pass'
- protocol: 'xtp'
- description: "New Test pass Rule with Protocol xtp"
-
- - name: "Protocol: Test pass Rule with Protocol ddp"
- puzzle.opnsense.firewall_rules:
- interface: 'lan'
- action: 'pass'
- protocol: 'ddp'
- description: "New Test pass Rule with Protocol ddp"
-
- - name: "Protocol: Test pass Rule with Protocol idpr-cmtp"
- puzzle.opnsense.firewall_rules:
- interface: 'lan'
- action: 'pass'
- protocol: 'idpr-cmtp'
- description: "New Test pass Rule with Protocol idpr-cmtp"
-
- - name: "Protocol: Test pass Rule with Protocol tp++"
- puzzle.opnsense.firewall_rules:
- interface: 'lan'
- action: 'pass'
- protocol: 'tp++'
- description: "New Test pass Rule with Protocol tp++"
-
- - name: "Protocol: Test pass Rule with Protocol il"
- puzzle.opnsense.firewall_rules:
- interface: 'lan'
- action: 'pass'
- protocol: 'il'
- description: "New Test pass Rule with Protocol il"
-
- - name: "Protocol: Test pass Rule with Protocol ipv6"
- puzzle.opnsense.firewall_rules:
- interface: 'lan'
- action: 'pass'
- protocol: 'ipv6'
- description: "New Test pass Rule with Protocol ipv6"
-
- - name: "Protocol: Test pass Rule with Protocol sdrp"
- puzzle.opnsense.firewall_rules:
- interface: 'lan'
- action: 'pass'
- protocol: 'sdrp'
- description: "New Test pass Rule with Protocol sdrp"
-
- - name: "Protocol: Test pass Rule with Protocol idrp"
- puzzle.opnsense.firewall_rules:
- interface: 'lan'
- action: 'pass'
- protocol: 'idrp'
- description: "New Test pass Rule with Protocol idrp"
-
- - name: "Protocol: Test pass Rule with Protocol rsvp"
- puzzle.opnsense.firewall_rules:
- interface: 'lan'
- action: 'pass'
- protocol: 'rsvp'
- description: "New Test pass Rule with Protocol rsvp"
-
- - name: "Protocol: Test pass Rule with Protocol dsr"
- puzzle.opnsense.firewall_rules:
- interface: 'lan'
- action: 'pass'
- protocol: 'dsr'
- description: "New Test pass Rule with Protocol dsr"
-
- - name: "Protocol: Test pass Rule with Protocol bna"
- puzzle.opnsense.firewall_rules:
- interface: 'lan'
- action: 'pass'
- protocol: 'bna'
- description: "New Test pass Rule with Protocol bna"
-
- - name: "Protocol: Test pass Rule with Protocol i-nlsp"
- puzzle.opnsense.firewall_rules:
- interface: 'lan'
- action: 'pass'
- protocol: 'i-nlsp'
- description: "New Test pass Rule with Protocol i-nlsp"
-
- - name: "Protocol: Test pass Rule with Protocol swipe"
- puzzle.opnsense.firewall_rules:
- interface: 'lan'
- action: 'pass'
- protocol: 'swipe'
- description: "New Test pass Rule with Protocol swipe"
-
- - name: "Protocol: Test pass Rule with Protocol narp"
- puzzle.opnsense.firewall_rules:
- interface: 'lan'
- action: 'pass'
- protocol: 'narp'
- description: "New Test pass Rule with Protocol narp"
-
- - name: "Protocol: Test pass Rule with Protocol mobile"
- puzzle.opnsense.firewall_rules:
- interface: 'lan'
- action: 'pass'
- protocol: 'mobile'
- description: "New Test pass Rule with Protocol mobile"
-
- - name: "Protocol: Test pass Rule with Protocol tlsp"
- puzzle.opnsense.firewall_rules:
- interface: 'lan'
- action: 'pass'
- protocol: 'tlsp'
- description: "New Test pass Rule with Protocol tlsp"
-
-
- - name: "Protocol: Test pass Rule with Protocol skip"
- puzzle.opnsense.firewall_rules:
- interface: 'lan'
- action: 'pass'
- protocol: 'skip'
- description: "New Test pass Rule with Protocol skip"
-
- - name: "Protocol: Test pass Rule with Protocol ipv6-icmp"
- puzzle.opnsense.firewall_rules:
- interface: 'lan'
- action: 'pass'
- protocol: 'ipv6-icmp'
- description: "New Test pass Rule with Protocol ipv6-icmp"
-
- - name: "Protocol: Test pass Rule with Protocol cftp"
- puzzle.opnsense.firewall_rules:
- interface: 'lan'
- action: 'pass'
- protocol: 'cftp'
- description: "New Test pass Rule with Protocol cftp"
-
- - name: "Protocol: Test pass Rule with Protocol sat-expak"
- puzzle.opnsense.firewall_rules:
- interface: 'lan'
- action: 'pass'
- protocol: 'sat-expak'
- description: "New Test pass Rule with Protocol sat-expak"
-
- - name: "Protocol: Test pass Rule with Protocol kryptolan"
- puzzle.opnsense.firewall_rules:
- interface: 'lan'
- action: 'pass'
- protocol: 'kryptolan'
- description: "New Test pass Rule with Protocol kryptolan"
-
- - name: "Protocol: Test pass Rule with Protocol rvd"
- puzzle.opnsense.firewall_rules:
- interface: 'lan'
- action: 'pass'
- protocol: 'rvd'
- description: "New Test pass Rule with Protocol rvd"
-
- - name: "Protocol: Test pass Rule with Protocol ippc"
- puzzle.opnsense.firewall_rules:
- interface: 'lan'
- action: 'pass'
- protocol: 'ippc'
- description: "New Test pass Rule with Protocol ippc"
-
- - name: "Protocol: Test pass Rule with Protocol sat-mon"
- puzzle.opnsense.firewall_rules:
- interface: 'lan'
- action: 'pass'
- protocol: 'sat-mon'
- description: "New Test pass Rule with Protocol sat-mon"
-
- - name: "Protocol: Test pass Rule with Protocol visa"
- puzzle.opnsense.firewall_rules:
- interface: 'lan'
- action: 'pass'
- protocol: 'visa'
- description: "New Test pass Rule with Protocol visa"
-
- - name: "Protocol: Test pass Rule with Protocol ipcv"
- puzzle.opnsense.firewall_rules:
- interface: 'lan'
- action: 'pass'
- protocol: 'ipcv'
- description: "New Test pass Rule with Protocol ipcv"
-
- - name: "Protocol: Test pass Rule with Protocol cpnx"
- puzzle.opnsense.firewall_rules:
- interface: 'lan'
- action: 'pass'
- protocol: 'cpnx'
- description: "New Test pass Rule with Protocol cpnx"
-
- - name: "Protocol: Test pass Rule with Protocol cphb"
- puzzle.opnsense.firewall_rules:
- interface: 'lan'
- action: 'pass'
- protocol: 'cphb'
- description: "New Test pass Rule with Protocol cphb"
-
- - name: "Protocol: Test pass Rule with Protocol wsn"
- puzzle.opnsense.firewall_rules:
- interface: 'lan'
- action: 'pass'
- protocol: 'wsn'
- description: "New Test pass Rule with Protocol wsn"
-
- - name: "Protocol: Test pass Rule with Protocol pvp"
- puzzle.opnsense.firewall_rules:
- interface: 'lan'
- action: 'pass'
- protocol: 'pvp'
- description: "New Test pass Rule with Protocol pvp"
-
- - name: "Protocol: Test pass Rule with Protocol br-sat-mon"
- puzzle.opnsense.firewall_rules:
- interface: 'lan'
- action: 'pass'
- protocol: 'br-sat-mon'
- description: "New Test pass Rule with Protocol br-sat-mon"
-
- - name: "Protocol: Test pass Rule with Protocol sun-nd"
- puzzle.opnsense.firewall_rules:
- interface: 'lan'
- action: 'pass'
- protocol: 'sun-nd'
- description: "New Test pass Rule with Protocol sun-nd"
-
- - name: "Protocol: Test pass Rule with Protocol wb-mon"
- puzzle.opnsense.firewall_rules:
- interface: 'lan'
- action: 'pass'
- protocol: 'wb-mon'
- description: "New Test pass Rule with Protocol wb-mon"
-
- - name: "Protocol: Test pass Rule with Protocol wb-expak"
- puzzle.opnsense.firewall_rules:
- interface: 'lan'
- action: 'pass'
- protocol: 'wb-expak'
- description: "New Test pass Rule with Protocol wb-expak"
-
- - name: "Protocol: Test pass Rule with Protocol iso-ip"
- puzzle.opnsense.firewall_rules:
- interface: 'lan'
- action: 'pass'
- protocol: 'iso-ip'
- description: "New Test pass Rule with Protocol iso-ip"
-
- - name: "Protocol: Test pass Rule with Protocol vmtp"
- puzzle.opnsense.firewall_rules:
- interface: 'lan'
- action: 'pass'
- protocol: 'vmtp'
- description: "New Test pass Rule with Protocol vmtp"
-
- - name: "Protocol: Test pass Rule with Protocol secure-vmtp"
- puzzle.opnsense.firewall_rules:
- interface: 'lan'
- action: 'pass'
- protocol: 'secure-vmtp'
- description: "New Test pass Rule with Protocol secure-vmtp"
-
- - name: "Protocol: Test pass Rule with Protocol vines"
- puzzle.opnsense.firewall_rules:
- interface: 'lan'
- action: 'pass'
- protocol: 'vines'
- description: "New Test pass Rule with Protocol vines"
-
- - name: "Protocol: Test pass Rule with Protocol ttp"
- puzzle.opnsense.firewall_rules:
- interface: 'lan'
- action: 'pass'
- protocol: 'ttp'
- description: "New Test pass Rule with Protocol ttp"
-
- - name: "Protocol: Test pass Rule with Protocol nsfnet-igp"
- puzzle.opnsense.firewall_rules:
- interface: 'lan'
- action: 'pass'
- protocol: 'nsfnet-igp'
- description: "New Test pass Rule with Protocol nsfnet-igp"
-
- - name: "Protocol: Test pass Rule with Protocol dgp"
- puzzle.opnsense.firewall_rules:
- interface: 'lan'
- action: 'pass'
- protocol: 'dgp'
- description: "New Test pass Rule with Protocol dgp"
-
- - name: "Protocol: Test pass Rule with Protocol tcf"
- puzzle.opnsense.firewall_rules:
- interface: 'lan'
- action: 'pass'
- protocol: 'tcf'
- description: "New Test pass Rule with Protocol tcf"
-
- - name: "Protocol: Test pass Rule with Protocol eigrp"
- puzzle.opnsense.firewall_rules:
- interface: 'lan'
- action: 'pass'
- protocol: 'eigrp'
- description: "New Test pass Rule with Protocol eigrp"
-
- - name: "Protocol: Test pass Rule with Protocol sprite-rpc"
- puzzle.opnsense.firewall_rules:
- interface: 'lan'
- action: 'pass'
- protocol: 'sprite-rpc'
- description: "New Test pass Rule with Protocol sprite-rpc"
-
- - name: "Protocol: Test pass Rule with Protocol larp"
- puzzle.opnsense.firewall_rules:
- interface: 'lan'
- action: 'pass'
- protocol: 'larp'
- description: "New Test pass Rule with Protocol larp"
-
- - name: "Protocol: Test pass Rule with Protocol mtp"
- puzzle.opnsense.firewall_rules:
- interface: 'lan'
- action: 'pass'
- protocol: 'mtp'
- description: "New Test pass Rule with Protocol mtp"
-
- - name: "Protocol: Test pass Rule with Protocol ax.25"
- puzzle.opnsense.firewall_rules:
- interface: 'lan'
- action: 'pass'
- protocol: 'ax.25'
- description: "New Test pass Rule with Protocol ax.25"
-
- - name: "Protocol: Test pass Rule with Protocol ipip"
- puzzle.opnsense.firewall_rules:
- interface: 'lan'
- action: 'pass'
- protocol: 'ipip'
- description: "New Test pass Rule with Protocol ipip"
-
- - name: "Protocol: Test pass Rule with Protocol micp"
- puzzle.opnsense.firewall_rules:
- interface: 'lan'
- action: 'pass'
- protocol: 'micp'
- description: "New Test pass Rule with Protocol micp"
-
- - name: "Protocol: Test pass Rule with Protocol scc-sp"
- puzzle.opnsense.firewall_rules:
- interface: 'lan'
- action: 'pass'
- protocol: 'scc-sp'
- description: "New Test pass Rule with Protocol scc-sp"
-
- - name: "Protocol: Test pass Rule with Protocol etherip"
- puzzle.opnsense.firewall_rules:
- interface: 'lan'
- action: 'pass'
- protocol: 'etherip'
- description: "New Test pass Rule with Protocol etherip"
-
- - name: "Protocol: Test pass Rule with Protocol encap"
- puzzle.opnsense.firewall_rules:
- interface: 'lan'
- action: 'pass'
- protocol: 'encap'
- description: "New Test pass Rule with Protocol encap"
-
- - name: "Protocol: Test pass Rule with Protocol gmtp"
- puzzle.opnsense.firewall_rules:
- interface: 'lan'
- action: 'pass'
- protocol: 'gmtp'
- description: "New Test pass Rule with Protocol gmtp"
-
- - name: "Protocol: Test pass Rule with Protocol ifmp"
- puzzle.opnsense.firewall_rules:
- interface: 'lan'
- action: 'pass'
- protocol: 'ifmp'
- description: "New Test pass Rule with Protocol ifmp"
-
- - name: "Protocol: Test pass Rule with Protocol pnni"
- puzzle.opnsense.firewall_rules:
- interface: 'lan'
- action: 'pass'
- protocol: 'pnni'
- description: "New Test pass Rule with Protocol pnni"
-
- - name: "Protocol: Test pass Rule with Protocol aris"
- puzzle.opnsense.firewall_rules:
- interface: 'lan'
- action: 'pass'
- protocol: 'aris'
- description: "New Test pass Rule with Protocol aris"
-
- - name: "Protocol: Test pass Rule with Protocol scps"
- puzzle.opnsense.firewall_rules:
- interface: 'lan'
- action: 'pass'
- protocol: 'scps'
- description: "New Test pass Rule with Protocol scps"
-
- - name: "Protocol: Test pass Rule with Protocol qnx"
- puzzle.opnsense.firewall_rules:
- interface: 'lan'
- action: 'pass'
- protocol: 'qnx'
- description: "New Test pass Rule with Protocol qnx"
-
- - name: "Protocol: Test pass Rule with Protocol a/n"
- puzzle.opnsense.firewall_rules:
- interface: 'lan'
- action: 'pass'
- protocol: 'a/n'
- description: "New Test pass Rule with Protocol a/n"
-
- - name: "Protocol: Test pass Rule with Protocol ipcomp"
- puzzle.opnsense.firewall_rules:
- interface: 'lan'
- action: 'pass'
- protocol: 'ipcomp'
- description: "New Test pass Rule with Protocol ipcomp"
-
- - name: "Protocol: Test pass Rule with Protocol snp"
- puzzle.opnsense.firewall_rules:
- interface: 'lan'
- action: 'pass'
- protocol: 'snp'
- description: "New Test pass Rule with Protocol snp"
-
- - name: "Protocol: Test pass Rule with Protocol compaq-peer"
- puzzle.opnsense.firewall_rules:
- interface: 'lan'
- action: 'pass'
- protocol: 'compaq-peer'
- description: "New Test pass Rule with Protocol compaq-peer"
-
- - name: "Protocol: Test pass Rule with Protocol ipx-in-ip"
- puzzle.opnsense.firewall_rules:
- interface: 'lan'
- action: 'pass'
- protocol: 'ipx-in-ip'
- description: "New Test pass Rule with Protocol ipx-in-ip"
-
- - name: "Protocol: Test pass Rule with Protocol carp"
- puzzle.opnsense.firewall_rules:
- interface: 'lan'
- action: 'pass'
- protocol: 'carp'
- description: "New Test pass Rule with Protocol carp"
-
- - name: "Protocol: Test pass Rule with Protocol pgm"
- puzzle.opnsense.firewall_rules:
- interface: 'lan'
- action: 'pass'
- protocol: 'pgm'
- description: "New Test pass Rule with Protocol pgm"
-
- - name: "Protocol: Test pass Rule with Protocol l2tp"
- puzzle.opnsense.firewall_rules:
- interface: 'lan'
- action: 'pass'
- protocol: 'l2tp'
- description: "New Test pass Rule with Protocol l2tp"
-
- - name: "Protocol: Test pass Rule with Protocol ddx"
- puzzle.opnsense.firewall_rules:
- interface: 'lan'
- action: 'pass'
- protocol: 'ddx'
- description: "New Test pass Rule with Protocol ddx"
-
- - name: "Protocol: Test pass Rule with Protocol iatp"
- puzzle.opnsense.firewall_rules:
- interface: 'lan'
- action: 'pass'
- protocol: 'iatp'
- description: "New Test pass Rule with Protocol iatp"
-
- - name: "Protocol: Test pass Rule with Protocol stp"
- puzzle.opnsense.firewall_rules:
- interface: 'lan'
- action: 'pass'
- protocol: 'stp'
- description: "New Test pass Rule with Protocol stp"
-
- - name: "Protocol: Test pass Rule with Protocol srp"
- puzzle.opnsense.firewall_rules:
- interface: 'lan'
- action: 'pass'
- protocol: 'srp'
- description: "New Test pass Rule with Protocol srp"
-
- - name: "Protocol: Test pass Rule with Protocol uti"
- puzzle.opnsense.firewall_rules:
- interface: 'lan'
- action: 'pass'
- protocol: 'uti'
- description: "New Test pass Rule with Protocol uti"
-
- - name: "Protocol: Test pass Rule with Protocol smp"
- puzzle.opnsense.firewall_rules:
- interface: 'lan'
- action: 'pass'
- protocol: 'smp'
- description: "New Test pass Rule with Protocol smp"
-
- - name: "Protocol: Test pass Rule with Protocol sm"
- puzzle.opnsense.firewall_rules:
- interface: 'lan'
- action: 'pass'
- protocol: 'sm'
- description: "New Test pass Rule with Protocol sm"
-
- - name: "Protocol: Test pass Rule with Protocol ptp"
- puzzle.opnsense.firewall_rules:
- interface: 'lan'
- action: 'pass'
- protocol: 'ptp'
- description: "New Test pass Rule with Protocol ptp"
-
- - name: "Protocol: Test pass Rule with Protocol isis"
- puzzle.opnsense.firewall_rules:
- interface: 'lan'
- action: 'pass'
- protocol: 'isis'
- description: "New Test pass Rule with Protocol isis"
-
- - name: "Protocol: Test pass Rule with Protocol crtp"
- puzzle.opnsense.firewall_rules:
- interface: 'lan'
- action: 'pass'
- protocol: 'crtp'
- description: "New Test pass Rule with Protocol crtp"
-
- - name: "Protocol: Test pass Rule with Protocol crudp"
- puzzle.opnsense.firewall_rules:
- interface: 'lan'
- action: 'pass'
- protocol: 'crudp'
- description: "New Test pass Rule with Protocol crudp"
-
- - name: "Protocol: Test pass Rule with Protocol sps"
- puzzle.opnsense.firewall_rules:
- interface: 'lan'
- action: 'pass'
- protocol: 'sps'
- description: "New Test pass Rule with Protocol sps"
+ # this rule should have the extra attributes 'create' updated'
+ # 'tag' 'statetype' and 'disablereplyto' persisted until the end
+ # of the execution of this playbook.
+ - name: "Create rule with 'disablereplyto' and a tag"
+ ansible.builtin.blockinfile:
+ path: /conf/config.xml
+ insertbefore: ""
+ content: |
+
+ pass
+ lan
+ inet
+ test-local-tag
+ keep state
+ in
+ 1
+ 1
+ [ ANSIBLE ] - Test extra attributes
+
+
+ 1
+
+
+ vagrant@10.0.2.2
+
+ /firewall_rules_edit.php made changes
+
+
+ vagrant@10.0.2.2
+
+ /firewall_rules_edit.php made changes
+
+
- - name: "Protocol: Test pass Rule with Protocol pipe"
- puzzle.opnsense.firewall_rules:
- interface: 'lan'
- action: 'pass'
- protocol: 'pipe'
- description: "New Test pass Rule with Protocol pipe"
- - name: "Protocol: Test pass Rule with Protocol sctp"
+ # Test basic functionality with different actions
+ - name: "Action: Test pass action"
puzzle.opnsense.firewall_rules:
interface: 'lan'
action: 'pass'
- protocol: 'sctp'
- description: "New Test pass Rule with Protocol sctp"
+ description: "New Test pass Rule"
+ source:
+ destination:
- - name: "Protocol: Test pass Rule with Protocol fc"
+ - name: "Action: Test block action"
puzzle.opnsense.firewall_rules:
interface: 'lan'
- action: 'pass'
- protocol: 'fc'
- description: "New Test pass Rule with Protocol fc"
+ action: 'block'
+ description: "New Test block Rule"
- - name: "Protocol: Test pass Rule with Protocol rsvp-e2e-ignore"
+ - name: "Action: Test reject action"
puzzle.opnsense.firewall_rules:
interface: 'lan'
- action: 'pass'
- protocol: 'rsvp-e2e-ignore'
- description: "New Test pass Rule with Protocol rsvp-e2e-ignore"
+ action: 'reject'
+ description: "New Test reject Rule"
- - name: "Protocol: Test pass Rule with Protocol udplite"
+ # Test basic functionality of the disabled button
+ - name: "Disabled: Test disabled button"
puzzle.opnsense.firewall_rules:
interface: 'lan'
action: 'pass'
- protocol: 'udplite'
- description: "New Test pass Rule with Protocol udplite"
+ description: "New Test disabled pass Rule"
+ disabled: true
- - name: "Protocol: Test pass Rule with Protocol mpls-in-ip"
+ # Test basic functionality of the disabled quick button
+ - name: "Quick: Test pass Rule with quick disabled"
puzzle.opnsense.firewall_rules:
interface: 'lan'
action: 'pass'
- protocol: 'mpls-in-ip'
- description: "New Test pass Rule with Protocol mpls-in-ip"
+ quick: false
+ description: "New Test pass Rule with quick disabled"
- - name: "Protocol: Test pass Rule with Protocol manet"
+ # Test different Interfaces
+ - name: "Interface: Test pass Rules"
puzzle.opnsense.firewall_rules:
- interface: 'lan'
+ interface: "{{ item }}"
action: 'pass'
- protocol: 'manet'
- description: "New Test pass Rule with Protocol manet"
+ description: "New Test pass Rule of Interface {{ item }}"
+ loop:
+ - "lan"
+ - "lo0"
+ - "openvpn"
+ - "opt2"
- - name: "Protocol: Test pass Rule with Protocol hip"
+ # Test different Directions
+ - name: "Direction: Test pass Rule with Direction in"
puzzle.opnsense.firewall_rules:
interface: 'lan'
action: 'pass'
- protocol: 'hip'
- description: "New Test pass Rule with Protocol hip"
+ direction: in
+ description: "New Test pass Rule with Direction in"
- - name: "Protocol: Test pass Rule with Protocol shim6"
+ - name: "Direction: Test pass Rule with Direction out"
puzzle.opnsense.firewall_rules:
interface: 'lan'
action: 'pass'
- protocol: 'shim6'
- description: "New Test pass Rule with Protocol shim6"
+ direction: out
+ description: "New Test pass Rule with Direction out"
- - name: "Protocol: Test pass Rule with Protocol wesp"
+ # Test different IPProtocols
+ - name: "IPProtocol: Test pass Rule with IPProtocol IPv4"
puzzle.opnsense.firewall_rules:
interface: 'lan'
action: 'pass'
- protocol: 'wesp'
- description: "New Test pass Rule with Protocol wesp"
+ ipprotocol: 'inet'
+ description: "New Test pass Rule with IPv4"
- - name: "Protocol: Test pass Rule with Protocol rohc"
+ - name: "IPProtocol: Test pass Rule with IPProtocol IPv6"
puzzle.opnsense.firewall_rules:
interface: 'lan'
action: 'pass'
- protocol: 'rohc'
- description: "New Test pass Rule with Protocol rohc"
+ ipprotocol: 'inet6'
+ description: "New Test pass Rule with IPProtocol IPv6"
- - name: "Protocol: Test pass Rule with Protocol pfsync"
+ - name: "IPProtocol: Test pass Rule with IPProtocol IPv4 + IPv6"
puzzle.opnsense.firewall_rules:
interface: 'lan'
action: 'pass'
- protocol: 'pfsync'
- description: "New Test pass Rule with Protocol pfsync"
+ ipprotocol: 'inet46'
+ description: "New Test pass Rule with IPProtocol IPv4 + IPv6"
- - name: "Protocol: Test pass Rule with Protocol divert"
- puzzle.opnsense.firewall_rules:
- interface: 'lan'
- action: 'pass'
- protocol: 'divert'
- description: "New Test pass Rule with Protocol divert"
+ # Test different Protocols
+ - name: "Protocol: Test pass rule for all protocols"
+ puzzle.opnsense.firewall_rules:
+ interface: "lan"
+ action: "pass"
+ protocol: "{{ item }}"
+ loop:
+ - "any"
+ - "tcp"
+ - "udp"
+ - "tcp/udp"
+ - "icmp"
+ - "esp"
+ - "ah"
+ - "gre"
+ - "igmp"
+ - "pim"
+ - "ospf"
+ - "ggp"
+ - "ipencap"
+ - "st2"
+ - "cbt"
+ - "egp"
+ - "igp"
+ - "bbn-rcc"
+ - "nvp"
+ - "pup"
+ - "argus"
+ - "emcon"
+ - "xnet"
+ - "chaos"
+ - "mux"
+ - "dcn"
+ - "hmp"
+ - "prm"
+ - "xns-idp"
+ - "trunk-1"
+ - "trunk-2"
+ - "leaf-1"
+ - "leaf-2"
+ - "rdp"
+ - "irtp"
+ - "iso-tp4"
+ - "netblt"
+ - "mfe-nsp"
+ - "merit-inp"
+ - "dccp"
+ - "3pc"
+ - "idpr"
+ - "xtp"
+ - "ddp"
+ - "idpr-cmtp"
+ - "tp++"
+ - "il"
+ - "ipv6"
+ - "sdrp"
+ - "idrp"
+ - "rsvp"
+ - "dsr"
+ - "bna"
+ - "i-nlsp"
+ - "swipe"
+ - "narp"
+ - "mobile"
+ - "tlsp"
+ - "skip"
+ - "ipv6-icmp"
+ - "cftp"
+ - "sat-expak"
+ - "kryptolan"
+ - "rvd"
+ - "ippc"
+ - "sat-mon"
+ - "visa"
+ - "ipcv"
+ - "cpnx"
+ - "cphb"
+ - "wsn"
+ - "pvp"
+ - "br-sat-mon"
+ - "sun-nd"
+ - "wb-mon"
+ - "wb-expak"
+ - "iso-ip"
+ - "vmtp"
+ - "secure-vmtp"
+ - "vines"
+ - "ttp"
+ - "nsfnet-igp"
+ - "dgp"
+ - "tcf"
+ - "eigrp"
+ - "sprite-rpc"
+ - "larp"
+ - "mtp"
+ - "ax.25"
+ - "ipip"
+ - "micp"
+ - "scc-sp"
+ - "etherip"
+ - "encap"
+ - "gmtp"
+ - "ifmp"
+ - "pnni"
+ - "aris"
+ - "scps"
+ - "qnx"
+ - "a/n"
+ - "ipcomp"
+ - "snp"
+ - "compaq-peer"
+ - "ipx-in-ip"
+ - "carp"
+ - "pgm"
+ - "l2tp"
+ - "ddx"
+ - "iatp"
+ - "stp"
+ - "srp"
+ - "uti"
+ - "smp"
+ - "sm"
+ - "ptp"
+ - "isis"
+ - "crtp"
+ - "crudp"
+ - "sps"
+ - "pipe"
+ - "sctp"
+ - "fc"
+ - "rsvp-e2e-ignore"
+ - "udplite"
+ - "mpls-in-ip"
+ - "manet"
+ - "hip"
+ - "shim6"
+ - "wesp"
+ - "rohc"
+ - "pfsync"
+ - "divert"
# Source / Invert: Test basic functionality of the source/invert button
- name: "Source / Invert: Test basic functionality of the source/invert button"
@@ -1152,22 +384,18 @@
# TODO add support for Advanced features: No XMLRPC Sync, Schedule and Gateway
# TODO add support for Advanced Options
- # Idempotency test
- - name: Apply rule twice and check for idempotency
- puzzle.opnsense.firewall_rules:
- interface: 'lan'
- action: 'pass'
- source:
- address: '192.168.0.0/16'
- register: first_apply
- - name: Re-apply same rule
- puzzle.opnsense.firewall_rules:
- interface: 'lan'
- action: 'pass'
- source:
- address: '192.168.0.0/16'
- register: second_apply
- - name: Assert no change on second apply
- ansible.builtin.assert:
- that:
- - not second_apply.changed
+ - name: Test extra argument persistence
+ block:
+
+ - name: Read the config
+ ansible.builtin.slurp:
+ src: /conf/config.xml
+ register: current_config
+
+ - name: "Check that the extra attributes are still present"
+ ansible.builtin.assert:
+ that:
+ - "'keep state' in ( current_config.content | b64decode )"
+ - "'' in ( current_config.content | b64decode )"
+ - "'test-local-tag' in ( current_config.content | b64decode )"
+ - "'1' in ( current_config.content | b64decode )"
\ No newline at end of file
diff --git a/plugins/module_utils/firewall_rules_utils.py b/plugins/module_utils/firewall_rules_utils.py
index 76807ad0..549e72b0 100644
--- a/plugins/module_utils/firewall_rules_utils.py
+++ b/plugins/module_utils/firewall_rules_utils.py
@@ -3,6 +3,7 @@
"""
Utilities for firewall_rules module related operations.
"""
+import dataclasses
from dataclasses import dataclass, asdict, field
from typing import List, Optional
from xml.etree.ElementTree import Element
@@ -11,7 +12,6 @@
from ansible_collections.puzzle.opnsense.plugins.module_utils.config_utils import (
OPNsenseModuleConfig,
)
-
from ansible_collections.puzzle.opnsense.plugins.module_utils.enum_utils import ListEnum
@@ -296,9 +296,8 @@ class FirewallRule:
disabled: bool = False
log: bool = False
category: Optional[str] = None
- statetype: FirewallRuleStateType = FirewallRuleStateType.KEEP_STATE
- # TODO ChangeLog
+ extra_attributes: dict = field(default_factory=dict)
def __post_init__(self):
# Manually define the fields and their expected types
@@ -306,7 +305,6 @@ def __post_init__(self):
"type": FirewallRuleAction,
"ipprotocol": IPProtocol,
"protocol": FirewallRuleProtocol,
- "statetype": FirewallRuleStateType,
"direction": FirewallRuleDirection,
}
@@ -354,8 +352,11 @@ def to_etree(self) -> Element:
"""
rule_dict: dict = asdict(self)
del rule_dict["uuid"]
+ del rule_dict["extra_attributes"]
for rule_key, rule_val in rule_dict.copy().items():
+ if rule_key == "extra_attributes":
+ continue
if rule_key == "quick":
if rule_val:
del rule_dict[rule_key]
@@ -371,6 +372,9 @@ def to_etree(self) -> Element:
elif isinstance(rule_val, bool):
rule_dict[rule_key] = "1"
+ for extra_key, extra_val in self.extra_attributes.items():
+ rule_dict[extra_key] = extra_val
+
element: Element = xml_utils.dict_to_etree("rule", rule_dict)[0]
if self.uuid:
@@ -446,8 +450,8 @@ def from_ansible_module_params(cls, params: dict) -> "FirewallRule":
return cls(**rule_dict)
- @staticmethod
- def from_xml(element: Element) -> "FirewallRule":
+ @classmethod
+ def from_xml(cls, element: Element) -> "FirewallRule":
"""
Converts an XML element into a FirewallRule object.
@@ -489,20 +493,25 @@ def from_xml(element: Element) -> "FirewallRule":
uuid=element.attrib.get("uuid"),
)
- # TODO ignore changelog for now
- rule_dict.pop("updated", None)
- rule_dict.pop("created", None)
-
- rule_dict.pop("source")
- rule_dict.pop("destination")
- source: FirewallRuleTarget = FirewallRuleTarget.from_xml(
+ rule_dict["source"] = FirewallRuleTarget.from_xml(
"source", element.find("./source")
)
- destination: FirewallRuleTarget = FirewallRuleTarget.from_xml(
+ rule_dict["destination"] = FirewallRuleTarget.from_xml(
"destination", element.find("./destination")
)
- return FirewallRule(source=source, destination=destination, **rule_dict)
+ class_attribute_names: List[str] = list(
+ map(lambda f: f.name, dataclasses.fields(cls))
+ )
+
+ rule_dict["extra_attributes"] = {}
+
+ for k, v in rule_dict.copy().items():
+ if k not in class_attribute_names:
+ rule_dict["extra_attributes"][k] = v
+ rule_dict.pop(k)
+
+ return FirewallRule(**rule_dict)
class FirewallRuleSet(OPNsenseModuleConfig):
diff --git a/tests/unit/plugins/module_utils/test_firewall_rules_utils.py b/tests/unit/plugins/module_utils/test_firewall_rules_utils.py
index 9ca23e53..3f4c2f8f 100644
--- a/tests/unit/plugins/module_utils/test_firewall_rules_utils.py
+++ b/tests/unit/plugins/module_utils/test_firewall_rules_utils.py
@@ -13,7 +13,6 @@
from xml.etree.ElementTree import Element
import pytest
-
from ansible_collections.puzzle.opnsense.plugins.module_utils import xml_utils
from ansible_collections.puzzle.opnsense.plugins.module_utils.firewall_rules_utils import (
FirewallRuleAction,
@@ -21,7 +20,6 @@
FirewallRule,
IPProtocol,
FirewallRuleProtocol,
- FirewallRuleStateType,
FirewallRuleTarget,
)
from ansible_collections.puzzle.opnsense.plugins.module_utils.module_index import (
@@ -75,6 +73,24 @@
22
+
+ pass
+ wan
+ inet
+ keep state
+ Allow SSH access
+ tcp
+
+
+
+ 22
+
+
+ this is an extra attribute
+
+
pass
wan
@@ -161,7 +177,6 @@ def test_firewall_rule_from_xml():
assert test_rule.type == FirewallRuleAction.PASS
assert test_rule.interface == "wan"
assert test_rule.ipprotocol == IPProtocol.IPv4
- assert test_rule.statetype == FirewallRuleStateType.KEEP_STATE
assert test_rule.descr == "Allow SSH access"
assert test_rule.protocol == FirewallRuleProtocol.TCP
assert test_rule.source.port == "any"
@@ -193,9 +208,8 @@ def test_firewall_rule_to_etree():
protocol=FirewallRuleProtocol.TCP,
source=FirewallRuleTarget("source"),
destination=FirewallRuleTarget("destination", port="22"),
- statetype=FirewallRuleStateType.KEEP_STATE,
)
-
+ test_rule.extra_attributes["statetype"] = "keep state"
test_element = test_rule.to_etree()
orig_etree: Element = ElementTree.fromstring(TEST_XML)
@@ -207,6 +221,33 @@ def test_firewall_rule_to_etree():
)
+def test_firewall_rule_to_etree_with_extra_attributes():
+ """
+ An extra non dataclass relevant field in the xml should be
+ persisted.
+ """
+ test_rule: FirewallRule = FirewallRule(
+ interface="wan",
+ type=FirewallRuleAction.PASS,
+ descr="Allow SSH access",
+ ipprotocol=IPProtocol.IPv4,
+ protocol=FirewallRuleProtocol.TCP,
+ source=FirewallRuleTarget("source"),
+ destination=FirewallRuleTarget("destination", port="22"),
+ extra_attributes={"extra": "this is an extra attribute"},
+ )
+
+ test_rule.extra_attributes["statetype"] = "keep state"
+ test_element = test_rule.to_etree()
+ orig_etree: Element = ElementTree.fromstring(TEST_XML)
+ orig_rule: Element = orig_etree.find("filter")[1]
+
+ assert elements_equal(test_element, orig_rule), (
+ f"{xml_utils.etree_to_dict(test_element)}\n"
+ f"{xml_utils.etree_to_dict(orig_rule)}"
+ )
+
+
def test_firewall_rule_from_ansible_module_params_simple():
"""
Test FirewallRule instantiation form simple Ansible parameters.
@@ -257,7 +298,7 @@ def test_rule_set_load_simple_rules(
Test correct loading of FirewallRuleSet from XML config without changes.
"""
with FirewallRuleSet(sample_config_path) as rule_set:
- assert len(rule_set._rules) == 4
+ assert len(rule_set._rules) == 5
rule_set.save()