diff --git a/docs/templates/template_reference.md b/docs/templates/template_reference.md index fabe0882425..66f1ba668b9 100644 --- a/docs/templates/template_reference.md +++ b/docs/templates/template_reference.md @@ -1118,6 +1118,9 @@ escape_yaml_key - Escape uppercase letters and `^` with additional `^` and convert letters to lovercase. This is because of OVAL's name argument limitations. +join_comma_and +- Join list using comma and "and". Example ["a", "b", "c"] -> "a, b and c". + quote - Escape string to be used as POSIX shell value. Like Ansible `quote`. diff --git a/linux_os/guide/services/ssh/ssh_server/firewalld_sshd_port_enabled/ansible/shared.yml b/linux_os/guide/services/ssh/ssh_server/firewalld_sshd_port_enabled/ansible/shared.yml index 7b0bda3f10c..8167cf7b34a 100644 --- a/linux_os/guide/services/ssh/ssh_server/firewalld_sshd_port_enabled/ansible/shared.yml +++ b/linux_os/guide/services/ssh/ssh_server/firewalld_sshd_port_enabled/ansible/shared.yml @@ -6,13 +6,7 @@ {{{ ansible_instantiate_variables("firewalld_sshd_zone") }}} -- name: '{{{ rule_title }}} - Ensure firewalld and NetworkManager packages are installed' - ansible.builtin.package: - name: "{{ item }}" - state: present - with_items: - - firewalld - - NetworkManager +{{{ ansible_package_install(["firewalld", "NetworkManager"]) }}} - name: '{{{ rule_title }}} - Collect facts about system services' ansible.builtin.service_facts: diff --git a/linux_os/guide/system/accounts/accounts-pam/locking_out_password_attempts/accounts_passwords_pam_faillock_dir/ansible/shared.yml b/linux_os/guide/system/accounts/accounts-pam/locking_out_password_attempts/accounts_passwords_pam_faillock_dir/ansible/shared.yml index e199dc3dca8..f03e107fa1b 100644 --- a/linux_os/guide/system/accounts/accounts-pam/locking_out_password_attempts/accounts_passwords_pam_faillock_dir/ansible/shared.yml +++ b/linux_os/guide/system/accounts/accounts-pam/locking_out_password_attempts/accounts_passwords_pam_faillock_dir/ansible/shared.yml @@ -7,14 +7,7 @@ {{{ ansible_pam_faillock_enable() }}} {{{ ansible_pam_faillock_parameter_value("dir", "var_accounts_passwords_pam_faillock_dir") }}} -- name: '{{{ rule_title }}} - Ensure necessary SELinux packages are installed' - ansible.builtin.package: - name: "{{ item }}" - state: present - with_items: - - python3-libselinux - - python3-policycoreutils - - policycoreutils-python-utils +{{{ ansible_package_install(["python3-libselinux", "python3-policycoreutils", "policycoreutils-python-utils"], "necessary SELinux") }}} - name: '{{{ rule_title }}} - Create the tally directory if it does not exist' ansible.builtin.file: diff --git a/linux_os/guide/system/network/network-firewalld/ruleset_modifications/firewalld_loopback_traffic_restricted/ansible/shared.yml b/linux_os/guide/system/network/network-firewalld/ruleset_modifications/firewalld_loopback_traffic_restricted/ansible/shared.yml index 47570544658..1cc3861b26a 100644 --- a/linux_os/guide/system/network/network-firewalld/ruleset_modifications/firewalld_loopback_traffic_restricted/ansible/shared.yml +++ b/linux_os/guide/system/network/network-firewalld/ruleset_modifications/firewalld_loopback_traffic_restricted/ansible/shared.yml @@ -4,12 +4,7 @@ # strategy = configure # disruption = low -- name: '{{{ rule_title }}} - Ensure firewalld Package is Installed' - ansible.builtin.package: - name: "{{ item }}" - state: present - with_items: - - firewalld +{{{ ansible_package_install(["firewalld"]) }}} - name: '{{{ rule_title }}} - Collect Facts About System Services' ansible.builtin.service_facts: diff --git a/linux_os/guide/system/network/network-firewalld/ruleset_modifications/firewalld_loopback_traffic_trusted/ansible/shared.yml b/linux_os/guide/system/network/network-firewalld/ruleset_modifications/firewalld_loopback_traffic_trusted/ansible/shared.yml index 311650f72ee..1d14fd889d0 100644 --- a/linux_os/guide/system/network/network-firewalld/ruleset_modifications/firewalld_loopback_traffic_trusted/ansible/shared.yml +++ b/linux_os/guide/system/network/network-firewalld/ruleset_modifications/firewalld_loopback_traffic_trusted/ansible/shared.yml @@ -4,12 +4,7 @@ # strategy = configure # disruption = low -- name: '{{{ rule_title }}} - Ensure firewalld Package is Installed' - ansible.builtin.package: - name: "{{ item }}" - state: present - with_items: - - firewalld +{{{ ansible_package_install(["firewalld"]) }}} - name: '{{{ rule_title }}} - Collect Facts About System Services' ansible.builtin.service_facts: diff --git a/linux_os/guide/system/network/network-wireless/wireless_software/wireless_disable_interfaces/ansible/shared.yml b/linux_os/guide/system/network/network-wireless/wireless_software/wireless_disable_interfaces/ansible/shared.yml index be7a30c34a3..d7b9f542435 100644 --- a/linux_os/guide/system/network/network-wireless/wireless_software/wireless_disable_interfaces/ansible/shared.yml +++ b/linux_os/guide/system/network/network-wireless/wireless_software/wireless_disable_interfaces/ansible/shared.yml @@ -4,12 +4,7 @@ # complexity = low # disruption = medium -- name: Ensure NetworkManager is installed - ansible.builtin.package: - name: "{{ item }}" - state: present - with_items: - - NetworkManager +{{{ ansible_package_install(["NetworkManager"]) }}} - name: Deactivate Wireless Network Interfaces command: nmcli radio wifi off diff --git a/linux_os/guide/system/software/integrity/fips/grub2_enable_fips_mode/ansible/shared.yml b/linux_os/guide/system/software/integrity/fips/grub2_enable_fips_mode/ansible/shared.yml index 3af960a3698..82ee56ec83f 100644 --- a/linux_os/guide/system/software/integrity/fips/grub2_enable_fips_mode/ansible/shared.yml +++ b/linux_os/guide/system/software/integrity/fips/grub2_enable_fips_mode/ansible/shared.yml @@ -26,17 +26,11 @@ register: aesni_supported check_mode: no -- name: Ensure dracut-fips-aesni is installed - package: - name: dracut-fips-aesni - state: present +{{{ ansible_package_install(["dracut-fips-aesni"]) }}} when: - aesni_supported.rc == 0 -- name: Install dracut-fips - package: - name: dracut-fips - state: present +{{{ ansible_package_install(["dracut-fips"]) }}} - name: Rebuild initramfs command: dracut -f diff --git a/linux_os/guide/system/software/integrity/fips/package_dracut-fips-aesni_installed/ansible/shared.yml b/linux_os/guide/system/software/integrity/fips/package_dracut-fips-aesni_installed/ansible/shared.yml index 7c3e3c4f416..618d95efcb6 100644 --- a/linux_os/guide/system/software/integrity/fips/package_dracut-fips-aesni_installed/ansible/shared.yml +++ b/linux_os/guide/system/software/integrity/fips/package_dracut-fips-aesni_installed/ansible/shared.yml @@ -9,9 +9,6 @@ register: aesni_supported check_mode: no -- name: Ensure dracut-fips-aesni is installed - package: - name: dracut-fips-aesni - state: present +{{{ ansible_package_install(["dracut-fips-aesni"]) }}} when: - aesni_supported.rc == 0 diff --git a/linux_os/guide/system/software/integrity/software-integrity/aide/aide_build_database/ansible/shared.yml b/linux_os/guide/system/software/integrity/software-integrity/aide/aide_build_database/ansible/shared.yml index d9b022f0d54..c0ca52e48f7 100644 --- a/linux_os/guide/system/software/integrity/software-integrity/aide/aide_build_database/ansible/shared.yml +++ b/linux_os/guide/system/software/integrity/software-integrity/aide/aide_build_database/ansible/shared.yml @@ -3,12 +3,8 @@ # strategy = restrict # complexity = low # disruption = low -- name: "Ensure AIDE is installed" - package: - name: "{{ item }}" - state: present - with_items: - - aide + +{{{ ansible_package_install(['aide'], name="AIDE") }}} - name: "Build and Test AIDE Database" {{% if 'sle' in product %}} diff --git a/linux_os/guide/system/software/integrity/software-integrity/aide/aide_check_audit_tools/ansible/shared.yml b/linux_os/guide/system/software/integrity/software-integrity/aide/aide_check_audit_tools/ansible/shared.yml index b40cc174d0e..7c8a5bf961b 100644 --- a/linux_os/guide/system/software/integrity/software-integrity/aide/aide_check_audit_tools/ansible/shared.yml +++ b/linux_os/guide/system/software/integrity/software-integrity/aide/aide_check_audit_tools/ansible/shared.yml @@ -4,13 +4,7 @@ # complexity = low # disruption = low -- name: Ensure aide is installed - package: - name: "{{ item }}" - state: present - with_items: - - aide - +{{{ ansible_package_install(['aide'], name="AIDE") }}} - name: Set audit_tools fact set_fact: diff --git a/linux_os/guide/system/software/integrity/software-integrity/aide/aide_periodic_cron_checking/ansible/shared.yml b/linux_os/guide/system/software/integrity/software-integrity/aide/aide_periodic_cron_checking/ansible/shared.yml index 7d4063bda29..be6c8d1d533 100644 --- a/linux_os/guide/system/software/integrity/software-integrity/aide/aide_periodic_cron_checking/ansible/shared.yml +++ b/linux_os/guide/system/software/integrity/software-integrity/aide/aide_periodic_cron_checking/ansible/shared.yml @@ -3,12 +3,8 @@ # strategy = restrict # complexity = low # disruption = low -- name: "Ensure AIDE is installed" - package: - name: - - aide - - crontabs - state: present + +{{{ ansible_package_install(['aide', 'crontabs'], name="AIDE") }}} - name: Set cron package name - RedHat set_fact: diff --git a/linux_os/guide/system/software/integrity/software-integrity/aide/aide_scan_notification/ansible/shared.yml b/linux_os/guide/system/software/integrity/software-integrity/aide/aide_scan_notification/ansible/shared.yml index 45db52bf238..58289b10eb2 100644 --- a/linux_os/guide/system/software/integrity/software-integrity/aide/aide_scan_notification/ansible/shared.yml +++ b/linux_os/guide/system/software/integrity/software-integrity/aide/aide_scan_notification/ansible/shared.yml @@ -5,12 +5,7 @@ # disruption = low - (xccdf-var var_aide_scan_notification_email) -- name: "Ensure AIDE is installed" - package: - name: - - aide - - crontabs - state: present +{{{ ansible_package_install(['aide', 'crontabs'], name="AIDE") }}} - name: "{{{ rule_title }}}" cron: diff --git a/shared/macros/10-ansible.jinja b/shared/macros/10-ansible.jinja index 47103022b21..4ad993b7aa6 100644 --- a/shared/macros/10-ansible.jinja +++ b/shared/macros/10-ansible.jinja @@ -771,6 +771,37 @@ The following macro remediates Audit syscall rule in :code:`/etc/audit/audit.rul {{%- endmacro -%}} +{{# +Ansible ansible.builtin.package wrapping macro, ensure package(s) are installed + +:param package: Package(s) to ensure are installed +:type package: str | list[str] +:param name: Name used in task name. If not set, package names joined with comma and "and". +:type name: None | str + +#}} +{{%- macro ansible_package_install(package, name=none) -%}} +{{%- if (package is sequence) and (package is not mapping) and (package is not string) -%}} +{{%- set packages = package -%}} +{{%- else %}} +{{%- set packages = [package] -%}} +{{%- endif %}} +{{%- if name is none %}} +{{%- set name = "the " ~ (packages | join_comma_and) -%}} +{{%- endif %}} +- name: "{{{ rule_title }}} - Ensure {{{ name }}} {{% if packages | length > 1 %}}Packages Are{{% else %}}Package Is{{% endif %}} Installed" + ansible.builtin.package: + name: +{{%- for p in packages %}} +{{%- if p in platform_package_overrides %}} + {{%- set p = platform_package_overrides[p] %}} +{{%- endif %}} + - "{{{ p }}}" +{{%- endfor %}} + state: present +{{%- endmacro -%}} + + {{# Macro used to check if authselect files are intact. When used, it will exit the respective script if any authselect file was modified without proper use of authselect tool and diff --git a/shared/macros/10-bash.jinja b/shared/macros/10-bash.jinja index 3316c487561..020393b5c97 100644 --- a/shared/macros/10-bash.jinja +++ b/shared/macros/10-bash.jinja @@ -603,6 +603,9 @@ done #}} {{%- macro bash_package_install(package) -%}} +{{%- if package in platform_package_overrides -%}} + {{%- set package = platform_package_overrides[package] -%}} +{{%- endif -%}} {{%- if pkg_manager is defined -%}} {{%- if pkg_manager == "yum" or pkg_manager == "dnf" -%}} if ! rpm -q --quiet "{{{ package }}}" ; then @@ -632,6 +635,9 @@ zypper install -y "{{{ package }}}" #}} {{%- macro bash_package_remove(package) -%}} +{{%- if package in platform_package_overrides -%}} + {{%- set package = platform_package_overrides[package] -%}} +{{%- endif -%}} {{%- if pkg_manager is defined -%}} {{%- if pkg_manager == "yum" or pkg_manager == "dnf" -%}} if rpm -q --quiet "{{{ package }}}" ; then diff --git a/ssg/jinja.py b/ssg/jinja.py index 7aee25b5ecc..127d93d7d11 100644 --- a/ssg/jinja.py +++ b/ssg/jinja.py @@ -24,6 +24,7 @@ escape_id, escape_regex, escape_yaml_key, + join_comma_and, sha256 ) @@ -95,6 +96,7 @@ def _get_jinja_environment(substitutions_dict): _get_jinja_environment.env.filters['escape_id'] = escape_id _get_jinja_environment.env.filters['escape_regex'] = escape_regex _get_jinja_environment.env.filters['escape_yaml_key'] = escape_yaml_key + _get_jinja_environment.env.filters['join_comma_and'] = join_comma_and _get_jinja_environment.env.filters['quote'] = shell_quote _get_jinja_environment.env.filters['sha256'] = sha256 diff --git a/ssg/utils.py b/ssg/utils.py index 1c2ac1d4251..789ce938665 100644 --- a/ssg/utils.py +++ b/ssg/utils.py @@ -470,3 +470,7 @@ def apply_formatting_on_dict_values(source_dict, string_dict, ignored_keys=froze else: new_dict[k] = v return new_dict + + +def join_comma_and(lst): + return ", ".join(lst[:-2] + [" and ".join(lst[-2:])]) diff --git a/tests/unit/ssg-module/test_jinja.py b/tests/unit/ssg-module/test_jinja.py index 7545515a487..20909fcf41d 100644 --- a/tests/unit/ssg-module/test_jinja.py +++ b/tests/unit/ssg-module/test_jinja.py @@ -26,3 +26,11 @@ def test_macro_expansion(): complete_defs = get_definitions_with_substitution(dict(global_var="value")) assert complete_defs["expand_to_global_var"]() == "value" + + +def test_join_comma_and(): + assert ssg.jinja.join_comma_and([]) == "" + assert ssg.jinja.join_comma_and(["first"]) == "first" + assert ssg.jinja.join_comma_and(["first", "last"]) == "first and last" + assert ssg.jinja.join_comma_and(["first", "b", "last"]) == "first, b and last" + assert ssg.jinja.join_comma_and(["first", "b", "c", "last"]) == "first, b, c and last"