Ansible vs. FirewallD


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:

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"
    cmd: firewall-cmd --set-default-zone=internal
  changed_when: false

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

- name: "Disable all other predefined FirewallD services"
    service: "{{ item }}"
    permanent: yes
    immediate: yes
    state: disabled
    - 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

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

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

      - name: nftables is required
          name:  nftables
          state: present

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

      - name: Include our ruleset
          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
          name: firewalld
          enabled: no
          masked:  yes
          state: stopped
        -["firewalld.service"] is defined

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

      - _found_ruleset|length > 0

    - block:
      # Use FirewallD
      # ... necessary tasks ...
      - _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.