6

I added some rule to firewalld in centos 7 with ansible. But I must reload firewalld daemon thus service work properly. Is there any idea?

Here is my ansible code:

- name: Add port to firewalld
  firewalld:
    port: "{{ item }}"
    permanent: yes
    state: enabled
  when: ansible_distribution == 'CentOS' or ansible_distribution == 'Red Hat Enterprise Linux'
  loop:
    - 8080/tcp
    - 8000/tcp
    - 8090/tcp
    - 8040/tcp
Ali
  • 337
  • 1
  • 5
  • 15
  • What makes you think you need to reload firewalld after this ? From [documentation](https://docs.ansible.com/ansible/latest/modules/firewalld_module.html) this is only needed when performing zone transactions which is not your case. Meanwhile, if I'm wrong, have a look at the [service](https://docs.ansible.com/ansible/latest/modules/service_module.html) or [systemd](https://docs.ansible.com/ansible/latest/modules/systemd_module.html) modules....(or whatever initialization specific module for your particular case) – Zeitounator Mar 02 '20 at 12:54
  • 1
    @Zeitounator, since the example doesn't set `immediate` - but sets `permanent` - firewalld has to be reloaded. One could add `immediate` but with the loop this would yield `n` firewalld refreshes - in contrast to one refresh if you reload firewalld in a following task or handler. – maxschlepzig Aug 21 '20 at 21:31

6 Answers6

11

First of all use with_items for list of ports as below:

- name: Add port to firewalld
  firewalld:
    port: "{{ item }}"
    permanent: yes
    state: enabled
  when: ansible_distribution == 'CentOS' or ansible_distribution == 'Red Hat Enterprise Linux'
  loop:
    - 8080/tcp
    - 8000/tcp
    - 8090/tcp
    - 8040/tcp

You can also use the below code to enter ports if they are not fixed and use its as a variable:

- hosts: localhost
  gather_facts: no
  vars_prompt:
    - name: ports
      prompt: "Enter port(s) number"
      private: no
  tasks:
    - name: add port
      firewalld:
            service: "{{ item }}"
            permanent: yes
            immediate: yes
            state: enabled
      with_items: "{{ ports.split(',') }}"

and regarding reloading firewalld its mentioned here we can't reload firewalld using state parameter So use systemd module as below:

- name: reload service firewalld
  systemd:
    name: firewalld
    state: reloaded
Santosh Garole
  • 1,419
  • 13
  • 23
8

firewalld module has immediate option which is performing the same reload within firewall-cmd cli tool.

- name: Add port to firewalld
  firewalld:
    port: "{{ item }}"
    permanent: yes
    state: enabled
    immediate: true
dpinhas
  • 81
  • 1
  • 1
5

As dave mentioned in the coments Firewalld can be reloaded with 'service' or 'systemctl' commands or with it's own specific command:

firewall-cmd --reload

There is no difference in the outcome. Both ways load new rules without interrupting any active network connections as would be the case when using iptables directly. In the examples below firewalld's specific command is used.

If you just want to create a task I suggest using the command module from ansible to execute this command. Or you could write a handler like so:

- name: reload firewalld
  command: firewall-cmd --reload

Just put the handler in the handlers/main.yml file inside your role. Then in your tasks you can call that handler with:

notify: reload firewalld

That way Ansible only executes the handler at the end of your Ansible run. I successfully tested this on RHEL7 and it should work without issues on CentOS/Rocky/Alma as well and also on the newer releases 8 and 9.

cstoll
  • 94
  • 1
  • 3
  • Do you have to do this at the end of every task or can you just put one "notify: reload firewalld" at the end of the last item in your playbook.yml? – Prithvi Boinpally Mar 31 '23 at 08:39
  • 1
    Handlers are only executed when things change. If you have a task you already ran previously and it does not change anything anymore then the handler will not run. That means you should add the notify to every task where you change things over time (e.g. adding more ports/services). That way you make sure the handler is executed whenever a task changes something on the server. – cstoll Mar 31 '23 at 11:29
  • 1
    While you can use `firewall-cmd --reload`, `systemctl reload firewalld` *also* works.This is because the unit file has `ExecReload=/bin/kill -HUP $MAINPID` and the man page explains that SIGHUP reloads the firewall in the same way as `firewall-cmd --reload` – dave Aug 03 '23 at 15:34
  • Thanks dave I adjusted my answer accordingly. – cstoll Sep 01 '23 at 15:30
4

You can use service or systemd module.

#Supports init systems include BSD init, OpenRC, SysV, Solaris SMF, systemd, upstart.
- name: Restart service 
  service:
    name: firewalld
    state: restarted

#Controls systemd services on remote hosts.
- name: Restart service 
  systemd:
    state: restarted
    daemon_reload: yes
    name: firewalld

Smily
  • 2,308
  • 2
  • 17
  • 41
3

If you are using permanent conditional, you can use immediate option.

Example:

- name: Apply Base Services
  ansible.posix.firewalld:
    service: "{{ item }}"
    state: enabled
    zone: public
    permanent: yes
    immediate: true
  loop:
    - http
    - https

After this rule will applied, firewalld will reload automatically.

m0zgen
  • 569
  • 7
  • 20
1

You already got a number of excellent answers. There is yet another possible approach (although the reloading part is the same as in cstoll's answer).

If you are certain that nobody and nothing else but Ansible will ever manipulate firewalld rules, you can use a template to directly generate the zone XML files in /etc/firewalld/zones . You will still need to add

notify: reload firewalld

and the corresponding handler, as in cstoll's answer.

The main advantage of this approach is that it can be dramatically faster and simpler than adding the rules one at a time.

The drawback of this approach is that it will not preserve any rules added to firewalld outside of Ansible. A second drawback is that it will not do any error checking; you can create invalid zone files easily. The firewall-cmd command (and thus the firewalld module) will verify the validity of each rule. For instance, it checks that zones do not overlap.

Kevin Keane
  • 1,506
  • 12
  • 24