--- - name: "Check whether OS is a SUSE derivative" ansible.builtin.assert: that: - ansible_distribution_file_variety == 'SUSE' or ansible_distribution_file_variety == 'SuSE' no_log: true - name: Check for existence of rkhunter ansible.builtin.stat: path: /usr/bin/rkhunter register: rkhex ignore_errors: true no_log: true # yum always tosses this arbitrary extra line at you, a simple tr -s does not eradicate it, so - well, # 0 and 1 are fine. As explained above, the RC is worthless when run through ansible. changed_when: false notify: "rkhunter execution" - name: Update zypper cache (SUSE) # we cannot cheat like we did with yum: we need to update any package to refresh the cache with the zypper module. Hence falling back # to shell. ansible.builtin.shell: cmd: 'zypper refs && zypper ref' changed_when: false register: zypperref become: true - name: Verify Zypper repository availability # Now, here's the thing with zypper. If you have a dead repository, you need to face the following facts: # 1. All output goes to stdout. For zypper lu at least on SLE12/openSUSE42 and earlier, this is: # - The packages available for update # - Debug output lik "loading repository data..." and "reading installed packages..." # (could be silenced with -q, but without RC feedback we need the debug strings again, kek.) # - WARNING(!!) messages # ... there is no STDERR. # 2. There is no return code other than 0 for warnings. # Great. Interaction with automatisms as if that stuff came directly from Redmond. # So we need to parse the fucking output string in ansible. Let's start with the "repository not available" warnings. ansible.builtin.debug: msg: "Dead repositories existing and no update present, we consider this a failure." when: - zypperref is search("Repository.*appears to be outdated") - zypperref is search("No updates found") failed_when: true - name: Check for zypper updates ansible.builtin.command: zypper lu register: zypperlu changed_when: false become: true - block: - name: Update all packages (SUSE) # we could narrow this down via type:patch, but that's about all. So fire away. community.general.zypper: name: '*' state: latest extra_args: '--no-refresh' # this is only document as "zypper rm -u", so apparently nothing is existing like # rpm's cleanup or apt's "autoremove" :( # clean_deps: true become: true name: Update and RKhunter checks when: - zypperlu is not search("No updates found.") - block: - name: Register requirement for reboot (SUSE) # change in paradigm: we will now use "needs-rebooting", suse implemented that somewhere between 12 and 15, instead of "ps -sss" # todo: what to do if services require a refork? # shell: zypper ps -sss ansible.builtin.command: zypper needs-rebooting register: nrout changed_when: nrout.rc|int == 102 failed_when: nrout.rc|int != 102 and nrout.rc|int != 0 notify: "Reboot if required" # we listen to "suse upd" here in case a previous reboot was skipped. Change to "suse updates available" if undesired. name: Check reboot requirement - block: - name: Clean packages cache # ansible's zypper module does not have a dedicated action for this yet. So shell it is: ansible.builtin.command: zypper clean changed_when: false - name: Purge old kernels # ansible's zypper module does not have a dedicated action for this yet. So shell it is: ansible.builtin.command: zypper purge-kernels # TODO: Check output for actual kernel-purging and make this a proper statement: changed_when: false name: Cleanup become: true - name: RKhunter properties update ansible.builtin.command: rkhunter --propupd --rwo --ns become: true changed_when: true when: - rkhex.stat is defined - rkhex.stat.executable is defined - rkhex.stat.executable|bool == true - name: Reboot if required # ignore_errors: yes ansible.builtin.reboot: reboot_timeout: 300 pre_reboot_delay: 5 test_command: uptime reboot_command: "/bin/systemctl reboot" become: true when: nrout is defined and nrout.rc is defined and nrout.rc|int == 102