ansible-collections / ansible.posix

Ansible Collection for Posix
Other
155 stars 149 forks source link

firewalld module does not permanently set an interface zone on CentOS / RedHat due to upstream bugs #75

Open StudioMaX opened 4 years ago

StudioMaX commented 4 years ago
SUMMARY

As per NetworkManager and firewalld - Zone is lost on network restart, this ansible firewalld module is unable to persist zone settings for interfaces. This can be enhanced/compensated for by also running a nmcli connection modify conn_name connection.zone zone_name command if the interface is managed by network managed. Unfortunately, the current ansible nmcli module does not expose zone settings.

ISSUE TYPE
COMPONENT NAME

firewalld

ANSIBLE VERSION
ansible 2.9.11
  config file = /etc/ansible/ansible.cfg
  configured module search path = [u'/home/user/.ansible/plugins/modules', u'/usr/share/ansible/plugins/modules']
  ansible python module location = /usr/lib/python2.7/dist-packages/ansible
  executable location = /usr/bin/ansible
  python version = 2.7.17 (default, Jul 20 2020, 15:37:01) [GCC 7.5.0]
CONFIGURATION
ANSIBLE_PIPELINING(ansible.cfg) = True
ANSIBLE_SSH_ARGS(ansible.cfg) = -o ServerAliveInterval=30 -o ControlMaster=auto -o ControlPersist=60s -o PreferredAuthentications=publickey,password,keyboard-interactive
DEFAULT_BECOME_METHOD(ansible.cfg) = sudo
DEFAULT_GATHERING(ansible.cfg) = smart
DEFAULT_HASH_BEHAVIOUR(ansible.cfg) = merge
OS / ENVIRONMENT

Ubuntu 16.04/18.04 LTS control host, CentOS 7.8 target

STEPS TO REPRODUCE
    - name: Set zone for the internal network
      become: true
      firewalld:
        permanent: true
        immediate: true
        zone: internal
        interface: eth0
        state: enabled
EXPECTED RESULTS

The firewall zone was set after rebooting or restarting firewalld

ACTUAL RESULTS

The change is forgotten and interface switches back to the default public zone

E.g. after running play

# firewall-cmd --zone=internal --list-all
internal
  target: default
  icmp-block-inversion: no
  interfaces: eth0
  ...

E.g. after systemctl restart firewalld, interfaces empty.

# firewall-cmd --zone=internal --list-all
internal
  target: default
  icmp-block-inversion: no
  interfaces: 
...

Copied from original issue: ansible/ansible#41738

maxamillion commented 4 years ago

This is a bug in upstream firewalld, bug was previously filed by someone else before this issue was found but I wanted to link it here for posterity.

https://bugzilla.redhat.com/show_bug.cgi?id=1112742

Akasurde commented 3 years ago

The above-mentioned bug is resolved. @StudioMaX Do you think we should close this as well? Thanks,

StudioMaX commented 3 years ago

To be honest, I don’t know, as I haven’t used this action for a long time. What fixed bug are you talking about? This one? It was marked as fixed in 2015, but according to the history of this issue, the problem was observed by users in 2020 as well. I think it's better to ask other users from the original issue.

phpHavok commented 3 years ago

I can confirm this has happened to me recently (within the past month) on CentOS 8.3 and is still an issue. It's very annoying because you either have to run the module twice or manually push a ZONE= line to the sysconfig script to get around it.

Akasurde commented 3 years ago

Before

[root@localhost vagrant]# cat /etc/redhat-release
CentOS Linux release 8.3.2011
[root@localhost vagrant]# rpm -qa | grep firewalld
firewalld-filesystem-0.9.3-1.el8.noarch
firewalld-0.9.3-1.el8.noarch
[root@localhost vagrant]# firewall-cmd --zone=internal --list-all
internal
  target: default
  icmp-block-inversion: no
  interfaces:
  sources:
  services: cockpit dhcpv6-client mdns samba-client ssh
  ports:
  protocols:
  forward: no
  masquerade: no
  forward-ports:
  source-ports:
  icmp-blocks:
  rich rules:

Ansible Playbook run

TASK [Set zone for the internal network] ******************************************************
task path: /Volumes/data/src/playbooks/posix/firewalld/75.yml:5
redirecting (type: modules) ansible.builtin.firewalld to ansible.posix.firewalld
changed: [127.0.0.1] => {"ansible_facts": {"discovered_interpreter_python": "/usr/libexec/platform-python"}, "changed": true, "msg": "Permanent and Non-Permanent(immediate) operation, Changed eth1 to zone internal"}
META: ran handlers
META: ran handlers
[root@localhost vagrant]# firewall-cmd --zone=internal --list-all
internal (active)
  target: default
  icmp-block-inversion: no
  interfaces: eth1
  sources:
  services: cockpit dhcpv6-client mdns samba-client ssh
  ports:
  protocols:
  forward: no
  masquerade: no
  forward-ports:
  source-ports:
  icmp-blocks:
  rich rules:
[root@localhost vagrant]# systemctl restart firewalld
[root@localhost vagrant]# firewall-cmd --zone=internal --list-all
internal (active)
  target: default
  icmp-block-inversion: no
  interfaces: eth1
  sources:
  services: cockpit dhcpv6-client mdns samba-client ssh
  ports:
  protocols:
  forward: no
  masquerade: no
  forward-ports:
  source-ports:
  icmp-blocks:
  rich rules:

I am not able to reproduce this. Any reproduction steps will help.

needs_info

kellinm commented 2 years ago

I ran into this bug on a system where the network interfaces are managed by NetworkManager.

The issue may be reproduced with an Ansible play that includes this zone installation task I created. To use it - define the the two variables that represent the custom zone name and the interface the custom zone should be bound against after the play is complete. This example should work against any EL8 binary compatible Linux distribution.

Investigation and proposed solution

The FirewallClient class in the firewall library only seems to update the appropriate file at /etc/firewall/zones/myzone.xml.

Upon investigation, it looks to me like upstream FirewallD has resolved the issues by adding an invocation to update NetworkManager as seen in the upstream source code.

I put together a very naive proof of concept patch that resolves functionality only. This proof of concept resolved the issue when running my playbook.

The next step is to take this proof-of-concept and turn it into a working pull request. I already know a few things need to be changed, such as adding the imports over in to the module_utils firewall file.

Before going to that next step though, I wanted to check in and see what you think of the approach @Akasurde and @maxamillion - it's basically a mimic of what the upstream firewalld project does in firewall-cmd.

Does this seem like an acceptable path to pursue?

kellinm commented 2 years ago

@Akasurde and @maxamillion - re-pinging - what do you think of the approach in the proof of concept?

Is it worth taking it from proof of concept to something more polished or is a different approach preferable?

areguera commented 1 year ago

I experienced this issue today, in CentOS Stream 9 (vagrant box generic/centos9s). In my case I am not touching eth0 but eth1. I change eth1 from public zone to trusted zone and it works, but after a systemct restart firewalld (or a system reboot) the eth1 interface is no longer in trusted zone but in public zone. I am using ansible.posix 1.4.0

carlosfamilia commented 1 year ago

Had the same issue with Rocky 8.7. The changes are only added to runtime and not to permanent configuration, despite the permanent: true is set on the playbook.

gulywwx commented 1 year ago

According to https://github.com/firewalld/firewalld/issues/636, I reckon it is an firewalld issue. My VM is running on Azure. so ifcfg is generated by cloud-init. I can not just edit the ifcfg file. My workaround is to create an executable file under /etc/NetworkManager/dispatcher.d. It is called when the interface is up after reboot. And put firewall-cmd in the file.

marcstraube commented 10 months ago

I just ran into this bug on Rocky Linux 9, while testing my role with molecule. After restarting firewalld.service the interface zone settings set by my Ansible role are gone and back to default. I was able to set the zones via the nmcli module, which is now able to change the interface zones in its current version.

darius-m commented 9 months ago

This appears to also be an issue on CentOS 9, but from what I can tell there is something wrong with firewalld itself - the zone file in /etc/firewalld/zones contains an <interface name="eth0"> rule. Also running firewall-cmd --list-all-zones --permanent appears to attribute the interface to that zone, but neither restarting the service or running firewall-cmd --reload or firewall-cmd --complete-reload do not appear to correctly redistribute the zone, even if FlushAllOnReload=yes is configured (by default) in /etc/firewalld/firewalld.conf.

LE: After some more investigation there still seems to be some weird interaction between firwalld and NetworkManager on CentOS 9 (and likely also on RHEL and other RHEL derivatives). In theory, RHEL has moved away from using the configuration files in /etc/sysconfig/network-scripts, and instead uses the configuration files in /etc/NetworkManager/system-connections. In practice, if these files exist, they are still taken into account.

Adding ZONE=zone_name to the /etc/sysconfig/network-scripts/ifcfg-eth0 config file fixes this issue (running firewall-cmd --permanent --zone=zone_name --add-interface=eth0 displays the warning that the interface is managed by NetworkManager, and then calls the NetworkManager API to set the interface's zone, which ultimately results in having the line appended).