-
Notifications
You must be signed in to change notification settings - Fork 2
Description
In certain situations, the zpe.nodegrid.firewall may not properly update all defined options of an existing firewall rule, because the used dict_diff() method will omit any option that is not present in the "current rule state". This will cause sub-options to be omitted, which are enabled by other options that are set just before.
Assume a nodegrid system, which has an empty no-op rule in the IPv4 INPUT chain:
[ansible@nodegrid /]# show /settings/ipv4_firewall/chains/INPUT/0/
target = ACCEPT
rule_number = 0
description =
source_net4 =
destination_net4 =
source_mac_address =
protocol = numeric
protocol_number =
input_interface = any
output_interface = any
fragments = all_packets_and_fragments
reverse_match_for_source_ip|mask = no
reverse_match_for_destination_ip|mask = no
reverse_match_for_source_mac_address = no
reverse_match_for_source_port = no
reverse_match_for_destination_port = no
reverse_match_for_protocol = no
reverse_match_for_tcp_flags = no
reverse_match_for_icmp_type = no
reverse_match_for_input_interface = no
enable_state_match = no
reverse_match_for_output_interface = no
reject_with = port_unreacheable
log_level = debug
log_prefix =
log_tcp_sequence_numbers = no
log_options_from_the_tcp_packet_header = no
log_options_from_the_ip_packet_header = no
Executing the following example playbook
- hosts: all
tasks:
- zpe.nodegrid.firewall:
debug: true
ipv4_firewall:
chains:
INPUT:
- rule_number: 0
enable_state_match: "yes"
invalid: "yes"
result in
TASK [zpe.nodegrid.firewall] *********************
changed: [nodegrid] =>
changed: true
cmds:
- cmd: config_start
- cmd: cd /settings/ipv4_firewall/chains/INPUT/0
- cmd: set enable_state_match=yes
- cmd: set rule_number=0
- cmd: set target=ACCEPT
- cmd: commit
- cmd: config_confirm
cmds_output:
[ ---- 8< ---- ]
message: ''
While the enable_state_match option is set, the invalid is not. The invalidoption is only available when the enable_state_match option is yes. Because the enable_state_match was initially no, the invalid option was not part of the "current rule state", and filtered out by the dict_diff() method.
Running the playbook again will then properly set the invalid option, because at that point enable_state_match is already yes in the "current rule state".
As a workaround, you can run the task multiple times in a row (three should be enough) using Ansible's loop statement. Do note however that this makes the firewall updates non-atomic, with the potential to lock yourself out using a partially configured firewall ruleset.
The zpe.nodegrid.firewallv2 module is not effected by this, because it uses a more strict match to existing rules. But its iterative nature and multiple task invocations make it inherently non-atomic, with the same potential to lock yourself out using a partially configured firewall ruleset. Or leaving it unprotected with a flushed ruleset.