linuxansibleredhatfirewalld

Ansible Rhel-system-roles-firewalld always trying to install firewalld


I'm currently usign rhel-system-roles-1.23.0-2.21.el8.noarch despite my effort the role always trying to install firewall. It feel like the ansible_facts are not good well path to my include_role maybe.

The documentation tell us :

This role configures the firewall on machines that are using firewalld. If firewalld is not in use, the role will install (if not already installed), unmask, and enable firewalld.

But as i see in the source code of the role, the use of state present will always trying to install firewalld: https://github.com/linux-system-roles/firewall/blob/1.7.5/tasks/firewalld.yml

The problem is that i work with an internetless environment and i will never have access to it. I've try to override the variable used before but without success :

    - name: Gather only required firewall facts
      setup:
        gather_subset:
          - '!all'
          - '!min'
          - python_version
          - service_mgr

    - name: Mock package
      set_fact:
        __firewall_packages_base: []

    - name: Include firewall role
      include_role:
        name: redhat.rhel_system_roles.firewall
      vars:
        firewall:
          - service: ssh
            state: enabled

I've thinked about overriding the role manually by adding a variable to skip the task Install firewall.

Or to modify the file in a previous task who will commenting this specific task.

But for me those are not the proper way to do it, is there is an other solution ?

The log :

TASK [firewall : Ensure ansible_facts used by role] ***************************************************************************************************************
task path: /usr/share/ansible/collections/ansible_collections/redhat/rhel_system_roles/roles/firewall/tasks/firewalld.yml:2
skipping: [localhost] => {
    "changed": false,
    "skip_reason": "Conditional result was False"
}
TASK [firewall : Check if system is ostree] 
ok: [localhost] => {
    "changed": false,
    "invocation": {
        "module_args": {
            "checksum_algorithm": "sha1",
            "follow": false,
            "get_attributes": true,
            "get_checksum": true,
            "get_md5": false,
            "get_mime": true,
            "path": "/run/ostree-booted"
        }
    },
    "stat": {
        "exists": false
    }
}

TASK [firewall : Set flag to indicate system is ostree] ***********************************************************************************************************
task path: /usr/share/ansible/collections/ansible_collections/redhat/rhel_system_roles/roles/firewall/tasks/firewalld.yml:15
ok: [localhost] => {
    "ansible_facts": {
        "__firewall_is_ostree": false
    },
    "changed": false
}

TASK [firewall : Install firewalld] *******************************************************************************************************************************
task path: /usr/share/ansible/collections/ansible_collections/redhat/rhel_system_roles/roles/firewall/tasks/firewalld.yml:19
Running dnf
<localhost> ESTABLISH LOCAL CONNECTION FOR USER: exploit
<localhost> EXEC /bin/sh -c 'echo ~exploit && sleep 0'
<localhost> EXEC /bin/sh -c '( umask 77 && mkdir -p "` echo /home/exploit/.ansible/tmp/ansible-tmp-1746175176.850642-7862754315108 `" && echo ansible-tmp-1746175176.850642-7862754315108="` echo /home/exploit/.ansible/tmp/ansible-tmp-1746175176.850642-7862754315108 `" ) && sleep 0'
Using module file /opt/ansible_venv/lib/python3.6/site-packages/ansible/modules/packaging/os/dnf.py
<localhost> PUT /home/exploit/.ansible/tmp/ansible-local-3738394t7btox0_/tmpxog9lekc TO /home/exploit/.ansible/tmp/ansible-tmp-1746175176.850642-7862754315108/AnsiballZ_dnf.py
<localhost> EXEC /bin/sh -c 'chmod u+x /home/exploit/.ansible/tmp/ansible-tmp-1746175176.850642-7862754315108/ /home/exploit/.ansible/tmp/ansible-tmp-1746175176.850642-7862754315108/AnsiballZ_dnf.py && sleep 0'
<localhost> EXEC /bin/sh -c 'sudo -H -S  -p "[sudo via ansible, key=mjanqipehlfiikdfmahfqildjkdewgkh] password:" -u root /bin/sh -c '"'"'echo BECOME-SUCCESS-mjanqipehlfiikdfmahfqildjkdewgkh ; /usr/libexec/platform-python /home/exploit/.ansible/tmp/ansible-tmp-1746175176.850642-7862754315108/AnsiballZ_dnf.py'"'"' && sleep 0'
<localhost> EXEC /bin/sh -c 'rm -f -r /home/exploit/.ansible/tmp/ansible-tmp-1746175176.850642-7862754315108/ > /dev/null 2>&1 && sleep 0'
The full traceback is:
  File "/tmp/ansible_dnf_payload_y1gkrn9h/ansible_dnf_payload.zip/ansible/modules/packaging/os/dnf.py", line 649, in _base
  File "/usr/lib/python3.6/site-packages/dnf/base.py", line 400, in fill_sack
    self._add_repo_to_sack(r)
  File "/usr/lib/python3.6/site-packages/dnf/base.py", line 140, in _add_repo_to_sack
    repo.load()
  File "/usr/lib/python3.6/site-packages/dnf/repo.py", line 580, in load
    raise dnf.exceptions.RepoError(str(e))
fatal: [localhost]: FAILED! => {
    "changed": false,
    "invocation": {
        "module_args": {
            "allow_downgrade": false,
            "autoremove": false,
            "bugfix": false,
            "conf_file": null,
            "disable_excludes": null,
            "disable_gpg_check": false,
            "disable_plugin": [],
            "disablerepo": [],
            "download_dir": null,
            "download_only": false,
            "enable_plugin": [],
            "enablerepo": [],
            "exclude": [],
            "install_repoquery": true,
            "install_weak_deps": true,
            "installroot": "/",
            "list": null,
            "lock_timeout": 30,
            "name": [],
            "releasever": null,
            "security": false,
            "skip_broken": false,
            "state": "present",
            "update_cache": false,
            "update_only": false,
            "validate_certs": true
        }
    },
    "msg": "Failed to download metadata for repo 'appstream_local': Cannot download repomd.xml: Cannot download repodata/repomd.xml: All mirrors were tried",
    "rc": 1,
    "results": []
}

Solution

  • I checked how package module works with incorrect (example.invalid) repos, and it is indeed trying to check them by default. And since this role actually uses package module instead of dnf, you can't provide a disablerepo: "*" option to make it ignore all repos (it would've worked that way).

    As for working around this limitation, i think that disabling repositories using separate playbook (or pre task, if you wish) would be the cleanest and most idiomatic option, especially if these machines are not supposed to be connected to the internet ever. You can achieve that by either moving contents of /etc/yum.repod.d to, i.e. /etc/yum.repos.d.bak , to be easily restored later, or by using either yum_repo or ini module to disable currently enabled repos.

    I would advise against patching system roles, because explicit disabling of repositories will certainly be easier to see and maintain later, than supporting a fork of fairly active repo.

    The other potential workaround was to use -e or --extra-vars cli option, but it haven't worked with the same error, even when setting package name to [] or None. When you tried to override __firewall_packages_base with

        - name: Mock package
          set_fact:
            __firewall_packages_base: []
    

    that wouldn't work because per ansible variable precedence set_fact is lower priority than role variables by default, and __firewall_packages_base: [firewalld] is actually set in vars/ of firewall role.