Ansible vs. FirewallD

Hi,

I’m currently trying to translate the following into Ansible lingo:

# firewall-cmd --permanent --zone=internal --change-interface=enp3s0
# firewall-cmd --set-default-zone=internal
# firewall-cmd --permanent --remove-service=cockpit
# firewall-cmd --permanent --remove-service=dhcpv6-client
# firewall-cmd --permanent --remove-service=mdns
# firewall-cmd --permanent --remove-service=samba-client
# firewall-cmd --reload

There’s a FirewallD-specific Ansible module here:

https://docs.ansible.com/ansible/latest/collections/ansible/posix/firewalld_module.html

But I’m not sure I understand how to translate my commands above into Ansible’s way of doing things.

Any suggestions ?

I’ll answer this myself, since I did some experimenting, and it works:

- name: "Set default FirewallD zone: internal"
  ansible.builtin.command:
    cmd: firewall-cmd --set-default-zone=internal
  changed_when: false

- name: "Make sure SSH is enabled in FirewallD"
  ansible.posix.firewalld:
    service: ssh
    permanent: yes
    immediate: yes
    state: enabled

- name: "Disable all other predefined FirewallD services"
  ansible.posix.firewalld:
    service: "{{ item }}"
    permanent: yes
    immediate: yes
    state: disabled
  with_items:
    - cockpit
    - dhcpv6-client
    - samba-client
    - mdns

Of course I’m always open for suggestions.

1 Like

That is nice. These show one alternative:
blog: Automating firewall configuration with RHEL System Roles
docs: Chapter 10. Configuring firewalld using System Roles Red Hat Enterprise Linux 9 | Red Hat Customer Portal

1 Like

Comme te le conseille @jlehtone et dans la continuité de tes précédents posts, il faut que tu prennes l’habitude de séparer tes variables (à mettre dans l’inventaire) de ton code technique (tes playbooks).
Et la meilleure façon de faire ça, c’est d’utiliser des rôles.
Les rôles RHEL System Roles fonctionnent à merveille notamment pour la partie firewall, c’est un peu compliqué (je trouve) au départ, mais la doc donne des exemples et après quelques tests ça fonctionnera très bien, surtout que ton besoin n’est pas très compliqué !
Bon courage.

As @jlehtone advises and in line with your previous posts, you need to get into the habit of separating your variables (to be put in the inventory) from your technical code (your playbooks).
The best way to do this is to use roles.
The RHEL System Roles work wonderfully, especially for the firewall part. It’s a bit complicated (I find) at first, but the doc gives examples and after a few tests it’ll work just fine, especially as your needs aren’t very complicated!
All the best.

1 Like

A very different alternative:

    - name: Get service facts
      service_facts:

    - name: Do we have nftables ruleset
      ansible.builtin.set_fact:
        _found_ruleset: "{{ lookup('ansible.builtin.first_found', files, skip=True, errors='ignore') }}"
      vars:
        files:
        - "{{ inventory_hostname }}.nft"

    - block:
      - name: Ruleset src
        ansible.builtin.debug:
          msg: "Use nftables.service with {{  _found_ruleset }}"

      - name: nftables is required
        ansible.builtin.package:
          name:  nftables
          state: present

      - name: Deploy ruleset
        ansible.builtin.copy:
          src:  "{{  _found_ruleset }}"
          dest: "/etc/nftables/{{ site_name }}.nft"
          owner: root
          group: root
          mode: '0600'

      - name: Include our ruleset
        ansible.builtin.lineinfile:
          path:   /etc/sysconfig/nftables.conf
          regexp: '^include "/etc/nftables/{{ site_name }}.nft"'
          line:   'include "/etc/nftables/{{ site_name }}.nft"'

      - name: Stop firewalld and prevent its use
        ansible.builtin.systemd:
          name: firewalld
          enabled: no
          masked:  yes
          state: stopped
        when:
        - ansible_facts.services["firewalld.service"] is defined

      - name: Ensure that nftables runs with our ruleset
        ansible.builtin.systemd:
          name: nftables
          enabled: yes
          masked:  no
          state: restarted

      when:
      - _found_ruleset|length > 0

    - block:
      # Use FirewallD
      # ... necessary tasks ...
      when:
      - _found_ruleset|length == 0

The downside is that one has to write the entire ruleset for the machine, rather than let FirewallD handle the syntax.
The upside is that you (can) get lean and mean ruleset for a server that does not need fancy “dynamic” rules.

2 Likes