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
  • 97
  • 1
  • 9
  • 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
  • @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

5 Answers5

7

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
  • 403
  • 3
  • 13
4

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
  • 41
  • 1
3

I'm a bit late but given that all previous answers seem to just speculate I will give another input. Firewalld is not reloaded with 'service' or 'systemctl' commands but rather with it's own specific command:

firewall-cmd --reload

This is because that way you can load new rules without interrupting any active network connections as would be the case when using iptables directly. Given this I think using service or systemctl is not a good solution. So 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.

cstoll
  • 51
  • 3
2

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
  • 1,745
  • 2
  • 7
  • 21
0

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,170
  • 8
  • 19