403Webshell
Server IP : 178.212.43.201  /  Your IP : 10.100.0.33
Web Server : Apache/2.4.37 (Oracle Linux Server) OpenSSL/1.1.1k
System : Linux spa0007.srv.paxillus.pl 5.4.17-2136.355.3.1.el8uek.x86_64 #3 SMP Sat May 9 17:11:55 PDT 2026 x86_64
User : apache ( 48)
PHP Version : 7.4.33
Disable Function : NONE
MySQL : OFF  |  cURL : ON  |  WGET : ON  |  Perl : ON  |  Python : OFF  |  Sudo : ON  |  Pkexec : ON
Directory :  /usr/share/scap-security-guide/ansible/

Upload File :
current_dir [ Writeable ] document_root [ Writeable ]

 

Command :


[ Back ]     

Current File : /usr/share/scap-security-guide/ansible/ol9-playbook-stig.yml
---
###############################################################################
#
# Ansible Playbook for DISA STIG for Oracle Linux 9
#
# Profile Description:
# This profile contains configuration checks that align to the
# DISA STIG for Oracle Linux 9 V1R4.
#
# Profile ID:  xccdf_org.ssgproject.content_profile_stig
# Benchmark ID:  xccdf_org.ssgproject.content_benchmark_OL-9
# Benchmark Version:  0.1.80
# XCCDF Version:  1.2
#
# This file can be generated by OpenSCAP using:
# $ oscap xccdf generate fix --profile xccdf_org.ssgproject.content_profile_stig --fix-type ansible ssg-ol9-ds.xml
#
# This Ansible Playbook is generated from an XCCDF profile without preliminary evaluation.
# It attempts to fix every selected rule, even if the system is already compliant.
#
# How to apply this Ansible Playbook:
# $ ansible-playbook -i "localhost," -c local playbook.yml
# $ ansible-playbook -i "192.168.1.155," playbook.yml
# $ ansible-playbook -i inventory.ini playbook.yml
#
###############################################################################

- name: Ansible Playbook for xccdf_org.ssgproject.content_profile_stig
  hosts: all
  vars:
    var_aide_scan_notification_email: root@localhost
    var_system_crypto_policy: FIPS
    sshd_approved_ciphers: [email protected],aes256-ctr,[email protected],aes128-ctr
    sshd_approved_macs: [email protected],[email protected],hmac-sha2-256,hmac-sha2-512
    inactivity_timeout_value: '600'
    var_screensaver_lock_delay: '5'
    var_sudo_timestamp_timeout: '0'
    var_authselect_profile: sssd
    login_banner_text: ^You[\s\n]+are[\s\n]+accessing[\s\n]+a[\s\n]+U\.S\.[\s\n]+Government[\s\n]+\(USG\)[\s\n]+Information[\s\n]+System[\s\n]+\(IS\)[\s\n]+that[\s\n]+is[\s\n]+provided[\s\n]+for[\s\n]+USG\-authorized[\s\n]+use[\s\n]+only\.[\s\n]+By[\s\n]+using[\s\n]+this[\s\n]+IS[\s\n]+\(which[\s\n]+includes[\s\n]+any[\s\n]+device[\s\n]+attached[\s\n]+to[\s\n]+this[\s\n]+IS\),[\s\n]+you[\s\n]+consent[\s\n]+to[\s\n]+the[\s\n]+following[\s\n]+conditions\:(?:[\n]+|(?:\\n)+)\-The[\s\n]+USG[\s\n]+routinely[\s\n]+intercepts[\s\n]+and[\s\n]+monitors[\s\n]+communications[\s\n]+on[\s\n]+this[\s\n]+IS[\s\n]+for[\s\n]+purposes[\s\n]+including,[\s\n]+but[\s\n]+not[\s\n]+limited[\s\n]+to,[\s\n]+penetration[\s\n]+testing,[\s\n]+COMSEC[\s\n]+monitoring,[\s\n]+network[\s\n]+operations[\s\n]+and[\s\n]+defense,[\s\n]+personnel[\s\n]+misconduct[\s\n]+\(PM\),[\s\n]+law[\s\n]+enforcement[\s\n]+\(LE\),[\s\n]+and[\s\n]+counterintelligence[\s\n]+\(CI\)[\s\n]+investigations\.(?:[\n]+|(?:\\n)+)\-At[\s\n]+any[\s\n]+time,[\s\n]+the[\s\n]+USG[\s\n]+may[\s\n]+inspect[\s\n]+and[\s\n]+seize[\s\n]+data[\s\n]+stored[\s\n]+on[\s\n]+this[\s\n]+IS\.(?:[\n]+|(?:\\n)+)\-Communications[\s\n]+using,[\s\n]+or[\s\n]+data[\s\n]+stored[\s\n]+on,[\s\n]+this[\s\n]+IS[\s\n]+are[\s\n]+not[\s\n]+private,[\s\n]+are[\s\n]+subject[\s\n]+to[\s\n]+routine[\s\n]+monitoring,[\s\n]+interception,[\s\n]+and[\s\n]+search,[\s\n]+and[\s\n]+may[\s\n]+be[\s\n]+disclosed[\s\n]+or[\s\n]+used[\s\n]+for[\s\n]+any[\s\n]+USG\-authorized[\s\n]+purpose\.(?:[\n]+|(?:\\n)+)\-This[\s\n]+IS[\s\n]+includes[\s\n]+security[\s\n]+measures[\s\n]+\(e\.g\.,[\s\n]+authentication[\s\n]+and[\s\n]+access[\s\n]+controls\)[\s\n]+to[\s\n]+protect[\s\n]+USG[\s\n]+interests\-\-not[\s\n]+for[\s\n]+your[\s\n]+personal[\s\n]+benefit[\s\n]+or[\s\n]+privacy\.(?:[\n]+|(?:\\n)+)\-Notwithstanding[\s\n]+the[\s\n]+above,[\s\n]+using[\s\n]+this[\s\n]+IS[\s\n]+does[\s\n]+not[\s\n]+constitute[\s\n]+consent[\s\n]+to[\s\n]+PM,[\s\n]+LE[\s\n]+or[\s\n]+CI[\s\n]+investigative[\s\n]+searching[\s\n]+or[\s\n]+monitoring[\s\n]+of[\s\n]+the[\s\n]+content[\s\n]+of[\s\n]+privileged[\s\n]+communications,[\s\n]+or[\s\n]+work[\s\n]+product,[\s\n]+related[\s\n]+to[\s\n]+personal[\s\n]+representation[\s\n]+or[\s\n]+services[\s\n]+by[\s\n]+attorneys,[\s\n]+psychotherapists,[\s\n]+or[\s\n]+clergy,[\s\n]+and[\s\n]+their[\s\n]+assistants\.[\s\n]+Such[\s\n]+communications[\s\n]+and[\s\n]+work[\s\n]+product[\s\n]+are[\s\n]+private[\s\n]+and[\s\n]+confidential\.[\s\n]+See[\s\n]+User[\s\n]+Agreement[\s\n]+for[\s\n]+details\.$
    var_accounts_passwords_pam_faillock_deny: '3'
    var_accounts_passwords_pam_faillock_dir: /var/log/faillock
    var_accounts_passwords_pam_faillock_fail_interval: '900'
    var_accounts_passwords_pam_faillock_unlock_time: '0'
    var_password_pam_dcredit: '-1'
    var_password_pam_dictcheck: '1'
    var_password_pam_difok: '8'
    var_password_pam_lcredit: '-1'
    var_password_pam_maxclassrepeat: '4'
    var_password_pam_maxrepeat: '3'
    var_password_pam_minclass: '4'
    var_password_pam_minlen: '15'
    var_password_pam_ocredit: '-1'
    var_password_pam_retry: '3'
    var_password_pam_ucredit: '-1'
    var_password_hashing_algorithm_pam: sha512
    var_password_hashing_algorithm: SHA512
    var_password_hashing_min_rounds_login_defs: '100000'
    var_smartcard_drivers: cac
    var_account_disable_post_pw_expiration: '35'
    var_accounts_maximum_age_login_defs: '60'
    var_accounts_minimum_age_login_defs: '1'
    var_password_pam_unix_rounds: '100000'
    var_accounts_fail_delay: '4'
    var_accounts_max_concurrent_login_sessions: '10'
    var_accounts_tmout: '900'
    var_user_initialization_files_regex: ^(\.bashrc|\.zshrc|\.cshrc|\.profile|\.bash_login|\.bash_profile)$
    var_accounts_user_umask: '077'
    rsyslog_remote_loghost_address: logcollector
    sysctl_net_ipv6_conf_all_accept_ra_value: '0'
    sysctl_net_ipv6_conf_all_accept_redirects_value: '0'
    sysctl_net_ipv6_conf_all_accept_source_route_value: '0'
    sysctl_net_ipv6_conf_all_forwarding_value: '0'
    sysctl_net_ipv6_conf_default_accept_ra_value: '0'
    sysctl_net_ipv6_conf_default_accept_redirects_value: '0'
    sysctl_net_ipv6_conf_default_accept_source_route_value: '0'
    sysctl_net_ipv4_conf_all_accept_redirects_value: '0'
    sysctl_net_ipv4_conf_all_accept_source_route_value: '0'
    sysctl_net_ipv4_conf_all_forwarding_value: '0'
    sysctl_net_ipv4_conf_all_log_martians_value: '1'
    sysctl_net_ipv4_conf_all_rp_filter_value: '1'
    sysctl_net_ipv4_conf_default_accept_redirects_value: '0'
    sysctl_net_ipv4_conf_default_accept_source_route_value: '0'
    sysctl_net_ipv4_conf_default_log_martians_value: '1'
    sysctl_net_ipv4_conf_default_rp_filter_value: '1'
    sysctl_net_ipv4_icmp_echo_ignore_broadcasts_value: '1'
    sysctl_net_ipv4_icmp_ignore_bogus_error_responses_value: '1'
    sysctl_net_ipv4_tcp_syncookies_value: '1'
    var_networkmanager_dns_mode: none
    var_removable_partition: /dev/cdrom
    sysctl_kernel_kptr_restrict_value: '1'
    var_slub_debug_options: P
    var_selinux_policy_name: targeted
    var_selinux_state: enforcing
    var_time_service_set_maxpoll: '16'
    var_tftpd_secure_directory: /var/lib/tftpboot
    var_sshd_set_keepalive: '1'
    sshd_idle_timeout_value: '600'
    var_sshd_disable_compression: 'no'
    var_rekey_limit_size: 1G
    var_rekey_limit_time: 1h
    var_sssd_certificate_verification_digest_function: sha512
    var_audit_backlog_limit: '8192'
    var_audit_failure_mode: '2'
    var_auditd_disk_error_action: halt
    var_auditd_disk_full_action: halt
    var_auditd_action_mail_acct: root
    var_auditd_admin_space_left_action: single
    var_auditd_admin_space_left_percentage: '5'
    var_auditd_max_log_file_action: rotate
    var_auditd_space_left_action: email
    var_auditd_space_left_percentage: '25'
    var_auditd_freq: '100'
    var_auditd_name_format: hostname|fqd|numeric
  tasks:

  - name: Gather the package facts
    ansible.builtin.package_facts:
      manager: auto
    tags:
    - always

  - name: Ensure aide is installed
    ansible.builtin.package:
      name: aide
      state: present
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - CJIS-5.10.1.3
    - DISA-STIG-OL09-00-000300
    - NIST-800-53-CM-6(a)
    - PCI-DSS-Req-11.5
    - PCI-DSSv4-11.5.2
    - enable_strategy
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - package_aide_installed

  - name: Build and Test AIDE Database - Ensure AIDE Is Installed
    ansible.builtin.package:
      name: '{{ item }}'
      state: present
    with_items:
    - aide
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - CJIS-5.10.1.3
    - DISA-STIG-OL09-00-000300
    - NIST-800-53-CM-6(a)
    - PCI-DSS-Req-11.5
    - PCI-DSSv4-11.5.2
    - aide_build_database
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Configure AIDE to Verify the Audit Tools - Ensure AIDE is Installed
    ansible.builtin.package:
      name: '{{ item }}'
      state: present
    with_items:
    - aide
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-000710
    - NIST-800-53-AU-9(3)
    - NIST-800-53-AU-9(3).1
    - aide_check_audit_tools
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Configure Notification of Post-AIDE Scan Details - Ensure AIDE is installed
    ansible.builtin.package:
      name: '{{ item }}'
      state: present
    with_items:
    - aide
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-000301
    - NIST-800-53-CM-3(5)
    - NIST-800-53-CM-6(a)
    - aide_scan_notification
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Configure AIDE to Use FIPS 140-2 for Validating Hashes - Ensure aide is
      installed
    ansible.builtin.package:
      name: aide
      state: present
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-000302
    - NIST-800-171-3.13.11
    - NIST-800-53-CM-6(a)
    - NIST-800-53-SI-7
    - NIST-800-53-SI-7(1)
    - aide_use_fips_hashes
    - enable_strategy
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

  - name: Ensure crypto-policies is installed
    ansible.builtin.package:
      name: crypto-policies
      state: present
    tags:
    - DISA-STIG-OL09-00-000240
    - enable_strategy
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - package_crypto-policies_installed

  - name: Ensure sudo is installed
    ansible.builtin.package:
      name: sudo
      state: present
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-000230
    - NIST-800-53-CM-6(a)
    - PCI-DSSv4-2.2
    - PCI-DSSv4-2.2.6
    - enable_strategy
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - package_sudo_installed

  - name: Ensure gnutls-utils is installed
    ansible.builtin.package:
      name: gnutls-utils
      state: present
    tags:
    - DISA-STIG-OL09-00-000430
    - enable_strategy
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - package_gnutls-utils_installed

  - name: Ensure nss-tools is installed
    ansible.builtin.package:
      name: nss-tools
      state: present
    tags:
    - DISA-STIG-OL09-00-000380
    - enable_strategy
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - package_nss-tools_installed

  - name: Ensure rng-tools is installed
    ansible.builtin.package:
      name: rng-tools
      state: present
    when: ( ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
      )
    tags:
    - DISA-STIG-OL09-00-000370
    - enable_strategy
    - low_complexity
    - low_disruption
    - low_severity
    - no_reboot_needed
    - package_rng-tools_installed

  - name: 'Uninstall gssproxy Package: Ensure gssproxy is removed'
    ansible.builtin.package:
      name: gssproxy
      state: absent
    tags:
    - DISA-STIG-OL09-00-000115
    - disable_strategy
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - package_gssproxy_removed

  - name: 'Uninstall iprutils Package: Ensure iprutils is removed'
    ansible.builtin.package:
      name: iprutils
      state: absent
    tags:
    - DISA-STIG-OL09-00-000120
    - disable_strategy
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - package_iprutils_removed

  - name: 'Uninstall tuned Package: Ensure tuned is removed'
    ansible.builtin.package:
      name: tuned
      state: absent
    tags:
    - DISA-STIG-OL09-00-000125
    - disable_strategy
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - package_tuned_removed

  - name: Ensure dnf-plugins-core is installed
    package:
      name: dnf-plugins-core
      state: present
    when: ansible_pkg_mgr == "dnf"
    tags:
    - DISA-STIG-OL09-00-000105
    - disable_strategy
    - ensure_epel_repos_disabled
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

  - name: Security patches are up to date
    ansible.builtin.package:
      name: '*'
      state: latest
    tags:
    - CJIS-5.10.4.1
    - DISA-STIG-OL09-00-000015
    - NIST-800-53-CM-6(a)
    - NIST-800-53-SI-2(5)
    - NIST-800-53-SI-2(c)
    - PCI-DSS-Req-6.2
    - PCI-DSSv4-6.3
    - PCI-DSSv4-6.3.3
    - high_disruption
    - low_complexity
    - medium_severity
    - patch_strategy
    - reboot_required
    - security_patches_up_to_date
    - skip_ansible_lint

  - name: Lock Accounts Must Persist - Ensure necessary SELinux packages are installed
    ansible.builtin.package:
      name: '{{ item }}'
      state: present
    with_items:
    - python3-libselinux
    - python3-policycoreutils
    - policycoreutils-python-utils
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - '"pam" in ansible_facts.packages'
    tags:
    - DISA-STIG-OL09-00-003023
    - NIST-800-53-AC-7(a)
    - NIST-800-53-AC-7(b)
    - NIST-800-53-AC-7.1(ii)
    - accounts_passwords_pam_faillock_dir
    - configure_strategy
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

  - name: Ensure opensc is installed
    ansible.builtin.package:
      name: opensc
      state: present
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-000400
    - NIST-800-53-CM-6(a)
    - enable_strategy
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - package_opensc_installed

  - name: Ensure pcsc-lite is installed
    ansible.builtin.package:
      name: pcsc-lite
      state: present
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-000390
    - NIST-800-53-CM-6(a)
    - enable_strategy
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - package_pcsc-lite_installed

  - name: Ensure openssl-pkcs11 is installed
    ansible.builtin.package:
      name: openssl-pkcs11
      state: present
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - ansible_architecture != "s390x"
    tags:
    - DISA-STIG-OL09-00-000270
    - NIST-800-53-CM-6(a)
    - PCI-DSS-Req-8.3
    - enable_strategy
    - install_smartcard_packages
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

  - name: Ensure rsyslog-gnutls is installed
    ansible.builtin.package:
      name: rsyslog-gnutls
      state: present
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-000355
    - enable_strategy
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - package_rsyslog-gnutls_installed

  - name: Ensure rsyslog is installed
    ansible.builtin.package:
      name: rsyslog
      state: present
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-000350
    - NIST-800-53-CM-6(a)
    - enable_strategy
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - package_rsyslog_installed

  - name: Ensure firewalld is installed
    ansible.builtin.package:
      name: firewalld
      state: present
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-000220
    - NIST-800-53-CM-6(a)
    - PCI-DSSv4-1.2
    - PCI-DSSv4-1.2.1
    - enable_strategy
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - package_firewalld_installed

  - name: Ensure libreswan is installed
    ansible.builtin.package:
      name: libreswan
      state: present
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-000410
    - NIST-800-53-CM-6(a)
    - PCI-DSS-Req-4.1
    - enable_strategy
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - package_libreswan_installed

  - name: Deactivate Wireless Network Interfaces - Ensure NetworkManager is installed
    ansible.builtin.package:
      name: '{{ item }}'
      state: present
    with_items:
    - NetworkManager
    when: ( not ( ansible_virtualization_type in ["docker", "lxc", "openvz", "podman",
      "container"] ) )
    tags:
    - DISA-STIG-OL09-00-006001
    - NIST-800-171-3.1.16
    - NIST-800-53-AC-18(3)
    - NIST-800-53-AC-18(a)
    - NIST-800-53-CM-6(a)
    - NIST-800-53-CM-7(a)
    - NIST-800-53-CM-7(b)
    - NIST-800-53-MP-7
    - PCI-DSS-Req-1.3.3
    - PCI-DSSv4-1.3
    - PCI-DSSv4-1.3.3
    - low_complexity
    - medium_disruption
    - medium_severity
    - no_reboot_needed
    - unknown_strategy
    - wireless_disable_interfaces

  - name: Ensure policycoreutils-python-utils is installed
    ansible.builtin.package:
      name: policycoreutils-python-utils
      state: present
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-000210
    - enable_strategy
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - package_policycoreutils-python-utils_installed

  - name: Ensure policycoreutils is installed
    ansible.builtin.package:
      name: policycoreutils
      state: present
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-000200
    - enable_strategy
    - low_complexity
    - low_disruption
    - low_severity
    - no_reboot_needed
    - package_policycoreutils_installed

  - name: Ensure cronie is installed
    ansible.builtin.package:
      name: cronie
      state: present
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-002580
    - NIST-800-53-CM-6(a)
    - PCI-DSSv4-2.2
    - PCI-DSSv4-2.2.6
    - enable_strategy
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - package_cron_installed

  - name: Ensure fapolicyd is installed
    ansible.builtin.package:
      name: fapolicyd
      state: present
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-000340
    - NIST-800-53-CM-6(a)
    - NIST-800-53-SI-4(22)
    - enable_strategy
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - package_fapolicyd_installed

  - name: 'Uninstall vsftpd Package: Ensure vsftpd is removed'
    ansible.builtin.package:
      name: vsftpd
      state: absent
    tags:
    - DISA-STIG-OL09-00-000130
    - NIST-800-53-CM-6(a)
    - NIST-800-53-CM-7
    - NIST-800-53-CM-7(a)
    - NIST-800-53-CM-7(b)
    - NIST-800-53-CM-7.1(ii)
    - NIST-800-53-IA-5(1)(c)
    - NIST-800-53-IA-5(1).1(v)
    - disable_strategy
    - high_severity
    - low_complexity
    - low_disruption
    - no_reboot_needed
    - package_vsftpd_removed

  - name: Ensure s-nail is installed
    ansible.builtin.package:
      name: s-nail
      state: present
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-000290
    - NIST-800-53-CM-3(5)
    - enable_strategy
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - package_s-nail_installed

  - name: 'Uninstall Sendmail Package: Ensure sendmail is removed'
    ansible.builtin.package:
      name: sendmail
      state: absent
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-000150
    - NIST-800-53-CM-6(a)
    - NIST-800-53-CM-7(a)
    - NIST-800-53-CM-7(b)
    - disable_strategy
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - package_sendmail_removed

  - name: 'Uninstall nfs-utils Package: Ensure nfs-utils is removed'
    ansible.builtin.package:
      name: nfs-utils
      state: absent
    tags:
    - DISA-STIG-OL09-00-000100
    - disable_strategy
    - low_complexity
    - low_disruption
    - low_severity
    - no_reboot_needed
    - package_nfs-utils_removed

  - name: Ensure chrony is installed
    ansible.builtin.package:
      name: chrony
      state: present
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-000310
    - PCI-DSS-Req-10.4
    - PCI-DSSv4-10.6
    - PCI-DSSv4-10.6.1
    - enable_strategy
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - package_chrony_installed

  - name: 'Uninstall telnet-server Package: Ensure telnet-server is removed'
    ansible.builtin.package:
      name: telnet-server
      state: absent
    tags:
    - DISA-STIG-OL09-00-000110
    - NIST-800-53-CM-6(a)
    - NIST-800-53-CM-7(a)
    - NIST-800-53-CM-7(b)
    - PCI-DSS-Req-2.2.2
    - PCI-DSSv4-2.2
    - PCI-DSSv4-2.2.4
    - disable_strategy
    - high_severity
    - low_complexity
    - low_disruption
    - no_reboot_needed
    - package_telnet-server_removed

  - name: 'Uninstall tftp-server Package: Ensure tftp-server is removed'
    ansible.builtin.package:
      name: tftp-server
      state: absent
    tags:
    - DISA-STIG-OL09-00-000135
    - NIST-800-53-CM-6(a)
    - NIST-800-53-CM-7(a)
    - NIST-800-53-CM-7(b)
    - PCI-DSSv4-2.2
    - PCI-DSSv4-2.2.4
    - disable_strategy
    - high_severity
    - low_complexity
    - low_disruption
    - no_reboot_needed
    - package_tftp-server_removed

  - name: 'Uninstall quagga Package: Ensure quagga is removed'
    ansible.builtin.package:
      name: quagga
      state: absent
    tags:
    - DISA-STIG-OL09-00-000140
    - NIST-800-53-CM-6(a)
    - NIST-800-53-CM-7(a)
    - NIST-800-53-CM-7(b)
    - disable_strategy
    - low_complexity
    - low_disruption
    - low_severity
    - no_reboot_needed
    - package_quagga_removed

  - name: Ensure openssh-clients is installed
    ansible.builtin.package:
      name: openssh-clients
      state: present
    tags:
    - DISA-STIG-OL09-00-000260
    - enable_strategy
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - package_openssh-clients_installed

  - name: Ensure openssh-server is installed
    ansible.builtin.package:
      name: openssh-server
      state: present
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-000250
    - NIST-800-53-CM-6(a)
    - enable_strategy
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - package_openssh-server_installed

  - name: Ensure sssd is installed
    ansible.builtin.package:
      name: sssd
      state: present
    when: '"sssd-common" in ansible_facts.packages'
    tags:
    - DISA-STIG-OL09-00-000285
    - NIST-800-53-CM-6(a)
    - enable_strategy
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - package_sssd_installed

  - name: Ensure usbguard is installed
    ansible.builtin.package:
      name: usbguard
      state: present
    when: ( ansible_architecture != "s390x" and ("kernel" in ansible_facts.packages
      or "kernel-uek" in ansible_facts.packages) )
    tags:
    - DISA-STIG-OL09-00-000320
    - NIST-800-53-CM-8(3)
    - NIST-800-53-IA-3
    - enable_strategy
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - package_usbguard_installed

  - name: Disable graphical user interface - Ensure xorg-x11-server-Xorg is removed
    ansible.builtin.package:
      name: xorg-x11-server-Xorg
      state: absent
    tags:
    - DISA-STIG-OL09-00-000145
    - NIST-800-53-CM-6(b)
    - low_complexity
    - low_disruption
    - medium_severity
    - reboot_required
    - restrict_strategy
    - xwindows_remove_packages

  - name: Disable graphical user interface - Ensure xorg-x11-server-common is removed
    ansible.builtin.package:
      name: xorg-x11-server-common
      state: absent
    tags:
    - DISA-STIG-OL09-00-000145
    - NIST-800-53-CM-6(b)
    - low_complexity
    - low_disruption
    - medium_severity
    - reboot_required
    - restrict_strategy
    - xwindows_remove_packages

  - name: Disable graphical user interface - Ensure xorg-x11-server-utils is removed
    ansible.builtin.package:
      name: xorg-x11-server-utils
      state: absent
    tags:
    - DISA-STIG-OL09-00-000145
    - NIST-800-53-CM-6(b)
    - low_complexity
    - low_disruption
    - medium_severity
    - reboot_required
    - restrict_strategy
    - xwindows_remove_packages

  - name: Disable graphical user interface - Ensure xorg-x11-server-Xwayland is removed
    ansible.builtin.package:
      name: xorg-x11-server-Xwayland
      state: absent
    tags:
    - DISA-STIG-OL09-00-000145
    - NIST-800-53-CM-6(b)
    - low_complexity
    - low_disruption
    - medium_severity
    - reboot_required
    - restrict_strategy
    - xwindows_remove_packages

  - name: Ensure audispd-plugins is installed
    ansible.builtin.package:
      name: audispd-plugins
      state: present
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-000450
    - PCI-DSSv4-10.3
    - PCI-DSSv4-10.3.3
    - enable_strategy
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - package_audispd-plugins_installed

  - name: Ensure audit is installed
    ansible.builtin.package:
      name: audit
      state: present
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-000440
    - NIST-800-53-AC-7(a)
    - NIST-800-53-AU-12(2)
    - NIST-800-53-AU-14
    - NIST-800-53-AU-2(a)
    - NIST-800-53-AU-7(1)
    - NIST-800-53-AU-7(2)
    - NIST-800-53-CM-6(a)
    - PCI-DSS-Req-10.1
    - PCI-DSSv4-10.2
    - PCI-DSSv4-10.2.1
    - enable_strategy
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - package_audit_installed

  - name: Gather the package facts
    ansible.builtin.package_facts:
      manager: auto
    tags:
    - always

  - name: Disable debug-shell SystemD Service - Disable service debug-shell
    block:

    - name: Disable debug-shell SystemD Service - Collect systemd Services Present
        in the System
      ansible.builtin.command: systemctl -q list-unit-files --type service
      register: service_exists
      changed_when: false
      failed_when: service_exists.rc not in [0, 1]
      check_mode: false

    - name: Disable debug-shell SystemD Service - Ensure debug-shell.service is Masked
      ansible.builtin.systemd:
        name: debug-shell.service
        state: stopped
        enabled: false
        masked: true
      when: service_exists.stdout_lines is search("debug-shell.service", multiline=True)

    - name: Unit Socket Exists - debug-shell.socket
      ansible.builtin.command: systemctl -q list-unit-files debug-shell.socket
      register: socket_file_exists
      changed_when: false
      failed_when: socket_file_exists.rc not in [0, 1]
      check_mode: false

    - name: Disable debug-shell SystemD Service - Disable Socket debug-shell
      ansible.builtin.systemd:
        name: debug-shell.socket
        enabled: false
        state: stopped
        masked: true
      when: socket_file_exists.stdout_lines is search("debug-shell.socket", multiline=True)
    tags:
    - DISA-STIG-OL09-00-002403
    - NIST-800-171-3.4.5
    - NIST-800-53-CM-6
    - disable_strategy
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - service_debug-shell_disabled
    - special_service_block
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)

  - name: Enable the pcscd Service - Enable service pcscd
    block:

    - name: Enable the pcscd Service - Enable Service pcscd
      ansible.builtin.systemd:
        name: pcscd
        enabled: true
        state: started
        masked: false
      when:
      - '"pcsc-lite" in ansible_facts.packages'
    tags:
    - DISA-STIG-OL09-00-000401
    - NIST-800-53-CM-6(a)
    - NIST-800-53-IA-2(1)
    - NIST-800-53-IA-2(11)
    - NIST-800-53-IA-2(2)
    - NIST-800-53-IA-2(3)
    - NIST-800-53-IA-2(4)
    - NIST-800-53-IA-2(6)
    - NIST-800-53-IA-2(7)
    - PCI-DSS-Req-8.3
    - enable_strategy
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - service_pcscd_enabled
    - special_service_block
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)

  - name: Enable rsyslog Service - Enable service rsyslog
    block:

    - name: Enable rsyslog Service - Enable Service rsyslog
      ansible.builtin.systemd:
        name: rsyslog
        enabled: true
        state: started
        masked: false
      when:
      - '"rsyslog" in ansible_facts.packages'
    tags:
    - DISA-STIG-OL09-00-000351
    - NIST-800-53-AU-4(1)
    - NIST-800-53-CM-6(a)
    - enable_strategy
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - service_rsyslog_enabled
    - special_service_block
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)

  - name: Enable systemd-journald Service - Enable service systemd-journald
    block:

    - name: Enable systemd-journald Service - Enable Service systemd-journald
      ansible.builtin.systemd:
        name: systemd-journald
        enabled: true
        state: started
        masked: false
      when:
      - '"systemd" in ansible_facts.packages'
    tags:
    - DISA-STIG-OL09-00-002400
    - NIST-800-53-SC-24
    - enable_strategy
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - service_systemd-journald_enabled
    - special_service_block
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)

  - name: Verify firewalld Enabled - Enable service firewalld
    block:

    - name: Verify firewalld Enabled - Enable Service firewalld
      ansible.builtin.systemd:
        name: firewalld
        enabled: true
        state: started
        masked: false
      when:
      - '"firewalld" in ansible_facts.packages'
    tags:
    - DISA-STIG-OL09-00-000221
    - NIST-800-171-3.1.3
    - NIST-800-171-3.4.7
    - NIST-800-53-AC-4
    - NIST-800-53-CA-3(5)
    - NIST-800-53-CM-6(a)
    - NIST-800-53-CM-7(b)
    - NIST-800-53-SC-7(21)
    - PCI-DSSv4-1.2
    - PCI-DSSv4-1.2.1
    - enable_strategy
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - service_firewalld_enabled
    - special_service_block
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - '"firewalld" in ansible_facts.packages'

  - name: Disable the Automounter - Disable service autofs
    block:

    - name: Disable the Automounter - Collect systemd Services Present in the System
      ansible.builtin.command: systemctl -q list-unit-files --type service
      register: service_exists
      changed_when: false
      failed_when: service_exists.rc not in [0, 1]
      check_mode: false

    - name: Disable the Automounter - Ensure autofs.service is Masked
      ansible.builtin.systemd:
        name: autofs.service
        state: stopped
        enabled: false
        masked: true
      when: service_exists.stdout_lines is search("autofs.service", multiline=True)

    - name: Unit Socket Exists - autofs.socket
      ansible.builtin.command: systemctl -q list-unit-files autofs.socket
      register: socket_file_exists
      changed_when: false
      failed_when: socket_file_exists.rc not in [0, 1]
      check_mode: false

    - name: Disable the Automounter - Disable Socket autofs
      ansible.builtin.systemd:
        name: autofs.socket
        enabled: false
        state: stopped
        masked: true
      when: socket_file_exists.stdout_lines is search("autofs.socket", multiline=True)
    tags:
    - DISA-STIG-OL09-00-002000
    - NIST-800-171-3.4.6
    - NIST-800-53-CM-6(a)
    - NIST-800-53-CM-7(a)
    - NIST-800-53-CM-7(b)
    - NIST-800-53-MP-7
    - disable_strategy
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - service_autofs_disabled
    - special_service_block
    when: ( "autofs" in ansible_facts.packages and ("kernel" in ansible_facts.packages
      or "kernel-uek" in ansible_facts.packages) )

  - name: Disable KDump Kernel Crash Analyzer (kdump) - Disable service kdump
    block:

    - name: Disable KDump Kernel Crash Analyzer (kdump) - Collect systemd Services
        Present in the System
      ansible.builtin.command: systemctl -q list-unit-files --type service
      register: service_exists
      changed_when: false
      failed_when: service_exists.rc not in [0, 1]
      check_mode: false

    - name: Disable KDump Kernel Crash Analyzer (kdump) - Ensure kdump.service is
        Masked
      ansible.builtin.systemd:
        name: kdump.service
        state: stopped
        enabled: false
        masked: true
      when: service_exists.stdout_lines is search("kdump.service", multiline=True)

    - name: Unit Socket Exists - kdump.socket
      ansible.builtin.command: systemctl -q list-unit-files kdump.socket
      register: socket_file_exists
      changed_when: false
      failed_when: socket_file_exists.rc not in [0, 1]
      check_mode: false

    - name: Disable KDump Kernel Crash Analyzer (kdump) - Disable Socket kdump
      ansible.builtin.systemd:
        name: kdump.socket
        enabled: false
        state: stopped
        masked: true
      when: socket_file_exists.stdout_lines is search("kdump.socket", multiline=True)
    tags:
    - DISA-STIG-OL09-00-002385
    - NIST-800-53-CM-6(a)
    - NIST-800-53-CM-7(a)
    - NIST-800-53-CM-7(b)
    - disable_strategy
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - service_kdump_disabled
    - special_service_block
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)

  - name: Enable the File Access Policy Service - Enable service fapolicyd
    block:

    - name: Enable the File Access Policy Service - Enable Service fapolicyd
      ansible.builtin.systemd:
        name: fapolicyd
        enabled: true
        state: started
        masked: false
      when:
      - '"fapolicyd" in ansible_facts.packages'
    tags:
    - DISA-STIG-OL09-00-000341
    - NIST-800-53-CM-6(a)
    - NIST-800-53-SI-4(22)
    - enable_strategy
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - service_fapolicyd_enabled
    - special_service_block
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)

  - name: The Chronyd service is enabled - Enable service chronyd
    block:

    - name: The Chronyd service is enabled - Enable Service chronyd
      ansible.builtin.systemd:
        name: chronyd
        enabled: true
        state: started
        masked: false
      when:
      - '"chrony" in ansible_facts.packages'
    tags:
    - DISA-STIG-OL09-00-000311
    - enable_strategy
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - service_chronyd_enabled
    - special_service_block
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - '"chrony" in ansible_facts.packages'

  - name: Enable the OpenSSH Service - Enable service sshd
    block:

    - name: Enable the OpenSSH Service - Enable Service sshd
      ansible.builtin.systemd:
        name: sshd
        enabled: true
        state: started
        masked: false
      when:
      - '"openssh-server" in ansible_facts.packages'
    tags:
    - DISA-STIG-OL09-00-000251
    - NIST-800-171-3.1.13
    - NIST-800-171-3.13.8
    - NIST-800-171-3.5.4
    - NIST-800-53-CM-6(a)
    - NIST-800-53-SC-8
    - NIST-800-53-SC-8(1)
    - NIST-800-53-SC-8(2)
    - NIST-800-53-SC-8(3)
    - NIST-800-53-SC-8(4)
    - enable_strategy
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - service_sshd_enabled
    - special_service_block
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)

  - name: Enable the SSSD Service - Enable service sssd
    block:

    - name: Enable the SSSD Service - Enable Service sssd
      ansible.builtin.systemd:
        name: sssd
        enabled: true
        state: started
        masked: false
      when:
      - '"sssd-common" in ansible_facts.packages'
    tags:
    - DISA-STIG-OL09-00-000286
    - NIST-800-53-CM-6(a)
    - NIST-800-53-IA-5(10)
    - enable_strategy
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - service_sssd_enabled
    - special_service_block
    when:
    - '"sssd-common" in ansible_facts.packages'
    - ( "sssd-common" in ansible_facts.packages and ("kernel" in ansible_facts.packages
      or "kernel-uek" in ansible_facts.packages) )

  - name: Enable the USBGuard Service - Enable service usbguard
    block:

    - name: Enable the USBGuard Service - Enable Service usbguard
      ansible.builtin.systemd:
        name: usbguard
        enabled: true
        state: started
        masked: false
      when:
      - '"usbguard" in ansible_facts.packages'
    tags:
    - DISA-STIG-OL09-00-000321
    - NIST-800-53-CM-8(3)(a)
    - NIST-800-53-IA-3
    - enable_strategy
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - service_usbguard_enabled
    - special_service_block
    when: ( ansible_architecture != "s390x" and ("kernel" in ansible_facts.packages
      or "kernel-uek" in ansible_facts.packages) )

  - name: Enable auditd Service - Enable service auditd
    block:

    - name: Enable auditd Service - Enable Service auditd
      ansible.builtin.systemd:
        name: auditd
        enabled: true
        state: started
        masked: false
      when:
      - '"audit" in ansible_facts.packages'
    tags:
    - CJIS-5.4.1.1
    - DISA-STIG-OL09-00-000441
    - NIST-800-171-3.3.1
    - NIST-800-171-3.3.2
    - NIST-800-171-3.3.6
    - NIST-800-53-AC-2(g)
    - NIST-800-53-AC-6(9)
    - NIST-800-53-AU-10
    - NIST-800-53-AU-12(c)
    - NIST-800-53-AU-14(1)
    - NIST-800-53-AU-2(d)
    - NIST-800-53-AU-3
    - NIST-800-53-CM-6(a)
    - NIST-800-53-SI-4(23)
    - PCI-DSS-Req-10.1
    - PCI-DSSv4-10.2
    - PCI-DSSv4-10.2.1
    - enable_strategy
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - service_auditd_enabled
    - special_service_block
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - '"audit" in ansible_facts.packages'

  - name: Gather the service facts
    ansible.builtin.service_facts: null
    tags:
    - always

  - name: Verify crypto-policies with RPM - Read files with incorrect hash
    ansible.builtin.command: rpm -V crypto-policies
    register: files_with_incorrect_hash
    changed_when: false
    failed_when: files_with_incorrect_hash.rc > 1
    check_mode: false
    when: not ( "kernel" in ansible_facts.packages and "rpm-ostree" in ansible_facts.packages
      and "bootc" in ansible_facts.packages and not "openshift-kubelet" in ansible_facts.packages
      and "ostree" in ansible_proc_cmdline )
    tags:
    - DISA-STIG-OL09-00-000244
    - high_complexity
    - high_severity
    - medium_disruption
    - no_reboot_needed
    - restrict_strategy
    - rpm_verify_crypto_policies

  - name: Verify crypto-policies with RPM - Reinstall packages of files with incorrect
      hash
    ansible.builtin.command: yum reinstall -y crypto-policies
    when:
    - not ( "kernel" in ansible_facts.packages and "rpm-ostree" in ansible_facts.packages
      and "bootc" in ansible_facts.packages and not "openshift-kubelet" in ansible_facts.packages
      and "ostree" in ansible_proc_cmdline )
    - files_with_incorrect_hash.stdout_lines is defined
    - (files_with_incorrect_hash.stdout_lines | length > 0)
    tags:
    - DISA-STIG-OL09-00-000244
    - high_complexity
    - high_severity
    - medium_disruption
    - no_reboot_needed
    - restrict_strategy
    - rpm_verify_crypto_policies

  - name: 'Set fact: Package manager reinstall command'
    ansible.builtin.set_fact:
      package_manager_reinstall_cmd: yum reinstall -y
    when:
    - not ( "kernel" in ansible_facts.packages and "rpm-ostree" in ansible_facts.packages
      and "bootc" in ansible_facts.packages and not "openshift-kubelet" in ansible_facts.packages
      and "ostree" in ansible_proc_cmdline )
    - ansible_distribution in [ "Fedora", "RedHat", "CentOS", "OracleLinux", "AlmaLinux"
      ]
    tags:
    - CJIS-5.10.4.1
    - DISA-STIG-OL09-00-000243
    - NIST-800-171-3.3.8
    - NIST-800-171-3.4.1
    - NIST-800-53-AU-9(3)
    - NIST-800-53-CM-6(c)
    - NIST-800-53-CM-6(d)
    - NIST-800-53-SI-7
    - NIST-800-53-SI-7(1)
    - NIST-800-53-SI-7(6)
    - PCI-DSS-Req-11.5
    - PCI-DSSv4-11.5.2
    - high_complexity
    - high_severity
    - medium_disruption
    - no_reboot_needed
    - restrict_strategy
    - rpm_verify_hashes

  - name: 'Set fact: Package manager reinstall command (zypper)'
    ansible.builtin.set_fact:
      package_manager_reinstall_cmd: zypper in -f -y
    when:
    - not ( "kernel" in ansible_facts.packages and "rpm-ostree" in ansible_facts.packages
      and "bootc" in ansible_facts.packages and not "openshift-kubelet" in ansible_facts.packages
      and "ostree" in ansible_proc_cmdline )
    - ansible_distribution == "SLES"
    tags:
    - CJIS-5.10.4.1
    - DISA-STIG-OL09-00-000243
    - NIST-800-171-3.3.8
    - NIST-800-171-3.4.1
    - NIST-800-53-AU-9(3)
    - NIST-800-53-CM-6(c)
    - NIST-800-53-CM-6(d)
    - NIST-800-53-SI-7
    - NIST-800-53-SI-7(1)
    - NIST-800-53-SI-7(6)
    - PCI-DSS-Req-11.5
    - PCI-DSSv4-11.5.2
    - high_complexity
    - high_severity
    - medium_disruption
    - no_reboot_needed
    - restrict_strategy
    - rpm_verify_hashes

  - name: Read files with incorrect hash
    ansible.builtin.command: rpm -Va --nodeps --nosize --nomtime --nordev --nocaps
      --nolinkto --nouser --nogroup --nomode --noghost --noconfig
    register: files_with_incorrect_hash
    changed_when: false
    failed_when: files_with_incorrect_hash.rc > 1
    check_mode: false
    when:
    - not ( "kernel" in ansible_facts.packages and "rpm-ostree" in ansible_facts.packages
      and "bootc" in ansible_facts.packages and not "openshift-kubelet" in ansible_facts.packages
      and "ostree" in ansible_proc_cmdline )
    - (package_manager_reinstall_cmd is defined)
    tags:
    - CJIS-5.10.4.1
    - DISA-STIG-OL09-00-000243
    - NIST-800-171-3.3.8
    - NIST-800-171-3.4.1
    - NIST-800-53-AU-9(3)
    - NIST-800-53-CM-6(c)
    - NIST-800-53-CM-6(d)
    - NIST-800-53-SI-7
    - NIST-800-53-SI-7(1)
    - NIST-800-53-SI-7(6)
    - PCI-DSS-Req-11.5
    - PCI-DSSv4-11.5.2
    - high_complexity
    - high_severity
    - medium_disruption
    - no_reboot_needed
    - restrict_strategy
    - rpm_verify_hashes

  - name: Create list of packages
    ansible.builtin.command: rpm -qf "{{ item }}"
    with_items: '{{ files_with_incorrect_hash.stdout_lines | map(''regex_findall'',
      ''^[.]+[5]+.* (\/.*)'', ''\1'') | map(''join'') | select(''match'', ''(\/.*)'')
      | list | unique }}'
    register: list_of_packages
    changed_when: false
    check_mode: false
    when:
    - not ( "kernel" in ansible_facts.packages and "rpm-ostree" in ansible_facts.packages
      and "bootc" in ansible_facts.packages and not "openshift-kubelet" in ansible_facts.packages
      and "ostree" in ansible_proc_cmdline )
    - files_with_incorrect_hash.stdout_lines is defined
    - (files_with_incorrect_hash.stdout_lines | length > 0)
    tags:
    - CJIS-5.10.4.1
    - DISA-STIG-OL09-00-000243
    - NIST-800-171-3.3.8
    - NIST-800-171-3.4.1
    - NIST-800-53-AU-9(3)
    - NIST-800-53-CM-6(c)
    - NIST-800-53-CM-6(d)
    - NIST-800-53-SI-7
    - NIST-800-53-SI-7(1)
    - NIST-800-53-SI-7(6)
    - PCI-DSS-Req-11.5
    - PCI-DSSv4-11.5.2
    - high_complexity
    - high_severity
    - medium_disruption
    - no_reboot_needed
    - restrict_strategy
    - rpm_verify_hashes

  - name: Reinstall packages of files with incorrect hash
    ansible.builtin.command: '{{ package_manager_reinstall_cmd }} ''{{ item }}'''
    with_items: '{{ list_of_packages.results | map(attribute=''stdout_lines'') | list
      | unique }}'
    when:
    - not ( "kernel" in ansible_facts.packages and "rpm-ostree" in ansible_facts.packages
      and "bootc" in ansible_facts.packages and not "openshift-kubelet" in ansible_facts.packages
      and "ostree" in ansible_proc_cmdline )
    - files_with_incorrect_hash.stdout_lines is defined
    - (package_manager_reinstall_cmd is defined and (files_with_incorrect_hash.stdout_lines
      | length > 0))
    tags:
    - CJIS-5.10.4.1
    - DISA-STIG-OL09-00-000243
    - NIST-800-171-3.3.8
    - NIST-800-171-3.4.1
    - NIST-800-53-AU-9(3)
    - NIST-800-53-CM-6(c)
    - NIST-800-53-CM-6(d)
    - NIST-800-53-SI-7
    - NIST-800-53-SI-7(1)
    - NIST-800-53-SI-7(6)
    - PCI-DSS-Req-11.5
    - PCI-DSSv4-11.5.2
    - high_complexity
    - high_severity
    - medium_disruption
    - no_reboot_needed
    - restrict_strategy
    - rpm_verify_hashes

  - name: Build and Test AIDE Database - Check Whether the Stock AIDE Database Exists
    ansible.builtin.stat:
      path: /var/lib/aide/aide.db.new.gz
    register: aide_database_stat
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - CJIS-5.10.1.3
    - DISA-STIG-OL09-00-000300
    - NIST-800-53-CM-6(a)
    - PCI-DSS-Req-11.5
    - PCI-DSSv4-11.5.2
    - aide_build_database
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Build and Test AIDE Database - Build and Test AIDE Database
    ansible.builtin.command: /usr/sbin/aide --init
    changed_when: true
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - not (aide_database_stat.stat.exists is defined and aide_database_stat.stat.exists)
    register: aide_database_init
    tags:
    - CJIS-5.10.1.3
    - DISA-STIG-OL09-00-000300
    - NIST-800-53-CM-6(a)
    - PCI-DSS-Req-11.5
    - PCI-DSSv4-11.5.2
    - aide_build_database
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Build and Test AIDE Database - Stage AIDE Database
    ansible.builtin.copy:
      src: /var/lib/aide/aide.db.new.gz
      dest: /var/lib/aide/aide.db.gz
      backup: true
      remote_src: true
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - aide_database_init is changed
    - not ansible_check_mode
    tags:
    - CJIS-5.10.1.3
    - DISA-STIG-OL09-00-000300
    - NIST-800-53-CM-6(a)
    - PCI-DSS-Req-11.5
    - PCI-DSSv4-11.5.2
    - aide_build_database
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Set "Configure AIDE to Verify the Audit Tools - audit_tools fact"
    ansible.builtin.set_fact:
      audit_tools:
      - /usr/sbin/auditctl
      - /usr/sbin/auditd
      - /usr/sbin/augenrules
      - /usr/sbin/aureport
      - /usr/sbin/ausearch
      - /usr/sbin/autrace
      - /usr/sbin/rsyslogd
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-000710
    - NIST-800-53-AU-9(3)
    - NIST-800-53-AU-9(3).1
    - aide_check_audit_tools
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Configure AIDE to Verify the Audit Tools - Ensure Existing AIDE Configuration
      for Audit Tools are Correct
    ansible.builtin.lineinfile:
      path: /etc/aide.conf
      regexp: ^{{ item }}\s
      line: '{{ item }} p+i+n+u+g+s+b+acl+xattrs+sha512'
      create: true
    with_items: '{{ audit_tools }}'
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - '"aide" in ansible_facts.packages'
    tags:
    - DISA-STIG-OL09-00-000710
    - NIST-800-53-AU-9(3)
    - NIST-800-53-AU-9(3).1
    - aide_check_audit_tools
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Configure AIDE to Verify the Audit Tools - Configure AIDE to Properly Protect
      Audit Tools
    ansible.builtin.lineinfile:
      path: /etc/aide.conf
      line: '{{ item }} p+i+n+u+g+s+b+acl+xattrs+sha512'
      create: true
    with_items: '{{ audit_tools }}'
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - '"aide" in ansible_facts.packages'
    tags:
    - DISA-STIG-OL09-00-000710
    - NIST-800-53-AU-9(3)
    - NIST-800-53-AU-9(3).1
    - aide_check_audit_tools
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Configure Notification of Post-AIDE Scan Details - Setup Cron Tab
    ansible.builtin.cron:
      name: run AIDE check
      minute: 5
      hour: 4
      weekday: 0
      user: root
      job: /usr/sbin/aide  --check | /bin/mail -s "$(hostname) - AIDE Integrity Check"
        {{ var_aide_scan_notification_email }}
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-000301
    - NIST-800-53-CM-3(5)
    - NIST-800-53-CM-6(a)
    - aide_scan_notification
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Configure AIDE to Use FIPS 140-2 for Validating Hashes - Set-fact aide config
      file and forbidden hashes
    ansible.builtin.set_fact:
      aide_conf: /etc/aide.conf
      forbidden_hashes:
      - sha1
      - rmd160
      - sha256
      - whirlpool
      - tiger
      - haval
      - gost
      - crc32
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-000302
    - NIST-800-171-3.13.11
    - NIST-800-53-CM-6(a)
    - NIST-800-53-SI-7
    - NIST-800-53-SI-7(1)
    - aide_use_fips_hashes
    - enable_strategy
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

  - name: Configure AIDE to Use FIPS 140-2 for Validating Hashes - Remove forbidden
      hashes
    ansible.builtin.replace:
      path: '{{ aide_conf }}'
      regexp: (^\s*[A-Z][A-Za-z_]*\s*=.*?)({{ item }}\+|\+?{{ item }})(.*)
      replace: \1\3
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - '"aide" in ansible_facts.packages'
    loop: '{{ forbidden_hashes }}'
    tags:
    - DISA-STIG-OL09-00-000302
    - NIST-800-171-3.13.11
    - NIST-800-53-CM-6(a)
    - NIST-800-53-SI-7
    - NIST-800-53-SI-7(1)
    - aide_use_fips_hashes
    - enable_strategy
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

  - name: Configure AIDE to Use FIPS 140-2 for Validating Hashes - Set sha512
    ansible.builtin.replace:
      path: '{{ aide_conf }}'
      regexp: (^\s*[A-Z][A-Za-z_]*\s*=)((?:(?!\+?sha512).)*)\s*$
      replace: \1\2+sha512
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - '"aide" in ansible_facts.packages'
    tags:
    - DISA-STIG-OL09-00-000302
    - NIST-800-171-3.13.11
    - NIST-800-53-CM-6(a)
    - NIST-800-53-SI-7
    - NIST-800-53-SI-7(1)
    - aide_use_fips_hashes
    - enable_strategy
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

  - name: Get rules groups
    ansible.builtin.shell: |
      set -o pipefail
      LC_ALL=C grep "^[A-Z][A-Za-z_]*" /etc/aide.conf | grep -v "^ALLXTRAHASHES" | cut -f1 -d '=' | tr -d ' ' | sort -u || true
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - '''aide'' in ansible_facts.packages'
    register: find_rules_groups_results
    changed_when: false
    check_mode: false
    tags:
    - DISA-STIG-OL09-00-000303
    - NIST-800-53-CM-6(a)
    - NIST-800-53-SI-7
    - NIST-800-53-SI-7(1)
    - aide_verify_acls
    - low_complexity
    - low_disruption
    - low_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Ensure the acl rule is present when aide is installed.
    ansible.builtin.replace:
      path: /etc/aide.conf
      regexp: (^\s*{{ item }}\s*=\s*)(?!.*acl)([^\s]*)
      replace: \g<1>\g<2>+acl
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - find_rules_groups_results is not skipped and "'aide' in ansible_facts.packages"
    with_items: '{{ find_rules_groups_results.stdout_lines | map(''trim'') | list
      }}'
    tags:
    - DISA-STIG-OL09-00-000303
    - NIST-800-53-CM-6(a)
    - NIST-800-53-SI-7
    - NIST-800-53-SI-7(1)
    - aide_verify_acls
    - low_complexity
    - low_disruption
    - low_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Get rules groups
    ansible.builtin.shell: |
      set -o pipefail
      LC_ALL=C grep "^[A-Z][A-Za-z_]*" /etc/aide.conf | grep -v "^ALLXTRAHASHES" | cut -f1 -d '=' | tr -d ' ' | sort -u || true
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - '''aide'' in ansible_facts.packages'
    register: find_rules_groups_results
    changed_when: false
    check_mode: false
    tags:
    - DISA-STIG-OL09-00-000304
    - NIST-800-53-CM-6(a)
    - NIST-800-53-SI-7
    - NIST-800-53-SI-7(1)
    - aide_verify_ext_attributes
    - low_complexity
    - low_disruption
    - low_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Ensure the xattrs rule is present when aide is installed.
    ansible.builtin.replace:
      path: /etc/aide.conf
      regexp: (^\s*{{ item }}\s*=\s*)(?!.*xattrs)([^\s]*)
      replace: \g<1>\g<2>+xattrs
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - find_rules_groups_results is not skipped and "'aide' in ansible_facts.packages"
    with_items: '{{ find_rules_groups_results.stdout_lines | map(''trim'') | list
      }}'
    tags:
    - DISA-STIG-OL09-00-000304
    - NIST-800-53-CM-6(a)
    - NIST-800-53-SI-7
    - NIST-800-53-SI-7(1)
    - aide_verify_ext_attributes
    - low_complexity
    - low_disruption
    - low_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Set the file_audit_tools_group_ownership_newgroup variable if represented
      by gid
    ansible.builtin.set_fact:
      file_audit_tools_group_ownership_newgroup: '0'
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-002570
    - NIST-800-53-AU-9
    - configure_strategy
    - file_audit_tools_group_ownership
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

  - name: Test for existence /sbin/auditctl
    ansible.builtin.stat:
      path: /sbin/auditctl
    register: file_exists
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-002570
    - NIST-800-53-AU-9
    - configure_strategy
    - file_audit_tools_group_ownership
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

  - name: Ensure group owner on /sbin/auditctl
    ansible.builtin.file:
      path: /sbin/auditctl
      follow: false
      group: '{{ file_audit_tools_group_ownership_newgroup }}'
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - file_exists.stat is defined and file_exists.stat.exists
    tags:
    - DISA-STIG-OL09-00-002570
    - NIST-800-53-AU-9
    - configure_strategy
    - file_audit_tools_group_ownership
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

  - name: Test for existence /sbin/aureport
    ansible.builtin.stat:
      path: /sbin/aureport
    register: file_exists
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-002570
    - NIST-800-53-AU-9
    - configure_strategy
    - file_audit_tools_group_ownership
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

  - name: Ensure group owner on /sbin/aureport
    ansible.builtin.file:
      path: /sbin/aureport
      follow: false
      group: '{{ file_audit_tools_group_ownership_newgroup }}'
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - file_exists.stat is defined and file_exists.stat.exists
    tags:
    - DISA-STIG-OL09-00-002570
    - NIST-800-53-AU-9
    - configure_strategy
    - file_audit_tools_group_ownership
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

  - name: Test for existence /sbin/ausearch
    ansible.builtin.stat:
      path: /sbin/ausearch
    register: file_exists
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-002570
    - NIST-800-53-AU-9
    - configure_strategy
    - file_audit_tools_group_ownership
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

  - name: Ensure group owner on /sbin/ausearch
    ansible.builtin.file:
      path: /sbin/ausearch
      follow: false
      group: '{{ file_audit_tools_group_ownership_newgroup }}'
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - file_exists.stat is defined and file_exists.stat.exists
    tags:
    - DISA-STIG-OL09-00-002570
    - NIST-800-53-AU-9
    - configure_strategy
    - file_audit_tools_group_ownership
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

  - name: Test for existence /sbin/autrace
    ansible.builtin.stat:
      path: /sbin/autrace
    register: file_exists
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-002570
    - NIST-800-53-AU-9
    - configure_strategy
    - file_audit_tools_group_ownership
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

  - name: Ensure group owner on /sbin/autrace
    ansible.builtin.file:
      path: /sbin/autrace
      follow: false
      group: '{{ file_audit_tools_group_ownership_newgroup }}'
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - file_exists.stat is defined and file_exists.stat.exists
    tags:
    - DISA-STIG-OL09-00-002570
    - NIST-800-53-AU-9
    - configure_strategy
    - file_audit_tools_group_ownership
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

  - name: Test for existence /sbin/auditd
    ansible.builtin.stat:
      path: /sbin/auditd
    register: file_exists
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-002570
    - NIST-800-53-AU-9
    - configure_strategy
    - file_audit_tools_group_ownership
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

  - name: Ensure group owner on /sbin/auditd
    ansible.builtin.file:
      path: /sbin/auditd
      follow: false
      group: '{{ file_audit_tools_group_ownership_newgroup }}'
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - file_exists.stat is defined and file_exists.stat.exists
    tags:
    - DISA-STIG-OL09-00-002570
    - NIST-800-53-AU-9
    - configure_strategy
    - file_audit_tools_group_ownership
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

  - name: Test for existence /sbin/rsyslogd
    ansible.builtin.stat:
      path: /sbin/rsyslogd
    register: file_exists
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-002570
    - NIST-800-53-AU-9
    - configure_strategy
    - file_audit_tools_group_ownership
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

  - name: Ensure group owner on /sbin/rsyslogd
    ansible.builtin.file:
      path: /sbin/rsyslogd
      follow: false
      group: '{{ file_audit_tools_group_ownership_newgroup }}'
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - file_exists.stat is defined and file_exists.stat.exists
    tags:
    - DISA-STIG-OL09-00-002570
    - NIST-800-53-AU-9
    - configure_strategy
    - file_audit_tools_group_ownership
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

  - name: Test for existence /sbin/augenrules
    ansible.builtin.stat:
      path: /sbin/augenrules
    register: file_exists
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-002570
    - NIST-800-53-AU-9
    - configure_strategy
    - file_audit_tools_group_ownership
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

  - name: Ensure group owner on /sbin/augenrules
    ansible.builtin.file:
      path: /sbin/augenrules
      follow: false
      group: '{{ file_audit_tools_group_ownership_newgroup }}'
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - file_exists.stat is defined and file_exists.stat.exists
    tags:
    - DISA-STIG-OL09-00-002570
    - NIST-800-53-AU-9
    - configure_strategy
    - file_audit_tools_group_ownership
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

  - name: Set the file_audit_tools_ownership_newown variable if represented by uid
    ansible.builtin.set_fact:
      file_audit_tools_ownership_newown: '0'
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-002571
    - NIST-800-53-AU-9
    - configure_strategy
    - file_audit_tools_ownership
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

  - name: Test for existence /sbin/auditctl
    ansible.builtin.stat:
      path: /sbin/auditctl
    register: file_exists
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-002571
    - NIST-800-53-AU-9
    - configure_strategy
    - file_audit_tools_ownership
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

  - name: Ensure owner on /sbin/auditctl
    ansible.builtin.file:
      path: /sbin/auditctl
      follow: false
      owner: '{{ file_audit_tools_ownership_newown }}'
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - file_exists.stat is defined and file_exists.stat.exists
    tags:
    - DISA-STIG-OL09-00-002571
    - NIST-800-53-AU-9
    - configure_strategy
    - file_audit_tools_ownership
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

  - name: Test for existence /sbin/aureport
    ansible.builtin.stat:
      path: /sbin/aureport
    register: file_exists
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-002571
    - NIST-800-53-AU-9
    - configure_strategy
    - file_audit_tools_ownership
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

  - name: Ensure owner on /sbin/aureport
    ansible.builtin.file:
      path: /sbin/aureport
      follow: false
      owner: '{{ file_audit_tools_ownership_newown }}'
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - file_exists.stat is defined and file_exists.stat.exists
    tags:
    - DISA-STIG-OL09-00-002571
    - NIST-800-53-AU-9
    - configure_strategy
    - file_audit_tools_ownership
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

  - name: Test for existence /sbin/ausearch
    ansible.builtin.stat:
      path: /sbin/ausearch
    register: file_exists
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-002571
    - NIST-800-53-AU-9
    - configure_strategy
    - file_audit_tools_ownership
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

  - name: Ensure owner on /sbin/ausearch
    ansible.builtin.file:
      path: /sbin/ausearch
      follow: false
      owner: '{{ file_audit_tools_ownership_newown }}'
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - file_exists.stat is defined and file_exists.stat.exists
    tags:
    - DISA-STIG-OL09-00-002571
    - NIST-800-53-AU-9
    - configure_strategy
    - file_audit_tools_ownership
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

  - name: Test for existence /sbin/autrace
    ansible.builtin.stat:
      path: /sbin/autrace
    register: file_exists
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-002571
    - NIST-800-53-AU-9
    - configure_strategy
    - file_audit_tools_ownership
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

  - name: Ensure owner on /sbin/autrace
    ansible.builtin.file:
      path: /sbin/autrace
      follow: false
      owner: '{{ file_audit_tools_ownership_newown }}'
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - file_exists.stat is defined and file_exists.stat.exists
    tags:
    - DISA-STIG-OL09-00-002571
    - NIST-800-53-AU-9
    - configure_strategy
    - file_audit_tools_ownership
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

  - name: Test for existence /sbin/auditd
    ansible.builtin.stat:
      path: /sbin/auditd
    register: file_exists
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-002571
    - NIST-800-53-AU-9
    - configure_strategy
    - file_audit_tools_ownership
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

  - name: Ensure owner on /sbin/auditd
    ansible.builtin.file:
      path: /sbin/auditd
      follow: false
      owner: '{{ file_audit_tools_ownership_newown }}'
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - file_exists.stat is defined and file_exists.stat.exists
    tags:
    - DISA-STIG-OL09-00-002571
    - NIST-800-53-AU-9
    - configure_strategy
    - file_audit_tools_ownership
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

  - name: Test for existence /sbin/rsyslogd
    ansible.builtin.stat:
      path: /sbin/rsyslogd
    register: file_exists
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-002571
    - NIST-800-53-AU-9
    - configure_strategy
    - file_audit_tools_ownership
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

  - name: Ensure owner on /sbin/rsyslogd
    ansible.builtin.file:
      path: /sbin/rsyslogd
      follow: false
      owner: '{{ file_audit_tools_ownership_newown }}'
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - file_exists.stat is defined and file_exists.stat.exists
    tags:
    - DISA-STIG-OL09-00-002571
    - NIST-800-53-AU-9
    - configure_strategy
    - file_audit_tools_ownership
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

  - name: Test for existence /sbin/augenrules
    ansible.builtin.stat:
      path: /sbin/augenrules
    register: file_exists
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-002571
    - NIST-800-53-AU-9
    - configure_strategy
    - file_audit_tools_ownership
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

  - name: Ensure owner on /sbin/augenrules
    ansible.builtin.file:
      path: /sbin/augenrules
      follow: false
      owner: '{{ file_audit_tools_ownership_newown }}'
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - file_exists.stat is defined and file_exists.stat.exists
    tags:
    - DISA-STIG-OL09-00-002571
    - NIST-800-53-AU-9
    - configure_strategy
    - file_audit_tools_ownership
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

  - name: Test for existence /sbin/auditctl
    ansible.builtin.stat:
      path: /sbin/auditctl
    register: file_exists
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-002572
    - NIST-800-53-AU-9
    - configure_strategy
    - file_audit_tools_permissions
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

  - name: Ensure permission u-s,g-ws,o-wt on /sbin/auditctl
    ansible.builtin.file:
      path: /sbin/auditctl
      mode: u-s,g-ws,o-wt
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - file_exists.stat is defined and file_exists.stat.exists
    tags:
    - DISA-STIG-OL09-00-002572
    - NIST-800-53-AU-9
    - configure_strategy
    - file_audit_tools_permissions
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

  - name: Test for existence /sbin/aureport
    ansible.builtin.stat:
      path: /sbin/aureport
    register: file_exists
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-002572
    - NIST-800-53-AU-9
    - configure_strategy
    - file_audit_tools_permissions
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

  - name: Ensure permission u-s,g-ws,o-wt on /sbin/aureport
    ansible.builtin.file:
      path: /sbin/aureport
      mode: u-s,g-ws,o-wt
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - file_exists.stat is defined and file_exists.stat.exists
    tags:
    - DISA-STIG-OL09-00-002572
    - NIST-800-53-AU-9
    - configure_strategy
    - file_audit_tools_permissions
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

  - name: Test for existence /sbin/ausearch
    ansible.builtin.stat:
      path: /sbin/ausearch
    register: file_exists
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-002572
    - NIST-800-53-AU-9
    - configure_strategy
    - file_audit_tools_permissions
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

  - name: Ensure permission u-s,g-ws,o-wt on /sbin/ausearch
    ansible.builtin.file:
      path: /sbin/ausearch
      mode: u-s,g-ws,o-wt
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - file_exists.stat is defined and file_exists.stat.exists
    tags:
    - DISA-STIG-OL09-00-002572
    - NIST-800-53-AU-9
    - configure_strategy
    - file_audit_tools_permissions
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

  - name: Test for existence /sbin/autrace
    ansible.builtin.stat:
      path: /sbin/autrace
    register: file_exists
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-002572
    - NIST-800-53-AU-9
    - configure_strategy
    - file_audit_tools_permissions
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

  - name: Ensure permission u-s,g-ws,o-wt on /sbin/autrace
    ansible.builtin.file:
      path: /sbin/autrace
      mode: u-s,g-ws,o-wt
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - file_exists.stat is defined and file_exists.stat.exists
    tags:
    - DISA-STIG-OL09-00-002572
    - NIST-800-53-AU-9
    - configure_strategy
    - file_audit_tools_permissions
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

  - name: Test for existence /sbin/auditd
    ansible.builtin.stat:
      path: /sbin/auditd
    register: file_exists
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-002572
    - NIST-800-53-AU-9
    - configure_strategy
    - file_audit_tools_permissions
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

  - name: Ensure permission u-s,g-ws,o-wt on /sbin/auditd
    ansible.builtin.file:
      path: /sbin/auditd
      mode: u-s,g-ws,o-wt
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - file_exists.stat is defined and file_exists.stat.exists
    tags:
    - DISA-STIG-OL09-00-002572
    - NIST-800-53-AU-9
    - configure_strategy
    - file_audit_tools_permissions
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

  - name: Test for existence /sbin/rsyslogd
    ansible.builtin.stat:
      path: /sbin/rsyslogd
    register: file_exists
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-002572
    - NIST-800-53-AU-9
    - configure_strategy
    - file_audit_tools_permissions
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

  - name: Ensure permission u-s,g-ws,o-wt on /sbin/rsyslogd
    ansible.builtin.file:
      path: /sbin/rsyslogd
      mode: u-s,g-ws,o-wt
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - file_exists.stat is defined and file_exists.stat.exists
    tags:
    - DISA-STIG-OL09-00-002572
    - NIST-800-53-AU-9
    - configure_strategy
    - file_audit_tools_permissions
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

  - name: Test for existence /sbin/augenrules
    ansible.builtin.stat:
      path: /sbin/augenrules
    register: file_exists
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-002572
    - NIST-800-53-AU-9
    - configure_strategy
    - file_audit_tools_permissions
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

  - name: Ensure permission u-s,g-ws,o-wt on /sbin/augenrules
    ansible.builtin.file:
      path: /sbin/augenrules
      mode: u-s,g-ws,o-wt
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - file_exists.stat is defined and file_exists.stat.exists
    tags:
    - DISA-STIG-OL09-00-002572
    - NIST-800-53-AU-9
    - configure_strategy
    - file_audit_tools_permissions
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

  - name: Check to see the current status of FIPS mode
    ansible.builtin.command: /usr/bin/fips-mode-setup --check
    register: is_fips_enabled
    changed_when: false
    failed_when: false
    when: ( not ( "kernel" in ansible_facts.packages and "rpm-ostree" in ansible_facts.packages
      and "bootc" in ansible_facts.packages and not "openshift-kubelet" in ansible_facts.packages
      and "ostree" in ansible_proc_cmdline ) and not ( lookup("env", "container")
      == "bwrap-osbuild" ) and ("kernel" in ansible_facts.packages or "kernel-uek"
      in ansible_facts.packages) )
    tags:
    - DISA-STIG-OL09-00-000070
    - NIST-800-53-CM-6(a)
    - NIST-800-53-IA-7
    - NIST-800-53-SC-12
    - NIST-800-53-SC-12(2)
    - NIST-800-53-SC-12(3)
    - NIST-800-53-SC-13
    - enable_dracut_fips_module
    - high_severity
    - medium_complexity
    - medium_disruption
    - reboot_required
    - restrict_strategy

  - name: Enable FIPS mode
    ansible.builtin.command: /usr/bin/fips-mode-setup --enable
    when:
    - ( not ( "kernel" in ansible_facts.packages and "rpm-ostree" in ansible_facts.packages
      and "bootc" in ansible_facts.packages and not "openshift-kubelet" in ansible_facts.packages
      and "ostree" in ansible_proc_cmdline ) and not ( lookup("env", "container")
      == "bwrap-osbuild" ) and ("kernel" in ansible_facts.packages or "kernel-uek"
      in ansible_facts.packages) )
    - is_fips_enabled.stdout.find('FIPS mode is enabled.') == -1
    tags:
    - DISA-STIG-OL09-00-000070
    - NIST-800-53-CM-6(a)
    - NIST-800-53-IA-7
    - NIST-800-53-SC-12
    - NIST-800-53-SC-12(2)
    - NIST-800-53-SC-12(3)
    - NIST-800-53-SC-13
    - enable_dracut_fips_module
    - high_severity
    - medium_complexity
    - medium_disruption
    - reboot_required
    - restrict_strategy

  - name: Enable Dracut FIPS Module
    ansible.builtin.lineinfile:
      path: /etc/dracut.conf.d/40-fips.conf
      line: add_dracutmodules+=" fips "
    when: ( not ( "kernel" in ansible_facts.packages and "rpm-ostree" in ansible_facts.packages
      and "bootc" in ansible_facts.packages and not "openshift-kubelet" in ansible_facts.packages
      and "ostree" in ansible_proc_cmdline ) and not ( lookup("env", "container")
      == "bwrap-osbuild" ) and ("kernel" in ansible_facts.packages or "kernel-uek"
      in ansible_facts.packages) )
    tags:
    - DISA-STIG-OL09-00-000070
    - NIST-800-53-CM-6(a)
    - NIST-800-53-IA-7
    - NIST-800-53-SC-12
    - NIST-800-53-SC-12(2)
    - NIST-800-53-SC-12(3)
    - NIST-800-53-SC-13
    - enable_dracut_fips_module
    - high_severity
    - medium_complexity
    - medium_disruption
    - reboot_required
    - restrict_strategy

  - name: Configure BIND to use System Crypto Policy - Check BIND configuration file
      exists
    ansible.builtin.stat:
      path: /etc/named.conf
    register: bind_config_file
    when: '"bind" in ansible_facts.packages'
    tags:
    - DISA-STIG-OL09-00-002421
    - NIST-800-53-SC-12(2)
    - NIST-800-53-SC-12(3)
    - NIST-800-53-SC-13
    - configure_bind_crypto_policy
    - configure_strategy
    - high_severity
    - low_complexity
    - low_disruption
    - no_reboot_needed

  - name: Configure BIND to use System Crypto Policy - Aborting remediation, file
      not found
    ansible.builtin.debug:
      msg: Aborting remediation as '/etc/named.conf' was not found.
    when:
    - '"bind" in ansible_facts.packages'
    - not bind_config_file.stat.exists
    tags:
    - DISA-STIG-OL09-00-002421
    - NIST-800-53-SC-12(2)
    - NIST-800-53-SC-12(3)
    - NIST-800-53-SC-13
    - configure_bind_crypto_policy
    - configure_strategy
    - high_severity
    - low_complexity
    - low_disruption
    - no_reboot_needed

  - name: Configure BIND to use System Crypto Policy - Insert crypto-policy into BIND
      config
    ansible.builtin.lineinfile:
      path: /etc/named.conf
      insertafter: ^\s*options\s*{
      line: ' include "/etc/crypto-policies/back-ends/bind.config";'
      state: present
    when:
    - '"bind" in ansible_facts.packages'
    - bind_config_file.stat.exists
    tags:
    - DISA-STIG-OL09-00-002421
    - NIST-800-53-SC-12(2)
    - NIST-800-53-SC-12(3)
    - NIST-800-53-SC-13
    - configure_bind_crypto_policy
    - configure_strategy
    - high_severity
    - low_complexity
    - low_disruption
    - no_reboot_needed

  - name: Configure System Cryptography Policy - Check current crypto policy (runtime)
    ansible.builtin.command: /usr/bin/update-crypto-policies --show
    register: current_crypto_policy
    changed_when: false
    failed_when: false
    check_mode: false
    tags:
    - DISA-STIG-OL09-00-000070
    - DISA-STIG-OL09-00-000241
    - NIST-800-53-AC-17(2)
    - NIST-800-53-AC-17(a)
    - NIST-800-53-CM-6(a)
    - NIST-800-53-MA-4(6)
    - NIST-800-53-SC-12(2)
    - NIST-800-53-SC-12(3)
    - NIST-800-53-SC-13
    - PCI-DSSv4-2.2
    - PCI-DSSv4-2.2.7
    - configure_crypto_policy
    - high_severity
    - low_complexity
    - low_disruption
    - no_reboot_needed
    - restrict_strategy

  - name: Configure System Cryptography Policy - Get mtime of /etc/crypto-policies/config
    ansible.builtin.stat:
      path: /etc/crypto-policies/config
    register: config_file_stat
    changed_when: false
    failed_when: false
    check_mode: false
    tags:
    - DISA-STIG-OL09-00-000070
    - DISA-STIG-OL09-00-000241
    - NIST-800-53-AC-17(2)
    - NIST-800-53-AC-17(a)
    - NIST-800-53-CM-6(a)
    - NIST-800-53-MA-4(6)
    - NIST-800-53-SC-12(2)
    - NIST-800-53-SC-12(3)
    - NIST-800-53-SC-13
    - PCI-DSSv4-2.2
    - PCI-DSSv4-2.2.7
    - configure_crypto_policy
    - high_severity
    - low_complexity
    - low_disruption
    - no_reboot_needed
    - restrict_strategy

  - name: Configure System Cryptography Policy - Get mtime of /etc/crypto-policies/state/current
    ansible.builtin.stat:
      path: /etc/crypto-policies/state/current
    register: current_file_stat
    changed_when: false
    failed_when: false
    check_mode: false
    tags:
    - DISA-STIG-OL09-00-000070
    - DISA-STIG-OL09-00-000241
    - NIST-800-53-AC-17(2)
    - NIST-800-53-AC-17(a)
    - NIST-800-53-CM-6(a)
    - NIST-800-53-MA-4(6)
    - NIST-800-53-SC-12(2)
    - NIST-800-53-SC-12(3)
    - NIST-800-53-SC-13
    - PCI-DSSv4-2.2
    - PCI-DSSv4-2.2.7
    - configure_crypto_policy
    - high_severity
    - low_complexity
    - low_disruption
    - no_reboot_needed
    - restrict_strategy

  - name: Configure System Cryptography Policy - Check existence of /etc/crypto-policies/back-ends/nss.config
    ansible.builtin.stat:
      path: /etc/crypto-policies/back-ends/nss.config
    register: nss_config_stat
    changed_when: false
    failed_when: false
    check_mode: false
    tags:
    - DISA-STIG-OL09-00-000070
    - DISA-STIG-OL09-00-000241
    - NIST-800-53-AC-17(2)
    - NIST-800-53-AC-17(a)
    - NIST-800-53-CM-6(a)
    - NIST-800-53-MA-4(6)
    - NIST-800-53-SC-12(2)
    - NIST-800-53-SC-12(3)
    - NIST-800-53-SC-13
    - PCI-DSSv4-2.2
    - PCI-DSSv4-2.2.7
    - configure_crypto_policy
    - high_severity
    - low_complexity
    - low_disruption
    - no_reboot_needed
    - restrict_strategy

  - name: Configure System Cryptography Policy - Verify that Crypto Policy is Set
      (runtime)
    ansible.builtin.command: /usr/bin/update-crypto-policies --set {{ var_system_crypto_policy
      }}
    when: (current_crypto_policy.stdout.strip() != var_system_crypto_policy) or (config_file_stat.stat.exists
      and current_file_stat.stat.exists and config_file_stat.stat.mtime > current_file_stat.stat.mtime)
      or (not nss_config_stat.stat.exists)
    tags:
    - DISA-STIG-OL09-00-000070
    - DISA-STIG-OL09-00-000241
    - NIST-800-53-AC-17(2)
    - NIST-800-53-AC-17(a)
    - NIST-800-53-CM-6(a)
    - NIST-800-53-MA-4(6)
    - NIST-800-53-SC-12(2)
    - NIST-800-53-SC-12(3)
    - NIST-800-53-SC-13
    - PCI-DSSv4-2.2
    - PCI-DSSv4-2.2.7
    - configure_crypto_policy
    - high_severity
    - low_complexity
    - low_disruption
    - no_reboot_needed
    - restrict_strategy

  - name: Configure Libreswan to use System Crypto Policy
    ansible.builtin.lineinfile:
      path: /etc/ipsec.conf
      line: include /etc/crypto-policies/back-ends/libreswan.config
      create: true
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-002404
    - NIST-800-53-CM-6(a)
    - NIST-800-53-MA-4(6)
    - NIST-800-53-SC-12(2)
    - NIST-800-53-SC-12(3)
    - NIST-800-53-SC-13
    - PCI-DSS-Req-2.2
    - configure_libreswan_crypto_policy
    - high_severity
    - low_complexity
    - low_disruption
    - no_reboot_needed
    - restrict_strategy

  - name: 'Configure SSH Daemon to Use FIPS 140-2 Validated Ciphers: openssh.config'
    block:

    - name: Check for duplicate values
      ansible.builtin.lineinfile:
        path: /etc/crypto-policies/back-ends/openssh.config
        create: true
        regexp: (?i)^.*Ciphers\s+
        state: absent
      check_mode: true
      changed_when: false
      register: dupes

    - name: Deduplicate values from /etc/crypto-policies/back-ends/openssh.config
      ansible.builtin.lineinfile:
        path: /etc/crypto-policies/back-ends/openssh.config
        create: true
        regexp: (?i)^.*Ciphers\s+
        state: absent
      when: dupes.found is defined and dupes.found > 1

    - name: Insert correct line to /etc/crypto-policies/back-ends/openssh.config
      ansible.builtin.lineinfile:
        path: /etc/crypto-policies/back-ends/openssh.config
        create: true
        regexp: (?i)^.*Ciphers\s+
        line: Ciphers {{ sshd_approved_ciphers }}
        state: present
    tags:
    - DISA-STIG-OL09-00-000261
    - NIST-800-53-AC-17(2)
    - harden_sshd_ciphers_openssh_conf_crypto_policy
    - high_severity
    - low_complexity
    - low_disruption
    - reboot_required
    - restrict_strategy

  - name: 'Configure SSH Daemon to Use FIPS 140-2 Validated MACs: openssh.config'
    block:

    - name: Check for duplicate values
      ansible.builtin.lineinfile:
        path: /etc/crypto-policies/back-ends/openssh.config
        create: true
        regexp: (?i)^.*MACs\s+
        state: absent
      check_mode: true
      changed_when: false
      register: dupes

    - name: Deduplicate values from /etc/crypto-policies/back-ends/openssh.config
      ansible.builtin.lineinfile:
        path: /etc/crypto-policies/back-ends/openssh.config
        create: true
        regexp: (?i)^.*MACs\s+
        state: absent
      when: dupes.found is defined and dupes.found > 1

    - name: Insert correct line to /etc/crypto-policies/back-ends/openssh.config
      ansible.builtin.lineinfile:
        path: /etc/crypto-policies/back-ends/openssh.config
        create: true
        regexp: (?i)^.*MACs\s+
        line: MACs {{ sshd_approved_macs }}
        state: present
    tags:
    - DISA-STIG-OL09-00-000262
    - NIST-800-53-AC-17(2)
    - harden_sshd_macs_openssh_conf_crypto_policy
    - low_complexity
    - low_disruption
    - medium_severity
    - reboot_required
    - restrict_strategy

  - name: Make sure that the dconf databases are up-to-date with regards to respective
      keyfiles - Get database modification time for local
    ansible.builtin.stat:
      path: /etc/dconf/db/local
    register: local_db
    when:
    - '"gdm" in ansible_facts.packages'
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-002162
    - PCI-DSS-Req-6.2
    - PCI-DSSv4-8.2
    - PCI-DSSv4-8.2.8
    - dconf_db_up_to_date
    - high_severity
    - low_complexity
    - medium_disruption
    - no_reboot_needed
    - unknown_strategy

  - name: Make sure that the dconf databases are up-to-date with regards to respective
      keyfiles - Get keyfiles for local
    ansible.builtin.find:
      paths: /etc/dconf/db/local.d/
    register: local_keyfiles
    when:
    - '"gdm" in ansible_facts.packages'
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-002162
    - PCI-DSS-Req-6.2
    - PCI-DSSv4-8.2
    - PCI-DSSv4-8.2.8
    - dconf_db_up_to_date
    - high_severity
    - low_complexity
    - medium_disruption
    - no_reboot_needed
    - unknown_strategy

  - name: Make sure that the dconf databases are up-to-date with regards to respective
      keyfiles - Run dconf update for local
    ansible.builtin.command:
      cmd: dconf update
    when:
    - '"gdm" in ansible_facts.packages'
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - not local_db.stat.exists or local_keyfiles.files | length > 0 and local_keyfiles.files
      | map(attribute='mtime') | max > local_db.stat.mtime
    tags:
    - DISA-STIG-OL09-00-002162
    - PCI-DSS-Req-6.2
    - PCI-DSSv4-8.2
    - PCI-DSSv4-8.2.8
    - dconf_db_up_to_date
    - high_severity
    - low_complexity
    - medium_disruption
    - no_reboot_needed
    - unknown_strategy

  - name: Disable the GNOME3 Login Restart and Shutdown Buttons
    community.general.ini_file:
      dest: /etc/dconf/db/local.d/00-security-settings
      section: org/gnome/login-screen
      option: disable-restart-buttons
      value: 'true'
      create: true
      no_extra_spaces: true
    register: result_ini
    when: '"gdm" in ansible_facts.packages'
    tags:
    - DISA-STIG-OL09-00-002127
    - DISA-STIG-OL09-00-002128
    - NIST-800-171-3.1.2
    - NIST-800-53-AC-6(1)
    - NIST-800-53-CM-6(a)
    - NIST-800-53-CM-7(b)
    - dconf_gnome_disable_restart_shutdown
    - high_severity
    - low_complexity
    - medium_disruption
    - no_reboot_needed
    - unknown_strategy

  - name: Prevent user modification of GNOME disablement of Login Restart and Shutdown
      Buttons
    ansible.builtin.lineinfile:
      path: /etc/dconf/db/local.d/locks/00-security-settings-lock
      regexp: ^/org/gnome/login-screen/disable-restart-buttons
      line: /org/gnome/login-screen/disable-restart-buttons
      create: true
    register: result_lineinfile
    when: '"gdm" in ansible_facts.packages'
    tags:
    - DISA-STIG-OL09-00-002127
    - DISA-STIG-OL09-00-002128
    - NIST-800-171-3.1.2
    - NIST-800-53-AC-6(1)
    - NIST-800-53-CM-6(a)
    - NIST-800-53-CM-7(b)
    - dconf_gnome_disable_restart_shutdown
    - high_severity
    - low_complexity
    - medium_disruption
    - no_reboot_needed
    - unknown_strategy

  - name: Dconf Update
    ansible.builtin.command: dconf update
    when:
    - '"gdm" in ansible_facts.packages'
    - result_ini is changed or result_lineinfile is changed
    tags:
    - DISA-STIG-OL09-00-002127
    - DISA-STIG-OL09-00-002128
    - NIST-800-171-3.1.2
    - NIST-800-53-AC-6(1)
    - NIST-800-53-CM-6(a)
    - NIST-800-53-CM-7(b)
    - dconf_gnome_disable_restart_shutdown
    - high_severity
    - low_complexity
    - medium_disruption
    - no_reboot_needed
    - unknown_strategy

  - name: Disable the GNOME3 Login User List
    community.general.ini_file:
      dest: /etc/dconf/db/local.d/00-security-settings
      section: org/gnome/login-screen
      option: disable-user-list
      value: 'true'
      no_extra_spaces: true
      create: true
    register: result_ini
    when: '"gdm" in ansible_facts.packages'
    tags:
    - DISA-STIG-OL09-00-002102
    - NIST-800-53-AC-23
    - NIST-800-53-CM-6(a)
    - dconf_gnome_disable_user_list
    - low_complexity
    - medium_disruption
    - medium_severity
    - no_reboot_needed
    - unknown_strategy

  - name: Prevent user modification of GNOME3 disablement of Login User List
    ansible.builtin.lineinfile:
      path: /etc/dconf/db/local.d/locks/00-security-settings-lock
      regexp: ^/org/gnome/login-screen/disable-user-list$
      line: /org/gnome/login-screen/disable-user-list
      create: true
    register: result_lineinfile
    when: '"gdm" in ansible_facts.packages'
    tags:
    - DISA-STIG-OL09-00-002102
    - NIST-800-53-AC-23
    - NIST-800-53-CM-6(a)
    - dconf_gnome_disable_user_list
    - low_complexity
    - medium_disruption
    - medium_severity
    - no_reboot_needed
    - unknown_strategy

  - name: Dconf Update
    ansible.builtin.command: dconf update
    when:
    - '"gdm" in ansible_facts.packages'
    - result_ini is changed or result_lineinfile is changed
    tags:
    - DISA-STIG-OL09-00-002102
    - NIST-800-53-AC-23
    - NIST-800-53-CM-6(a)
    - dconf_gnome_disable_user_list
    - low_complexity
    - medium_disruption
    - medium_severity
    - no_reboot_needed
    - unknown_strategy

  - name: Detect if removal-action can be found on /etc/dconf/db/local.d/
    ansible.builtin.find:
      path: /etc/dconf/db/local.d/
      contains: ^\s*removal-action
    register: dconf_gnome_lock_screen_on_smartcard_removal_config_files
    when: '"gdm" in ansible_facts.packages'
    tags:
    - DISA-STIG-OL09-00-002126
    - DISA-STIG-OL09-00-002160
    - dconf_gnome_lock_screen_on_smartcard_removal
    - low_complexity
    - medium_disruption
    - medium_severity
    - no_reboot_needed
    - unknown_strategy

  - name: Configure removal-action - default file
    community.general.ini_file:
      dest: /etc/dconf/db/local.d//00-security-settings
      section: org/gnome/settings-daemon/peripherals/smartcard
      option: removal-action
      value: '''lock-screen'''
      create: true
    when:
    - '"gdm" in ansible_facts.packages'
    - dconf_gnome_lock_screen_on_smartcard_removal_config_files is defined and dconf_gnome_lock_screen_on_smartcard_removal_config_files.matched
      == 0
    register: default_file
    tags:
    - DISA-STIG-OL09-00-002126
    - DISA-STIG-OL09-00-002160
    - dconf_gnome_lock_screen_on_smartcard_removal
    - low_complexity
    - medium_disruption
    - medium_severity
    - no_reboot_needed
    - unknown_strategy

  - name: Configure removal-action - existing files
    community.general.ini_file:
      dest: '{{ item.path }}'
      section: org/gnome/settings-daemon/peripherals/smartcard
      option: removal-action
      value: '''lock-screen'''
      create: true
    with_items: '{{ dconf_gnome_lock_screen_on_smartcard_removal_config_files.files
      }}'
    when:
    - '"gdm" in ansible_facts.packages'
    - dconf_gnome_lock_screen_on_smartcard_removal_config_files is defined and dconf_gnome_lock_screen_on_smartcard_removal_config_files.matched
      > 0
    register: existing_files
    tags:
    - DISA-STIG-OL09-00-002126
    - DISA-STIG-OL09-00-002160
    - dconf_gnome_lock_screen_on_smartcard_removal
    - low_complexity
    - medium_disruption
    - medium_severity
    - no_reboot_needed
    - unknown_strategy

  - name: Detect if lock for removal-action can be found on /etc/dconf/db/local.d/
    ansible.builtin.find:
      path: /etc/dconf/db/local.d/locks
      contains: ^\s*removal-action
    register: dconf_gnome_lock_screen_on_smartcard_removal_lock_files
    when: '"gdm" in ansible_facts.packages'
    tags:
    - DISA-STIG-OL09-00-002126
    - DISA-STIG-OL09-00-002160
    - dconf_gnome_lock_screen_on_smartcard_removal
    - low_complexity
    - medium_disruption
    - medium_severity
    - no_reboot_needed
    - unknown_strategy

  - name: Prevent user modification removal-action - default file
    ansible.builtin.lineinfile:
      path: /etc/dconf/db/local.d/locks/00-security-settings-lock
      regexp: ^/org/gnome/settings-daemon/peripherals/smartcard/removal-action$
      line: /org/gnome/settings-daemon/peripherals/smartcard/removal-action
      create: true
    when:
    - '"gdm" in ansible_facts.packages'
    - dconf_gnome_lock_screen_on_smartcard_removal_lock_files is defined and dconf_gnome_lock_screen_on_smartcard_removal_lock_files.matched
      == 0
    tags:
    - DISA-STIG-OL09-00-002126
    - DISA-STIG-OL09-00-002160
    - dconf_gnome_lock_screen_on_smartcard_removal
    - low_complexity
    - medium_disruption
    - medium_severity
    - no_reboot_needed
    - unknown_strategy

  - name: Prevent user modification removal-action - existing files
    ansible.builtin.lineinfile:
      path: '{{ item.path }}'
      regexp: ^/org/gnome/settings-daemon/peripherals/smartcard/removal-action$
      line: /org/gnome/settings-daemon/peripherals/smartcard/removal-action
      create: true
    with_items: '{{ dconf_gnome_lock_screen_on_smartcard_removal_lock_files.files
      }}'
    when:
    - '"gdm" in ansible_facts.packages'
    - dconf_gnome_lock_screen_on_smartcard_removal_lock_files is defined and dconf_gnome_lock_screen_on_smartcard_removal_lock_files.matched
      > 0
    tags:
    - DISA-STIG-OL09-00-002126
    - DISA-STIG-OL09-00-002160
    - dconf_gnome_lock_screen_on_smartcard_removal
    - low_complexity
    - medium_disruption
    - medium_severity
    - no_reboot_needed
    - unknown_strategy

  - name: Dconf Update - removal-action
    ansible.builtin.command: dconf update
    when:
    - '"gdm" in ansible_facts.packages'
    - default_file is changed or existing_files is changed
    tags:
    - DISA-STIG-OL09-00-002126
    - DISA-STIG-OL09-00-002160
    - dconf_gnome_lock_screen_on_smartcard_removal
    - low_complexity
    - medium_disruption
    - medium_severity
    - no_reboot_needed
    - unknown_strategy

  - name: Disable GDM Automatic Login
    community.general.ini_file:
      dest: /etc/gdm/custom.conf
      section: daemon
      option: AutomaticLoginEnable
      value: 'false'
      no_extra_spaces: true
      create: true
    when: '"gdm" in ansible_facts.packages'
    tags:
    - DISA-STIG-OL09-00-002161
    - NIST-800-171-3.1.1
    - NIST-800-53-AC-6(1)
    - NIST-800-53-CM-6(a)
    - NIST-800-53-CM-7(b)
    - PCI-DSSv4-8.3
    - PCI-DSSv4-8.3.1
    - gnome_gdm_disable_automatic_login
    - high_severity
    - low_complexity
    - medium_disruption
    - no_reboot_needed
    - unknown_strategy

  - name: Disable GNOME3 Automounting - automount-open
    community.general.ini_file:
      dest: /etc/dconf/db/local.d/00-security-settings
      section: org/gnome/desktop/media-handling
      option: automount-open
      value: 'false'
      create: true
      no_extra_spaces: true
    register: result_ini
    when: '"gdm" in ansible_facts.packages'
    tags:
    - DISA-STIG-OL09-00-002100
    - DISA-STIG-OL09-00-002120
    - NIST-800-171-3.1.7
    - NIST-800-53-CM-6(a)
    - NIST-800-53-CM-7(a)
    - NIST-800-53-CM-7(b)
    - PCI-DSSv4-3.4
    - PCI-DSSv4-3.4.2
    - dconf_gnome_disable_automount_open
    - low_complexity
    - medium_disruption
    - medium_severity
    - no_reboot_needed
    - unknown_strategy

  - name: Prevent user modification of GNOME3 Automounting - automount-open
    ansible.builtin.lineinfile:
      path: /etc/dconf/db/local.d/locks/00-security-settings-lock
      regexp: ^/org/gnome/desktop/media-handling/automount-open$
      line: /org/gnome/desktop/media-handling/automount-open
      create: true
    register: result_lineinfile
    when: '"gdm" in ansible_facts.packages'
    tags:
    - DISA-STIG-OL09-00-002100
    - DISA-STIG-OL09-00-002120
    - NIST-800-171-3.1.7
    - NIST-800-53-CM-6(a)
    - NIST-800-53-CM-7(a)
    - NIST-800-53-CM-7(b)
    - PCI-DSSv4-3.4
    - PCI-DSSv4-3.4.2
    - dconf_gnome_disable_automount_open
    - low_complexity
    - medium_disruption
    - medium_severity
    - no_reboot_needed
    - unknown_strategy

  - name: Dconf Update
    ansible.builtin.command: dconf update
    when:
    - '"gdm" in ansible_facts.packages'
    - result_ini is changed or result_lineinfile is changed
    tags:
    - DISA-STIG-OL09-00-002100
    - DISA-STIG-OL09-00-002120
    - NIST-800-171-3.1.7
    - NIST-800-53-CM-6(a)
    - NIST-800-53-CM-7(a)
    - NIST-800-53-CM-7(b)
    - PCI-DSSv4-3.4
    - PCI-DSSv4-3.4.2
    - dconf_gnome_disable_automount_open
    - low_complexity
    - medium_disruption
    - medium_severity
    - no_reboot_needed
    - unknown_strategy

  - name: Disable GNOME3 Automounting - autorun-never
    community.general.ini_file:
      dest: /etc/dconf/db/local.d/00-security-settings
      section: org/gnome/desktop/media-handling
      option: autorun-never
      value: 'true'
      create: true
      no_extra_spaces: true
    register: result_ini
    when: '"gdm" in ansible_facts.packages'
    tags:
    - DISA-STIG-OL09-00-002101
    - DISA-STIG-OL09-00-002121
    - NIST-800-171-3.1.7
    - NIST-800-53-CM-6(a)
    - NIST-800-53-CM-7(a)
    - NIST-800-53-CM-7(b)
    - dconf_gnome_disable_autorun
    - low_complexity
    - low_severity
    - medium_disruption
    - no_reboot_needed
    - unknown_strategy

  - name: Prevent user modification of GNOME3 Automounting - autorun-never
    ansible.builtin.lineinfile:
      path: /etc/dconf/db/local.d/locks/00-security-settings-lock
      regexp: ^/org/gnome/desktop/media-handling/autorun-never$
      line: /org/gnome/desktop/media-handling/autorun-never
      create: true
    register: result_lineinfile
    when: '"gdm" in ansible_facts.packages'
    tags:
    - DISA-STIG-OL09-00-002101
    - DISA-STIG-OL09-00-002121
    - NIST-800-171-3.1.7
    - NIST-800-53-CM-6(a)
    - NIST-800-53-CM-7(a)
    - NIST-800-53-CM-7(b)
    - dconf_gnome_disable_autorun
    - low_complexity
    - low_severity
    - medium_disruption
    - no_reboot_needed
    - unknown_strategy

  - name: Dconf Update
    ansible.builtin.command: dconf update
    when:
    - '"gdm" in ansible_facts.packages'
    - result_ini is changed or result_lineinfile is changed
    tags:
    - DISA-STIG-OL09-00-002101
    - DISA-STIG-OL09-00-002121
    - NIST-800-171-3.1.7
    - NIST-800-53-CM-6(a)
    - NIST-800-53-CM-7(a)
    - NIST-800-53-CM-7(b)
    - dconf_gnome_disable_autorun
    - low_complexity
    - low_severity
    - medium_disruption
    - no_reboot_needed
    - unknown_strategy

  - name: Set GNOME3 Screensaver Inactivity Timeout
    community.general.ini_file:
      dest: /etc/dconf/db/local.d/00-security-settings
      section: org/gnome/desktop/session
      option: idle-delay
      value: uint32 {{ inactivity_timeout_value }}
      create: true
      no_extra_spaces: true
    register: result_ini
    when: '"gdm" in ansible_facts.packages'
    tags:
    - CJIS-5.5.5
    - DISA-STIG-OL09-00-002104
    - NIST-800-171-3.1.10
    - NIST-800-53-AC-11(a)
    - NIST-800-53-CM-6(a)
    - PCI-DSS-Req-8.1.8
    - PCI-DSSv4-8.2
    - PCI-DSSv4-8.2.8
    - dconf_gnome_screensaver_idle_delay
    - low_complexity
    - medium_disruption
    - medium_severity
    - no_reboot_needed
    - unknown_strategy

  - name: Dconf Update
    ansible.builtin.command: dconf update
    when:
    - '"gdm" in ansible_facts.packages'
    - result_ini is changed
    tags:
    - CJIS-5.5.5
    - DISA-STIG-OL09-00-002104
    - NIST-800-171-3.1.10
    - NIST-800-53-AC-11(a)
    - NIST-800-53-CM-6(a)
    - PCI-DSS-Req-8.1.8
    - PCI-DSSv4-8.2
    - PCI-DSSv4-8.2.8
    - dconf_gnome_screensaver_idle_delay
    - low_complexity
    - medium_disruption
    - medium_severity
    - no_reboot_needed
    - unknown_strategy

  - name: Set GNOME3 Screensaver Lock Delay After Activation Period
    community.general.ini_file:
      dest: /etc/dconf/db/local.d/00-security-settings
      section: org/gnome/desktop/screensaver
      option: lock-delay
      value: uint32 {{ var_screensaver_lock_delay }}
      create: true
      no_extra_spaces: true
    register: result_ini
    when: '"gdm" in ansible_facts.packages'
    tags:
    - DISA-STIG-OL09-00-002103
    - NIST-800-171-3.1.10
    - NIST-800-53-AC-11(a)
    - NIST-800-53-CM-6(a)
    - PCI-DSS-Req-8.1.8
    - PCI-DSSv4-8.2
    - PCI-DSSv4-8.2.8
    - dconf_gnome_screensaver_lock_delay
    - low_complexity
    - medium_disruption
    - medium_severity
    - no_reboot_needed
    - unknown_strategy

  - name: Dconf Update
    ansible.builtin.command: dconf update
    when:
    - '"gdm" in ansible_facts.packages'
    - result_ini is changed
    tags:
    - DISA-STIG-OL09-00-002103
    - NIST-800-171-3.1.10
    - NIST-800-53-AC-11(a)
    - NIST-800-53-CM-6(a)
    - PCI-DSS-Req-8.1.8
    - PCI-DSSv4-8.2
    - PCI-DSSv4-8.2.8
    - dconf_gnome_screensaver_lock_delay
    - low_complexity
    - medium_disruption
    - medium_severity
    - no_reboot_needed
    - unknown_strategy

  - name: Enable GNOME3 Screensaver Lock After Idle Period - Enable GNOME3 Screensaver
      Lock After Idle Period
    community.general.ini_file:
      dest: /etc/dconf/db/local.d/00-security-settings
      section: org/gnome/desktop/screensaver
      option: lock-enabled
      value: 'true'
      create: true
      no_extra_spaces: true
    when:
    - '"gdm" in ansible_facts.packages'
    - ansible_distribution != 'SLES'
    register: screensaver_config
    tags:
    - CJIS-5.5.5
    - DISA-STIG-OL09-00-002123
    - NIST-800-171-3.1.10
    - NIST-800-53-CM-6(a)
    - PCI-DSS-Req-8.1.8
    - PCI-DSSv4-8.2
    - PCI-DSSv4-8.2.8
    - dconf_gnome_screensaver_lock_enabled
    - low_complexity
    - medium_disruption
    - medium_severity
    - no_reboot_needed
    - unknown_strategy

  - name: Enable GNOME3 Screensaver Lock After Idle Period - Prevent user modification
      of GNOME lock-enabled
    ansible.builtin.lineinfile:
      path: /etc/dconf/db/local.d/locks/00-security-settings-lock
      regexp: ^/org/gnome/desktop/screensaver/lock-enabled$
      line: /org/gnome/desktop/screensaver/lock-enabled
      create: true
    when:
    - '"gdm" in ansible_facts.packages'
    - ansible_distribution != 'SLES'
    register: screensaver_lock
    tags:
    - CJIS-5.5.5
    - DISA-STIG-OL09-00-002123
    - NIST-800-171-3.1.10
    - NIST-800-53-CM-6(a)
    - PCI-DSS-Req-8.1.8
    - PCI-DSSv4-8.2
    - PCI-DSSv4-8.2.8
    - dconf_gnome_screensaver_lock_enabled
    - low_complexity
    - medium_disruption
    - medium_severity
    - no_reboot_needed
    - unknown_strategy

  - name: Enable GNOME3 Screensaver Lock After Idle Period - Enable GNOME3 Screensaver
      Lock After Idle Period
    community.general.ini_file:
      dest: /etc/dconf/db/local.d/00-security-settings
      section: org/gnome/desktop/lockdown
      option: disable-lock-screen
      value: 'false'
      create: true
      no_extra_spaces: true
    when:
    - '"gdm" in ansible_facts.packages'
    - ansible_distribution == 'SLES'
    register: lockdown_config
    tags:
    - CJIS-5.5.5
    - DISA-STIG-OL09-00-002123
    - NIST-800-171-3.1.10
    - NIST-800-53-CM-6(a)
    - PCI-DSS-Req-8.1.8
    - PCI-DSSv4-8.2
    - PCI-DSSv4-8.2.8
    - dconf_gnome_screensaver_lock_enabled
    - low_complexity
    - medium_disruption
    - medium_severity
    - no_reboot_needed
    - unknown_strategy

  - name: Enable GNOME3 Screensaver Lock After Idle Period - Prevent user modification
      of GNOME disable-lock-screen
    ansible.builtin.lineinfile:
      path: /etc/dconf/db/local.d/locks/00-security-settings-lock
      regexp: ^/org/gnome/desktop/lockdown/disable-lock-screen$
      line: /org/gnome/desktop/lockdown/disable-lock-screen
      create: true
    when:
    - '"gdm" in ansible_facts.packages'
    - ansible_distribution == 'SLES'
    register: lockdown_lock
    tags:
    - CJIS-5.5.5
    - DISA-STIG-OL09-00-002123
    - NIST-800-171-3.1.10
    - NIST-800-53-CM-6(a)
    - PCI-DSS-Req-8.1.8
    - PCI-DSSv4-8.2
    - PCI-DSSv4-8.2.8
    - dconf_gnome_screensaver_lock_enabled
    - low_complexity
    - medium_disruption
    - medium_severity
    - no_reboot_needed
    - unknown_strategy

  - name: Enable GNOME3 Screensaver Lock After Idle Period - Check GNOME3 screenserver
      disable-lock-screen false
    ansible.builtin.command: gsettings get org.gnome.desktop.lockdown disable-lock-screen
    register: cmd_out
    when:
    - '"gdm" in ansible_facts.packages'
    - ansible_distribution == 'SLES'
    changed_when: false
    tags:
    - CJIS-5.5.5
    - DISA-STIG-OL09-00-002123
    - NIST-800-171-3.1.10
    - NIST-800-53-CM-6(a)
    - PCI-DSS-Req-8.1.8
    - PCI-DSSv4-8.2
    - PCI-DSSv4-8.2.8
    - dconf_gnome_screensaver_lock_enabled
    - low_complexity
    - medium_disruption
    - medium_severity
    - no_reboot_needed
    - unknown_strategy

  - name: Enable GNOME3 Screensaver Lock After Idle Period - Update GNOME3 screenserver
      disable-lock-screen false
    ansible.builtin.command: gsettings set org.gnome.desktop.lockdown disable-lock-screen
      false
    when:
    - '"gdm" in ansible_facts.packages'
    - ansible_distribution == 'SLES'
    - cmd_out.stdout != 'false'
    tags:
    - CJIS-5.5.5
    - DISA-STIG-OL09-00-002123
    - NIST-800-171-3.1.10
    - NIST-800-53-CM-6(a)
    - PCI-DSS-Req-8.1.8
    - PCI-DSSv4-8.2
    - PCI-DSSv4-8.2.8
    - dconf_gnome_screensaver_lock_enabled
    - low_complexity
    - medium_disruption
    - medium_severity
    - no_reboot_needed
    - unknown_strategy

  - name: Enable GNOME3 Screensaver Lock After Idle Period - Update dconf database
      for non-SLES systems
    ansible.builtin.command: dconf update
    when:
    - '"gdm" in ansible_facts.packages'
    - ansible_distribution != 'SLES'
    - (screensaver_config is changed or screensaver_lock is changed)
    tags:
    - CJIS-5.5.5
    - DISA-STIG-OL09-00-002123
    - NIST-800-171-3.1.10
    - NIST-800-53-CM-6(a)
    - PCI-DSS-Req-8.1.8
    - PCI-DSSv4-8.2
    - PCI-DSSv4-8.2.8
    - dconf_gnome_screensaver_lock_enabled
    - low_complexity
    - medium_disruption
    - medium_severity
    - no_reboot_needed
    - unknown_strategy

  - name: Enable GNOME3 Screensaver Lock After Idle Period - Update dconf database
      for SLES systems
    ansible.builtin.command: dconf update
    when:
    - '"gdm" in ansible_facts.packages'
    - ansible_distribution == 'SLES'
    - (lockdown_config is changed or lockdown_lock is changed)
    tags:
    - CJIS-5.5.5
    - DISA-STIG-OL09-00-002123
    - NIST-800-171-3.1.10
    - NIST-800-53-CM-6(a)
    - PCI-DSS-Req-8.1.8
    - PCI-DSSv4-8.2
    - PCI-DSSv4-8.2.8
    - dconf_gnome_screensaver_lock_enabled
    - low_complexity
    - medium_disruption
    - medium_severity
    - no_reboot_needed
    - unknown_strategy

  - name: Implement Blank Screensaver
    community.general.ini_file:
      dest: /etc/dconf/db/local.d/00-security-settings
      section: org/gnome/desktop/screensaver
      option: picture-uri
      value: string ''
      create: true
      no_extra_spaces: true
    register: result_ini
    when: '"gdm" in ansible_facts.packages'
    tags:
    - CJIS-5.5.5
    - DISA-STIG-OL09-00-002106
    - NIST-800-171-3.1.10
    - NIST-800-53-AC-11(1)
    - NIST-800-53-AC-11(1).1
    - NIST-800-53-CM-6(a)
    - PCI-DSS-Req-8.1.8
    - PCI-DSSv4-8.2
    - PCI-DSSv4-8.2.8
    - dconf_gnome_screensaver_mode_blank
    - low_complexity
    - medium_disruption
    - medium_severity
    - no_reboot_needed
    - unknown_strategy

  - name: Prevent user modification of GNOME picture-uri
    ansible.builtin.lineinfile:
      path: /etc/dconf/db/local.d/locks/00-security-settings-lock
      regexp: ^/org/gnome/desktop/screensaver/picture-uri$
      line: /org/gnome/desktop/screensaver/picture-uri
      create: true
    register: result_lineinfile
    when: '"gdm" in ansible_facts.packages'
    tags:
    - CJIS-5.5.5
    - DISA-STIG-OL09-00-002106
    - NIST-800-171-3.1.10
    - NIST-800-53-AC-11(1)
    - NIST-800-53-AC-11(1).1
    - NIST-800-53-CM-6(a)
    - PCI-DSS-Req-8.1.8
    - PCI-DSSv4-8.2
    - PCI-DSSv4-8.2.8
    - dconf_gnome_screensaver_mode_blank
    - low_complexity
    - medium_disruption
    - medium_severity
    - no_reboot_needed
    - unknown_strategy

  - name: Dconf Update
    ansible.builtin.command: dconf update
    when:
    - '"gdm" in ansible_facts.packages'
    - result_ini is changed or result_lineinfile is changed
    tags:
    - CJIS-5.5.5
    - DISA-STIG-OL09-00-002106
    - NIST-800-171-3.1.10
    - NIST-800-53-AC-11(1)
    - NIST-800-53-AC-11(1).1
    - NIST-800-53-CM-6(a)
    - PCI-DSS-Req-8.1.8
    - PCI-DSSv4-8.2
    - PCI-DSSv4-8.2.8
    - dconf_gnome_screensaver_mode_blank
    - low_complexity
    - medium_disruption
    - medium_severity
    - no_reboot_needed
    - unknown_strategy

  - name: Prevent user modification of GNOME lock-delay
    ansible.builtin.lineinfile:
      path: /etc/dconf/db/local.d/locks/00-security-settings-lock
      regexp: ^/org/gnome/desktop/screensaver/lock-delay$
      line: /org/gnome/desktop/screensaver/lock-delay
      create: true
    register: result_lineinfile
    when: '"gdm" in ansible_facts.packages'
    tags:
    - DISA-STIG-OL09-00-002125
    - NIST-800-171-3.1.10
    - NIST-800-53-CM-6(a)
    - dconf_gnome_screensaver_user_locks
    - low_complexity
    - medium_disruption
    - medium_severity
    - no_reboot_needed
    - unknown_strategy

  - name: Dconf Update
    ansible.builtin.command: dconf update
    when:
    - '"gdm" in ansible_facts.packages'
    - result_lineinfile is changed
    tags:
    - DISA-STIG-OL09-00-002125
    - NIST-800-171-3.1.10
    - NIST-800-53-CM-6(a)
    - dconf_gnome_screensaver_user_locks
    - low_complexity
    - medium_disruption
    - medium_severity
    - no_reboot_needed
    - unknown_strategy

  - name: Prevent user modification of GNOME Session idle-delay
    ansible.builtin.lineinfile:
      path: /etc/dconf/db/local.d/locks/00-security-settings-lock
      regexp: ^/org/gnome/desktop/session/idle-delay$
      line: /org/gnome/desktop/session/idle-delay
      create: true
    register: result_lineinfile
    when: '"gdm" in ansible_facts.packages'
    tags:
    - DISA-STIG-OL09-00-002124
    - NIST-800-171-3.1.10
    - NIST-800-53-CM-6(a)
    - PCI-DSS-Req-8.1.8
    - PCI-DSSv4-8.2
    - PCI-DSSv4-8.2.8
    - dconf_gnome_session_idle_user_locks
    - low_complexity
    - medium_disruption
    - medium_severity
    - no_reboot_needed
    - unknown_strategy

  - name: Dconf Update
    ansible.builtin.command: dconf update
    when:
    - '"gdm" in ansible_facts.packages'
    - result_lineinfile is changed
    tags:
    - DISA-STIG-OL09-00-002124
    - NIST-800-171-3.1.10
    - NIST-800-53-CM-6(a)
    - PCI-DSS-Req-8.1.8
    - PCI-DSSv4-8.2
    - PCI-DSSv4-8.2.8
    - dconf_gnome_session_idle_user_locks
    - low_complexity
    - medium_disruption
    - medium_severity
    - no_reboot_needed
    - unknown_strategy

  - name: Disable Ctrl-Alt-Del Reboot Key Sequence in GNOME3
    community.general.ini_file:
      dest: /etc/dconf/db/local.d/00-security-settings
      section: org/gnome/settings-daemon/plugins/media-keys
      option: logout
      value: '['''']'
      create: true
      no_extra_spaces: true
    register: result_ini
    when: '"gdm" in ansible_facts.packages'
    tags:
    - DISA-STIG-OL09-00-002107
    - DISA-STIG-OL09-00-002129
    - NIST-800-171-3.1.2
    - NIST-800-53-AC-6(1)
    - NIST-800-53-CM-6(a)
    - NIST-800-53-CM-7(b)
    - dconf_gnome_disable_ctrlaltdel_reboot
    - high_severity
    - low_complexity
    - medium_disruption
    - no_reboot_needed
    - unknown_strategy

  - name: Prevent user modification of GNOME disablement of Ctrl-Alt-Del
    ansible.builtin.lineinfile:
      path: /etc/dconf/db/local.d/locks/00-security-settings-lock
      regexp: ^/org/gnome/settings-daemon/plugins/media-keys/logout$
      line: /org/gnome/settings-daemon/plugins/media-keys/logout
      create: true
    register: result_lineinfile
    when: '"gdm" in ansible_facts.packages'
    tags:
    - DISA-STIG-OL09-00-002107
    - DISA-STIG-OL09-00-002129
    - NIST-800-171-3.1.2
    - NIST-800-53-AC-6(1)
    - NIST-800-53-CM-6(a)
    - NIST-800-53-CM-7(b)
    - dconf_gnome_disable_ctrlaltdel_reboot
    - high_severity
    - low_complexity
    - medium_disruption
    - no_reboot_needed
    - unknown_strategy

  - name: Dconf Update
    ansible.builtin.command: dconf update
    when:
    - '"gdm" in ansible_facts.packages'
    - result_ini is changed or result_lineinfile is changed
    tags:
    - DISA-STIG-OL09-00-002107
    - DISA-STIG-OL09-00-002129
    - NIST-800-171-3.1.2
    - NIST-800-53-AC-6(1)
    - NIST-800-53-CM-6(a)
    - NIST-800-53-CM-7(b)
    - dconf_gnome_disable_ctrlaltdel_reboot
    - high_severity
    - low_complexity
    - medium_disruption
    - no_reboot_needed
    - unknown_strategy

  - name: Find /etc/sudoers.d/ files
    ansible.builtin.find:
      paths:
      - /etc/sudoers.d/
    register: sudoers
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-002362
    - NIST-800-53-CM-6(a)
    - NIST-800-53-IA-11
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy
    - sudo_remove_no_authenticate

  - name: Remove lines containing !authenticate from sudoers files
    ansible.builtin.replace:
      regexp: (^(?!#).*[\s]+\!authenticate.*$)
      replace: '# \g<1>'
      path: '{{ item.path }}'
      validate: /usr/sbin/visudo -cf %s
    with_items:
    - path: /etc/sudoers
    - '{{ sudoers.files }}'
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-002362
    - NIST-800-53-CM-6(a)
    - NIST-800-53-IA-11
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy
    - sudo_remove_no_authenticate

  - name: Find /etc/sudoers.d/ files
    ansible.builtin.find:
      paths:
      - /etc/sudoers.d/
    register: sudoers
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-002363
    - NIST-800-53-CM-6(a)
    - NIST-800-53-IA-11
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy
    - sudo_remove_nopasswd

  - name: Remove lines containing NOPASSWD from sudoers files
    ansible.builtin.replace:
      regexp: (^(?!#).*[\s]+NOPASSWD[\s]*\:.*$)
      replace: '# \g<1>'
      path: '{{ item.path }}'
      validate: /usr/sbin/visudo -cf %s
    with_items:
    - path: /etc/sudoers
    - '{{ sudoers.files }}'
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-002363
    - NIST-800-53-CM-6(a)
    - NIST-800-53-IA-11
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy
    - sudo_remove_nopasswd

  - name: Require Re-Authentication When Using the sudo Command - Find /etc/sudoers.d/*
      files containing 'Defaults timestamp_timeout'
    ansible.builtin.find:
      path: /etc/sudoers.d
      patterns: '*'
      contains: ^[\s]*Defaults\s.*\btimestamp_timeout[\s]*=.*
    register: sudoers_d_defaults_timestamp_timeout
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - '"sudo" in ansible_facts.packages'
    tags:
    - DISA-STIG-OL09-00-002360
    - NIST-800-53-IA-11
    - PCI-DSSv4-2.2
    - PCI-DSSv4-2.2.6
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy
    - sudo_require_reauthentication

  - name: Require Re-Authentication When Using the sudo Command - Remove 'Defaults
      timestamp_timeout' from /etc/sudoers.d/* files
    ansible.builtin.lineinfile:
      path: '{{ item.path }}'
      regexp: ^[\s]*Defaults\s.*\btimestamp_timeout[\s]*=.*
      state: absent
    with_items: '{{ sudoers_d_defaults_timestamp_timeout.files }}'
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - '"sudo" in ansible_facts.packages'
    tags:
    - DISA-STIG-OL09-00-002360
    - NIST-800-53-IA-11
    - PCI-DSSv4-2.2
    - PCI-DSSv4-2.2.6
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy
    - sudo_require_reauthentication

  - name: Require Re-Authentication When Using the sudo Command - Ensure timestamp_timeout
      has the appropriate value in /etc/sudoers
    ansible.builtin.lineinfile:
      path: /etc/sudoers
      regexp: ^[\s]*Defaults\s(.*)\btimestamp_timeout[\s]*=[\s]*[-]?\w+\b(.*)$
      line: Defaults \1timestamp_timeout={{ var_sudo_timestamp_timeout }}\2
      validate: /usr/sbin/visudo -cf %s
      backrefs: true
    register: edit_sudoers_timestamp_timeout_option
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - '"sudo" in ansible_facts.packages'
    tags:
    - DISA-STIG-OL09-00-002360
    - NIST-800-53-IA-11
    - PCI-DSSv4-2.2
    - PCI-DSSv4-2.2.6
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy
    - sudo_require_reauthentication

  - name: Require Re-Authentication When Using the sudo Command - Enable timestamp_timeout
      option with correct value in /etc/sudoers
    ansible.builtin.lineinfile:
      path: /etc/sudoers
      line: Defaults timestamp_timeout={{ var_sudo_timestamp_timeout }}
      validate: /usr/sbin/visudo -cf %s
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - '"sudo" in ansible_facts.packages'
    - |
      edit_sudoers_timestamp_timeout_option is defined and not edit_sudoers_timestamp_timeout_option.changed
    tags:
    - DISA-STIG-OL09-00-002360
    - NIST-800-53-IA-11
    - PCI-DSSv4-2.2
    - PCI-DSSv4-2.2.6
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy
    - sudo_require_reauthentication

  - name: Require Re-Authentication When Using the sudo Command - Remove timestamp_timeout
      wrong values in /etc/sudoers
    ansible.builtin.lineinfile:
      path: /etc/sudoers
      regexp: ^[\s]*Defaults\s.*\btimestamp_timeout[\s]*=[\s]*(?!{{ var_sudo_timestamp_timeout
        }}\b)[-]?\w+\b.*$
      state: absent
      validate: /usr/sbin/visudo -cf %s
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - '"sudo" in ansible_facts.packages'
    tags:
    - DISA-STIG-OL09-00-002360
    - NIST-800-53-IA-11
    - PCI-DSSv4-2.2
    - PCI-DSSv4-2.2.6
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy
    - sudo_require_reauthentication

  - name: Find out if /etc/sudoers.d/* files contain Defaults targetpw to be deduplicated
    ansible.builtin.find:
      path: /etc/sudoers.d
      patterns: '*'
      contains: ^Defaults targetpw$
    register: sudoers_d_defaults
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - '"sudo" in ansible_facts.packages'
    tags:
    - DISA-STIG-OL09-00-000231
    - NIST-800-53-CM-6(b)
    - NIST-800-53-CM-6.1(iv)
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy
    - sudoers_validate_passwd

  - name: Remove found occurrences of Defaults targetpw from /etc/sudoers.d/* files
    ansible.builtin.lineinfile:
      path: '{{ item.path }}'
      regexp: ^Defaults targetpw$
      state: absent
    with_items: '{{ sudoers_d_defaults.files }}'
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - '"sudo" in ansible_facts.packages'
    tags:
    - DISA-STIG-OL09-00-000231
    - NIST-800-53-CM-6(b)
    - NIST-800-53-CM-6.1(iv)
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy
    - sudoers_validate_passwd

  - name: Find out if /etc/sudoers.d/* files contain Defaults rootpw to be deduplicated
    ansible.builtin.find:
      path: /etc/sudoers.d
      patterns: '*'
      contains: ^Defaults rootpw$
    register: sudoers_d_defaults
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - '"sudo" in ansible_facts.packages'
    tags:
    - DISA-STIG-OL09-00-000231
    - NIST-800-53-CM-6(b)
    - NIST-800-53-CM-6.1(iv)
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy
    - sudoers_validate_passwd

  - name: Remove found occurrences of Defaults rootpw from /etc/sudoers.d/* files
    ansible.builtin.lineinfile:
      path: '{{ item.path }}'
      regexp: ^Defaults rootpw$
      state: absent
    with_items: '{{ sudoers_d_defaults.files }}'
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - '"sudo" in ansible_facts.packages'
    tags:
    - DISA-STIG-OL09-00-000231
    - NIST-800-53-CM-6(b)
    - NIST-800-53-CM-6.1(iv)
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy
    - sudoers_validate_passwd

  - name: Find out if /etc/sudoers.d/* files contain Defaults runaspw to be deduplicated
    ansible.builtin.find:
      path: /etc/sudoers.d
      patterns: '*'
      contains: ^Defaults runaspw$
    register: sudoers_d_defaults
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - '"sudo" in ansible_facts.packages'
    tags:
    - DISA-STIG-OL09-00-000231
    - NIST-800-53-CM-6(b)
    - NIST-800-53-CM-6.1(iv)
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy
    - sudoers_validate_passwd

  - name: Remove found occurrences of Defaults runaspw from /etc/sudoers.d/* files
    ansible.builtin.lineinfile:
      path: '{{ item.path }}'
      regexp: ^Defaults runaspw$
      state: absent
    with_items: '{{ sudoers_d_defaults.files }}'
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - '"sudo" in ansible_facts.packages'
    tags:
    - DISA-STIG-OL09-00-000231
    - NIST-800-53-CM-6(b)
    - NIST-800-53-CM-6.1(iv)
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy
    - sudoers_validate_passwd

  - name: Remove any occurrences of Defaults targetpw in /etc/sudoers
    ansible.builtin.lineinfile:
      path: /etc/sudoers
      regexp: ^Defaults targetpw$
      validate: /usr/sbin/visudo -cf %s
      state: absent
    register: sudoers_file_defaults
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - '"sudo" in ansible_facts.packages'
    tags:
    - DISA-STIG-OL09-00-000231
    - NIST-800-53-CM-6(b)
    - NIST-800-53-CM-6.1(iv)
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy
    - sudoers_validate_passwd

  - name: Remove any occurrences of Defaults rootpw in /etc/sudoers
    ansible.builtin.lineinfile:
      path: /etc/sudoers
      regexp: ^Defaults rootpw$
      validate: /usr/sbin/visudo -cf %s
      state: absent
    register: sudoers_file_defaults
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - '"sudo" in ansible_facts.packages'
    tags:
    - DISA-STIG-OL09-00-000231
    - NIST-800-53-CM-6(b)
    - NIST-800-53-CM-6.1(iv)
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy
    - sudoers_validate_passwd

  - name: Remove any occurrences of Defaults runaspw in /etc/sudoers
    ansible.builtin.lineinfile:
      path: /etc/sudoers
      regexp: ^Defaults runaspw$
      validate: /usr/sbin/visudo -cf %s
      state: absent
    register: sudoers_file_defaults
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - '"sudo" in ansible_facts.packages'
    tags:
    - DISA-STIG-OL09-00-000231
    - NIST-800-53-CM-6(b)
    - NIST-800-53-CM-6.1(iv)
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy
    - sudoers_validate_passwd

  - name: Check for duplicate values
    ansible.builtin.lineinfile:
      path: /etc/sudoers
      create: false
      regexp: ^Defaults !targetpw$
      state: absent
    check_mode: true
    changed_when: false
    register: dupes
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - '"sudo" in ansible_facts.packages'
    tags:
    - DISA-STIG-OL09-00-000231
    - NIST-800-53-CM-6(b)
    - NIST-800-53-CM-6.1(iv)
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy
    - sudoers_validate_passwd

  - name: Deduplicate values from /etc/sudoers
    ansible.builtin.lineinfile:
      path: /etc/sudoers
      create: false
      regexp: ^Defaults !targetpw$
      state: absent
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - '"sudo" in ansible_facts.packages'
    - dupes.found is defined and dupes.found > 1
    tags:
    - DISA-STIG-OL09-00-000231
    - NIST-800-53-CM-6(b)
    - NIST-800-53-CM-6.1(iv)
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy
    - sudoers_validate_passwd

  - name: Insert correct line into /etc/sudoers
    ansible.builtin.lineinfile:
      path: /etc/sudoers
      create: false
      regexp: ^Defaults !targetpw$
      line: Defaults !targetpw
      state: present
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - '"sudo" in ansible_facts.packages'
    tags:
    - DISA-STIG-OL09-00-000231
    - NIST-800-53-CM-6(b)
    - NIST-800-53-CM-6.1(iv)
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy
    - sudoers_validate_passwd

  - name: Check for duplicate values
    ansible.builtin.lineinfile:
      path: /etc/sudoers
      create: false
      regexp: ^Defaults !rootpw$
      state: absent
    check_mode: true
    changed_when: false
    register: dupes
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - '"sudo" in ansible_facts.packages'
    tags:
    - DISA-STIG-OL09-00-000231
    - NIST-800-53-CM-6(b)
    - NIST-800-53-CM-6.1(iv)
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy
    - sudoers_validate_passwd

  - name: Deduplicate values from /etc/sudoers
    ansible.builtin.lineinfile:
      path: /etc/sudoers
      create: false
      regexp: ^Defaults !rootpw$
      state: absent
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - '"sudo" in ansible_facts.packages'
    - dupes.found is defined and dupes.found > 1
    tags:
    - DISA-STIG-OL09-00-000231
    - NIST-800-53-CM-6(b)
    - NIST-800-53-CM-6.1(iv)
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy
    - sudoers_validate_passwd

  - name: Insert correct line into /etc/sudoers
    ansible.builtin.lineinfile:
      path: /etc/sudoers
      create: false
      regexp: ^Defaults !rootpw$
      line: Defaults !rootpw
      state: present
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - '"sudo" in ansible_facts.packages'
    tags:
    - DISA-STIG-OL09-00-000231
    - NIST-800-53-CM-6(b)
    - NIST-800-53-CM-6.1(iv)
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy
    - sudoers_validate_passwd

  - name: Check for duplicate values
    ansible.builtin.lineinfile:
      path: /etc/sudoers
      create: false
      regexp: ^Defaults !runaspw$
      state: absent
    check_mode: true
    changed_when: false
    register: dupes
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - '"sudo" in ansible_facts.packages'
    tags:
    - DISA-STIG-OL09-00-000231
    - NIST-800-53-CM-6(b)
    - NIST-800-53-CM-6.1(iv)
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy
    - sudoers_validate_passwd

  - name: Deduplicate values from /etc/sudoers
    ansible.builtin.lineinfile:
      path: /etc/sudoers
      create: false
      regexp: ^Defaults !runaspw$
      state: absent
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - '"sudo" in ansible_facts.packages'
    - dupes.found is defined and dupes.found > 1
    tags:
    - DISA-STIG-OL09-00-000231
    - NIST-800-53-CM-6(b)
    - NIST-800-53-CM-6.1(iv)
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy
    - sudoers_validate_passwd

  - name: Insert correct line into /etc/sudoers
    ansible.builtin.lineinfile:
      path: /etc/sudoers
      create: false
      regexp: ^Defaults !runaspw$
      line: Defaults !runaspw
      state: present
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - '"sudo" in ansible_facts.packages'
    tags:
    - DISA-STIG-OL09-00-000231
    - NIST-800-53-CM-6(b)
    - NIST-800-53-CM-6.1(iv)
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy
    - sudoers_validate_passwd

  - name: Ensure yum Removes Previous Package Versions - Ensure YUM Removes Previous
      Package Versions
    ansible.builtin.lineinfile:
      dest: /etc/yum.conf
      regexp: ^#?clean_requirements_on_remove
      line: clean_requirements_on_remove=1
      insertafter: \[main\]
      create: true
    when: ( not ( "kernel" in ansible_facts.packages and "rpm-ostree" in ansible_facts.packages
      and "bootc" in ansible_facts.packages and not "openshift-kubelet" in ansible_facts.packages
      and "ostree" in ansible_proc_cmdline ) and "yum" in ansible_facts.packages )
    tags:
    - DISA-STIG-OL09-00-000495
    - NIST-800-171-3.4.8
    - NIST-800-53-CM-11(a)
    - NIST-800-53-CM-11(b)
    - NIST-800-53-CM-6(a)
    - NIST-800-53-SI-2(6)
    - clean_components_post_updating
    - low_complexity
    - low_disruption
    - low_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Find all repository files
    find:
      paths: /etc/yum.repos.d/
      patterns: '*.repo'
    register: repo_files
    tags:
    - DISA-STIG-OL09-00-000105
    - disable_strategy
    - ensure_epel_repos_disabled
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

  - name: Find EPEL repository IDs by name
    shell: |
      set -o pipefail
      # Find repository IDs by name (case-insensitive)
      grep -ioP '^\[\K[^\]]*epel[^\]]*(?=\])' "{{ item.path }}" || true
    register: epel_repo_ids
    loop: '{{ repo_files.files }}'
    changed_when: false
    when: repo_files.files is defined
    tags:
    - DISA-STIG-OL09-00-000105
    - disable_strategy
    - ensure_epel_repos_disabled
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

  - name: Disable EPEL repositories using dnf/yum config-manager
    command: '{% if ansible_pkg_mgr == "dnf" %} dnf config-manager --set-disabled
      {{ item.1 }} {% else %} yum-config-manager --set-disabled {{ item.1 }} {% endif
      %}'
    loop: '{{ epel_repo_ids.results | subelements(''stdout_lines'', skip_missing=True)
      }}'
    when:
    - epel_repo_ids.results is defined
    - item.1 | length > 0
    loop_control:
      label: '{{ item.1 }}'
    register: disable_result
    changed_when: disable_result.rc == 0
    failed_when: false
    tags:
    - DISA-STIG-OL09-00-000105
    - disable_strategy
    - ensure_epel_repos_disabled
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

  - name: Ensure GPG check is globally activated
    community.general.ini_file:
      dest: /etc/yum.conf
      section: main
      option: gpgcheck
      value: 1
      no_extra_spaces: true
      create: false
    when: '"yum" in ansible_facts.packages'
    tags:
    - CJIS-5.10.4.1
    - DISA-STIG-OL09-00-000497
    - NIST-800-171-3.4.8
    - NIST-800-53-CM-11(a)
    - NIST-800-53-CM-11(b)
    - NIST-800-53-CM-5(3)
    - NIST-800-53-CM-6(a)
    - NIST-800-53-SA-12
    - NIST-800-53-SA-12(10)
    - NIST-800-53-SC-12
    - NIST-800-53-SC-12(3)
    - NIST-800-53-SI-7
    - PCI-DSS-Req-6.2
    - PCI-DSSv4-6.3
    - PCI-DSSv4-6.3.3
    - configure_strategy
    - ensure_gpgcheck_globally_activated
    - high_severity
    - low_complexity
    - medium_disruption
    - no_reboot_needed

  - name: Ensure GPG check Enabled for Local Packages (yum)
    block:

    - name: Check stats of yum
      ansible.builtin.stat:
        path: /etc/yum.conf
      register: pkg

    - name: Check if config file of yum is a symlink
      ansible.builtin.set_fact:
        pkg_config_file_symlink: '{{ pkg.stat.lnk_target if pkg.stat.lnk_target is
          match("^/.*") else "/etc/yum.conf" | dirname ~ "/" ~ pkg.stat.lnk_target
          }}'
      when: pkg.stat.lnk_target is defined

    - name: Ensure GPG check Enabled for Local Packages (yum)
      community.general.ini_file:
        dest: '{{ pkg_config_file_symlink |  default("/etc/yum.conf") }}'
        section: main
        option: localpkg_gpgcheck
        value: 1
        no_extra_spaces: true
        create: true
    when: '"yum" in ansible_facts.packages'
    tags:
    - DISA-STIG-OL09-00-000496
    - NIST-800-171-3.4.8
    - NIST-800-53-CM-11(a)
    - NIST-800-53-CM-11(b)
    - NIST-800-53-CM-5(3)
    - NIST-800-53-CM-6(a)
    - NIST-800-53-SA-12
    - NIST-800-53-SA-12(10)
    - ensure_gpgcheck_local_packages
    - high_severity
    - low_complexity
    - medium_disruption
    - no_reboot_needed
    - unknown_strategy

  - name: Grep for yum repo section names
    ansible.builtin.shell: |
      set -o pipefail
      grep -HEr '^\[.+\]' -r /etc/yum.repos.d/
    register: repo_grep_results
    failed_when: repo_grep_results.rc not in [0, 1]
    changed_when: false
    tags:
    - CJIS-5.10.4.1
    - DISA-STIG-OL09-00-000498
    - NIST-800-171-3.4.8
    - NIST-800-53-CM-11(a)
    - NIST-800-53-CM-11(b)
    - NIST-800-53-CM-5(3)
    - NIST-800-53-CM-6(a)
    - NIST-800-53-SA-12
    - NIST-800-53-SA-12(10)
    - NIST-800-53-SC-12
    - NIST-800-53-SC-12(3)
    - NIST-800-53-SI-7
    - PCI-DSS-Req-6.2
    - PCI-DSSv4-6.3
    - PCI-DSSv4-6.3.3
    - enable_strategy
    - ensure_gpgcheck_never_disabled
    - high_severity
    - low_complexity
    - medium_disruption
    - no_reboot_needed

  - name: Set gpgcheck=1 for each yum repo
    community.general.ini_file:
      path: '{{ item[0] }}'
      section: '{{ item[1] }}'
      option: gpgcheck
      value: '1'
      no_extra_spaces: true
    loop: '{{ repo_grep_results.stdout |regex_findall( ''(.+\.repo):\[(.+)\]\n?''
      ) if repo_grep_results is not skipped else [] }}'
    when: repo_grep_results is not skipped
    tags:
    - CJIS-5.10.4.1
    - DISA-STIG-OL09-00-000498
    - NIST-800-171-3.4.8
    - NIST-800-53-CM-11(a)
    - NIST-800-53-CM-11(b)
    - NIST-800-53-CM-5(3)
    - NIST-800-53-CM-6(a)
    - NIST-800-53-SA-12
    - NIST-800-53-SA-12(10)
    - NIST-800-53-SC-12
    - NIST-800-53-SC-12(3)
    - NIST-800-53-SI-7
    - PCI-DSS-Req-6.2
    - PCI-DSSv4-6.3
    - PCI-DSSv4-6.3.3
    - enable_strategy
    - ensure_gpgcheck_never_disabled
    - high_severity
    - low_complexity
    - medium_disruption
    - no_reboot_needed

  - name: Ensure Oracle Linux GPG Key Installed - Read GPG key directory permission
    ansible.builtin.stat:
      path: /etc/pki/rpm-gpg/
    register: gpg_key_directory_permission
    check_mode: false
    tags:
    - DISA-STIG-OL09-00-000499
    - NIST-800-53-CM-11(a)
    - NIST-800-53-CM-11(b)
    - NIST-800-53-CM-5(3)
    - NIST-800-53-CM-6(a)
    - NIST-800-53-SC-12
    - NIST-800-53-SC-12(3)
    - NIST-800-53-SI-7
    - PCI-DSS-Req-6.2
    - ensure_oracle_gpgkey_installed
    - high_severity
    - medium_complexity
    - medium_disruption
    - no_reboot_needed
    - restrict_strategy

  - name: Ensure Oracle Linux GPG Key Installed - Retrieve GPG key fingerprints information
    ansible.builtin.command: gpg --show-keys --with-fingerprint --with-colons "/etc/pki/rpm-gpg/RPM-GPG-KEY-oracle"
    changed_when: false
    register: gpg_fingerprints
    check_mode: false
    tags:
    - DISA-STIG-OL09-00-000499
    - NIST-800-53-CM-11(a)
    - NIST-800-53-CM-11(b)
    - NIST-800-53-CM-5(3)
    - NIST-800-53-CM-6(a)
    - NIST-800-53-SC-12
    - NIST-800-53-SC-12(3)
    - NIST-800-53-SI-7
    - PCI-DSS-Req-6.2
    - ensure_oracle_gpgkey_installed
    - high_severity
    - medium_complexity
    - medium_disruption
    - no_reboot_needed
    - restrict_strategy

  - name: Ensure Oracle Linux GPG Key Installed - Set fact for installed fingerprints
    ansible.builtin.set_fact:
      gpg_installed_fingerprints: |-
        {{ gpg_fingerprints.stdout | regex_findall('^pub.*
        (?:^fpr[:]*)([0-9A-Fa-f]*)', '\1') | list }}
    tags:
    - DISA-STIG-OL09-00-000499
    - NIST-800-53-CM-11(a)
    - NIST-800-53-CM-11(b)
    - NIST-800-53-CM-5(3)
    - NIST-800-53-CM-6(a)
    - NIST-800-53-SC-12
    - NIST-800-53-SC-12(3)
    - NIST-800-53-SI-7
    - PCI-DSS-Req-6.2
    - ensure_oracle_gpgkey_installed
    - high_severity
    - medium_complexity
    - medium_disruption
    - no_reboot_needed
    - restrict_strategy

  - name: Ensure Oracle Linux GPG Key Installed - Set fact for valid fingerprints
    ansible.builtin.set_fact:
      gpg_valid_fingerprints:
      - 3E6D826D3FBAB389C2F38E34BC4D06A08D8B756F
      - 982231759C7467065D0CE9B2A7DD07088B4EFBE6
    tags:
    - DISA-STIG-OL09-00-000499
    - NIST-800-53-CM-11(a)
    - NIST-800-53-CM-11(b)
    - NIST-800-53-CM-5(3)
    - NIST-800-53-CM-6(a)
    - NIST-800-53-SC-12
    - NIST-800-53-SC-12(3)
    - NIST-800-53-SI-7
    - PCI-DSS-Req-6.2
    - ensure_oracle_gpgkey_installed
    - high_severity
    - medium_complexity
    - medium_disruption
    - no_reboot_needed
    - restrict_strategy

  - name: Ensure Oracle Linux GPG Key Installed - Import Oracle GPG key securely
    ansible.builtin.rpm_key:
      state: present
      key: /etc/pki/rpm-gpg/RPM-GPG-KEY-oracle
    when:
    - gpg_key_directory_permission.stat.mode <= '0755'
    - (gpg_installed_fingerprints | difference(gpg_valid_fingerprints)) | length ==
      0
    - gpg_installed_fingerprints | length > 0
    tags:
    - DISA-STIG-OL09-00-000499
    - NIST-800-53-CM-11(a)
    - NIST-800-53-CM-11(b)
    - NIST-800-53-CM-5(3)
    - NIST-800-53-CM-6(a)
    - NIST-800-53-SC-12
    - NIST-800-53-SC-12(3)
    - NIST-800-53-SI-7
    - PCI-DSS-Req-6.2
    - ensure_oracle_gpgkey_installed
    - high_severity
    - medium_complexity
    - medium_disruption
    - no_reboot_needed
    - restrict_strategy

  - name: Enable authselect - Check Current authselect Profile
    ansible.builtin.command:
      cmd: authselect current
    register: result_authselect_current
    changed_when: false
    failed_when: false
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-needed_rules
    - NIST-800-53-AC-3
    - PCI-DSSv4-8.3
    - PCI-DSSv4-8.3.4
    - configure_strategy
    - enable_authselect
    - low_complexity
    - medium_disruption
    - medium_severity
    - no_reboot_needed

  - name: Enable authselect - Try to Select an authselect Profile
    ansible.builtin.command:
      cmd: authselect select "{{ var_authselect_profile }}"
    register: result_authselect_select
    changed_when: result_authselect_select.rc == 0
    failed_when: false
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - result_authselect_current.rc != 0
    tags:
    - DISA-STIG-needed_rules
    - NIST-800-53-AC-3
    - PCI-DSSv4-8.3
    - PCI-DSSv4-8.3.4
    - configure_strategy
    - enable_authselect
    - low_complexity
    - medium_disruption
    - medium_severity
    - no_reboot_needed

  - name: Enable authselect - Verify If pam Has Been Altered
    ansible.builtin.command:
      cmd: rpm -qV pam
    register: result_altered_authselect
    changed_when: false
    failed_when: false
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - result_authselect_select is not skipped
    - result_authselect_select.rc != 0
    tags:
    - DISA-STIG-needed_rules
    - NIST-800-53-AC-3
    - PCI-DSSv4-8.3
    - PCI-DSSv4-8.3.4
    - configure_strategy
    - enable_authselect
    - low_complexity
    - medium_disruption
    - medium_severity
    - no_reboot_needed

  - name: Enable authselect - Informative Message Based on authselect Integrity Check
    ansible.builtin.assert:
      that:
      - result_authselect_current.rc == 0 or result_altered_authselect is skipped
        or result_altered_authselect.rc == 0
      fail_msg:
      - authselect is not used but files from the 'pam' package have been altered,
        so the authselect configuration won't be forced.
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-needed_rules
    - NIST-800-53-AC-3
    - PCI-DSSv4-8.3
    - PCI-DSSv4-8.3.4
    - configure_strategy
    - enable_authselect
    - low_complexity
    - medium_disruption
    - medium_severity
    - no_reboot_needed

  - name: Enable authselect - Force authselect Profile Selection
    ansible.builtin.command:
      cmd: authselect select --force "{{ var_authselect_profile }}"
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - result_authselect_current.rc != 0
    - result_authselect_select.rc != 0
    - result_altered_authselect.rc == 0
    tags:
    - DISA-STIG-needed_rules
    - NIST-800-53-AC-3
    - PCI-DSSv4-8.3
    - PCI-DSSv4-8.3.4
    - configure_strategy
    - enable_authselect
    - low_complexity
    - medium_disruption
    - medium_severity
    - no_reboot_needed

  - name: Modify the System Login Banner - Ensure Correct Banner
    ansible.builtin.copy:
      dest: /etc/issue
      content: '{{ login_banner_text | regex_replace("^\^(.*)\$$", "\1") | regex_replace("^\((.*\.)\|.*\)$",
        "\1") | regex_replace("\[\\s\\n\]\+"," ") | regex_replace("\(\?:\[\\n\]\+\|\(\?:\\\\n\)\+\)",
        "\n") | regex_replace("\\", "") | wordwrap() }}'
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-000090
    - NIST-800-171-3.1.9
    - NIST-800-53-AC-8(a)
    - NIST-800-53-AC-8(c)
    - banner_etc_issue
    - low_complexity
    - medium_disruption
    - medium_severity
    - no_reboot_needed
    - unknown_strategy

  - name: Enable GNOME3 Login Warning Banner
    community.general.ini_file:
      dest: /etc/dconf/db/local.d/00-security-settings
      section: org/gnome/login-screen
      option: banner-message-enable
      value: 'true'
      create: true
      no_extra_spaces: true
    register: result_ini
    when: '"gdm" in ansible_facts.packages'
    tags:
    - DISA-STIG-OL09-00-002122
    - DISA-STIG-OL09-00-002150
    - NIST-800-171-3.1.9
    - NIST-800-53-AC-8(a)
    - NIST-800-53-AC-8(b)
    - NIST-800-53-AC-8(c)
    - dconf_gnome_banner_enabled
    - low_complexity
    - medium_disruption
    - medium_severity
    - no_reboot_needed
    - unknown_strategy

  - name: Prevent user modification of GNOME banner-message-enabled
    ansible.builtin.lineinfile:
      path: /etc/dconf/db/local.d/locks/00-security-settings-lock
      regexp: ^/org/gnome/login-screen/banner-message-enable$
      line: /org/gnome/login-screen/banner-message-enable
      create: true
    register: result_lineinfile
    when: '"gdm" in ansible_facts.packages'
    tags:
    - DISA-STIG-OL09-00-002122
    - DISA-STIG-OL09-00-002150
    - NIST-800-171-3.1.9
    - NIST-800-53-AC-8(a)
    - NIST-800-53-AC-8(b)
    - NIST-800-53-AC-8(c)
    - dconf_gnome_banner_enabled
    - low_complexity
    - medium_disruption
    - medium_severity
    - no_reboot_needed
    - unknown_strategy

  - name: Dconf Update
    ansible.builtin.command: dconf update
    when:
    - '"gdm" in ansible_facts.packages'
    - result_ini is changed or result_lineinfile is changed
    tags:
    - DISA-STIG-OL09-00-002122
    - DISA-STIG-OL09-00-002150
    - NIST-800-171-3.1.9
    - NIST-800-53-AC-8(a)
    - NIST-800-53-AC-8(b)
    - NIST-800-53-AC-8(c)
    - dconf_gnome_banner_enabled
    - low_complexity
    - medium_disruption
    - medium_severity
    - no_reboot_needed
    - unknown_strategy

  - name: Set the GNOME3 Login Warning Banner Text
    ansible.builtin.file:
      path: /etc/dconf/db/{{ item }}
      owner: root
      group: root
      mode: 493
      state: directory
    with_items:
    - local.d
    - local.d/locks
    when: '"gdm" in ansible_facts.packages'
    tags:
    - DISA-STIG-OL09-00-002151
    - NIST-800-171-3.1.9
    - NIST-800-53-AC-8(a)
    - NIST-800-53-AC-8(c)
    - dconf_gnome_login_banner_text
    - low_complexity
    - medium_disruption
    - medium_severity
    - no_reboot_needed
    - unknown_strategy

  - name: Set the GNOME3 Login Warning Banner Text
    ansible.builtin.file:
      path: /etc/dconf/db/local.d/{{ item }}
      owner: root
      group: root
      mode: 420
      state: touch
    with_items:
    - 00-security-settings
    - locks/00-security-settings-lock
    when: '"gdm" in ansible_facts.packages'
    tags:
    - DISA-STIG-OL09-00-002151
    - NIST-800-171-3.1.9
    - NIST-800-53-AC-8(a)
    - NIST-800-53-AC-8(c)
    - dconf_gnome_login_banner_text
    - low_complexity
    - medium_disruption
    - medium_severity
    - no_reboot_needed
    - unknown_strategy

  - name: Set the GNOME3 Login Warning Banner Text
    community.general.ini_file:
      dest: /etc/dconf/db/local.d/00-security-settings
      section: org/gnome/login-screen
      option: banner-message-text
      value: '''{{ login_banner_text | regex_replace("^\^(.*)\$$", "\1") | regex_replace("^\((.*\.)\|.*\)$",
        "\1") | regex_replace("\[\\s\\n\]\+"," ") | regex_replace("\(\?:\[\\n\]\+\|\(\?:\\\\n\)\+\)",
        "(n)*") | regex_replace("\\", "") | regex_replace("\(n\)\*", "\\n") }}'''
      create: true
      no_extra_spaces: true
    register: result_ini
    when: '"gdm" in ansible_facts.packages'
    tags:
    - DISA-STIG-OL09-00-002151
    - NIST-800-171-3.1.9
    - NIST-800-53-AC-8(a)
    - NIST-800-53-AC-8(c)
    - dconf_gnome_login_banner_text
    - low_complexity
    - medium_disruption
    - medium_severity
    - no_reboot_needed
    - unknown_strategy

  - name: Prevent user modification of the GNOME3 Login Warning Banner Text
    ansible.builtin.lineinfile:
      path: /etc/dconf/db/local.d/locks/00-security-settings-lock
      regexp: ^/org/gnome/login-screen/banner-message-text$
      line: /org/gnome/login-screen/banner-message-text
      create: true
      state: present
    register: result_lineinfile
    when: '"gdm" in ansible_facts.packages'
    tags:
    - DISA-STIG-OL09-00-002151
    - NIST-800-171-3.1.9
    - NIST-800-53-AC-8(a)
    - NIST-800-53-AC-8(c)
    - dconf_gnome_login_banner_text
    - low_complexity
    - medium_disruption
    - medium_severity
    - no_reboot_needed
    - unknown_strategy

  - name: Dconf Update
    ansible.builtin.command: dconf update
    when:
    - '"gdm" in ansible_facts.packages'
    - result_ini is changed or result_lineinfile is changed
    tags:
    - DISA-STIG-OL09-00-002151
    - NIST-800-171-3.1.9
    - NIST-800-53-AC-8(a)
    - NIST-800-53-AC-8(c)
    - dconf_gnome_login_banner_text
    - low_complexity
    - medium_disruption
    - medium_severity
    - no_reboot_needed
    - unknown_strategy

  - name: Check for pam_succeed_if entry
    ansible.builtin.lineinfile:
      path: /etc/pam.d/sudo
      create: false
      regexp: pam_succeed_if
      state: absent
    when: ( "pam" in ansible_facts.packages and ("kernel" in ansible_facts.packages
      or "kernel-uek" in ansible_facts.packages) )
    tags:
    - DISA-STIG-OL09-00-002364
    - NIST-800-53-IA-11
    - disallow_bypass_password_sudo
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Configure the Use of the pam_faillock.so Module in the /etc/pam.d/password-auth
      File. - Force reselect authselect profile
    ansible.builtin.shell:
      cmd: authselect select "$(authselect current --raw)" --force
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-003012
    - NIST-800-53-AC-7 (a)
    - account_password_pam_faillock_password_auth
    - enable_strategy
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

  - name: Configure the Use of the pam_faillock.so Module in the /etc/pam.d/password-auth
      File. - Check if system relies on authselect tool
    ansible.builtin.stat:
      path: /usr/bin/authselect
    register: result_authselect_present
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-003012
    - NIST-800-53-AC-7 (a)
    - account_password_pam_faillock_password_auth
    - enable_strategy
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

  - name: Configure the Use of the pam_faillock.so Module in the /etc/pam.d/password-auth
      File. - Remediation where authselect tool is present
    block:

    - name: Configure the Use of the pam_faillock.so Module in the /etc/pam.d/password-auth
        File. - Check integrity of authselect current profile
      ansible.builtin.command:
        cmd: authselect check
      register: result_authselect_check_cmd
      changed_when: false
      check_mode: false
      failed_when: false

    - name: Configure the Use of the pam_faillock.so Module in the /etc/pam.d/password-auth
        File. - Informative message based on the authselect integrity check result
      ansible.builtin.assert:
        that:
        - ansible_check_mode or result_authselect_check_cmd.rc == 0
        fail_msg:
        - authselect integrity check failed. Remediation aborted!
        - This remediation could not be applied because an authselect profile was
          not selected or the selected profile is not intact.
        - It is not recommended to manually edit the PAM files when authselect tool
          is available.
        - In cases where the default authselect profile does not cover a specific
          demand, a custom authselect profile is recommended.
        success_msg:
        - authselect integrity check passed

    - name: Configure the Use of the pam_faillock.so Module in the /etc/pam.d/password-auth
        File. - Get authselect current features
      ansible.builtin.shell:
        cmd: authselect current | tail -n+3 | awk '{ print $2 }'
      register: result_authselect_features
      changed_when: false
      check_mode: false
      when:
      - result_authselect_check_cmd is success

    - name: Configure the Use of the pam_faillock.so Module in the /etc/pam.d/password-auth
        File. - Ensure "with-faillock" feature is enabled using authselect tool
      ansible.builtin.command:
        cmd: authselect enable-feature with-faillock
      register: result_authselect_enable_feature_cmd
      when:
      - result_authselect_check_cmd is success
      - result_authselect_features.stdout is not search("with-faillock")

    - name: Configure the Use of the pam_faillock.so Module in the /etc/pam.d/password-auth
        File. - Ensure authselect changes are applied
      ansible.builtin.command:
        cmd: authselect apply-changes -b
      when:
      - result_authselect_enable_feature_cmd is not skipped
      - result_authselect_enable_feature_cmd is success
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - result_authselect_present.stat.exists
    tags:
    - DISA-STIG-OL09-00-003012
    - NIST-800-53-AC-7 (a)
    - account_password_pam_faillock_password_auth
    - enable_strategy
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

  - name: Configure the Use of the pam_faillock.so Module in the /etc/pam.d/password-auth
      File. - Remediation where authselect tool is not present
    block:

    - name: Configure the Use of the pam_faillock.so Module in the /etc/pam.d/password-auth
        File. - Check if pam_faillock.so is already enabled
      ansible.builtin.lineinfile:
        path: /etc/pam.d/system-auth
        regexp: .*auth.*pam_faillock\.so (preauth|authfail)
        state: absent
      check_mode: true
      changed_when: false
      register: result_pam_faillock_is_enabled

    - name: Configure the Use of the pam_faillock.so Module in the /etc/pam.d/password-auth
        File. - Enable pam_faillock.so preauth editing PAM files
      ansible.builtin.lineinfile:
        path: '{{ item }}'
        line: auth        required      pam_faillock.so preauth
        insertbefore: ^auth.*sufficient.*pam_unix\.so.*
        state: present
      loop:
      - /etc/pam.d/system-auth
      - /etc/pam.d/password-auth
      when:
      - result_pam_faillock_is_enabled.found == 0

    - name: Configure the Use of the pam_faillock.so Module in the /etc/pam.d/password-auth
        File. - Enable pam_faillock.so authfail editing PAM files
      ansible.builtin.lineinfile:
        path: '{{ item }}'
        line: auth        required      pam_faillock.so authfail
        insertbefore: ^auth.*required.*pam_deny\.so.*
        state: present
      loop:
      - /etc/pam.d/system-auth
      - /etc/pam.d/password-auth
      when:
      - result_pam_faillock_is_enabled.found == 0

    - name: Configure the Use of the pam_faillock.so Module in the /etc/pam.d/password-auth
        File. - Enable pam_faillock.so account section editing PAM files
      ansible.builtin.lineinfile:
        path: '{{ item }}'
        line: account     required      pam_faillock.so
        insertbefore: ^account.*required.*pam_unix\.so.*
        state: present
      loop:
      - /etc/pam.d/system-auth
      - /etc/pam.d/password-auth
      when:
      - result_pam_faillock_is_enabled.found == 0
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - not result_authselect_present.stat.exists
    tags:
    - DISA-STIG-OL09-00-003012
    - NIST-800-53-AC-7 (a)
    - account_password_pam_faillock_password_auth
    - enable_strategy
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

  - name: Configure the Use of the pam_faillock.so Module in the /etc/pam.d/system-auth
      File. - Check if system relies on authselect tool
    ansible.builtin.stat:
      path: /usr/bin/authselect
    register: result_authselect_present
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-003011
    - NIST-800-53-AC-7 (a)
    - account_password_pam_faillock_system_auth
    - enable_strategy
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

  - name: Configure the Use of the pam_faillock.so Module in the /etc/pam.d/system-auth
      File. - Remediation where authselect tool is present
    block:

    - name: Configure the Use of the pam_faillock.so Module in the /etc/pam.d/system-auth
        File. - Check integrity of authselect current profile
      ansible.builtin.command:
        cmd: authselect check
      register: result_authselect_check_cmd
      changed_when: false
      check_mode: false
      failed_when: false

    - name: Configure the Use of the pam_faillock.so Module in the /etc/pam.d/system-auth
        File. - Informative message based on the authselect integrity check result
      ansible.builtin.assert:
        that:
        - ansible_check_mode or result_authselect_check_cmd.rc == 0
        fail_msg:
        - authselect integrity check failed. Remediation aborted!
        - This remediation could not be applied because an authselect profile was
          not selected or the selected profile is not intact.
        - It is not recommended to manually edit the PAM files when authselect tool
          is available.
        - In cases where the default authselect profile does not cover a specific
          demand, a custom authselect profile is recommended.
        success_msg:
        - authselect integrity check passed

    - name: Configure the Use of the pam_faillock.so Module in the /etc/pam.d/system-auth
        File. - Get authselect current features
      ansible.builtin.shell:
        cmd: authselect current | tail -n+3 | awk '{ print $2 }'
      register: result_authselect_features
      changed_when: false
      check_mode: false
      when:
      - result_authselect_check_cmd is success

    - name: Configure the Use of the pam_faillock.so Module in the /etc/pam.d/system-auth
        File. - Ensure "with-faillock" feature is enabled using authselect tool
      ansible.builtin.command:
        cmd: authselect enable-feature with-faillock
      register: result_authselect_enable_feature_cmd
      when:
      - result_authselect_check_cmd is success
      - result_authselect_features.stdout is not search("with-faillock")

    - name: Configure the Use of the pam_faillock.so Module in the /etc/pam.d/system-auth
        File. - Ensure authselect changes are applied
      ansible.builtin.command:
        cmd: authselect apply-changes -b
      when:
      - result_authselect_enable_feature_cmd is not skipped
      - result_authselect_enable_feature_cmd is success
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - result_authselect_present.stat.exists
    tags:
    - DISA-STIG-OL09-00-003011
    - NIST-800-53-AC-7 (a)
    - account_password_pam_faillock_system_auth
    - enable_strategy
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

  - name: Configure the Use of the pam_faillock.so Module in the /etc/pam.d/system-auth
      File. - Remediation where authselect tool is not present
    block:

    - name: Configure the Use of the pam_faillock.so Module in the /etc/pam.d/system-auth
        File. - Check if pam_faillock.so is already enabled
      ansible.builtin.lineinfile:
        path: /etc/pam.d/system-auth
        regexp: .*auth.*pam_faillock\.so (preauth|authfail)
        state: absent
      check_mode: true
      changed_when: false
      register: result_pam_faillock_is_enabled

    - name: Configure the Use of the pam_faillock.so Module in the /etc/pam.d/system-auth
        File. - Enable pam_faillock.so preauth editing PAM files
      ansible.builtin.lineinfile:
        path: '{{ item }}'
        line: auth        required      pam_faillock.so preauth
        insertbefore: ^auth.*sufficient.*pam_unix\.so.*
        state: present
      loop:
      - /etc/pam.d/system-auth
      - /etc/pam.d/password-auth
      when:
      - result_pam_faillock_is_enabled.found == 0

    - name: Configure the Use of the pam_faillock.so Module in the /etc/pam.d/system-auth
        File. - Enable pam_faillock.so authfail editing PAM files
      ansible.builtin.lineinfile:
        path: '{{ item }}'
        line: auth        required      pam_faillock.so authfail
        insertbefore: ^auth.*required.*pam_deny\.so.*
        state: present
      loop:
      - /etc/pam.d/system-auth
      - /etc/pam.d/password-auth
      when:
      - result_pam_faillock_is_enabled.found == 0

    - name: Configure the Use of the pam_faillock.so Module in the /etc/pam.d/system-auth
        File. - Enable pam_faillock.so account section editing PAM files
      ansible.builtin.lineinfile:
        path: '{{ item }}'
        line: account     required      pam_faillock.so
        insertbefore: ^account.*required.*pam_unix\.so.*
        state: present
      loop:
      - /etc/pam.d/system-auth
      - /etc/pam.d/password-auth
      when:
      - result_pam_faillock_is_enabled.found == 0
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - not result_authselect_present.stat.exists
    tags:
    - DISA-STIG-OL09-00-003011
    - NIST-800-53-AC-7 (a)
    - account_password_pam_faillock_system_auth
    - enable_strategy
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

  - name: An SELinux Context must be configured for the pam_faillock.so records directory
      - Get directories from faillock
    ansible.builtin.shell: grep -oP '^\s*(?:auth.*pam_faillock.so.*)?dir\s*=\s*(\S+)'
      "{{ item }}" | sed -r 's/.*=\s*(\S+)/\1/'
    register: faillock_output
    changed_when: false
    check_mode: false
    with_items:
    - /etc/security/faillock.conf
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-003010
    - NIST-800-53-AC-7 (a)
    - account_password_selinux_faillock_dir
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: An SELinux Context must be configured for the pam_faillock.so records directory
      - Create a list directories from faillock
    ansible.builtin.set_fact:
      list_faillock_dir: '{{ faillock_output.results | map(attribute=''stdout_lines'')
        | flatten }}'
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-003010
    - NIST-800-53-AC-7 (a)
    - account_password_selinux_faillock_dir
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: An SELinux Context must be configured for the pam_faillock.so records directory
      - Create directories for faillock
    ansible.builtin.file:
      path: '{{ item }}'
      state: directory
    with_items: '{{ list_faillock_dir }}'
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - item != ""
    tags:
    - DISA-STIG-OL09-00-003010
    - NIST-800-53-AC-7 (a)
    - account_password_selinux_faillock_dir
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: An SELinux Context must be configured for the pam_faillock.so records directory
      - Get SELinux context for faillock directories
    ansible.builtin.command: ls -dZ "{{ item }}"
    register: faillock_selinux_context
    changed_when: false
    check_mode: false
    with_items: '{{ list_faillock_dir }}'
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - item != ""
    tags:
    - DISA-STIG-OL09-00-003010
    - NIST-800-53-AC-7 (a)
    - account_password_selinux_faillock_dir
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: An SELinux Context must be configured for the pam_faillock.so records directory
      - Set up SELinux context for faillock
    ansible.builtin.shell: |-
      if ! semanage fcontext -a -t faillog_t "{{ item.item }}(/.*)?"; then
        semanage fcontext -m -t faillog_t "{{ item.item }}(/.*)?"
      fi
    with_items: '{{ faillock_selinux_context.results }}'
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - item.item != ""
    - item.stdout is defined
    - '"faillog_t" not in item.stdout'
    tags:
    - DISA-STIG-OL09-00-003010
    - NIST-800-53-AC-7 (a)
    - account_password_selinux_faillock_dir
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: An SELinux Context must be configured for the pam_faillock.so records directory
      - Restore SELinux context
    ansible.builtin.command: restorecon -R -v "{{ item.item }}"
    with_items: '{{ faillock_selinux_context.results }}'
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - item.item != ""
    - item.stdout is defined
    - '"faillog_t" not in item.stdout'
    tags:
    - DISA-STIG-OL09-00-003010
    - NIST-800-53-AC-7 (a)
    - account_password_selinux_faillock_dir
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: An SELinux Context must be configured for the pam_faillock.so records directory
      - Verify pam_faillock.so configuration
    ansible.builtin.debug:
      msg: |-
        "The pam_faillock.so dir option is not set in the system.
        If this is not expected, make sure pam_faillock.so is properly configured."
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - list_faillock_dir | length == 0
    tags:
    - DISA-STIG-OL09-00-003010
    - NIST-800-53-AC-7 (a)
    - account_password_selinux_faillock_dir
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Account Lockouts Must Be Logged - Check if system relies on authselect tool
    ansible.builtin.stat:
      path: /usr/bin/authselect
    register: result_authselect_present
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - '"pam" in ansible_facts.packages'
    tags:
    - DISA-STIG-OL09-00-003022
    - NIST-800-53-AC-7 (a)
    - accounts_passwords_pam_faillock_audit
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Account Lockouts Must Be Logged - Remediation where authselect tool is present
    block:

    - name: Account Lockouts Must Be Logged - Check integrity of authselect current
        profile
      ansible.builtin.command:
        cmd: authselect check
      register: result_authselect_check_cmd
      changed_when: false
      check_mode: false
      failed_when: false

    - name: Account Lockouts Must Be Logged - Informative message based on the authselect
        integrity check result
      ansible.builtin.assert:
        that:
        - ansible_check_mode or result_authselect_check_cmd.rc == 0
        fail_msg:
        - authselect integrity check failed. Remediation aborted!
        - This remediation could not be applied because an authselect profile was
          not selected or the selected profile is not intact.
        - It is not recommended to manually edit the PAM files when authselect tool
          is available.
        - In cases where the default authselect profile does not cover a specific
          demand, a custom authselect profile is recommended.
        success_msg:
        - authselect integrity check passed

    - name: Account Lockouts Must Be Logged - Get authselect current features
      ansible.builtin.shell:
        cmd: authselect current | tail -n+3 | awk '{ print $2 }'
      register: result_authselect_features
      changed_when: false
      check_mode: false
      when:
      - result_authselect_check_cmd is success

    - name: Account Lockouts Must Be Logged - Ensure "with-faillock" feature is enabled
        using authselect tool
      ansible.builtin.command:
        cmd: authselect enable-feature with-faillock
      register: result_authselect_enable_feature_cmd
      when:
      - result_authselect_check_cmd is success
      - result_authselect_features.stdout is not search("with-faillock")

    - name: Account Lockouts Must Be Logged - Ensure authselect changes are applied
      ansible.builtin.command:
        cmd: authselect apply-changes -b
      when:
      - result_authselect_enable_feature_cmd is not skipped
      - result_authselect_enable_feature_cmd is success
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - '"pam" in ansible_facts.packages'
    - result_authselect_present.stat.exists
    tags:
    - DISA-STIG-OL09-00-003022
    - NIST-800-53-AC-7 (a)
    - accounts_passwords_pam_faillock_audit
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Account Lockouts Must Be Logged - Remediation where authselect tool is not
      present
    block:

    - name: Account Lockouts Must Be Logged - Check if pam_faillock.so is already
        enabled
      ansible.builtin.lineinfile:
        path: /etc/pam.d/system-auth
        regexp: .*auth.*pam_faillock\.so (preauth|authfail)
        state: absent
      check_mode: true
      changed_when: false
      register: result_pam_faillock_is_enabled

    - name: Account Lockouts Must Be Logged - Enable pam_faillock.so preauth editing
        PAM files
      ansible.builtin.lineinfile:
        path: '{{ item }}'
        line: auth        required      pam_faillock.so preauth
        insertbefore: ^auth.*sufficient.*pam_unix\.so.*
        state: present
      loop:
      - /etc/pam.d/system-auth
      - /etc/pam.d/password-auth
      when:
      - result_pam_faillock_is_enabled.found == 0

    - name: Account Lockouts Must Be Logged - Enable pam_faillock.so authfail editing
        PAM files
      ansible.builtin.lineinfile:
        path: '{{ item }}'
        line: auth        required      pam_faillock.so authfail
        insertbefore: ^auth.*required.*pam_deny\.so.*
        state: present
      loop:
      - /etc/pam.d/system-auth
      - /etc/pam.d/password-auth
      when:
      - result_pam_faillock_is_enabled.found == 0

    - name: Account Lockouts Must Be Logged - Enable pam_faillock.so account section
        editing PAM files
      ansible.builtin.lineinfile:
        path: '{{ item }}'
        line: account     required      pam_faillock.so
        insertbefore: ^account.*required.*pam_unix\.so.*
        state: present
      loop:
      - /etc/pam.d/system-auth
      - /etc/pam.d/password-auth
      when:
      - result_pam_faillock_is_enabled.found == 0
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - '"pam" in ansible_facts.packages'
    - not result_authselect_present.stat.exists
    tags:
    - DISA-STIG-OL09-00-003022
    - NIST-800-53-AC-7 (a)
    - accounts_passwords_pam_faillock_audit
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Account Lockouts Must Be Logged - Check the presence of /etc/security/faillock.conf
      file
    ansible.builtin.stat:
      path: /etc/security/faillock.conf
    register: result_faillock_conf_check
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - '"pam" in ansible_facts.packages'
    tags:
    - DISA-STIG-OL09-00-003022
    - NIST-800-53-AC-7 (a)
    - accounts_passwords_pam_faillock_audit
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Account Lockouts Must Be Logged - Ensure the pam_faillock.so audit parameter
      in /etc/security/faillock.conf
    ansible.builtin.lineinfile:
      path: /etc/security/faillock.conf
      regexp: ^\s*audit
      line: audit
      state: present
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - '"pam" in ansible_facts.packages'
    - result_faillock_conf_check.stat.exists
    tags:
    - DISA-STIG-OL09-00-003022
    - NIST-800-53-AC-7 (a)
    - accounts_passwords_pam_faillock_audit
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Account Lockouts Must Be Logged - Ensure the pam_faillock.so audit parameter
      not in PAM files
    block:

    - name: Account Lockouts Must Be Logged - Check if /etc/pam.d/system-auth file
        is present
      ansible.builtin.stat:
        path: /etc/pam.d/system-auth
      register: result_pam_auth_file_present

    - name: Account Lockouts Must Be Logged - Check the proper remediation for the
        system
      block:

      - name: Account Lockouts Must Be Logged - Define the PAM file to be edited as
          a local fact
        ansible.builtin.set_fact:
          pam_file_path: /etc/pam.d/system-auth

      - name: Account Lockouts Must Be Logged - Check if system relies on authselect
          tool
        ansible.builtin.stat:
          path: /usr/bin/authselect
        register: result_authselect_present

      - name: Account Lockouts Must Be Logged - Ensure authselect custom profile is
          used if authselect is present
        block:

        - name: Account Lockouts Must Be Logged - Check integrity of authselect current
            profile
          ansible.builtin.command:
            cmd: authselect check
          register: result_authselect_check_cmd
          changed_when: false
          check_mode: false
          failed_when: false

        - name: Account Lockouts Must Be Logged - Informative message based on the
            authselect integrity check result
          ansible.builtin.assert:
            that:
            - ansible_check_mode or result_authselect_check_cmd.rc == 0
            fail_msg:
            - authselect integrity check failed. Remediation aborted!
            - This remediation could not be applied because an authselect profile
              was not selected or the selected profile is not intact.
            - It is not recommended to manually edit the PAM files when authselect
              tool is available.
            - In cases where the default authselect profile does not cover a specific
              demand, a custom authselect profile is recommended.
            success_msg:
            - authselect integrity check passed

        - name: Account Lockouts Must Be Logged - Get authselect current profile
          ansible.builtin.shell:
            cmd: authselect current -r | awk '{ print $1 }'
          register: result_authselect_profile
          changed_when: false
          when:
          - result_authselect_check_cmd is success

        - name: Account Lockouts Must Be Logged - Define the current authselect profile
            as a local fact
          ansible.builtin.set_fact:
            authselect_current_profile: '{{ result_authselect_profile.stdout }}'
            authselect_custom_profile: '{{ result_authselect_profile.stdout }}'
          when:
          - result_authselect_profile is not skipped
          - result_authselect_profile.stdout is match("custom/")

        - name: Account Lockouts Must Be Logged - Define the new authselect custom
            profile as a local fact
          ansible.builtin.set_fact:
            authselect_current_profile: '{{ result_authselect_profile.stdout }}'
            authselect_custom_profile: custom/hardening
          when:
          - result_authselect_profile is not skipped
          - result_authselect_profile.stdout is not match("custom/")

        - name: Account Lockouts Must Be Logged - Get authselect current features
            to also enable them in the custom profile
          ansible.builtin.shell:
            cmd: authselect current | tail -n+3 | awk '{ print $2 }'
          register: result_authselect_features
          changed_when: false
          check_mode: false
          when:
          - result_authselect_profile is not skipped
          - authselect_current_profile is not match("custom/")

        - name: Account Lockouts Must Be Logged - Check if any custom profile with
            the same name was already created
          ansible.builtin.stat:
            path: /etc/authselect/{{ authselect_custom_profile }}
          register: result_authselect_custom_profile_present
          changed_when: false
          when:
          - result_authselect_profile is not skipped
          - authselect_current_profile is not match("custom/")

        - name: Account Lockouts Must Be Logged - Create an authselect custom profile
            based on the current profile
          ansible.builtin.command:
            cmd: authselect create-profile hardening -b {{ authselect_current_profile
              }}
          when:
          - result_authselect_profile is not skipped
          - result_authselect_check_cmd is success
          - authselect_current_profile is not match("^(custom/|local)")
          - not result_authselect_custom_profile_present.stat.exists

        - name: Account Lockouts Must Be Logged - Create an authselect custom profile
            based on sssd profile
          ansible.builtin.command:
            cmd: authselect create-profile hardening -b sssd
          when:
          - result_authselect_profile is not skipped
          - result_authselect_check_cmd is success
          - authselect_current_profile is match("local")
          - not result_authselect_custom_profile_present.stat.exists

        - name: Account Lockouts Must Be Logged - Ensure authselect changes are applied
          ansible.builtin.command:
            cmd: authselect apply-changes -b --backup=before-hardening-custom-profile
          when:
          - result_authselect_check_cmd is success
          - result_authselect_profile is not skipped
          - authselect_current_profile is not match("custom/")
          - authselect_custom_profile is not match(authselect_current_profile)

        - name: Account Lockouts Must Be Logged - Ensure the authselect custom profile
            is selected
          ansible.builtin.command:
            cmd: authselect select {{ authselect_custom_profile }}
          register: result_pam_authselect_select_profile
          when:
          - result_authselect_check_cmd is success
          - result_authselect_profile is not skipped
          - authselect_current_profile is not match("custom/")
          - authselect_custom_profile is not match(authselect_current_profile)

        - name: Account Lockouts Must Be Logged - Restore the authselect features
            in the custom profile
          ansible.builtin.command:
            cmd: authselect enable-feature {{ item }}
          loop: '{{ result_authselect_features.stdout_lines }}'
          register: result_pam_authselect_restore_features
          when:
          - result_authselect_profile is not skipped
          - result_authselect_features is not skipped
          - result_pam_authselect_select_profile is not skipped

        - name: Account Lockouts Must Be Logged - Ensure authselect changes are applied
          ansible.builtin.command:
            cmd: authselect apply-changes -b --backup=after-hardening-custom-profile
          when:
          - result_authselect_check_cmd is success
          - result_authselect_profile is not skipped
          - result_pam_authselect_restore_features is not skipped

        - name: Account Lockouts Must Be Logged - Change the PAM file to be edited
            according to the custom authselect profile
          ansible.builtin.set_fact:
            pam_file_path: /etc/authselect/{{ authselect_custom_profile }}/{{ pam_file_path
              | basename }}
          when:
          - authselect_custom_profile is defined
        when:
        - result_authselect_present.stat.exists

      - name: Account Lockouts Must Be Logged - Define a fact for control already
          filtered in case filters are used
        ansible.builtin.set_fact:
          pam_module_control: ''

      - name: Account Lockouts Must Be Logged - Check if {{ pam_file_path }} file
          is present
        ansible.builtin.stat:
          path: '{{ pam_file_path }}'
        register: result_pam_file_present

      - name: Account Lockouts Must Be Logged - Ensure the "audit" option from "pam_faillock.so"
          is not present in {{ pam_file_path }}
        ansible.builtin.replace:
          dest: '{{ pam_file_path }}'
          regexp: (.*auth.*pam_faillock.so.*)\baudit\b=?[0-9a-zA-Z]*(.*)
          replace: \1\2
        register: result_pam_option_removal
        when:
        - result_pam_file_present.stat.exists

      - name: Account Lockouts Must Be Logged - Ensure authselect changes are applied
        ansible.builtin.command:
          cmd: authselect apply-changes -b
        when:
        - result_authselect_present.stat.exists
        - result_pam_option_removal is changed
      when:
      - result_pam_auth_file_present.stat.exists

    - name: Account Lockouts Must Be Logged - Check if /etc/pam.d/password-auth file
        is present
      ansible.builtin.stat:
        path: /etc/pam.d/password-auth
      register: result_pam_password_auth_file_present

    - name: Account Lockouts Must Be Logged - Check the proper remediation for the
        system
      block:

      - name: Account Lockouts Must Be Logged - Define the PAM file to be edited as
          a local fact
        ansible.builtin.set_fact:
          pam_file_path: /etc/pam.d/password-auth

      - name: Account Lockouts Must Be Logged - Check if system relies on authselect
          tool
        ansible.builtin.stat:
          path: /usr/bin/authselect
        register: result_authselect_present

      - name: Account Lockouts Must Be Logged - Ensure authselect custom profile is
          used if authselect is present
        block:

        - name: Account Lockouts Must Be Logged - Check integrity of authselect current
            profile
          ansible.builtin.command:
            cmd: authselect check
          register: result_authselect_check_cmd
          changed_when: false
          check_mode: false
          failed_when: false

        - name: Account Lockouts Must Be Logged - Informative message based on the
            authselect integrity check result
          ansible.builtin.assert:
            that:
            - ansible_check_mode or result_authselect_check_cmd.rc == 0
            fail_msg:
            - authselect integrity check failed. Remediation aborted!
            - This remediation could not be applied because an authselect profile
              was not selected or the selected profile is not intact.
            - It is not recommended to manually edit the PAM files when authselect
              tool is available.
            - In cases where the default authselect profile does not cover a specific
              demand, a custom authselect profile is recommended.
            success_msg:
            - authselect integrity check passed

        - name: Account Lockouts Must Be Logged - Get authselect current profile
          ansible.builtin.shell:
            cmd: authselect current -r | awk '{ print $1 }'
          register: result_authselect_profile
          changed_when: false
          when:
          - result_authselect_check_cmd is success

        - name: Account Lockouts Must Be Logged - Define the current authselect profile
            as a local fact
          ansible.builtin.set_fact:
            authselect_current_profile: '{{ result_authselect_profile.stdout }}'
            authselect_custom_profile: '{{ result_authselect_profile.stdout }}'
          when:
          - result_authselect_profile is not skipped
          - result_authselect_profile.stdout is match("custom/")

        - name: Account Lockouts Must Be Logged - Define the new authselect custom
            profile as a local fact
          ansible.builtin.set_fact:
            authselect_current_profile: '{{ result_authselect_profile.stdout }}'
            authselect_custom_profile: custom/hardening
          when:
          - result_authselect_profile is not skipped
          - result_authselect_profile.stdout is not match("custom/")

        - name: Account Lockouts Must Be Logged - Get authselect current features
            to also enable them in the custom profile
          ansible.builtin.shell:
            cmd: authselect current | tail -n+3 | awk '{ print $2 }'
          register: result_authselect_features
          changed_when: false
          check_mode: false
          when:
          - result_authselect_profile is not skipped
          - authselect_current_profile is not match("custom/")

        - name: Account Lockouts Must Be Logged - Check if any custom profile with
            the same name was already created
          ansible.builtin.stat:
            path: /etc/authselect/{{ authselect_custom_profile }}
          register: result_authselect_custom_profile_present
          changed_when: false
          when:
          - result_authselect_profile is not skipped
          - authselect_current_profile is not match("custom/")

        - name: Account Lockouts Must Be Logged - Create an authselect custom profile
            based on the current profile
          ansible.builtin.command:
            cmd: authselect create-profile hardening -b {{ authselect_current_profile
              }}
          when:
          - result_authselect_profile is not skipped
          - result_authselect_check_cmd is success
          - authselect_current_profile is not match("^(custom/|local)")
          - not result_authselect_custom_profile_present.stat.exists

        - name: Account Lockouts Must Be Logged - Create an authselect custom profile
            based on sssd profile
          ansible.builtin.command:
            cmd: authselect create-profile hardening -b sssd
          when:
          - result_authselect_profile is not skipped
          - result_authselect_check_cmd is success
          - authselect_current_profile is match("local")
          - not result_authselect_custom_profile_present.stat.exists

        - name: Account Lockouts Must Be Logged - Ensure authselect changes are applied
          ansible.builtin.command:
            cmd: authselect apply-changes -b --backup=before-hardening-custom-profile
          when:
          - result_authselect_check_cmd is success
          - result_authselect_profile is not skipped
          - authselect_current_profile is not match("custom/")
          - authselect_custom_profile is not match(authselect_current_profile)

        - name: Account Lockouts Must Be Logged - Ensure the authselect custom profile
            is selected
          ansible.builtin.command:
            cmd: authselect select {{ authselect_custom_profile }}
          register: result_pam_authselect_select_profile
          when:
          - result_authselect_check_cmd is success
          - result_authselect_profile is not skipped
          - authselect_current_profile is not match("custom/")
          - authselect_custom_profile is not match(authselect_current_profile)

        - name: Account Lockouts Must Be Logged - Restore the authselect features
            in the custom profile
          ansible.builtin.command:
            cmd: authselect enable-feature {{ item }}
          loop: '{{ result_authselect_features.stdout_lines }}'
          register: result_pam_authselect_restore_features
          when:
          - result_authselect_profile is not skipped
          - result_authselect_features is not skipped
          - result_pam_authselect_select_profile is not skipped

        - name: Account Lockouts Must Be Logged - Ensure authselect changes are applied
          ansible.builtin.command:
            cmd: authselect apply-changes -b --backup=after-hardening-custom-profile
          when:
          - result_authselect_check_cmd is success
          - result_authselect_profile is not skipped
          - result_pam_authselect_restore_features is not skipped

        - name: Account Lockouts Must Be Logged - Change the PAM file to be edited
            according to the custom authselect profile
          ansible.builtin.set_fact:
            pam_file_path: /etc/authselect/{{ authselect_custom_profile }}/{{ pam_file_path
              | basename }}
          when:
          - authselect_custom_profile is defined
        when:
        - result_authselect_present.stat.exists

      - name: Account Lockouts Must Be Logged - Define a fact for control already
          filtered in case filters are used
        ansible.builtin.set_fact:
          pam_module_control: ''

      - name: Account Lockouts Must Be Logged - Check if {{ pam_file_path }} file
          is present
        ansible.builtin.stat:
          path: '{{ pam_file_path }}'
        register: result_pam_file_present

      - name: Account Lockouts Must Be Logged - Ensure the "audit" option from "pam_faillock.so"
          is not present in {{ pam_file_path }}
        ansible.builtin.replace:
          dest: '{{ pam_file_path }}'
          regexp: (.*auth.*pam_faillock.so.*)\baudit\b=?[0-9a-zA-Z]*(.*)
          replace: \1\2
        register: result_pam_option_removal
        when:
        - result_pam_file_present.stat.exists

      - name: Account Lockouts Must Be Logged - Ensure authselect changes are applied
        ansible.builtin.command:
          cmd: authselect apply-changes -b
        when:
        - result_authselect_present.stat.exists
        - result_pam_option_removal is changed
      when:
      - result_pam_password_auth_file_present.stat.exists
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - '"pam" in ansible_facts.packages'
    - result_faillock_conf_check.stat.exists
    tags:
    - DISA-STIG-OL09-00-003022
    - NIST-800-53-AC-7 (a)
    - accounts_passwords_pam_faillock_audit
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Account Lockouts Must Be Logged - Ensure the pam_faillock.so audit parameter
      in PAM files
    block:

    - name: Account Lockouts Must Be Logged - Check if pam_faillock.so audit parameter
        is already enabled in pam files
      ansible.builtin.lineinfile:
        path: /etc/pam.d/system-auth
        regexp: .*auth.*pam_faillock\.so (preauth|authfail).*audit
        state: absent
      check_mode: true
      changed_when: false
      register: result_pam_faillock_audit_parameter_is_present

    - name: Account Lockouts Must Be Logged - Ensure the inclusion of pam_faillock.so
        preauth audit parameter in auth section
      ansible.builtin.lineinfile:
        path: '{{ item }}'
        backrefs: true
        regexp: (^\s*auth\s+)([\w\[].*\b)(\s+pam_faillock.so preauth.*)
        line: \1required\3 audit
        state: present
      loop:
      - /etc/pam.d/system-auth
      - /etc/pam.d/password-auth
      when:
      - result_pam_faillock_audit_parameter_is_present.found == 0
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - '"pam" in ansible_facts.packages'
    - not result_faillock_conf_check.stat.exists
    tags:
    - DISA-STIG-OL09-00-003022
    - NIST-800-53-AC-7 (a)
    - accounts_passwords_pam_faillock_audit
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Lock Accounts After Failed Password Attempts - Check if system relies on
      authselect tool
    ansible.builtin.stat:
      path: /usr/bin/authselect
    register: result_authselect_present
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - '"pam" in ansible_facts.packages'
    tags:
    - CJIS-5.5.3
    - DISA-STIG-OL09-00-003020
    - NIST-800-171-3.1.8
    - NIST-800-53-AC-7(a)
    - NIST-800-53-CM-6(a)
    - PCI-DSS-Req-8.1.6
    - PCI-DSSv4-8.3
    - PCI-DSSv4-8.3.4
    - accounts_passwords_pam_faillock_deny
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Lock Accounts After Failed Password Attempts - Remediation where authselect
      tool is present
    block:

    - name: Lock Accounts After Failed Password Attempts - Check integrity of authselect
        current profile
      ansible.builtin.command:
        cmd: authselect check
      register: result_authselect_check_cmd
      changed_when: false
      check_mode: false
      failed_when: false

    - name: Lock Accounts After Failed Password Attempts - Informative message based
        on the authselect integrity check result
      ansible.builtin.assert:
        that:
        - ansible_check_mode or result_authselect_check_cmd.rc == 0
        fail_msg:
        - authselect integrity check failed. Remediation aborted!
        - This remediation could not be applied because an authselect profile was
          not selected or the selected profile is not intact.
        - It is not recommended to manually edit the PAM files when authselect tool
          is available.
        - In cases where the default authselect profile does not cover a specific
          demand, a custom authselect profile is recommended.
        success_msg:
        - authselect integrity check passed

    - name: Lock Accounts After Failed Password Attempts - Get authselect current
        features
      ansible.builtin.shell:
        cmd: authselect current | tail -n+3 | awk '{ print $2 }'
      register: result_authselect_features
      changed_when: false
      check_mode: false
      when:
      - result_authselect_check_cmd is success

    - name: Lock Accounts After Failed Password Attempts - Ensure "with-faillock"
        feature is enabled using authselect tool
      ansible.builtin.command:
        cmd: authselect enable-feature with-faillock
      register: result_authselect_enable_feature_cmd
      when:
      - result_authselect_check_cmd is success
      - result_authselect_features.stdout is not search("with-faillock")

    - name: Lock Accounts After Failed Password Attempts - Ensure authselect changes
        are applied
      ansible.builtin.command:
        cmd: authselect apply-changes -b
      when:
      - result_authselect_enable_feature_cmd is not skipped
      - result_authselect_enable_feature_cmd is success
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - '"pam" in ansible_facts.packages'
    - result_authselect_present.stat.exists
    tags:
    - CJIS-5.5.3
    - DISA-STIG-OL09-00-003020
    - NIST-800-171-3.1.8
    - NIST-800-53-AC-7(a)
    - NIST-800-53-CM-6(a)
    - PCI-DSS-Req-8.1.6
    - PCI-DSSv4-8.3
    - PCI-DSSv4-8.3.4
    - accounts_passwords_pam_faillock_deny
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Lock Accounts After Failed Password Attempts - Remediation where authselect
      tool is not present
    block:

    - name: Lock Accounts After Failed Password Attempts - Check if pam_faillock.so
        is already enabled
      ansible.builtin.lineinfile:
        path: /etc/pam.d/system-auth
        regexp: .*auth.*pam_faillock\.so (preauth|authfail)
        state: absent
      check_mode: true
      changed_when: false
      register: result_pam_faillock_is_enabled

    - name: Lock Accounts After Failed Password Attempts - Enable pam_faillock.so
        preauth editing PAM files
      ansible.builtin.lineinfile:
        path: '{{ item }}'
        line: auth        required      pam_faillock.so preauth
        insertbefore: ^auth.*sufficient.*pam_unix\.so.*
        state: present
      loop:
      - /etc/pam.d/system-auth
      - /etc/pam.d/password-auth
      when:
      - result_pam_faillock_is_enabled.found == 0

    - name: Lock Accounts After Failed Password Attempts - Enable pam_faillock.so
        authfail editing PAM files
      ansible.builtin.lineinfile:
        path: '{{ item }}'
        line: auth        required      pam_faillock.so authfail
        insertbefore: ^auth.*required.*pam_deny\.so.*
        state: present
      loop:
      - /etc/pam.d/system-auth
      - /etc/pam.d/password-auth
      when:
      - result_pam_faillock_is_enabled.found == 0

    - name: Lock Accounts After Failed Password Attempts - Enable pam_faillock.so
        account section editing PAM files
      ansible.builtin.lineinfile:
        path: '{{ item }}'
        line: account     required      pam_faillock.so
        insertbefore: ^account.*required.*pam_unix\.so.*
        state: present
      loop:
      - /etc/pam.d/system-auth
      - /etc/pam.d/password-auth
      when:
      - result_pam_faillock_is_enabled.found == 0
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - '"pam" in ansible_facts.packages'
    - not result_authselect_present.stat.exists
    tags:
    - CJIS-5.5.3
    - DISA-STIG-OL09-00-003020
    - NIST-800-171-3.1.8
    - NIST-800-53-AC-7(a)
    - NIST-800-53-CM-6(a)
    - PCI-DSS-Req-8.1.6
    - PCI-DSSv4-8.3
    - PCI-DSSv4-8.3.4
    - accounts_passwords_pam_faillock_deny
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Lock Accounts After Failed Password Attempts - Check the presence of /etc/security/faillock.conf
      file
    ansible.builtin.stat:
      path: /etc/security/faillock.conf
    register: result_faillock_conf_check
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - '"pam" in ansible_facts.packages'
    tags:
    - CJIS-5.5.3
    - DISA-STIG-OL09-00-003020
    - NIST-800-171-3.1.8
    - NIST-800-53-AC-7(a)
    - NIST-800-53-CM-6(a)
    - PCI-DSS-Req-8.1.6
    - PCI-DSSv4-8.3
    - PCI-DSSv4-8.3.4
    - accounts_passwords_pam_faillock_deny
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Lock Accounts After Failed Password Attempts - Ensure the pam_faillock.so
      deny parameter in /etc/security/faillock.conf
    ansible.builtin.lineinfile:
      path: /etc/security/faillock.conf
      regexp: ^\s*deny\s*=
      line: deny = {{ var_accounts_passwords_pam_faillock_deny }}
      state: present
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - '"pam" in ansible_facts.packages'
    - result_faillock_conf_check.stat.exists
    tags:
    - CJIS-5.5.3
    - DISA-STIG-OL09-00-003020
    - NIST-800-171-3.1.8
    - NIST-800-53-AC-7(a)
    - NIST-800-53-CM-6(a)
    - PCI-DSS-Req-8.1.6
    - PCI-DSSv4-8.3
    - PCI-DSSv4-8.3.4
    - accounts_passwords_pam_faillock_deny
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Lock Accounts After Failed Password Attempts - Ensure the pam_faillock.so
      deny parameter not in PAM files
    block:

    - name: Lock Accounts After Failed Password Attempts - Check if /etc/pam.d/system-auth
        file is present
      ansible.builtin.stat:
        path: /etc/pam.d/system-auth
      register: result_pam_auth_file_present

    - name: Lock Accounts After Failed Password Attempts - Check the proper remediation
        for the system
      block:

      - name: Lock Accounts After Failed Password Attempts - Define the PAM file to
          be edited as a local fact
        ansible.builtin.set_fact:
          pam_file_path: /etc/pam.d/system-auth

      - name: Lock Accounts After Failed Password Attempts - Check if system relies
          on authselect tool
        ansible.builtin.stat:
          path: /usr/bin/authselect
        register: result_authselect_present

      - name: Lock Accounts After Failed Password Attempts - Ensure authselect custom
          profile is used if authselect is present
        block:

        - name: Lock Accounts After Failed Password Attempts - Check integrity of
            authselect current profile
          ansible.builtin.command:
            cmd: authselect check
          register: result_authselect_check_cmd
          changed_when: false
          check_mode: false
          failed_when: false

        - name: Lock Accounts After Failed Password Attempts - Informative message
            based on the authselect integrity check result
          ansible.builtin.assert:
            that:
            - ansible_check_mode or result_authselect_check_cmd.rc == 0
            fail_msg:
            - authselect integrity check failed. Remediation aborted!
            - This remediation could not be applied because an authselect profile
              was not selected or the selected profile is not intact.
            - It is not recommended to manually edit the PAM files when authselect
              tool is available.
            - In cases where the default authselect profile does not cover a specific
              demand, a custom authselect profile is recommended.
            success_msg:
            - authselect integrity check passed

        - name: Lock Accounts After Failed Password Attempts - Get authselect current
            profile
          ansible.builtin.shell:
            cmd: authselect current -r | awk '{ print $1 }'
          register: result_authselect_profile
          changed_when: false
          when:
          - result_authselect_check_cmd is success

        - name: Lock Accounts After Failed Password Attempts - Define the current
            authselect profile as a local fact
          ansible.builtin.set_fact:
            authselect_current_profile: '{{ result_authselect_profile.stdout }}'
            authselect_custom_profile: '{{ result_authselect_profile.stdout }}'
          when:
          - result_authselect_profile is not skipped
          - result_authselect_profile.stdout is match("custom/")

        - name: Lock Accounts After Failed Password Attempts - Define the new authselect
            custom profile as a local fact
          ansible.builtin.set_fact:
            authselect_current_profile: '{{ result_authselect_profile.stdout }}'
            authselect_custom_profile: custom/hardening
          when:
          - result_authselect_profile is not skipped
          - result_authselect_profile.stdout is not match("custom/")

        - name: Lock Accounts After Failed Password Attempts - Get authselect current
            features to also enable them in the custom profile
          ansible.builtin.shell:
            cmd: authselect current | tail -n+3 | awk '{ print $2 }'
          register: result_authselect_features
          changed_when: false
          check_mode: false
          when:
          - result_authselect_profile is not skipped
          - authselect_current_profile is not match("custom/")

        - name: Lock Accounts After Failed Password Attempts - Check if any custom
            profile with the same name was already created
          ansible.builtin.stat:
            path: /etc/authselect/{{ authselect_custom_profile }}
          register: result_authselect_custom_profile_present
          changed_when: false
          when:
          - result_authselect_profile is not skipped
          - authselect_current_profile is not match("custom/")

        - name: Lock Accounts After Failed Password Attempts - Create an authselect
            custom profile based on the current profile
          ansible.builtin.command:
            cmd: authselect create-profile hardening -b {{ authselect_current_profile
              }}
          when:
          - result_authselect_profile is not skipped
          - result_authselect_check_cmd is success
          - authselect_current_profile is not match("^(custom/|local)")
          - not result_authselect_custom_profile_present.stat.exists

        - name: Lock Accounts After Failed Password Attempts - Create an authselect
            custom profile based on sssd profile
          ansible.builtin.command:
            cmd: authselect create-profile hardening -b sssd
          when:
          - result_authselect_profile is not skipped
          - result_authselect_check_cmd is success
          - authselect_current_profile is match("local")
          - not result_authselect_custom_profile_present.stat.exists

        - name: Lock Accounts After Failed Password Attempts - Ensure authselect changes
            are applied
          ansible.builtin.command:
            cmd: authselect apply-changes -b --backup=before-hardening-custom-profile
          when:
          - result_authselect_check_cmd is success
          - result_authselect_profile is not skipped
          - authselect_current_profile is not match("custom/")
          - authselect_custom_profile is not match(authselect_current_profile)

        - name: Lock Accounts After Failed Password Attempts - Ensure the authselect
            custom profile is selected
          ansible.builtin.command:
            cmd: authselect select {{ authselect_custom_profile }}
          register: result_pam_authselect_select_profile
          when:
          - result_authselect_check_cmd is success
          - result_authselect_profile is not skipped
          - authselect_current_profile is not match("custom/")
          - authselect_custom_profile is not match(authselect_current_profile)

        - name: Lock Accounts After Failed Password Attempts - Restore the authselect
            features in the custom profile
          ansible.builtin.command:
            cmd: authselect enable-feature {{ item }}
          loop: '{{ result_authselect_features.stdout_lines }}'
          register: result_pam_authselect_restore_features
          when:
          - result_authselect_profile is not skipped
          - result_authselect_features is not skipped
          - result_pam_authselect_select_profile is not skipped

        - name: Lock Accounts After Failed Password Attempts - Ensure authselect changes
            are applied
          ansible.builtin.command:
            cmd: authselect apply-changes -b --backup=after-hardening-custom-profile
          when:
          - result_authselect_check_cmd is success
          - result_authselect_profile is not skipped
          - result_pam_authselect_restore_features is not skipped

        - name: Lock Accounts After Failed Password Attempts - Change the PAM file
            to be edited according to the custom authselect profile
          ansible.builtin.set_fact:
            pam_file_path: /etc/authselect/{{ authselect_custom_profile }}/{{ pam_file_path
              | basename }}
          when:
          - authselect_custom_profile is defined
        when:
        - result_authselect_present.stat.exists

      - name: Lock Accounts After Failed Password Attempts - Define a fact for control
          already filtered in case filters are used
        ansible.builtin.set_fact:
          pam_module_control: ''

      - name: Lock Accounts After Failed Password Attempts - Check if {{ pam_file_path
          }} file is present
        ansible.builtin.stat:
          path: '{{ pam_file_path }}'
        register: result_pam_file_present

      - name: Lock Accounts After Failed Password Attempts - Ensure the "deny" option
          from "pam_faillock.so" is not present in {{ pam_file_path }}
        ansible.builtin.replace:
          dest: '{{ pam_file_path }}'
          regexp: (.*auth.*pam_faillock.so.*)\bdeny\b=?[0-9a-zA-Z]*(.*)
          replace: \1\2
        register: result_pam_option_removal
        when:
        - result_pam_file_present.stat.exists

      - name: Lock Accounts After Failed Password Attempts - Ensure authselect changes
          are applied
        ansible.builtin.command:
          cmd: authselect apply-changes -b
        when:
        - result_authselect_present.stat.exists
        - result_pam_option_removal is changed
      when:
      - result_pam_auth_file_present.stat.exists

    - name: Lock Accounts After Failed Password Attempts - Check if /etc/pam.d/password-auth
        file is present
      ansible.builtin.stat:
        path: /etc/pam.d/password-auth
      register: result_pam_password_auth_file_present

    - name: Lock Accounts After Failed Password Attempts - Check the proper remediation
        for the system
      block:

      - name: Lock Accounts After Failed Password Attempts - Define the PAM file to
          be edited as a local fact
        ansible.builtin.set_fact:
          pam_file_path: /etc/pam.d/password-auth

      - name: Lock Accounts After Failed Password Attempts - Check if system relies
          on authselect tool
        ansible.builtin.stat:
          path: /usr/bin/authselect
        register: result_authselect_present

      - name: Lock Accounts After Failed Password Attempts - Ensure authselect custom
          profile is used if authselect is present
        block:

        - name: Lock Accounts After Failed Password Attempts - Check integrity of
            authselect current profile
          ansible.builtin.command:
            cmd: authselect check
          register: result_authselect_check_cmd
          changed_when: false
          check_mode: false
          failed_when: false

        - name: Lock Accounts After Failed Password Attempts - Informative message
            based on the authselect integrity check result
          ansible.builtin.assert:
            that:
            - ansible_check_mode or result_authselect_check_cmd.rc == 0
            fail_msg:
            - authselect integrity check failed. Remediation aborted!
            - This remediation could not be applied because an authselect profile
              was not selected or the selected profile is not intact.
            - It is not recommended to manually edit the PAM files when authselect
              tool is available.
            - In cases where the default authselect profile does not cover a specific
              demand, a custom authselect profile is recommended.
            success_msg:
            - authselect integrity check passed

        - name: Lock Accounts After Failed Password Attempts - Get authselect current
            profile
          ansible.builtin.shell:
            cmd: authselect current -r | awk '{ print $1 }'
          register: result_authselect_profile
          changed_when: false
          when:
          - result_authselect_check_cmd is success

        - name: Lock Accounts After Failed Password Attempts - Define the current
            authselect profile as a local fact
          ansible.builtin.set_fact:
            authselect_current_profile: '{{ result_authselect_profile.stdout }}'
            authselect_custom_profile: '{{ result_authselect_profile.stdout }}'
          when:
          - result_authselect_profile is not skipped
          - result_authselect_profile.stdout is match("custom/")

        - name: Lock Accounts After Failed Password Attempts - Define the new authselect
            custom profile as a local fact
          ansible.builtin.set_fact:
            authselect_current_profile: '{{ result_authselect_profile.stdout }}'
            authselect_custom_profile: custom/hardening
          when:
          - result_authselect_profile is not skipped
          - result_authselect_profile.stdout is not match("custom/")

        - name: Lock Accounts After Failed Password Attempts - Get authselect current
            features to also enable them in the custom profile
          ansible.builtin.shell:
            cmd: authselect current | tail -n+3 | awk '{ print $2 }'
          register: result_authselect_features
          changed_when: false
          check_mode: false
          when:
          - result_authselect_profile is not skipped
          - authselect_current_profile is not match("custom/")

        - name: Lock Accounts After Failed Password Attempts - Check if any custom
            profile with the same name was already created
          ansible.builtin.stat:
            path: /etc/authselect/{{ authselect_custom_profile }}
          register: result_authselect_custom_profile_present
          changed_when: false
          when:
          - result_authselect_profile is not skipped
          - authselect_current_profile is not match("custom/")

        - name: Lock Accounts After Failed Password Attempts - Create an authselect
            custom profile based on the current profile
          ansible.builtin.command:
            cmd: authselect create-profile hardening -b {{ authselect_current_profile
              }}
          when:
          - result_authselect_profile is not skipped
          - result_authselect_check_cmd is success
          - authselect_current_profile is not match("^(custom/|local)")
          - not result_authselect_custom_profile_present.stat.exists

        - name: Lock Accounts After Failed Password Attempts - Create an authselect
            custom profile based on sssd profile
          ansible.builtin.command:
            cmd: authselect create-profile hardening -b sssd
          when:
          - result_authselect_profile is not skipped
          - result_authselect_check_cmd is success
          - authselect_current_profile is match("local")
          - not result_authselect_custom_profile_present.stat.exists

        - name: Lock Accounts After Failed Password Attempts - Ensure authselect changes
            are applied
          ansible.builtin.command:
            cmd: authselect apply-changes -b --backup=before-hardening-custom-profile
          when:
          - result_authselect_check_cmd is success
          - result_authselect_profile is not skipped
          - authselect_current_profile is not match("custom/")
          - authselect_custom_profile is not match(authselect_current_profile)

        - name: Lock Accounts After Failed Password Attempts - Ensure the authselect
            custom profile is selected
          ansible.builtin.command:
            cmd: authselect select {{ authselect_custom_profile }}
          register: result_pam_authselect_select_profile
          when:
          - result_authselect_check_cmd is success
          - result_authselect_profile is not skipped
          - authselect_current_profile is not match("custom/")
          - authselect_custom_profile is not match(authselect_current_profile)

        - name: Lock Accounts After Failed Password Attempts - Restore the authselect
            features in the custom profile
          ansible.builtin.command:
            cmd: authselect enable-feature {{ item }}
          loop: '{{ result_authselect_features.stdout_lines }}'
          register: result_pam_authselect_restore_features
          when:
          - result_authselect_profile is not skipped
          - result_authselect_features is not skipped
          - result_pam_authselect_select_profile is not skipped

        - name: Lock Accounts After Failed Password Attempts - Ensure authselect changes
            are applied
          ansible.builtin.command:
            cmd: authselect apply-changes -b --backup=after-hardening-custom-profile
          when:
          - result_authselect_check_cmd is success
          - result_authselect_profile is not skipped
          - result_pam_authselect_restore_features is not skipped

        - name: Lock Accounts After Failed Password Attempts - Change the PAM file
            to be edited according to the custom authselect profile
          ansible.builtin.set_fact:
            pam_file_path: /etc/authselect/{{ authselect_custom_profile }}/{{ pam_file_path
              | basename }}
          when:
          - authselect_custom_profile is defined
        when:
        - result_authselect_present.stat.exists

      - name: Lock Accounts After Failed Password Attempts - Define a fact for control
          already filtered in case filters are used
        ansible.builtin.set_fact:
          pam_module_control: ''

      - name: Lock Accounts After Failed Password Attempts - Check if {{ pam_file_path
          }} file is present
        ansible.builtin.stat:
          path: '{{ pam_file_path }}'
        register: result_pam_file_present

      - name: Lock Accounts After Failed Password Attempts - Ensure the "deny" option
          from "pam_faillock.so" is not present in {{ pam_file_path }}
        ansible.builtin.replace:
          dest: '{{ pam_file_path }}'
          regexp: (.*auth.*pam_faillock.so.*)\bdeny\b=?[0-9a-zA-Z]*(.*)
          replace: \1\2
        register: result_pam_option_removal
        when:
        - result_pam_file_present.stat.exists

      - name: Lock Accounts After Failed Password Attempts - Ensure authselect changes
          are applied
        ansible.builtin.command:
          cmd: authselect apply-changes -b
        when:
        - result_authselect_present.stat.exists
        - result_pam_option_removal is changed
      when:
      - result_pam_password_auth_file_present.stat.exists
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - '"pam" in ansible_facts.packages'
    - result_faillock_conf_check.stat.exists
    tags:
    - CJIS-5.5.3
    - DISA-STIG-OL09-00-003020
    - NIST-800-171-3.1.8
    - NIST-800-53-AC-7(a)
    - NIST-800-53-CM-6(a)
    - PCI-DSS-Req-8.1.6
    - PCI-DSSv4-8.3
    - PCI-DSSv4-8.3.4
    - accounts_passwords_pam_faillock_deny
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Lock Accounts After Failed Password Attempts - Ensure the pam_faillock.so
      deny parameter in PAM files
    block:

    - name: Lock Accounts After Failed Password Attempts - Check if pam_faillock.so
        deny parameter is already enabled in pam files
      ansible.builtin.lineinfile:
        path: /etc/pam.d/system-auth
        regexp: .*auth.*pam_faillock\.so (preauth|authfail).*deny
        state: absent
      check_mode: true
      changed_when: false
      register: result_pam_faillock_deny_parameter_is_present

    - name: Lock Accounts After Failed Password Attempts - Ensure the inclusion of
        pam_faillock.so preauth deny parameter in auth section
      ansible.builtin.lineinfile:
        path: '{{ item }}'
        backrefs: true
        regexp: (^\s*auth\s+)([\w\[].*\b)(\s+pam_faillock.so preauth.*)
        line: \1required\3 deny={{ var_accounts_passwords_pam_faillock_deny }}
        state: present
      loop:
      - /etc/pam.d/system-auth
      - /etc/pam.d/password-auth
      when:
      - result_pam_faillock_deny_parameter_is_present.found == 0

    - name: Lock Accounts After Failed Password Attempts - Ensure the inclusion of
        pam_faillock.so authfail deny parameter in auth section
      ansible.builtin.lineinfile:
        path: '{{ item }}'
        backrefs: true
        regexp: (^\s*auth\s+)([\w\[].*\b)(\s+pam_faillock.so authfail.*)
        line: \1required\3 deny={{ var_accounts_passwords_pam_faillock_deny }}
        state: present
      loop:
      - /etc/pam.d/system-auth
      - /etc/pam.d/password-auth
      when:
      - result_pam_faillock_deny_parameter_is_present.found == 0

    - name: Lock Accounts After Failed Password Attempts - Ensure the desired value
        for pam_faillock.so preauth deny parameter in auth section
      ansible.builtin.lineinfile:
        path: '{{ item }}'
        backrefs: true
        regexp: (^\s*auth\s+)([\w\[].*\b)(\s+pam_faillock.so preauth.*)(deny)=[0-9]+(.*)
        line: \1required\3\4={{ var_accounts_passwords_pam_faillock_deny }}\5
        state: present
      loop:
      - /etc/pam.d/system-auth
      - /etc/pam.d/password-auth
      when:
      - result_pam_faillock_deny_parameter_is_present.found > 0

    - name: Lock Accounts After Failed Password Attempts - Ensure the desired value
        for pam_faillock.so authfail deny parameter in auth section
      ansible.builtin.lineinfile:
        path: '{{ item }}'
        backrefs: true
        regexp: (^\s*auth\s+)([\w\[].*\b)(\s+pam_faillock.so authfail.*)(deny)=[0-9]+(.*)
        line: \1required\3\4={{ var_accounts_passwords_pam_faillock_deny }}\5
        state: present
      loop:
      - /etc/pam.d/system-auth
      - /etc/pam.d/password-auth
      when:
      - result_pam_faillock_deny_parameter_is_present.found > 0
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - '"pam" in ansible_facts.packages'
    - not result_faillock_conf_check.stat.exists
    tags:
    - CJIS-5.5.3
    - DISA-STIG-OL09-00-003020
    - NIST-800-171-3.1.8
    - NIST-800-53-AC-7(a)
    - NIST-800-53-CM-6(a)
    - PCI-DSS-Req-8.1.6
    - PCI-DSSv4-8.3
    - PCI-DSSv4-8.3.4
    - accounts_passwords_pam_faillock_deny
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Configure the root Account for Failed Password Attempts - Check if system
      relies on authselect tool
    ansible.builtin.stat:
      path: /usr/bin/authselect
    register: result_authselect_present
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - '"pam" in ansible_facts.packages'
    tags:
    - DISA-STIG-OL09-00-003021
    - NIST-800-53-AC-7(b)
    - NIST-800-53-CM-6(a)
    - NIST-800-53-IA-5(c)
    - accounts_passwords_pam_faillock_deny_root
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Configure the root Account for Failed Password Attempts - Remediation where
      authselect tool is present
    block:

    - name: Configure the root Account for Failed Password Attempts - Check integrity
        of authselect current profile
      ansible.builtin.command:
        cmd: authselect check
      register: result_authselect_check_cmd
      changed_when: false
      check_mode: false
      failed_when: false

    - name: Configure the root Account for Failed Password Attempts - Informative
        message based on the authselect integrity check result
      ansible.builtin.assert:
        that:
        - ansible_check_mode or result_authselect_check_cmd.rc == 0
        fail_msg:
        - authselect integrity check failed. Remediation aborted!
        - This remediation could not be applied because an authselect profile was
          not selected or the selected profile is not intact.
        - It is not recommended to manually edit the PAM files when authselect tool
          is available.
        - In cases where the default authselect profile does not cover a specific
          demand, a custom authselect profile is recommended.
        success_msg:
        - authselect integrity check passed

    - name: Configure the root Account for Failed Password Attempts - Get authselect
        current features
      ansible.builtin.shell:
        cmd: authselect current | tail -n+3 | awk '{ print $2 }'
      register: result_authselect_features
      changed_when: false
      check_mode: false
      when:
      - result_authselect_check_cmd is success

    - name: Configure the root Account for Failed Password Attempts - Ensure "with-faillock"
        feature is enabled using authselect tool
      ansible.builtin.command:
        cmd: authselect enable-feature with-faillock
      register: result_authselect_enable_feature_cmd
      when:
      - result_authselect_check_cmd is success
      - result_authselect_features.stdout is not search("with-faillock")

    - name: Configure the root Account for Failed Password Attempts - Ensure authselect
        changes are applied
      ansible.builtin.command:
        cmd: authselect apply-changes -b
      when:
      - result_authselect_enable_feature_cmd is not skipped
      - result_authselect_enable_feature_cmd is success
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - '"pam" in ansible_facts.packages'
    - result_authselect_present.stat.exists
    tags:
    - DISA-STIG-OL09-00-003021
    - NIST-800-53-AC-7(b)
    - NIST-800-53-CM-6(a)
    - NIST-800-53-IA-5(c)
    - accounts_passwords_pam_faillock_deny_root
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Configure the root Account for Failed Password Attempts - Remediation where
      authselect tool is not present
    block:

    - name: Configure the root Account for Failed Password Attempts - Check if pam_faillock.so
        is already enabled
      ansible.builtin.lineinfile:
        path: /etc/pam.d/system-auth
        regexp: .*auth.*pam_faillock\.so (preauth|authfail)
        state: absent
      check_mode: true
      changed_when: false
      register: result_pam_faillock_is_enabled

    - name: Configure the root Account for Failed Password Attempts - Enable pam_faillock.so
        preauth editing PAM files
      ansible.builtin.lineinfile:
        path: '{{ item }}'
        line: auth        required      pam_faillock.so preauth
        insertbefore: ^auth.*sufficient.*pam_unix\.so.*
        state: present
      loop:
      - /etc/pam.d/system-auth
      - /etc/pam.d/password-auth
      when:
      - result_pam_faillock_is_enabled.found == 0

    - name: Configure the root Account for Failed Password Attempts - Enable pam_faillock.so
        authfail editing PAM files
      ansible.builtin.lineinfile:
        path: '{{ item }}'
        line: auth        required      pam_faillock.so authfail
        insertbefore: ^auth.*required.*pam_deny\.so.*
        state: present
      loop:
      - /etc/pam.d/system-auth
      - /etc/pam.d/password-auth
      when:
      - result_pam_faillock_is_enabled.found == 0

    - name: Configure the root Account for Failed Password Attempts - Enable pam_faillock.so
        account section editing PAM files
      ansible.builtin.lineinfile:
        path: '{{ item }}'
        line: account     required      pam_faillock.so
        insertbefore: ^account.*required.*pam_unix\.so.*
        state: present
      loop:
      - /etc/pam.d/system-auth
      - /etc/pam.d/password-auth
      when:
      - result_pam_faillock_is_enabled.found == 0
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - '"pam" in ansible_facts.packages'
    - not result_authselect_present.stat.exists
    tags:
    - DISA-STIG-OL09-00-003021
    - NIST-800-53-AC-7(b)
    - NIST-800-53-CM-6(a)
    - NIST-800-53-IA-5(c)
    - accounts_passwords_pam_faillock_deny_root
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Configure the root Account for Failed Password Attempts - Check the presence
      of /etc/security/faillock.conf file
    ansible.builtin.stat:
      path: /etc/security/faillock.conf
    register: result_faillock_conf_check
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - '"pam" in ansible_facts.packages'
    tags:
    - DISA-STIG-OL09-00-003021
    - NIST-800-53-AC-7(b)
    - NIST-800-53-CM-6(a)
    - NIST-800-53-IA-5(c)
    - accounts_passwords_pam_faillock_deny_root
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Configure the root Account for Failed Password Attempts - Ensure the pam_faillock.so
      even_deny_root parameter in /etc/security/faillock.conf
    ansible.builtin.lineinfile:
      path: /etc/security/faillock.conf
      regexp: ^\s*even_deny_root
      line: even_deny_root
      state: present
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - '"pam" in ansible_facts.packages'
    - result_faillock_conf_check.stat.exists
    tags:
    - DISA-STIG-OL09-00-003021
    - NIST-800-53-AC-7(b)
    - NIST-800-53-CM-6(a)
    - NIST-800-53-IA-5(c)
    - accounts_passwords_pam_faillock_deny_root
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Configure the root Account for Failed Password Attempts - Ensure the pam_faillock.so
      even_deny_root parameter not in PAM files
    block:

    - name: Configure the root Account for Failed Password Attempts - Check if /etc/pam.d/system-auth
        file is present
      ansible.builtin.stat:
        path: /etc/pam.d/system-auth
      register: result_pam_auth_file_present

    - name: Configure the root Account for Failed Password Attempts - Check the proper
        remediation for the system
      block:

      - name: Configure the root Account for Failed Password Attempts - Define the
          PAM file to be edited as a local fact
        ansible.builtin.set_fact:
          pam_file_path: /etc/pam.d/system-auth

      - name: Configure the root Account for Failed Password Attempts - Check if system
          relies on authselect tool
        ansible.builtin.stat:
          path: /usr/bin/authselect
        register: result_authselect_present

      - name: Configure the root Account for Failed Password Attempts - Ensure authselect
          custom profile is used if authselect is present
        block:

        - name: Configure the root Account for Failed Password Attempts - Check integrity
            of authselect current profile
          ansible.builtin.command:
            cmd: authselect check
          register: result_authselect_check_cmd
          changed_when: false
          check_mode: false
          failed_when: false

        - name: Configure the root Account for Failed Password Attempts - Informative
            message based on the authselect integrity check result
          ansible.builtin.assert:
            that:
            - ansible_check_mode or result_authselect_check_cmd.rc == 0
            fail_msg:
            - authselect integrity check failed. Remediation aborted!
            - This remediation could not be applied because an authselect profile
              was not selected or the selected profile is not intact.
            - It is not recommended to manually edit the PAM files when authselect
              tool is available.
            - In cases where the default authselect profile does not cover a specific
              demand, a custom authselect profile is recommended.
            success_msg:
            - authselect integrity check passed

        - name: Configure the root Account for Failed Password Attempts - Get authselect
            current profile
          ansible.builtin.shell:
            cmd: authselect current -r | awk '{ print $1 }'
          register: result_authselect_profile
          changed_when: false
          when:
          - result_authselect_check_cmd is success

        - name: Configure the root Account for Failed Password Attempts - Define the
            current authselect profile as a local fact
          ansible.builtin.set_fact:
            authselect_current_profile: '{{ result_authselect_profile.stdout }}'
            authselect_custom_profile: '{{ result_authselect_profile.stdout }}'
          when:
          - result_authselect_profile is not skipped
          - result_authselect_profile.stdout is match("custom/")

        - name: Configure the root Account for Failed Password Attempts - Define the
            new authselect custom profile as a local fact
          ansible.builtin.set_fact:
            authselect_current_profile: '{{ result_authselect_profile.stdout }}'
            authselect_custom_profile: custom/hardening
          when:
          - result_authselect_profile is not skipped
          - result_authselect_profile.stdout is not match("custom/")

        - name: Configure the root Account for Failed Password Attempts - Get authselect
            current features to also enable them in the custom profile
          ansible.builtin.shell:
            cmd: authselect current | tail -n+3 | awk '{ print $2 }'
          register: result_authselect_features
          changed_when: false
          check_mode: false
          when:
          - result_authselect_profile is not skipped
          - authselect_current_profile is not match("custom/")

        - name: Configure the root Account for Failed Password Attempts - Check if
            any custom profile with the same name was already created
          ansible.builtin.stat:
            path: /etc/authselect/{{ authselect_custom_profile }}
          register: result_authselect_custom_profile_present
          changed_when: false
          when:
          - result_authselect_profile is not skipped
          - authselect_current_profile is not match("custom/")

        - name: Configure the root Account for Failed Password Attempts - Create an
            authselect custom profile based on the current profile
          ansible.builtin.command:
            cmd: authselect create-profile hardening -b {{ authselect_current_profile
              }}
          when:
          - result_authselect_profile is not skipped
          - result_authselect_check_cmd is success
          - authselect_current_profile is not match("^(custom/|local)")
          - not result_authselect_custom_profile_present.stat.exists

        - name: Configure the root Account for Failed Password Attempts - Create an
            authselect custom profile based on sssd profile
          ansible.builtin.command:
            cmd: authselect create-profile hardening -b sssd
          when:
          - result_authselect_profile is not skipped
          - result_authselect_check_cmd is success
          - authselect_current_profile is match("local")
          - not result_authselect_custom_profile_present.stat.exists

        - name: Configure the root Account for Failed Password Attempts - Ensure authselect
            changes are applied
          ansible.builtin.command:
            cmd: authselect apply-changes -b --backup=before-hardening-custom-profile
          when:
          - result_authselect_check_cmd is success
          - result_authselect_profile is not skipped
          - authselect_current_profile is not match("custom/")
          - authselect_custom_profile is not match(authselect_current_profile)

        - name: Configure the root Account for Failed Password Attempts - Ensure the
            authselect custom profile is selected
          ansible.builtin.command:
            cmd: authselect select {{ authselect_custom_profile }}
          register: result_pam_authselect_select_profile
          when:
          - result_authselect_check_cmd is success
          - result_authselect_profile is not skipped
          - authselect_current_profile is not match("custom/")
          - authselect_custom_profile is not match(authselect_current_profile)

        - name: Configure the root Account for Failed Password Attempts - Restore
            the authselect features in the custom profile
          ansible.builtin.command:
            cmd: authselect enable-feature {{ item }}
          loop: '{{ result_authselect_features.stdout_lines }}'
          register: result_pam_authselect_restore_features
          when:
          - result_authselect_profile is not skipped
          - result_authselect_features is not skipped
          - result_pam_authselect_select_profile is not skipped

        - name: Configure the root Account for Failed Password Attempts - Ensure authselect
            changes are applied
          ansible.builtin.command:
            cmd: authselect apply-changes -b --backup=after-hardening-custom-profile
          when:
          - result_authselect_check_cmd is success
          - result_authselect_profile is not skipped
          - result_pam_authselect_restore_features is not skipped

        - name: Configure the root Account for Failed Password Attempts - Change the
            PAM file to be edited according to the custom authselect profile
          ansible.builtin.set_fact:
            pam_file_path: /etc/authselect/{{ authselect_custom_profile }}/{{ pam_file_path
              | basename }}
          when:
          - authselect_custom_profile is defined
        when:
        - result_authselect_present.stat.exists

      - name: Configure the root Account for Failed Password Attempts - Define a fact
          for control already filtered in case filters are used
        ansible.builtin.set_fact:
          pam_module_control: ''

      - name: Configure the root Account for Failed Password Attempts - Check if {{
          pam_file_path }} file is present
        ansible.builtin.stat:
          path: '{{ pam_file_path }}'
        register: result_pam_file_present

      - name: Configure the root Account for Failed Password Attempts - Ensure the
          "even_deny_root" option from "pam_faillock.so" is not present in {{ pam_file_path
          }}
        ansible.builtin.replace:
          dest: '{{ pam_file_path }}'
          regexp: (.*auth.*pam_faillock.so.*)\beven_deny_root\b=?[0-9a-zA-Z]*(.*)
          replace: \1\2
        register: result_pam_option_removal
        when:
        - result_pam_file_present.stat.exists

      - name: Configure the root Account for Failed Password Attempts - Ensure authselect
          changes are applied
        ansible.builtin.command:
          cmd: authselect apply-changes -b
        when:
        - result_authselect_present.stat.exists
        - result_pam_option_removal is changed
      when:
      - result_pam_auth_file_present.stat.exists

    - name: Configure the root Account for Failed Password Attempts - Check if /etc/pam.d/password-auth
        file is present
      ansible.builtin.stat:
        path: /etc/pam.d/password-auth
      register: result_pam_password_auth_file_present

    - name: Configure the root Account for Failed Password Attempts - Check the proper
        remediation for the system
      block:

      - name: Configure the root Account for Failed Password Attempts - Define the
          PAM file to be edited as a local fact
        ansible.builtin.set_fact:
          pam_file_path: /etc/pam.d/password-auth

      - name: Configure the root Account for Failed Password Attempts - Check if system
          relies on authselect tool
        ansible.builtin.stat:
          path: /usr/bin/authselect
        register: result_authselect_present

      - name: Configure the root Account for Failed Password Attempts - Ensure authselect
          custom profile is used if authselect is present
        block:

        - name: Configure the root Account for Failed Password Attempts - Check integrity
            of authselect current profile
          ansible.builtin.command:
            cmd: authselect check
          register: result_authselect_check_cmd
          changed_when: false
          check_mode: false
          failed_when: false

        - name: Configure the root Account for Failed Password Attempts - Informative
            message based on the authselect integrity check result
          ansible.builtin.assert:
            that:
            - ansible_check_mode or result_authselect_check_cmd.rc == 0
            fail_msg:
            - authselect integrity check failed. Remediation aborted!
            - This remediation could not be applied because an authselect profile
              was not selected or the selected profile is not intact.
            - It is not recommended to manually edit the PAM files when authselect
              tool is available.
            - In cases where the default authselect profile does not cover a specific
              demand, a custom authselect profile is recommended.
            success_msg:
            - authselect integrity check passed

        - name: Configure the root Account for Failed Password Attempts - Get authselect
            current profile
          ansible.builtin.shell:
            cmd: authselect current -r | awk '{ print $1 }'
          register: result_authselect_profile
          changed_when: false
          when:
          - result_authselect_check_cmd is success

        - name: Configure the root Account for Failed Password Attempts - Define the
            current authselect profile as a local fact
          ansible.builtin.set_fact:
            authselect_current_profile: '{{ result_authselect_profile.stdout }}'
            authselect_custom_profile: '{{ result_authselect_profile.stdout }}'
          when:
          - result_authselect_profile is not skipped
          - result_authselect_profile.stdout is match("custom/")

        - name: Configure the root Account for Failed Password Attempts - Define the
            new authselect custom profile as a local fact
          ansible.builtin.set_fact:
            authselect_current_profile: '{{ result_authselect_profile.stdout }}'
            authselect_custom_profile: custom/hardening
          when:
          - result_authselect_profile is not skipped
          - result_authselect_profile.stdout is not match("custom/")

        - name: Configure the root Account for Failed Password Attempts - Get authselect
            current features to also enable them in the custom profile
          ansible.builtin.shell:
            cmd: authselect current | tail -n+3 | awk '{ print $2 }'
          register: result_authselect_features
          changed_when: false
          check_mode: false
          when:
          - result_authselect_profile is not skipped
          - authselect_current_profile is not match("custom/")

        - name: Configure the root Account for Failed Password Attempts - Check if
            any custom profile with the same name was already created
          ansible.builtin.stat:
            path: /etc/authselect/{{ authselect_custom_profile }}
          register: result_authselect_custom_profile_present
          changed_when: false
          when:
          - result_authselect_profile is not skipped
          - authselect_current_profile is not match("custom/")

        - name: Configure the root Account for Failed Password Attempts - Create an
            authselect custom profile based on the current profile
          ansible.builtin.command:
            cmd: authselect create-profile hardening -b {{ authselect_current_profile
              }}
          when:
          - result_authselect_profile is not skipped
          - result_authselect_check_cmd is success
          - authselect_current_profile is not match("^(custom/|local)")
          - not result_authselect_custom_profile_present.stat.exists

        - name: Configure the root Account for Failed Password Attempts - Create an
            authselect custom profile based on sssd profile
          ansible.builtin.command:
            cmd: authselect create-profile hardening -b sssd
          when:
          - result_authselect_profile is not skipped
          - result_authselect_check_cmd is success
          - authselect_current_profile is match("local")
          - not result_authselect_custom_profile_present.stat.exists

        - name: Configure the root Account for Failed Password Attempts - Ensure authselect
            changes are applied
          ansible.builtin.command:
            cmd: authselect apply-changes -b --backup=before-hardening-custom-profile
          when:
          - result_authselect_check_cmd is success
          - result_authselect_profile is not skipped
          - authselect_current_profile is not match("custom/")
          - authselect_custom_profile is not match(authselect_current_profile)

        - name: Configure the root Account for Failed Password Attempts - Ensure the
            authselect custom profile is selected
          ansible.builtin.command:
            cmd: authselect select {{ authselect_custom_profile }}
          register: result_pam_authselect_select_profile
          when:
          - result_authselect_check_cmd is success
          - result_authselect_profile is not skipped
          - authselect_current_profile is not match("custom/")
          - authselect_custom_profile is not match(authselect_current_profile)

        - name: Configure the root Account for Failed Password Attempts - Restore
            the authselect features in the custom profile
          ansible.builtin.command:
            cmd: authselect enable-feature {{ item }}
          loop: '{{ result_authselect_features.stdout_lines }}'
          register: result_pam_authselect_restore_features
          when:
          - result_authselect_profile is not skipped
          - result_authselect_features is not skipped
          - result_pam_authselect_select_profile is not skipped

        - name: Configure the root Account for Failed Password Attempts - Ensure authselect
            changes are applied
          ansible.builtin.command:
            cmd: authselect apply-changes -b --backup=after-hardening-custom-profile
          when:
          - result_authselect_check_cmd is success
          - result_authselect_profile is not skipped
          - result_pam_authselect_restore_features is not skipped

        - name: Configure the root Account for Failed Password Attempts - Change the
            PAM file to be edited according to the custom authselect profile
          ansible.builtin.set_fact:
            pam_file_path: /etc/authselect/{{ authselect_custom_profile }}/{{ pam_file_path
              | basename }}
          when:
          - authselect_custom_profile is defined
        when:
        - result_authselect_present.stat.exists

      - name: Configure the root Account for Failed Password Attempts - Define a fact
          for control already filtered in case filters are used
        ansible.builtin.set_fact:
          pam_module_control: ''

      - name: Configure the root Account for Failed Password Attempts - Check if {{
          pam_file_path }} file is present
        ansible.builtin.stat:
          path: '{{ pam_file_path }}'
        register: result_pam_file_present

      - name: Configure the root Account for Failed Password Attempts - Ensure the
          "even_deny_root" option from "pam_faillock.so" is not present in {{ pam_file_path
          }}
        ansible.builtin.replace:
          dest: '{{ pam_file_path }}'
          regexp: (.*auth.*pam_faillock.so.*)\beven_deny_root\b=?[0-9a-zA-Z]*(.*)
          replace: \1\2
        register: result_pam_option_removal
        when:
        - result_pam_file_present.stat.exists

      - name: Configure the root Account for Failed Password Attempts - Ensure authselect
          changes are applied
        ansible.builtin.command:
          cmd: authselect apply-changes -b
        when:
        - result_authselect_present.stat.exists
        - result_pam_option_removal is changed
      when:
      - result_pam_password_auth_file_present.stat.exists
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - '"pam" in ansible_facts.packages'
    - result_faillock_conf_check.stat.exists
    tags:
    - DISA-STIG-OL09-00-003021
    - NIST-800-53-AC-7(b)
    - NIST-800-53-CM-6(a)
    - NIST-800-53-IA-5(c)
    - accounts_passwords_pam_faillock_deny_root
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Configure the root Account for Failed Password Attempts - Ensure the pam_faillock.so
      even_deny_root parameter in PAM files
    block:

    - name: Configure the root Account for Failed Password Attempts - Check if pam_faillock.so
        even_deny_root parameter is already enabled in pam files
      ansible.builtin.lineinfile:
        path: /etc/pam.d/system-auth
        regexp: .*auth.*pam_faillock\.so (preauth|authfail).*even_deny_root
        state: absent
      check_mode: true
      changed_when: false
      register: result_pam_faillock_even_deny_root_parameter_is_present

    - name: Configure the root Account for Failed Password Attempts - Ensure the inclusion
        of pam_faillock.so preauth even_deny_root parameter in auth section
      ansible.builtin.lineinfile:
        path: '{{ item }}'
        backrefs: true
        regexp: (^\s*auth\s+)([\w\[].*\b)(\s+pam_faillock.so preauth.*)
        line: \1required\3 even_deny_root
        state: present
      loop:
      - /etc/pam.d/system-auth
      - /etc/pam.d/password-auth
      when:
      - result_pam_faillock_even_deny_root_parameter_is_present.found == 0

    - name: Configure the root Account for Failed Password Attempts - Ensure the inclusion
        of pam_faillock.so authfail even_deny_root parameter in auth section
      ansible.builtin.lineinfile:
        path: '{{ item }}'
        backrefs: true
        regexp: (^\s*auth\s+)([\w\[].*\b)(\s+pam_faillock.so authfail.*)
        line: \1required\3 even_deny_root
        state: present
      loop:
      - /etc/pam.d/system-auth
      - /etc/pam.d/password-auth
      when:
      - result_pam_faillock_even_deny_root_parameter_is_present.found == 0
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - '"pam" in ansible_facts.packages'
    - not result_faillock_conf_check.stat.exists
    tags:
    - DISA-STIG-OL09-00-003021
    - NIST-800-53-AC-7(b)
    - NIST-800-53-CM-6(a)
    - NIST-800-53-IA-5(c)
    - accounts_passwords_pam_faillock_deny_root
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Lock Accounts Must Persist - Check if system relies on authselect tool
    ansible.builtin.stat:
      path: /usr/bin/authselect
    register: result_authselect_present
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - '"pam" in ansible_facts.packages'
    tags:
    - DISA-STIG-OL09-00-003023
    - NIST-800-53-AC-7(a)
    - NIST-800-53-AC-7(b)
    - NIST-800-53-AC-7.1(ii)
    - accounts_passwords_pam_faillock_dir
    - configure_strategy
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

  - name: Lock Accounts Must Persist - Remediation where authselect tool is present
    block:

    - name: Lock Accounts Must Persist - Check integrity of authselect current profile
      ansible.builtin.command:
        cmd: authselect check
      register: result_authselect_check_cmd
      changed_when: false
      check_mode: false
      failed_when: false

    - name: Lock Accounts Must Persist - Informative message based on the authselect
        integrity check result
      ansible.builtin.assert:
        that:
        - ansible_check_mode or result_authselect_check_cmd.rc == 0
        fail_msg:
        - authselect integrity check failed. Remediation aborted!
        - This remediation could not be applied because an authselect profile was
          not selected or the selected profile is not intact.
        - It is not recommended to manually edit the PAM files when authselect tool
          is available.
        - In cases where the default authselect profile does not cover a specific
          demand, a custom authselect profile is recommended.
        success_msg:
        - authselect integrity check passed

    - name: Lock Accounts Must Persist - Get authselect current features
      ansible.builtin.shell:
        cmd: authselect current | tail -n+3 | awk '{ print $2 }'
      register: result_authselect_features
      changed_when: false
      check_mode: false
      when:
      - result_authselect_check_cmd is success

    - name: Lock Accounts Must Persist - Ensure "with-faillock" feature is enabled
        using authselect tool
      ansible.builtin.command:
        cmd: authselect enable-feature with-faillock
      register: result_authselect_enable_feature_cmd
      when:
      - result_authselect_check_cmd is success
      - result_authselect_features.stdout is not search("with-faillock")

    - name: Lock Accounts Must Persist - Ensure authselect changes are applied
      ansible.builtin.command:
        cmd: authselect apply-changes -b
      when:
      - result_authselect_enable_feature_cmd is not skipped
      - result_authselect_enable_feature_cmd is success
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - '"pam" in ansible_facts.packages'
    - result_authselect_present.stat.exists
    tags:
    - DISA-STIG-OL09-00-003023
    - NIST-800-53-AC-7(a)
    - NIST-800-53-AC-7(b)
    - NIST-800-53-AC-7.1(ii)
    - accounts_passwords_pam_faillock_dir
    - configure_strategy
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

  - name: Lock Accounts Must Persist - Remediation where authselect tool is not present
    block:

    - name: Lock Accounts Must Persist - Check if pam_faillock.so is already enabled
      ansible.builtin.lineinfile:
        path: /etc/pam.d/system-auth
        regexp: .*auth.*pam_faillock\.so (preauth|authfail)
        state: absent
      check_mode: true
      changed_when: false
      register: result_pam_faillock_is_enabled

    - name: Lock Accounts Must Persist - Enable pam_faillock.so preauth editing PAM
        files
      ansible.builtin.lineinfile:
        path: '{{ item }}'
        line: auth        required      pam_faillock.so preauth
        insertbefore: ^auth.*sufficient.*pam_unix\.so.*
        state: present
      loop:
      - /etc/pam.d/system-auth
      - /etc/pam.d/password-auth
      when:
      - result_pam_faillock_is_enabled.found == 0

    - name: Lock Accounts Must Persist - Enable pam_faillock.so authfail editing PAM
        files
      ansible.builtin.lineinfile:
        path: '{{ item }}'
        line: auth        required      pam_faillock.so authfail
        insertbefore: ^auth.*required.*pam_deny\.so.*
        state: present
      loop:
      - /etc/pam.d/system-auth
      - /etc/pam.d/password-auth
      when:
      - result_pam_faillock_is_enabled.found == 0

    - name: Lock Accounts Must Persist - Enable pam_faillock.so account section editing
        PAM files
      ansible.builtin.lineinfile:
        path: '{{ item }}'
        line: account     required      pam_faillock.so
        insertbefore: ^account.*required.*pam_unix\.so.*
        state: present
      loop:
      - /etc/pam.d/system-auth
      - /etc/pam.d/password-auth
      when:
      - result_pam_faillock_is_enabled.found == 0
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - '"pam" in ansible_facts.packages'
    - not result_authselect_present.stat.exists
    tags:
    - DISA-STIG-OL09-00-003023
    - NIST-800-53-AC-7(a)
    - NIST-800-53-AC-7(b)
    - NIST-800-53-AC-7.1(ii)
    - accounts_passwords_pam_faillock_dir
    - configure_strategy
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

  - name: Lock Accounts Must Persist - Check the presence of /etc/security/faillock.conf
      file
    ansible.builtin.stat:
      path: /etc/security/faillock.conf
    register: result_faillock_conf_check
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - '"pam" in ansible_facts.packages'
    tags:
    - DISA-STIG-OL09-00-003023
    - NIST-800-53-AC-7(a)
    - NIST-800-53-AC-7(b)
    - NIST-800-53-AC-7.1(ii)
    - accounts_passwords_pam_faillock_dir
    - configure_strategy
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

  - name: Lock Accounts Must Persist - Ensure the pam_faillock.so dir parameter in
      /etc/security/faillock.conf
    ansible.builtin.lineinfile:
      path: /etc/security/faillock.conf
      regexp: ^\s*dir\s*=
      line: dir = {{ var_accounts_passwords_pam_faillock_dir }}
      state: present
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - '"pam" in ansible_facts.packages'
    - result_faillock_conf_check.stat.exists
    tags:
    - DISA-STIG-OL09-00-003023
    - NIST-800-53-AC-7(a)
    - NIST-800-53-AC-7(b)
    - NIST-800-53-AC-7.1(ii)
    - accounts_passwords_pam_faillock_dir
    - configure_strategy
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

  - name: Lock Accounts Must Persist - Ensure the pam_faillock.so dir parameter not
      in PAM files
    block:

    - name: Lock Accounts Must Persist - Check if /etc/pam.d/system-auth file is present
      ansible.builtin.stat:
        path: /etc/pam.d/system-auth
      register: result_pam_auth_file_present

    - name: Lock Accounts Must Persist - Check the proper remediation for the system
      block:

      - name: Lock Accounts Must Persist - Define the PAM file to be edited as a local
          fact
        ansible.builtin.set_fact:
          pam_file_path: /etc/pam.d/system-auth

      - name: Lock Accounts Must Persist - Check if system relies on authselect tool
        ansible.builtin.stat:
          path: /usr/bin/authselect
        register: result_authselect_present

      - name: Lock Accounts Must Persist - Ensure authselect custom profile is used
          if authselect is present
        block:

        - name: Lock Accounts Must Persist - Check integrity of authselect current
            profile
          ansible.builtin.command:
            cmd: authselect check
          register: result_authselect_check_cmd
          changed_when: false
          check_mode: false
          failed_when: false

        - name: Lock Accounts Must Persist - Informative message based on the authselect
            integrity check result
          ansible.builtin.assert:
            that:
            - ansible_check_mode or result_authselect_check_cmd.rc == 0
            fail_msg:
            - authselect integrity check failed. Remediation aborted!
            - This remediation could not be applied because an authselect profile
              was not selected or the selected profile is not intact.
            - It is not recommended to manually edit the PAM files when authselect
              tool is available.
            - In cases where the default authselect profile does not cover a specific
              demand, a custom authselect profile is recommended.
            success_msg:
            - authselect integrity check passed

        - name: Lock Accounts Must Persist - Get authselect current profile
          ansible.builtin.shell:
            cmd: authselect current -r | awk '{ print $1 }'
          register: result_authselect_profile
          changed_when: false
          when:
          - result_authselect_check_cmd is success

        - name: Lock Accounts Must Persist - Define the current authselect profile
            as a local fact
          ansible.builtin.set_fact:
            authselect_current_profile: '{{ result_authselect_profile.stdout }}'
            authselect_custom_profile: '{{ result_authselect_profile.stdout }}'
          when:
          - result_authselect_profile is not skipped
          - result_authselect_profile.stdout is match("custom/")

        - name: Lock Accounts Must Persist - Define the new authselect custom profile
            as a local fact
          ansible.builtin.set_fact:
            authselect_current_profile: '{{ result_authselect_profile.stdout }}'
            authselect_custom_profile: custom/hardening
          when:
          - result_authselect_profile is not skipped
          - result_authselect_profile.stdout is not match("custom/")

        - name: Lock Accounts Must Persist - Get authselect current features to also
            enable them in the custom profile
          ansible.builtin.shell:
            cmd: authselect current | tail -n+3 | awk '{ print $2 }'
          register: result_authselect_features
          changed_when: false
          check_mode: false
          when:
          - result_authselect_profile is not skipped
          - authselect_current_profile is not match("custom/")

        - name: Lock Accounts Must Persist - Check if any custom profile with the
            same name was already created
          ansible.builtin.stat:
            path: /etc/authselect/{{ authselect_custom_profile }}
          register: result_authselect_custom_profile_present
          changed_when: false
          when:
          - result_authselect_profile is not skipped
          - authselect_current_profile is not match("custom/")

        - name: Lock Accounts Must Persist - Create an authselect custom profile based
            on the current profile
          ansible.builtin.command:
            cmd: authselect create-profile hardening -b {{ authselect_current_profile
              }}
          when:
          - result_authselect_profile is not skipped
          - result_authselect_check_cmd is success
          - authselect_current_profile is not match("^(custom/|local)")
          - not result_authselect_custom_profile_present.stat.exists

        - name: Lock Accounts Must Persist - Create an authselect custom profile based
            on sssd profile
          ansible.builtin.command:
            cmd: authselect create-profile hardening -b sssd
          when:
          - result_authselect_profile is not skipped
          - result_authselect_check_cmd is success
          - authselect_current_profile is match("local")
          - not result_authselect_custom_profile_present.stat.exists

        - name: Lock Accounts Must Persist - Ensure authselect changes are applied
          ansible.builtin.command:
            cmd: authselect apply-changes -b --backup=before-hardening-custom-profile
          when:
          - result_authselect_check_cmd is success
          - result_authselect_profile is not skipped
          - authselect_current_profile is not match("custom/")
          - authselect_custom_profile is not match(authselect_current_profile)

        - name: Lock Accounts Must Persist - Ensure the authselect custom profile
            is selected
          ansible.builtin.command:
            cmd: authselect select {{ authselect_custom_profile }}
          register: result_pam_authselect_select_profile
          when:
          - result_authselect_check_cmd is success
          - result_authselect_profile is not skipped
          - authselect_current_profile is not match("custom/")
          - authselect_custom_profile is not match(authselect_current_profile)

        - name: Lock Accounts Must Persist - Restore the authselect features in the
            custom profile
          ansible.builtin.command:
            cmd: authselect enable-feature {{ item }}
          loop: '{{ result_authselect_features.stdout_lines }}'
          register: result_pam_authselect_restore_features
          when:
          - result_authselect_profile is not skipped
          - result_authselect_features is not skipped
          - result_pam_authselect_select_profile is not skipped

        - name: Lock Accounts Must Persist - Ensure authselect changes are applied
          ansible.builtin.command:
            cmd: authselect apply-changes -b --backup=after-hardening-custom-profile
          when:
          - result_authselect_check_cmd is success
          - result_authselect_profile is not skipped
          - result_pam_authselect_restore_features is not skipped

        - name: Lock Accounts Must Persist - Change the PAM file to be edited according
            to the custom authselect profile
          ansible.builtin.set_fact:
            pam_file_path: /etc/authselect/{{ authselect_custom_profile }}/{{ pam_file_path
              | basename }}
          when:
          - authselect_custom_profile is defined
        when:
        - result_authselect_present.stat.exists

      - name: Lock Accounts Must Persist - Define a fact for control already filtered
          in case filters are used
        ansible.builtin.set_fact:
          pam_module_control: ''

      - name: Lock Accounts Must Persist - Check if {{ pam_file_path }} file is present
        ansible.builtin.stat:
          path: '{{ pam_file_path }}'
        register: result_pam_file_present

      - name: Lock Accounts Must Persist - Ensure the "dir" option from "pam_faillock.so"
          is not present in {{ pam_file_path }}
        ansible.builtin.replace:
          dest: '{{ pam_file_path }}'
          regexp: (.*auth.*pam_faillock.so.*)\bdir\b=?[0-9a-zA-Z]*(.*)
          replace: \1\2
        register: result_pam_option_removal
        when:
        - result_pam_file_present.stat.exists

      - name: Lock Accounts Must Persist - Ensure authselect changes are applied
        ansible.builtin.command:
          cmd: authselect apply-changes -b
        when:
        - result_authselect_present.stat.exists
        - result_pam_option_removal is changed
      when:
      - result_pam_auth_file_present.stat.exists

    - name: Lock Accounts Must Persist - Check if /etc/pam.d/password-auth file is
        present
      ansible.builtin.stat:
        path: /etc/pam.d/password-auth
      register: result_pam_password_auth_file_present

    - name: Lock Accounts Must Persist - Check the proper remediation for the system
      block:

      - name: Lock Accounts Must Persist - Define the PAM file to be edited as a local
          fact
        ansible.builtin.set_fact:
          pam_file_path: /etc/pam.d/password-auth

      - name: Lock Accounts Must Persist - Check if system relies on authselect tool
        ansible.builtin.stat:
          path: /usr/bin/authselect
        register: result_authselect_present

      - name: Lock Accounts Must Persist - Ensure authselect custom profile is used
          if authselect is present
        block:

        - name: Lock Accounts Must Persist - Check integrity of authselect current
            profile
          ansible.builtin.command:
            cmd: authselect check
          register: result_authselect_check_cmd
          changed_when: false
          check_mode: false
          failed_when: false

        - name: Lock Accounts Must Persist - Informative message based on the authselect
            integrity check result
          ansible.builtin.assert:
            that:
            - ansible_check_mode or result_authselect_check_cmd.rc == 0
            fail_msg:
            - authselect integrity check failed. Remediation aborted!
            - This remediation could not be applied because an authselect profile
              was not selected or the selected profile is not intact.
            - It is not recommended to manually edit the PAM files when authselect
              tool is available.
            - In cases where the default authselect profile does not cover a specific
              demand, a custom authselect profile is recommended.
            success_msg:
            - authselect integrity check passed

        - name: Lock Accounts Must Persist - Get authselect current profile
          ansible.builtin.shell:
            cmd: authselect current -r | awk '{ print $1 }'
          register: result_authselect_profile
          changed_when: false
          when:
          - result_authselect_check_cmd is success

        - name: Lock Accounts Must Persist - Define the current authselect profile
            as a local fact
          ansible.builtin.set_fact:
            authselect_current_profile: '{{ result_authselect_profile.stdout }}'
            authselect_custom_profile: '{{ result_authselect_profile.stdout }}'
          when:
          - result_authselect_profile is not skipped
          - result_authselect_profile.stdout is match("custom/")

        - name: Lock Accounts Must Persist - Define the new authselect custom profile
            as a local fact
          ansible.builtin.set_fact:
            authselect_current_profile: '{{ result_authselect_profile.stdout }}'
            authselect_custom_profile: custom/hardening
          when:
          - result_authselect_profile is not skipped
          - result_authselect_profile.stdout is not match("custom/")

        - name: Lock Accounts Must Persist - Get authselect current features to also
            enable them in the custom profile
          ansible.builtin.shell:
            cmd: authselect current | tail -n+3 | awk '{ print $2 }'
          register: result_authselect_features
          changed_when: false
          check_mode: false
          when:
          - result_authselect_profile is not skipped
          - authselect_current_profile is not match("custom/")

        - name: Lock Accounts Must Persist - Check if any custom profile with the
            same name was already created
          ansible.builtin.stat:
            path: /etc/authselect/{{ authselect_custom_profile }}
          register: result_authselect_custom_profile_present
          changed_when: false
          when:
          - result_authselect_profile is not skipped
          - authselect_current_profile is not match("custom/")

        - name: Lock Accounts Must Persist - Create an authselect custom profile based
            on the current profile
          ansible.builtin.command:
            cmd: authselect create-profile hardening -b {{ authselect_current_profile
              }}
          when:
          - result_authselect_profile is not skipped
          - result_authselect_check_cmd is success
          - authselect_current_profile is not match("^(custom/|local)")
          - not result_authselect_custom_profile_present.stat.exists

        - name: Lock Accounts Must Persist - Create an authselect custom profile based
            on sssd profile
          ansible.builtin.command:
            cmd: authselect create-profile hardening -b sssd
          when:
          - result_authselect_profile is not skipped
          - result_authselect_check_cmd is success
          - authselect_current_profile is match("local")
          - not result_authselect_custom_profile_present.stat.exists

        - name: Lock Accounts Must Persist - Ensure authselect changes are applied
          ansible.builtin.command:
            cmd: authselect apply-changes -b --backup=before-hardening-custom-profile
          when:
          - result_authselect_check_cmd is success
          - result_authselect_profile is not skipped
          - authselect_current_profile is not match("custom/")
          - authselect_custom_profile is not match(authselect_current_profile)

        - name: Lock Accounts Must Persist - Ensure the authselect custom profile
            is selected
          ansible.builtin.command:
            cmd: authselect select {{ authselect_custom_profile }}
          register: result_pam_authselect_select_profile
          when:
          - result_authselect_check_cmd is success
          - result_authselect_profile is not skipped
          - authselect_current_profile is not match("custom/")
          - authselect_custom_profile is not match(authselect_current_profile)

        - name: Lock Accounts Must Persist - Restore the authselect features in the
            custom profile
          ansible.builtin.command:
            cmd: authselect enable-feature {{ item }}
          loop: '{{ result_authselect_features.stdout_lines }}'
          register: result_pam_authselect_restore_features
          when:
          - result_authselect_profile is not skipped
          - result_authselect_features is not skipped
          - result_pam_authselect_select_profile is not skipped

        - name: Lock Accounts Must Persist - Ensure authselect changes are applied
          ansible.builtin.command:
            cmd: authselect apply-changes -b --backup=after-hardening-custom-profile
          when:
          - result_authselect_check_cmd is success
          - result_authselect_profile is not skipped
          - result_pam_authselect_restore_features is not skipped

        - name: Lock Accounts Must Persist - Change the PAM file to be edited according
            to the custom authselect profile
          ansible.builtin.set_fact:
            pam_file_path: /etc/authselect/{{ authselect_custom_profile }}/{{ pam_file_path
              | basename }}
          when:
          - authselect_custom_profile is defined
        when:
        - result_authselect_present.stat.exists

      - name: Lock Accounts Must Persist - Define a fact for control already filtered
          in case filters are used
        ansible.builtin.set_fact:
          pam_module_control: ''

      - name: Lock Accounts Must Persist - Check if {{ pam_file_path }} file is present
        ansible.builtin.stat:
          path: '{{ pam_file_path }}'
        register: result_pam_file_present

      - name: Lock Accounts Must Persist - Ensure the "dir" option from "pam_faillock.so"
          is not present in {{ pam_file_path }}
        ansible.builtin.replace:
          dest: '{{ pam_file_path }}'
          regexp: (.*auth.*pam_faillock.so.*)\bdir\b=?[0-9a-zA-Z]*(.*)
          replace: \1\2
        register: result_pam_option_removal
        when:
        - result_pam_file_present.stat.exists

      - name: Lock Accounts Must Persist - Ensure authselect changes are applied
        ansible.builtin.command:
          cmd: authselect apply-changes -b
        when:
        - result_authselect_present.stat.exists
        - result_pam_option_removal is changed
      when:
      - result_pam_password_auth_file_present.stat.exists
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - '"pam" in ansible_facts.packages'
    - result_faillock_conf_check.stat.exists
    tags:
    - DISA-STIG-OL09-00-003023
    - NIST-800-53-AC-7(a)
    - NIST-800-53-AC-7(b)
    - NIST-800-53-AC-7.1(ii)
    - accounts_passwords_pam_faillock_dir
    - configure_strategy
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

  - name: Lock Accounts Must Persist - Ensure the pam_faillock.so dir parameter in
      PAM files
    block:

    - name: Lock Accounts Must Persist - Check if pam_faillock.so dir parameter is
        already enabled in pam files
      ansible.builtin.lineinfile:
        path: /etc/pam.d/system-auth
        regexp: .*auth.*pam_faillock\.so (preauth|authfail).*dir
        state: absent
      check_mode: true
      changed_when: false
      register: result_pam_faillock_dir_parameter_is_present

    - name: Lock Accounts Must Persist - Ensure the inclusion of pam_faillock.so preauth
        dir parameter in auth section
      ansible.builtin.lineinfile:
        path: '{{ item }}'
        backrefs: true
        regexp: (^\s*auth\s+)([\w\[].*\b)(\s+pam_faillock.so preauth.*)
        line: \1required\3 dir={{ var_accounts_passwords_pam_faillock_dir }}
        state: present
      loop:
      - /etc/pam.d/system-auth
      - /etc/pam.d/password-auth
      when:
      - result_pam_faillock_dir_parameter_is_present.found == 0

    - name: Lock Accounts Must Persist - Ensure the inclusion of pam_faillock.so authfail
        dir parameter in auth section
      ansible.builtin.lineinfile:
        path: '{{ item }}'
        backrefs: true
        regexp: (^\s*auth\s+)([\w\[].*\b)(\s+pam_faillock.so authfail.*)
        line: \1required\3 dir={{ var_accounts_passwords_pam_faillock_dir }}
        state: present
      loop:
      - /etc/pam.d/system-auth
      - /etc/pam.d/password-auth
      when:
      - result_pam_faillock_dir_parameter_is_present.found == 0

    - name: Lock Accounts Must Persist - Ensure the desired value for pam_faillock.so
        preauth dir parameter in auth section
      ansible.builtin.lineinfile:
        path: '{{ item }}'
        backrefs: true
        regexp: (^\s*auth\s+)([\w\[].*\b)(\s+pam_faillock.so preauth.*)(dir)=[0-9]+(.*)
        line: \1required\3\4={{ var_accounts_passwords_pam_faillock_dir }}\5
        state: present
      loop:
      - /etc/pam.d/system-auth
      - /etc/pam.d/password-auth
      when:
      - result_pam_faillock_dir_parameter_is_present.found > 0

    - name: Lock Accounts Must Persist - Ensure the desired value for pam_faillock.so
        authfail dir parameter in auth section
      ansible.builtin.lineinfile:
        path: '{{ item }}'
        backrefs: true
        regexp: (^\s*auth\s+)([\w\[].*\b)(\s+pam_faillock.so authfail.*)(dir)=[0-9]+(.*)
        line: \1required\3\4={{ var_accounts_passwords_pam_faillock_dir }}\5
        state: present
      loop:
      - /etc/pam.d/system-auth
      - /etc/pam.d/password-auth
      when:
      - result_pam_faillock_dir_parameter_is_present.found > 0
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - '"pam" in ansible_facts.packages'
    - not result_faillock_conf_check.stat.exists
    tags:
    - DISA-STIG-OL09-00-003023
    - NIST-800-53-AC-7(a)
    - NIST-800-53-AC-7(b)
    - NIST-800-53-AC-7.1(ii)
    - accounts_passwords_pam_faillock_dir
    - configure_strategy
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

  - name: Lock Accounts Must Persist - Create the faillock directory if it does not
      exist
    ansible.builtin.file:
      path: '{{ var_accounts_passwords_pam_faillock_dir }}'
      state: directory
      setype: faillog_t
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - '"pam" in ansible_facts.packages'
    tags:
    - DISA-STIG-OL09-00-003023
    - NIST-800-53-AC-7(a)
    - NIST-800-53-AC-7(b)
    - NIST-800-53-AC-7.1(ii)
    - accounts_passwords_pam_faillock_dir
    - configure_strategy
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

  - name: Lock Accounts Must Persist - Get SELinux context for faillock directory
    ansible.builtin.command:
      cmd: ls -dZ {{ var_accounts_passwords_pam_faillock_dir }}
    register: faillock_selinux_context
    changed_when: false
    check_mode: false
    failed_when: false
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - '"pam" in ansible_facts.packages'
    tags:
    - DISA-STIG-OL09-00-003023
    - NIST-800-53-AC-7(a)
    - NIST-800-53-AC-7(b)
    - NIST-800-53-AC-7.1(ii)
    - accounts_passwords_pam_faillock_dir
    - configure_strategy
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

  - name: Lock Accounts Must Persist - Ensure SELinux file context is permanently
      set
    ansible.builtin.command:
      cmd: semanage fcontext -a -t faillog_t "{{ var_accounts_passwords_pam_faillock_dir
        }}(/.*)?"
    register: result_accounts_passwords_pam_faillock_dir_semanage
    failed_when: false
    changed_when:
    - result_accounts_passwords_pam_faillock_dir_semanage.rc == 0
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - '"pam" in ansible_facts.packages'
    - '"faillog_t" not in faillock_selinux_context.stdout'
    tags:
    - DISA-STIG-OL09-00-003023
    - NIST-800-53-AC-7(a)
    - NIST-800-53-AC-7(b)
    - NIST-800-53-AC-7.1(ii)
    - accounts_passwords_pam_faillock_dir
    - configure_strategy
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

  - name: Lock Accounts Must Persist - Ensure SELinux file context is applied
    ansible.builtin.command:
      cmd: restorecon -R "{{ var_accounts_passwords_pam_faillock_dir }}"
    register: result_accounts_passwords_pam_faillock_dir_restorecon
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - '"pam" in ansible_facts.packages'
    - '"faillog_t" not in faillock_selinux_context.stdout'
    tags:
    - DISA-STIG-OL09-00-003023
    - NIST-800-53-AC-7(a)
    - NIST-800-53-AC-7(b)
    - NIST-800-53-AC-7.1(ii)
    - accounts_passwords_pam_faillock_dir
    - configure_strategy
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

  - name: Set Interval For Counting Failed Password Attempts - Check if system relies
      on authselect tool
    ansible.builtin.stat:
      path: /usr/bin/authselect
    register: result_authselect_present
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - '"pam" in ansible_facts.packages'
    tags:
    - DISA-STIG-OL09-00-002416
    - NIST-800-53-AC-7(a)
    - NIST-800-53-CM-6(a)
    - accounts_passwords_pam_faillock_interval
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Set Interval For Counting Failed Password Attempts - Remediation where authselect
      tool is present
    block:

    - name: Set Interval For Counting Failed Password Attempts - Check integrity of
        authselect current profile
      ansible.builtin.command:
        cmd: authselect check
      register: result_authselect_check_cmd
      changed_when: false
      check_mode: false
      failed_when: false

    - name: Set Interval For Counting Failed Password Attempts - Informative message
        based on the authselect integrity check result
      ansible.builtin.assert:
        that:
        - ansible_check_mode or result_authselect_check_cmd.rc == 0
        fail_msg:
        - authselect integrity check failed. Remediation aborted!
        - This remediation could not be applied because an authselect profile was
          not selected or the selected profile is not intact.
        - It is not recommended to manually edit the PAM files when authselect tool
          is available.
        - In cases where the default authselect profile does not cover a specific
          demand, a custom authselect profile is recommended.
        success_msg:
        - authselect integrity check passed

    - name: Set Interval For Counting Failed Password Attempts - Get authselect current
        features
      ansible.builtin.shell:
        cmd: authselect current | tail -n+3 | awk '{ print $2 }'
      register: result_authselect_features
      changed_when: false
      check_mode: false
      when:
      - result_authselect_check_cmd is success

    - name: Set Interval For Counting Failed Password Attempts - Ensure "with-faillock"
        feature is enabled using authselect tool
      ansible.builtin.command:
        cmd: authselect enable-feature with-faillock
      register: result_authselect_enable_feature_cmd
      when:
      - result_authselect_check_cmd is success
      - result_authselect_features.stdout is not search("with-faillock")

    - name: Set Interval For Counting Failed Password Attempts - Ensure authselect
        changes are applied
      ansible.builtin.command:
        cmd: authselect apply-changes -b
      when:
      - result_authselect_enable_feature_cmd is not skipped
      - result_authselect_enable_feature_cmd is success
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - '"pam" in ansible_facts.packages'
    - result_authselect_present.stat.exists
    tags:
    - DISA-STIG-OL09-00-002416
    - NIST-800-53-AC-7(a)
    - NIST-800-53-CM-6(a)
    - accounts_passwords_pam_faillock_interval
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Set Interval For Counting Failed Password Attempts - Remediation where authselect
      tool is not present
    block:

    - name: Set Interval For Counting Failed Password Attempts - Check if pam_faillock.so
        is already enabled
      ansible.builtin.lineinfile:
        path: /etc/pam.d/system-auth
        regexp: .*auth.*pam_faillock\.so (preauth|authfail)
        state: absent
      check_mode: true
      changed_when: false
      register: result_pam_faillock_is_enabled

    - name: Set Interval For Counting Failed Password Attempts - Enable pam_faillock.so
        preauth editing PAM files
      ansible.builtin.lineinfile:
        path: '{{ item }}'
        line: auth        required      pam_faillock.so preauth
        insertbefore: ^auth.*sufficient.*pam_unix\.so.*
        state: present
      loop:
      - /etc/pam.d/system-auth
      - /etc/pam.d/password-auth
      when:
      - result_pam_faillock_is_enabled.found == 0

    - name: Set Interval For Counting Failed Password Attempts - Enable pam_faillock.so
        authfail editing PAM files
      ansible.builtin.lineinfile:
        path: '{{ item }}'
        line: auth        required      pam_faillock.so authfail
        insertbefore: ^auth.*required.*pam_deny\.so.*
        state: present
      loop:
      - /etc/pam.d/system-auth
      - /etc/pam.d/password-auth
      when:
      - result_pam_faillock_is_enabled.found == 0

    - name: Set Interval For Counting Failed Password Attempts - Enable pam_faillock.so
        account section editing PAM files
      ansible.builtin.lineinfile:
        path: '{{ item }}'
        line: account     required      pam_faillock.so
        insertbefore: ^account.*required.*pam_unix\.so.*
        state: present
      loop:
      - /etc/pam.d/system-auth
      - /etc/pam.d/password-auth
      when:
      - result_pam_faillock_is_enabled.found == 0
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - '"pam" in ansible_facts.packages'
    - not result_authselect_present.stat.exists
    tags:
    - DISA-STIG-OL09-00-002416
    - NIST-800-53-AC-7(a)
    - NIST-800-53-CM-6(a)
    - accounts_passwords_pam_faillock_interval
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Set Interval For Counting Failed Password Attempts - Check the presence
      of /etc/security/faillock.conf file
    ansible.builtin.stat:
      path: /etc/security/faillock.conf
    register: result_faillock_conf_check
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - '"pam" in ansible_facts.packages'
    tags:
    - DISA-STIG-OL09-00-002416
    - NIST-800-53-AC-7(a)
    - NIST-800-53-CM-6(a)
    - accounts_passwords_pam_faillock_interval
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Set Interval For Counting Failed Password Attempts - Ensure the pam_faillock.so
      fail_interval parameter in /etc/security/faillock.conf
    ansible.builtin.lineinfile:
      path: /etc/security/faillock.conf
      regexp: ^\s*fail_interval\s*=
      line: fail_interval = {{ var_accounts_passwords_pam_faillock_fail_interval }}
      state: present
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - '"pam" in ansible_facts.packages'
    - result_faillock_conf_check.stat.exists
    tags:
    - DISA-STIG-OL09-00-002416
    - NIST-800-53-AC-7(a)
    - NIST-800-53-CM-6(a)
    - accounts_passwords_pam_faillock_interval
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Set Interval For Counting Failed Password Attempts - Ensure the pam_faillock.so
      fail_interval parameter not in PAM files
    block:

    - name: Set Interval For Counting Failed Password Attempts - Check if /etc/pam.d/system-auth
        file is present
      ansible.builtin.stat:
        path: /etc/pam.d/system-auth
      register: result_pam_auth_file_present

    - name: Set Interval For Counting Failed Password Attempts - Check the proper
        remediation for the system
      block:

      - name: Set Interval For Counting Failed Password Attempts - Define the PAM
          file to be edited as a local fact
        ansible.builtin.set_fact:
          pam_file_path: /etc/pam.d/system-auth

      - name: Set Interval For Counting Failed Password Attempts - Check if system
          relies on authselect tool
        ansible.builtin.stat:
          path: /usr/bin/authselect
        register: result_authselect_present

      - name: Set Interval For Counting Failed Password Attempts - Ensure authselect
          custom profile is used if authselect is present
        block:

        - name: Set Interval For Counting Failed Password Attempts - Check integrity
            of authselect current profile
          ansible.builtin.command:
            cmd: authselect check
          register: result_authselect_check_cmd
          changed_when: false
          check_mode: false
          failed_when: false

        - name: Set Interval For Counting Failed Password Attempts - Informative message
            based on the authselect integrity check result
          ansible.builtin.assert:
            that:
            - ansible_check_mode or result_authselect_check_cmd.rc == 0
            fail_msg:
            - authselect integrity check failed. Remediation aborted!
            - This remediation could not be applied because an authselect profile
              was not selected or the selected profile is not intact.
            - It is not recommended to manually edit the PAM files when authselect
              tool is available.
            - In cases where the default authselect profile does not cover a specific
              demand, a custom authselect profile is recommended.
            success_msg:
            - authselect integrity check passed

        - name: Set Interval For Counting Failed Password Attempts - Get authselect
            current profile
          ansible.builtin.shell:
            cmd: authselect current -r | awk '{ print $1 }'
          register: result_authselect_profile
          changed_when: false
          when:
          - result_authselect_check_cmd is success

        - name: Set Interval For Counting Failed Password Attempts - Define the current
            authselect profile as a local fact
          ansible.builtin.set_fact:
            authselect_current_profile: '{{ result_authselect_profile.stdout }}'
            authselect_custom_profile: '{{ result_authselect_profile.stdout }}'
          when:
          - result_authselect_profile is not skipped
          - result_authselect_profile.stdout is match("custom/")

        - name: Set Interval For Counting Failed Password Attempts - Define the new
            authselect custom profile as a local fact
          ansible.builtin.set_fact:
            authselect_current_profile: '{{ result_authselect_profile.stdout }}'
            authselect_custom_profile: custom/hardening
          when:
          - result_authselect_profile is not skipped
          - result_authselect_profile.stdout is not match("custom/")

        - name: Set Interval For Counting Failed Password Attempts - Get authselect
            current features to also enable them in the custom profile
          ansible.builtin.shell:
            cmd: authselect current | tail -n+3 | awk '{ print $2 }'
          register: result_authselect_features
          changed_when: false
          check_mode: false
          when:
          - result_authselect_profile is not skipped
          - authselect_current_profile is not match("custom/")

        - name: Set Interval For Counting Failed Password Attempts - Check if any
            custom profile with the same name was already created
          ansible.builtin.stat:
            path: /etc/authselect/{{ authselect_custom_profile }}
          register: result_authselect_custom_profile_present
          changed_when: false
          when:
          - result_authselect_profile is not skipped
          - authselect_current_profile is not match("custom/")

        - name: Set Interval For Counting Failed Password Attempts - Create an authselect
            custom profile based on the current profile
          ansible.builtin.command:
            cmd: authselect create-profile hardening -b {{ authselect_current_profile
              }}
          when:
          - result_authselect_profile is not skipped
          - result_authselect_check_cmd is success
          - authselect_current_profile is not match("^(custom/|local)")
          - not result_authselect_custom_profile_present.stat.exists

        - name: Set Interval For Counting Failed Password Attempts - Create an authselect
            custom profile based on sssd profile
          ansible.builtin.command:
            cmd: authselect create-profile hardening -b sssd
          when:
          - result_authselect_profile is not skipped
          - result_authselect_check_cmd is success
          - authselect_current_profile is match("local")
          - not result_authselect_custom_profile_present.stat.exists

        - name: Set Interval For Counting Failed Password Attempts - Ensure authselect
            changes are applied
          ansible.builtin.command:
            cmd: authselect apply-changes -b --backup=before-hardening-custom-profile
          when:
          - result_authselect_check_cmd is success
          - result_authselect_profile is not skipped
          - authselect_current_profile is not match("custom/")
          - authselect_custom_profile is not match(authselect_current_profile)

        - name: Set Interval For Counting Failed Password Attempts - Ensure the authselect
            custom profile is selected
          ansible.builtin.command:
            cmd: authselect select {{ authselect_custom_profile }}
          register: result_pam_authselect_select_profile
          when:
          - result_authselect_check_cmd is success
          - result_authselect_profile is not skipped
          - authselect_current_profile is not match("custom/")
          - authselect_custom_profile is not match(authselect_current_profile)

        - name: Set Interval For Counting Failed Password Attempts - Restore the authselect
            features in the custom profile
          ansible.builtin.command:
            cmd: authselect enable-feature {{ item }}
          loop: '{{ result_authselect_features.stdout_lines }}'
          register: result_pam_authselect_restore_features
          when:
          - result_authselect_profile is not skipped
          - result_authselect_features is not skipped
          - result_pam_authselect_select_profile is not skipped

        - name: Set Interval For Counting Failed Password Attempts - Ensure authselect
            changes are applied
          ansible.builtin.command:
            cmd: authselect apply-changes -b --backup=after-hardening-custom-profile
          when:
          - result_authselect_check_cmd is success
          - result_authselect_profile is not skipped
          - result_pam_authselect_restore_features is not skipped

        - name: Set Interval For Counting Failed Password Attempts - Change the PAM
            file to be edited according to the custom authselect profile
          ansible.builtin.set_fact:
            pam_file_path: /etc/authselect/{{ authselect_custom_profile }}/{{ pam_file_path
              | basename }}
          when:
          - authselect_custom_profile is defined
        when:
        - result_authselect_present.stat.exists

      - name: Set Interval For Counting Failed Password Attempts - Define a fact for
          control already filtered in case filters are used
        ansible.builtin.set_fact:
          pam_module_control: ''

      - name: Set Interval For Counting Failed Password Attempts - Check if {{ pam_file_path
          }} file is present
        ansible.builtin.stat:
          path: '{{ pam_file_path }}'
        register: result_pam_file_present

      - name: Set Interval For Counting Failed Password Attempts - Ensure the "fail_interval"
          option from "pam_faillock.so" is not present in {{ pam_file_path }}
        ansible.builtin.replace:
          dest: '{{ pam_file_path }}'
          regexp: (.*auth.*pam_faillock.so.*)\bfail_interval\b=?[0-9a-zA-Z]*(.*)
          replace: \1\2
        register: result_pam_option_removal
        when:
        - result_pam_file_present.stat.exists

      - name: Set Interval For Counting Failed Password Attempts - Ensure authselect
          changes are applied
        ansible.builtin.command:
          cmd: authselect apply-changes -b
        when:
        - result_authselect_present.stat.exists
        - result_pam_option_removal is changed
      when:
      - result_pam_auth_file_present.stat.exists

    - name: Set Interval For Counting Failed Password Attempts - Check if /etc/pam.d/password-auth
        file is present
      ansible.builtin.stat:
        path: /etc/pam.d/password-auth
      register: result_pam_password_auth_file_present

    - name: Set Interval For Counting Failed Password Attempts - Check the proper
        remediation for the system
      block:

      - name: Set Interval For Counting Failed Password Attempts - Define the PAM
          file to be edited as a local fact
        ansible.builtin.set_fact:
          pam_file_path: /etc/pam.d/password-auth

      - name: Set Interval For Counting Failed Password Attempts - Check if system
          relies on authselect tool
        ansible.builtin.stat:
          path: /usr/bin/authselect
        register: result_authselect_present

      - name: Set Interval For Counting Failed Password Attempts - Ensure authselect
          custom profile is used if authselect is present
        block:

        - name: Set Interval For Counting Failed Password Attempts - Check integrity
            of authselect current profile
          ansible.builtin.command:
            cmd: authselect check
          register: result_authselect_check_cmd
          changed_when: false
          check_mode: false
          failed_when: false

        - name: Set Interval For Counting Failed Password Attempts - Informative message
            based on the authselect integrity check result
          ansible.builtin.assert:
            that:
            - ansible_check_mode or result_authselect_check_cmd.rc == 0
            fail_msg:
            - authselect integrity check failed. Remediation aborted!
            - This remediation could not be applied because an authselect profile
              was not selected or the selected profile is not intact.
            - It is not recommended to manually edit the PAM files when authselect
              tool is available.
            - In cases where the default authselect profile does not cover a specific
              demand, a custom authselect profile is recommended.
            success_msg:
            - authselect integrity check passed

        - name: Set Interval For Counting Failed Password Attempts - Get authselect
            current profile
          ansible.builtin.shell:
            cmd: authselect current -r | awk '{ print $1 }'
          register: result_authselect_profile
          changed_when: false
          when:
          - result_authselect_check_cmd is success

        - name: Set Interval For Counting Failed Password Attempts - Define the current
            authselect profile as a local fact
          ansible.builtin.set_fact:
            authselect_current_profile: '{{ result_authselect_profile.stdout }}'
            authselect_custom_profile: '{{ result_authselect_profile.stdout }}'
          when:
          - result_authselect_profile is not skipped
          - result_authselect_profile.stdout is match("custom/")

        - name: Set Interval For Counting Failed Password Attempts - Define the new
            authselect custom profile as a local fact
          ansible.builtin.set_fact:
            authselect_current_profile: '{{ result_authselect_profile.stdout }}'
            authselect_custom_profile: custom/hardening
          when:
          - result_authselect_profile is not skipped
          - result_authselect_profile.stdout is not match("custom/")

        - name: Set Interval For Counting Failed Password Attempts - Get authselect
            current features to also enable them in the custom profile
          ansible.builtin.shell:
            cmd: authselect current | tail -n+3 | awk '{ print $2 }'
          register: result_authselect_features
          changed_when: false
          check_mode: false
          when:
          - result_authselect_profile is not skipped
          - authselect_current_profile is not match("custom/")

        - name: Set Interval For Counting Failed Password Attempts - Check if any
            custom profile with the same name was already created
          ansible.builtin.stat:
            path: /etc/authselect/{{ authselect_custom_profile }}
          register: result_authselect_custom_profile_present
          changed_when: false
          when:
          - result_authselect_profile is not skipped
          - authselect_current_profile is not match("custom/")

        - name: Set Interval For Counting Failed Password Attempts - Create an authselect
            custom profile based on the current profile
          ansible.builtin.command:
            cmd: authselect create-profile hardening -b {{ authselect_current_profile
              }}
          when:
          - result_authselect_profile is not skipped
          - result_authselect_check_cmd is success
          - authselect_current_profile is not match("^(custom/|local)")
          - not result_authselect_custom_profile_present.stat.exists

        - name: Set Interval For Counting Failed Password Attempts - Create an authselect
            custom profile based on sssd profile
          ansible.builtin.command:
            cmd: authselect create-profile hardening -b sssd
          when:
          - result_authselect_profile is not skipped
          - result_authselect_check_cmd is success
          - authselect_current_profile is match("local")
          - not result_authselect_custom_profile_present.stat.exists

        - name: Set Interval For Counting Failed Password Attempts - Ensure authselect
            changes are applied
          ansible.builtin.command:
            cmd: authselect apply-changes -b --backup=before-hardening-custom-profile
          when:
          - result_authselect_check_cmd is success
          - result_authselect_profile is not skipped
          - authselect_current_profile is not match("custom/")
          - authselect_custom_profile is not match(authselect_current_profile)

        - name: Set Interval For Counting Failed Password Attempts - Ensure the authselect
            custom profile is selected
          ansible.builtin.command:
            cmd: authselect select {{ authselect_custom_profile }}
          register: result_pam_authselect_select_profile
          when:
          - result_authselect_check_cmd is success
          - result_authselect_profile is not skipped
          - authselect_current_profile is not match("custom/")
          - authselect_custom_profile is not match(authselect_current_profile)

        - name: Set Interval For Counting Failed Password Attempts - Restore the authselect
            features in the custom profile
          ansible.builtin.command:
            cmd: authselect enable-feature {{ item }}
          loop: '{{ result_authselect_features.stdout_lines }}'
          register: result_pam_authselect_restore_features
          when:
          - result_authselect_profile is not skipped
          - result_authselect_features is not skipped
          - result_pam_authselect_select_profile is not skipped

        - name: Set Interval For Counting Failed Password Attempts - Ensure authselect
            changes are applied
          ansible.builtin.command:
            cmd: authselect apply-changes -b --backup=after-hardening-custom-profile
          when:
          - result_authselect_check_cmd is success
          - result_authselect_profile is not skipped
          - result_pam_authselect_restore_features is not skipped

        - name: Set Interval For Counting Failed Password Attempts - Change the PAM
            file to be edited according to the custom authselect profile
          ansible.builtin.set_fact:
            pam_file_path: /etc/authselect/{{ authselect_custom_profile }}/{{ pam_file_path
              | basename }}
          when:
          - authselect_custom_profile is defined
        when:
        - result_authselect_present.stat.exists

      - name: Set Interval For Counting Failed Password Attempts - Define a fact for
          control already filtered in case filters are used
        ansible.builtin.set_fact:
          pam_module_control: ''

      - name: Set Interval For Counting Failed Password Attempts - Check if {{ pam_file_path
          }} file is present
        ansible.builtin.stat:
          path: '{{ pam_file_path }}'
        register: result_pam_file_present

      - name: Set Interval For Counting Failed Password Attempts - Ensure the "fail_interval"
          option from "pam_faillock.so" is not present in {{ pam_file_path }}
        ansible.builtin.replace:
          dest: '{{ pam_file_path }}'
          regexp: (.*auth.*pam_faillock.so.*)\bfail_interval\b=?[0-9a-zA-Z]*(.*)
          replace: \1\2
        register: result_pam_option_removal
        when:
        - result_pam_file_present.stat.exists

      - name: Set Interval For Counting Failed Password Attempts - Ensure authselect
          changes are applied
        ansible.builtin.command:
          cmd: authselect apply-changes -b
        when:
        - result_authselect_present.stat.exists
        - result_pam_option_removal is changed
      when:
      - result_pam_password_auth_file_present.stat.exists
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - '"pam" in ansible_facts.packages'
    - result_faillock_conf_check.stat.exists
    tags:
    - DISA-STIG-OL09-00-002416
    - NIST-800-53-AC-7(a)
    - NIST-800-53-CM-6(a)
    - accounts_passwords_pam_faillock_interval
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Set Interval For Counting Failed Password Attempts - Ensure the pam_faillock.so
      fail_interval parameter in PAM files
    block:

    - name: Set Interval For Counting Failed Password Attempts - Check if pam_faillock.so
        fail_interval parameter is already enabled in pam files
      ansible.builtin.lineinfile:
        path: /etc/pam.d/system-auth
        regexp: .*auth.*pam_faillock\.so (preauth|authfail).*fail_interval
        state: absent
      check_mode: true
      changed_when: false
      register: result_pam_faillock_fail_interval_parameter_is_present

    - name: Set Interval For Counting Failed Password Attempts - Ensure the inclusion
        of pam_faillock.so preauth fail_interval parameter in auth section
      ansible.builtin.lineinfile:
        path: '{{ item }}'
        backrefs: true
        regexp: (^\s*auth\s+)([\w\[].*\b)(\s+pam_faillock.so preauth.*)
        line: \1required\3 fail_interval={{ var_accounts_passwords_pam_faillock_fail_interval
          }}
        state: present
      loop:
      - /etc/pam.d/system-auth
      - /etc/pam.d/password-auth
      when:
      - result_pam_faillock_fail_interval_parameter_is_present.found == 0

    - name: Set Interval For Counting Failed Password Attempts - Ensure the inclusion
        of pam_faillock.so authfail fail_interval parameter in auth section
      ansible.builtin.lineinfile:
        path: '{{ item }}'
        backrefs: true
        regexp: (^\s*auth\s+)([\w\[].*\b)(\s+pam_faillock.so authfail.*)
        line: \1required\3 fail_interval={{ var_accounts_passwords_pam_faillock_fail_interval
          }}
        state: present
      loop:
      - /etc/pam.d/system-auth
      - /etc/pam.d/password-auth
      when:
      - result_pam_faillock_fail_interval_parameter_is_present.found == 0

    - name: Set Interval For Counting Failed Password Attempts - Ensure the desired
        value for pam_faillock.so preauth fail_interval parameter in auth section
      ansible.builtin.lineinfile:
        path: '{{ item }}'
        backrefs: true
        regexp: (^\s*auth\s+)([\w\[].*\b)(\s+pam_faillock.so preauth.*)(fail_interval)=[0-9]+(.*)
        line: \1required\3\4={{ var_accounts_passwords_pam_faillock_fail_interval
          }}\5
        state: present
      loop:
      - /etc/pam.d/system-auth
      - /etc/pam.d/password-auth
      when:
      - result_pam_faillock_fail_interval_parameter_is_present.found > 0

    - name: Set Interval For Counting Failed Password Attempts - Ensure the desired
        value for pam_faillock.so authfail fail_interval parameter in auth section
      ansible.builtin.lineinfile:
        path: '{{ item }}'
        backrefs: true
        regexp: (^\s*auth\s+)([\w\[].*\b)(\s+pam_faillock.so authfail.*)(fail_interval)=[0-9]+(.*)
        line: \1required\3\4={{ var_accounts_passwords_pam_faillock_fail_interval
          }}\5
        state: present
      loop:
      - /etc/pam.d/system-auth
      - /etc/pam.d/password-auth
      when:
      - result_pam_faillock_fail_interval_parameter_is_present.found > 0
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - '"pam" in ansible_facts.packages'
    - not result_faillock_conf_check.stat.exists
    tags:
    - DISA-STIG-OL09-00-002416
    - NIST-800-53-AC-7(a)
    - NIST-800-53-CM-6(a)
    - accounts_passwords_pam_faillock_interval
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Set Lockout Time for Failed Password Attempts - Check if system relies on
      authselect tool
    ansible.builtin.stat:
      path: /usr/bin/authselect
    register: result_authselect_present
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - '"pam" in ansible_facts.packages'
    tags:
    - CJIS-5.5.3
    - DISA-STIG-OL09-00-002417
    - NIST-800-171-3.1.8
    - NIST-800-53-AC-7(b)
    - NIST-800-53-CM-6(a)
    - PCI-DSS-Req-8.1.7
    - PCI-DSSv4-8.3
    - PCI-DSSv4-8.3.4
    - accounts_passwords_pam_faillock_unlock_time
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Set Lockout Time for Failed Password Attempts - Remediation where authselect
      tool is present
    block:

    - name: Set Lockout Time for Failed Password Attempts - Check integrity of authselect
        current profile
      ansible.builtin.command:
        cmd: authselect check
      register: result_authselect_check_cmd
      changed_when: false
      check_mode: false
      failed_when: false

    - name: Set Lockout Time for Failed Password Attempts - Informative message based
        on the authselect integrity check result
      ansible.builtin.assert:
        that:
        - ansible_check_mode or result_authselect_check_cmd.rc == 0
        fail_msg:
        - authselect integrity check failed. Remediation aborted!
        - This remediation could not be applied because an authselect profile was
          not selected or the selected profile is not intact.
        - It is not recommended to manually edit the PAM files when authselect tool
          is available.
        - In cases where the default authselect profile does not cover a specific
          demand, a custom authselect profile is recommended.
        success_msg:
        - authselect integrity check passed

    - name: Set Lockout Time for Failed Password Attempts - Get authselect current
        features
      ansible.builtin.shell:
        cmd: authselect current | tail -n+3 | awk '{ print $2 }'
      register: result_authselect_features
      changed_when: false
      check_mode: false
      when:
      - result_authselect_check_cmd is success

    - name: Set Lockout Time for Failed Password Attempts - Ensure "with-faillock"
        feature is enabled using authselect tool
      ansible.builtin.command:
        cmd: authselect enable-feature with-faillock
      register: result_authselect_enable_feature_cmd
      when:
      - result_authselect_check_cmd is success
      - result_authselect_features.stdout is not search("with-faillock")

    - name: Set Lockout Time for Failed Password Attempts - Ensure authselect changes
        are applied
      ansible.builtin.command:
        cmd: authselect apply-changes -b
      when:
      - result_authselect_enable_feature_cmd is not skipped
      - result_authselect_enable_feature_cmd is success
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - '"pam" in ansible_facts.packages'
    - result_authselect_present.stat.exists
    tags:
    - CJIS-5.5.3
    - DISA-STIG-OL09-00-002417
    - NIST-800-171-3.1.8
    - NIST-800-53-AC-7(b)
    - NIST-800-53-CM-6(a)
    - PCI-DSS-Req-8.1.7
    - PCI-DSSv4-8.3
    - PCI-DSSv4-8.3.4
    - accounts_passwords_pam_faillock_unlock_time
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Set Lockout Time for Failed Password Attempts - Remediation where authselect
      tool is not present
    block:

    - name: Set Lockout Time for Failed Password Attempts - Check if pam_faillock.so
        is already enabled
      ansible.builtin.lineinfile:
        path: /etc/pam.d/system-auth
        regexp: .*auth.*pam_faillock\.so (preauth|authfail)
        state: absent
      check_mode: true
      changed_when: false
      register: result_pam_faillock_is_enabled

    - name: Set Lockout Time for Failed Password Attempts - Enable pam_faillock.so
        preauth editing PAM files
      ansible.builtin.lineinfile:
        path: '{{ item }}'
        line: auth        required      pam_faillock.so preauth
        insertbefore: ^auth.*sufficient.*pam_unix\.so.*
        state: present
      loop:
      - /etc/pam.d/system-auth
      - /etc/pam.d/password-auth
      when:
      - result_pam_faillock_is_enabled.found == 0

    - name: Set Lockout Time for Failed Password Attempts - Enable pam_faillock.so
        authfail editing PAM files
      ansible.builtin.lineinfile:
        path: '{{ item }}'
        line: auth        required      pam_faillock.so authfail
        insertbefore: ^auth.*required.*pam_deny\.so.*
        state: present
      loop:
      - /etc/pam.d/system-auth
      - /etc/pam.d/password-auth
      when:
      - result_pam_faillock_is_enabled.found == 0

    - name: Set Lockout Time for Failed Password Attempts - Enable pam_faillock.so
        account section editing PAM files
      ansible.builtin.lineinfile:
        path: '{{ item }}'
        line: account     required      pam_faillock.so
        insertbefore: ^account.*required.*pam_unix\.so.*
        state: present
      loop:
      - /etc/pam.d/system-auth
      - /etc/pam.d/password-auth
      when:
      - result_pam_faillock_is_enabled.found == 0
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - '"pam" in ansible_facts.packages'
    - not result_authselect_present.stat.exists
    tags:
    - CJIS-5.5.3
    - DISA-STIG-OL09-00-002417
    - NIST-800-171-3.1.8
    - NIST-800-53-AC-7(b)
    - NIST-800-53-CM-6(a)
    - PCI-DSS-Req-8.1.7
    - PCI-DSSv4-8.3
    - PCI-DSSv4-8.3.4
    - accounts_passwords_pam_faillock_unlock_time
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Set Lockout Time for Failed Password Attempts - Check the presence of /etc/security/faillock.conf
      file
    ansible.builtin.stat:
      path: /etc/security/faillock.conf
    register: result_faillock_conf_check
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - '"pam" in ansible_facts.packages'
    tags:
    - CJIS-5.5.3
    - DISA-STIG-OL09-00-002417
    - NIST-800-171-3.1.8
    - NIST-800-53-AC-7(b)
    - NIST-800-53-CM-6(a)
    - PCI-DSS-Req-8.1.7
    - PCI-DSSv4-8.3
    - PCI-DSSv4-8.3.4
    - accounts_passwords_pam_faillock_unlock_time
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Set Lockout Time for Failed Password Attempts - Ensure the pam_faillock.so
      unlock_time parameter in /etc/security/faillock.conf
    ansible.builtin.lineinfile:
      path: /etc/security/faillock.conf
      regexp: ^\s*unlock_time\s*=
      line: unlock_time = {{ var_accounts_passwords_pam_faillock_unlock_time }}
      state: present
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - '"pam" in ansible_facts.packages'
    - result_faillock_conf_check.stat.exists
    tags:
    - CJIS-5.5.3
    - DISA-STIG-OL09-00-002417
    - NIST-800-171-3.1.8
    - NIST-800-53-AC-7(b)
    - NIST-800-53-CM-6(a)
    - PCI-DSS-Req-8.1.7
    - PCI-DSSv4-8.3
    - PCI-DSSv4-8.3.4
    - accounts_passwords_pam_faillock_unlock_time
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Set Lockout Time for Failed Password Attempts - Ensure the pam_faillock.so
      unlock_time parameter not in PAM files
    block:

    - name: Set Lockout Time for Failed Password Attempts - Check if /etc/pam.d/system-auth
        file is present
      ansible.builtin.stat:
        path: /etc/pam.d/system-auth
      register: result_pam_auth_file_present

    - name: Set Lockout Time for Failed Password Attempts - Check the proper remediation
        for the system
      block:

      - name: Set Lockout Time for Failed Password Attempts - Define the PAM file
          to be edited as a local fact
        ansible.builtin.set_fact:
          pam_file_path: /etc/pam.d/system-auth

      - name: Set Lockout Time for Failed Password Attempts - Check if system relies
          on authselect tool
        ansible.builtin.stat:
          path: /usr/bin/authselect
        register: result_authselect_present

      - name: Set Lockout Time for Failed Password Attempts - Ensure authselect custom
          profile is used if authselect is present
        block:

        - name: Set Lockout Time for Failed Password Attempts - Check integrity of
            authselect current profile
          ansible.builtin.command:
            cmd: authselect check
          register: result_authselect_check_cmd
          changed_when: false
          check_mode: false
          failed_when: false

        - name: Set Lockout Time for Failed Password Attempts - Informative message
            based on the authselect integrity check result
          ansible.builtin.assert:
            that:
            - ansible_check_mode or result_authselect_check_cmd.rc == 0
            fail_msg:
            - authselect integrity check failed. Remediation aborted!
            - This remediation could not be applied because an authselect profile
              was not selected or the selected profile is not intact.
            - It is not recommended to manually edit the PAM files when authselect
              tool is available.
            - In cases where the default authselect profile does not cover a specific
              demand, a custom authselect profile is recommended.
            success_msg:
            - authselect integrity check passed

        - name: Set Lockout Time for Failed Password Attempts - Get authselect current
            profile
          ansible.builtin.shell:
            cmd: authselect current -r | awk '{ print $1 }'
          register: result_authselect_profile
          changed_when: false
          when:
          - result_authselect_check_cmd is success

        - name: Set Lockout Time for Failed Password Attempts - Define the current
            authselect profile as a local fact
          ansible.builtin.set_fact:
            authselect_current_profile: '{{ result_authselect_profile.stdout }}'
            authselect_custom_profile: '{{ result_authselect_profile.stdout }}'
          when:
          - result_authselect_profile is not skipped
          - result_authselect_profile.stdout is match("custom/")

        - name: Set Lockout Time for Failed Password Attempts - Define the new authselect
            custom profile as a local fact
          ansible.builtin.set_fact:
            authselect_current_profile: '{{ result_authselect_profile.stdout }}'
            authselect_custom_profile: custom/hardening
          when:
          - result_authselect_profile is not skipped
          - result_authselect_profile.stdout is not match("custom/")

        - name: Set Lockout Time for Failed Password Attempts - Get authselect current
            features to also enable them in the custom profile
          ansible.builtin.shell:
            cmd: authselect current | tail -n+3 | awk '{ print $2 }'
          register: result_authselect_features
          changed_when: false
          check_mode: false
          when:
          - result_authselect_profile is not skipped
          - authselect_current_profile is not match("custom/")

        - name: Set Lockout Time for Failed Password Attempts - Check if any custom
            profile with the same name was already created
          ansible.builtin.stat:
            path: /etc/authselect/{{ authselect_custom_profile }}
          register: result_authselect_custom_profile_present
          changed_when: false
          when:
          - result_authselect_profile is not skipped
          - authselect_current_profile is not match("custom/")

        - name: Set Lockout Time for Failed Password Attempts - Create an authselect
            custom profile based on the current profile
          ansible.builtin.command:
            cmd: authselect create-profile hardening -b {{ authselect_current_profile
              }}
          when:
          - result_authselect_profile is not skipped
          - result_authselect_check_cmd is success
          - authselect_current_profile is not match("^(custom/|local)")
          - not result_authselect_custom_profile_present.stat.exists

        - name: Set Lockout Time for Failed Password Attempts - Create an authselect
            custom profile based on sssd profile
          ansible.builtin.command:
            cmd: authselect create-profile hardening -b sssd
          when:
          - result_authselect_profile is not skipped
          - result_authselect_check_cmd is success
          - authselect_current_profile is match("local")
          - not result_authselect_custom_profile_present.stat.exists

        - name: Set Lockout Time for Failed Password Attempts - Ensure authselect
            changes are applied
          ansible.builtin.command:
            cmd: authselect apply-changes -b --backup=before-hardening-custom-profile
          when:
          - result_authselect_check_cmd is success
          - result_authselect_profile is not skipped
          - authselect_current_profile is not match("custom/")
          - authselect_custom_profile is not match(authselect_current_profile)

        - name: Set Lockout Time for Failed Password Attempts - Ensure the authselect
            custom profile is selected
          ansible.builtin.command:
            cmd: authselect select {{ authselect_custom_profile }}
          register: result_pam_authselect_select_profile
          when:
          - result_authselect_check_cmd is success
          - result_authselect_profile is not skipped
          - authselect_current_profile is not match("custom/")
          - authselect_custom_profile is not match(authselect_current_profile)

        - name: Set Lockout Time for Failed Password Attempts - Restore the authselect
            features in the custom profile
          ansible.builtin.command:
            cmd: authselect enable-feature {{ item }}
          loop: '{{ result_authselect_features.stdout_lines }}'
          register: result_pam_authselect_restore_features
          when:
          - result_authselect_profile is not skipped
          - result_authselect_features is not skipped
          - result_pam_authselect_select_profile is not skipped

        - name: Set Lockout Time for Failed Password Attempts - Ensure authselect
            changes are applied
          ansible.builtin.command:
            cmd: authselect apply-changes -b --backup=after-hardening-custom-profile
          when:
          - result_authselect_check_cmd is success
          - result_authselect_profile is not skipped
          - result_pam_authselect_restore_features is not skipped

        - name: Set Lockout Time for Failed Password Attempts - Change the PAM file
            to be edited according to the custom authselect profile
          ansible.builtin.set_fact:
            pam_file_path: /etc/authselect/{{ authselect_custom_profile }}/{{ pam_file_path
              | basename }}
          when:
          - authselect_custom_profile is defined
        when:
        - result_authselect_present.stat.exists

      - name: Set Lockout Time for Failed Password Attempts - Define a fact for control
          already filtered in case filters are used
        ansible.builtin.set_fact:
          pam_module_control: ''

      - name: Set Lockout Time for Failed Password Attempts - Check if {{ pam_file_path
          }} file is present
        ansible.builtin.stat:
          path: '{{ pam_file_path }}'
        register: result_pam_file_present

      - name: Set Lockout Time for Failed Password Attempts - Ensure the "unlock_time"
          option from "pam_faillock.so" is not present in {{ pam_file_path }}
        ansible.builtin.replace:
          dest: '{{ pam_file_path }}'
          regexp: (.*auth.*pam_faillock.so.*)\bunlock_time\b=?[0-9a-zA-Z]*(.*)
          replace: \1\2
        register: result_pam_option_removal
        when:
        - result_pam_file_present.stat.exists

      - name: Set Lockout Time for Failed Password Attempts - Ensure authselect changes
          are applied
        ansible.builtin.command:
          cmd: authselect apply-changes -b
        when:
        - result_authselect_present.stat.exists
        - result_pam_option_removal is changed
      when:
      - result_pam_auth_file_present.stat.exists

    - name: Set Lockout Time for Failed Password Attempts - Check if /etc/pam.d/password-auth
        file is present
      ansible.builtin.stat:
        path: /etc/pam.d/password-auth
      register: result_pam_password_auth_file_present

    - name: Set Lockout Time for Failed Password Attempts - Check the proper remediation
        for the system
      block:

      - name: Set Lockout Time for Failed Password Attempts - Define the PAM file
          to be edited as a local fact
        ansible.builtin.set_fact:
          pam_file_path: /etc/pam.d/password-auth

      - name: Set Lockout Time for Failed Password Attempts - Check if system relies
          on authselect tool
        ansible.builtin.stat:
          path: /usr/bin/authselect
        register: result_authselect_present

      - name: Set Lockout Time for Failed Password Attempts - Ensure authselect custom
          profile is used if authselect is present
        block:

        - name: Set Lockout Time for Failed Password Attempts - Check integrity of
            authselect current profile
          ansible.builtin.command:
            cmd: authselect check
          register: result_authselect_check_cmd
          changed_when: false
          check_mode: false
          failed_when: false

        - name: Set Lockout Time for Failed Password Attempts - Informative message
            based on the authselect integrity check result
          ansible.builtin.assert:
            that:
            - ansible_check_mode or result_authselect_check_cmd.rc == 0
            fail_msg:
            - authselect integrity check failed. Remediation aborted!
            - This remediation could not be applied because an authselect profile
              was not selected or the selected profile is not intact.
            - It is not recommended to manually edit the PAM files when authselect
              tool is available.
            - In cases where the default authselect profile does not cover a specific
              demand, a custom authselect profile is recommended.
            success_msg:
            - authselect integrity check passed

        - name: Set Lockout Time for Failed Password Attempts - Get authselect current
            profile
          ansible.builtin.shell:
            cmd: authselect current -r | awk '{ print $1 }'
          register: result_authselect_profile
          changed_when: false
          when:
          - result_authselect_check_cmd is success

        - name: Set Lockout Time for Failed Password Attempts - Define the current
            authselect profile as a local fact
          ansible.builtin.set_fact:
            authselect_current_profile: '{{ result_authselect_profile.stdout }}'
            authselect_custom_profile: '{{ result_authselect_profile.stdout }}'
          when:
          - result_authselect_profile is not skipped
          - result_authselect_profile.stdout is match("custom/")

        - name: Set Lockout Time for Failed Password Attempts - Define the new authselect
            custom profile as a local fact
          ansible.builtin.set_fact:
            authselect_current_profile: '{{ result_authselect_profile.stdout }}'
            authselect_custom_profile: custom/hardening
          when:
          - result_authselect_profile is not skipped
          - result_authselect_profile.stdout is not match("custom/")

        - name: Set Lockout Time for Failed Password Attempts - Get authselect current
            features to also enable them in the custom profile
          ansible.builtin.shell:
            cmd: authselect current | tail -n+3 | awk '{ print $2 }'
          register: result_authselect_features
          changed_when: false
          check_mode: false
          when:
          - result_authselect_profile is not skipped
          - authselect_current_profile is not match("custom/")

        - name: Set Lockout Time for Failed Password Attempts - Check if any custom
            profile with the same name was already created
          ansible.builtin.stat:
            path: /etc/authselect/{{ authselect_custom_profile }}
          register: result_authselect_custom_profile_present
          changed_when: false
          when:
          - result_authselect_profile is not skipped
          - authselect_current_profile is not match("custom/")

        - name: Set Lockout Time for Failed Password Attempts - Create an authselect
            custom profile based on the current profile
          ansible.builtin.command:
            cmd: authselect create-profile hardening -b {{ authselect_current_profile
              }}
          when:
          - result_authselect_profile is not skipped
          - result_authselect_check_cmd is success
          - authselect_current_profile is not match("^(custom/|local)")
          - not result_authselect_custom_profile_present.stat.exists

        - name: Set Lockout Time for Failed Password Attempts - Create an authselect
            custom profile based on sssd profile
          ansible.builtin.command:
            cmd: authselect create-profile hardening -b sssd
          when:
          - result_authselect_profile is not skipped
          - result_authselect_check_cmd is success
          - authselect_current_profile is match("local")
          - not result_authselect_custom_profile_present.stat.exists

        - name: Set Lockout Time for Failed Password Attempts - Ensure authselect
            changes are applied
          ansible.builtin.command:
            cmd: authselect apply-changes -b --backup=before-hardening-custom-profile
          when:
          - result_authselect_check_cmd is success
          - result_authselect_profile is not skipped
          - authselect_current_profile is not match("custom/")
          - authselect_custom_profile is not match(authselect_current_profile)

        - name: Set Lockout Time for Failed Password Attempts - Ensure the authselect
            custom profile is selected
          ansible.builtin.command:
            cmd: authselect select {{ authselect_custom_profile }}
          register: result_pam_authselect_select_profile
          when:
          - result_authselect_check_cmd is success
          - result_authselect_profile is not skipped
          - authselect_current_profile is not match("custom/")
          - authselect_custom_profile is not match(authselect_current_profile)

        - name: Set Lockout Time for Failed Password Attempts - Restore the authselect
            features in the custom profile
          ansible.builtin.command:
            cmd: authselect enable-feature {{ item }}
          loop: '{{ result_authselect_features.stdout_lines }}'
          register: result_pam_authselect_restore_features
          when:
          - result_authselect_profile is not skipped
          - result_authselect_features is not skipped
          - result_pam_authselect_select_profile is not skipped

        - name: Set Lockout Time for Failed Password Attempts - Ensure authselect
            changes are applied
          ansible.builtin.command:
            cmd: authselect apply-changes -b --backup=after-hardening-custom-profile
          when:
          - result_authselect_check_cmd is success
          - result_authselect_profile is not skipped
          - result_pam_authselect_restore_features is not skipped

        - name: Set Lockout Time for Failed Password Attempts - Change the PAM file
            to be edited according to the custom authselect profile
          ansible.builtin.set_fact:
            pam_file_path: /etc/authselect/{{ authselect_custom_profile }}/{{ pam_file_path
              | basename }}
          when:
          - authselect_custom_profile is defined
        when:
        - result_authselect_present.stat.exists

      - name: Set Lockout Time for Failed Password Attempts - Define a fact for control
          already filtered in case filters are used
        ansible.builtin.set_fact:
          pam_module_control: ''

      - name: Set Lockout Time for Failed Password Attempts - Check if {{ pam_file_path
          }} file is present
        ansible.builtin.stat:
          path: '{{ pam_file_path }}'
        register: result_pam_file_present

      - name: Set Lockout Time for Failed Password Attempts - Ensure the "unlock_time"
          option from "pam_faillock.so" is not present in {{ pam_file_path }}
        ansible.builtin.replace:
          dest: '{{ pam_file_path }}'
          regexp: (.*auth.*pam_faillock.so.*)\bunlock_time\b=?[0-9a-zA-Z]*(.*)
          replace: \1\2
        register: result_pam_option_removal
        when:
        - result_pam_file_present.stat.exists

      - name: Set Lockout Time for Failed Password Attempts - Ensure authselect changes
          are applied
        ansible.builtin.command:
          cmd: authselect apply-changes -b
        when:
        - result_authselect_present.stat.exists
        - result_pam_option_removal is changed
      when:
      - result_pam_password_auth_file_present.stat.exists
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - '"pam" in ansible_facts.packages'
    - result_faillock_conf_check.stat.exists
    tags:
    - CJIS-5.5.3
    - DISA-STIG-OL09-00-002417
    - NIST-800-171-3.1.8
    - NIST-800-53-AC-7(b)
    - NIST-800-53-CM-6(a)
    - PCI-DSS-Req-8.1.7
    - PCI-DSSv4-8.3
    - PCI-DSSv4-8.3.4
    - accounts_passwords_pam_faillock_unlock_time
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Set Lockout Time for Failed Password Attempts - Ensure the pam_faillock.so
      unlock_time parameter in PAM files
    block:

    - name: Set Lockout Time for Failed Password Attempts - Check if pam_faillock.so
        unlock_time parameter is already enabled in pam files
      ansible.builtin.lineinfile:
        path: /etc/pam.d/system-auth
        regexp: .*auth.*pam_faillock\.so (preauth|authfail).*unlock_time
        state: absent
      check_mode: true
      changed_when: false
      register: result_pam_faillock_unlock_time_parameter_is_present

    - name: Set Lockout Time for Failed Password Attempts - Ensure the inclusion of
        pam_faillock.so preauth unlock_time parameter in auth section
      ansible.builtin.lineinfile:
        path: '{{ item }}'
        backrefs: true
        regexp: (^\s*auth\s+)([\w\[].*\b)(\s+pam_faillock.so preauth.*)
        line: \1required\3 unlock_time={{ var_accounts_passwords_pam_faillock_unlock_time
          }}
        state: present
      loop:
      - /etc/pam.d/system-auth
      - /etc/pam.d/password-auth
      when:
      - result_pam_faillock_unlock_time_parameter_is_present.found == 0

    - name: Set Lockout Time for Failed Password Attempts - Ensure the inclusion of
        pam_faillock.so authfail unlock_time parameter in auth section
      ansible.builtin.lineinfile:
        path: '{{ item }}'
        backrefs: true
        regexp: (^\s*auth\s+)([\w\[].*\b)(\s+pam_faillock.so authfail.*)
        line: \1required\3 unlock_time={{ var_accounts_passwords_pam_faillock_unlock_time
          }}
        state: present
      loop:
      - /etc/pam.d/system-auth
      - /etc/pam.d/password-auth
      when:
      - result_pam_faillock_unlock_time_parameter_is_present.found == 0

    - name: Set Lockout Time for Failed Password Attempts - Ensure the desired value
        for pam_faillock.so preauth unlock_time parameter in auth section
      ansible.builtin.lineinfile:
        path: '{{ item }}'
        backrefs: true
        regexp: (^\s*auth\s+)([\w\[].*\b)(\s+pam_faillock.so preauth.*)(unlock_time)=[0-9]+(.*)
        line: \1required\3\4={{ var_accounts_passwords_pam_faillock_unlock_time }}\5
        state: present
      loop:
      - /etc/pam.d/system-auth
      - /etc/pam.d/password-auth
      when:
      - result_pam_faillock_unlock_time_parameter_is_present.found > 0

    - name: Set Lockout Time for Failed Password Attempts - Ensure the desired value
        for pam_faillock.so authfail unlock_time parameter in auth section
      ansible.builtin.lineinfile:
        path: '{{ item }}'
        backrefs: true
        regexp: (^\s*auth\s+)([\w\[].*\b)(\s+pam_faillock.so authfail.*)(unlock_time)=[0-9]+(.*)
        line: \1required\3\4={{ var_accounts_passwords_pam_faillock_unlock_time }}\5
        state: present
      loop:
      - /etc/pam.d/system-auth
      - /etc/pam.d/password-auth
      when:
      - result_pam_faillock_unlock_time_parameter_is_present.found > 0
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - '"pam" in ansible_facts.packages'
    - not result_faillock_conf_check.stat.exists
    tags:
    - CJIS-5.5.3
    - DISA-STIG-OL09-00-002417
    - NIST-800-171-3.1.8
    - NIST-800-53-AC-7(b)
    - NIST-800-53-CM-6(a)
    - PCI-DSS-Req-8.1.7
    - PCI-DSSv4-8.3
    - PCI-DSSv4-8.3.4
    - accounts_passwords_pam_faillock_unlock_time
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Ensure PAM Enforces Password Requirements - Minimum Digit Characters - Find
      pwquality.conf.d files
    ansible.builtin.find:
      paths: /etc/security/pwquality.conf.d/
      patterns: '*.conf'
    register: pwquality_conf_d_files
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - '"libpwquality" in ansible_facts.packages'
    tags:
    - DISA-STIG-OL09-00-001020
    - NIST-800-53-CM-6(a)
    - NIST-800-53-IA-5(1)(a)
    - NIST-800-53-IA-5(4)
    - NIST-800-53-IA-5(c)
    - PCI-DSS-Req-8.2.3
    - PCI-DSSv4-8.3
    - PCI-DSSv4-8.3.6
    - accounts_password_pam_dcredit
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Ensure PAM Enforces Password Requirements - Minimum Digit Characters - Ensure
      dcredit is not set in pwquality.conf.d
    ansible.builtin.lineinfile:
      path: '{{ item.path }}'
      regexp: ^\s*\bdcredit\b.*
      state: absent
    with_items: '{{ pwquality_conf_d_files.files }}'
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - '"libpwquality" in ansible_facts.packages'
    tags:
    - DISA-STIG-OL09-00-001020
    - NIST-800-53-CM-6(a)
    - NIST-800-53-IA-5(1)(a)
    - NIST-800-53-IA-5(4)
    - NIST-800-53-IA-5(c)
    - PCI-DSS-Req-8.2.3
    - PCI-DSSv4-8.3
    - PCI-DSSv4-8.3.6
    - accounts_password_pam_dcredit
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Ensure PAM Enforces Password Requirements - Minimum Digit Characters - Check
      if /etc/pam.d/system-auth file is present
    ansible.builtin.stat:
      path: /etc/pam.d/system-auth
    register: result_pam_auth_file_present
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - '"libpwquality" in ansible_facts.packages'
    tags:
    - DISA-STIG-OL09-00-001020
    - NIST-800-53-CM-6(a)
    - NIST-800-53-IA-5(1)(a)
    - NIST-800-53-IA-5(4)
    - NIST-800-53-IA-5(c)
    - PCI-DSS-Req-8.2.3
    - PCI-DSSv4-8.3
    - PCI-DSSv4-8.3.6
    - accounts_password_pam_dcredit
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Ensure PAM Enforces Password Requirements - Minimum Digit Characters - Check
      the proper remediation for the system
    block:

    - name: Ensure PAM Enforces Password Requirements - Minimum Digit Characters -
        Define the PAM file to be edited as a local fact
      ansible.builtin.set_fact:
        pam_file_path: /etc/pam.d/system-auth

    - name: Ensure PAM Enforces Password Requirements - Minimum Digit Characters -
        Check if system relies on authselect tool
      ansible.builtin.stat:
        path: /usr/bin/authselect
      register: result_authselect_present

    - name: Ensure PAM Enforces Password Requirements - Minimum Digit Characters -
        Ensure authselect custom profile is used if authselect is present
      block:

      - name: Ensure PAM Enforces Password Requirements - Minimum Digit Characters
          - Check integrity of authselect current profile
        ansible.builtin.command:
          cmd: authselect check
        register: result_authselect_check_cmd
        changed_when: false
        check_mode: false
        failed_when: false

      - name: Ensure PAM Enforces Password Requirements - Minimum Digit Characters
          - Informative message based on the authselect integrity check result
        ansible.builtin.assert:
          that:
          - ansible_check_mode or result_authselect_check_cmd.rc == 0
          fail_msg:
          - authselect integrity check failed. Remediation aborted!
          - This remediation could not be applied because an authselect profile was
            not selected or the selected profile is not intact.
          - It is not recommended to manually edit the PAM files when authselect tool
            is available.
          - In cases where the default authselect profile does not cover a specific
            demand, a custom authselect profile is recommended.
          success_msg:
          - authselect integrity check passed

      - name: Ensure PAM Enforces Password Requirements - Minimum Digit Characters
          - Get authselect current profile
        ansible.builtin.shell:
          cmd: authselect current -r | awk '{ print $1 }'
        register: result_authselect_profile
        changed_when: false
        when:
        - result_authselect_check_cmd is success

      - name: Ensure PAM Enforces Password Requirements - Minimum Digit Characters
          - Define the current authselect profile as a local fact
        ansible.builtin.set_fact:
          authselect_current_profile: '{{ result_authselect_profile.stdout }}'
          authselect_custom_profile: '{{ result_authselect_profile.stdout }}'
        when:
        - result_authselect_profile is not skipped
        - result_authselect_profile.stdout is match("custom/")

      - name: Ensure PAM Enforces Password Requirements - Minimum Digit Characters
          - Define the new authselect custom profile as a local fact
        ansible.builtin.set_fact:
          authselect_current_profile: '{{ result_authselect_profile.stdout }}'
          authselect_custom_profile: custom/hardening
        when:
        - result_authselect_profile is not skipped
        - result_authselect_profile.stdout is not match("custom/")

      - name: Ensure PAM Enforces Password Requirements - Minimum Digit Characters
          - Get authselect current features to also enable them in the custom profile
        ansible.builtin.shell:
          cmd: authselect current | tail -n+3 | awk '{ print $2 }'
        register: result_authselect_features
        changed_when: false
        check_mode: false
        when:
        - result_authselect_profile is not skipped
        - authselect_current_profile is not match("custom/")

      - name: Ensure PAM Enforces Password Requirements - Minimum Digit Characters
          - Check if any custom profile with the same name was already created
        ansible.builtin.stat:
          path: /etc/authselect/{{ authselect_custom_profile }}
        register: result_authselect_custom_profile_present
        changed_when: false
        when:
        - result_authselect_profile is not skipped
        - authselect_current_profile is not match("custom/")

      - name: Ensure PAM Enforces Password Requirements - Minimum Digit Characters
          - Create an authselect custom profile based on the current profile
        ansible.builtin.command:
          cmd: authselect create-profile hardening -b {{ authselect_current_profile
            }}
        when:
        - result_authselect_profile is not skipped
        - result_authselect_check_cmd is success
        - authselect_current_profile is not match("^(custom/|local)")
        - not result_authselect_custom_profile_present.stat.exists

      - name: Ensure PAM Enforces Password Requirements - Minimum Digit Characters
          - Create an authselect custom profile based on sssd profile
        ansible.builtin.command:
          cmd: authselect create-profile hardening -b sssd
        when:
        - result_authselect_profile is not skipped
        - result_authselect_check_cmd is success
        - authselect_current_profile is match("local")
        - not result_authselect_custom_profile_present.stat.exists

      - name: Ensure PAM Enforces Password Requirements - Minimum Digit Characters
          - Ensure authselect changes are applied
        ansible.builtin.command:
          cmd: authselect apply-changes -b --backup=before-hardening-custom-profile
        when:
        - result_authselect_check_cmd is success
        - result_authselect_profile is not skipped
        - authselect_current_profile is not match("custom/")
        - authselect_custom_profile is not match(authselect_current_profile)

      - name: Ensure PAM Enforces Password Requirements - Minimum Digit Characters
          - Ensure the authselect custom profile is selected
        ansible.builtin.command:
          cmd: authselect select {{ authselect_custom_profile }}
        register: result_pam_authselect_select_profile
        when:
        - result_authselect_check_cmd is success
        - result_authselect_profile is not skipped
        - authselect_current_profile is not match("custom/")
        - authselect_custom_profile is not match(authselect_current_profile)

      - name: Ensure PAM Enforces Password Requirements - Minimum Digit Characters
          - Restore the authselect features in the custom profile
        ansible.builtin.command:
          cmd: authselect enable-feature {{ item }}
        loop: '{{ result_authselect_features.stdout_lines }}'
        register: result_pam_authselect_restore_features
        when:
        - result_authselect_profile is not skipped
        - result_authselect_features is not skipped
        - result_pam_authselect_select_profile is not skipped

      - name: Ensure PAM Enforces Password Requirements - Minimum Digit Characters
          - Ensure authselect changes are applied
        ansible.builtin.command:
          cmd: authselect apply-changes -b --backup=after-hardening-custom-profile
        when:
        - result_authselect_check_cmd is success
        - result_authselect_profile is not skipped
        - result_pam_authselect_restore_features is not skipped

      - name: Ensure PAM Enforces Password Requirements - Minimum Digit Characters
          - Change the PAM file to be edited according to the custom authselect profile
        ansible.builtin.set_fact:
          pam_file_path: /etc/authselect/{{ authselect_custom_profile }}/{{ pam_file_path
            | basename }}
        when:
        - authselect_custom_profile is defined
      when:
      - result_authselect_present.stat.exists

    - name: Ensure PAM Enforces Password Requirements - Minimum Digit Characters -
        Define a fact for control already filtered in case filters are used
      ansible.builtin.set_fact:
        pam_module_control: ''

    - name: Ensure PAM Enforces Password Requirements - Minimum Digit Characters -
        Check if {{ pam_file_path }} file is present
      ansible.builtin.stat:
        path: '{{ pam_file_path }}'
      register: result_pam_file_present

    - name: Ensure PAM Enforces Password Requirements - Minimum Digit Characters -
        Ensure the "dcredit" option from "pam_pwquality.so" is not present in {{ pam_file_path
        }}
      ansible.builtin.replace:
        dest: '{{ pam_file_path }}'
        regexp: (.*password.*pam_pwquality.so.*)\bdcredit\b=?[0-9a-zA-Z]*(.*)
        replace: \1\2
      register: result_pam_option_removal
      when:
      - result_pam_file_present.stat.exists

    - name: Ensure PAM Enforces Password Requirements - Minimum Digit Characters -
        Ensure authselect changes are applied
      ansible.builtin.command:
        cmd: authselect apply-changes -b
      when:
      - result_authselect_present.stat.exists
      - result_pam_option_removal is changed
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - '"libpwquality" in ansible_facts.packages'
    - result_pam_auth_file_present.stat.exists
    tags:
    - DISA-STIG-OL09-00-001020
    - NIST-800-53-CM-6(a)
    - NIST-800-53-IA-5(1)(a)
    - NIST-800-53-IA-5(4)
    - NIST-800-53-IA-5(c)
    - PCI-DSS-Req-8.2.3
    - PCI-DSSv4-8.3
    - PCI-DSSv4-8.3.6
    - accounts_password_pam_dcredit
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Ensure PAM Enforces Password Requirements - Minimum Digit Characters - Check
      if /etc/pam.d/password-auth file is present
    ansible.builtin.stat:
      path: /etc/pam.d/password-auth
    register: result_pam_password_auth_file_present
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - '"libpwquality" in ansible_facts.packages'
    tags:
    - DISA-STIG-OL09-00-001020
    - NIST-800-53-CM-6(a)
    - NIST-800-53-IA-5(1)(a)
    - NIST-800-53-IA-5(4)
    - NIST-800-53-IA-5(c)
    - PCI-DSS-Req-8.2.3
    - PCI-DSSv4-8.3
    - PCI-DSSv4-8.3.6
    - accounts_password_pam_dcredit
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Ensure PAM Enforces Password Requirements - Minimum Digit Characters - Check
      the proper remediation for the system
    block:

    - name: Ensure PAM Enforces Password Requirements - Minimum Digit Characters -
        Define the PAM file to be edited as a local fact
      ansible.builtin.set_fact:
        pam_file_path: /etc/pam.d/password-auth

    - name: Ensure PAM Enforces Password Requirements - Minimum Digit Characters -
        Check if system relies on authselect tool
      ansible.builtin.stat:
        path: /usr/bin/authselect
      register: result_authselect_present

    - name: Ensure PAM Enforces Password Requirements - Minimum Digit Characters -
        Ensure authselect custom profile is used if authselect is present
      block:

      - name: Ensure PAM Enforces Password Requirements - Minimum Digit Characters
          - Check integrity of authselect current profile
        ansible.builtin.command:
          cmd: authselect check
        register: result_authselect_check_cmd
        changed_when: false
        check_mode: false
        failed_when: false

      - name: Ensure PAM Enforces Password Requirements - Minimum Digit Characters
          - Informative message based on the authselect integrity check result
        ansible.builtin.assert:
          that:
          - ansible_check_mode or result_authselect_check_cmd.rc == 0
          fail_msg:
          - authselect integrity check failed. Remediation aborted!
          - This remediation could not be applied because an authselect profile was
            not selected or the selected profile is not intact.
          - It is not recommended to manually edit the PAM files when authselect tool
            is available.
          - In cases where the default authselect profile does not cover a specific
            demand, a custom authselect profile is recommended.
          success_msg:
          - authselect integrity check passed

      - name: Ensure PAM Enforces Password Requirements - Minimum Digit Characters
          - Get authselect current profile
        ansible.builtin.shell:
          cmd: authselect current -r | awk '{ print $1 }'
        register: result_authselect_profile
        changed_when: false
        when:
        - result_authselect_check_cmd is success

      - name: Ensure PAM Enforces Password Requirements - Minimum Digit Characters
          - Define the current authselect profile as a local fact
        ansible.builtin.set_fact:
          authselect_current_profile: '{{ result_authselect_profile.stdout }}'
          authselect_custom_profile: '{{ result_authselect_profile.stdout }}'
        when:
        - result_authselect_profile is not skipped
        - result_authselect_profile.stdout is match("custom/")

      - name: Ensure PAM Enforces Password Requirements - Minimum Digit Characters
          - Define the new authselect custom profile as a local fact
        ansible.builtin.set_fact:
          authselect_current_profile: '{{ result_authselect_profile.stdout }}'
          authselect_custom_profile: custom/hardening
        when:
        - result_authselect_profile is not skipped
        - result_authselect_profile.stdout is not match("custom/")

      - name: Ensure PAM Enforces Password Requirements - Minimum Digit Characters
          - Get authselect current features to also enable them in the custom profile
        ansible.builtin.shell:
          cmd: authselect current | tail -n+3 | awk '{ print $2 }'
        register: result_authselect_features
        changed_when: false
        check_mode: false
        when:
        - result_authselect_profile is not skipped
        - authselect_current_profile is not match("custom/")

      - name: Ensure PAM Enforces Password Requirements - Minimum Digit Characters
          - Check if any custom profile with the same name was already created
        ansible.builtin.stat:
          path: /etc/authselect/{{ authselect_custom_profile }}
        register: result_authselect_custom_profile_present
        changed_when: false
        when:
        - result_authselect_profile is not skipped
        - authselect_current_profile is not match("custom/")

      - name: Ensure PAM Enforces Password Requirements - Minimum Digit Characters
          - Create an authselect custom profile based on the current profile
        ansible.builtin.command:
          cmd: authselect create-profile hardening -b {{ authselect_current_profile
            }}
        when:
        - result_authselect_profile is not skipped
        - result_authselect_check_cmd is success
        - authselect_current_profile is not match("^(custom/|local)")
        - not result_authselect_custom_profile_present.stat.exists

      - name: Ensure PAM Enforces Password Requirements - Minimum Digit Characters
          - Create an authselect custom profile based on sssd profile
        ansible.builtin.command:
          cmd: authselect create-profile hardening -b sssd
        when:
        - result_authselect_profile is not skipped
        - result_authselect_check_cmd is success
        - authselect_current_profile is match("local")
        - not result_authselect_custom_profile_present.stat.exists

      - name: Ensure PAM Enforces Password Requirements - Minimum Digit Characters
          - Ensure authselect changes are applied
        ansible.builtin.command:
          cmd: authselect apply-changes -b --backup=before-hardening-custom-profile
        when:
        - result_authselect_check_cmd is success
        - result_authselect_profile is not skipped
        - authselect_current_profile is not match("custom/")
        - authselect_custom_profile is not match(authselect_current_profile)

      - name: Ensure PAM Enforces Password Requirements - Minimum Digit Characters
          - Ensure the authselect custom profile is selected
        ansible.builtin.command:
          cmd: authselect select {{ authselect_custom_profile }}
        register: result_pam_authselect_select_profile
        when:
        - result_authselect_check_cmd is success
        - result_authselect_profile is not skipped
        - authselect_current_profile is not match("custom/")
        - authselect_custom_profile is not match(authselect_current_profile)

      - name: Ensure PAM Enforces Password Requirements - Minimum Digit Characters
          - Restore the authselect features in the custom profile
        ansible.builtin.command:
          cmd: authselect enable-feature {{ item }}
        loop: '{{ result_authselect_features.stdout_lines }}'
        register: result_pam_authselect_restore_features
        when:
        - result_authselect_profile is not skipped
        - result_authselect_features is not skipped
        - result_pam_authselect_select_profile is not skipped

      - name: Ensure PAM Enforces Password Requirements - Minimum Digit Characters
          - Ensure authselect changes are applied
        ansible.builtin.command:
          cmd: authselect apply-changes -b --backup=after-hardening-custom-profile
        when:
        - result_authselect_check_cmd is success
        - result_authselect_profile is not skipped
        - result_pam_authselect_restore_features is not skipped

      - name: Ensure PAM Enforces Password Requirements - Minimum Digit Characters
          - Change the PAM file to be edited according to the custom authselect profile
        ansible.builtin.set_fact:
          pam_file_path: /etc/authselect/{{ authselect_custom_profile }}/{{ pam_file_path
            | basename }}
        when:
        - authselect_custom_profile is defined
      when:
      - result_authselect_present.stat.exists

    - name: Ensure PAM Enforces Password Requirements - Minimum Digit Characters -
        Define a fact for control already filtered in case filters are used
      ansible.builtin.set_fact:
        pam_module_control: ''

    - name: Ensure PAM Enforces Password Requirements - Minimum Digit Characters -
        Check if {{ pam_file_path }} file is present
      ansible.builtin.stat:
        path: '{{ pam_file_path }}'
      register: result_pam_file_present

    - name: Ensure PAM Enforces Password Requirements - Minimum Digit Characters -
        Ensure the "dcredit" option from "pam_pwquality.so" is not present in {{ pam_file_path
        }}
      ansible.builtin.replace:
        dest: '{{ pam_file_path }}'
        regexp: (.*password.*pam_pwquality.so.*)\bdcredit\b=?[0-9a-zA-Z]*(.*)
        replace: \1\2
      register: result_pam_option_removal
      when:
      - result_pam_file_present.stat.exists

    - name: Ensure PAM Enforces Password Requirements - Minimum Digit Characters -
        Ensure authselect changes are applied
      ansible.builtin.command:
        cmd: authselect apply-changes -b
      when:
      - result_authselect_present.stat.exists
      - result_pam_option_removal is changed
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - '"libpwquality" in ansible_facts.packages'
    - result_pam_password_auth_file_present.stat.exists
    tags:
    - DISA-STIG-OL09-00-001020
    - NIST-800-53-CM-6(a)
    - NIST-800-53-IA-5(1)(a)
    - NIST-800-53-IA-5(4)
    - NIST-800-53-IA-5(c)
    - PCI-DSS-Req-8.2.3
    - PCI-DSSv4-8.3
    - PCI-DSSv4-8.3.6
    - accounts_password_pam_dcredit
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Ensure PAM Enforces Password Requirements - Minimum Digit Characters - Ensure
      PAM variable dcredit is set accordingly
    ansible.builtin.lineinfile:
      create: true
      dest: /etc/security/pwquality.conf
      regexp: ^#?\s*dcredit
      line: dcredit = {{ var_password_pam_dcredit }}
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - '"libpwquality" in ansible_facts.packages'
    tags:
    - DISA-STIG-OL09-00-001020
    - NIST-800-53-CM-6(a)
    - NIST-800-53-IA-5(1)(a)
    - NIST-800-53-IA-5(4)
    - NIST-800-53-IA-5(c)
    - PCI-DSS-Req-8.2.3
    - PCI-DSSv4-8.3
    - PCI-DSSv4-8.3.6
    - accounts_password_pam_dcredit
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Ensure PAM Enforces Password Requirements - Prevent the Use of Dictionary
      Words - Find pwquality.conf.d files
    ansible.builtin.find:
      paths: /etc/security/pwquality.conf.d/
      patterns: '*.conf'
    register: pwquality_conf_d_files
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - '"libpwquality" in ansible_facts.packages'
    tags:
    - DISA-STIG-OL09-00-001125
    - NIST-800-53-CM-6(a)
    - NIST-800-53-IA-5(1)(a)
    - NIST-800-53-IA-5(4)
    - NIST-800-53-IA-5(c)
    - accounts_password_pam_dictcheck
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Ensure PAM Enforces Password Requirements - Prevent the Use of Dictionary
      Words - Ensure dictcheck is not set in pwquality.conf.d
    ansible.builtin.lineinfile:
      path: '{{ item.path }}'
      regexp: ^\s*\bdictcheck\b.*
      state: absent
    with_items: '{{ pwquality_conf_d_files.files }}'
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - '"libpwquality" in ansible_facts.packages'
    tags:
    - DISA-STIG-OL09-00-001125
    - NIST-800-53-CM-6(a)
    - NIST-800-53-IA-5(1)(a)
    - NIST-800-53-IA-5(4)
    - NIST-800-53-IA-5(c)
    - accounts_password_pam_dictcheck
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Ensure PAM Enforces Password Requirements - Prevent the Use of Dictionary
      Words - Check if /etc/pam.d/system-auth file is present
    ansible.builtin.stat:
      path: /etc/pam.d/system-auth
    register: result_pam_auth_file_present
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - '"libpwquality" in ansible_facts.packages'
    tags:
    - DISA-STIG-OL09-00-001125
    - NIST-800-53-CM-6(a)
    - NIST-800-53-IA-5(1)(a)
    - NIST-800-53-IA-5(4)
    - NIST-800-53-IA-5(c)
    - accounts_password_pam_dictcheck
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Ensure PAM Enforces Password Requirements - Prevent the Use of Dictionary
      Words - Check the proper remediation for the system
    block:

    - name: Ensure PAM Enforces Password Requirements - Prevent the Use of Dictionary
        Words - Define the PAM file to be edited as a local fact
      ansible.builtin.set_fact:
        pam_file_path: /etc/pam.d/system-auth

    - name: Ensure PAM Enforces Password Requirements - Prevent the Use of Dictionary
        Words - Check if system relies on authselect tool
      ansible.builtin.stat:
        path: /usr/bin/authselect
      register: result_authselect_present

    - name: Ensure PAM Enforces Password Requirements - Prevent the Use of Dictionary
        Words - Ensure authselect custom profile is used if authselect is present
      block:

      - name: Ensure PAM Enforces Password Requirements - Prevent the Use of Dictionary
          Words - Check integrity of authselect current profile
        ansible.builtin.command:
          cmd: authselect check
        register: result_authselect_check_cmd
        changed_when: false
        check_mode: false
        failed_when: false

      - name: Ensure PAM Enforces Password Requirements - Prevent the Use of Dictionary
          Words - Informative message based on the authselect integrity check result
        ansible.builtin.assert:
          that:
          - ansible_check_mode or result_authselect_check_cmd.rc == 0
          fail_msg:
          - authselect integrity check failed. Remediation aborted!
          - This remediation could not be applied because an authselect profile was
            not selected or the selected profile is not intact.
          - It is not recommended to manually edit the PAM files when authselect tool
            is available.
          - In cases where the default authselect profile does not cover a specific
            demand, a custom authselect profile is recommended.
          success_msg:
          - authselect integrity check passed

      - name: Ensure PAM Enforces Password Requirements - Prevent the Use of Dictionary
          Words - Get authselect current profile
        ansible.builtin.shell:
          cmd: authselect current -r | awk '{ print $1 }'
        register: result_authselect_profile
        changed_when: false
        when:
        - result_authselect_check_cmd is success

      - name: Ensure PAM Enforces Password Requirements - Prevent the Use of Dictionary
          Words - Define the current authselect profile as a local fact
        ansible.builtin.set_fact:
          authselect_current_profile: '{{ result_authselect_profile.stdout }}'
          authselect_custom_profile: '{{ result_authselect_profile.stdout }}'
        when:
        - result_authselect_profile is not skipped
        - result_authselect_profile.stdout is match("custom/")

      - name: Ensure PAM Enforces Password Requirements - Prevent the Use of Dictionary
          Words - Define the new authselect custom profile as a local fact
        ansible.builtin.set_fact:
          authselect_current_profile: '{{ result_authselect_profile.stdout }}'
          authselect_custom_profile: custom/hardening
        when:
        - result_authselect_profile is not skipped
        - result_authselect_profile.stdout is not match("custom/")

      - name: Ensure PAM Enforces Password Requirements - Prevent the Use of Dictionary
          Words - Get authselect current features to also enable them in the custom
          profile
        ansible.builtin.shell:
          cmd: authselect current | tail -n+3 | awk '{ print $2 }'
        register: result_authselect_features
        changed_when: false
        check_mode: false
        when:
        - result_authselect_profile is not skipped
        - authselect_current_profile is not match("custom/")

      - name: Ensure PAM Enforces Password Requirements - Prevent the Use of Dictionary
          Words - Check if any custom profile with the same name was already created
        ansible.builtin.stat:
          path: /etc/authselect/{{ authselect_custom_profile }}
        register: result_authselect_custom_profile_present
        changed_when: false
        when:
        - result_authselect_profile is not skipped
        - authselect_current_profile is not match("custom/")

      - name: Ensure PAM Enforces Password Requirements - Prevent the Use of Dictionary
          Words - Create an authselect custom profile based on the current profile
        ansible.builtin.command:
          cmd: authselect create-profile hardening -b {{ authselect_current_profile
            }}
        when:
        - result_authselect_profile is not skipped
        - result_authselect_check_cmd is success
        - authselect_current_profile is not match("^(custom/|local)")
        - not result_authselect_custom_profile_present.stat.exists

      - name: Ensure PAM Enforces Password Requirements - Prevent the Use of Dictionary
          Words - Create an authselect custom profile based on sssd profile
        ansible.builtin.command:
          cmd: authselect create-profile hardening -b sssd
        when:
        - result_authselect_profile is not skipped
        - result_authselect_check_cmd is success
        - authselect_current_profile is match("local")
        - not result_authselect_custom_profile_present.stat.exists

      - name: Ensure PAM Enforces Password Requirements - Prevent the Use of Dictionary
          Words - Ensure authselect changes are applied
        ansible.builtin.command:
          cmd: authselect apply-changes -b --backup=before-hardening-custom-profile
        when:
        - result_authselect_check_cmd is success
        - result_authselect_profile is not skipped
        - authselect_current_profile is not match("custom/")
        - authselect_custom_profile is not match(authselect_current_profile)

      - name: Ensure PAM Enforces Password Requirements - Prevent the Use of Dictionary
          Words - Ensure the authselect custom profile is selected
        ansible.builtin.command:
          cmd: authselect select {{ authselect_custom_profile }}
        register: result_pam_authselect_select_profile
        when:
        - result_authselect_check_cmd is success
        - result_authselect_profile is not skipped
        - authselect_current_profile is not match("custom/")
        - authselect_custom_profile is not match(authselect_current_profile)

      - name: Ensure PAM Enforces Password Requirements - Prevent the Use of Dictionary
          Words - Restore the authselect features in the custom profile
        ansible.builtin.command:
          cmd: authselect enable-feature {{ item }}
        loop: '{{ result_authselect_features.stdout_lines }}'
        register: result_pam_authselect_restore_features
        when:
        - result_authselect_profile is not skipped
        - result_authselect_features is not skipped
        - result_pam_authselect_select_profile is not skipped

      - name: Ensure PAM Enforces Password Requirements - Prevent the Use of Dictionary
          Words - Ensure authselect changes are applied
        ansible.builtin.command:
          cmd: authselect apply-changes -b --backup=after-hardening-custom-profile
        when:
        - result_authselect_check_cmd is success
        - result_authselect_profile is not skipped
        - result_pam_authselect_restore_features is not skipped

      - name: Ensure PAM Enforces Password Requirements - Prevent the Use of Dictionary
          Words - Change the PAM file to be edited according to the custom authselect
          profile
        ansible.builtin.set_fact:
          pam_file_path: /etc/authselect/{{ authselect_custom_profile }}/{{ pam_file_path
            | basename }}
        when:
        - authselect_custom_profile is defined
      when:
      - result_authselect_present.stat.exists

    - name: Ensure PAM Enforces Password Requirements - Prevent the Use of Dictionary
        Words - Define a fact for control already filtered in case filters are used
      ansible.builtin.set_fact:
        pam_module_control: ''

    - name: Ensure PAM Enforces Password Requirements - Prevent the Use of Dictionary
        Words - Check if {{ pam_file_path }} file is present
      ansible.builtin.stat:
        path: '{{ pam_file_path }}'
      register: result_pam_file_present

    - name: Ensure PAM Enforces Password Requirements - Prevent the Use of Dictionary
        Words - Ensure the "dictcheck" option from "pam_pwquality.so" is not present
        in {{ pam_file_path }}
      ansible.builtin.replace:
        dest: '{{ pam_file_path }}'
        regexp: (.*password.*pam_pwquality.so.*)\bdictcheck\b=?[0-9a-zA-Z]*(.*)
        replace: \1\2
      register: result_pam_option_removal
      when:
      - result_pam_file_present.stat.exists

    - name: Ensure PAM Enforces Password Requirements - Prevent the Use of Dictionary
        Words - Ensure authselect changes are applied
      ansible.builtin.command:
        cmd: authselect apply-changes -b
      when:
      - result_authselect_present.stat.exists
      - result_pam_option_removal is changed
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - '"libpwquality" in ansible_facts.packages'
    - result_pam_auth_file_present.stat.exists
    tags:
    - DISA-STIG-OL09-00-001125
    - NIST-800-53-CM-6(a)
    - NIST-800-53-IA-5(1)(a)
    - NIST-800-53-IA-5(4)
    - NIST-800-53-IA-5(c)
    - accounts_password_pam_dictcheck
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Ensure PAM Enforces Password Requirements - Prevent the Use of Dictionary
      Words - Check if /etc/pam.d/password-auth file is present
    ansible.builtin.stat:
      path: /etc/pam.d/password-auth
    register: result_pam_password_auth_file_present
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - '"libpwquality" in ansible_facts.packages'
    tags:
    - DISA-STIG-OL09-00-001125
    - NIST-800-53-CM-6(a)
    - NIST-800-53-IA-5(1)(a)
    - NIST-800-53-IA-5(4)
    - NIST-800-53-IA-5(c)
    - accounts_password_pam_dictcheck
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Ensure PAM Enforces Password Requirements - Prevent the Use of Dictionary
      Words - Check the proper remediation for the system
    block:

    - name: Ensure PAM Enforces Password Requirements - Prevent the Use of Dictionary
        Words - Define the PAM file to be edited as a local fact
      ansible.builtin.set_fact:
        pam_file_path: /etc/pam.d/password-auth

    - name: Ensure PAM Enforces Password Requirements - Prevent the Use of Dictionary
        Words - Check if system relies on authselect tool
      ansible.builtin.stat:
        path: /usr/bin/authselect
      register: result_authselect_present

    - name: Ensure PAM Enforces Password Requirements - Prevent the Use of Dictionary
        Words - Ensure authselect custom profile is used if authselect is present
      block:

      - name: Ensure PAM Enforces Password Requirements - Prevent the Use of Dictionary
          Words - Check integrity of authselect current profile
        ansible.builtin.command:
          cmd: authselect check
        register: result_authselect_check_cmd
        changed_when: false
        check_mode: false
        failed_when: false

      - name: Ensure PAM Enforces Password Requirements - Prevent the Use of Dictionary
          Words - Informative message based on the authselect integrity check result
        ansible.builtin.assert:
          that:
          - ansible_check_mode or result_authselect_check_cmd.rc == 0
          fail_msg:
          - authselect integrity check failed. Remediation aborted!
          - This remediation could not be applied because an authselect profile was
            not selected or the selected profile is not intact.
          - It is not recommended to manually edit the PAM files when authselect tool
            is available.
          - In cases where the default authselect profile does not cover a specific
            demand, a custom authselect profile is recommended.
          success_msg:
          - authselect integrity check passed

      - name: Ensure PAM Enforces Password Requirements - Prevent the Use of Dictionary
          Words - Get authselect current profile
        ansible.builtin.shell:
          cmd: authselect current -r | awk '{ print $1 }'
        register: result_authselect_profile
        changed_when: false
        when:
        - result_authselect_check_cmd is success

      - name: Ensure PAM Enforces Password Requirements - Prevent the Use of Dictionary
          Words - Define the current authselect profile as a local fact
        ansible.builtin.set_fact:
          authselect_current_profile: '{{ result_authselect_profile.stdout }}'
          authselect_custom_profile: '{{ result_authselect_profile.stdout }}'
        when:
        - result_authselect_profile is not skipped
        - result_authselect_profile.stdout is match("custom/")

      - name: Ensure PAM Enforces Password Requirements - Prevent the Use of Dictionary
          Words - Define the new authselect custom profile as a local fact
        ansible.builtin.set_fact:
          authselect_current_profile: '{{ result_authselect_profile.stdout }}'
          authselect_custom_profile: custom/hardening
        when:
        - result_authselect_profile is not skipped
        - result_authselect_profile.stdout is not match("custom/")

      - name: Ensure PAM Enforces Password Requirements - Prevent the Use of Dictionary
          Words - Get authselect current features to also enable them in the custom
          profile
        ansible.builtin.shell:
          cmd: authselect current | tail -n+3 | awk '{ print $2 }'
        register: result_authselect_features
        changed_when: false
        check_mode: false
        when:
        - result_authselect_profile is not skipped
        - authselect_current_profile is not match("custom/")

      - name: Ensure PAM Enforces Password Requirements - Prevent the Use of Dictionary
          Words - Check if any custom profile with the same name was already created
        ansible.builtin.stat:
          path: /etc/authselect/{{ authselect_custom_profile }}
        register: result_authselect_custom_profile_present
        changed_when: false
        when:
        - result_authselect_profile is not skipped
        - authselect_current_profile is not match("custom/")

      - name: Ensure PAM Enforces Password Requirements - Prevent the Use of Dictionary
          Words - Create an authselect custom profile based on the current profile
        ansible.builtin.command:
          cmd: authselect create-profile hardening -b {{ authselect_current_profile
            }}
        when:
        - result_authselect_profile is not skipped
        - result_authselect_check_cmd is success
        - authselect_current_profile is not match("^(custom/|local)")
        - not result_authselect_custom_profile_present.stat.exists

      - name: Ensure PAM Enforces Password Requirements - Prevent the Use of Dictionary
          Words - Create an authselect custom profile based on sssd profile
        ansible.builtin.command:
          cmd: authselect create-profile hardening -b sssd
        when:
        - result_authselect_profile is not skipped
        - result_authselect_check_cmd is success
        - authselect_current_profile is match("local")
        - not result_authselect_custom_profile_present.stat.exists

      - name: Ensure PAM Enforces Password Requirements - Prevent the Use of Dictionary
          Words - Ensure authselect changes are applied
        ansible.builtin.command:
          cmd: authselect apply-changes -b --backup=before-hardening-custom-profile
        when:
        - result_authselect_check_cmd is success
        - result_authselect_profile is not skipped
        - authselect_current_profile is not match("custom/")
        - authselect_custom_profile is not match(authselect_current_profile)

      - name: Ensure PAM Enforces Password Requirements - Prevent the Use of Dictionary
          Words - Ensure the authselect custom profile is selected
        ansible.builtin.command:
          cmd: authselect select {{ authselect_custom_profile }}
        register: result_pam_authselect_select_profile
        when:
        - result_authselect_check_cmd is success
        - result_authselect_profile is not skipped
        - authselect_current_profile is not match("custom/")
        - authselect_custom_profile is not match(authselect_current_profile)

      - name: Ensure PAM Enforces Password Requirements - Prevent the Use of Dictionary
          Words - Restore the authselect features in the custom profile
        ansible.builtin.command:
          cmd: authselect enable-feature {{ item }}
        loop: '{{ result_authselect_features.stdout_lines }}'
        register: result_pam_authselect_restore_features
        when:
        - result_authselect_profile is not skipped
        - result_authselect_features is not skipped
        - result_pam_authselect_select_profile is not skipped

      - name: Ensure PAM Enforces Password Requirements - Prevent the Use of Dictionary
          Words - Ensure authselect changes are applied
        ansible.builtin.command:
          cmd: authselect apply-changes -b --backup=after-hardening-custom-profile
        when:
        - result_authselect_check_cmd is success
        - result_authselect_profile is not skipped
        - result_pam_authselect_restore_features is not skipped

      - name: Ensure PAM Enforces Password Requirements - Prevent the Use of Dictionary
          Words - Change the PAM file to be edited according to the custom authselect
          profile
        ansible.builtin.set_fact:
          pam_file_path: /etc/authselect/{{ authselect_custom_profile }}/{{ pam_file_path
            | basename }}
        when:
        - authselect_custom_profile is defined
      when:
      - result_authselect_present.stat.exists

    - name: Ensure PAM Enforces Password Requirements - Prevent the Use of Dictionary
        Words - Define a fact for control already filtered in case filters are used
      ansible.builtin.set_fact:
        pam_module_control: ''

    - name: Ensure PAM Enforces Password Requirements - Prevent the Use of Dictionary
        Words - Check if {{ pam_file_path }} file is present
      ansible.builtin.stat:
        path: '{{ pam_file_path }}'
      register: result_pam_file_present

    - name: Ensure PAM Enforces Password Requirements - Prevent the Use of Dictionary
        Words - Ensure the "dictcheck" option from "pam_pwquality.so" is not present
        in {{ pam_file_path }}
      ansible.builtin.replace:
        dest: '{{ pam_file_path }}'
        regexp: (.*password.*pam_pwquality.so.*)\bdictcheck\b=?[0-9a-zA-Z]*(.*)
        replace: \1\2
      register: result_pam_option_removal
      when:
      - result_pam_file_present.stat.exists

    - name: Ensure PAM Enforces Password Requirements - Prevent the Use of Dictionary
        Words - Ensure authselect changes are applied
      ansible.builtin.command:
        cmd: authselect apply-changes -b
      when:
      - result_authselect_present.stat.exists
      - result_pam_option_removal is changed
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - '"libpwquality" in ansible_facts.packages'
    - result_pam_password_auth_file_present.stat.exists
    tags:
    - DISA-STIG-OL09-00-001125
    - NIST-800-53-CM-6(a)
    - NIST-800-53-IA-5(1)(a)
    - NIST-800-53-IA-5(4)
    - NIST-800-53-IA-5(c)
    - accounts_password_pam_dictcheck
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Ensure PAM Enforces Password Requirements - Prevent the Use of Dictionary
      Words - Ensure PAM variable dictcheck is set accordingly
    ansible.builtin.lineinfile:
      create: true
      dest: /etc/security/pwquality.conf
      regexp: ^#?\s*dictcheck
      line: dictcheck = {{ var_password_pam_dictcheck }}
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - '"libpwquality" in ansible_facts.packages'
    tags:
    - DISA-STIG-OL09-00-001125
    - NIST-800-53-CM-6(a)
    - NIST-800-53-IA-5(1)(a)
    - NIST-800-53-IA-5(4)
    - NIST-800-53-IA-5(c)
    - accounts_password_pam_dictcheck
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Ensure PAM Enforces Password Requirements - Minimum Different Characters
      - Find pwquality.conf.d files
    ansible.builtin.find:
      paths: /etc/security/pwquality.conf.d/
      patterns: '*.conf'
    register: pwquality_conf_d_files
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - '"libpwquality" in ansible_facts.packages'
    tags:
    - CJIS-5.6.2.1.1
    - DISA-STIG-OL09-00-001025
    - NIST-800-53-CM-6(a)
    - NIST-800-53-IA-5(1)(b)
    - NIST-800-53-IA-5(4)
    - NIST-800-53-IA-5(c)
    - accounts_password_pam_difok
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Ensure PAM Enforces Password Requirements - Minimum Different Characters
      - Ensure difok is not set in pwquality.conf.d
    ansible.builtin.lineinfile:
      path: '{{ item.path }}'
      regexp: ^\s*\bdifok\b.*
      state: absent
    with_items: '{{ pwquality_conf_d_files.files }}'
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - '"libpwquality" in ansible_facts.packages'
    tags:
    - CJIS-5.6.2.1.1
    - DISA-STIG-OL09-00-001025
    - NIST-800-53-CM-6(a)
    - NIST-800-53-IA-5(1)(b)
    - NIST-800-53-IA-5(4)
    - NIST-800-53-IA-5(c)
    - accounts_password_pam_difok
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Ensure PAM Enforces Password Requirements - Minimum Different Characters
      - Check if /etc/pam.d/system-auth file is present
    ansible.builtin.stat:
      path: /etc/pam.d/system-auth
    register: result_pam_auth_file_present
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - '"libpwquality" in ansible_facts.packages'
    tags:
    - CJIS-5.6.2.1.1
    - DISA-STIG-OL09-00-001025
    - NIST-800-53-CM-6(a)
    - NIST-800-53-IA-5(1)(b)
    - NIST-800-53-IA-5(4)
    - NIST-800-53-IA-5(c)
    - accounts_password_pam_difok
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Ensure PAM Enforces Password Requirements - Minimum Different Characters
      - Check the proper remediation for the system
    block:

    - name: Ensure PAM Enforces Password Requirements - Minimum Different Characters
        - Define the PAM file to be edited as a local fact
      ansible.builtin.set_fact:
        pam_file_path: /etc/pam.d/system-auth

    - name: Ensure PAM Enforces Password Requirements - Minimum Different Characters
        - Check if system relies on authselect tool
      ansible.builtin.stat:
        path: /usr/bin/authselect
      register: result_authselect_present

    - name: Ensure PAM Enforces Password Requirements - Minimum Different Characters
        - Ensure authselect custom profile is used if authselect is present
      block:

      - name: Ensure PAM Enforces Password Requirements - Minimum Different Characters
          - Check integrity of authselect current profile
        ansible.builtin.command:
          cmd: authselect check
        register: result_authselect_check_cmd
        changed_when: false
        check_mode: false
        failed_when: false

      - name: Ensure PAM Enforces Password Requirements - Minimum Different Characters
          - Informative message based on the authselect integrity check result
        ansible.builtin.assert:
          that:
          - ansible_check_mode or result_authselect_check_cmd.rc == 0
          fail_msg:
          - authselect integrity check failed. Remediation aborted!
          - This remediation could not be applied because an authselect profile was
            not selected or the selected profile is not intact.
          - It is not recommended to manually edit the PAM files when authselect tool
            is available.
          - In cases where the default authselect profile does not cover a specific
            demand, a custom authselect profile is recommended.
          success_msg:
          - authselect integrity check passed

      - name: Ensure PAM Enforces Password Requirements - Minimum Different Characters
          - Get authselect current profile
        ansible.builtin.shell:
          cmd: authselect current -r | awk '{ print $1 }'
        register: result_authselect_profile
        changed_when: false
        when:
        - result_authselect_check_cmd is success

      - name: Ensure PAM Enforces Password Requirements - Minimum Different Characters
          - Define the current authselect profile as a local fact
        ansible.builtin.set_fact:
          authselect_current_profile: '{{ result_authselect_profile.stdout }}'
          authselect_custom_profile: '{{ result_authselect_profile.stdout }}'
        when:
        - result_authselect_profile is not skipped
        - result_authselect_profile.stdout is match("custom/")

      - name: Ensure PAM Enforces Password Requirements - Minimum Different Characters
          - Define the new authselect custom profile as a local fact
        ansible.builtin.set_fact:
          authselect_current_profile: '{{ result_authselect_profile.stdout }}'
          authselect_custom_profile: custom/hardening
        when:
        - result_authselect_profile is not skipped
        - result_authselect_profile.stdout is not match("custom/")

      - name: Ensure PAM Enforces Password Requirements - Minimum Different Characters
          - Get authselect current features to also enable them in the custom profile
        ansible.builtin.shell:
          cmd: authselect current | tail -n+3 | awk '{ print $2 }'
        register: result_authselect_features
        changed_when: false
        check_mode: false
        when:
        - result_authselect_profile is not skipped
        - authselect_current_profile is not match("custom/")

      - name: Ensure PAM Enforces Password Requirements - Minimum Different Characters
          - Check if any custom profile with the same name was already created
        ansible.builtin.stat:
          path: /etc/authselect/{{ authselect_custom_profile }}
        register: result_authselect_custom_profile_present
        changed_when: false
        when:
        - result_authselect_profile is not skipped
        - authselect_current_profile is not match("custom/")

      - name: Ensure PAM Enforces Password Requirements - Minimum Different Characters
          - Create an authselect custom profile based on the current profile
        ansible.builtin.command:
          cmd: authselect create-profile hardening -b {{ authselect_current_profile
            }}
        when:
        - result_authselect_profile is not skipped
        - result_authselect_check_cmd is success
        - authselect_current_profile is not match("^(custom/|local)")
        - not result_authselect_custom_profile_present.stat.exists

      - name: Ensure PAM Enforces Password Requirements - Minimum Different Characters
          - Create an authselect custom profile based on sssd profile
        ansible.builtin.command:
          cmd: authselect create-profile hardening -b sssd
        when:
        - result_authselect_profile is not skipped
        - result_authselect_check_cmd is success
        - authselect_current_profile is match("local")
        - not result_authselect_custom_profile_present.stat.exists

      - name: Ensure PAM Enforces Password Requirements - Minimum Different Characters
          - Ensure authselect changes are applied
        ansible.builtin.command:
          cmd: authselect apply-changes -b --backup=before-hardening-custom-profile
        when:
        - result_authselect_check_cmd is success
        - result_authselect_profile is not skipped
        - authselect_current_profile is not match("custom/")
        - authselect_custom_profile is not match(authselect_current_profile)

      - name: Ensure PAM Enforces Password Requirements - Minimum Different Characters
          - Ensure the authselect custom profile is selected
        ansible.builtin.command:
          cmd: authselect select {{ authselect_custom_profile }}
        register: result_pam_authselect_select_profile
        when:
        - result_authselect_check_cmd is success
        - result_authselect_profile is not skipped
        - authselect_current_profile is not match("custom/")
        - authselect_custom_profile is not match(authselect_current_profile)

      - name: Ensure PAM Enforces Password Requirements - Minimum Different Characters
          - Restore the authselect features in the custom profile
        ansible.builtin.command:
          cmd: authselect enable-feature {{ item }}
        loop: '{{ result_authselect_features.stdout_lines }}'
        register: result_pam_authselect_restore_features
        when:
        - result_authselect_profile is not skipped
        - result_authselect_features is not skipped
        - result_pam_authselect_select_profile is not skipped

      - name: Ensure PAM Enforces Password Requirements - Minimum Different Characters
          - Ensure authselect changes are applied
        ansible.builtin.command:
          cmd: authselect apply-changes -b --backup=after-hardening-custom-profile
        when:
        - result_authselect_check_cmd is success
        - result_authselect_profile is not skipped
        - result_pam_authselect_restore_features is not skipped

      - name: Ensure PAM Enforces Password Requirements - Minimum Different Characters
          - Change the PAM file to be edited according to the custom authselect profile
        ansible.builtin.set_fact:
          pam_file_path: /etc/authselect/{{ authselect_custom_profile }}/{{ pam_file_path
            | basename }}
        when:
        - authselect_custom_profile is defined
      when:
      - result_authselect_present.stat.exists

    - name: Ensure PAM Enforces Password Requirements - Minimum Different Characters
        - Define a fact for control already filtered in case filters are used
      ansible.builtin.set_fact:
        pam_module_control: ''

    - name: Ensure PAM Enforces Password Requirements - Minimum Different Characters
        - Check if {{ pam_file_path }} file is present
      ansible.builtin.stat:
        path: '{{ pam_file_path }}'
      register: result_pam_file_present

    - name: Ensure PAM Enforces Password Requirements - Minimum Different Characters
        - Ensure the "difok" option from "pam_pwquality.so" is not present in {{ pam_file_path
        }}
      ansible.builtin.replace:
        dest: '{{ pam_file_path }}'
        regexp: (.*password.*pam_pwquality.so.*)\bdifok\b=?[0-9a-zA-Z]*(.*)
        replace: \1\2
      register: result_pam_option_removal
      when:
      - result_pam_file_present.stat.exists

    - name: Ensure PAM Enforces Password Requirements - Minimum Different Characters
        - Ensure authselect changes are applied
      ansible.builtin.command:
        cmd: authselect apply-changes -b
      when:
      - result_authselect_present.stat.exists
      - result_pam_option_removal is changed
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - '"libpwquality" in ansible_facts.packages'
    - result_pam_auth_file_present.stat.exists
    tags:
    - CJIS-5.6.2.1.1
    - DISA-STIG-OL09-00-001025
    - NIST-800-53-CM-6(a)
    - NIST-800-53-IA-5(1)(b)
    - NIST-800-53-IA-5(4)
    - NIST-800-53-IA-5(c)
    - accounts_password_pam_difok
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Ensure PAM Enforces Password Requirements - Minimum Different Characters
      - Check if /etc/pam.d/password-auth file is present
    ansible.builtin.stat:
      path: /etc/pam.d/password-auth
    register: result_pam_password_auth_file_present
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - '"libpwquality" in ansible_facts.packages'
    tags:
    - CJIS-5.6.2.1.1
    - DISA-STIG-OL09-00-001025
    - NIST-800-53-CM-6(a)
    - NIST-800-53-IA-5(1)(b)
    - NIST-800-53-IA-5(4)
    - NIST-800-53-IA-5(c)
    - accounts_password_pam_difok
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Ensure PAM Enforces Password Requirements - Minimum Different Characters
      - Check the proper remediation for the system
    block:

    - name: Ensure PAM Enforces Password Requirements - Minimum Different Characters
        - Define the PAM file to be edited as a local fact
      ansible.builtin.set_fact:
        pam_file_path: /etc/pam.d/password-auth

    - name: Ensure PAM Enforces Password Requirements - Minimum Different Characters
        - Check if system relies on authselect tool
      ansible.builtin.stat:
        path: /usr/bin/authselect
      register: result_authselect_present

    - name: Ensure PAM Enforces Password Requirements - Minimum Different Characters
        - Ensure authselect custom profile is used if authselect is present
      block:

      - name: Ensure PAM Enforces Password Requirements - Minimum Different Characters
          - Check integrity of authselect current profile
        ansible.builtin.command:
          cmd: authselect check
        register: result_authselect_check_cmd
        changed_when: false
        check_mode: false
        failed_when: false

      - name: Ensure PAM Enforces Password Requirements - Minimum Different Characters
          - Informative message based on the authselect integrity check result
        ansible.builtin.assert:
          that:
          - ansible_check_mode or result_authselect_check_cmd.rc == 0
          fail_msg:
          - authselect integrity check failed. Remediation aborted!
          - This remediation could not be applied because an authselect profile was
            not selected or the selected profile is not intact.
          - It is not recommended to manually edit the PAM files when authselect tool
            is available.
          - In cases where the default authselect profile does not cover a specific
            demand, a custom authselect profile is recommended.
          success_msg:
          - authselect integrity check passed

      - name: Ensure PAM Enforces Password Requirements - Minimum Different Characters
          - Get authselect current profile
        ansible.builtin.shell:
          cmd: authselect current -r | awk '{ print $1 }'
        register: result_authselect_profile
        changed_when: false
        when:
        - result_authselect_check_cmd is success

      - name: Ensure PAM Enforces Password Requirements - Minimum Different Characters
          - Define the current authselect profile as a local fact
        ansible.builtin.set_fact:
          authselect_current_profile: '{{ result_authselect_profile.stdout }}'
          authselect_custom_profile: '{{ result_authselect_profile.stdout }}'
        when:
        - result_authselect_profile is not skipped
        - result_authselect_profile.stdout is match("custom/")

      - name: Ensure PAM Enforces Password Requirements - Minimum Different Characters
          - Define the new authselect custom profile as a local fact
        ansible.builtin.set_fact:
          authselect_current_profile: '{{ result_authselect_profile.stdout }}'
          authselect_custom_profile: custom/hardening
        when:
        - result_authselect_profile is not skipped
        - result_authselect_profile.stdout is not match("custom/")

      - name: Ensure PAM Enforces Password Requirements - Minimum Different Characters
          - Get authselect current features to also enable them in the custom profile
        ansible.builtin.shell:
          cmd: authselect current | tail -n+3 | awk '{ print $2 }'
        register: result_authselect_features
        changed_when: false
        check_mode: false
        when:
        - result_authselect_profile is not skipped
        - authselect_current_profile is not match("custom/")

      - name: Ensure PAM Enforces Password Requirements - Minimum Different Characters
          - Check if any custom profile with the same name was already created
        ansible.builtin.stat:
          path: /etc/authselect/{{ authselect_custom_profile }}
        register: result_authselect_custom_profile_present
        changed_when: false
        when:
        - result_authselect_profile is not skipped
        - authselect_current_profile is not match("custom/")

      - name: Ensure PAM Enforces Password Requirements - Minimum Different Characters
          - Create an authselect custom profile based on the current profile
        ansible.builtin.command:
          cmd: authselect create-profile hardening -b {{ authselect_current_profile
            }}
        when:
        - result_authselect_profile is not skipped
        - result_authselect_check_cmd is success
        - authselect_current_profile is not match("^(custom/|local)")
        - not result_authselect_custom_profile_present.stat.exists

      - name: Ensure PAM Enforces Password Requirements - Minimum Different Characters
          - Create an authselect custom profile based on sssd profile
        ansible.builtin.command:
          cmd: authselect create-profile hardening -b sssd
        when:
        - result_authselect_profile is not skipped
        - result_authselect_check_cmd is success
        - authselect_current_profile is match("local")
        - not result_authselect_custom_profile_present.stat.exists

      - name: Ensure PAM Enforces Password Requirements - Minimum Different Characters
          - Ensure authselect changes are applied
        ansible.builtin.command:
          cmd: authselect apply-changes -b --backup=before-hardening-custom-profile
        when:
        - result_authselect_check_cmd is success
        - result_authselect_profile is not skipped
        - authselect_current_profile is not match("custom/")
        - authselect_custom_profile is not match(authselect_current_profile)

      - name: Ensure PAM Enforces Password Requirements - Minimum Different Characters
          - Ensure the authselect custom profile is selected
        ansible.builtin.command:
          cmd: authselect select {{ authselect_custom_profile }}
        register: result_pam_authselect_select_profile
        when:
        - result_authselect_check_cmd is success
        - result_authselect_profile is not skipped
        - authselect_current_profile is not match("custom/")
        - authselect_custom_profile is not match(authselect_current_profile)

      - name: Ensure PAM Enforces Password Requirements - Minimum Different Characters
          - Restore the authselect features in the custom profile
        ansible.builtin.command:
          cmd: authselect enable-feature {{ item }}
        loop: '{{ result_authselect_features.stdout_lines }}'
        register: result_pam_authselect_restore_features
        when:
        - result_authselect_profile is not skipped
        - result_authselect_features is not skipped
        - result_pam_authselect_select_profile is not skipped

      - name: Ensure PAM Enforces Password Requirements - Minimum Different Characters
          - Ensure authselect changes are applied
        ansible.builtin.command:
          cmd: authselect apply-changes -b --backup=after-hardening-custom-profile
        when:
        - result_authselect_check_cmd is success
        - result_authselect_profile is not skipped
        - result_pam_authselect_restore_features is not skipped

      - name: Ensure PAM Enforces Password Requirements - Minimum Different Characters
          - Change the PAM file to be edited according to the custom authselect profile
        ansible.builtin.set_fact:
          pam_file_path: /etc/authselect/{{ authselect_custom_profile }}/{{ pam_file_path
            | basename }}
        when:
        - authselect_custom_profile is defined
      when:
      - result_authselect_present.stat.exists

    - name: Ensure PAM Enforces Password Requirements - Minimum Different Characters
        - Define a fact for control already filtered in case filters are used
      ansible.builtin.set_fact:
        pam_module_control: ''

    - name: Ensure PAM Enforces Password Requirements - Minimum Different Characters
        - Check if {{ pam_file_path }} file is present
      ansible.builtin.stat:
        path: '{{ pam_file_path }}'
      register: result_pam_file_present

    - name: Ensure PAM Enforces Password Requirements - Minimum Different Characters
        - Ensure the "difok" option from "pam_pwquality.so" is not present in {{ pam_file_path
        }}
      ansible.builtin.replace:
        dest: '{{ pam_file_path }}'
        regexp: (.*password.*pam_pwquality.so.*)\bdifok\b=?[0-9a-zA-Z]*(.*)
        replace: \1\2
      register: result_pam_option_removal
      when:
      - result_pam_file_present.stat.exists

    - name: Ensure PAM Enforces Password Requirements - Minimum Different Characters
        - Ensure authselect changes are applied
      ansible.builtin.command:
        cmd: authselect apply-changes -b
      when:
      - result_authselect_present.stat.exists
      - result_pam_option_removal is changed
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - '"libpwquality" in ansible_facts.packages'
    - result_pam_password_auth_file_present.stat.exists
    tags:
    - CJIS-5.6.2.1.1
    - DISA-STIG-OL09-00-001025
    - NIST-800-53-CM-6(a)
    - NIST-800-53-IA-5(1)(b)
    - NIST-800-53-IA-5(4)
    - NIST-800-53-IA-5(c)
    - accounts_password_pam_difok
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Ensure PAM Enforces Password Requirements - Minimum Different Characters
      - Ensure PAM variable difok is set accordingly
    ansible.builtin.lineinfile:
      create: true
      dest: /etc/security/pwquality.conf
      regexp: ^#?\s*difok
      line: difok = {{ var_password_pam_difok }}
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - '"libpwquality" in ansible_facts.packages'
    tags:
    - CJIS-5.6.2.1.1
    - DISA-STIG-OL09-00-001025
    - NIST-800-53-CM-6(a)
    - NIST-800-53-IA-5(1)(b)
    - NIST-800-53-IA-5(4)
    - NIST-800-53-IA-5(c)
    - accounts_password_pam_difok
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Ensure PAM Enforces Password Requirements - Enforce for root User
    ansible.builtin.lineinfile:
      path: /etc/security/pwquality.conf
      create: true
      regexp: ''
      line: enforce_for_root
      state: present
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - '"libpwquality" in ansible_facts.packages'
    tags:
    - DISA-STIG-OL09-00-001045
    - NIST-800-53-CM-6(a)
    - NIST-800-53-IA-5(1)(a)
    - NIST-800-53-IA-5(4)
    - NIST-800-53-IA-5(c)
    - accounts_password_pam_enforce_root
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Ensure PAM Enforces Password Requirements - Minimum Lowercase Characters
      - Find pwquality.conf.d files
    ansible.builtin.find:
      paths: /etc/security/pwquality.conf.d/
      patterns: '*.conf'
    register: pwquality_conf_d_files
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - '"libpwquality" in ansible_facts.packages'
    tags:
    - DISA-STIG-OL09-00-001015
    - NIST-800-53-CM-6(a)
    - NIST-800-53-IA-5(1)(a)
    - NIST-800-53-IA-5(4)
    - NIST-800-53-IA-5(c)
    - PCI-DSS-Req-8.2.3
    - PCI-DSSv4-8.3
    - PCI-DSSv4-8.3.6
    - accounts_password_pam_lcredit
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Ensure PAM Enforces Password Requirements - Minimum Lowercase Characters
      - Ensure lcredit is not set in pwquality.conf.d
    ansible.builtin.lineinfile:
      path: '{{ item.path }}'
      regexp: ^\s*\blcredit\b.*
      state: absent
    with_items: '{{ pwquality_conf_d_files.files }}'
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - '"libpwquality" in ansible_facts.packages'
    tags:
    - DISA-STIG-OL09-00-001015
    - NIST-800-53-CM-6(a)
    - NIST-800-53-IA-5(1)(a)
    - NIST-800-53-IA-5(4)
    - NIST-800-53-IA-5(c)
    - PCI-DSS-Req-8.2.3
    - PCI-DSSv4-8.3
    - PCI-DSSv4-8.3.6
    - accounts_password_pam_lcredit
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Ensure PAM Enforces Password Requirements - Minimum Lowercase Characters
      - Check if /etc/pam.d/system-auth file is present
    ansible.builtin.stat:
      path: /etc/pam.d/system-auth
    register: result_pam_auth_file_present
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - '"libpwquality" in ansible_facts.packages'
    tags:
    - DISA-STIG-OL09-00-001015
    - NIST-800-53-CM-6(a)
    - NIST-800-53-IA-5(1)(a)
    - NIST-800-53-IA-5(4)
    - NIST-800-53-IA-5(c)
    - PCI-DSS-Req-8.2.3
    - PCI-DSSv4-8.3
    - PCI-DSSv4-8.3.6
    - accounts_password_pam_lcredit
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Ensure PAM Enforces Password Requirements - Minimum Lowercase Characters
      - Check the proper remediation for the system
    block:

    - name: Ensure PAM Enforces Password Requirements - Minimum Lowercase Characters
        - Define the PAM file to be edited as a local fact
      ansible.builtin.set_fact:
        pam_file_path: /etc/pam.d/system-auth

    - name: Ensure PAM Enforces Password Requirements - Minimum Lowercase Characters
        - Check if system relies on authselect tool
      ansible.builtin.stat:
        path: /usr/bin/authselect
      register: result_authselect_present

    - name: Ensure PAM Enforces Password Requirements - Minimum Lowercase Characters
        - Ensure authselect custom profile is used if authselect is present
      block:

      - name: Ensure PAM Enforces Password Requirements - Minimum Lowercase Characters
          - Check integrity of authselect current profile
        ansible.builtin.command:
          cmd: authselect check
        register: result_authselect_check_cmd
        changed_when: false
        check_mode: false
        failed_when: false

      - name: Ensure PAM Enforces Password Requirements - Minimum Lowercase Characters
          - Informative message based on the authselect integrity check result
        ansible.builtin.assert:
          that:
          - ansible_check_mode or result_authselect_check_cmd.rc == 0
          fail_msg:
          - authselect integrity check failed. Remediation aborted!
          - This remediation could not be applied because an authselect profile was
            not selected or the selected profile is not intact.
          - It is not recommended to manually edit the PAM files when authselect tool
            is available.
          - In cases where the default authselect profile does not cover a specific
            demand, a custom authselect profile is recommended.
          success_msg:
          - authselect integrity check passed

      - name: Ensure PAM Enforces Password Requirements - Minimum Lowercase Characters
          - Get authselect current profile
        ansible.builtin.shell:
          cmd: authselect current -r | awk '{ print $1 }'
        register: result_authselect_profile
        changed_when: false
        when:
        - result_authselect_check_cmd is success

      - name: Ensure PAM Enforces Password Requirements - Minimum Lowercase Characters
          - Define the current authselect profile as a local fact
        ansible.builtin.set_fact:
          authselect_current_profile: '{{ result_authselect_profile.stdout }}'
          authselect_custom_profile: '{{ result_authselect_profile.stdout }}'
        when:
        - result_authselect_profile is not skipped
        - result_authselect_profile.stdout is match("custom/")

      - name: Ensure PAM Enforces Password Requirements - Minimum Lowercase Characters
          - Define the new authselect custom profile as a local fact
        ansible.builtin.set_fact:
          authselect_current_profile: '{{ result_authselect_profile.stdout }}'
          authselect_custom_profile: custom/hardening
        when:
        - result_authselect_profile is not skipped
        - result_authselect_profile.stdout is not match("custom/")

      - name: Ensure PAM Enforces Password Requirements - Minimum Lowercase Characters
          - Get authselect current features to also enable them in the custom profile
        ansible.builtin.shell:
          cmd: authselect current | tail -n+3 | awk '{ print $2 }'
        register: result_authselect_features
        changed_when: false
        check_mode: false
        when:
        - result_authselect_profile is not skipped
        - authselect_current_profile is not match("custom/")

      - name: Ensure PAM Enforces Password Requirements - Minimum Lowercase Characters
          - Check if any custom profile with the same name was already created
        ansible.builtin.stat:
          path: /etc/authselect/{{ authselect_custom_profile }}
        register: result_authselect_custom_profile_present
        changed_when: false
        when:
        - result_authselect_profile is not skipped
        - authselect_current_profile is not match("custom/")

      - name: Ensure PAM Enforces Password Requirements - Minimum Lowercase Characters
          - Create an authselect custom profile based on the current profile
        ansible.builtin.command:
          cmd: authselect create-profile hardening -b {{ authselect_current_profile
            }}
        when:
        - result_authselect_profile is not skipped
        - result_authselect_check_cmd is success
        - authselect_current_profile is not match("^(custom/|local)")
        - not result_authselect_custom_profile_present.stat.exists

      - name: Ensure PAM Enforces Password Requirements - Minimum Lowercase Characters
          - Create an authselect custom profile based on sssd profile
        ansible.builtin.command:
          cmd: authselect create-profile hardening -b sssd
        when:
        - result_authselect_profile is not skipped
        - result_authselect_check_cmd is success
        - authselect_current_profile is match("local")
        - not result_authselect_custom_profile_present.stat.exists

      - name: Ensure PAM Enforces Password Requirements - Minimum Lowercase Characters
          - Ensure authselect changes are applied
        ansible.builtin.command:
          cmd: authselect apply-changes -b --backup=before-hardening-custom-profile
        when:
        - result_authselect_check_cmd is success
        - result_authselect_profile is not skipped
        - authselect_current_profile is not match("custom/")
        - authselect_custom_profile is not match(authselect_current_profile)

      - name: Ensure PAM Enforces Password Requirements - Minimum Lowercase Characters
          - Ensure the authselect custom profile is selected
        ansible.builtin.command:
          cmd: authselect select {{ authselect_custom_profile }}
        register: result_pam_authselect_select_profile
        when:
        - result_authselect_check_cmd is success
        - result_authselect_profile is not skipped
        - authselect_current_profile is not match("custom/")
        - authselect_custom_profile is not match(authselect_current_profile)

      - name: Ensure PAM Enforces Password Requirements - Minimum Lowercase Characters
          - Restore the authselect features in the custom profile
        ansible.builtin.command:
          cmd: authselect enable-feature {{ item }}
        loop: '{{ result_authselect_features.stdout_lines }}'
        register: result_pam_authselect_restore_features
        when:
        - result_authselect_profile is not skipped
        - result_authselect_features is not skipped
        - result_pam_authselect_select_profile is not skipped

      - name: Ensure PAM Enforces Password Requirements - Minimum Lowercase Characters
          - Ensure authselect changes are applied
        ansible.builtin.command:
          cmd: authselect apply-changes -b --backup=after-hardening-custom-profile
        when:
        - result_authselect_check_cmd is success
        - result_authselect_profile is not skipped
        - result_pam_authselect_restore_features is not skipped

      - name: Ensure PAM Enforces Password Requirements - Minimum Lowercase Characters
          - Change the PAM file to be edited according to the custom authselect profile
        ansible.builtin.set_fact:
          pam_file_path: /etc/authselect/{{ authselect_custom_profile }}/{{ pam_file_path
            | basename }}
        when:
        - authselect_custom_profile is defined
      when:
      - result_authselect_present.stat.exists

    - name: Ensure PAM Enforces Password Requirements - Minimum Lowercase Characters
        - Define a fact for control already filtered in case filters are used
      ansible.builtin.set_fact:
        pam_module_control: ''

    - name: Ensure PAM Enforces Password Requirements - Minimum Lowercase Characters
        - Check if {{ pam_file_path }} file is present
      ansible.builtin.stat:
        path: '{{ pam_file_path }}'
      register: result_pam_file_present

    - name: Ensure PAM Enforces Password Requirements - Minimum Lowercase Characters
        - Ensure the "lcredit" option from "pam_pwquality.so" is not present in {{
        pam_file_path }}
      ansible.builtin.replace:
        dest: '{{ pam_file_path }}'
        regexp: (.*password.*pam_pwquality.so.*)\blcredit\b=?[0-9a-zA-Z]*(.*)
        replace: \1\2
      register: result_pam_option_removal
      when:
      - result_pam_file_present.stat.exists

    - name: Ensure PAM Enforces Password Requirements - Minimum Lowercase Characters
        - Ensure authselect changes are applied
      ansible.builtin.command:
        cmd: authselect apply-changes -b
      when:
      - result_authselect_present.stat.exists
      - result_pam_option_removal is changed
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - '"libpwquality" in ansible_facts.packages'
    - result_pam_auth_file_present.stat.exists
    tags:
    - DISA-STIG-OL09-00-001015
    - NIST-800-53-CM-6(a)
    - NIST-800-53-IA-5(1)(a)
    - NIST-800-53-IA-5(4)
    - NIST-800-53-IA-5(c)
    - PCI-DSS-Req-8.2.3
    - PCI-DSSv4-8.3
    - PCI-DSSv4-8.3.6
    - accounts_password_pam_lcredit
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Ensure PAM Enforces Password Requirements - Minimum Lowercase Characters
      - Check if /etc/pam.d/password-auth file is present
    ansible.builtin.stat:
      path: /etc/pam.d/password-auth
    register: result_pam_password_auth_file_present
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - '"libpwquality" in ansible_facts.packages'
    tags:
    - DISA-STIG-OL09-00-001015
    - NIST-800-53-CM-6(a)
    - NIST-800-53-IA-5(1)(a)
    - NIST-800-53-IA-5(4)
    - NIST-800-53-IA-5(c)
    - PCI-DSS-Req-8.2.3
    - PCI-DSSv4-8.3
    - PCI-DSSv4-8.3.6
    - accounts_password_pam_lcredit
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Ensure PAM Enforces Password Requirements - Minimum Lowercase Characters
      - Check the proper remediation for the system
    block:

    - name: Ensure PAM Enforces Password Requirements - Minimum Lowercase Characters
        - Define the PAM file to be edited as a local fact
      ansible.builtin.set_fact:
        pam_file_path: /etc/pam.d/password-auth

    - name: Ensure PAM Enforces Password Requirements - Minimum Lowercase Characters
        - Check if system relies on authselect tool
      ansible.builtin.stat:
        path: /usr/bin/authselect
      register: result_authselect_present

    - name: Ensure PAM Enforces Password Requirements - Minimum Lowercase Characters
        - Ensure authselect custom profile is used if authselect is present
      block:

      - name: Ensure PAM Enforces Password Requirements - Minimum Lowercase Characters
          - Check integrity of authselect current profile
        ansible.builtin.command:
          cmd: authselect check
        register: result_authselect_check_cmd
        changed_when: false
        check_mode: false
        failed_when: false

      - name: Ensure PAM Enforces Password Requirements - Minimum Lowercase Characters
          - Informative message based on the authselect integrity check result
        ansible.builtin.assert:
          that:
          - ansible_check_mode or result_authselect_check_cmd.rc == 0
          fail_msg:
          - authselect integrity check failed. Remediation aborted!
          - This remediation could not be applied because an authselect profile was
            not selected or the selected profile is not intact.
          - It is not recommended to manually edit the PAM files when authselect tool
            is available.
          - In cases where the default authselect profile does not cover a specific
            demand, a custom authselect profile is recommended.
          success_msg:
          - authselect integrity check passed

      - name: Ensure PAM Enforces Password Requirements - Minimum Lowercase Characters
          - Get authselect current profile
        ansible.builtin.shell:
          cmd: authselect current -r | awk '{ print $1 }'
        register: result_authselect_profile
        changed_when: false
        when:
        - result_authselect_check_cmd is success

      - name: Ensure PAM Enforces Password Requirements - Minimum Lowercase Characters
          - Define the current authselect profile as a local fact
        ansible.builtin.set_fact:
          authselect_current_profile: '{{ result_authselect_profile.stdout }}'
          authselect_custom_profile: '{{ result_authselect_profile.stdout }}'
        when:
        - result_authselect_profile is not skipped
        - result_authselect_profile.stdout is match("custom/")

      - name: Ensure PAM Enforces Password Requirements - Minimum Lowercase Characters
          - Define the new authselect custom profile as a local fact
        ansible.builtin.set_fact:
          authselect_current_profile: '{{ result_authselect_profile.stdout }}'
          authselect_custom_profile: custom/hardening
        when:
        - result_authselect_profile is not skipped
        - result_authselect_profile.stdout is not match("custom/")

      - name: Ensure PAM Enforces Password Requirements - Minimum Lowercase Characters
          - Get authselect current features to also enable them in the custom profile
        ansible.builtin.shell:
          cmd: authselect current | tail -n+3 | awk '{ print $2 }'
        register: result_authselect_features
        changed_when: false
        check_mode: false
        when:
        - result_authselect_profile is not skipped
        - authselect_current_profile is not match("custom/")

      - name: Ensure PAM Enforces Password Requirements - Minimum Lowercase Characters
          - Check if any custom profile with the same name was already created
        ansible.builtin.stat:
          path: /etc/authselect/{{ authselect_custom_profile }}
        register: result_authselect_custom_profile_present
        changed_when: false
        when:
        - result_authselect_profile is not skipped
        - authselect_current_profile is not match("custom/")

      - name: Ensure PAM Enforces Password Requirements - Minimum Lowercase Characters
          - Create an authselect custom profile based on the current profile
        ansible.builtin.command:
          cmd: authselect create-profile hardening -b {{ authselect_current_profile
            }}
        when:
        - result_authselect_profile is not skipped
        - result_authselect_check_cmd is success
        - authselect_current_profile is not match("^(custom/|local)")
        - not result_authselect_custom_profile_present.stat.exists

      - name: Ensure PAM Enforces Password Requirements - Minimum Lowercase Characters
          - Create an authselect custom profile based on sssd profile
        ansible.builtin.command:
          cmd: authselect create-profile hardening -b sssd
        when:
        - result_authselect_profile is not skipped
        - result_authselect_check_cmd is success
        - authselect_current_profile is match("local")
        - not result_authselect_custom_profile_present.stat.exists

      - name: Ensure PAM Enforces Password Requirements - Minimum Lowercase Characters
          - Ensure authselect changes are applied
        ansible.builtin.command:
          cmd: authselect apply-changes -b --backup=before-hardening-custom-profile
        when:
        - result_authselect_check_cmd is success
        - result_authselect_profile is not skipped
        - authselect_current_profile is not match("custom/")
        - authselect_custom_profile is not match(authselect_current_profile)

      - name: Ensure PAM Enforces Password Requirements - Minimum Lowercase Characters
          - Ensure the authselect custom profile is selected
        ansible.builtin.command:
          cmd: authselect select {{ authselect_custom_profile }}
        register: result_pam_authselect_select_profile
        when:
        - result_authselect_check_cmd is success
        - result_authselect_profile is not skipped
        - authselect_current_profile is not match("custom/")
        - authselect_custom_profile is not match(authselect_current_profile)

      - name: Ensure PAM Enforces Password Requirements - Minimum Lowercase Characters
          - Restore the authselect features in the custom profile
        ansible.builtin.command:
          cmd: authselect enable-feature {{ item }}
        loop: '{{ result_authselect_features.stdout_lines }}'
        register: result_pam_authselect_restore_features
        when:
        - result_authselect_profile is not skipped
        - result_authselect_features is not skipped
        - result_pam_authselect_select_profile is not skipped

      - name: Ensure PAM Enforces Password Requirements - Minimum Lowercase Characters
          - Ensure authselect changes are applied
        ansible.builtin.command:
          cmd: authselect apply-changes -b --backup=after-hardening-custom-profile
        when:
        - result_authselect_check_cmd is success
        - result_authselect_profile is not skipped
        - result_pam_authselect_restore_features is not skipped

      - name: Ensure PAM Enforces Password Requirements - Minimum Lowercase Characters
          - Change the PAM file to be edited according to the custom authselect profile
        ansible.builtin.set_fact:
          pam_file_path: /etc/authselect/{{ authselect_custom_profile }}/{{ pam_file_path
            | basename }}
        when:
        - authselect_custom_profile is defined
      when:
      - result_authselect_present.stat.exists

    - name: Ensure PAM Enforces Password Requirements - Minimum Lowercase Characters
        - Define a fact for control already filtered in case filters are used
      ansible.builtin.set_fact:
        pam_module_control: ''

    - name: Ensure PAM Enforces Password Requirements - Minimum Lowercase Characters
        - Check if {{ pam_file_path }} file is present
      ansible.builtin.stat:
        path: '{{ pam_file_path }}'
      register: result_pam_file_present

    - name: Ensure PAM Enforces Password Requirements - Minimum Lowercase Characters
        - Ensure the "lcredit" option from "pam_pwquality.so" is not present in {{
        pam_file_path }}
      ansible.builtin.replace:
        dest: '{{ pam_file_path }}'
        regexp: (.*password.*pam_pwquality.so.*)\blcredit\b=?[0-9a-zA-Z]*(.*)
        replace: \1\2
      register: result_pam_option_removal
      when:
      - result_pam_file_present.stat.exists

    - name: Ensure PAM Enforces Password Requirements - Minimum Lowercase Characters
        - Ensure authselect changes are applied
      ansible.builtin.command:
        cmd: authselect apply-changes -b
      when:
      - result_authselect_present.stat.exists
      - result_pam_option_removal is changed
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - '"libpwquality" in ansible_facts.packages'
    - result_pam_password_auth_file_present.stat.exists
    tags:
    - DISA-STIG-OL09-00-001015
    - NIST-800-53-CM-6(a)
    - NIST-800-53-IA-5(1)(a)
    - NIST-800-53-IA-5(4)
    - NIST-800-53-IA-5(c)
    - PCI-DSS-Req-8.2.3
    - PCI-DSSv4-8.3
    - PCI-DSSv4-8.3.6
    - accounts_password_pam_lcredit
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Ensure PAM Enforces Password Requirements - Minimum Lowercase Characters
      - Ensure PAM variable lcredit is set accordingly
    ansible.builtin.lineinfile:
      create: true
      dest: /etc/security/pwquality.conf
      regexp: ^#?\s*lcredit
      line: lcredit = {{ var_password_pam_lcredit }}
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - '"libpwquality" in ansible_facts.packages'
    tags:
    - DISA-STIG-OL09-00-001015
    - NIST-800-53-CM-6(a)
    - NIST-800-53-IA-5(1)(a)
    - NIST-800-53-IA-5(4)
    - NIST-800-53-IA-5(c)
    - PCI-DSS-Req-8.2.3
    - PCI-DSSv4-8.3
    - PCI-DSSv4-8.3.6
    - accounts_password_pam_lcredit
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Ensure PAM Enforces Password Requirements - Maximum Consecutive Repeating
      Characters from Same Character Class - Find pwquality.conf.d files
    ansible.builtin.find:
      paths: /etc/security/pwquality.conf.d/
      patterns: '*.conf'
    register: pwquality_conf_d_files
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - '"libpwquality" in ansible_facts.packages'
    tags:
    - DISA-STIG-OL09-00-001030
    - NIST-800-53-CM-6(a)
    - NIST-800-53-IA-5(1)(a)
    - NIST-800-53-IA-5(4)
    - NIST-800-53-IA-5(c)
    - accounts_password_pam_maxclassrepeat
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Ensure PAM Enforces Password Requirements - Maximum Consecutive Repeating
      Characters from Same Character Class - Ensure maxclassrepeat is not set in pwquality.conf.d
    ansible.builtin.lineinfile:
      path: '{{ item.path }}'
      regexp: ^\s*\bmaxclassrepeat\b.*
      state: absent
    with_items: '{{ pwquality_conf_d_files.files }}'
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - '"libpwquality" in ansible_facts.packages'
    tags:
    - DISA-STIG-OL09-00-001030
    - NIST-800-53-CM-6(a)
    - NIST-800-53-IA-5(1)(a)
    - NIST-800-53-IA-5(4)
    - NIST-800-53-IA-5(c)
    - accounts_password_pam_maxclassrepeat
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Ensure PAM Enforces Password Requirements - Maximum Consecutive Repeating
      Characters from Same Character Class - Check if /etc/pam.d/system-auth file
      is present
    ansible.builtin.stat:
      path: /etc/pam.d/system-auth
    register: result_pam_auth_file_present
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - '"libpwquality" in ansible_facts.packages'
    tags:
    - DISA-STIG-OL09-00-001030
    - NIST-800-53-CM-6(a)
    - NIST-800-53-IA-5(1)(a)
    - NIST-800-53-IA-5(4)
    - NIST-800-53-IA-5(c)
    - accounts_password_pam_maxclassrepeat
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Ensure PAM Enforces Password Requirements - Maximum Consecutive Repeating
      Characters from Same Character Class - Check the proper remediation for the
      system
    block:

    - name: Ensure PAM Enforces Password Requirements - Maximum Consecutive Repeating
        Characters from Same Character Class - Define the PAM file to be edited as
        a local fact
      ansible.builtin.set_fact:
        pam_file_path: /etc/pam.d/system-auth

    - name: Ensure PAM Enforces Password Requirements - Maximum Consecutive Repeating
        Characters from Same Character Class - Check if system relies on authselect
        tool
      ansible.builtin.stat:
        path: /usr/bin/authselect
      register: result_authselect_present

    - name: Ensure PAM Enforces Password Requirements - Maximum Consecutive Repeating
        Characters from Same Character Class - Ensure authselect custom profile is
        used if authselect is present
      block:

      - name: Ensure PAM Enforces Password Requirements - Maximum Consecutive Repeating
          Characters from Same Character Class - Check integrity of authselect current
          profile
        ansible.builtin.command:
          cmd: authselect check
        register: result_authselect_check_cmd
        changed_when: false
        check_mode: false
        failed_when: false

      - name: Ensure PAM Enforces Password Requirements - Maximum Consecutive Repeating
          Characters from Same Character Class - Informative message based on the
          authselect integrity check result
        ansible.builtin.assert:
          that:
          - ansible_check_mode or result_authselect_check_cmd.rc == 0
          fail_msg:
          - authselect integrity check failed. Remediation aborted!
          - This remediation could not be applied because an authselect profile was
            not selected or the selected profile is not intact.
          - It is not recommended to manually edit the PAM files when authselect tool
            is available.
          - In cases where the default authselect profile does not cover a specific
            demand, a custom authselect profile is recommended.
          success_msg:
          - authselect integrity check passed

      - name: Ensure PAM Enforces Password Requirements - Maximum Consecutive Repeating
          Characters from Same Character Class - Get authselect current profile
        ansible.builtin.shell:
          cmd: authselect current -r | awk '{ print $1 }'
        register: result_authselect_profile
        changed_when: false
        when:
        - result_authselect_check_cmd is success

      - name: Ensure PAM Enforces Password Requirements - Maximum Consecutive Repeating
          Characters from Same Character Class - Define the current authselect profile
          as a local fact
        ansible.builtin.set_fact:
          authselect_current_profile: '{{ result_authselect_profile.stdout }}'
          authselect_custom_profile: '{{ result_authselect_profile.stdout }}'
        when:
        - result_authselect_profile is not skipped
        - result_authselect_profile.stdout is match("custom/")

      - name: Ensure PAM Enforces Password Requirements - Maximum Consecutive Repeating
          Characters from Same Character Class - Define the new authselect custom
          profile as a local fact
        ansible.builtin.set_fact:
          authselect_current_profile: '{{ result_authselect_profile.stdout }}'
          authselect_custom_profile: custom/hardening
        when:
        - result_authselect_profile is not skipped
        - result_authselect_profile.stdout is not match("custom/")

      - name: Ensure PAM Enforces Password Requirements - Maximum Consecutive Repeating
          Characters from Same Character Class - Get authselect current features to
          also enable them in the custom profile
        ansible.builtin.shell:
          cmd: authselect current | tail -n+3 | awk '{ print $2 }'
        register: result_authselect_features
        changed_when: false
        check_mode: false
        when:
        - result_authselect_profile is not skipped
        - authselect_current_profile is not match("custom/")

      - name: Ensure PAM Enforces Password Requirements - Maximum Consecutive Repeating
          Characters from Same Character Class - Check if any custom profile with
          the same name was already created
        ansible.builtin.stat:
          path: /etc/authselect/{{ authselect_custom_profile }}
        register: result_authselect_custom_profile_present
        changed_when: false
        when:
        - result_authselect_profile is not skipped
        - authselect_current_profile is not match("custom/")

      - name: Ensure PAM Enforces Password Requirements - Maximum Consecutive Repeating
          Characters from Same Character Class - Create an authselect custom profile
          based on the current profile
        ansible.builtin.command:
          cmd: authselect create-profile hardening -b {{ authselect_current_profile
            }}
        when:
        - result_authselect_profile is not skipped
        - result_authselect_check_cmd is success
        - authselect_current_profile is not match("^(custom/|local)")
        - not result_authselect_custom_profile_present.stat.exists

      - name: Ensure PAM Enforces Password Requirements - Maximum Consecutive Repeating
          Characters from Same Character Class - Create an authselect custom profile
          based on sssd profile
        ansible.builtin.command:
          cmd: authselect create-profile hardening -b sssd
        when:
        - result_authselect_profile is not skipped
        - result_authselect_check_cmd is success
        - authselect_current_profile is match("local")
        - not result_authselect_custom_profile_present.stat.exists

      - name: Ensure PAM Enforces Password Requirements - Maximum Consecutive Repeating
          Characters from Same Character Class - Ensure authselect changes are applied
        ansible.builtin.command:
          cmd: authselect apply-changes -b --backup=before-hardening-custom-profile
        when:
        - result_authselect_check_cmd is success
        - result_authselect_profile is not skipped
        - authselect_current_profile is not match("custom/")
        - authselect_custom_profile is not match(authselect_current_profile)

      - name: Ensure PAM Enforces Password Requirements - Maximum Consecutive Repeating
          Characters from Same Character Class - Ensure the authselect custom profile
          is selected
        ansible.builtin.command:
          cmd: authselect select {{ authselect_custom_profile }}
        register: result_pam_authselect_select_profile
        when:
        - result_authselect_check_cmd is success
        - result_authselect_profile is not skipped
        - authselect_current_profile is not match("custom/")
        - authselect_custom_profile is not match(authselect_current_profile)

      - name: Ensure PAM Enforces Password Requirements - Maximum Consecutive Repeating
          Characters from Same Character Class - Restore the authselect features in
          the custom profile
        ansible.builtin.command:
          cmd: authselect enable-feature {{ item }}
        loop: '{{ result_authselect_features.stdout_lines }}'
        register: result_pam_authselect_restore_features
        when:
        - result_authselect_profile is not skipped
        - result_authselect_features is not skipped
        - result_pam_authselect_select_profile is not skipped

      - name: Ensure PAM Enforces Password Requirements - Maximum Consecutive Repeating
          Characters from Same Character Class - Ensure authselect changes are applied
        ansible.builtin.command:
          cmd: authselect apply-changes -b --backup=after-hardening-custom-profile
        when:
        - result_authselect_check_cmd is success
        - result_authselect_profile is not skipped
        - result_pam_authselect_restore_features is not skipped

      - name: Ensure PAM Enforces Password Requirements - Maximum Consecutive Repeating
          Characters from Same Character Class - Change the PAM file to be edited
          according to the custom authselect profile
        ansible.builtin.set_fact:
          pam_file_path: /etc/authselect/{{ authselect_custom_profile }}/{{ pam_file_path
            | basename }}
        when:
        - authselect_custom_profile is defined
      when:
      - result_authselect_present.stat.exists

    - name: Ensure PAM Enforces Password Requirements - Maximum Consecutive Repeating
        Characters from Same Character Class - Define a fact for control already filtered
        in case filters are used
      ansible.builtin.set_fact:
        pam_module_control: ''

    - name: Ensure PAM Enforces Password Requirements - Maximum Consecutive Repeating
        Characters from Same Character Class - Check if {{ pam_file_path }} file is
        present
      ansible.builtin.stat:
        path: '{{ pam_file_path }}'
      register: result_pam_file_present

    - name: Ensure PAM Enforces Password Requirements - Maximum Consecutive Repeating
        Characters from Same Character Class - Ensure the "maxclassrepeat" option
        from "pam_pwquality.so" is not present in {{ pam_file_path }}
      ansible.builtin.replace:
        dest: '{{ pam_file_path }}'
        regexp: (.*password.*pam_pwquality.so.*)\bmaxclassrepeat\b=?[0-9a-zA-Z]*(.*)
        replace: \1\2
      register: result_pam_option_removal
      when:
      - result_pam_file_present.stat.exists

    - name: Ensure PAM Enforces Password Requirements - Maximum Consecutive Repeating
        Characters from Same Character Class - Ensure authselect changes are applied
      ansible.builtin.command:
        cmd: authselect apply-changes -b
      when:
      - result_authselect_present.stat.exists
      - result_pam_option_removal is changed
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - '"libpwquality" in ansible_facts.packages'
    - result_pam_auth_file_present.stat.exists
    tags:
    - DISA-STIG-OL09-00-001030
    - NIST-800-53-CM-6(a)
    - NIST-800-53-IA-5(1)(a)
    - NIST-800-53-IA-5(4)
    - NIST-800-53-IA-5(c)
    - accounts_password_pam_maxclassrepeat
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Ensure PAM Enforces Password Requirements - Maximum Consecutive Repeating
      Characters from Same Character Class - Check if /etc/pam.d/password-auth file
      is present
    ansible.builtin.stat:
      path: /etc/pam.d/password-auth
    register: result_pam_password_auth_file_present
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - '"libpwquality" in ansible_facts.packages'
    tags:
    - DISA-STIG-OL09-00-001030
    - NIST-800-53-CM-6(a)
    - NIST-800-53-IA-5(1)(a)
    - NIST-800-53-IA-5(4)
    - NIST-800-53-IA-5(c)
    - accounts_password_pam_maxclassrepeat
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Ensure PAM Enforces Password Requirements - Maximum Consecutive Repeating
      Characters from Same Character Class - Check the proper remediation for the
      system
    block:

    - name: Ensure PAM Enforces Password Requirements - Maximum Consecutive Repeating
        Characters from Same Character Class - Define the PAM file to be edited as
        a local fact
      ansible.builtin.set_fact:
        pam_file_path: /etc/pam.d/password-auth

    - name: Ensure PAM Enforces Password Requirements - Maximum Consecutive Repeating
        Characters from Same Character Class - Check if system relies on authselect
        tool
      ansible.builtin.stat:
        path: /usr/bin/authselect
      register: result_authselect_present

    - name: Ensure PAM Enforces Password Requirements - Maximum Consecutive Repeating
        Characters from Same Character Class - Ensure authselect custom profile is
        used if authselect is present
      block:

      - name: Ensure PAM Enforces Password Requirements - Maximum Consecutive Repeating
          Characters from Same Character Class - Check integrity of authselect current
          profile
        ansible.builtin.command:
          cmd: authselect check
        register: result_authselect_check_cmd
        changed_when: false
        check_mode: false
        failed_when: false

      - name: Ensure PAM Enforces Password Requirements - Maximum Consecutive Repeating
          Characters from Same Character Class - Informative message based on the
          authselect integrity check result
        ansible.builtin.assert:
          that:
          - ansible_check_mode or result_authselect_check_cmd.rc == 0
          fail_msg:
          - authselect integrity check failed. Remediation aborted!
          - This remediation could not be applied because an authselect profile was
            not selected or the selected profile is not intact.
          - It is not recommended to manually edit the PAM files when authselect tool
            is available.
          - In cases where the default authselect profile does not cover a specific
            demand, a custom authselect profile is recommended.
          success_msg:
          - authselect integrity check passed

      - name: Ensure PAM Enforces Password Requirements - Maximum Consecutive Repeating
          Characters from Same Character Class - Get authselect current profile
        ansible.builtin.shell:
          cmd: authselect current -r | awk '{ print $1 }'
        register: result_authselect_profile
        changed_when: false
        when:
        - result_authselect_check_cmd is success

      - name: Ensure PAM Enforces Password Requirements - Maximum Consecutive Repeating
          Characters from Same Character Class - Define the current authselect profile
          as a local fact
        ansible.builtin.set_fact:
          authselect_current_profile: '{{ result_authselect_profile.stdout }}'
          authselect_custom_profile: '{{ result_authselect_profile.stdout }}'
        when:
        - result_authselect_profile is not skipped
        - result_authselect_profile.stdout is match("custom/")

      - name: Ensure PAM Enforces Password Requirements - Maximum Consecutive Repeating
          Characters from Same Character Class - Define the new authselect custom
          profile as a local fact
        ansible.builtin.set_fact:
          authselect_current_profile: '{{ result_authselect_profile.stdout }}'
          authselect_custom_profile: custom/hardening
        when:
        - result_authselect_profile is not skipped
        - result_authselect_profile.stdout is not match("custom/")

      - name: Ensure PAM Enforces Password Requirements - Maximum Consecutive Repeating
          Characters from Same Character Class - Get authselect current features to
          also enable them in the custom profile
        ansible.builtin.shell:
          cmd: authselect current | tail -n+3 | awk '{ print $2 }'
        register: result_authselect_features
        changed_when: false
        check_mode: false
        when:
        - result_authselect_profile is not skipped
        - authselect_current_profile is not match("custom/")

      - name: Ensure PAM Enforces Password Requirements - Maximum Consecutive Repeating
          Characters from Same Character Class - Check if any custom profile with
          the same name was already created
        ansible.builtin.stat:
          path: /etc/authselect/{{ authselect_custom_profile }}
        register: result_authselect_custom_profile_present
        changed_when: false
        when:
        - result_authselect_profile is not skipped
        - authselect_current_profile is not match("custom/")

      - name: Ensure PAM Enforces Password Requirements - Maximum Consecutive Repeating
          Characters from Same Character Class - Create an authselect custom profile
          based on the current profile
        ansible.builtin.command:
          cmd: authselect create-profile hardening -b {{ authselect_current_profile
            }}
        when:
        - result_authselect_profile is not skipped
        - result_authselect_check_cmd is success
        - authselect_current_profile is not match("^(custom/|local)")
        - not result_authselect_custom_profile_present.stat.exists

      - name: Ensure PAM Enforces Password Requirements - Maximum Consecutive Repeating
          Characters from Same Character Class - Create an authselect custom profile
          based on sssd profile
        ansible.builtin.command:
          cmd: authselect create-profile hardening -b sssd
        when:
        - result_authselect_profile is not skipped
        - result_authselect_check_cmd is success
        - authselect_current_profile is match("local")
        - not result_authselect_custom_profile_present.stat.exists

      - name: Ensure PAM Enforces Password Requirements - Maximum Consecutive Repeating
          Characters from Same Character Class - Ensure authselect changes are applied
        ansible.builtin.command:
          cmd: authselect apply-changes -b --backup=before-hardening-custom-profile
        when:
        - result_authselect_check_cmd is success
        - result_authselect_profile is not skipped
        - authselect_current_profile is not match("custom/")
        - authselect_custom_profile is not match(authselect_current_profile)

      - name: Ensure PAM Enforces Password Requirements - Maximum Consecutive Repeating
          Characters from Same Character Class - Ensure the authselect custom profile
          is selected
        ansible.builtin.command:
          cmd: authselect select {{ authselect_custom_profile }}
        register: result_pam_authselect_select_profile
        when:
        - result_authselect_check_cmd is success
        - result_authselect_profile is not skipped
        - authselect_current_profile is not match("custom/")
        - authselect_custom_profile is not match(authselect_current_profile)

      - name: Ensure PAM Enforces Password Requirements - Maximum Consecutive Repeating
          Characters from Same Character Class - Restore the authselect features in
          the custom profile
        ansible.builtin.command:
          cmd: authselect enable-feature {{ item }}
        loop: '{{ result_authselect_features.stdout_lines }}'
        register: result_pam_authselect_restore_features
        when:
        - result_authselect_profile is not skipped
        - result_authselect_features is not skipped
        - result_pam_authselect_select_profile is not skipped

      - name: Ensure PAM Enforces Password Requirements - Maximum Consecutive Repeating
          Characters from Same Character Class - Ensure authselect changes are applied
        ansible.builtin.command:
          cmd: authselect apply-changes -b --backup=after-hardening-custom-profile
        when:
        - result_authselect_check_cmd is success
        - result_authselect_profile is not skipped
        - result_pam_authselect_restore_features is not skipped

      - name: Ensure PAM Enforces Password Requirements - Maximum Consecutive Repeating
          Characters from Same Character Class - Change the PAM file to be edited
          according to the custom authselect profile
        ansible.builtin.set_fact:
          pam_file_path: /etc/authselect/{{ authselect_custom_profile }}/{{ pam_file_path
            | basename }}
        when:
        - authselect_custom_profile is defined
      when:
      - result_authselect_present.stat.exists

    - name: Ensure PAM Enforces Password Requirements - Maximum Consecutive Repeating
        Characters from Same Character Class - Define a fact for control already filtered
        in case filters are used
      ansible.builtin.set_fact:
        pam_module_control: ''

    - name: Ensure PAM Enforces Password Requirements - Maximum Consecutive Repeating
        Characters from Same Character Class - Check if {{ pam_file_path }} file is
        present
      ansible.builtin.stat:
        path: '{{ pam_file_path }}'
      register: result_pam_file_present

    - name: Ensure PAM Enforces Password Requirements - Maximum Consecutive Repeating
        Characters from Same Character Class - Ensure the "maxclassrepeat" option
        from "pam_pwquality.so" is not present in {{ pam_file_path }}
      ansible.builtin.replace:
        dest: '{{ pam_file_path }}'
        regexp: (.*password.*pam_pwquality.so.*)\bmaxclassrepeat\b=?[0-9a-zA-Z]*(.*)
        replace: \1\2
      register: result_pam_option_removal
      when:
      - result_pam_file_present.stat.exists

    - name: Ensure PAM Enforces Password Requirements - Maximum Consecutive Repeating
        Characters from Same Character Class - Ensure authselect changes are applied
      ansible.builtin.command:
        cmd: authselect apply-changes -b
      when:
      - result_authselect_present.stat.exists
      - result_pam_option_removal is changed
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - '"libpwquality" in ansible_facts.packages'
    - result_pam_password_auth_file_present.stat.exists
    tags:
    - DISA-STIG-OL09-00-001030
    - NIST-800-53-CM-6(a)
    - NIST-800-53-IA-5(1)(a)
    - NIST-800-53-IA-5(4)
    - NIST-800-53-IA-5(c)
    - accounts_password_pam_maxclassrepeat
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Ensure PAM Enforces Password Requirements - Maximum Consecutive Repeating
      Characters from Same Character Class - Ensure PAM variable maxclassrepeat is
      set accordingly
    ansible.builtin.lineinfile:
      create: true
      dest: /etc/security/pwquality.conf
      regexp: ^#?\s*maxclassrepeat
      line: maxclassrepeat = {{ var_password_pam_maxclassrepeat }}
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - '"libpwquality" in ansible_facts.packages'
    tags:
    - DISA-STIG-OL09-00-001030
    - NIST-800-53-CM-6(a)
    - NIST-800-53-IA-5(1)(a)
    - NIST-800-53-IA-5(4)
    - NIST-800-53-IA-5(c)
    - accounts_password_pam_maxclassrepeat
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Set Password Maximum Consecutive Repeating Characters - Find pwquality.conf.d
      files
    ansible.builtin.find:
      paths: /etc/security/pwquality.conf.d/
      patterns: '*.conf'
    register: pwquality_conf_d_files
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - '"libpwquality" in ansible_facts.packages'
    tags:
    - DISA-STIG-OL09-00-001035
    - NIST-800-53-CM-6(a)
    - NIST-800-53-IA-5(4)
    - NIST-800-53-IA-5(c)
    - accounts_password_pam_maxrepeat
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Set Password Maximum Consecutive Repeating Characters - Ensure maxrepeat
      is not set in pwquality.conf.d
    ansible.builtin.lineinfile:
      path: '{{ item.path }}'
      regexp: ^\s*\bmaxrepeat\b.*
      state: absent
    with_items: '{{ pwquality_conf_d_files.files }}'
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - '"libpwquality" in ansible_facts.packages'
    tags:
    - DISA-STIG-OL09-00-001035
    - NIST-800-53-CM-6(a)
    - NIST-800-53-IA-5(4)
    - NIST-800-53-IA-5(c)
    - accounts_password_pam_maxrepeat
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Set Password Maximum Consecutive Repeating Characters - Check if /etc/pam.d/system-auth
      file is present
    ansible.builtin.stat:
      path: /etc/pam.d/system-auth
    register: result_pam_auth_file_present
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - '"libpwquality" in ansible_facts.packages'
    tags:
    - DISA-STIG-OL09-00-001035
    - NIST-800-53-CM-6(a)
    - NIST-800-53-IA-5(4)
    - NIST-800-53-IA-5(c)
    - accounts_password_pam_maxrepeat
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Set Password Maximum Consecutive Repeating Characters - Check the proper
      remediation for the system
    block:

    - name: Set Password Maximum Consecutive Repeating Characters - Define the PAM
        file to be edited as a local fact
      ansible.builtin.set_fact:
        pam_file_path: /etc/pam.d/system-auth

    - name: Set Password Maximum Consecutive Repeating Characters - Check if system
        relies on authselect tool
      ansible.builtin.stat:
        path: /usr/bin/authselect
      register: result_authselect_present

    - name: Set Password Maximum Consecutive Repeating Characters - Ensure authselect
        custom profile is used if authselect is present
      block:

      - name: Set Password Maximum Consecutive Repeating Characters - Check integrity
          of authselect current profile
        ansible.builtin.command:
          cmd: authselect check
        register: result_authselect_check_cmd
        changed_when: false
        check_mode: false
        failed_when: false

      - name: Set Password Maximum Consecutive Repeating Characters - Informative
          message based on the authselect integrity check result
        ansible.builtin.assert:
          that:
          - ansible_check_mode or result_authselect_check_cmd.rc == 0
          fail_msg:
          - authselect integrity check failed. Remediation aborted!
          - This remediation could not be applied because an authselect profile was
            not selected or the selected profile is not intact.
          - It is not recommended to manually edit the PAM files when authselect tool
            is available.
          - In cases where the default authselect profile does not cover a specific
            demand, a custom authselect profile is recommended.
          success_msg:
          - authselect integrity check passed

      - name: Set Password Maximum Consecutive Repeating Characters - Get authselect
          current profile
        ansible.builtin.shell:
          cmd: authselect current -r | awk '{ print $1 }'
        register: result_authselect_profile
        changed_when: false
        when:
        - result_authselect_check_cmd is success

      - name: Set Password Maximum Consecutive Repeating Characters - Define the current
          authselect profile as a local fact
        ansible.builtin.set_fact:
          authselect_current_profile: '{{ result_authselect_profile.stdout }}'
          authselect_custom_profile: '{{ result_authselect_profile.stdout }}'
        when:
        - result_authselect_profile is not skipped
        - result_authselect_profile.stdout is match("custom/")

      - name: Set Password Maximum Consecutive Repeating Characters - Define the new
          authselect custom profile as a local fact
        ansible.builtin.set_fact:
          authselect_current_profile: '{{ result_authselect_profile.stdout }}'
          authselect_custom_profile: custom/hardening
        when:
        - result_authselect_profile is not skipped
        - result_authselect_profile.stdout is not match("custom/")

      - name: Set Password Maximum Consecutive Repeating Characters - Get authselect
          current features to also enable them in the custom profile
        ansible.builtin.shell:
          cmd: authselect current | tail -n+3 | awk '{ print $2 }'
        register: result_authselect_features
        changed_when: false
        check_mode: false
        when:
        - result_authselect_profile is not skipped
        - authselect_current_profile is not match("custom/")

      - name: Set Password Maximum Consecutive Repeating Characters - Check if any
          custom profile with the same name was already created
        ansible.builtin.stat:
          path: /etc/authselect/{{ authselect_custom_profile }}
        register: result_authselect_custom_profile_present
        changed_when: false
        when:
        - result_authselect_profile is not skipped
        - authselect_current_profile is not match("custom/")

      - name: Set Password Maximum Consecutive Repeating Characters - Create an authselect
          custom profile based on the current profile
        ansible.builtin.command:
          cmd: authselect create-profile hardening -b {{ authselect_current_profile
            }}
        when:
        - result_authselect_profile is not skipped
        - result_authselect_check_cmd is success
        - authselect_current_profile is not match("^(custom/|local)")
        - not result_authselect_custom_profile_present.stat.exists

      - name: Set Password Maximum Consecutive Repeating Characters - Create an authselect
          custom profile based on sssd profile
        ansible.builtin.command:
          cmd: authselect create-profile hardening -b sssd
        when:
        - result_authselect_profile is not skipped
        - result_authselect_check_cmd is success
        - authselect_current_profile is match("local")
        - not result_authselect_custom_profile_present.stat.exists

      - name: Set Password Maximum Consecutive Repeating Characters - Ensure authselect
          changes are applied
        ansible.builtin.command:
          cmd: authselect apply-changes -b --backup=before-hardening-custom-profile
        when:
        - result_authselect_check_cmd is success
        - result_authselect_profile is not skipped
        - authselect_current_profile is not match("custom/")
        - authselect_custom_profile is not match(authselect_current_profile)

      - name: Set Password Maximum Consecutive Repeating Characters - Ensure the authselect
          custom profile is selected
        ansible.builtin.command:
          cmd: authselect select {{ authselect_custom_profile }}
        register: result_pam_authselect_select_profile
        when:
        - result_authselect_check_cmd is success
        - result_authselect_profile is not skipped
        - authselect_current_profile is not match("custom/")
        - authselect_custom_profile is not match(authselect_current_profile)

      - name: Set Password Maximum Consecutive Repeating Characters - Restore the
          authselect features in the custom profile
        ansible.builtin.command:
          cmd: authselect enable-feature {{ item }}
        loop: '{{ result_authselect_features.stdout_lines }}'
        register: result_pam_authselect_restore_features
        when:
        - result_authselect_profile is not skipped
        - result_authselect_features is not skipped
        - result_pam_authselect_select_profile is not skipped

      - name: Set Password Maximum Consecutive Repeating Characters - Ensure authselect
          changes are applied
        ansible.builtin.command:
          cmd: authselect apply-changes -b --backup=after-hardening-custom-profile
        when:
        - result_authselect_check_cmd is success
        - result_authselect_profile is not skipped
        - result_pam_authselect_restore_features is not skipped

      - name: Set Password Maximum Consecutive Repeating Characters - Change the PAM
          file to be edited according to the custom authselect profile
        ansible.builtin.set_fact:
          pam_file_path: /etc/authselect/{{ authselect_custom_profile }}/{{ pam_file_path
            | basename }}
        when:
        - authselect_custom_profile is defined
      when:
      - result_authselect_present.stat.exists

    - name: Set Password Maximum Consecutive Repeating Characters - Define a fact
        for control already filtered in case filters are used
      ansible.builtin.set_fact:
        pam_module_control: ''

    - name: Set Password Maximum Consecutive Repeating Characters - Check if {{ pam_file_path
        }} file is present
      ansible.builtin.stat:
        path: '{{ pam_file_path }}'
      register: result_pam_file_present

    - name: Set Password Maximum Consecutive Repeating Characters - Ensure the "maxrepeat"
        option from "pam_pwquality.so" is not present in {{ pam_file_path }}
      ansible.builtin.replace:
        dest: '{{ pam_file_path }}'
        regexp: (.*password.*pam_pwquality.so.*)\bmaxrepeat\b=?[0-9a-zA-Z]*(.*)
        replace: \1\2
      register: result_pam_option_removal
      when:
      - result_pam_file_present.stat.exists

    - name: Set Password Maximum Consecutive Repeating Characters - Ensure authselect
        changes are applied
      ansible.builtin.command:
        cmd: authselect apply-changes -b
      when:
      - result_authselect_present.stat.exists
      - result_pam_option_removal is changed
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - '"libpwquality" in ansible_facts.packages'
    - result_pam_auth_file_present.stat.exists
    tags:
    - DISA-STIG-OL09-00-001035
    - NIST-800-53-CM-6(a)
    - NIST-800-53-IA-5(4)
    - NIST-800-53-IA-5(c)
    - accounts_password_pam_maxrepeat
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Set Password Maximum Consecutive Repeating Characters - Check if /etc/pam.d/password-auth
      file is present
    ansible.builtin.stat:
      path: /etc/pam.d/password-auth
    register: result_pam_password_auth_file_present
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - '"libpwquality" in ansible_facts.packages'
    tags:
    - DISA-STIG-OL09-00-001035
    - NIST-800-53-CM-6(a)
    - NIST-800-53-IA-5(4)
    - NIST-800-53-IA-5(c)
    - accounts_password_pam_maxrepeat
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Set Password Maximum Consecutive Repeating Characters - Check the proper
      remediation for the system
    block:

    - name: Set Password Maximum Consecutive Repeating Characters - Define the PAM
        file to be edited as a local fact
      ansible.builtin.set_fact:
        pam_file_path: /etc/pam.d/password-auth

    - name: Set Password Maximum Consecutive Repeating Characters - Check if system
        relies on authselect tool
      ansible.builtin.stat:
        path: /usr/bin/authselect
      register: result_authselect_present

    - name: Set Password Maximum Consecutive Repeating Characters - Ensure authselect
        custom profile is used if authselect is present
      block:

      - name: Set Password Maximum Consecutive Repeating Characters - Check integrity
          of authselect current profile
        ansible.builtin.command:
          cmd: authselect check
        register: result_authselect_check_cmd
        changed_when: false
        check_mode: false
        failed_when: false

      - name: Set Password Maximum Consecutive Repeating Characters - Informative
          message based on the authselect integrity check result
        ansible.builtin.assert:
          that:
          - ansible_check_mode or result_authselect_check_cmd.rc == 0
          fail_msg:
          - authselect integrity check failed. Remediation aborted!
          - This remediation could not be applied because an authselect profile was
            not selected or the selected profile is not intact.
          - It is not recommended to manually edit the PAM files when authselect tool
            is available.
          - In cases where the default authselect profile does not cover a specific
            demand, a custom authselect profile is recommended.
          success_msg:
          - authselect integrity check passed

      - name: Set Password Maximum Consecutive Repeating Characters - Get authselect
          current profile
        ansible.builtin.shell:
          cmd: authselect current -r | awk '{ print $1 }'
        register: result_authselect_profile
        changed_when: false
        when:
        - result_authselect_check_cmd is success

      - name: Set Password Maximum Consecutive Repeating Characters - Define the current
          authselect profile as a local fact
        ansible.builtin.set_fact:
          authselect_current_profile: '{{ result_authselect_profile.stdout }}'
          authselect_custom_profile: '{{ result_authselect_profile.stdout }}'
        when:
        - result_authselect_profile is not skipped
        - result_authselect_profile.stdout is match("custom/")

      - name: Set Password Maximum Consecutive Repeating Characters - Define the new
          authselect custom profile as a local fact
        ansible.builtin.set_fact:
          authselect_current_profile: '{{ result_authselect_profile.stdout }}'
          authselect_custom_profile: custom/hardening
        when:
        - result_authselect_profile is not skipped
        - result_authselect_profile.stdout is not match("custom/")

      - name: Set Password Maximum Consecutive Repeating Characters - Get authselect
          current features to also enable them in the custom profile
        ansible.builtin.shell:
          cmd: authselect current | tail -n+3 | awk '{ print $2 }'
        register: result_authselect_features
        changed_when: false
        check_mode: false
        when:
        - result_authselect_profile is not skipped
        - authselect_current_profile is not match("custom/")

      - name: Set Password Maximum Consecutive Repeating Characters - Check if any
          custom profile with the same name was already created
        ansible.builtin.stat:
          path: /etc/authselect/{{ authselect_custom_profile }}
        register: result_authselect_custom_profile_present
        changed_when: false
        when:
        - result_authselect_profile is not skipped
        - authselect_current_profile is not match("custom/")

      - name: Set Password Maximum Consecutive Repeating Characters - Create an authselect
          custom profile based on the current profile
        ansible.builtin.command:
          cmd: authselect create-profile hardening -b {{ authselect_current_profile
            }}
        when:
        - result_authselect_profile is not skipped
        - result_authselect_check_cmd is success
        - authselect_current_profile is not match("^(custom/|local)")
        - not result_authselect_custom_profile_present.stat.exists

      - name: Set Password Maximum Consecutive Repeating Characters - Create an authselect
          custom profile based on sssd profile
        ansible.builtin.command:
          cmd: authselect create-profile hardening -b sssd
        when:
        - result_authselect_profile is not skipped
        - result_authselect_check_cmd is success
        - authselect_current_profile is match("local")
        - not result_authselect_custom_profile_present.stat.exists

      - name: Set Password Maximum Consecutive Repeating Characters - Ensure authselect
          changes are applied
        ansible.builtin.command:
          cmd: authselect apply-changes -b --backup=before-hardening-custom-profile
        when:
        - result_authselect_check_cmd is success
        - result_authselect_profile is not skipped
        - authselect_current_profile is not match("custom/")
        - authselect_custom_profile is not match(authselect_current_profile)

      - name: Set Password Maximum Consecutive Repeating Characters - Ensure the authselect
          custom profile is selected
        ansible.builtin.command:
          cmd: authselect select {{ authselect_custom_profile }}
        register: result_pam_authselect_select_profile
        when:
        - result_authselect_check_cmd is success
        - result_authselect_profile is not skipped
        - authselect_current_profile is not match("custom/")
        - authselect_custom_profile is not match(authselect_current_profile)

      - name: Set Password Maximum Consecutive Repeating Characters - Restore the
          authselect features in the custom profile
        ansible.builtin.command:
          cmd: authselect enable-feature {{ item }}
        loop: '{{ result_authselect_features.stdout_lines }}'
        register: result_pam_authselect_restore_features
        when:
        - result_authselect_profile is not skipped
        - result_authselect_features is not skipped
        - result_pam_authselect_select_profile is not skipped

      - name: Set Password Maximum Consecutive Repeating Characters - Ensure authselect
          changes are applied
        ansible.builtin.command:
          cmd: authselect apply-changes -b --backup=after-hardening-custom-profile
        when:
        - result_authselect_check_cmd is success
        - result_authselect_profile is not skipped
        - result_pam_authselect_restore_features is not skipped

      - name: Set Password Maximum Consecutive Repeating Characters - Change the PAM
          file to be edited according to the custom authselect profile
        ansible.builtin.set_fact:
          pam_file_path: /etc/authselect/{{ authselect_custom_profile }}/{{ pam_file_path
            | basename }}
        when:
        - authselect_custom_profile is defined
      when:
      - result_authselect_present.stat.exists

    - name: Set Password Maximum Consecutive Repeating Characters - Define a fact
        for control already filtered in case filters are used
      ansible.builtin.set_fact:
        pam_module_control: ''

    - name: Set Password Maximum Consecutive Repeating Characters - Check if {{ pam_file_path
        }} file is present
      ansible.builtin.stat:
        path: '{{ pam_file_path }}'
      register: result_pam_file_present

    - name: Set Password Maximum Consecutive Repeating Characters - Ensure the "maxrepeat"
        option from "pam_pwquality.so" is not present in {{ pam_file_path }}
      ansible.builtin.replace:
        dest: '{{ pam_file_path }}'
        regexp: (.*password.*pam_pwquality.so.*)\bmaxrepeat\b=?[0-9a-zA-Z]*(.*)
        replace: \1\2
      register: result_pam_option_removal
      when:
      - result_pam_file_present.stat.exists

    - name: Set Password Maximum Consecutive Repeating Characters - Ensure authselect
        changes are applied
      ansible.builtin.command:
        cmd: authselect apply-changes -b
      when:
      - result_authselect_present.stat.exists
      - result_pam_option_removal is changed
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - '"libpwquality" in ansible_facts.packages'
    - result_pam_password_auth_file_present.stat.exists
    tags:
    - DISA-STIG-OL09-00-001035
    - NIST-800-53-CM-6(a)
    - NIST-800-53-IA-5(4)
    - NIST-800-53-IA-5(c)
    - accounts_password_pam_maxrepeat
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Set Password Maximum Consecutive Repeating Characters - Ensure PAM variable
      maxrepeat is set accordingly
    ansible.builtin.lineinfile:
      create: true
      dest: /etc/security/pwquality.conf
      regexp: ^#?\s*maxrepeat
      line: maxrepeat = {{ var_password_pam_maxrepeat }}
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - '"libpwquality" in ansible_facts.packages'
    tags:
    - DISA-STIG-OL09-00-001035
    - NIST-800-53-CM-6(a)
    - NIST-800-53-IA-5(4)
    - NIST-800-53-IA-5(c)
    - accounts_password_pam_maxrepeat
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Ensure PAM Enforces Password Requirements - Minimum Different Categories
      - Find pwquality.conf.d files
    ansible.builtin.find:
      paths: /etc/security/pwquality.conf.d/
      patterns: '*.conf'
    register: pwquality_conf_d_files
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - '"libpwquality" in ansible_facts.packages'
    tags:
    - DISA-STIG-OL09-00-001040
    - NIST-800-53-CM-6(a)
    - NIST-800-53-IA-5(1)(a)
    - NIST-800-53-IA-5(4)
    - NIST-800-53-IA-5(c)
    - accounts_password_pam_minclass
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Ensure PAM Enforces Password Requirements - Minimum Different Categories
      - Ensure minclass is not set in pwquality.conf.d
    ansible.builtin.lineinfile:
      path: '{{ item.path }}'
      regexp: ^\s*\bminclass\b.*
      state: absent
    with_items: '{{ pwquality_conf_d_files.files }}'
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - '"libpwquality" in ansible_facts.packages'
    tags:
    - DISA-STIG-OL09-00-001040
    - NIST-800-53-CM-6(a)
    - NIST-800-53-IA-5(1)(a)
    - NIST-800-53-IA-5(4)
    - NIST-800-53-IA-5(c)
    - accounts_password_pam_minclass
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Ensure PAM Enforces Password Requirements - Minimum Different Categories
      - Check if /etc/pam.d/system-auth file is present
    ansible.builtin.stat:
      path: /etc/pam.d/system-auth
    register: result_pam_auth_file_present
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - '"libpwquality" in ansible_facts.packages'
    tags:
    - DISA-STIG-OL09-00-001040
    - NIST-800-53-CM-6(a)
    - NIST-800-53-IA-5(1)(a)
    - NIST-800-53-IA-5(4)
    - NIST-800-53-IA-5(c)
    - accounts_password_pam_minclass
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Ensure PAM Enforces Password Requirements - Minimum Different Categories
      - Check the proper remediation for the system
    block:

    - name: Ensure PAM Enforces Password Requirements - Minimum Different Categories
        - Define the PAM file to be edited as a local fact
      ansible.builtin.set_fact:
        pam_file_path: /etc/pam.d/system-auth

    - name: Ensure PAM Enforces Password Requirements - Minimum Different Categories
        - Check if system relies on authselect tool
      ansible.builtin.stat:
        path: /usr/bin/authselect
      register: result_authselect_present

    - name: Ensure PAM Enforces Password Requirements - Minimum Different Categories
        - Ensure authselect custom profile is used if authselect is present
      block:

      - name: Ensure PAM Enforces Password Requirements - Minimum Different Categories
          - Check integrity of authselect current profile
        ansible.builtin.command:
          cmd: authselect check
        register: result_authselect_check_cmd
        changed_when: false
        check_mode: false
        failed_when: false

      - name: Ensure PAM Enforces Password Requirements - Minimum Different Categories
          - Informative message based on the authselect integrity check result
        ansible.builtin.assert:
          that:
          - ansible_check_mode or result_authselect_check_cmd.rc == 0
          fail_msg:
          - authselect integrity check failed. Remediation aborted!
          - This remediation could not be applied because an authselect profile was
            not selected or the selected profile is not intact.
          - It is not recommended to manually edit the PAM files when authselect tool
            is available.
          - In cases where the default authselect profile does not cover a specific
            demand, a custom authselect profile is recommended.
          success_msg:
          - authselect integrity check passed

      - name: Ensure PAM Enforces Password Requirements - Minimum Different Categories
          - Get authselect current profile
        ansible.builtin.shell:
          cmd: authselect current -r | awk '{ print $1 }'
        register: result_authselect_profile
        changed_when: false
        when:
        - result_authselect_check_cmd is success

      - name: Ensure PAM Enforces Password Requirements - Minimum Different Categories
          - Define the current authselect profile as a local fact
        ansible.builtin.set_fact:
          authselect_current_profile: '{{ result_authselect_profile.stdout }}'
          authselect_custom_profile: '{{ result_authselect_profile.stdout }}'
        when:
        - result_authselect_profile is not skipped
        - result_authselect_profile.stdout is match("custom/")

      - name: Ensure PAM Enforces Password Requirements - Minimum Different Categories
          - Define the new authselect custom profile as a local fact
        ansible.builtin.set_fact:
          authselect_current_profile: '{{ result_authselect_profile.stdout }}'
          authselect_custom_profile: custom/hardening
        when:
        - result_authselect_profile is not skipped
        - result_authselect_profile.stdout is not match("custom/")

      - name: Ensure PAM Enforces Password Requirements - Minimum Different Categories
          - Get authselect current features to also enable them in the custom profile
        ansible.builtin.shell:
          cmd: authselect current | tail -n+3 | awk '{ print $2 }'
        register: result_authselect_features
        changed_when: false
        check_mode: false
        when:
        - result_authselect_profile is not skipped
        - authselect_current_profile is not match("custom/")

      - name: Ensure PAM Enforces Password Requirements - Minimum Different Categories
          - Check if any custom profile with the same name was already created
        ansible.builtin.stat:
          path: /etc/authselect/{{ authselect_custom_profile }}
        register: result_authselect_custom_profile_present
        changed_when: false
        when:
        - result_authselect_profile is not skipped
        - authselect_current_profile is not match("custom/")

      - name: Ensure PAM Enforces Password Requirements - Minimum Different Categories
          - Create an authselect custom profile based on the current profile
        ansible.builtin.command:
          cmd: authselect create-profile hardening -b {{ authselect_current_profile
            }}
        when:
        - result_authselect_profile is not skipped
        - result_authselect_check_cmd is success
        - authselect_current_profile is not match("^(custom/|local)")
        - not result_authselect_custom_profile_present.stat.exists

      - name: Ensure PAM Enforces Password Requirements - Minimum Different Categories
          - Create an authselect custom profile based on sssd profile
        ansible.builtin.command:
          cmd: authselect create-profile hardening -b sssd
        when:
        - result_authselect_profile is not skipped
        - result_authselect_check_cmd is success
        - authselect_current_profile is match("local")
        - not result_authselect_custom_profile_present.stat.exists

      - name: Ensure PAM Enforces Password Requirements - Minimum Different Categories
          - Ensure authselect changes are applied
        ansible.builtin.command:
          cmd: authselect apply-changes -b --backup=before-hardening-custom-profile
        when:
        - result_authselect_check_cmd is success
        - result_authselect_profile is not skipped
        - authselect_current_profile is not match("custom/")
        - authselect_custom_profile is not match(authselect_current_profile)

      - name: Ensure PAM Enforces Password Requirements - Minimum Different Categories
          - Ensure the authselect custom profile is selected
        ansible.builtin.command:
          cmd: authselect select {{ authselect_custom_profile }}
        register: result_pam_authselect_select_profile
        when:
        - result_authselect_check_cmd is success
        - result_authselect_profile is not skipped
        - authselect_current_profile is not match("custom/")
        - authselect_custom_profile is not match(authselect_current_profile)

      - name: Ensure PAM Enforces Password Requirements - Minimum Different Categories
          - Restore the authselect features in the custom profile
        ansible.builtin.command:
          cmd: authselect enable-feature {{ item }}
        loop: '{{ result_authselect_features.stdout_lines }}'
        register: result_pam_authselect_restore_features
        when:
        - result_authselect_profile is not skipped
        - result_authselect_features is not skipped
        - result_pam_authselect_select_profile is not skipped

      - name: Ensure PAM Enforces Password Requirements - Minimum Different Categories
          - Ensure authselect changes are applied
        ansible.builtin.command:
          cmd: authselect apply-changes -b --backup=after-hardening-custom-profile
        when:
        - result_authselect_check_cmd is success
        - result_authselect_profile is not skipped
        - result_pam_authselect_restore_features is not skipped

      - name: Ensure PAM Enforces Password Requirements - Minimum Different Categories
          - Change the PAM file to be edited according to the custom authselect profile
        ansible.builtin.set_fact:
          pam_file_path: /etc/authselect/{{ authselect_custom_profile }}/{{ pam_file_path
            | basename }}
        when:
        - authselect_custom_profile is defined
      when:
      - result_authselect_present.stat.exists

    - name: Ensure PAM Enforces Password Requirements - Minimum Different Categories
        - Define a fact for control already filtered in case filters are used
      ansible.builtin.set_fact:
        pam_module_control: ''

    - name: Ensure PAM Enforces Password Requirements - Minimum Different Categories
        - Check if {{ pam_file_path }} file is present
      ansible.builtin.stat:
        path: '{{ pam_file_path }}'
      register: result_pam_file_present

    - name: Ensure PAM Enforces Password Requirements - Minimum Different Categories
        - Ensure the "minclass" option from "pam_pwquality.so" is not present in {{
        pam_file_path }}
      ansible.builtin.replace:
        dest: '{{ pam_file_path }}'
        regexp: (.*password.*pam_pwquality.so.*)\bminclass\b=?[0-9a-zA-Z]*(.*)
        replace: \1\2
      register: result_pam_option_removal
      when:
      - result_pam_file_present.stat.exists

    - name: Ensure PAM Enforces Password Requirements - Minimum Different Categories
        - Ensure authselect changes are applied
      ansible.builtin.command:
        cmd: authselect apply-changes -b
      when:
      - result_authselect_present.stat.exists
      - result_pam_option_removal is changed
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - '"libpwquality" in ansible_facts.packages'
    - result_pam_auth_file_present.stat.exists
    tags:
    - DISA-STIG-OL09-00-001040
    - NIST-800-53-CM-6(a)
    - NIST-800-53-IA-5(1)(a)
    - NIST-800-53-IA-5(4)
    - NIST-800-53-IA-5(c)
    - accounts_password_pam_minclass
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Ensure PAM Enforces Password Requirements - Minimum Different Categories
      - Check if /etc/pam.d/password-auth file is present
    ansible.builtin.stat:
      path: /etc/pam.d/password-auth
    register: result_pam_password_auth_file_present
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - '"libpwquality" in ansible_facts.packages'
    tags:
    - DISA-STIG-OL09-00-001040
    - NIST-800-53-CM-6(a)
    - NIST-800-53-IA-5(1)(a)
    - NIST-800-53-IA-5(4)
    - NIST-800-53-IA-5(c)
    - accounts_password_pam_minclass
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Ensure PAM Enforces Password Requirements - Minimum Different Categories
      - Check the proper remediation for the system
    block:

    - name: Ensure PAM Enforces Password Requirements - Minimum Different Categories
        - Define the PAM file to be edited as a local fact
      ansible.builtin.set_fact:
        pam_file_path: /etc/pam.d/password-auth

    - name: Ensure PAM Enforces Password Requirements - Minimum Different Categories
        - Check if system relies on authselect tool
      ansible.builtin.stat:
        path: /usr/bin/authselect
      register: result_authselect_present

    - name: Ensure PAM Enforces Password Requirements - Minimum Different Categories
        - Ensure authselect custom profile is used if authselect is present
      block:

      - name: Ensure PAM Enforces Password Requirements - Minimum Different Categories
          - Check integrity of authselect current profile
        ansible.builtin.command:
          cmd: authselect check
        register: result_authselect_check_cmd
        changed_when: false
        check_mode: false
        failed_when: false

      - name: Ensure PAM Enforces Password Requirements - Minimum Different Categories
          - Informative message based on the authselect integrity check result
        ansible.builtin.assert:
          that:
          - ansible_check_mode or result_authselect_check_cmd.rc == 0
          fail_msg:
          - authselect integrity check failed. Remediation aborted!
          - This remediation could not be applied because an authselect profile was
            not selected or the selected profile is not intact.
          - It is not recommended to manually edit the PAM files when authselect tool
            is available.
          - In cases where the default authselect profile does not cover a specific
            demand, a custom authselect profile is recommended.
          success_msg:
          - authselect integrity check passed

      - name: Ensure PAM Enforces Password Requirements - Minimum Different Categories
          - Get authselect current profile
        ansible.builtin.shell:
          cmd: authselect current -r | awk '{ print $1 }'
        register: result_authselect_profile
        changed_when: false
        when:
        - result_authselect_check_cmd is success

      - name: Ensure PAM Enforces Password Requirements - Minimum Different Categories
          - Define the current authselect profile as a local fact
        ansible.builtin.set_fact:
          authselect_current_profile: '{{ result_authselect_profile.stdout }}'
          authselect_custom_profile: '{{ result_authselect_profile.stdout }}'
        when:
        - result_authselect_profile is not skipped
        - result_authselect_profile.stdout is match("custom/")

      - name: Ensure PAM Enforces Password Requirements - Minimum Different Categories
          - Define the new authselect custom profile as a local fact
        ansible.builtin.set_fact:
          authselect_current_profile: '{{ result_authselect_profile.stdout }}'
          authselect_custom_profile: custom/hardening
        when:
        - result_authselect_profile is not skipped
        - result_authselect_profile.stdout is not match("custom/")

      - name: Ensure PAM Enforces Password Requirements - Minimum Different Categories
          - Get authselect current features to also enable them in the custom profile
        ansible.builtin.shell:
          cmd: authselect current | tail -n+3 | awk '{ print $2 }'
        register: result_authselect_features
        changed_when: false
        check_mode: false
        when:
        - result_authselect_profile is not skipped
        - authselect_current_profile is not match("custom/")

      - name: Ensure PAM Enforces Password Requirements - Minimum Different Categories
          - Check if any custom profile with the same name was already created
        ansible.builtin.stat:
          path: /etc/authselect/{{ authselect_custom_profile }}
        register: result_authselect_custom_profile_present
        changed_when: false
        when:
        - result_authselect_profile is not skipped
        - authselect_current_profile is not match("custom/")

      - name: Ensure PAM Enforces Password Requirements - Minimum Different Categories
          - Create an authselect custom profile based on the current profile
        ansible.builtin.command:
          cmd: authselect create-profile hardening -b {{ authselect_current_profile
            }}
        when:
        - result_authselect_profile is not skipped
        - result_authselect_check_cmd is success
        - authselect_current_profile is not match("^(custom/|local)")
        - not result_authselect_custom_profile_present.stat.exists

      - name: Ensure PAM Enforces Password Requirements - Minimum Different Categories
          - Create an authselect custom profile based on sssd profile
        ansible.builtin.command:
          cmd: authselect create-profile hardening -b sssd
        when:
        - result_authselect_profile is not skipped
        - result_authselect_check_cmd is success
        - authselect_current_profile is match("local")
        - not result_authselect_custom_profile_present.stat.exists

      - name: Ensure PAM Enforces Password Requirements - Minimum Different Categories
          - Ensure authselect changes are applied
        ansible.builtin.command:
          cmd: authselect apply-changes -b --backup=before-hardening-custom-profile
        when:
        - result_authselect_check_cmd is success
        - result_authselect_profile is not skipped
        - authselect_current_profile is not match("custom/")
        - authselect_custom_profile is not match(authselect_current_profile)

      - name: Ensure PAM Enforces Password Requirements - Minimum Different Categories
          - Ensure the authselect custom profile is selected
        ansible.builtin.command:
          cmd: authselect select {{ authselect_custom_profile }}
        register: result_pam_authselect_select_profile
        when:
        - result_authselect_check_cmd is success
        - result_authselect_profile is not skipped
        - authselect_current_profile is not match("custom/")
        - authselect_custom_profile is not match(authselect_current_profile)

      - name: Ensure PAM Enforces Password Requirements - Minimum Different Categories
          - Restore the authselect features in the custom profile
        ansible.builtin.command:
          cmd: authselect enable-feature {{ item }}
        loop: '{{ result_authselect_features.stdout_lines }}'
        register: result_pam_authselect_restore_features
        when:
        - result_authselect_profile is not skipped
        - result_authselect_features is not skipped
        - result_pam_authselect_select_profile is not skipped

      - name: Ensure PAM Enforces Password Requirements - Minimum Different Categories
          - Ensure authselect changes are applied
        ansible.builtin.command:
          cmd: authselect apply-changes -b --backup=after-hardening-custom-profile
        when:
        - result_authselect_check_cmd is success
        - result_authselect_profile is not skipped
        - result_pam_authselect_restore_features is not skipped

      - name: Ensure PAM Enforces Password Requirements - Minimum Different Categories
          - Change the PAM file to be edited according to the custom authselect profile
        ansible.builtin.set_fact:
          pam_file_path: /etc/authselect/{{ authselect_custom_profile }}/{{ pam_file_path
            | basename }}
        when:
        - authselect_custom_profile is defined
      when:
      - result_authselect_present.stat.exists

    - name: Ensure PAM Enforces Password Requirements - Minimum Different Categories
        - Define a fact for control already filtered in case filters are used
      ansible.builtin.set_fact:
        pam_module_control: ''

    - name: Ensure PAM Enforces Password Requirements - Minimum Different Categories
        - Check if {{ pam_file_path }} file is present
      ansible.builtin.stat:
        path: '{{ pam_file_path }}'
      register: result_pam_file_present

    - name: Ensure PAM Enforces Password Requirements - Minimum Different Categories
        - Ensure the "minclass" option from "pam_pwquality.so" is not present in {{
        pam_file_path }}
      ansible.builtin.replace:
        dest: '{{ pam_file_path }}'
        regexp: (.*password.*pam_pwquality.so.*)\bminclass\b=?[0-9a-zA-Z]*(.*)
        replace: \1\2
      register: result_pam_option_removal
      when:
      - result_pam_file_present.stat.exists

    - name: Ensure PAM Enforces Password Requirements - Minimum Different Categories
        - Ensure authselect changes are applied
      ansible.builtin.command:
        cmd: authselect apply-changes -b
      when:
      - result_authselect_present.stat.exists
      - result_pam_option_removal is changed
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - '"libpwquality" in ansible_facts.packages'
    - result_pam_password_auth_file_present.stat.exists
    tags:
    - DISA-STIG-OL09-00-001040
    - NIST-800-53-CM-6(a)
    - NIST-800-53-IA-5(1)(a)
    - NIST-800-53-IA-5(4)
    - NIST-800-53-IA-5(c)
    - accounts_password_pam_minclass
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Ensure PAM Enforces Password Requirements - Minimum Different Categories
      - Ensure PAM variable minclass is set accordingly
    ansible.builtin.lineinfile:
      create: true
      dest: /etc/security/pwquality.conf
      regexp: ^#?\s*minclass
      line: minclass = {{ var_password_pam_minclass }}
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - '"libpwquality" in ansible_facts.packages'
    tags:
    - DISA-STIG-OL09-00-001040
    - NIST-800-53-CM-6(a)
    - NIST-800-53-IA-5(1)(a)
    - NIST-800-53-IA-5(4)
    - NIST-800-53-IA-5(c)
    - accounts_password_pam_minclass
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Ensure PAM Enforces Password Requirements - Minimum Length - Find pwquality.conf.d
      files
    ansible.builtin.find:
      paths: /etc/security/pwquality.conf.d/
      patterns: '*.conf'
    register: pwquality_conf_d_files
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - '"libpwquality" in ansible_facts.packages'
    tags:
    - CJIS-5.6.2.1.1
    - DISA-STIG-OL09-00-001105
    - NIST-800-53-CM-6(a)
    - NIST-800-53-IA-5(1)(a)
    - NIST-800-53-IA-5(4)
    - NIST-800-53-IA-5(c)
    - PCI-DSS-Req-8.2.3
    - PCI-DSSv4-8.3
    - PCI-DSSv4-8.3.6
    - accounts_password_pam_minlen
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Ensure PAM Enforces Password Requirements - Minimum Length - Ensure minlen
      is not set in pwquality.conf.d
    ansible.builtin.lineinfile:
      path: '{{ item.path }}'
      regexp: ^\s*\bminlen\b.*
      state: absent
    with_items: '{{ pwquality_conf_d_files.files }}'
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - '"libpwquality" in ansible_facts.packages'
    tags:
    - CJIS-5.6.2.1.1
    - DISA-STIG-OL09-00-001105
    - NIST-800-53-CM-6(a)
    - NIST-800-53-IA-5(1)(a)
    - NIST-800-53-IA-5(4)
    - NIST-800-53-IA-5(c)
    - PCI-DSS-Req-8.2.3
    - PCI-DSSv4-8.3
    - PCI-DSSv4-8.3.6
    - accounts_password_pam_minlen
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Ensure PAM Enforces Password Requirements - Minimum Length - Check if /etc/pam.d/system-auth
      file is present
    ansible.builtin.stat:
      path: /etc/pam.d/system-auth
    register: result_pam_auth_file_present
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - '"libpwquality" in ansible_facts.packages'
    tags:
    - CJIS-5.6.2.1.1
    - DISA-STIG-OL09-00-001105
    - NIST-800-53-CM-6(a)
    - NIST-800-53-IA-5(1)(a)
    - NIST-800-53-IA-5(4)
    - NIST-800-53-IA-5(c)
    - PCI-DSS-Req-8.2.3
    - PCI-DSSv4-8.3
    - PCI-DSSv4-8.3.6
    - accounts_password_pam_minlen
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Ensure PAM Enforces Password Requirements - Minimum Length - Check the proper
      remediation for the system
    block:

    - name: Ensure PAM Enforces Password Requirements - Minimum Length - Define the
        PAM file to be edited as a local fact
      ansible.builtin.set_fact:
        pam_file_path: /etc/pam.d/system-auth

    - name: Ensure PAM Enforces Password Requirements - Minimum Length - Check if
        system relies on authselect tool
      ansible.builtin.stat:
        path: /usr/bin/authselect
      register: result_authselect_present

    - name: Ensure PAM Enforces Password Requirements - Minimum Length - Ensure authselect
        custom profile is used if authselect is present
      block:

      - name: Ensure PAM Enforces Password Requirements - Minimum Length - Check integrity
          of authselect current profile
        ansible.builtin.command:
          cmd: authselect check
        register: result_authselect_check_cmd
        changed_when: false
        check_mode: false
        failed_when: false

      - name: Ensure PAM Enforces Password Requirements - Minimum Length - Informative
          message based on the authselect integrity check result
        ansible.builtin.assert:
          that:
          - ansible_check_mode or result_authselect_check_cmd.rc == 0
          fail_msg:
          - authselect integrity check failed. Remediation aborted!
          - This remediation could not be applied because an authselect profile was
            not selected or the selected profile is not intact.
          - It is not recommended to manually edit the PAM files when authselect tool
            is available.
          - In cases where the default authselect profile does not cover a specific
            demand, a custom authselect profile is recommended.
          success_msg:
          - authselect integrity check passed

      - name: Ensure PAM Enforces Password Requirements - Minimum Length - Get authselect
          current profile
        ansible.builtin.shell:
          cmd: authselect current -r | awk '{ print $1 }'
        register: result_authselect_profile
        changed_when: false
        when:
        - result_authselect_check_cmd is success

      - name: Ensure PAM Enforces Password Requirements - Minimum Length - Define
          the current authselect profile as a local fact
        ansible.builtin.set_fact:
          authselect_current_profile: '{{ result_authselect_profile.stdout }}'
          authselect_custom_profile: '{{ result_authselect_profile.stdout }}'
        when:
        - result_authselect_profile is not skipped
        - result_authselect_profile.stdout is match("custom/")

      - name: Ensure PAM Enforces Password Requirements - Minimum Length - Define
          the new authselect custom profile as a local fact
        ansible.builtin.set_fact:
          authselect_current_profile: '{{ result_authselect_profile.stdout }}'
          authselect_custom_profile: custom/hardening
        when:
        - result_authselect_profile is not skipped
        - result_authselect_profile.stdout is not match("custom/")

      - name: Ensure PAM Enforces Password Requirements - Minimum Length - Get authselect
          current features to also enable them in the custom profile
        ansible.builtin.shell:
          cmd: authselect current | tail -n+3 | awk '{ print $2 }'
        register: result_authselect_features
        changed_when: false
        check_mode: false
        when:
        - result_authselect_profile is not skipped
        - authselect_current_profile is not match("custom/")

      - name: Ensure PAM Enforces Password Requirements - Minimum Length - Check if
          any custom profile with the same name was already created
        ansible.builtin.stat:
          path: /etc/authselect/{{ authselect_custom_profile }}
        register: result_authselect_custom_profile_present
        changed_when: false
        when:
        - result_authselect_profile is not skipped
        - authselect_current_profile is not match("custom/")

      - name: Ensure PAM Enforces Password Requirements - Minimum Length - Create
          an authselect custom profile based on the current profile
        ansible.builtin.command:
          cmd: authselect create-profile hardening -b {{ authselect_current_profile
            }}
        when:
        - result_authselect_profile is not skipped
        - result_authselect_check_cmd is success
        - authselect_current_profile is not match("^(custom/|local)")
        - not result_authselect_custom_profile_present.stat.exists

      - name: Ensure PAM Enforces Password Requirements - Minimum Length - Create
          an authselect custom profile based on sssd profile
        ansible.builtin.command:
          cmd: authselect create-profile hardening -b sssd
        when:
        - result_authselect_profile is not skipped
        - result_authselect_check_cmd is success
        - authselect_current_profile is match("local")
        - not result_authselect_custom_profile_present.stat.exists

      - name: Ensure PAM Enforces Password Requirements - Minimum Length - Ensure
          authselect changes are applied
        ansible.builtin.command:
          cmd: authselect apply-changes -b --backup=before-hardening-custom-profile
        when:
        - result_authselect_check_cmd is success
        - result_authselect_profile is not skipped
        - authselect_current_profile is not match("custom/")
        - authselect_custom_profile is not match(authselect_current_profile)

      - name: Ensure PAM Enforces Password Requirements - Minimum Length - Ensure
          the authselect custom profile is selected
        ansible.builtin.command:
          cmd: authselect select {{ authselect_custom_profile }}
        register: result_pam_authselect_select_profile
        when:
        - result_authselect_check_cmd is success
        - result_authselect_profile is not skipped
        - authselect_current_profile is not match("custom/")
        - authselect_custom_profile is not match(authselect_current_profile)

      - name: Ensure PAM Enforces Password Requirements - Minimum Length - Restore
          the authselect features in the custom profile
        ansible.builtin.command:
          cmd: authselect enable-feature {{ item }}
        loop: '{{ result_authselect_features.stdout_lines }}'
        register: result_pam_authselect_restore_features
        when:
        - result_authselect_profile is not skipped
        - result_authselect_features is not skipped
        - result_pam_authselect_select_profile is not skipped

      - name: Ensure PAM Enforces Password Requirements - Minimum Length - Ensure
          authselect changes are applied
        ansible.builtin.command:
          cmd: authselect apply-changes -b --backup=after-hardening-custom-profile
        when:
        - result_authselect_check_cmd is success
        - result_authselect_profile is not skipped
        - result_pam_authselect_restore_features is not skipped

      - name: Ensure PAM Enforces Password Requirements - Minimum Length - Change
          the PAM file to be edited according to the custom authselect profile
        ansible.builtin.set_fact:
          pam_file_path: /etc/authselect/{{ authselect_custom_profile }}/{{ pam_file_path
            | basename }}
        when:
        - authselect_custom_profile is defined
      when:
      - result_authselect_present.stat.exists

    - name: Ensure PAM Enforces Password Requirements - Minimum Length - Define a
        fact for control already filtered in case filters are used
      ansible.builtin.set_fact:
        pam_module_control: ''

    - name: Ensure PAM Enforces Password Requirements - Minimum Length - Check if
        {{ pam_file_path }} file is present
      ansible.builtin.stat:
        path: '{{ pam_file_path }}'
      register: result_pam_file_present

    - name: Ensure PAM Enforces Password Requirements - Minimum Length - Ensure the
        "minlen" option from "pam_pwquality.so" is not present in {{ pam_file_path
        }}
      ansible.builtin.replace:
        dest: '{{ pam_file_path }}'
        regexp: (.*password.*pam_pwquality.so.*)\bminlen\b=?[0-9a-zA-Z]*(.*)
        replace: \1\2
      register: result_pam_option_removal
      when:
      - result_pam_file_present.stat.exists

    - name: Ensure PAM Enforces Password Requirements - Minimum Length - Ensure authselect
        changes are applied
      ansible.builtin.command:
        cmd: authselect apply-changes -b
      when:
      - result_authselect_present.stat.exists
      - result_pam_option_removal is changed
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - '"libpwquality" in ansible_facts.packages'
    - result_pam_auth_file_present.stat.exists
    tags:
    - CJIS-5.6.2.1.1
    - DISA-STIG-OL09-00-001105
    - NIST-800-53-CM-6(a)
    - NIST-800-53-IA-5(1)(a)
    - NIST-800-53-IA-5(4)
    - NIST-800-53-IA-5(c)
    - PCI-DSS-Req-8.2.3
    - PCI-DSSv4-8.3
    - PCI-DSSv4-8.3.6
    - accounts_password_pam_minlen
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Ensure PAM Enforces Password Requirements - Minimum Length - Check if /etc/pam.d/password-auth
      file is present
    ansible.builtin.stat:
      path: /etc/pam.d/password-auth
    register: result_pam_password_auth_file_present
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - '"libpwquality" in ansible_facts.packages'
    tags:
    - CJIS-5.6.2.1.1
    - DISA-STIG-OL09-00-001105
    - NIST-800-53-CM-6(a)
    - NIST-800-53-IA-5(1)(a)
    - NIST-800-53-IA-5(4)
    - NIST-800-53-IA-5(c)
    - PCI-DSS-Req-8.2.3
    - PCI-DSSv4-8.3
    - PCI-DSSv4-8.3.6
    - accounts_password_pam_minlen
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Ensure PAM Enforces Password Requirements - Minimum Length - Check the proper
      remediation for the system
    block:

    - name: Ensure PAM Enforces Password Requirements - Minimum Length - Define the
        PAM file to be edited as a local fact
      ansible.builtin.set_fact:
        pam_file_path: /etc/pam.d/password-auth

    - name: Ensure PAM Enforces Password Requirements - Minimum Length - Check if
        system relies on authselect tool
      ansible.builtin.stat:
        path: /usr/bin/authselect
      register: result_authselect_present

    - name: Ensure PAM Enforces Password Requirements - Minimum Length - Ensure authselect
        custom profile is used if authselect is present
      block:

      - name: Ensure PAM Enforces Password Requirements - Minimum Length - Check integrity
          of authselect current profile
        ansible.builtin.command:
          cmd: authselect check
        register: result_authselect_check_cmd
        changed_when: false
        check_mode: false
        failed_when: false

      - name: Ensure PAM Enforces Password Requirements - Minimum Length - Informative
          message based on the authselect integrity check result
        ansible.builtin.assert:
          that:
          - ansible_check_mode or result_authselect_check_cmd.rc == 0
          fail_msg:
          - authselect integrity check failed. Remediation aborted!
          - This remediation could not be applied because an authselect profile was
            not selected or the selected profile is not intact.
          - It is not recommended to manually edit the PAM files when authselect tool
            is available.
          - In cases where the default authselect profile does not cover a specific
            demand, a custom authselect profile is recommended.
          success_msg:
          - authselect integrity check passed

      - name: Ensure PAM Enforces Password Requirements - Minimum Length - Get authselect
          current profile
        ansible.builtin.shell:
          cmd: authselect current -r | awk '{ print $1 }'
        register: result_authselect_profile
        changed_when: false
        when:
        - result_authselect_check_cmd is success

      - name: Ensure PAM Enforces Password Requirements - Minimum Length - Define
          the current authselect profile as a local fact
        ansible.builtin.set_fact:
          authselect_current_profile: '{{ result_authselect_profile.stdout }}'
          authselect_custom_profile: '{{ result_authselect_profile.stdout }}'
        when:
        - result_authselect_profile is not skipped
        - result_authselect_profile.stdout is match("custom/")

      - name: Ensure PAM Enforces Password Requirements - Minimum Length - Define
          the new authselect custom profile as a local fact
        ansible.builtin.set_fact:
          authselect_current_profile: '{{ result_authselect_profile.stdout }}'
          authselect_custom_profile: custom/hardening
        when:
        - result_authselect_profile is not skipped
        - result_authselect_profile.stdout is not match("custom/")

      - name: Ensure PAM Enforces Password Requirements - Minimum Length - Get authselect
          current features to also enable them in the custom profile
        ansible.builtin.shell:
          cmd: authselect current | tail -n+3 | awk '{ print $2 }'
        register: result_authselect_features
        changed_when: false
        check_mode: false
        when:
        - result_authselect_profile is not skipped
        - authselect_current_profile is not match("custom/")

      - name: Ensure PAM Enforces Password Requirements - Minimum Length - Check if
          any custom profile with the same name was already created
        ansible.builtin.stat:
          path: /etc/authselect/{{ authselect_custom_profile }}
        register: result_authselect_custom_profile_present
        changed_when: false
        when:
        - result_authselect_profile is not skipped
        - authselect_current_profile is not match("custom/")

      - name: Ensure PAM Enforces Password Requirements - Minimum Length - Create
          an authselect custom profile based on the current profile
        ansible.builtin.command:
          cmd: authselect create-profile hardening -b {{ authselect_current_profile
            }}
        when:
        - result_authselect_profile is not skipped
        - result_authselect_check_cmd is success
        - authselect_current_profile is not match("^(custom/|local)")
        - not result_authselect_custom_profile_present.stat.exists

      - name: Ensure PAM Enforces Password Requirements - Minimum Length - Create
          an authselect custom profile based on sssd profile
        ansible.builtin.command:
          cmd: authselect create-profile hardening -b sssd
        when:
        - result_authselect_profile is not skipped
        - result_authselect_check_cmd is success
        - authselect_current_profile is match("local")
        - not result_authselect_custom_profile_present.stat.exists

      - name: Ensure PAM Enforces Password Requirements - Minimum Length - Ensure
          authselect changes are applied
        ansible.builtin.command:
          cmd: authselect apply-changes -b --backup=before-hardening-custom-profile
        when:
        - result_authselect_check_cmd is success
        - result_authselect_profile is not skipped
        - authselect_current_profile is not match("custom/")
        - authselect_custom_profile is not match(authselect_current_profile)

      - name: Ensure PAM Enforces Password Requirements - Minimum Length - Ensure
          the authselect custom profile is selected
        ansible.builtin.command:
          cmd: authselect select {{ authselect_custom_profile }}
        register: result_pam_authselect_select_profile
        when:
        - result_authselect_check_cmd is success
        - result_authselect_profile is not skipped
        - authselect_current_profile is not match("custom/")
        - authselect_custom_profile is not match(authselect_current_profile)

      - name: Ensure PAM Enforces Password Requirements - Minimum Length - Restore
          the authselect features in the custom profile
        ansible.builtin.command:
          cmd: authselect enable-feature {{ item }}
        loop: '{{ result_authselect_features.stdout_lines }}'
        register: result_pam_authselect_restore_features
        when:
        - result_authselect_profile is not skipped
        - result_authselect_features is not skipped
        - result_pam_authselect_select_profile is not skipped

      - name: Ensure PAM Enforces Password Requirements - Minimum Length - Ensure
          authselect changes are applied
        ansible.builtin.command:
          cmd: authselect apply-changes -b --backup=after-hardening-custom-profile
        when:
        - result_authselect_check_cmd is success
        - result_authselect_profile is not skipped
        - result_pam_authselect_restore_features is not skipped

      - name: Ensure PAM Enforces Password Requirements - Minimum Length - Change
          the PAM file to be edited according to the custom authselect profile
        ansible.builtin.set_fact:
          pam_file_path: /etc/authselect/{{ authselect_custom_profile }}/{{ pam_file_path
            | basename }}
        when:
        - authselect_custom_profile is defined
      when:
      - result_authselect_present.stat.exists

    - name: Ensure PAM Enforces Password Requirements - Minimum Length - Define a
        fact for control already filtered in case filters are used
      ansible.builtin.set_fact:
        pam_module_control: ''

    - name: Ensure PAM Enforces Password Requirements - Minimum Length - Check if
        {{ pam_file_path }} file is present
      ansible.builtin.stat:
        path: '{{ pam_file_path }}'
      register: result_pam_file_present

    - name: Ensure PAM Enforces Password Requirements - Minimum Length - Ensure the
        "minlen" option from "pam_pwquality.so" is not present in {{ pam_file_path
        }}
      ansible.builtin.replace:
        dest: '{{ pam_file_path }}'
        regexp: (.*password.*pam_pwquality.so.*)\bminlen\b=?[0-9a-zA-Z]*(.*)
        replace: \1\2
      register: result_pam_option_removal
      when:
      - result_pam_file_present.stat.exists

    - name: Ensure PAM Enforces Password Requirements - Minimum Length - Ensure authselect
        changes are applied
      ansible.builtin.command:
        cmd: authselect apply-changes -b
      when:
      - result_authselect_present.stat.exists
      - result_pam_option_removal is changed
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - '"libpwquality" in ansible_facts.packages'
    - result_pam_password_auth_file_present.stat.exists
    tags:
    - CJIS-5.6.2.1.1
    - DISA-STIG-OL09-00-001105
    - NIST-800-53-CM-6(a)
    - NIST-800-53-IA-5(1)(a)
    - NIST-800-53-IA-5(4)
    - NIST-800-53-IA-5(c)
    - PCI-DSS-Req-8.2.3
    - PCI-DSSv4-8.3
    - PCI-DSSv4-8.3.6
    - accounts_password_pam_minlen
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Ensure PAM Enforces Password Requirements - Minimum Length - Ensure PAM
      variable minlen is set accordingly
    ansible.builtin.lineinfile:
      create: true
      dest: /etc/security/pwquality.conf
      regexp: ^#?\s*minlen
      line: minlen = {{ var_password_pam_minlen }}
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - '"libpwquality" in ansible_facts.packages'
    tags:
    - CJIS-5.6.2.1.1
    - DISA-STIG-OL09-00-001105
    - NIST-800-53-CM-6(a)
    - NIST-800-53-IA-5(1)(a)
    - NIST-800-53-IA-5(4)
    - NIST-800-53-IA-5(c)
    - PCI-DSS-Req-8.2.3
    - PCI-DSSv4-8.3
    - PCI-DSSv4-8.3.6
    - accounts_password_pam_minlen
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Ensure PAM Enforces Password Requirements - Minimum Special Characters -
      Find pwquality.conf.d files
    ansible.builtin.find:
      paths: /etc/security/pwquality.conf.d/
      patterns: '*.conf'
    register: pwquality_conf_d_files
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - '"libpwquality" in ansible_facts.packages'
    tags:
    - DISA-STIG-OL09-00-001120
    - NIST-800-53-CM-6(a)
    - NIST-800-53-IA-5(1)(a)
    - NIST-800-53-IA-5(4)
    - NIST-800-53-IA-5(c)
    - accounts_password_pam_ocredit
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Ensure PAM Enforces Password Requirements - Minimum Special Characters -
      Ensure ocredit is not set in pwquality.conf.d
    ansible.builtin.lineinfile:
      path: '{{ item.path }}'
      regexp: ^\s*\bocredit\b.*
      state: absent
    with_items: '{{ pwquality_conf_d_files.files }}'
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - '"libpwquality" in ansible_facts.packages'
    tags:
    - DISA-STIG-OL09-00-001120
    - NIST-800-53-CM-6(a)
    - NIST-800-53-IA-5(1)(a)
    - NIST-800-53-IA-5(4)
    - NIST-800-53-IA-5(c)
    - accounts_password_pam_ocredit
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Ensure PAM Enforces Password Requirements - Minimum Special Characters -
      Check if /etc/pam.d/system-auth file is present
    ansible.builtin.stat:
      path: /etc/pam.d/system-auth
    register: result_pam_auth_file_present
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - '"libpwquality" in ansible_facts.packages'
    tags:
    - DISA-STIG-OL09-00-001120
    - NIST-800-53-CM-6(a)
    - NIST-800-53-IA-5(1)(a)
    - NIST-800-53-IA-5(4)
    - NIST-800-53-IA-5(c)
    - accounts_password_pam_ocredit
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Ensure PAM Enforces Password Requirements - Minimum Special Characters -
      Check the proper remediation for the system
    block:

    - name: Ensure PAM Enforces Password Requirements - Minimum Special Characters
        - Define the PAM file to be edited as a local fact
      ansible.builtin.set_fact:
        pam_file_path: /etc/pam.d/system-auth

    - name: Ensure PAM Enforces Password Requirements - Minimum Special Characters
        - Check if system relies on authselect tool
      ansible.builtin.stat:
        path: /usr/bin/authselect
      register: result_authselect_present

    - name: Ensure PAM Enforces Password Requirements - Minimum Special Characters
        - Ensure authselect custom profile is used if authselect is present
      block:

      - name: Ensure PAM Enforces Password Requirements - Minimum Special Characters
          - Check integrity of authselect current profile
        ansible.builtin.command:
          cmd: authselect check
        register: result_authselect_check_cmd
        changed_when: false
        check_mode: false
        failed_when: false

      - name: Ensure PAM Enforces Password Requirements - Minimum Special Characters
          - Informative message based on the authselect integrity check result
        ansible.builtin.assert:
          that:
          - ansible_check_mode or result_authselect_check_cmd.rc == 0
          fail_msg:
          - authselect integrity check failed. Remediation aborted!
          - This remediation could not be applied because an authselect profile was
            not selected or the selected profile is not intact.
          - It is not recommended to manually edit the PAM files when authselect tool
            is available.
          - In cases where the default authselect profile does not cover a specific
            demand, a custom authselect profile is recommended.
          success_msg:
          - authselect integrity check passed

      - name: Ensure PAM Enforces Password Requirements - Minimum Special Characters
          - Get authselect current profile
        ansible.builtin.shell:
          cmd: authselect current -r | awk '{ print $1 }'
        register: result_authselect_profile
        changed_when: false
        when:
        - result_authselect_check_cmd is success

      - name: Ensure PAM Enforces Password Requirements - Minimum Special Characters
          - Define the current authselect profile as a local fact
        ansible.builtin.set_fact:
          authselect_current_profile: '{{ result_authselect_profile.stdout }}'
          authselect_custom_profile: '{{ result_authselect_profile.stdout }}'
        when:
        - result_authselect_profile is not skipped
        - result_authselect_profile.stdout is match("custom/")

      - name: Ensure PAM Enforces Password Requirements - Minimum Special Characters
          - Define the new authselect custom profile as a local fact
        ansible.builtin.set_fact:
          authselect_current_profile: '{{ result_authselect_profile.stdout }}'
          authselect_custom_profile: custom/hardening
        when:
        - result_authselect_profile is not skipped
        - result_authselect_profile.stdout is not match("custom/")

      - name: Ensure PAM Enforces Password Requirements - Minimum Special Characters
          - Get authselect current features to also enable them in the custom profile
        ansible.builtin.shell:
          cmd: authselect current | tail -n+3 | awk '{ print $2 }'
        register: result_authselect_features
        changed_when: false
        check_mode: false
        when:
        - result_authselect_profile is not skipped
        - authselect_current_profile is not match("custom/")

      - name: Ensure PAM Enforces Password Requirements - Minimum Special Characters
          - Check if any custom profile with the same name was already created
        ansible.builtin.stat:
          path: /etc/authselect/{{ authselect_custom_profile }}
        register: result_authselect_custom_profile_present
        changed_when: false
        when:
        - result_authselect_profile is not skipped
        - authselect_current_profile is not match("custom/")

      - name: Ensure PAM Enforces Password Requirements - Minimum Special Characters
          - Create an authselect custom profile based on the current profile
        ansible.builtin.command:
          cmd: authselect create-profile hardening -b {{ authselect_current_profile
            }}
        when:
        - result_authselect_profile is not skipped
        - result_authselect_check_cmd is success
        - authselect_current_profile is not match("^(custom/|local)")
        - not result_authselect_custom_profile_present.stat.exists

      - name: Ensure PAM Enforces Password Requirements - Minimum Special Characters
          - Create an authselect custom profile based on sssd profile
        ansible.builtin.command:
          cmd: authselect create-profile hardening -b sssd
        when:
        - result_authselect_profile is not skipped
        - result_authselect_check_cmd is success
        - authselect_current_profile is match("local")
        - not result_authselect_custom_profile_present.stat.exists

      - name: Ensure PAM Enforces Password Requirements - Minimum Special Characters
          - Ensure authselect changes are applied
        ansible.builtin.command:
          cmd: authselect apply-changes -b --backup=before-hardening-custom-profile
        when:
        - result_authselect_check_cmd is success
        - result_authselect_profile is not skipped
        - authselect_current_profile is not match("custom/")
        - authselect_custom_profile is not match(authselect_current_profile)

      - name: Ensure PAM Enforces Password Requirements - Minimum Special Characters
          - Ensure the authselect custom profile is selected
        ansible.builtin.command:
          cmd: authselect select {{ authselect_custom_profile }}
        register: result_pam_authselect_select_profile
        when:
        - result_authselect_check_cmd is success
        - result_authselect_profile is not skipped
        - authselect_current_profile is not match("custom/")
        - authselect_custom_profile is not match(authselect_current_profile)

      - name: Ensure PAM Enforces Password Requirements - Minimum Special Characters
          - Restore the authselect features in the custom profile
        ansible.builtin.command:
          cmd: authselect enable-feature {{ item }}
        loop: '{{ result_authselect_features.stdout_lines }}'
        register: result_pam_authselect_restore_features
        when:
        - result_authselect_profile is not skipped
        - result_authselect_features is not skipped
        - result_pam_authselect_select_profile is not skipped

      - name: Ensure PAM Enforces Password Requirements - Minimum Special Characters
          - Ensure authselect changes are applied
        ansible.builtin.command:
          cmd: authselect apply-changes -b --backup=after-hardening-custom-profile
        when:
        - result_authselect_check_cmd is success
        - result_authselect_profile is not skipped
        - result_pam_authselect_restore_features is not skipped

      - name: Ensure PAM Enforces Password Requirements - Minimum Special Characters
          - Change the PAM file to be edited according to the custom authselect profile
        ansible.builtin.set_fact:
          pam_file_path: /etc/authselect/{{ authselect_custom_profile }}/{{ pam_file_path
            | basename }}
        when:
        - authselect_custom_profile is defined
      when:
      - result_authselect_present.stat.exists

    - name: Ensure PAM Enforces Password Requirements - Minimum Special Characters
        - Define a fact for control already filtered in case filters are used
      ansible.builtin.set_fact:
        pam_module_control: ''

    - name: Ensure PAM Enforces Password Requirements - Minimum Special Characters
        - Check if {{ pam_file_path }} file is present
      ansible.builtin.stat:
        path: '{{ pam_file_path }}'
      register: result_pam_file_present

    - name: Ensure PAM Enforces Password Requirements - Minimum Special Characters
        - Ensure the "ocredit" option from "pam_pwquality.so" is not present in {{
        pam_file_path }}
      ansible.builtin.replace:
        dest: '{{ pam_file_path }}'
        regexp: (.*password.*pam_pwquality.so.*)\bocredit\b=?[0-9a-zA-Z]*(.*)
        replace: \1\2
      register: result_pam_option_removal
      when:
      - result_pam_file_present.stat.exists

    - name: Ensure PAM Enforces Password Requirements - Minimum Special Characters
        - Ensure authselect changes are applied
      ansible.builtin.command:
        cmd: authselect apply-changes -b
      when:
      - result_authselect_present.stat.exists
      - result_pam_option_removal is changed
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - '"libpwquality" in ansible_facts.packages'
    - result_pam_auth_file_present.stat.exists
    tags:
    - DISA-STIG-OL09-00-001120
    - NIST-800-53-CM-6(a)
    - NIST-800-53-IA-5(1)(a)
    - NIST-800-53-IA-5(4)
    - NIST-800-53-IA-5(c)
    - accounts_password_pam_ocredit
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Ensure PAM Enforces Password Requirements - Minimum Special Characters -
      Check if /etc/pam.d/password-auth file is present
    ansible.builtin.stat:
      path: /etc/pam.d/password-auth
    register: result_pam_password_auth_file_present
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - '"libpwquality" in ansible_facts.packages'
    tags:
    - DISA-STIG-OL09-00-001120
    - NIST-800-53-CM-6(a)
    - NIST-800-53-IA-5(1)(a)
    - NIST-800-53-IA-5(4)
    - NIST-800-53-IA-5(c)
    - accounts_password_pam_ocredit
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Ensure PAM Enforces Password Requirements - Minimum Special Characters -
      Check the proper remediation for the system
    block:

    - name: Ensure PAM Enforces Password Requirements - Minimum Special Characters
        - Define the PAM file to be edited as a local fact
      ansible.builtin.set_fact:
        pam_file_path: /etc/pam.d/password-auth

    - name: Ensure PAM Enforces Password Requirements - Minimum Special Characters
        - Check if system relies on authselect tool
      ansible.builtin.stat:
        path: /usr/bin/authselect
      register: result_authselect_present

    - name: Ensure PAM Enforces Password Requirements - Minimum Special Characters
        - Ensure authselect custom profile is used if authselect is present
      block:

      - name: Ensure PAM Enforces Password Requirements - Minimum Special Characters
          - Check integrity of authselect current profile
        ansible.builtin.command:
          cmd: authselect check
        register: result_authselect_check_cmd
        changed_when: false
        check_mode: false
        failed_when: false

      - name: Ensure PAM Enforces Password Requirements - Minimum Special Characters
          - Informative message based on the authselect integrity check result
        ansible.builtin.assert:
          that:
          - ansible_check_mode or result_authselect_check_cmd.rc == 0
          fail_msg:
          - authselect integrity check failed. Remediation aborted!
          - This remediation could not be applied because an authselect profile was
            not selected or the selected profile is not intact.
          - It is not recommended to manually edit the PAM files when authselect tool
            is available.
          - In cases where the default authselect profile does not cover a specific
            demand, a custom authselect profile is recommended.
          success_msg:
          - authselect integrity check passed

      - name: Ensure PAM Enforces Password Requirements - Minimum Special Characters
          - Get authselect current profile
        ansible.builtin.shell:
          cmd: authselect current -r | awk '{ print $1 }'
        register: result_authselect_profile
        changed_when: false
        when:
        - result_authselect_check_cmd is success

      - name: Ensure PAM Enforces Password Requirements - Minimum Special Characters
          - Define the current authselect profile as a local fact
        ansible.builtin.set_fact:
          authselect_current_profile: '{{ result_authselect_profile.stdout }}'
          authselect_custom_profile: '{{ result_authselect_profile.stdout }}'
        when:
        - result_authselect_profile is not skipped
        - result_authselect_profile.stdout is match("custom/")

      - name: Ensure PAM Enforces Password Requirements - Minimum Special Characters
          - Define the new authselect custom profile as a local fact
        ansible.builtin.set_fact:
          authselect_current_profile: '{{ result_authselect_profile.stdout }}'
          authselect_custom_profile: custom/hardening
        when:
        - result_authselect_profile is not skipped
        - result_authselect_profile.stdout is not match("custom/")

      - name: Ensure PAM Enforces Password Requirements - Minimum Special Characters
          - Get authselect current features to also enable them in the custom profile
        ansible.builtin.shell:
          cmd: authselect current | tail -n+3 | awk '{ print $2 }'
        register: result_authselect_features
        changed_when: false
        check_mode: false
        when:
        - result_authselect_profile is not skipped
        - authselect_current_profile is not match("custom/")

      - name: Ensure PAM Enforces Password Requirements - Minimum Special Characters
          - Check if any custom profile with the same name was already created
        ansible.builtin.stat:
          path: /etc/authselect/{{ authselect_custom_profile }}
        register: result_authselect_custom_profile_present
        changed_when: false
        when:
        - result_authselect_profile is not skipped
        - authselect_current_profile is not match("custom/")

      - name: Ensure PAM Enforces Password Requirements - Minimum Special Characters
          - Create an authselect custom profile based on the current profile
        ansible.builtin.command:
          cmd: authselect create-profile hardening -b {{ authselect_current_profile
            }}
        when:
        - result_authselect_profile is not skipped
        - result_authselect_check_cmd is success
        - authselect_current_profile is not match("^(custom/|local)")
        - not result_authselect_custom_profile_present.stat.exists

      - name: Ensure PAM Enforces Password Requirements - Minimum Special Characters
          - Create an authselect custom profile based on sssd profile
        ansible.builtin.command:
          cmd: authselect create-profile hardening -b sssd
        when:
        - result_authselect_profile is not skipped
        - result_authselect_check_cmd is success
        - authselect_current_profile is match("local")
        - not result_authselect_custom_profile_present.stat.exists

      - name: Ensure PAM Enforces Password Requirements - Minimum Special Characters
          - Ensure authselect changes are applied
        ansible.builtin.command:
          cmd: authselect apply-changes -b --backup=before-hardening-custom-profile
        when:
        - result_authselect_check_cmd is success
        - result_authselect_profile is not skipped
        - authselect_current_profile is not match("custom/")
        - authselect_custom_profile is not match(authselect_current_profile)

      - name: Ensure PAM Enforces Password Requirements - Minimum Special Characters
          - Ensure the authselect custom profile is selected
        ansible.builtin.command:
          cmd: authselect select {{ authselect_custom_profile }}
        register: result_pam_authselect_select_profile
        when:
        - result_authselect_check_cmd is success
        - result_authselect_profile is not skipped
        - authselect_current_profile is not match("custom/")
        - authselect_custom_profile is not match(authselect_current_profile)

      - name: Ensure PAM Enforces Password Requirements - Minimum Special Characters
          - Restore the authselect features in the custom profile
        ansible.builtin.command:
          cmd: authselect enable-feature {{ item }}
        loop: '{{ result_authselect_features.stdout_lines }}'
        register: result_pam_authselect_restore_features
        when:
        - result_authselect_profile is not skipped
        - result_authselect_features is not skipped
        - result_pam_authselect_select_profile is not skipped

      - name: Ensure PAM Enforces Password Requirements - Minimum Special Characters
          - Ensure authselect changes are applied
        ansible.builtin.command:
          cmd: authselect apply-changes -b --backup=after-hardening-custom-profile
        when:
        - result_authselect_check_cmd is success
        - result_authselect_profile is not skipped
        - result_pam_authselect_restore_features is not skipped

      - name: Ensure PAM Enforces Password Requirements - Minimum Special Characters
          - Change the PAM file to be edited according to the custom authselect profile
        ansible.builtin.set_fact:
          pam_file_path: /etc/authselect/{{ authselect_custom_profile }}/{{ pam_file_path
            | basename }}
        when:
        - authselect_custom_profile is defined
      when:
      - result_authselect_present.stat.exists

    - name: Ensure PAM Enforces Password Requirements - Minimum Special Characters
        - Define a fact for control already filtered in case filters are used
      ansible.builtin.set_fact:
        pam_module_control: ''

    - name: Ensure PAM Enforces Password Requirements - Minimum Special Characters
        - Check if {{ pam_file_path }} file is present
      ansible.builtin.stat:
        path: '{{ pam_file_path }}'
      register: result_pam_file_present

    - name: Ensure PAM Enforces Password Requirements - Minimum Special Characters
        - Ensure the "ocredit" option from "pam_pwquality.so" is not present in {{
        pam_file_path }}
      ansible.builtin.replace:
        dest: '{{ pam_file_path }}'
        regexp: (.*password.*pam_pwquality.so.*)\bocredit\b=?[0-9a-zA-Z]*(.*)
        replace: \1\2
      register: result_pam_option_removal
      when:
      - result_pam_file_present.stat.exists

    - name: Ensure PAM Enforces Password Requirements - Minimum Special Characters
        - Ensure authselect changes are applied
      ansible.builtin.command:
        cmd: authselect apply-changes -b
      when:
      - result_authselect_present.stat.exists
      - result_pam_option_removal is changed
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - '"libpwquality" in ansible_facts.packages'
    - result_pam_password_auth_file_present.stat.exists
    tags:
    - DISA-STIG-OL09-00-001120
    - NIST-800-53-CM-6(a)
    - NIST-800-53-IA-5(1)(a)
    - NIST-800-53-IA-5(4)
    - NIST-800-53-IA-5(c)
    - accounts_password_pam_ocredit
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Ensure PAM Enforces Password Requirements - Minimum Special Characters -
      Ensure PAM variable ocredit is set accordingly
    ansible.builtin.lineinfile:
      create: true
      dest: /etc/security/pwquality.conf
      regexp: ^#?\s*ocredit
      line: ocredit = {{ var_password_pam_ocredit }}
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - '"libpwquality" in ansible_facts.packages'
    tags:
    - DISA-STIG-OL09-00-001120
    - NIST-800-53-CM-6(a)
    - NIST-800-53-IA-5(1)(a)
    - NIST-800-53-IA-5(4)
    - NIST-800-53-IA-5(c)
    - accounts_password_pam_ocredit
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Ensure PAM password complexity module is enabled in password-auth - Check
      if /etc/pam.d/password-auth file is present
    ansible.builtin.stat:
      path: /etc/pam.d/password-auth
    register: result_pam_password_auth_file_present
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - '"libpwquality" in ansible_facts.packages'
    tags:
    - DISA-STIG-OL09-00-001010
    - accounts_password_pam_pwquality_password_auth
    - configure_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - no_reboot_needed

  - name: Ensure PAM password complexity module is enabled in password-auth - Check
      the proper remediation for the system
    block:

    - name: Ensure PAM password complexity module is enabled in password-auth - Define
        the PAM file to be edited as a local fact
      ansible.builtin.set_fact:
        pam_file_path: /etc/pam.d/password-auth

    - name: Ensure PAM password complexity module is enabled in password-auth - Check
        if system relies on authselect tool
      ansible.builtin.stat:
        path: /usr/bin/authselect
      register: result_authselect_present

    - name: Ensure PAM password complexity module is enabled in password-auth - Ensure
        authselect custom profile is used if authselect is present
      block:

      - name: Ensure PAM password complexity module is enabled in password-auth -
          Check integrity of authselect current profile
        ansible.builtin.command:
          cmd: authselect check
        register: result_authselect_check_cmd
        changed_when: false
        check_mode: false
        failed_when: false

      - name: Ensure PAM password complexity module is enabled in password-auth -
          Informative message based on the authselect integrity check result
        ansible.builtin.assert:
          that:
          - ansible_check_mode or result_authselect_check_cmd.rc == 0
          fail_msg:
          - authselect integrity check failed. Remediation aborted!
          - This remediation could not be applied because an authselect profile was
            not selected or the selected profile is not intact.
          - It is not recommended to manually edit the PAM files when authselect tool
            is available.
          - In cases where the default authselect profile does not cover a specific
            demand, a custom authselect profile is recommended.
          success_msg:
          - authselect integrity check passed

      - name: Ensure PAM password complexity module is enabled in password-auth -
          Get authselect current profile
        ansible.builtin.shell:
          cmd: authselect current -r | awk '{ print $1 }'
        register: result_authselect_profile
        changed_when: false
        when:
        - result_authselect_check_cmd is success

      - name: Ensure PAM password complexity module is enabled in password-auth -
          Define the current authselect profile as a local fact
        ansible.builtin.set_fact:
          authselect_current_profile: '{{ result_authselect_profile.stdout }}'
          authselect_custom_profile: '{{ result_authselect_profile.stdout }}'
        when:
        - result_authselect_profile is not skipped
        - result_authselect_profile.stdout is match("custom/")

      - name: Ensure PAM password complexity module is enabled in password-auth -
          Define the new authselect custom profile as a local fact
        ansible.builtin.set_fact:
          authselect_current_profile: '{{ result_authselect_profile.stdout }}'
          authselect_custom_profile: custom/hardening
        when:
        - result_authselect_profile is not skipped
        - result_authselect_profile.stdout is not match("custom/")

      - name: Ensure PAM password complexity module is enabled in password-auth -
          Get authselect current features to also enable them in the custom profile
        ansible.builtin.shell:
          cmd: authselect current | tail -n+3 | awk '{ print $2 }'
        register: result_authselect_features
        changed_when: false
        check_mode: false
        when:
        - result_authselect_profile is not skipped
        - authselect_current_profile is not match("custom/")

      - name: Ensure PAM password complexity module is enabled in password-auth -
          Check if any custom profile with the same name was already created
        ansible.builtin.stat:
          path: /etc/authselect/{{ authselect_custom_profile }}
        register: result_authselect_custom_profile_present
        changed_when: false
        when:
        - result_authselect_profile is not skipped
        - authselect_current_profile is not match("custom/")

      - name: Ensure PAM password complexity module is enabled in password-auth -
          Create an authselect custom profile based on the current profile
        ansible.builtin.command:
          cmd: authselect create-profile hardening -b {{ authselect_current_profile
            }}
        when:
        - result_authselect_profile is not skipped
        - result_authselect_check_cmd is success
        - authselect_current_profile is not match("^(custom/|local)")
        - not result_authselect_custom_profile_present.stat.exists

      - name: Ensure PAM password complexity module is enabled in password-auth -
          Create an authselect custom profile based on sssd profile
        ansible.builtin.command:
          cmd: authselect create-profile hardening -b sssd
        when:
        - result_authselect_profile is not skipped
        - result_authselect_check_cmd is success
        - authselect_current_profile is match("local")
        - not result_authselect_custom_profile_present.stat.exists

      - name: Ensure PAM password complexity module is enabled in password-auth -
          Ensure authselect changes are applied
        ansible.builtin.command:
          cmd: authselect apply-changes -b --backup=before-hardening-custom-profile
        when:
        - result_authselect_check_cmd is success
        - result_authselect_profile is not skipped
        - authselect_current_profile is not match("custom/")
        - authselect_custom_profile is not match(authselect_current_profile)

      - name: Ensure PAM password complexity module is enabled in password-auth -
          Ensure the authselect custom profile is selected
        ansible.builtin.command:
          cmd: authselect select {{ authselect_custom_profile }}
        register: result_pam_authselect_select_profile
        when:
        - result_authselect_check_cmd is success
        - result_authselect_profile is not skipped
        - authselect_current_profile is not match("custom/")
        - authselect_custom_profile is not match(authselect_current_profile)

      - name: Ensure PAM password complexity module is enabled in password-auth -
          Restore the authselect features in the custom profile
        ansible.builtin.command:
          cmd: authselect enable-feature {{ item }}
        loop: '{{ result_authselect_features.stdout_lines }}'
        register: result_pam_authselect_restore_features
        when:
        - result_authselect_profile is not skipped
        - result_authselect_features is not skipped
        - result_pam_authselect_select_profile is not skipped

      - name: Ensure PAM password complexity module is enabled in password-auth -
          Ensure authselect changes are applied
        ansible.builtin.command:
          cmd: authselect apply-changes -b --backup=after-hardening-custom-profile
        when:
        - result_authselect_check_cmd is success
        - result_authselect_profile is not skipped
        - result_pam_authselect_restore_features is not skipped

      - name: Ensure PAM password complexity module is enabled in password-auth -
          Change the PAM file to be edited according to the custom authselect profile
        ansible.builtin.set_fact:
          pam_file_path: /etc/authselect/{{ authselect_custom_profile }}/{{ pam_file_path
            | basename }}
        when:
        - authselect_custom_profile is defined
      when:
      - result_authselect_present.stat.exists

    - name: Ensure PAM password complexity module is enabled in password-auth - Define
        a fact for control already filtered in case filters are used
      ansible.builtin.set_fact:
        pam_module_control: requisite

    - name: Ensure PAM password complexity module is enabled in password-auth - Check
        if expected PAM module line is present in {{ pam_file_path }}
      ansible.builtin.lineinfile:
        path: '{{ pam_file_path }}'
        regexp: ^\s*password\s+{{ pam_module_control | regex_escape() }}\s+pam_pwquality.so\s*.*
        state: absent
      check_mode: true
      changed_when: false
      register: result_pam_line_present

    - name: Ensure PAM password complexity module is enabled in password-auth - Include
        or update the PAM module line in {{ pam_file_path }}
      block:

      - name: Ensure PAM password complexity module is enabled in password-auth -
          Check if required PAM module line is present in {{ pam_file_path }} with
          different control
        ansible.builtin.lineinfile:
          path: '{{ pam_file_path }}'
          regexp: ^\s*password\s+.*\s+pam_pwquality.so\s*
          state: absent
        check_mode: true
        changed_when: false
        register: result_pam_line_other_control_present

      - name: Ensure PAM password complexity module is enabled in password-auth -
          Ensure the correct control for the required PAM module line in {{ pam_file_path
          }}
        ansible.builtin.replace:
          dest: '{{ pam_file_path }}'
          regexp: ^(\s*password\s+).*(\bpam_pwquality.so.*)
          replace: \1{{ pam_module_control }} \2
        register: result_pam_module_edit
        when:
        - result_pam_line_other_control_present.found == 1

      - name: Ensure PAM password complexity module is enabled in password-auth -
          Ensure the required PAM module line is included in {{ pam_file_path }}
        ansible.builtin.lineinfile:
          dest: '{{ pam_file_path }}'
          insertafter: ^account.*required.*pam_permit\.so
          line: password    {{ pam_module_control }}    pam_pwquality.so
        register: result_pam_module_add
        when:
        - result_pam_line_other_control_present.found == 0 or result_pam_line_other_control_present.found
          > 1

      - name: Ensure PAM password complexity module is enabled in password-auth -
          Ensure authselect changes are applied
        ansible.builtin.command:
          cmd: authselect apply-changes -b
        when:
        - result_authselect_present is defined
        - result_authselect_present.stat.exists
        - |-
          (result_pam_module_add is defined and result_pam_module_add.changed)
           or (result_pam_module_edit is defined and result_pam_module_edit.changed)
      when:
      - result_pam_line_present.found is defined
      - result_pam_line_present.found == 0

    - name: Ensure PAM password complexity module is enabled in password-auth - Ensure
        authselect changes are applied
      ansible.builtin.command:
        cmd: authselect apply-changes -b
      when:
      - result_authselect_present.stat.exists
      - |-
        (result_pam_accounts_password_pam_pwquality_password_auth_add is defined and result_pam_accounts_password_pam_pwquality_password_auth_add.changed)
         or (result_pam_accounts_password_pam_pwquality_password_auth_edit is defined and result_pam_accounts_password_pam_pwquality_password_auth_edit.changed)
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - '"libpwquality" in ansible_facts.packages'
    - result_pam_password_auth_file_present.stat.exists
    tags:
    - DISA-STIG-OL09-00-001010
    - accounts_password_pam_pwquality_password_auth
    - configure_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - no_reboot_needed

  - name: Ensure PAM Enforces Password Requirements - Authentication Retry Prompts
      Permitted Per-Session in /etc/security/pwquality.conf - Find pwquality.conf.d
      files
    ansible.builtin.find:
      paths: /etc/security/pwquality.conf.d/
      patterns: '*.conf'
    register: pwquality_conf_d_files
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-001001
    - accounts_password_pam_pwquality_retry
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Ensure PAM Enforces Password Requirements - Authentication Retry Prompts
      Permitted Per-Session in /etc/security/pwquality.conf - Ensure retry is not
      set in pwquality.conf.d
    ansible.builtin.lineinfile:
      path: '{{ item.path }}'
      regexp: ^\s*\bretry\b.*
      state: absent
    with_items: '{{ pwquality_conf_d_files.files }}'
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-001001
    - accounts_password_pam_pwquality_retry
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Ensure PAM Enforces Password Requirements - Authentication Retry Prompts
      Permitted Per-Session in /etc/security/pwquality.conf - Check if /etc/pam.d/system-auth
      file is present
    ansible.builtin.stat:
      path: /etc/pam.d/system-auth
    register: result_pam_auth_file_present
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-001001
    - accounts_password_pam_pwquality_retry
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Ensure PAM Enforces Password Requirements - Authentication Retry Prompts
      Permitted Per-Session in /etc/security/pwquality.conf - Check the proper remediation
      for the system
    block:

    - name: Ensure PAM Enforces Password Requirements - Authentication Retry Prompts
        Permitted Per-Session in /etc/security/pwquality.conf - Define the PAM file
        to be edited as a local fact
      ansible.builtin.set_fact:
        pam_file_path: /etc/pam.d/system-auth

    - name: Ensure PAM Enforces Password Requirements - Authentication Retry Prompts
        Permitted Per-Session in /etc/security/pwquality.conf - Check if system relies
        on authselect tool
      ansible.builtin.stat:
        path: /usr/bin/authselect
      register: result_authselect_present

    - name: Ensure PAM Enforces Password Requirements - Authentication Retry Prompts
        Permitted Per-Session in /etc/security/pwquality.conf - Ensure authselect
        custom profile is used if authselect is present
      block:

      - name: Ensure PAM Enforces Password Requirements - Authentication Retry Prompts
          Permitted Per-Session in /etc/security/pwquality.conf - Check integrity
          of authselect current profile
        ansible.builtin.command:
          cmd: authselect check
        register: result_authselect_check_cmd
        changed_when: false
        check_mode: false
        failed_when: false

      - name: Ensure PAM Enforces Password Requirements - Authentication Retry Prompts
          Permitted Per-Session in /etc/security/pwquality.conf - Informative message
          based on the authselect integrity check result
        ansible.builtin.assert:
          that:
          - ansible_check_mode or result_authselect_check_cmd.rc == 0
          fail_msg:
          - authselect integrity check failed. Remediation aborted!
          - This remediation could not be applied because an authselect profile was
            not selected or the selected profile is not intact.
          - It is not recommended to manually edit the PAM files when authselect tool
            is available.
          - In cases where the default authselect profile does not cover a specific
            demand, a custom authselect profile is recommended.
          success_msg:
          - authselect integrity check passed

      - name: Ensure PAM Enforces Password Requirements - Authentication Retry Prompts
          Permitted Per-Session in /etc/security/pwquality.conf - Get authselect current
          profile
        ansible.builtin.shell:
          cmd: authselect current -r | awk '{ print $1 }'
        register: result_authselect_profile
        changed_when: false
        when:
        - result_authselect_check_cmd is success

      - name: Ensure PAM Enforces Password Requirements - Authentication Retry Prompts
          Permitted Per-Session in /etc/security/pwquality.conf - Define the current
          authselect profile as a local fact
        ansible.builtin.set_fact:
          authselect_current_profile: '{{ result_authselect_profile.stdout }}'
          authselect_custom_profile: '{{ result_authselect_profile.stdout }}'
        when:
        - result_authselect_profile is not skipped
        - result_authselect_profile.stdout is match("custom/")

      - name: Ensure PAM Enforces Password Requirements - Authentication Retry Prompts
          Permitted Per-Session in /etc/security/pwquality.conf - Define the new authselect
          custom profile as a local fact
        ansible.builtin.set_fact:
          authselect_current_profile: '{{ result_authselect_profile.stdout }}'
          authselect_custom_profile: custom/hardening
        when:
        - result_authselect_profile is not skipped
        - result_authselect_profile.stdout is not match("custom/")

      - name: Ensure PAM Enforces Password Requirements - Authentication Retry Prompts
          Permitted Per-Session in /etc/security/pwquality.conf - Get authselect current
          features to also enable them in the custom profile
        ansible.builtin.shell:
          cmd: authselect current | tail -n+3 | awk '{ print $2 }'
        register: result_authselect_features
        changed_when: false
        check_mode: false
        when:
        - result_authselect_profile is not skipped
        - authselect_current_profile is not match("custom/")

      - name: Ensure PAM Enforces Password Requirements - Authentication Retry Prompts
          Permitted Per-Session in /etc/security/pwquality.conf - Check if any custom
          profile with the same name was already created
        ansible.builtin.stat:
          path: /etc/authselect/{{ authselect_custom_profile }}
        register: result_authselect_custom_profile_present
        changed_when: false
        when:
        - result_authselect_profile is not skipped
        - authselect_current_profile is not match("custom/")

      - name: Ensure PAM Enforces Password Requirements - Authentication Retry Prompts
          Permitted Per-Session in /etc/security/pwquality.conf - Create an authselect
          custom profile based on the current profile
        ansible.builtin.command:
          cmd: authselect create-profile hardening -b {{ authselect_current_profile
            }}
        when:
        - result_authselect_profile is not skipped
        - result_authselect_check_cmd is success
        - authselect_current_profile is not match("^(custom/|local)")
        - not result_authselect_custom_profile_present.stat.exists

      - name: Ensure PAM Enforces Password Requirements - Authentication Retry Prompts
          Permitted Per-Session in /etc/security/pwquality.conf - Create an authselect
          custom profile based on sssd profile
        ansible.builtin.command:
          cmd: authselect create-profile hardening -b sssd
        when:
        - result_authselect_profile is not skipped
        - result_authselect_check_cmd is success
        - authselect_current_profile is match("local")
        - not result_authselect_custom_profile_present.stat.exists

      - name: Ensure PAM Enforces Password Requirements - Authentication Retry Prompts
          Permitted Per-Session in /etc/security/pwquality.conf - Ensure authselect
          changes are applied
        ansible.builtin.command:
          cmd: authselect apply-changes -b --backup=before-hardening-custom-profile
        when:
        - result_authselect_check_cmd is success
        - result_authselect_profile is not skipped
        - authselect_current_profile is not match("custom/")
        - authselect_custom_profile is not match(authselect_current_profile)

      - name: Ensure PAM Enforces Password Requirements - Authentication Retry Prompts
          Permitted Per-Session in /etc/security/pwquality.conf - Ensure the authselect
          custom profile is selected
        ansible.builtin.command:
          cmd: authselect select {{ authselect_custom_profile }}
        register: result_pam_authselect_select_profile
        when:
        - result_authselect_check_cmd is success
        - result_authselect_profile is not skipped
        - authselect_current_profile is not match("custom/")
        - authselect_custom_profile is not match(authselect_current_profile)

      - name: Ensure PAM Enforces Password Requirements - Authentication Retry Prompts
          Permitted Per-Session in /etc/security/pwquality.conf - Restore the authselect
          features in the custom profile
        ansible.builtin.command:
          cmd: authselect enable-feature {{ item }}
        loop: '{{ result_authselect_features.stdout_lines }}'
        register: result_pam_authselect_restore_features
        when:
        - result_authselect_profile is not skipped
        - result_authselect_features is not skipped
        - result_pam_authselect_select_profile is not skipped

      - name: Ensure PAM Enforces Password Requirements - Authentication Retry Prompts
          Permitted Per-Session in /etc/security/pwquality.conf - Ensure authselect
          changes are applied
        ansible.builtin.command:
          cmd: authselect apply-changes -b --backup=after-hardening-custom-profile
        when:
        - result_authselect_check_cmd is success
        - result_authselect_profile is not skipped
        - result_pam_authselect_restore_features is not skipped

      - name: Ensure PAM Enforces Password Requirements - Authentication Retry Prompts
          Permitted Per-Session in /etc/security/pwquality.conf - Change the PAM file
          to be edited according to the custom authselect profile
        ansible.builtin.set_fact:
          pam_file_path: /etc/authselect/{{ authselect_custom_profile }}/{{ pam_file_path
            | basename }}
        when:
        - authselect_custom_profile is defined
      when:
      - result_authselect_present.stat.exists

    - name: Ensure PAM Enforces Password Requirements - Authentication Retry Prompts
        Permitted Per-Session in /etc/security/pwquality.conf - Define a fact for
        control already filtered in case filters are used
      ansible.builtin.set_fact:
        pam_module_control: ''

    - name: Ensure PAM Enforces Password Requirements - Authentication Retry Prompts
        Permitted Per-Session in /etc/security/pwquality.conf - Check if {{ pam_file_path
        }} file is present
      ansible.builtin.stat:
        path: '{{ pam_file_path }}'
      register: result_pam_file_present

    - name: Ensure PAM Enforces Password Requirements - Authentication Retry Prompts
        Permitted Per-Session in /etc/security/pwquality.conf - Ensure the "retry"
        option from "pam_pwquality.so" is not present in {{ pam_file_path }}
      ansible.builtin.replace:
        dest: '{{ pam_file_path }}'
        regexp: (.*password.*pam_pwquality.so.*)\bretry\b=?[0-9a-zA-Z]*(.*)
        replace: \1\2
      register: result_pam_option_removal
      when:
      - result_pam_file_present.stat.exists

    - name: Ensure PAM Enforces Password Requirements - Authentication Retry Prompts
        Permitted Per-Session in /etc/security/pwquality.conf - Ensure authselect
        changes are applied
      ansible.builtin.command:
        cmd: authselect apply-changes -b
      when:
      - result_authselect_present.stat.exists
      - result_pam_option_removal is changed
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - result_pam_auth_file_present.stat.exists
    tags:
    - DISA-STIG-OL09-00-001001
    - accounts_password_pam_pwquality_retry
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Ensure PAM Enforces Password Requirements - Authentication Retry Prompts
      Permitted Per-Session in /etc/security/pwquality.conf - Check if /etc/pam.d/password-auth
      file is present
    ansible.builtin.stat:
      path: /etc/pam.d/password-auth
    register: result_pam_password_auth_file_present
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-001001
    - accounts_password_pam_pwquality_retry
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Ensure PAM Enforces Password Requirements - Authentication Retry Prompts
      Permitted Per-Session in /etc/security/pwquality.conf - Check the proper remediation
      for the system
    block:

    - name: Ensure PAM Enforces Password Requirements - Authentication Retry Prompts
        Permitted Per-Session in /etc/security/pwquality.conf - Define the PAM file
        to be edited as a local fact
      ansible.builtin.set_fact:
        pam_file_path: /etc/pam.d/password-auth

    - name: Ensure PAM Enforces Password Requirements - Authentication Retry Prompts
        Permitted Per-Session in /etc/security/pwquality.conf - Check if system relies
        on authselect tool
      ansible.builtin.stat:
        path: /usr/bin/authselect
      register: result_authselect_present

    - name: Ensure PAM Enforces Password Requirements - Authentication Retry Prompts
        Permitted Per-Session in /etc/security/pwquality.conf - Ensure authselect
        custom profile is used if authselect is present
      block:

      - name: Ensure PAM Enforces Password Requirements - Authentication Retry Prompts
          Permitted Per-Session in /etc/security/pwquality.conf - Check integrity
          of authselect current profile
        ansible.builtin.command:
          cmd: authselect check
        register: result_authselect_check_cmd
        changed_when: false
        check_mode: false
        failed_when: false

      - name: Ensure PAM Enforces Password Requirements - Authentication Retry Prompts
          Permitted Per-Session in /etc/security/pwquality.conf - Informative message
          based on the authselect integrity check result
        ansible.builtin.assert:
          that:
          - ansible_check_mode or result_authselect_check_cmd.rc == 0
          fail_msg:
          - authselect integrity check failed. Remediation aborted!
          - This remediation could not be applied because an authselect profile was
            not selected or the selected profile is not intact.
          - It is not recommended to manually edit the PAM files when authselect tool
            is available.
          - In cases where the default authselect profile does not cover a specific
            demand, a custom authselect profile is recommended.
          success_msg:
          - authselect integrity check passed

      - name: Ensure PAM Enforces Password Requirements - Authentication Retry Prompts
          Permitted Per-Session in /etc/security/pwquality.conf - Get authselect current
          profile
        ansible.builtin.shell:
          cmd: authselect current -r | awk '{ print $1 }'
        register: result_authselect_profile
        changed_when: false
        when:
        - result_authselect_check_cmd is success

      - name: Ensure PAM Enforces Password Requirements - Authentication Retry Prompts
          Permitted Per-Session in /etc/security/pwquality.conf - Define the current
          authselect profile as a local fact
        ansible.builtin.set_fact:
          authselect_current_profile: '{{ result_authselect_profile.stdout }}'
          authselect_custom_profile: '{{ result_authselect_profile.stdout }}'
        when:
        - result_authselect_profile is not skipped
        - result_authselect_profile.stdout is match("custom/")

      - name: Ensure PAM Enforces Password Requirements - Authentication Retry Prompts
          Permitted Per-Session in /etc/security/pwquality.conf - Define the new authselect
          custom profile as a local fact
        ansible.builtin.set_fact:
          authselect_current_profile: '{{ result_authselect_profile.stdout }}'
          authselect_custom_profile: custom/hardening
        when:
        - result_authselect_profile is not skipped
        - result_authselect_profile.stdout is not match("custom/")

      - name: Ensure PAM Enforces Password Requirements - Authentication Retry Prompts
          Permitted Per-Session in /etc/security/pwquality.conf - Get authselect current
          features to also enable them in the custom profile
        ansible.builtin.shell:
          cmd: authselect current | tail -n+3 | awk '{ print $2 }'
        register: result_authselect_features
        changed_when: false
        check_mode: false
        when:
        - result_authselect_profile is not skipped
        - authselect_current_profile is not match("custom/")

      - name: Ensure PAM Enforces Password Requirements - Authentication Retry Prompts
          Permitted Per-Session in /etc/security/pwquality.conf - Check if any custom
          profile with the same name was already created
        ansible.builtin.stat:
          path: /etc/authselect/{{ authselect_custom_profile }}
        register: result_authselect_custom_profile_present
        changed_when: false
        when:
        - result_authselect_profile is not skipped
        - authselect_current_profile is not match("custom/")

      - name: Ensure PAM Enforces Password Requirements - Authentication Retry Prompts
          Permitted Per-Session in /etc/security/pwquality.conf - Create an authselect
          custom profile based on the current profile
        ansible.builtin.command:
          cmd: authselect create-profile hardening -b {{ authselect_current_profile
            }}
        when:
        - result_authselect_profile is not skipped
        - result_authselect_check_cmd is success
        - authselect_current_profile is not match("^(custom/|local)")
        - not result_authselect_custom_profile_present.stat.exists

      - name: Ensure PAM Enforces Password Requirements - Authentication Retry Prompts
          Permitted Per-Session in /etc/security/pwquality.conf - Create an authselect
          custom profile based on sssd profile
        ansible.builtin.command:
          cmd: authselect create-profile hardening -b sssd
        when:
        - result_authselect_profile is not skipped
        - result_authselect_check_cmd is success
        - authselect_current_profile is match("local")
        - not result_authselect_custom_profile_present.stat.exists

      - name: Ensure PAM Enforces Password Requirements - Authentication Retry Prompts
          Permitted Per-Session in /etc/security/pwquality.conf - Ensure authselect
          changes are applied
        ansible.builtin.command:
          cmd: authselect apply-changes -b --backup=before-hardening-custom-profile
        when:
        - result_authselect_check_cmd is success
        - result_authselect_profile is not skipped
        - authselect_current_profile is not match("custom/")
        - authselect_custom_profile is not match(authselect_current_profile)

      - name: Ensure PAM Enforces Password Requirements - Authentication Retry Prompts
          Permitted Per-Session in /etc/security/pwquality.conf - Ensure the authselect
          custom profile is selected
        ansible.builtin.command:
          cmd: authselect select {{ authselect_custom_profile }}
        register: result_pam_authselect_select_profile
        when:
        - result_authselect_check_cmd is success
        - result_authselect_profile is not skipped
        - authselect_current_profile is not match("custom/")
        - authselect_custom_profile is not match(authselect_current_profile)

      - name: Ensure PAM Enforces Password Requirements - Authentication Retry Prompts
          Permitted Per-Session in /etc/security/pwquality.conf - Restore the authselect
          features in the custom profile
        ansible.builtin.command:
          cmd: authselect enable-feature {{ item }}
        loop: '{{ result_authselect_features.stdout_lines }}'
        register: result_pam_authselect_restore_features
        when:
        - result_authselect_profile is not skipped
        - result_authselect_features is not skipped
        - result_pam_authselect_select_profile is not skipped

      - name: Ensure PAM Enforces Password Requirements - Authentication Retry Prompts
          Permitted Per-Session in /etc/security/pwquality.conf - Ensure authselect
          changes are applied
        ansible.builtin.command:
          cmd: authselect apply-changes -b --backup=after-hardening-custom-profile
        when:
        - result_authselect_check_cmd is success
        - result_authselect_profile is not skipped
        - result_pam_authselect_restore_features is not skipped

      - name: Ensure PAM Enforces Password Requirements - Authentication Retry Prompts
          Permitted Per-Session in /etc/security/pwquality.conf - Change the PAM file
          to be edited according to the custom authselect profile
        ansible.builtin.set_fact:
          pam_file_path: /etc/authselect/{{ authselect_custom_profile }}/{{ pam_file_path
            | basename }}
        when:
        - authselect_custom_profile is defined
      when:
      - result_authselect_present.stat.exists

    - name: Ensure PAM Enforces Password Requirements - Authentication Retry Prompts
        Permitted Per-Session in /etc/security/pwquality.conf - Define a fact for
        control already filtered in case filters are used
      ansible.builtin.set_fact:
        pam_module_control: ''

    - name: Ensure PAM Enforces Password Requirements - Authentication Retry Prompts
        Permitted Per-Session in /etc/security/pwquality.conf - Check if {{ pam_file_path
        }} file is present
      ansible.builtin.stat:
        path: '{{ pam_file_path }}'
      register: result_pam_file_present

    - name: Ensure PAM Enforces Password Requirements - Authentication Retry Prompts
        Permitted Per-Session in /etc/security/pwquality.conf - Ensure the "retry"
        option from "pam_pwquality.so" is not present in {{ pam_file_path }}
      ansible.builtin.replace:
        dest: '{{ pam_file_path }}'
        regexp: (.*password.*pam_pwquality.so.*)\bretry\b=?[0-9a-zA-Z]*(.*)
        replace: \1\2
      register: result_pam_option_removal
      when:
      - result_pam_file_present.stat.exists

    - name: Ensure PAM Enforces Password Requirements - Authentication Retry Prompts
        Permitted Per-Session in /etc/security/pwquality.conf - Ensure authselect
        changes are applied
      ansible.builtin.command:
        cmd: authselect apply-changes -b
      when:
      - result_authselect_present.stat.exists
      - result_pam_option_removal is changed
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - result_pam_password_auth_file_present.stat.exists
    tags:
    - DISA-STIG-OL09-00-001001
    - accounts_password_pam_pwquality_retry
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Ensure PAM Enforces Password Requirements - Authentication Retry Prompts
      Permitted Per-Session in /etc/security/pwquality.conf - Ensure PAM variable
      retry is set accordingly
    ansible.builtin.lineinfile:
      create: true
      dest: /etc/security/pwquality.conf
      regexp: ^#?\s*retry
      line: retry = {{ var_password_pam_retry }}
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-001001
    - accounts_password_pam_pwquality_retry
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Ensure PAM password complexity module is enabled in system-auth - Check
      if /etc/pam.d/system-auth file is present
    ansible.builtin.stat:
      path: /etc/pam.d/system-auth
    register: result_pam_auth_file_present
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - '"libpwquality" in ansible_facts.packages'
    tags:
    - DISA-STIG-OL09-00-001000
    - accounts_password_pam_pwquality_system_auth
    - configure_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - no_reboot_needed

  - name: Ensure PAM password complexity module is enabled in system-auth - Check
      the proper remediation for the system
    block:

    - name: Ensure PAM password complexity module is enabled in system-auth - Define
        the PAM file to be edited as a local fact
      ansible.builtin.set_fact:
        pam_file_path: /etc/pam.d/system-auth

    - name: Ensure PAM password complexity module is enabled in system-auth - Check
        if system relies on authselect tool
      ansible.builtin.stat:
        path: /usr/bin/authselect
      register: result_authselect_present

    - name: Ensure PAM password complexity module is enabled in system-auth - Ensure
        authselect custom profile is used if authselect is present
      block:

      - name: Ensure PAM password complexity module is enabled in system-auth - Check
          integrity of authselect current profile
        ansible.builtin.command:
          cmd: authselect check
        register: result_authselect_check_cmd
        changed_when: false
        check_mode: false
        failed_when: false

      - name: Ensure PAM password complexity module is enabled in system-auth - Informative
          message based on the authselect integrity check result
        ansible.builtin.assert:
          that:
          - ansible_check_mode or result_authselect_check_cmd.rc == 0
          fail_msg:
          - authselect integrity check failed. Remediation aborted!
          - This remediation could not be applied because an authselect profile was
            not selected or the selected profile is not intact.
          - It is not recommended to manually edit the PAM files when authselect tool
            is available.
          - In cases where the default authselect profile does not cover a specific
            demand, a custom authselect profile is recommended.
          success_msg:
          - authselect integrity check passed

      - name: Ensure PAM password complexity module is enabled in system-auth - Get
          authselect current profile
        ansible.builtin.shell:
          cmd: authselect current -r | awk '{ print $1 }'
        register: result_authselect_profile
        changed_when: false
        when:
        - result_authselect_check_cmd is success

      - name: Ensure PAM password complexity module is enabled in system-auth - Define
          the current authselect profile as a local fact
        ansible.builtin.set_fact:
          authselect_current_profile: '{{ result_authselect_profile.stdout }}'
          authselect_custom_profile: '{{ result_authselect_profile.stdout }}'
        when:
        - result_authselect_profile is not skipped
        - result_authselect_profile.stdout is match("custom/")

      - name: Ensure PAM password complexity module is enabled in system-auth - Define
          the new authselect custom profile as a local fact
        ansible.builtin.set_fact:
          authselect_current_profile: '{{ result_authselect_profile.stdout }}'
          authselect_custom_profile: custom/hardening
        when:
        - result_authselect_profile is not skipped
        - result_authselect_profile.stdout is not match("custom/")

      - name: Ensure PAM password complexity module is enabled in system-auth - Get
          authselect current features to also enable them in the custom profile
        ansible.builtin.shell:
          cmd: authselect current | tail -n+3 | awk '{ print $2 }'
        register: result_authselect_features
        changed_when: false
        check_mode: false
        when:
        - result_authselect_profile is not skipped
        - authselect_current_profile is not match("custom/")

      - name: Ensure PAM password complexity module is enabled in system-auth - Check
          if any custom profile with the same name was already created
        ansible.builtin.stat:
          path: /etc/authselect/{{ authselect_custom_profile }}
        register: result_authselect_custom_profile_present
        changed_when: false
        when:
        - result_authselect_profile is not skipped
        - authselect_current_profile is not match("custom/")

      - name: Ensure PAM password complexity module is enabled in system-auth - Create
          an authselect custom profile based on the current profile
        ansible.builtin.command:
          cmd: authselect create-profile hardening -b {{ authselect_current_profile
            }}
        when:
        - result_authselect_profile is not skipped
        - result_authselect_check_cmd is success
        - authselect_current_profile is not match("^(custom/|local)")
        - not result_authselect_custom_profile_present.stat.exists

      - name: Ensure PAM password complexity module is enabled in system-auth - Create
          an authselect custom profile based on sssd profile
        ansible.builtin.command:
          cmd: authselect create-profile hardening -b sssd
        when:
        - result_authselect_profile is not skipped
        - result_authselect_check_cmd is success
        - authselect_current_profile is match("local")
        - not result_authselect_custom_profile_present.stat.exists

      - name: Ensure PAM password complexity module is enabled in system-auth - Ensure
          authselect changes are applied
        ansible.builtin.command:
          cmd: authselect apply-changes -b --backup=before-hardening-custom-profile
        when:
        - result_authselect_check_cmd is success
        - result_authselect_profile is not skipped
        - authselect_current_profile is not match("custom/")
        - authselect_custom_profile is not match(authselect_current_profile)

      - name: Ensure PAM password complexity module is enabled in system-auth - Ensure
          the authselect custom profile is selected
        ansible.builtin.command:
          cmd: authselect select {{ authselect_custom_profile }}
        register: result_pam_authselect_select_profile
        when:
        - result_authselect_check_cmd is success
        - result_authselect_profile is not skipped
        - authselect_current_profile is not match("custom/")
        - authselect_custom_profile is not match(authselect_current_profile)

      - name: Ensure PAM password complexity module is enabled in system-auth - Restore
          the authselect features in the custom profile
        ansible.builtin.command:
          cmd: authselect enable-feature {{ item }}
        loop: '{{ result_authselect_features.stdout_lines }}'
        register: result_pam_authselect_restore_features
        when:
        - result_authselect_profile is not skipped
        - result_authselect_features is not skipped
        - result_pam_authselect_select_profile is not skipped

      - name: Ensure PAM password complexity module is enabled in system-auth - Ensure
          authselect changes are applied
        ansible.builtin.command:
          cmd: authselect apply-changes -b --backup=after-hardening-custom-profile
        when:
        - result_authselect_check_cmd is success
        - result_authselect_profile is not skipped
        - result_pam_authselect_restore_features is not skipped

      - name: Ensure PAM password complexity module is enabled in system-auth - Change
          the PAM file to be edited according to the custom authselect profile
        ansible.builtin.set_fact:
          pam_file_path: /etc/authselect/{{ authselect_custom_profile }}/{{ pam_file_path
            | basename }}
        when:
        - authselect_custom_profile is defined
      when:
      - result_authselect_present.stat.exists

    - name: Ensure PAM password complexity module is enabled in system-auth - Define
        a fact for control already filtered in case filters are used
      ansible.builtin.set_fact:
        pam_module_control: requisite

    - name: Ensure PAM password complexity module is enabled in system-auth - Check
        if expected PAM module line is present in {{ pam_file_path }}
      ansible.builtin.lineinfile:
        path: '{{ pam_file_path }}'
        regexp: ^\s*password\s+{{ pam_module_control | regex_escape() }}\s+pam_pwquality.so\s*.*
        state: absent
      check_mode: true
      changed_when: false
      register: result_pam_line_present

    - name: Ensure PAM password complexity module is enabled in system-auth - Include
        or update the PAM module line in {{ pam_file_path }}
      block:

      - name: Ensure PAM password complexity module is enabled in system-auth - Check
          if required PAM module line is present in {{ pam_file_path }} with different
          control
        ansible.builtin.lineinfile:
          path: '{{ pam_file_path }}'
          regexp: ^\s*password\s+.*\s+pam_pwquality.so\s*
          state: absent
        check_mode: true
        changed_when: false
        register: result_pam_line_other_control_present

      - name: Ensure PAM password complexity module is enabled in system-auth - Ensure
          the correct control for the required PAM module line in {{ pam_file_path
          }}
        ansible.builtin.replace:
          dest: '{{ pam_file_path }}'
          regexp: ^(\s*password\s+).*(\bpam_pwquality.so.*)
          replace: \1{{ pam_module_control }} \2
        register: result_pam_module_edit
        when:
        - result_pam_line_other_control_present.found == 1

      - name: Ensure PAM password complexity module is enabled in system-auth - Ensure
          the required PAM module line is included in {{ pam_file_path }}
        ansible.builtin.lineinfile:
          dest: '{{ pam_file_path }}'
          insertafter: ^account.*required.*pam_permit\.so
          line: password    {{ pam_module_control }}    pam_pwquality.so
        register: result_pam_module_add
        when:
        - result_pam_line_other_control_present.found == 0 or result_pam_line_other_control_present.found
          > 1

      - name: Ensure PAM password complexity module is enabled in system-auth - Ensure
          authselect changes are applied
        ansible.builtin.command:
          cmd: authselect apply-changes -b
        when:
        - result_authselect_present is defined
        - result_authselect_present.stat.exists
        - |-
          (result_pam_module_add is defined and result_pam_module_add.changed)
           or (result_pam_module_edit is defined and result_pam_module_edit.changed)
      when:
      - result_pam_line_present.found is defined
      - result_pam_line_present.found == 0

    - name: Ensure PAM password complexity module is enabled in system-auth - Ensure
        authselect changes are applied
      ansible.builtin.command:
        cmd: authselect apply-changes -b
      when:
      - result_authselect_present.stat.exists
      - |-
        (result_pam_accounts_password_pam_pwquality_system_auth_add is defined and result_pam_accounts_password_pam_pwquality_system_auth_add.changed)
         or (result_pam_accounts_password_pam_pwquality_system_auth_edit is defined and result_pam_accounts_password_pam_pwquality_system_auth_edit.changed)
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - '"libpwquality" in ansible_facts.packages'
    - result_pam_auth_file_present.stat.exists
    tags:
    - DISA-STIG-OL09-00-001000
    - accounts_password_pam_pwquality_system_auth
    - configure_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - no_reboot_needed

  - name: Ensure PAM Enforces Password Requirements - Minimum Uppercase Characters
      - Find pwquality.conf.d files
    ansible.builtin.find:
      paths: /etc/security/pwquality.conf.d/
      patterns: '*.conf'
    register: pwquality_conf_d_files
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - '"libpwquality" in ansible_facts.packages'
    tags:
    - DISA-STIG-OL09-00-001005
    - NIST-800-53-CM-6(a)
    - NIST-800-53-IA-5(1)(a)
    - NIST-800-53-IA-5(4)
    - NIST-800-53-IA-5(c)
    - PCI-DSS-Req-8.2.3
    - accounts_password_pam_ucredit
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Ensure PAM Enforces Password Requirements - Minimum Uppercase Characters
      - Ensure ucredit is not set in pwquality.conf.d
    ansible.builtin.lineinfile:
      path: '{{ item.path }}'
      regexp: ^\s*\bucredit\b.*
      state: absent
    with_items: '{{ pwquality_conf_d_files.files }}'
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - '"libpwquality" in ansible_facts.packages'
    tags:
    - DISA-STIG-OL09-00-001005
    - NIST-800-53-CM-6(a)
    - NIST-800-53-IA-5(1)(a)
    - NIST-800-53-IA-5(4)
    - NIST-800-53-IA-5(c)
    - PCI-DSS-Req-8.2.3
    - accounts_password_pam_ucredit
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Ensure PAM Enforces Password Requirements - Minimum Uppercase Characters
      - Check if /etc/pam.d/system-auth file is present
    ansible.builtin.stat:
      path: /etc/pam.d/system-auth
    register: result_pam_auth_file_present
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - '"libpwquality" in ansible_facts.packages'
    tags:
    - DISA-STIG-OL09-00-001005
    - NIST-800-53-CM-6(a)
    - NIST-800-53-IA-5(1)(a)
    - NIST-800-53-IA-5(4)
    - NIST-800-53-IA-5(c)
    - PCI-DSS-Req-8.2.3
    - accounts_password_pam_ucredit
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Ensure PAM Enforces Password Requirements - Minimum Uppercase Characters
      - Check the proper remediation for the system
    block:

    - name: Ensure PAM Enforces Password Requirements - Minimum Uppercase Characters
        - Define the PAM file to be edited as a local fact
      ansible.builtin.set_fact:
        pam_file_path: /etc/pam.d/system-auth

    - name: Ensure PAM Enforces Password Requirements - Minimum Uppercase Characters
        - Check if system relies on authselect tool
      ansible.builtin.stat:
        path: /usr/bin/authselect
      register: result_authselect_present

    - name: Ensure PAM Enforces Password Requirements - Minimum Uppercase Characters
        - Ensure authselect custom profile is used if authselect is present
      block:

      - name: Ensure PAM Enforces Password Requirements - Minimum Uppercase Characters
          - Check integrity of authselect current profile
        ansible.builtin.command:
          cmd: authselect check
        register: result_authselect_check_cmd
        changed_when: false
        check_mode: false
        failed_when: false

      - name: Ensure PAM Enforces Password Requirements - Minimum Uppercase Characters
          - Informative message based on the authselect integrity check result
        ansible.builtin.assert:
          that:
          - ansible_check_mode or result_authselect_check_cmd.rc == 0
          fail_msg:
          - authselect integrity check failed. Remediation aborted!
          - This remediation could not be applied because an authselect profile was
            not selected or the selected profile is not intact.
          - It is not recommended to manually edit the PAM files when authselect tool
            is available.
          - In cases where the default authselect profile does not cover a specific
            demand, a custom authselect profile is recommended.
          success_msg:
          - authselect integrity check passed

      - name: Ensure PAM Enforces Password Requirements - Minimum Uppercase Characters
          - Get authselect current profile
        ansible.builtin.shell:
          cmd: authselect current -r | awk '{ print $1 }'
        register: result_authselect_profile
        changed_when: false
        when:
        - result_authselect_check_cmd is success

      - name: Ensure PAM Enforces Password Requirements - Minimum Uppercase Characters
          - Define the current authselect profile as a local fact
        ansible.builtin.set_fact:
          authselect_current_profile: '{{ result_authselect_profile.stdout }}'
          authselect_custom_profile: '{{ result_authselect_profile.stdout }}'
        when:
        - result_authselect_profile is not skipped
        - result_authselect_profile.stdout is match("custom/")

      - name: Ensure PAM Enforces Password Requirements - Minimum Uppercase Characters
          - Define the new authselect custom profile as a local fact
        ansible.builtin.set_fact:
          authselect_current_profile: '{{ result_authselect_profile.stdout }}'
          authselect_custom_profile: custom/hardening
        when:
        - result_authselect_profile is not skipped
        - result_authselect_profile.stdout is not match("custom/")

      - name: Ensure PAM Enforces Password Requirements - Minimum Uppercase Characters
          - Get authselect current features to also enable them in the custom profile
        ansible.builtin.shell:
          cmd: authselect current | tail -n+3 | awk '{ print $2 }'
        register: result_authselect_features
        changed_when: false
        check_mode: false
        when:
        - result_authselect_profile is not skipped
        - authselect_current_profile is not match("custom/")

      - name: Ensure PAM Enforces Password Requirements - Minimum Uppercase Characters
          - Check if any custom profile with the same name was already created
        ansible.builtin.stat:
          path: /etc/authselect/{{ authselect_custom_profile }}
        register: result_authselect_custom_profile_present
        changed_when: false
        when:
        - result_authselect_profile is not skipped
        - authselect_current_profile is not match("custom/")

      - name: Ensure PAM Enforces Password Requirements - Minimum Uppercase Characters
          - Create an authselect custom profile based on the current profile
        ansible.builtin.command:
          cmd: authselect create-profile hardening -b {{ authselect_current_profile
            }}
        when:
        - result_authselect_profile is not skipped
        - result_authselect_check_cmd is success
        - authselect_current_profile is not match("^(custom/|local)")
        - not result_authselect_custom_profile_present.stat.exists

      - name: Ensure PAM Enforces Password Requirements - Minimum Uppercase Characters
          - Create an authselect custom profile based on sssd profile
        ansible.builtin.command:
          cmd: authselect create-profile hardening -b sssd
        when:
        - result_authselect_profile is not skipped
        - result_authselect_check_cmd is success
        - authselect_current_profile is match("local")
        - not result_authselect_custom_profile_present.stat.exists

      - name: Ensure PAM Enforces Password Requirements - Minimum Uppercase Characters
          - Ensure authselect changes are applied
        ansible.builtin.command:
          cmd: authselect apply-changes -b --backup=before-hardening-custom-profile
        when:
        - result_authselect_check_cmd is success
        - result_authselect_profile is not skipped
        - authselect_current_profile is not match("custom/")
        - authselect_custom_profile is not match(authselect_current_profile)

      - name: Ensure PAM Enforces Password Requirements - Minimum Uppercase Characters
          - Ensure the authselect custom profile is selected
        ansible.builtin.command:
          cmd: authselect select {{ authselect_custom_profile }}
        register: result_pam_authselect_select_profile
        when:
        - result_authselect_check_cmd is success
        - result_authselect_profile is not skipped
        - authselect_current_profile is not match("custom/")
        - authselect_custom_profile is not match(authselect_current_profile)

      - name: Ensure PAM Enforces Password Requirements - Minimum Uppercase Characters
          - Restore the authselect features in the custom profile
        ansible.builtin.command:
          cmd: authselect enable-feature {{ item }}
        loop: '{{ result_authselect_features.stdout_lines }}'
        register: result_pam_authselect_restore_features
        when:
        - result_authselect_profile is not skipped
        - result_authselect_features is not skipped
        - result_pam_authselect_select_profile is not skipped

      - name: Ensure PAM Enforces Password Requirements - Minimum Uppercase Characters
          - Ensure authselect changes are applied
        ansible.builtin.command:
          cmd: authselect apply-changes -b --backup=after-hardening-custom-profile
        when:
        - result_authselect_check_cmd is success
        - result_authselect_profile is not skipped
        - result_pam_authselect_restore_features is not skipped

      - name: Ensure PAM Enforces Password Requirements - Minimum Uppercase Characters
          - Change the PAM file to be edited according to the custom authselect profile
        ansible.builtin.set_fact:
          pam_file_path: /etc/authselect/{{ authselect_custom_profile }}/{{ pam_file_path
            | basename }}
        when:
        - authselect_custom_profile is defined
      when:
      - result_authselect_present.stat.exists

    - name: Ensure PAM Enforces Password Requirements - Minimum Uppercase Characters
        - Define a fact for control already filtered in case filters are used
      ansible.builtin.set_fact:
        pam_module_control: ''

    - name: Ensure PAM Enforces Password Requirements - Minimum Uppercase Characters
        - Check if {{ pam_file_path }} file is present
      ansible.builtin.stat:
        path: '{{ pam_file_path }}'
      register: result_pam_file_present

    - name: Ensure PAM Enforces Password Requirements - Minimum Uppercase Characters
        - Ensure the "ucredit" option from "pam_pwquality.so" is not present in {{
        pam_file_path }}
      ansible.builtin.replace:
        dest: '{{ pam_file_path }}'
        regexp: (.*password.*pam_pwquality.so.*)\bucredit\b=?[0-9a-zA-Z]*(.*)
        replace: \1\2
      register: result_pam_option_removal
      when:
      - result_pam_file_present.stat.exists

    - name: Ensure PAM Enforces Password Requirements - Minimum Uppercase Characters
        - Ensure authselect changes are applied
      ansible.builtin.command:
        cmd: authselect apply-changes -b
      when:
      - result_authselect_present.stat.exists
      - result_pam_option_removal is changed
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - '"libpwquality" in ansible_facts.packages'
    - result_pam_auth_file_present.stat.exists
    tags:
    - DISA-STIG-OL09-00-001005
    - NIST-800-53-CM-6(a)
    - NIST-800-53-IA-5(1)(a)
    - NIST-800-53-IA-5(4)
    - NIST-800-53-IA-5(c)
    - PCI-DSS-Req-8.2.3
    - accounts_password_pam_ucredit
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Ensure PAM Enforces Password Requirements - Minimum Uppercase Characters
      - Check if /etc/pam.d/password-auth file is present
    ansible.builtin.stat:
      path: /etc/pam.d/password-auth
    register: result_pam_password_auth_file_present
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - '"libpwquality" in ansible_facts.packages'
    tags:
    - DISA-STIG-OL09-00-001005
    - NIST-800-53-CM-6(a)
    - NIST-800-53-IA-5(1)(a)
    - NIST-800-53-IA-5(4)
    - NIST-800-53-IA-5(c)
    - PCI-DSS-Req-8.2.3
    - accounts_password_pam_ucredit
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Ensure PAM Enforces Password Requirements - Minimum Uppercase Characters
      - Check the proper remediation for the system
    block:

    - name: Ensure PAM Enforces Password Requirements - Minimum Uppercase Characters
        - Define the PAM file to be edited as a local fact
      ansible.builtin.set_fact:
        pam_file_path: /etc/pam.d/password-auth

    - name: Ensure PAM Enforces Password Requirements - Minimum Uppercase Characters
        - Check if system relies on authselect tool
      ansible.builtin.stat:
        path: /usr/bin/authselect
      register: result_authselect_present

    - name: Ensure PAM Enforces Password Requirements - Minimum Uppercase Characters
        - Ensure authselect custom profile is used if authselect is present
      block:

      - name: Ensure PAM Enforces Password Requirements - Minimum Uppercase Characters
          - Check integrity of authselect current profile
        ansible.builtin.command:
          cmd: authselect check
        register: result_authselect_check_cmd
        changed_when: false
        check_mode: false
        failed_when: false

      - name: Ensure PAM Enforces Password Requirements - Minimum Uppercase Characters
          - Informative message based on the authselect integrity check result
        ansible.builtin.assert:
          that:
          - ansible_check_mode or result_authselect_check_cmd.rc == 0
          fail_msg:
          - authselect integrity check failed. Remediation aborted!
          - This remediation could not be applied because an authselect profile was
            not selected or the selected profile is not intact.
          - It is not recommended to manually edit the PAM files when authselect tool
            is available.
          - In cases where the default authselect profile does not cover a specific
            demand, a custom authselect profile is recommended.
          success_msg:
          - authselect integrity check passed

      - name: Ensure PAM Enforces Password Requirements - Minimum Uppercase Characters
          - Get authselect current profile
        ansible.builtin.shell:
          cmd: authselect current -r | awk '{ print $1 }'
        register: result_authselect_profile
        changed_when: false
        when:
        - result_authselect_check_cmd is success

      - name: Ensure PAM Enforces Password Requirements - Minimum Uppercase Characters
          - Define the current authselect profile as a local fact
        ansible.builtin.set_fact:
          authselect_current_profile: '{{ result_authselect_profile.stdout }}'
          authselect_custom_profile: '{{ result_authselect_profile.stdout }}'
        when:
        - result_authselect_profile is not skipped
        - result_authselect_profile.stdout is match("custom/")

      - name: Ensure PAM Enforces Password Requirements - Minimum Uppercase Characters
          - Define the new authselect custom profile as a local fact
        ansible.builtin.set_fact:
          authselect_current_profile: '{{ result_authselect_profile.stdout }}'
          authselect_custom_profile: custom/hardening
        when:
        - result_authselect_profile is not skipped
        - result_authselect_profile.stdout is not match("custom/")

      - name: Ensure PAM Enforces Password Requirements - Minimum Uppercase Characters
          - Get authselect current features to also enable them in the custom profile
        ansible.builtin.shell:
          cmd: authselect current | tail -n+3 | awk '{ print $2 }'
        register: result_authselect_features
        changed_when: false
        check_mode: false
        when:
        - result_authselect_profile is not skipped
        - authselect_current_profile is not match("custom/")

      - name: Ensure PAM Enforces Password Requirements - Minimum Uppercase Characters
          - Check if any custom profile with the same name was already created
        ansible.builtin.stat:
          path: /etc/authselect/{{ authselect_custom_profile }}
        register: result_authselect_custom_profile_present
        changed_when: false
        when:
        - result_authselect_profile is not skipped
        - authselect_current_profile is not match("custom/")

      - name: Ensure PAM Enforces Password Requirements - Minimum Uppercase Characters
          - Create an authselect custom profile based on the current profile
        ansible.builtin.command:
          cmd: authselect create-profile hardening -b {{ authselect_current_profile
            }}
        when:
        - result_authselect_profile is not skipped
        - result_authselect_check_cmd is success
        - authselect_current_profile is not match("^(custom/|local)")
        - not result_authselect_custom_profile_present.stat.exists

      - name: Ensure PAM Enforces Password Requirements - Minimum Uppercase Characters
          - Create an authselect custom profile based on sssd profile
        ansible.builtin.command:
          cmd: authselect create-profile hardening -b sssd
        when:
        - result_authselect_profile is not skipped
        - result_authselect_check_cmd is success
        - authselect_current_profile is match("local")
        - not result_authselect_custom_profile_present.stat.exists

      - name: Ensure PAM Enforces Password Requirements - Minimum Uppercase Characters
          - Ensure authselect changes are applied
        ansible.builtin.command:
          cmd: authselect apply-changes -b --backup=before-hardening-custom-profile
        when:
        - result_authselect_check_cmd is success
        - result_authselect_profile is not skipped
        - authselect_current_profile is not match("custom/")
        - authselect_custom_profile is not match(authselect_current_profile)

      - name: Ensure PAM Enforces Password Requirements - Minimum Uppercase Characters
          - Ensure the authselect custom profile is selected
        ansible.builtin.command:
          cmd: authselect select {{ authselect_custom_profile }}
        register: result_pam_authselect_select_profile
        when:
        - result_authselect_check_cmd is success
        - result_authselect_profile is not skipped
        - authselect_current_profile is not match("custom/")
        - authselect_custom_profile is not match(authselect_current_profile)

      - name: Ensure PAM Enforces Password Requirements - Minimum Uppercase Characters
          - Restore the authselect features in the custom profile
        ansible.builtin.command:
          cmd: authselect enable-feature {{ item }}
        loop: '{{ result_authselect_features.stdout_lines }}'
        register: result_pam_authselect_restore_features
        when:
        - result_authselect_profile is not skipped
        - result_authselect_features is not skipped
        - result_pam_authselect_select_profile is not skipped

      - name: Ensure PAM Enforces Password Requirements - Minimum Uppercase Characters
          - Ensure authselect changes are applied
        ansible.builtin.command:
          cmd: authselect apply-changes -b --backup=after-hardening-custom-profile
        when:
        - result_authselect_check_cmd is success
        - result_authselect_profile is not skipped
        - result_pam_authselect_restore_features is not skipped

      - name: Ensure PAM Enforces Password Requirements - Minimum Uppercase Characters
          - Change the PAM file to be edited according to the custom authselect profile
        ansible.builtin.set_fact:
          pam_file_path: /etc/authselect/{{ authselect_custom_profile }}/{{ pam_file_path
            | basename }}
        when:
        - authselect_custom_profile is defined
      when:
      - result_authselect_present.stat.exists

    - name: Ensure PAM Enforces Password Requirements - Minimum Uppercase Characters
        - Define a fact for control already filtered in case filters are used
      ansible.builtin.set_fact:
        pam_module_control: ''

    - name: Ensure PAM Enforces Password Requirements - Minimum Uppercase Characters
        - Check if {{ pam_file_path }} file is present
      ansible.builtin.stat:
        path: '{{ pam_file_path }}'
      register: result_pam_file_present

    - name: Ensure PAM Enforces Password Requirements - Minimum Uppercase Characters
        - Ensure the "ucredit" option from "pam_pwquality.so" is not present in {{
        pam_file_path }}
      ansible.builtin.replace:
        dest: '{{ pam_file_path }}'
        regexp: (.*password.*pam_pwquality.so.*)\bucredit\b=?[0-9a-zA-Z]*(.*)
        replace: \1\2
      register: result_pam_option_removal
      when:
      - result_pam_file_present.stat.exists

    - name: Ensure PAM Enforces Password Requirements - Minimum Uppercase Characters
        - Ensure authselect changes are applied
      ansible.builtin.command:
        cmd: authselect apply-changes -b
      when:
      - result_authselect_present.stat.exists
      - result_pam_option_removal is changed
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - '"libpwquality" in ansible_facts.packages'
    - result_pam_password_auth_file_present.stat.exists
    tags:
    - DISA-STIG-OL09-00-001005
    - NIST-800-53-CM-6(a)
    - NIST-800-53-IA-5(1)(a)
    - NIST-800-53-IA-5(4)
    - NIST-800-53-IA-5(c)
    - PCI-DSS-Req-8.2.3
    - accounts_password_pam_ucredit
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Ensure PAM Enforces Password Requirements - Minimum Uppercase Characters
      - Ensure PAM variable ucredit is set accordingly
    ansible.builtin.lineinfile:
      create: true
      dest: /etc/security/pwquality.conf
      regexp: ^#?\s*ucredit
      line: ucredit = {{ var_password_pam_ucredit }}
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - '"libpwquality" in ansible_facts.packages'
    tags:
    - DISA-STIG-OL09-00-001005
    - NIST-800-53-CM-6(a)
    - NIST-800-53-IA-5(1)(a)
    - NIST-800-53-IA-5(4)
    - NIST-800-53-IA-5(c)
    - PCI-DSS-Req-8.2.3
    - accounts_password_pam_ucredit
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Set Password Hashing Algorithm in /etc/libuser.conf - Set Password Hashing
      Algorithm in /etc/libuser.conf
    ansible.builtin.lineinfile:
      dest: /etc/libuser.conf
      insertafter: ^\s*\[defaults]
      regexp: ^#?crypt_style
      line: crypt_style = {{ var_password_hashing_algorithm_pam }}
      state: present
      create: true
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - '"libuser" in ansible_facts.packages'
    tags:
    - CJIS-5.6.2.2
    - DISA-STIG-OL09-00-001050
    - NIST-800-171-3.13.11
    - NIST-800-53-CM-6(a)
    - NIST-800-53-IA-5(1)(c)
    - NIST-800-53-IA-5(c)
    - PCI-DSS-Req-8.2.1
    - PCI-DSSv4-8.3
    - PCI-DSSv4-8.3.2
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy
    - set_password_hashing_algorithm_libuserconf

  - name: Set Password Hashing Algorithm in /etc/login.defs
    ansible.builtin.lineinfile:
      dest: /etc/login.defs
      regexp: ^#?ENCRYPT_METHOD
      line: ENCRYPT_METHOD {{ var_password_hashing_algorithm.split('|')[0] }}
      state: present
      create: true
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - '"shadow-utils" in ansible_facts.packages'
    tags:
    - CJIS-5.6.2.2
    - DISA-STIG-OL09-00-001055
    - NIST-800-171-3.13.11
    - NIST-800-53-CM-6(a)
    - NIST-800-53-IA-5(1)(c)
    - NIST-800-53-IA-5(c)
    - PCI-DSS-Req-8.2.1
    - PCI-DSSv4-8.3
    - PCI-DSSv4-8.3.2
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy
    - set_password_hashing_algorithm_logindefs

  - name: Set PAM Password Hashing Algorithm - password-auth - Check if /etc/pam.d/password-auth
      file is present
    ansible.builtin.stat:
      path: /etc/pam.d/password-auth
    register: result_pam_password_auth_file_present
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - '"pam" in ansible_facts.packages'
    tags:
    - CJIS-5.6.2.2
    - DISA-STIG-OL09-00-001060
    - NIST-800-171-3.13.11
    - NIST-800-53-CM-6(a)
    - NIST-800-53-IA-5(1)(c)
    - NIST-800-53-IA-5(c)
    - PCI-DSS-Req-8.2.1
    - configure_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - no_reboot_needed
    - set_password_hashing_algorithm_passwordauth

  - name: Set PAM Password Hashing Algorithm - password-auth - Check the proper remediation
      for the system
    block:

    - name: Set PAM Password Hashing Algorithm - password-auth - Define the PAM file
        to be edited as a local fact
      ansible.builtin.set_fact:
        pam_file_path: /etc/pam.d/password-auth

    - name: Set PAM Password Hashing Algorithm - password-auth - Check if system relies
        on authselect tool
      ansible.builtin.stat:
        path: /usr/bin/authselect
      register: result_authselect_present

    - name: Set PAM Password Hashing Algorithm - password-auth - Ensure authselect
        custom profile is used if authselect is present
      block:

      - name: Set PAM Password Hashing Algorithm - password-auth - Check integrity
          of authselect current profile
        ansible.builtin.command:
          cmd: authselect check
        register: result_authselect_check_cmd
        changed_when: false
        check_mode: false
        failed_when: false

      - name: Set PAM Password Hashing Algorithm - password-auth - Informative message
          based on the authselect integrity check result
        ansible.builtin.assert:
          that:
          - ansible_check_mode or result_authselect_check_cmd.rc == 0
          fail_msg:
          - authselect integrity check failed. Remediation aborted!
          - This remediation could not be applied because an authselect profile was
            not selected or the selected profile is not intact.
          - It is not recommended to manually edit the PAM files when authselect tool
            is available.
          - In cases where the default authselect profile does not cover a specific
            demand, a custom authselect profile is recommended.
          success_msg:
          - authselect integrity check passed

      - name: Set PAM Password Hashing Algorithm - password-auth - Get authselect
          current profile
        ansible.builtin.shell:
          cmd: authselect current -r | awk '{ print $1 }'
        register: result_authselect_profile
        changed_when: false
        when:
        - result_authselect_check_cmd is success

      - name: Set PAM Password Hashing Algorithm - password-auth - Define the current
          authselect profile as a local fact
        ansible.builtin.set_fact:
          authselect_current_profile: '{{ result_authselect_profile.stdout }}'
          authselect_custom_profile: '{{ result_authselect_profile.stdout }}'
        when:
        - result_authselect_profile is not skipped
        - result_authselect_profile.stdout is match("custom/")

      - name: Set PAM Password Hashing Algorithm - password-auth - Define the new
          authselect custom profile as a local fact
        ansible.builtin.set_fact:
          authselect_current_profile: '{{ result_authselect_profile.stdout }}'
          authselect_custom_profile: custom/hardening
        when:
        - result_authselect_profile is not skipped
        - result_authselect_profile.stdout is not match("custom/")

      - name: Set PAM Password Hashing Algorithm - password-auth - Get authselect
          current features to also enable them in the custom profile
        ansible.builtin.shell:
          cmd: authselect current | tail -n+3 | awk '{ print $2 }'
        register: result_authselect_features
        changed_when: false
        check_mode: false
        when:
        - result_authselect_profile is not skipped
        - authselect_current_profile is not match("custom/")

      - name: Set PAM Password Hashing Algorithm - password-auth - Check if any custom
          profile with the same name was already created
        ansible.builtin.stat:
          path: /etc/authselect/{{ authselect_custom_profile }}
        register: result_authselect_custom_profile_present
        changed_when: false
        when:
        - result_authselect_profile is not skipped
        - authselect_current_profile is not match("custom/")

      - name: Set PAM Password Hashing Algorithm - password-auth - Create an authselect
          custom profile based on the current profile
        ansible.builtin.command:
          cmd: authselect create-profile hardening -b {{ authselect_current_profile
            }}
        when:
        - result_authselect_profile is not skipped
        - result_authselect_check_cmd is success
        - authselect_current_profile is not match("^(custom/|local)")
        - not result_authselect_custom_profile_present.stat.exists

      - name: Set PAM Password Hashing Algorithm - password-auth - Create an authselect
          custom profile based on sssd profile
        ansible.builtin.command:
          cmd: authselect create-profile hardening -b sssd
        when:
        - result_authselect_profile is not skipped
        - result_authselect_check_cmd is success
        - authselect_current_profile is match("local")
        - not result_authselect_custom_profile_present.stat.exists

      - name: Set PAM Password Hashing Algorithm - password-auth - Ensure authselect
          changes are applied
        ansible.builtin.command:
          cmd: authselect apply-changes -b --backup=before-hardening-custom-profile
        when:
        - result_authselect_check_cmd is success
        - result_authselect_profile is not skipped
        - authselect_current_profile is not match("custom/")
        - authselect_custom_profile is not match(authselect_current_profile)

      - name: Set PAM Password Hashing Algorithm - password-auth - Ensure the authselect
          custom profile is selected
        ansible.builtin.command:
          cmd: authselect select {{ authselect_custom_profile }}
        register: result_pam_authselect_select_profile
        when:
        - result_authselect_check_cmd is success
        - result_authselect_profile is not skipped
        - authselect_current_profile is not match("custom/")
        - authselect_custom_profile is not match(authselect_current_profile)

      - name: Set PAM Password Hashing Algorithm - password-auth - Restore the authselect
          features in the custom profile
        ansible.builtin.command:
          cmd: authselect enable-feature {{ item }}
        loop: '{{ result_authselect_features.stdout_lines }}'
        register: result_pam_authselect_restore_features
        when:
        - result_authselect_profile is not skipped
        - result_authselect_features is not skipped
        - result_pam_authselect_select_profile is not skipped

      - name: Set PAM Password Hashing Algorithm - password-auth - Ensure authselect
          changes are applied
        ansible.builtin.command:
          cmd: authselect apply-changes -b --backup=after-hardening-custom-profile
        when:
        - result_authselect_check_cmd is success
        - result_authselect_profile is not skipped
        - result_pam_authselect_restore_features is not skipped

      - name: Set PAM Password Hashing Algorithm - password-auth - Change the PAM
          file to be edited according to the custom authselect profile
        ansible.builtin.set_fact:
          pam_file_path: /etc/authselect/{{ authselect_custom_profile }}/{{ pam_file_path
            | basename }}
        when:
        - authselect_custom_profile is defined
      when:
      - result_authselect_present.stat.exists

    - name: Set PAM Password Hashing Algorithm - password-auth - Define a fact for
        control already filtered in case filters are used
      ansible.builtin.set_fact:
        pam_module_control: sufficient

    - name: Set PAM Password Hashing Algorithm - password-auth - Check if expected
        PAM module line is present in {{ pam_file_path }}
      ansible.builtin.lineinfile:
        path: '{{ pam_file_path }}'
        regexp: ^\s*password\s+{{ pam_module_control | regex_escape() }}\s+pam_unix.so\s*.*
        state: absent
      check_mode: true
      changed_when: false
      register: result_pam_line_present

    - name: Set PAM Password Hashing Algorithm - password-auth - Include or update
        the PAM module line in {{ pam_file_path }}
      block:

      - name: Set PAM Password Hashing Algorithm - password-auth - Check if required
          PAM module line is present in {{ pam_file_path }} with different control
        ansible.builtin.lineinfile:
          path: '{{ pam_file_path }}'
          regexp: ^\s*password\s+.*\s+pam_unix.so\s*
          state: absent
        check_mode: true
        changed_when: false
        register: result_pam_line_other_control_present

      - name: Set PAM Password Hashing Algorithm - password-auth - Ensure the correct
          control for the required PAM module line in {{ pam_file_path }}
        ansible.builtin.replace:
          dest: '{{ pam_file_path }}'
          regexp: ^(\s*password\s+).*(\bpam_unix.so.*)
          replace: \1{{ pam_module_control }} \2
        register: result_pam_module_edit
        when:
        - result_pam_line_other_control_present.found == 1

      - name: Set PAM Password Hashing Algorithm - password-auth - Ensure the required
          PAM module line is included in {{ pam_file_path }}
        ansible.builtin.lineinfile:
          dest: '{{ pam_file_path }}'
          line: password    {{ pam_module_control }}    pam_unix.so
        register: result_pam_module_add
        when:
        - result_pam_line_other_control_present.found == 0 or result_pam_line_other_control_present.found
          > 1

      - name: Set PAM Password Hashing Algorithm - password-auth - Ensure authselect
          changes are applied
        ansible.builtin.command:
          cmd: authselect apply-changes -b
        when:
        - result_authselect_present is defined
        - result_authselect_present.stat.exists
        - |-
          (result_pam_module_add is defined and result_pam_module_add.changed)
           or (result_pam_module_edit is defined and result_pam_module_edit.changed)
      when:
      - result_pam_line_present.found is defined
      - result_pam_line_present.found == 0

    - name: Set PAM Password Hashing Algorithm - password-auth - Define a fact for
        control already filtered in case filters are used
      ansible.builtin.set_fact:
        pam_module_control: sufficient

    - name: Set PAM Password Hashing Algorithm - password-auth - Check if the required
        PAM module option is present in {{ pam_file_path }}
      ansible.builtin.lineinfile:
        path: '{{ pam_file_path }}'
        regexp: ^\s*password\s+{{ pam_module_control | regex_escape() }}\s+pam_unix.so\s*.*\s{{
          var_password_hashing_algorithm_pam.split("|")[0] }}\b
        state: absent
      check_mode: true
      changed_when: false
      register: result_pam_module_set_password_hashing_algorithm_passwordauth_option_present

    - name: Set PAM Password Hashing Algorithm - password-auth - Ensure the "{{ var_password_hashing_algorithm_pam.split("|")[0]
        }}" PAM option for "pam_unix.so" is included in {{ pam_file_path }}
      ansible.builtin.lineinfile:
        path: '{{ pam_file_path }}'
        backrefs: true
        regexp: ^(\s*password\s+{{ pam_module_control | regex_escape() }}\s+pam_unix.so.*)
        line: \1 {{ var_password_hashing_algorithm_pam.split("|")[0] }}
        state: present
      register: result_pam_set_password_hashing_algorithm_passwordauth_add
      when:
      - result_pam_module_set_password_hashing_algorithm_passwordauth_option_present.found
        is defined
      - result_pam_module_set_password_hashing_algorithm_passwordauth_option_present.found
        == 0

    - name: Set PAM Password Hashing Algorithm - password-auth - Ensure authselect
        changes are applied
      ansible.builtin.command:
        cmd: authselect apply-changes -b
      when:
      - result_authselect_present.stat.exists
      - |-
        (result_pam_set_password_hashing_algorithm_passwordauth_add is defined and result_pam_set_password_hashing_algorithm_passwordauth_add.changed)
         or (result_pam_set_password_hashing_algorithm_passwordauth_edit is defined and result_pam_set_password_hashing_algorithm_passwordauth_edit.changed)
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - '"pam" in ansible_facts.packages'
    - result_pam_password_auth_file_present.stat.exists
    tags:
    - CJIS-5.6.2.2
    - DISA-STIG-OL09-00-001060
    - NIST-800-171-3.13.11
    - NIST-800-53-CM-6(a)
    - NIST-800-53-IA-5(1)(c)
    - NIST-800-53-IA-5(c)
    - PCI-DSS-Req-8.2.1
    - configure_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - no_reboot_needed
    - set_password_hashing_algorithm_passwordauth

  - name: Set PAM Password Hashing Algorithm - password-auth - Check if /etc/pam.d/password-auth
      File is Present
    ansible.builtin.stat:
      path: /etc/pam.d/password-auth
    register: result_pam_password_auth_file_present
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - '"pam" in ansible_facts.packages'
    tags:
    - CJIS-5.6.2.2
    - DISA-STIG-OL09-00-001060
    - NIST-800-171-3.13.11
    - NIST-800-53-CM-6(a)
    - NIST-800-53-IA-5(1)(c)
    - NIST-800-53-IA-5(c)
    - PCI-DSS-Req-8.2.1
    - configure_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - no_reboot_needed
    - set_password_hashing_algorithm_passwordauth

  - name: Set PAM Password Hashing Algorithm - password-auth - Check The Proper Remediation
      For The System
    block:

    - name: Set PAM Password Hashing Algorithm - password-auth - Define the PAM file
        to be edited as a local fact
      ansible.builtin.set_fact:
        pam_file_path: /etc/pam.d/password-auth

    - name: Set PAM Password Hashing Algorithm - password-auth - Check if system relies
        on authselect tool
      ansible.builtin.stat:
        path: /usr/bin/authselect
      register: result_authselect_present

    - name: Set PAM Password Hashing Algorithm - password-auth - Ensure authselect
        custom profile is used if authselect is present
      block:

      - name: Set PAM Password Hashing Algorithm - password-auth - Check integrity
          of authselect current profile
        ansible.builtin.command:
          cmd: authselect check
        register: result_authselect_check_cmd
        changed_when: false
        check_mode: false
        failed_when: false

      - name: Set PAM Password Hashing Algorithm - password-auth - Informative message
          based on the authselect integrity check result
        ansible.builtin.assert:
          that:
          - ansible_check_mode or result_authselect_check_cmd.rc == 0
          fail_msg:
          - authselect integrity check failed. Remediation aborted!
          - This remediation could not be applied because an authselect profile was
            not selected or the selected profile is not intact.
          - It is not recommended to manually edit the PAM files when authselect tool
            is available.
          - In cases where the default authselect profile does not cover a specific
            demand, a custom authselect profile is recommended.
          success_msg:
          - authselect integrity check passed

      - name: Set PAM Password Hashing Algorithm - password-auth - Get authselect
          current profile
        ansible.builtin.shell:
          cmd: authselect current -r | awk '{ print $1 }'
        register: result_authselect_profile
        changed_when: false
        when:
        - result_authselect_check_cmd is success

      - name: Set PAM Password Hashing Algorithm - password-auth - Define the current
          authselect profile as a local fact
        ansible.builtin.set_fact:
          authselect_current_profile: '{{ result_authselect_profile.stdout }}'
          authselect_custom_profile: '{{ result_authselect_profile.stdout }}'
        when:
        - result_authselect_profile is not skipped
        - result_authselect_profile.stdout is match("custom/")

      - name: Set PAM Password Hashing Algorithm - password-auth - Define the new
          authselect custom profile as a local fact
        ansible.builtin.set_fact:
          authselect_current_profile: '{{ result_authselect_profile.stdout }}'
          authselect_custom_profile: custom/hardening
        when:
        - result_authselect_profile is not skipped
        - result_authselect_profile.stdout is not match("custom/")

      - name: Set PAM Password Hashing Algorithm - password-auth - Get authselect
          current features to also enable them in the custom profile
        ansible.builtin.shell:
          cmd: authselect current | tail -n+3 | awk '{ print $2 }'
        register: result_authselect_features
        changed_when: false
        check_mode: false
        when:
        - result_authselect_profile is not skipped
        - authselect_current_profile is not match("custom/")

      - name: Set PAM Password Hashing Algorithm - password-auth - Check if any custom
          profile with the same name was already created
        ansible.builtin.stat:
          path: /etc/authselect/{{ authselect_custom_profile }}
        register: result_authselect_custom_profile_present
        changed_when: false
        when:
        - result_authselect_profile is not skipped
        - authselect_current_profile is not match("custom/")

      - name: Set PAM Password Hashing Algorithm - password-auth - Create an authselect
          custom profile based on the current profile
        ansible.builtin.command:
          cmd: authselect create-profile hardening -b {{ authselect_current_profile
            }}
        when:
        - result_authselect_profile is not skipped
        - result_authselect_check_cmd is success
        - authselect_current_profile is not match("^(custom/|local)")
        - not result_authselect_custom_profile_present.stat.exists

      - name: Set PAM Password Hashing Algorithm - password-auth - Create an authselect
          custom profile based on sssd profile
        ansible.builtin.command:
          cmd: authselect create-profile hardening -b sssd
        when:
        - result_authselect_profile is not skipped
        - result_authselect_check_cmd is success
        - authselect_current_profile is match("local")
        - not result_authselect_custom_profile_present.stat.exists

      - name: Set PAM Password Hashing Algorithm - password-auth - Ensure authselect
          changes are applied
        ansible.builtin.command:
          cmd: authselect apply-changes -b --backup=before-hardening-custom-profile
        when:
        - result_authselect_check_cmd is success
        - result_authselect_profile is not skipped
        - authselect_current_profile is not match("custom/")
        - authselect_custom_profile is not match(authselect_current_profile)

      - name: Set PAM Password Hashing Algorithm - password-auth - Ensure the authselect
          custom profile is selected
        ansible.builtin.command:
          cmd: authselect select {{ authselect_custom_profile }}
        register: result_pam_authselect_select_profile
        when:
        - result_authselect_check_cmd is success
        - result_authselect_profile is not skipped
        - authselect_current_profile is not match("custom/")
        - authselect_custom_profile is not match(authselect_current_profile)

      - name: Set PAM Password Hashing Algorithm - password-auth - Restore the authselect
          features in the custom profile
        ansible.builtin.command:
          cmd: authselect enable-feature {{ item }}
        loop: '{{ result_authselect_features.stdout_lines }}'
        register: result_pam_authselect_restore_features
        when:
        - result_authselect_profile is not skipped
        - result_authselect_features is not skipped
        - result_pam_authselect_select_profile is not skipped

      - name: Set PAM Password Hashing Algorithm - password-auth - Ensure authselect
          changes are applied
        ansible.builtin.command:
          cmd: authselect apply-changes -b --backup=after-hardening-custom-profile
        when:
        - result_authselect_check_cmd is success
        - result_authselect_profile is not skipped
        - result_pam_authselect_restore_features is not skipped

      - name: Set PAM Password Hashing Algorithm - password-auth - Change the PAM
          file to be edited according to the custom authselect profile
        ansible.builtin.set_fact:
          pam_file_path: /etc/authselect/{{ authselect_custom_profile }}/{{ pam_file_path
            | basename }}
        when:
        - authselect_custom_profile is defined
      when:
      - result_authselect_present.stat.exists

    - name: Set PAM Password Hashing Algorithm - password-auth - Check if "{{ pam_file_path
        }}" File is Present
      ansible.builtin.stat:
        path: '{{ pam_file_path }}'
      register: pam_file_path_present

    - name: Set PAM Password Hashing Algorithm - password-auth - Ensure That Only
        the Correct Hashing Algorithm Option For pam_unix.so Is Used in {{ pam_file_path
        }}
      ansible.builtin.replace:
        dest: '{{ pam_file_path }}'
        regexp: (^\s*password.*pam_unix\.so.*)\b{{ item }}\b\s*(.*)
        replace: \1\2
      when:
      - item != var_password_hashing_algorithm_pam.split('|')[0]
      - pam_file_path_present.stat.exists
      loop:
      - sha512
      - yescrypt
      - gost_yescrypt
      - blowfish
      - sha256
      - md5
      - bigcrypt
      register: result_pam_hashing_options_removal

    - name: Set PAM Password Hashing Algorithm - password-auth - Ensure authselect
        changes are applied
      ansible.builtin.command:
        cmd: authselect apply-changes -b
      when:
      - result_authselect_present.stat.exists
      - result_pam_hashing_options_removal is changed
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - '"pam" in ansible_facts.packages'
    - result_pam_password_auth_file_present.stat.exists
    tags:
    - CJIS-5.6.2.2
    - DISA-STIG-OL09-00-001060
    - NIST-800-171-3.13.11
    - NIST-800-53-CM-6(a)
    - NIST-800-53-IA-5(1)(c)
    - NIST-800-53-IA-5(c)
    - PCI-DSS-Req-8.2.1
    - configure_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - no_reboot_needed
    - set_password_hashing_algorithm_passwordauth

  - name: Set Password Hashing Rounds in /etc/login.defs - extract contents of the
      file /etc/login.defs
    ansible.builtin.slurp:
      src: /etc/login.defs
    register: etc_login_defs
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-001075
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy
    - set_password_hashing_min_rounds_logindefs

  - name: Set Password Hashing Rounds in /etc/login.defs - extract the value of SHA_CRYPT_MIN_ROUNDS
      if present
    ansible.builtin.set_fact:
      etc_login_defs_sha_crypt_min_rounds: '{{ etc_login_defs[''content''] | b64decode
        | regex_search(''^\s*SHA_CRYPT_MIN_ROUNDS\s+(\d+)'', ''\1'', multiline=True)
        | default([], true) }}'
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-001075
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy
    - set_password_hashing_min_rounds_logindefs

  - name: Set Password Hashing Rounds in /etc/login.defs - extract the value of SHA_CRYPT_MAX_ROUNDS
      if present
    ansible.builtin.set_fact:
      etc_login_defs_sha_crypt_max_rounds: '{{ etc_login_defs[''content''] | b64decode
        | regex_search(''^\s*SHA_CRYPT_MAX_ROUNDS\s+(\d+)'', ''\1'', multiline=True)
        | default([], true) }}'
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-001075
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy
    - set_password_hashing_min_rounds_logindefs

  - name: Set Password Hashing Rounds in /etc/login.defs - Ensure SHA_CRYPT_MIN_ROUNDS
      has Minimum Value of 5000
    ansible.builtin.replace:
      path: /etc/login.defs
      regexp: (^\s*SHA_CRYPT_MIN_ROUNDS\s+)(?:\d+)(.*$)
      replace: \g<1>{{ var_password_hashing_min_rounds_login_defs }}\g<2>
      backup: false
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - etc_login_defs_sha_crypt_min_rounds is defined and etc_login_defs_sha_crypt_min_rounds
      | length > 0 and etc_login_defs_sha_crypt_min_rounds | first | int < var_password_hashing_min_rounds_login_defs
      | int
    tags:
    - DISA-STIG-OL09-00-001075
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy
    - set_password_hashing_min_rounds_logindefs

  - name: Set Password Hashing Rounds in /etc/login.defs - Ensure SHA_CRYPT_MAX_ROUNDS
      has Minimum Value of 5000
    ansible.builtin.replace:
      path: /etc/login.defs
      regexp: (^\s*SHA_CRYPT_MAX_ROUNDS\s+)(?:\d+)(.*$)
      replace: \g<1>{{ var_password_hashing_min_rounds_login_defs }}\g<2>
      backup: false
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - etc_login_defs_sha_crypt_max_rounds is defined and etc_login_defs_sha_crypt_max_rounds
      | length > 0 and etc_login_defs_sha_crypt_max_rounds | first | int < var_password_hashing_min_rounds_login_defs
      | int
    tags:
    - DISA-STIG-OL09-00-001075
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy
    - set_password_hashing_min_rounds_logindefs

  - name: Set Password Hashing Rounds in /etc/login.defs - SHA_CRYPT_MIN_ROUNDS add
      configuration if not found
    ansible.builtin.lineinfile:
      line: SHA_CRYPT_MIN_ROUNDS {{ var_password_hashing_min_rounds_login_defs }}
      path: /etc/login.defs
      state: present
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - etc_login_defs_sha_crypt_min_rounds | length == 0
    tags:
    - DISA-STIG-OL09-00-001075
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy
    - set_password_hashing_min_rounds_logindefs

  - name: Set Password Hashing Rounds in /etc/login.defs - SHA_CRYPT_MAX_ROUNDS add
      configuration if not found
    ansible.builtin.lineinfile:
      line: SHA_CRYPT_MAX_ROUNDS {{ var_password_hashing_min_rounds_login_defs }}
      path: /etc/login.defs
      state: present
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - etc_login_defs_sha_crypt_max_rounds | length == 0
    tags:
    - DISA-STIG-OL09-00-001075
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy
    - set_password_hashing_min_rounds_logindefs

  - name: Disable Ctrl-Alt-Del Burst Action
    ansible.builtin.lineinfile:
      dest: /etc/systemd/system.conf
      state: present
      regexp: ^CtrlAltDelBurstAction
      line: CtrlAltDelBurstAction=none
      create: true
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - '"systemd" in ansible_facts.packages'
    tags:
    - DISA-STIG-OL09-00-002412
    - NIST-800-171-3.4.5
    - NIST-800-53-AC-6(1)
    - NIST-800-53-CM-6(a)
    - NIST-800-53-CM-6(a)
    - disable_ctrlaltdel_burstaction
    - disable_strategy
    - high_severity
    - low_complexity
    - low_disruption
    - no_reboot_needed

  - name: Disable Ctrl-Alt-Del Reboot Activation
    ansible.builtin.systemd:
      name: ctrl-alt-del.target
      force: true
      masked: true
      state: stopped
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-002413
    - NIST-800-171-3.4.5
    - NIST-800-53-AC-6(1)
    - NIST-800-53-CM-6(a)
    - disable_ctrlaltdel_reboot
    - disable_strategy
    - high_severity
    - low_complexity
    - low_disruption
    - no_reboot_needed

  - name: Verify that Interactive Boot is Disabled - Verify GRUB_DISABLE_RECOVERY=true
    ansible.builtin.lineinfile:
      path: /etc/default/grub
      regexp: ^GRUB_DISABLE_RECOVERY=.*
      line: GRUB_DISABLE_RECOVERY=true
      state: present
    register: grub_disable_recovery_changed
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - '"grub2-common" in ansible_facts.packages'
    tags:
    - DISA-STIG-OL09-00-002392
    - NIST-800-171-3.1.2
    - NIST-800-171-3.4.5
    - NIST-800-53-CM-6(a)
    - NIST-800-53-SC-2(1)
    - grub2_disable_interactive_boot
    - low_complexity
    - low_disruption
    - medium_severity
    - reboot_required
    - restrict_strategy

  - name: Verify that Interactive Boot is Disabled - Verify that Interactive Boot
      is Disabled in /etc/default/grub
    ansible.builtin.replace:
      dest: /etc/default/grub
      regexp: systemd.confirm_spawn(=(1|yes|true|on)|\b)
      replace: systemd.confirm_spawn=no
    register: grub_confirm_spawn_changed
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - '"grub2-common" in ansible_facts.packages'
    tags:
    - DISA-STIG-OL09-00-002392
    - NIST-800-171-3.1.2
    - NIST-800-171-3.4.5
    - NIST-800-53-CM-6(a)
    - NIST-800-53-SC-2(1)
    - grub2_disable_interactive_boot
    - low_complexity
    - low_disruption
    - medium_severity
    - reboot_required
    - restrict_strategy

  - name: Verify that Interactive Boot is Disabled - Verify that Interactive Boot
      is Disabled (runtime)
    ansible.builtin.command: /sbin/grubby --update-kernel=ALL --remove-args="systemd.confirm_spawn"
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - '"grub2-common" in ansible_facts.packages'
    - grub_confirm_spawn_changed is changed
    tags:
    - DISA-STIG-OL09-00-002392
    - NIST-800-171-3.1.2
    - NIST-800-171-3.4.5
    - NIST-800-53-CM-6(a)
    - NIST-800-53-SC-2(1)
    - grub2_disable_interactive_boot
    - low_complexity
    - low_disruption
    - medium_severity
    - reboot_required
    - restrict_strategy

  - name: Verify that Interactive Boot is Disabled - Regen grub.cfg handle updated
      GRUB_DISABLE_RECOVERY and confirm_spawn
    ansible.builtin.command: grub2-mkconfig -o  /boot/grub2/grub.cfg
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - '"grub2-common" in ansible_facts.packages'
    - grub_disable_recovery_changed is changed or grub_confirm_spawn_changed is changed
    tags:
    - DISA-STIG-OL09-00-002392
    - NIST-800-171-3.1.2
    - NIST-800-171-3.4.5
    - NIST-800-53-CM-6(a)
    - NIST-800-53-SC-2(1)
    - grub2_disable_interactive_boot
    - low_complexity
    - low_disruption
    - medium_severity
    - reboot_required
    - restrict_strategy

  - name: Require emergency mode password
    ansible.builtin.blockinfile:
      create: true
      dest: /etc/systemd/system/emergency.service.d/10-oscap.conf
      block: |-
        [Service]
        ExecStart=
        ExecStart=-/usr/lib/systemd/systemd-sulogin-shell emergency
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-000025
    - NIST-800-171-3.1.1
    - NIST-800-171-3.4.5
    - NIST-800-53-AC-3
    - NIST-800-53-CM-6(a)
    - NIST-800-53-IA-2
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - require_emergency_target_auth
    - restrict_strategy

  - name: Require Authentication for Single User Mode - find files which already override
      Execstart of rescue.service
    ansible.builtin.find:
      paths: /etc/systemd/system/rescue.service.d
      patterns: '*.conf'
      contains: ^\s*ExecStart=.*$
    register: rescue_service_overrides_found
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-000030
    - NIST-800-171-3.1.1
    - NIST-800-171-3.4.5
    - NIST-800-53-AC-3
    - NIST-800-53-CM-6(a)
    - NIST-800-53-IA-2
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - require_singleuser_auth
    - restrict_strategy

  - name: Require Authentication for Single User Mode - set files containing ExecStart
      overrides as target
    ansible.builtin.set_fact:
      rescue_service_remediation_target_file: '{{ rescue_service_overrides_found.files
        | map(attribute=''path'') | list }}'
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - rescue_service_overrides_found.matched is defined and rescue_service_overrides_found.matched
      > 0
    tags:
    - DISA-STIG-OL09-00-000030
    - NIST-800-171-3.1.1
    - NIST-800-171-3.4.5
    - NIST-800-53-AC-3
    - NIST-800-53-CM-6(a)
    - NIST-800-53-IA-2
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - require_singleuser_auth
    - restrict_strategy

  - name: Require Authentication for Single User Mode - set default target for rescue.service
      override
    ansible.builtin.set_fact:
      rescue_service_remediation_target_file:
      - /etc/systemd/system/rescue.service.d/10-oscap.conf
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - rescue_service_overrides_found.matched is defined and rescue_service_overrides_found.matched
      == 0
    tags:
    - DISA-STIG-OL09-00-000030
    - NIST-800-171-3.1.1
    - NIST-800-171-3.4.5
    - NIST-800-53-AC-3
    - NIST-800-53-CM-6(a)
    - NIST-800-53-IA-2
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - require_singleuser_auth
    - restrict_strategy

  - name: Require Authentication for Single User Mode - Require emergency user mode
      password
    community.general.ini_file:
      path: '{{ item }}'
      section: Service
      option: ExecStart
      values:
      - ''
      - -/usr/lib/systemd/systemd-sulogin-shell rescue
    loop: '{{ rescue_service_remediation_target_file }}'
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-000030
    - NIST-800-171-3.1.1
    - NIST-800-171-3.4.5
    - NIST-800-53-AC-3
    - NIST-800-53-CM-6(a)
    - NIST-800-53-IA-2
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - require_singleuser_auth
    - restrict_strategy

  - name: Check existence of opensc conf
    ansible.builtin.stat:
      path: /etc/opensc-{{ ansible_architecture }}.conf
    register: opensc_conf_cd
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-000940
    - NIST-800-53-CM-6(a)
    - NIST-800-53-IA-2(1)
    - NIST-800-53-IA-2(11)
    - NIST-800-53-IA-2(2)
    - NIST-800-53-IA-2(3)
    - NIST-800-53-IA-2(4)
    - NIST-800-53-IA-2(6)
    - NIST-800-53-IA-2(7)
    - PCI-DSS-Req-8.3
    - configure_opensc_card_drivers
    - configure_strategy
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

  - name: Configure smartcard driver block
    block:

    - name: Check if card_drivers is defined
      ansible.builtin.command: /usr/bin/opensc-tool -G app:default:card_drivers
      changed_when: false
      register: card_drivers

    - name: Configure opensc Smart Card Drivers
      ansible.builtin.command: |
        /usr/bin/opensc-tool -S app:default:card_drivers:{{ var_smartcard_drivers }}
      when:
      - card_drivers.stdout != var_smartcard_drivers
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - opensc_conf_cd.stat.exists
    tags:
    - DISA-STIG-OL09-00-000940
    - NIST-800-53-CM-6(a)
    - NIST-800-53-IA-2(1)
    - NIST-800-53-IA-2(11)
    - NIST-800-53-IA-2(2)
    - NIST-800-53-IA-2(3)
    - NIST-800-53-IA-2(4)
    - NIST-800-53-IA-2(6)
    - NIST-800-53-IA-2(7)
    - PCI-DSS-Req-8.3
    - configure_opensc_card_drivers
    - configure_strategy
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

  - name: Set Account Expiration Following Inactivity
    ansible.builtin.lineinfile:
      create: true
      dest: /etc/default/useradd
      regexp: ^INACTIVE
      line: INACTIVE={{ var_account_disable_post_pw_expiration }}
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - '"shadow-utils" in ansible_facts.packages'
    tags:
    - CJIS-5.6.2.1.1
    - DISA-STIG-OL09-00-003065
    - NIST-800-171-3.5.6
    - NIST-800-53-AC-2(3)
    - NIST-800-53-CM-6(a)
    - NIST-800-53-IA-4(e)
    - PCI-DSS-Req-8.1.4
    - PCI-DSSv4-8.2
    - PCI-DSSv4-8.2.6
    - account_disable_post_pw_expiration
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Set Password Maximum Age
    ansible.builtin.lineinfile:
      create: true
      dest: /etc/login.defs
      regexp: ^#?PASS_MAX_DAYS
      line: PASS_MAX_DAYS {{ var_accounts_maximum_age_login_defs }}
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - '"shadow-utils" in ansible_facts.packages'
    tags:
    - CJIS-5.6.2.1
    - DISA-STIG-OL09-00-001095
    - NIST-800-171-3.5.6
    - NIST-800-53-CM-6(a)
    - NIST-800-53-IA-5(1)(d)
    - NIST-800-53-IA-5(f)
    - PCI-DSS-Req-8.2.4
    - PCI-DSSv4-8.3
    - PCI-DSSv4-8.3.9
    - accounts_maximum_age_login_defs
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Set Password Minimum Age
    ansible.builtin.lineinfile:
      create: true
      dest: /etc/login.defs
      regexp: ^#?PASS_MIN_DAYS
      line: PASS_MIN_DAYS {{ var_accounts_minimum_age_login_defs }}
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - '"shadow-utils" in ansible_facts.packages'
    tags:
    - CJIS-5.6.2.1.1
    - DISA-STIG-OL09-00-001085
    - NIST-800-171-3.5.8
    - NIST-800-53-CM-6(a)
    - NIST-800-53-IA-5(1)(d)
    - NIST-800-53-IA-5(f)
    - accounts_minimum_age_login_defs
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Collect users with not correct maximum time period between password changes
    ansible.builtin.command:
      cmd: awk -F':' '(/^[^:]+:[^!*]/ && ($5 > {{ var_accounts_maximum_age_login_defs
        }} || $5 == "")) {print $1}' /etc/shadow
    register: user_names
    changed_when: false
    check_mode: false
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-001100
    - NIST-800-53-CM-6(a)
    - NIST-800-53-IA-5(1)(d)
    - NIST-800-53-IA-5(f)
    - PCI-DSSv4-8.3
    - PCI-DSSv4-8.3.9
    - accounts_password_set_max_life_existing
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Change the maximum time period between password changes
    ansible.builtin.user:
      user: '{{ item }}'
      password_expire_max: '{{ var_accounts_maximum_age_login_defs }}'
    with_items: '{{ user_names.stdout_lines }}'
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - user_names.stdout_lines | length > 0
    tags:
    - DISA-STIG-OL09-00-001100
    - NIST-800-53-CM-6(a)
    - NIST-800-53-IA-5(1)(d)
    - NIST-800-53-IA-5(f)
    - PCI-DSSv4-8.3
    - PCI-DSSv4-8.3.9
    - accounts_password_set_max_life_existing
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Collect users with not correct minimum time period between password changes
    ansible.builtin.command: |
      awk -F':' '(/^[^:]+:[^!*]/ && ($4 < {{ var_accounts_minimum_age_login_defs }} || $4 == "")) {print $1}' /etc/shadow
    register: user_names
    changed_when: false
    check_mode: false
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-001090
    - NIST-800-53-CM-6(a)
    - NIST-800-53-IA-5(1)(d)
    - NIST-800-53-IA-5(f)
    - accounts_password_set_min_life_existing
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Change the minimum time period between password changes
    ansible.builtin.command: |
      chage -m {{ var_accounts_minimum_age_login_defs }} {{ item }}
    with_items: '{{ user_names.stdout_lines }}'
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - user_names.stdout_lines | length > 0
    tags:
    - DISA-STIG-OL09-00-001090
    - NIST-800-53-CM-6(a)
    - NIST-800-53-IA-5(1)(d)
    - NIST-800-53-IA-5(f)
    - accounts_password_set_min_life_existing
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Set number of Password Hashing Rounds - password-auth - Check if /etc/pam.d/password-auth
      file is present
    ansible.builtin.stat:
      path: /etc/pam.d/password-auth
    register: result_pam_password_auth_file_present
    when: ( "pam" in ansible_facts.packages and ("kernel" in ansible_facts.packages
      or "kernel-uek" in ansible_facts.packages) )
    tags:
    - DISA-STIG-OL09-00-001065
    - accounts_password_pam_unix_rounds_password_auth
    - configure_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - no_reboot_needed

  - name: Set number of Password Hashing Rounds - password-auth - Check the proper
      remediation for the system
    block:

    - name: Set number of Password Hashing Rounds - password-auth - Define the PAM
        file to be edited as a local fact
      ansible.builtin.set_fact:
        pam_file_path: /etc/pam.d/password-auth

    - name: Set number of Password Hashing Rounds - password-auth - Check if system
        relies on authselect tool
      ansible.builtin.stat:
        path: /usr/bin/authselect
      register: result_authselect_present

    - name: Set number of Password Hashing Rounds - password-auth - Ensure authselect
        custom profile is used if authselect is present
      block:

      - name: Set number of Password Hashing Rounds - password-auth - Check integrity
          of authselect current profile
        ansible.builtin.command:
          cmd: authselect check
        register: result_authselect_check_cmd
        changed_when: false
        check_mode: false
        failed_when: false

      - name: Set number of Password Hashing Rounds - password-auth - Informative
          message based on the authselect integrity check result
        ansible.builtin.assert:
          that:
          - ansible_check_mode or result_authselect_check_cmd.rc == 0
          fail_msg:
          - authselect integrity check failed. Remediation aborted!
          - This remediation could not be applied because an authselect profile was
            not selected or the selected profile is not intact.
          - It is not recommended to manually edit the PAM files when authselect tool
            is available.
          - In cases where the default authselect profile does not cover a specific
            demand, a custom authselect profile is recommended.
          success_msg:
          - authselect integrity check passed

      - name: Set number of Password Hashing Rounds - password-auth - Get authselect
          current profile
        ansible.builtin.shell:
          cmd: authselect current -r | awk '{ print $1 }'
        register: result_authselect_profile
        changed_when: false
        when:
        - result_authselect_check_cmd is success

      - name: Set number of Password Hashing Rounds - password-auth - Define the current
          authselect profile as a local fact
        ansible.builtin.set_fact:
          authselect_current_profile: '{{ result_authselect_profile.stdout }}'
          authselect_custom_profile: '{{ result_authselect_profile.stdout }}'
        when:
        - result_authselect_profile is not skipped
        - result_authselect_profile.stdout is match("custom/")

      - name: Set number of Password Hashing Rounds - password-auth - Define the new
          authselect custom profile as a local fact
        ansible.builtin.set_fact:
          authselect_current_profile: '{{ result_authselect_profile.stdout }}'
          authselect_custom_profile: custom/hardening
        when:
        - result_authselect_profile is not skipped
        - result_authselect_profile.stdout is not match("custom/")

      - name: Set number of Password Hashing Rounds - password-auth - Get authselect
          current features to also enable them in the custom profile
        ansible.builtin.shell:
          cmd: authselect current | tail -n+3 | awk '{ print $2 }'
        register: result_authselect_features
        changed_when: false
        check_mode: false
        when:
        - result_authselect_profile is not skipped
        - authselect_current_profile is not match("custom/")

      - name: Set number of Password Hashing Rounds - password-auth - Check if any
          custom profile with the same name was already created
        ansible.builtin.stat:
          path: /etc/authselect/{{ authselect_custom_profile }}
        register: result_authselect_custom_profile_present
        changed_when: false
        when:
        - result_authselect_profile is not skipped
        - authselect_current_profile is not match("custom/")

      - name: Set number of Password Hashing Rounds - password-auth - Create an authselect
          custom profile based on the current profile
        ansible.builtin.command:
          cmd: authselect create-profile hardening -b {{ authselect_current_profile
            }}
        when:
        - result_authselect_profile is not skipped
        - result_authselect_check_cmd is success
        - authselect_current_profile is not match("^(custom/|local)")
        - not result_authselect_custom_profile_present.stat.exists

      - name: Set number of Password Hashing Rounds - password-auth - Create an authselect
          custom profile based on sssd profile
        ansible.builtin.command:
          cmd: authselect create-profile hardening -b sssd
        when:
        - result_authselect_profile is not skipped
        - result_authselect_check_cmd is success
        - authselect_current_profile is match("local")
        - not result_authselect_custom_profile_present.stat.exists

      - name: Set number of Password Hashing Rounds - password-auth - Ensure authselect
          changes are applied
        ansible.builtin.command:
          cmd: authselect apply-changes -b --backup=before-hardening-custom-profile
        when:
        - result_authselect_check_cmd is success
        - result_authselect_profile is not skipped
        - authselect_current_profile is not match("custom/")
        - authselect_custom_profile is not match(authselect_current_profile)

      - name: Set number of Password Hashing Rounds - password-auth - Ensure the authselect
          custom profile is selected
        ansible.builtin.command:
          cmd: authselect select {{ authselect_custom_profile }}
        register: result_pam_authselect_select_profile
        when:
        - result_authselect_check_cmd is success
        - result_authselect_profile is not skipped
        - authselect_current_profile is not match("custom/")
        - authselect_custom_profile is not match(authselect_current_profile)

      - name: Set number of Password Hashing Rounds - password-auth - Restore the
          authselect features in the custom profile
        ansible.builtin.command:
          cmd: authselect enable-feature {{ item }}
        loop: '{{ result_authselect_features.stdout_lines }}'
        register: result_pam_authselect_restore_features
        when:
        - result_authselect_profile is not skipped
        - result_authselect_features is not skipped
        - result_pam_authselect_select_profile is not skipped

      - name: Set number of Password Hashing Rounds - password-auth - Ensure authselect
          changes are applied
        ansible.builtin.command:
          cmd: authselect apply-changes -b --backup=after-hardening-custom-profile
        when:
        - result_authselect_check_cmd is success
        - result_authselect_profile is not skipped
        - result_pam_authselect_restore_features is not skipped

      - name: Set number of Password Hashing Rounds - password-auth - Change the PAM
          file to be edited according to the custom authselect profile
        ansible.builtin.set_fact:
          pam_file_path: /etc/authselect/{{ authselect_custom_profile }}/{{ pam_file_path
            | basename }}
        when:
        - authselect_custom_profile is defined
      when:
      - result_authselect_present.stat.exists

    - name: Set number of Password Hashing Rounds - password-auth - Define a fact
        for control already filtered in case filters are used
      ansible.builtin.set_fact:
        pam_module_control: sufficient

    - name: Set number of Password Hashing Rounds - password-auth - Check if expected
        PAM module line is present in {{ pam_file_path }}
      ansible.builtin.lineinfile:
        path: '{{ pam_file_path }}'
        regexp: ^\s*password\s+{{ pam_module_control | regex_escape() }}\s+pam_unix.so\s*.*
        state: absent
      check_mode: true
      changed_when: false
      register: result_pam_line_present

    - name: Set number of Password Hashing Rounds - password-auth - Include or update
        the PAM module line in {{ pam_file_path }}
      block:

      - name: Set number of Password Hashing Rounds - password-auth - Check if required
          PAM module line is present in {{ pam_file_path }} with different control
        ansible.builtin.lineinfile:
          path: '{{ pam_file_path }}'
          regexp: ^\s*password\s+.*\s+pam_unix.so\s*
          state: absent
        check_mode: true
        changed_when: false
        register: result_pam_line_other_control_present

      - name: Set number of Password Hashing Rounds - password-auth - Ensure the correct
          control for the required PAM module line in {{ pam_file_path }}
        ansible.builtin.replace:
          dest: '{{ pam_file_path }}'
          regexp: ^(\s*password\s+).*(\bpam_unix.so.*)
          replace: \1{{ pam_module_control }} \2
        register: result_pam_module_edit
        when:
        - result_pam_line_other_control_present.found == 1

      - name: Set number of Password Hashing Rounds - password-auth - Ensure the required
          PAM module line is included in {{ pam_file_path }}
        ansible.builtin.lineinfile:
          dest: '{{ pam_file_path }}'
          line: password    {{ pam_module_control }}    pam_unix.so
        register: result_pam_module_add
        when:
        - result_pam_line_other_control_present.found == 0 or result_pam_line_other_control_present.found
          > 1

      - name: Set number of Password Hashing Rounds - password-auth - Ensure authselect
          changes are applied
        ansible.builtin.command:
          cmd: authselect apply-changes -b
        when:
        - result_authselect_present is defined
        - result_authselect_present.stat.exists
        - |-
          (result_pam_module_add is defined and result_pam_module_add.changed)
           or (result_pam_module_edit is defined and result_pam_module_edit.changed)
      when:
      - result_pam_line_present.found is defined
      - result_pam_line_present.found == 0

    - name: Set number of Password Hashing Rounds - password-auth - Define a fact
        for control already filtered in case filters are used
      ansible.builtin.set_fact:
        pam_module_control: sufficient

    - name: Set number of Password Hashing Rounds - password-auth - Check if the required
        PAM module option is present in {{ pam_file_path }}
      ansible.builtin.lineinfile:
        path: '{{ pam_file_path }}'
        regexp: ^\s*password\s+{{ pam_module_control | regex_escape() }}\s+pam_unix.so\s*.*\srounds\b
        state: absent
      check_mode: true
      changed_when: false
      register: result_pam_module_accounts_password_pam_unix_rounds_password_auth_option_present

    - name: Set number of Password Hashing Rounds - password-auth - Ensure the "rounds"
        PAM option for "pam_unix.so" is included in {{ pam_file_path }}
      ansible.builtin.lineinfile:
        path: '{{ pam_file_path }}'
        backrefs: true
        regexp: ^(\s*password\s+{{ pam_module_control | regex_escape() }}\s+pam_unix.so.*)
        line: \1 rounds={{ var_password_pam_unix_rounds }}
        state: present
      register: result_pam_accounts_password_pam_unix_rounds_password_auth_add
      when:
      - result_pam_module_accounts_password_pam_unix_rounds_password_auth_option_present.found
        is defined
      - result_pam_module_accounts_password_pam_unix_rounds_password_auth_option_present.found
        == 0

    - name: Set number of Password Hashing Rounds - password-auth - Ensure the required
        value for "rounds" PAM option from "pam_unix.so" in {{ pam_file_path }}
      ansible.builtin.lineinfile:
        path: '{{ pam_file_path }}'
        backrefs: true
        regexp: ^(\s*password\s+{{ pam_module_control | regex_escape() }}\s+pam_unix.so\s+.*)(rounds)=[0-9a-zA-Z]*\s*(.*)
        line: \1\2={{ var_password_pam_unix_rounds }} \3
      register: result_pam_accounts_password_pam_unix_rounds_password_auth_edit
      when:
      - result_pam_module_accounts_password_pam_unix_rounds_password_auth_option_present.found
        > 0

    - name: Set number of Password Hashing Rounds - password-auth - Ensure authselect
        changes are applied
      ansible.builtin.command:
        cmd: authselect apply-changes -b
      when:
      - result_authselect_present.stat.exists
      - |-
        (result_pam_accounts_password_pam_unix_rounds_password_auth_add is defined and result_pam_accounts_password_pam_unix_rounds_password_auth_add.changed)
         or (result_pam_accounts_password_pam_unix_rounds_password_auth_edit is defined and result_pam_accounts_password_pam_unix_rounds_password_auth_edit.changed)
    when:
    - ( "pam" in ansible_facts.packages and ("kernel" in ansible_facts.packages or
      "kernel-uek" in ansible_facts.packages) )
    - result_pam_password_auth_file_present.stat.exists
    tags:
    - DISA-STIG-OL09-00-001065
    - accounts_password_pam_unix_rounds_password_auth
    - configure_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - no_reboot_needed

  - name: Set number of Password Hashing Rounds - system-auth - Check if /etc/pam.d/system-auth
      file is present
    ansible.builtin.stat:
      path: /etc/pam.d/system-auth
    register: result_pam_auth_file_present
    when: ( "pam" in ansible_facts.packages and ("kernel" in ansible_facts.packages
      or "kernel-uek" in ansible_facts.packages) )
    tags:
    - DISA-STIG-OL09-00-001070
    - accounts_password_pam_unix_rounds_system_auth
    - configure_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - no_reboot_needed

  - name: Set number of Password Hashing Rounds - system-auth - Check the proper remediation
      for the system
    block:

    - name: Set number of Password Hashing Rounds - system-auth - Define the PAM file
        to be edited as a local fact
      ansible.builtin.set_fact:
        pam_file_path: /etc/pam.d/system-auth

    - name: Set number of Password Hashing Rounds - system-auth - Check if system
        relies on authselect tool
      ansible.builtin.stat:
        path: /usr/bin/authselect
      register: result_authselect_present

    - name: Set number of Password Hashing Rounds - system-auth - Ensure authselect
        custom profile is used if authselect is present
      block:

      - name: Set number of Password Hashing Rounds - system-auth - Check integrity
          of authselect current profile
        ansible.builtin.command:
          cmd: authselect check
        register: result_authselect_check_cmd
        changed_when: false
        check_mode: false
        failed_when: false

      - name: Set number of Password Hashing Rounds - system-auth - Informative message
          based on the authselect integrity check result
        ansible.builtin.assert:
          that:
          - ansible_check_mode or result_authselect_check_cmd.rc == 0
          fail_msg:
          - authselect integrity check failed. Remediation aborted!
          - This remediation could not be applied because an authselect profile was
            not selected or the selected profile is not intact.
          - It is not recommended to manually edit the PAM files when authselect tool
            is available.
          - In cases where the default authselect profile does not cover a specific
            demand, a custom authselect profile is recommended.
          success_msg:
          - authselect integrity check passed

      - name: Set number of Password Hashing Rounds - system-auth - Get authselect
          current profile
        ansible.builtin.shell:
          cmd: authselect current -r | awk '{ print $1 }'
        register: result_authselect_profile
        changed_when: false
        when:
        - result_authselect_check_cmd is success

      - name: Set number of Password Hashing Rounds - system-auth - Define the current
          authselect profile as a local fact
        ansible.builtin.set_fact:
          authselect_current_profile: '{{ result_authselect_profile.stdout }}'
          authselect_custom_profile: '{{ result_authselect_profile.stdout }}'
        when:
        - result_authselect_profile is not skipped
        - result_authselect_profile.stdout is match("custom/")

      - name: Set number of Password Hashing Rounds - system-auth - Define the new
          authselect custom profile as a local fact
        ansible.builtin.set_fact:
          authselect_current_profile: '{{ result_authselect_profile.stdout }}'
          authselect_custom_profile: custom/hardening
        when:
        - result_authselect_profile is not skipped
        - result_authselect_profile.stdout is not match("custom/")

      - name: Set number of Password Hashing Rounds - system-auth - Get authselect
          current features to also enable them in the custom profile
        ansible.builtin.shell:
          cmd: authselect current | tail -n+3 | awk '{ print $2 }'
        register: result_authselect_features
        changed_when: false
        check_mode: false
        when:
        - result_authselect_profile is not skipped
        - authselect_current_profile is not match("custom/")

      - name: Set number of Password Hashing Rounds - system-auth - Check if any custom
          profile with the same name was already created
        ansible.builtin.stat:
          path: /etc/authselect/{{ authselect_custom_profile }}
        register: result_authselect_custom_profile_present
        changed_when: false
        when:
        - result_authselect_profile is not skipped
        - authselect_current_profile is not match("custom/")

      - name: Set number of Password Hashing Rounds - system-auth - Create an authselect
          custom profile based on the current profile
        ansible.builtin.command:
          cmd: authselect create-profile hardening -b {{ authselect_current_profile
            }}
        when:
        - result_authselect_profile is not skipped
        - result_authselect_check_cmd is success
        - authselect_current_profile is not match("^(custom/|local)")
        - not result_authselect_custom_profile_present.stat.exists

      - name: Set number of Password Hashing Rounds - system-auth - Create an authselect
          custom profile based on sssd profile
        ansible.builtin.command:
          cmd: authselect create-profile hardening -b sssd
        when:
        - result_authselect_profile is not skipped
        - result_authselect_check_cmd is success
        - authselect_current_profile is match("local")
        - not result_authselect_custom_profile_present.stat.exists

      - name: Set number of Password Hashing Rounds - system-auth - Ensure authselect
          changes are applied
        ansible.builtin.command:
          cmd: authselect apply-changes -b --backup=before-hardening-custom-profile
        when:
        - result_authselect_check_cmd is success
        - result_authselect_profile is not skipped
        - authselect_current_profile is not match("custom/")
        - authselect_custom_profile is not match(authselect_current_profile)

      - name: Set number of Password Hashing Rounds - system-auth - Ensure the authselect
          custom profile is selected
        ansible.builtin.command:
          cmd: authselect select {{ authselect_custom_profile }}
        register: result_pam_authselect_select_profile
        when:
        - result_authselect_check_cmd is success
        - result_authselect_profile is not skipped
        - authselect_current_profile is not match("custom/")
        - authselect_custom_profile is not match(authselect_current_profile)

      - name: Set number of Password Hashing Rounds - system-auth - Restore the authselect
          features in the custom profile
        ansible.builtin.command:
          cmd: authselect enable-feature {{ item }}
        loop: '{{ result_authselect_features.stdout_lines }}'
        register: result_pam_authselect_restore_features
        when:
        - result_authselect_profile is not skipped
        - result_authselect_features is not skipped
        - result_pam_authselect_select_profile is not skipped

      - name: Set number of Password Hashing Rounds - system-auth - Ensure authselect
          changes are applied
        ansible.builtin.command:
          cmd: authselect apply-changes -b --backup=after-hardening-custom-profile
        when:
        - result_authselect_check_cmd is success
        - result_authselect_profile is not skipped
        - result_pam_authselect_restore_features is not skipped

      - name: Set number of Password Hashing Rounds - system-auth - Change the PAM
          file to be edited according to the custom authselect profile
        ansible.builtin.set_fact:
          pam_file_path: /etc/authselect/{{ authselect_custom_profile }}/{{ pam_file_path
            | basename }}
        when:
        - authselect_custom_profile is defined
      when:
      - result_authselect_present.stat.exists

    - name: Set number of Password Hashing Rounds - system-auth - Define a fact for
        control already filtered in case filters are used
      ansible.builtin.set_fact:
        pam_module_control: sufficient

    - name: Set number of Password Hashing Rounds - system-auth - Check if expected
        PAM module line is present in {{ pam_file_path }}
      ansible.builtin.lineinfile:
        path: '{{ pam_file_path }}'
        regexp: ^\s*password\s+{{ pam_module_control | regex_escape() }}\s+pam_unix.so\s*.*
        state: absent
      check_mode: true
      changed_when: false
      register: result_pam_line_present

    - name: Set number of Password Hashing Rounds - system-auth - Include or update
        the PAM module line in {{ pam_file_path }}
      block:

      - name: Set number of Password Hashing Rounds - system-auth - Check if required
          PAM module line is present in {{ pam_file_path }} with different control
        ansible.builtin.lineinfile:
          path: '{{ pam_file_path }}'
          regexp: ^\s*password\s+.*\s+pam_unix.so\s*
          state: absent
        check_mode: true
        changed_when: false
        register: result_pam_line_other_control_present

      - name: Set number of Password Hashing Rounds - system-auth - Ensure the correct
          control for the required PAM module line in {{ pam_file_path }}
        ansible.builtin.replace:
          dest: '{{ pam_file_path }}'
          regexp: ^(\s*password\s+).*(\bpam_unix.so.*)
          replace: \1{{ pam_module_control }} \2
        register: result_pam_module_edit
        when:
        - result_pam_line_other_control_present.found == 1

      - name: Set number of Password Hashing Rounds - system-auth - Ensure the required
          PAM module line is included in {{ pam_file_path }}
        ansible.builtin.lineinfile:
          dest: '{{ pam_file_path }}'
          line: password    {{ pam_module_control }}    pam_unix.so
        register: result_pam_module_add
        when:
        - result_pam_line_other_control_present.found == 0 or result_pam_line_other_control_present.found
          > 1

      - name: Set number of Password Hashing Rounds - system-auth - Ensure authselect
          changes are applied
        ansible.builtin.command:
          cmd: authselect apply-changes -b
        when:
        - result_authselect_present is defined
        - result_authselect_present.stat.exists
        - |-
          (result_pam_module_add is defined and result_pam_module_add.changed)
           or (result_pam_module_edit is defined and result_pam_module_edit.changed)
      when:
      - result_pam_line_present.found is defined
      - result_pam_line_present.found == 0

    - name: Set number of Password Hashing Rounds - system-auth - Define a fact for
        control already filtered in case filters are used
      ansible.builtin.set_fact:
        pam_module_control: sufficient

    - name: Set number of Password Hashing Rounds - system-auth - Check if the required
        PAM module option is present in {{ pam_file_path }}
      ansible.builtin.lineinfile:
        path: '{{ pam_file_path }}'
        regexp: ^\s*password\s+{{ pam_module_control | regex_escape() }}\s+pam_unix.so\s*.*\srounds\b
        state: absent
      check_mode: true
      changed_when: false
      register: result_pam_module_accounts_password_pam_unix_rounds_system_auth_option_present

    - name: Set number of Password Hashing Rounds - system-auth - Ensure the "rounds"
        PAM option for "pam_unix.so" is included in {{ pam_file_path }}
      ansible.builtin.lineinfile:
        path: '{{ pam_file_path }}'
        backrefs: true
        regexp: ^(\s*password\s+{{ pam_module_control | regex_escape() }}\s+pam_unix.so.*)
        line: \1 rounds={{ var_password_pam_unix_rounds }}
        state: present
      register: result_pam_accounts_password_pam_unix_rounds_system_auth_add
      when:
      - result_pam_module_accounts_password_pam_unix_rounds_system_auth_option_present.found
        is defined
      - result_pam_module_accounts_password_pam_unix_rounds_system_auth_option_present.found
        == 0

    - name: Set number of Password Hashing Rounds - system-auth - Ensure the required
        value for "rounds" PAM option from "pam_unix.so" in {{ pam_file_path }}
      ansible.builtin.lineinfile:
        path: '{{ pam_file_path }}'
        backrefs: true
        regexp: ^(\s*password\s+{{ pam_module_control | regex_escape() }}\s+pam_unix.so\s+.*)(rounds)=[0-9a-zA-Z]*\s*(.*)
        line: \1\2={{ var_password_pam_unix_rounds }} \3
      register: result_pam_accounts_password_pam_unix_rounds_system_auth_edit
      when:
      - result_pam_module_accounts_password_pam_unix_rounds_system_auth_option_present.found
        > 0

    - name: Set number of Password Hashing Rounds - system-auth - Ensure authselect
        changes are applied
      ansible.builtin.command:
        cmd: authselect apply-changes -b
      when:
      - result_authselect_present.stat.exists
      - |-
        (result_pam_accounts_password_pam_unix_rounds_system_auth_add is defined and result_pam_accounts_password_pam_unix_rounds_system_auth_add.changed)
         or (result_pam_accounts_password_pam_unix_rounds_system_auth_edit is defined and result_pam_accounts_password_pam_unix_rounds_system_auth_edit.changed)
    when:
    - ( "pam" in ansible_facts.packages and ("kernel" in ansible_facts.packages or
      "kernel-uek" in ansible_facts.packages) )
    - result_pam_auth_file_present.stat.exists
    tags:
    - DISA-STIG-OL09-00-001070
    - accounts_password_pam_unix_rounds_system_auth
    - configure_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - no_reboot_needed

  - name: Prevent Login to Accounts With Empty Password - Check if system relies on
      authselect
    ansible.builtin.stat:
      path: /usr/bin/authselect
    register: result_authselect_present
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - CJIS-5.5.2
    - DISA-STIG-OL09-00-001110
    - NIST-800-171-3.1.1
    - NIST-800-171-3.1.5
    - NIST-800-53-CM-6(a)
    - NIST-800-53-IA-5(1)(a)
    - NIST-800-53-IA-5(c)
    - PCI-DSS-Req-8.2.3
    - PCI-DSSv4-8.3
    - PCI-DSSv4-8.3.1
    - configure_strategy
    - high_severity
    - low_complexity
    - medium_disruption
    - no_empty_passwords
    - no_reboot_needed

  - name: Prevent Login to Accounts With Empty Password - Remediate using authselect
    block:

    - name: Prevent Login to Accounts With Empty Password - Check integrity of authselect
        current profile
      ansible.builtin.command:
        cmd: authselect check
      register: result_authselect_check_cmd
      changed_when: false
      check_mode: false
      failed_when: false

    - name: Prevent Login to Accounts With Empty Password - Informative message based
        on the authselect integrity check result
      ansible.builtin.assert:
        that:
        - ansible_check_mode or result_authselect_check_cmd.rc == 0
        fail_msg:
        - authselect integrity check failed. Remediation aborted!
        - This remediation could not be applied because an authselect profile was
          not selected or the selected profile is not intact.
        - It is not recommended to manually edit the PAM files when authselect tool
          is available.
        - In cases where the default authselect profile does not cover a specific
          demand, a custom authselect profile is recommended.
        success_msg:
        - authselect integrity check passed

    - name: Prevent Login to Accounts With Empty Password - Get authselect current
        features
      ansible.builtin.shell:
        cmd: authselect current | tail -n+3 | awk '{ print $2 }'
      register: result_authselect_features
      changed_when: false
      check_mode: false
      when:
      - result_authselect_check_cmd is success

    - name: Prevent Login to Accounts With Empty Password - Ensure "without-nullok"
        feature is enabled using authselect tool
      ansible.builtin.command:
        cmd: authselect enable-feature without-nullok
      register: result_authselect_enable_feature_cmd
      when:
      - result_authselect_check_cmd is success
      - result_authselect_features.stdout is not search("without-nullok")

    - name: Prevent Login to Accounts With Empty Password - Ensure authselect changes
        are applied
      ansible.builtin.command:
        cmd: authselect apply-changes -b
      when:
      - result_authselect_enable_feature_cmd is not skipped
      - result_authselect_enable_feature_cmd is success
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - result_authselect_present.stat.exists
    tags:
    - CJIS-5.5.2
    - DISA-STIG-OL09-00-001110
    - NIST-800-171-3.1.1
    - NIST-800-171-3.1.5
    - NIST-800-53-CM-6(a)
    - NIST-800-53-IA-5(1)(a)
    - NIST-800-53-IA-5(c)
    - PCI-DSS-Req-8.2.3
    - PCI-DSSv4-8.3
    - PCI-DSSv4-8.3.1
    - configure_strategy
    - high_severity
    - low_complexity
    - medium_disruption
    - no_empty_passwords
    - no_reboot_needed

  - name: Prevent Login to Accounts With Empty Password - Remediate directly editing
      PAM files
    ansible.builtin.replace:
      dest: '{{ item }}'
      regexp: nullok
    loop:
    - /etc/pam.d/system-auth
    - /etc/pam.d/password-auth
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - not result_authselect_present.stat.exists
    tags:
    - CJIS-5.5.2
    - DISA-STIG-OL09-00-001110
    - NIST-800-171-3.1.1
    - NIST-800-171-3.1.5
    - NIST-800-53-CM-6(a)
    - NIST-800-53-IA-5(1)(a)
    - NIST-800-53-IA-5(c)
    - PCI-DSS-Req-8.2.3
    - PCI-DSSv4-8.3
    - PCI-DSSv4-8.3.1
    - configure_strategy
    - high_severity
    - low_complexity
    - medium_disruption
    - no_empty_passwords
    - no_reboot_needed

  - name: Collect users with no password
    ansible.builtin.command: |
      awk -F: '!$2 {print $1}' /etc/shadow
    register: users_nopasswd
    changed_when: false
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-001130
    - NIST-800-53-CM-6(b)
    - NIST-800-53-CM-6.1(iv)
    - PCI-DSSv4-2.2
    - PCI-DSSv4-2.2.2
    - high_severity
    - low_complexity
    - low_disruption
    - no_empty_passwords_etc_shadow
    - no_reboot_needed
    - restrict_strategy

  - name: Lock users with no password
    ansible.builtin.command: |
      passwd -l {{ item }}
    with_items: '{{ users_nopasswd.stdout_lines }}'
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - users_nopasswd is not skipped and users_nopasswd.stdout_lines | length > 0
    tags:
    - DISA-STIG-OL09-00-001130
    - NIST-800-53-CM-6(b)
    - NIST-800-53-CM-6.1(iv)
    - PCI-DSSv4-2.2
    - PCI-DSSv4-2.2.2
    - high_severity
    - low_complexity
    - low_disruption
    - no_empty_passwords_etc_shadow
    - no_reboot_needed
    - restrict_strategy

  - name: Get all /etc/passwd file entries
    ansible.builtin.getent:
      database: passwd
      split: ':'
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-003000
    - NIST-800-171-3.1.1
    - NIST-800-171-3.1.5
    - NIST-800-53-AC-6(5)
    - NIST-800-53-IA-2
    - NIST-800-53-IA-4(b)
    - PCI-DSS-Req-8.5
    - PCI-DSSv4-8.2
    - PCI-DSSv4-8.2.1
    - accounts_no_uid_except_zero
    - high_severity
    - low_complexity
    - low_disruption
    - no_reboot_needed
    - restrict_strategy

  - name: Lock the password of the user accounts other than root with uid 0
    ansible.builtin.command: passwd -l {{ item.key }}
    loop: '{{ getent_passwd | dict2items | rejectattr(''key'', ''search'', ''root'')
      | list }}'
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - item.value.1  == '0'
    tags:
    - DISA-STIG-OL09-00-003000
    - NIST-800-171-3.1.1
    - NIST-800-171-3.1.5
    - NIST-800-53-AC-6(5)
    - NIST-800-53-IA-2
    - NIST-800-53-IA-4(b)
    - PCI-DSS-Req-8.5
    - PCI-DSSv4-8.2
    - PCI-DSSv4-8.2.1
    - accounts_no_uid_except_zero
    - high_severity
    - low_complexity
    - low_disruption
    - no_reboot_needed
    - restrict_strategy

  - name: Ensure that System Accounts Do Not Run a Shell Upon Login - Get All Local
      Users From /etc/passwd
    ansible.builtin.getent:
      database: passwd
      split: ':'
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-003051
    - NIST-800-53-AC-6
    - NIST-800-53-CM-6(a)
    - NIST-800-53-CM-6(b)
    - NIST-800-53-CM-6.1(iv)
    - PCI-DSSv4-8.2
    - PCI-DSSv4-8.2.2
    - low_complexity
    - medium_disruption
    - medium_severity
    - no_reboot_needed
    - no_shelllogin_for_systemaccounts
    - restrict_strategy

  - name: Ensure that System Accounts Do Not Run a Shell Upon Login - Create local_users
      Variable From getent_passwd Facts
    ansible.builtin.set_fact:
      local_users: '{{ ansible_facts.getent_passwd | dict2items }}'
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-003051
    - NIST-800-53-AC-6
    - NIST-800-53-CM-6(a)
    - NIST-800-53-CM-6(b)
    - NIST-800-53-CM-6.1(iv)
    - PCI-DSSv4-8.2
    - PCI-DSSv4-8.2.2
    - low_complexity
    - medium_disruption
    - medium_severity
    - no_reboot_needed
    - no_shelllogin_for_systemaccounts
    - restrict_strategy

  - name: Ensure that System Accounts Do Not Run a Shell Upon Login -  Disable Login
      Shell for System Accounts
    ansible.builtin.user:
      name: '{{ item.key }}'
      shell: /sbin/nologin
    loop: '{{ local_users }}'
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - item.key not in ['root']
    - item.value[1]|int < 1000
    - item.value[5] not in ['/sbin/shutdown', '/sbin/halt', '/bin/sync']
    tags:
    - DISA-STIG-OL09-00-003051
    - NIST-800-53-AC-6
    - NIST-800-53-CM-6(a)
    - NIST-800-53-CM-6(b)
    - NIST-800-53-CM-6.1(iv)
    - PCI-DSSv4-8.2
    - PCI-DSSv4-8.2.2
    - low_complexity
    - medium_disruption
    - medium_severity
    - no_reboot_needed
    - no_shelllogin_for_systemaccounts
    - restrict_strategy

  - name: Restrict usage of su command only to members of wheel group
    ansible.builtin.replace:
      path: /etc/pam.d/su
      regexp: ^[\s]*#[\s]*auth[\s]+required[\s]+pam_wheel\.so[\s]+use_uid$
      replace: auth             required        pam_wheel.so use_uid
    when: '"pam" in ansible_facts.packages'
    tags:
    - DISA-STIG-OL09-00-002361
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy
    - use_pam_wheel_for_su

  - name: Ensure new users receive home directories
    block:

    - name: Check for duplicate values
      ansible.builtin.lineinfile:
        path: /etc/login.defs
        create: true
        regexp: (?i)^\s*CREATE_HOME\s+
        state: absent
      check_mode: true
      changed_when: false
      register: dupes

    - name: Deduplicate values from /etc/login.defs
      ansible.builtin.lineinfile:
        path: /etc/login.defs
        create: true
        regexp: (?i)^\s*CREATE_HOME\s+
        state: absent
      when: dupes.found is defined and dupes.found > 1

    - name: Insert correct line to /etc/login.defs
      ansible.builtin.lineinfile:
        path: /etc/login.defs
        create: true
        regexp: (?i)^\s*CREATE_HOME\s+
        line: CREATE_HOME yes
        state: present
    when: ( "shadow-utils" in ansible_facts.packages and ("kernel" in ansible_facts.packages
      or "kernel-uek" in ansible_facts.packages) )
    tags:
    - DISA-STIG-OL09-00-003052
    - accounts_have_homedir_login_defs
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Set accounts logon fail delay
    ansible.builtin.lineinfile:
      dest: /etc/login.defs
      regexp: ^FAIL_DELAY
      line: FAIL_DELAY {{ var_accounts_fail_delay }}
      create: true
    when: ( "shadow-utils" in ansible_facts.packages and ("kernel" in ansible_facts.packages
      or "kernel-uek" in ansible_facts.packages) )
    tags:
    - DISA-STIG-OL09-00-003070
    - NIST-800-53-AC-7(b)
    - NIST-800-53-CM-6(a)
    - accounts_logon_fail_delay
    - low_complexity
    - low_disruption
    - medium_severity
    - reboot_required
    - restrict_strategy

  - name: Find /etc/security/limits.d files containing maxlogins configuration
    ansible.builtin.find:
      paths: /etc/security/limits.d
      contains: ^[\s]*\*[\s]+(?:(?:hard)|(?:-))[\s]+maxlogins
      patterns: '*.conf'
    register: maxlogins
    when: ( "pam" in ansible_facts.packages and ("kernel" in ansible_facts.packages
      or "kernel-uek" in ansible_facts.packages) )
    tags:
    - CJIS-5.5.2.2
    - DISA-STIG-OL09-00-002415
    - NIST-800-53-AC-10
    - NIST-800-53-CM-6(a)
    - accounts_max_concurrent_login_sessions
    - low_complexity
    - low_disruption
    - low_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Limit the Number of Concurrent Login Sessions Allowed Per User in files
      from limits.d
    ansible.builtin.replace:
      dest: '{{ item.path }}'
      regexp: ^#?\*.*maxlogins.*
      replace: '*          hard    maxlogins     {{ var_accounts_max_concurrent_login_sessions
        }}'
    with_items:
    - '{{ maxlogins.files }}'
    when: ( "pam" in ansible_facts.packages and ("kernel" in ansible_facts.packages
      or "kernel-uek" in ansible_facts.packages) )
    tags:
    - CJIS-5.5.2.2
    - DISA-STIG-OL09-00-002415
    - NIST-800-53-AC-10
    - NIST-800-53-CM-6(a)
    - accounts_max_concurrent_login_sessions
    - low_complexity
    - low_disruption
    - low_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Limit the Number of Concurrent Login Sessions Allowed Per User
    ansible.builtin.lineinfile:
      state: present
      dest: /etc/security/limits.conf
      insertbefore: ^# End of file
      regexp: ^#?\*.*maxlogins
      line: '*          hard    maxlogins     {{ var_accounts_max_concurrent_login_sessions
        }}'
      create: true
    when:
    - ( "pam" in ansible_facts.packages and ("kernel" in ansible_facts.packages or
      "kernel-uek" in ansible_facts.packages) )
    - maxlogins.matched == 0
    tags:
    - CJIS-5.5.2.2
    - DISA-STIG-OL09-00-002415
    - NIST-800-53-AC-10
    - NIST-800-53-CM-6(a)
    - accounts_max_concurrent_login_sessions
    - low_complexity
    - low_disruption
    - low_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Correct any occurrence of TMOUT in /etc/profile
    ansible.builtin.replace:
      path: /etc/profile
      regexp: ^[^#].*TMOUT=.*
      replace: typeset -xr TMOUT={{ var_accounts_tmout }}
    register: profile_replaced
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-002411
    - NIST-800-171-3.1.11
    - NIST-800-53-AC-12
    - NIST-800-53-AC-2(5)
    - NIST-800-53-CM-6(a)
    - NIST-800-53-SC-10
    - PCI-DSSv4-8.6
    - PCI-DSSv4-8.6.1
    - accounts_tmout
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Set Interactive Session Timeout
    ansible.builtin.lineinfile:
      path: /etc/profile.d/tmout.sh
      create: true
      regexp: TMOUT=
      line: typeset -xr TMOUT={{ var_accounts_tmout }}
      state: present
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-002411
    - NIST-800-171-3.1.11
    - NIST-800-53-AC-12
    - NIST-800-53-AC-2(5)
    - NIST-800-53-CM-6(a)
    - NIST-800-53-SC-10
    - PCI-DSSv4-8.6
    - PCI-DSSv4-8.6.1
    - accounts_tmout
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Get all local users from /etc/passwd
    ansible.builtin.getent:
      database: passwd
      split: ':'
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-003002
    - accounts_user_interactive_home_directory_defined
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Create local_users variable from the getent output
    ansible.builtin.set_fact:
      local_users: '{{ ansible_facts.getent_passwd|dict2items }}'
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-003002
    - accounts_user_interactive_home_directory_defined
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Ensure interactive users have an exclusive home directory defined
    ansible.builtin.user:
      name: '{{ item.key }}'
      home: /home/{{ item.key }}
      create_home: false
    loop: '{{ local_users }}'
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - item.value[2]|int >= 1000
    - item.value[2]|int != 65534
    - item.value[2]|int < 61184 or item.value[2]|int > 65519
    - not item.value[4] | regex_search('^\/\w*\/\w{1,}')
    tags:
    - DISA-STIG-OL09-00-003002
    - accounts_user_interactive_home_directory_defined
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Get all local users from /etc/passwd
    ansible.builtin.getent:
      database: passwd
      split: ':'
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-003050
    - accounts_user_interactive_home_directory_exists
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Create local_users variable from the getent output
    ansible.builtin.set_fact:
      local_users: '{{ ansible_facts.getent_passwd|dict2items }}'
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-003050
    - accounts_user_interactive_home_directory_exists
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Ensure interactive users have a home directory exists
    ansible.builtin.user:
      name: '{{ item.key }}'
      create_home: true
    loop: '{{ local_users }}'
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - item.value[1]|int >= 1000
    - item.value[1]|int != 65534
    tags:
    - DISA-STIG-OL09-00-003050
    - accounts_user_interactive_home_directory_exists
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Get all local users from /etc/passwd
    ansible.builtin.getent:
      database: passwd
      split: ':'
    tags:
    - DISA-STIG-OL09-00-002514
    - file_groupownership_home_directories
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Create local_users variable from the getent output
    ansible.builtin.set_fact:
      local_users: '{{ ansible_facts.getent_passwd|dict2items }}'
    tags:
    - DISA-STIG-OL09-00-002514
    - file_groupownership_home_directories
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Test for existence of home directories to avoid creating them, but only
      fixing group ownership
    ansible.builtin.stat:
      path: '{{ item.value[4] }}'
    register: path_exists
    loop: '{{ local_users }}'
    when:
    - item.value[1]|int >= 1000
    - item.value[1]|int != 65534
    tags:
    - DISA-STIG-OL09-00-002514
    - file_groupownership_home_directories
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Ensure interactive local users are the group-owners of their respective
      home directories
    ansible.builtin.file:
      path: '{{ item.0.value[4] }}'
      group: '{{ item.0.value[2] }}'
    loop: '{{ local_users|zip(path_exists.results)|list }}'
    when: item.1.stat is defined and item.1.stat.exists
    tags:
    - DISA-STIG-OL09-00-002514
    - file_groupownership_home_directories
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Ensure All User Initialization Files Have Mode 0740 Or Less Permissive -
      Gather User Info
    ansible.builtin.getent:
      database: passwd
    tags:
    - DISA-STIG-OL09-00-002513
    - file_permission_user_init_files_root
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Ensure All User Initialization Files Have Mode 0740 Or Less Permissive -
      Find Init Files
    ansible.builtin.find:
      paths: '{{ item.value[4] }}'
      pattern: '{{ var_user_initialization_files_regex }}'
      hidden: true
      use_regex: true
    with_dict: '{{ ansible_facts.getent_passwd }}'
    when:
    - item.value[4] != "/sbin/nologin"
    - item.key not in ["nobody", "nfsnobody"]
    - item.value[1] | int >= 1000 or item.key == "root"
    register: found_init_files
    tags:
    - DISA-STIG-OL09-00-002513
    - file_permission_user_init_files_root
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Ensure All User Initialization Files Have Mode 0740 Or Less Permissive -
      Fix Init Files Permissions
    ansible.builtin.file:
      path: '{{ item.1.path }}'
      mode: u-s,g-wxs,o=
    loop: '{{ q(''ansible.builtin.subelements'', found_init_files.results, ''files'',
      {''skip_missing'': True}) }}'
    tags:
    - DISA-STIG-OL09-00-002513
    - file_permission_user_init_files_root
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Get all local users from /etc/passwd
    ansible.builtin.getent:
      database: passwd
      split: ':'
    tags:
    - DISA-STIG-OL09-00-002515
    - file_permissions_home_directories
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Create local_users variable from the getent output
    ansible.builtin.set_fact:
      local_users: '{{ ansible_facts.getent_passwd|dict2items }}'
    tags:
    - DISA-STIG-OL09-00-002515
    - file_permissions_home_directories
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Test for existence home directories to avoid creating them.
    ansible.builtin.stat:
      path: '{{ item.value[4] }}'
    register: path_exists
    loop: '{{ local_users }}'
    when:
    - item.value[1]|int >= 1000
    - item.value[1]|int != 65534
    - item.value[4] != "/"
    tags:
    - DISA-STIG-OL09-00-002515
    - file_permissions_home_directories
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Ensure interactive local users have proper permissions on their respective
      home directories
    ansible.builtin.file:
      path: '{{ item.0.value[4] }}'
      mode: u-s,g-w-s,o=-
      follow: false
      recurse: false
    loop: '{{ local_users|zip(path_exists.results)|list }}'
    when: item.1.stat is defined and item.1.stat.exists
    tags:
    - DISA-STIG-OL09-00-002515
    - file_permissions_home_directories
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Check if umask in /etc/bashrc is already set
    ansible.builtin.lineinfile:
      path: /etc/bashrc
      regexp: ^[^#]*\bumask\s+\d+$
      state: absent
    check_mode: true
    changed_when: false
    register: umask_replace
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - '"bash" in ansible_facts.packages'
    tags:
    - DISA-STIG-OL09-00-002301
    - NIST-800-53-AC-6(1)
    - NIST-800-53-CM-6(a)
    - accounts_umask_etc_bashrc
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Replace user umask in /etc/bashrc
    ansible.builtin.replace:
      path: /etc/bashrc
      regexp: ^([^#]*\b)umask\s+\d+$
      replace: \g<1>umask {{ var_accounts_user_umask }}
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - '"bash" in ansible_facts.packages'
    - umask_replace.found > 0
    tags:
    - DISA-STIG-OL09-00-002301
    - NIST-800-53-AC-6(1)
    - NIST-800-53-CM-6(a)
    - accounts_umask_etc_bashrc
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Ensure the Default umask is Appended Correctly
    ansible.builtin.lineinfile:
      create: true
      path: /etc/bashrc
      line: umask {{ var_accounts_user_umask }}
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - '"bash" in ansible_facts.packages'
    - umask_replace.found == 0
    tags:
    - DISA-STIG-OL09-00-002301
    - NIST-800-53-AC-6(1)
    - NIST-800-53-CM-6(a)
    - accounts_umask_etc_bashrc
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Check if umask in /etc/csh.cshrc is already set
    ansible.builtin.lineinfile:
      path: /etc/csh.cshrc
      regexp: ^(\s*)umask\s+.*
      state: absent
    check_mode: true
    changed_when: false
    register: umask_replace
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-002302
    - NIST-800-53-AC-6(1)
    - NIST-800-53-CM-6(a)
    - accounts_umask_etc_csh_cshrc
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Replace user umask in /etc/csh.cshrc
    ansible.builtin.replace:
      path: /etc/csh.cshrc
      regexp: ^(\s*)umask(\s+).*
      replace: \g<1>umask\g<2>{{ var_accounts_user_umask }}
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - umask_replace.found > 0
    tags:
    - DISA-STIG-OL09-00-002302
    - NIST-800-53-AC-6(1)
    - NIST-800-53-CM-6(a)
    - accounts_umask_etc_csh_cshrc
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Ensure the Default umask is Appended Correctly
    ansible.builtin.lineinfile:
      create: true
      path: /etc/csh.cshrc
      line: umask {{ var_accounts_user_umask }}
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - umask_replace.found == 0
    tags:
    - DISA-STIG-OL09-00-002302
    - NIST-800-53-AC-6(1)
    - NIST-800-53-CM-6(a)
    - accounts_umask_etc_csh_cshrc
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Check if UMASK is already set
    ansible.builtin.lineinfile:
      path: /etc/login.defs
      regexp: ^(\s*)UMASK\s+.*
      state: absent
    check_mode: true
    changed_when: false
    register: result_umask_is_set
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - '"shadow-utils" in ansible_facts.packages'
    tags:
    - DISA-STIG-OL09-00-002304
    - NIST-800-53-AC-6(1)
    - NIST-800-53-CM-6(a)
    - accounts_umask_etc_login_defs
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Replace user UMASK in /etc/login.defs
    ansible.builtin.replace:
      path: /etc/login.defs
      regexp: ^(\s*)UMASK(\s+).*
      replace: \g<1>UMASK\g<2>{{ var_accounts_user_umask }}
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - '"shadow-utils" in ansible_facts.packages'
    - result_umask_is_set.found > 0
    tags:
    - DISA-STIG-OL09-00-002304
    - NIST-800-53-AC-6(1)
    - NIST-800-53-CM-6(a)
    - accounts_umask_etc_login_defs
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Ensure the Default UMASK is Appended Correctly
    ansible.builtin.lineinfile:
      create: true
      path: /etc/login.defs
      line: UMASK {{ var_accounts_user_umask }}
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - '"shadow-utils" in ansible_facts.packages'
    - result_umask_is_set.found == 0
    tags:
    - DISA-STIG-OL09-00-002304
    - NIST-800-53-AC-6(1)
    - NIST-800-53-CM-6(a)
    - accounts_umask_etc_login_defs
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Ensure the Default Umask is Set Correctly in /etc/profile - Locate Profile
      Configuration Files Where umask Is Defined
    ansible.builtin.find:
      paths:
      - /etc/profile.d
      patterns:
      - sh.local
      - '*.sh'
      contains: ^[\s]*umask\s+\d+
    register: result_profile_d_files
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-002303
    - NIST-800-53-AC-6(1)
    - NIST-800-53-CM-6(a)
    - accounts_umask_etc_profile
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Ensure the Default Umask is Set Correctly in /etc/profile - Replace Existing
      umask Value in Files From /etc/profile.d
    ansible.builtin.replace:
      path: '{{ item.path }}'
      regexp: ^(\s*)umask\s+\d+
      replace: \1umask {{ var_accounts_user_umask }}
    loop: '{{ result_profile_d_files.files }}'
    register: result_umask_replaced_profile_d
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - result_profile_d_files.matched
    tags:
    - DISA-STIG-OL09-00-002303
    - NIST-800-53-AC-6(1)
    - NIST-800-53-CM-6(a)
    - accounts_umask_etc_profile
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Ensure the Default Umask is Set Correctly in /etc/profile - Ensure umask
      Is Set in /etc/profile if Not Already Set Elsewhere
    ansible.builtin.lineinfile:
      create: true
      mode: 420
      path: /etc/profile
      line: umask {{ var_accounts_user_umask }}
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - not result_profile_d_files.matched
    tags:
    - DISA-STIG-OL09-00-002303
    - NIST-800-53-AC-6(1)
    - NIST-800-53-CM-6(a)
    - accounts_umask_etc_profile
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Ensure the Default Umask is Set Correctly in /etc/profile - Ensure umask
      Value For All Existing umask Definition in /etc/profile
    ansible.builtin.replace:
      path: /etc/profile
      regexp: ^(\s*)umask\s+\d+
      replace: \1umask {{ var_accounts_user_umask }}
    register: result_umask_replaced_profile
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-002303
    - NIST-800-53-AC-6(1)
    - NIST-800-53-CM-6(a)
    - accounts_umask_etc_profile
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Ensure the Default Umask is Set Correctly For Interactive Users - Get interactive
      users from passwd file
    ansible.builtin.getent:
      database: passwd
    register: passwd_entries
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-003060
    - accounts_umask_interactive_users
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Ensure the Default Umask is Set Correctly For Interactive Users - Filter
      interactive users and get home directories
    ansible.builtin.set_fact:
      interactive_user_homes: '{{ interactive_user_homes | default([]) + [item.value[4]]
        }}'
    loop: '{{ passwd_entries.ansible_facts.getent_passwd | dict2items }}'
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - item.value[2] | int >= 1000 | int
    - item.value[2] | int != 65534 | int
    - item.value[4] != ""
    tags:
    - DISA-STIG-OL09-00-003060
    - accounts_umask_interactive_users
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Ensure the Default Umask is Set Correctly For Interactive Users - Find dot
      files in interactive user home directories
    ansible.builtin.find:
      paths: '{{ item }}'
      patterns: .*
      file_type: file
      hidden: true
      depth: 1
    register: user_dotfiles
    with_items: '{{ interactive_user_homes | default([]) }}'
    failed_when: false
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - item != ""
    tags:
    - DISA-STIG-OL09-00-003060
    - accounts_umask_interactive_users
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Ensure the Default Umask is Set Correctly For Interactive Users - Comment
      out umask statements in user initialization files
    ansible.builtin.replace:
      path: '{{ item.1.path }}'
      regexp: ^\s*umask\s+
      replace: '#\g<0>'
      backup: false
    with_subelements:
    - '{{ user_dotfiles.results }}'
    - files
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - item.0 is not skipped
    - item.1.path is defined
    - '''.bash_history'' not in item.1.path'
    tags:
    - DISA-STIG-OL09-00-003060
    - accounts_umask_interactive_users
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Check if pti argument is already present in /etc/default/grub
    ansible.builtin.slurp:
      src: /etc/default/grub
    register: etc_default_grub
    when: ( "grub2-common" in ansible_facts.packages and ("kernel" in ansible_facts.packages
      or "kernel-uek" in ansible_facts.packages) )
    tags:
    - DISA-STIG-OL09-00-002391
    - NIST-800-53-SI-16
    - grub2_pti_argument
    - low_disruption
    - low_severity
    - medium_complexity
    - reboot_required
    - restrict_strategy

  - name: Check if pti argument is already present
    ansible.builtin.command: /sbin/grubby --info=ALL
    register: grubby_info
    check_mode: false
    changed_when: false
    failed_when: false
    when: ( "grub2-common" in ansible_facts.packages and ("kernel" in ansible_facts.packages
      or "kernel-uek" in ansible_facts.packages) )
    tags:
    - DISA-STIG-OL09-00-002391
    - NIST-800-53-SI-16
    - grub2_pti_argument
    - low_disruption
    - low_severity
    - medium_complexity
    - reboot_required
    - restrict_strategy

  - name: Update grub defaults and the bootloader menu
    ansible.builtin.command: /sbin/grubby --update-kernel=ALL --args="pti=on"
    when:
    - ( "grub2-common" in ansible_facts.packages and ("kernel" in ansible_facts.packages
      or "kernel-uek" in ansible_facts.packages) )
    - (grubby_info.stdout is not search('pti=on')) or ((etc_default_grub['content']
      | b64decode) is not search('pti=on'))
    tags:
    - DISA-STIG-OL09-00-002391
    - NIST-800-53-SI-16
    - grub2_pti_argument
    - low_disruption
    - low_severity
    - medium_complexity
    - reboot_required
    - restrict_strategy

  - name: Check if vsyscall argument is already present in /etc/default/grub
    ansible.builtin.slurp:
      src: /etc/default/grub
    register: etc_default_grub
    when:
    - ( "grub2-common" in ansible_facts.packages and ("kernel" in ansible_facts.packages
      or "kernel-uek" in ansible_facts.packages) )
    - ansible_architecture == "x86_64"
    tags:
    - DISA-STIG-OL09-00-002393
    - NIST-800-53-CM-7(a)
    - grub2_vsyscall_argument
    - low_disruption
    - medium_complexity
    - medium_severity
    - reboot_required
    - restrict_strategy

  - name: Check if vsyscall argument is already present
    ansible.builtin.command: /sbin/grubby --info=ALL
    register: grubby_info
    check_mode: false
    changed_when: false
    failed_when: false
    when:
    - ( "grub2-common" in ansible_facts.packages and ("kernel" in ansible_facts.packages
      or "kernel-uek" in ansible_facts.packages) )
    - ansible_architecture == "x86_64"
    tags:
    - DISA-STIG-OL09-00-002393
    - NIST-800-53-CM-7(a)
    - grub2_vsyscall_argument
    - low_disruption
    - medium_complexity
    - medium_severity
    - reboot_required
    - restrict_strategy

  - name: Update grub defaults and the bootloader menu
    ansible.builtin.command: /sbin/grubby --update-kernel=ALL --args="vsyscall=none"
    when:
    - ( "grub2-common" in ansible_facts.packages and ("kernel" in ansible_facts.packages
      or "kernel-uek" in ansible_facts.packages) )
    - ansible_architecture == "x86_64"
    - (grubby_info.stdout is not search('vsyscall=none')) or ((etc_default_grub['content']
      | b64decode) is not search('vsyscall=none'))
    tags:
    - DISA-STIG-OL09-00-002393
    - NIST-800-53-CM-7(a)
    - grub2_vsyscall_argument
    - low_disruption
    - medium_complexity
    - medium_severity
    - reboot_required
    - restrict_strategy

  - name: Set the file_groupowner_grub2_cfg_newgroup variable if represented by gid
    ansible.builtin.set_fact:
      file_groupowner_grub2_cfg_newgroup: '0'
    when:
    - ( "grub2-common" in ansible_facts.packages and ("kernel" in ansible_facts.packages
      or "kernel-uek" in ansible_facts.packages) )
    - not ( ansible_virtualization_type in ["docker", "lxc", "openvz", "podman", "container"]
      )
    tags:
    - CJIS-5.5.2.2
    - DISA-STIG-OL09-00-002530
    - NIST-800-171-3.4.5
    - NIST-800-53-AC-6(1)
    - NIST-800-53-CM-6(a)
    - PCI-DSS-Req-7.1
    - PCI-DSSv4-2.2
    - PCI-DSSv4-2.2.6
    - configure_strategy
    - file_groupowner_grub2_cfg
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

  - name: Test for existence /boot/grub2/grub.cfg
    ansible.builtin.stat:
      path: /boot/grub2/grub.cfg
    register: file_exists
    when:
    - ( "grub2-common" in ansible_facts.packages and ("kernel" in ansible_facts.packages
      or "kernel-uek" in ansible_facts.packages) )
    - not ( ansible_virtualization_type in ["docker", "lxc", "openvz", "podman", "container"]
      )
    tags:
    - CJIS-5.5.2.2
    - DISA-STIG-OL09-00-002530
    - NIST-800-171-3.4.5
    - NIST-800-53-AC-6(1)
    - NIST-800-53-CM-6(a)
    - PCI-DSS-Req-7.1
    - PCI-DSSv4-2.2
    - PCI-DSSv4-2.2.6
    - configure_strategy
    - file_groupowner_grub2_cfg
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

  - name: Ensure group owner on /boot/grub2/grub.cfg
    ansible.builtin.file:
      path: /boot/grub2/grub.cfg
      follow: false
      group: '{{ file_groupowner_grub2_cfg_newgroup }}'
    when:
    - ( "grub2-common" in ansible_facts.packages and ("kernel" in ansible_facts.packages
      or "kernel-uek" in ansible_facts.packages) )
    - not ( ansible_virtualization_type in ["docker", "lxc", "openvz", "podman", "container"]
      )
    - file_exists.stat is defined and file_exists.stat.exists
    tags:
    - CJIS-5.5.2.2
    - DISA-STIG-OL09-00-002530
    - NIST-800-171-3.4.5
    - NIST-800-53-AC-6(1)
    - NIST-800-53-CM-6(a)
    - PCI-DSS-Req-7.1
    - PCI-DSSv4-2.2
    - PCI-DSSv4-2.2.6
    - configure_strategy
    - file_groupowner_grub2_cfg
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

  - name: Set the file_owner_grub2_cfg_newown variable if represented by uid
    ansible.builtin.set_fact:
      file_owner_grub2_cfg_newown: '0'
    when:
    - ( "grub2-common" in ansible_facts.packages and ("kernel" in ansible_facts.packages
      or "kernel-uek" in ansible_facts.packages) )
    - not ( ansible_virtualization_type in ["docker", "lxc", "openvz", "podman", "container"]
      )
    tags:
    - CJIS-5.5.2.2
    - DISA-STIG-OL09-00-002531
    - NIST-800-171-3.4.5
    - NIST-800-53-AC-6(1)
    - NIST-800-53-CM-6(a)
    - PCI-DSS-Req-7.1
    - PCI-DSSv4-2.2
    - PCI-DSSv4-2.2.6
    - configure_strategy
    - file_owner_grub2_cfg
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

  - name: Test for existence /boot/grub2/grub.cfg
    ansible.builtin.stat:
      path: /boot/grub2/grub.cfg
    register: file_exists
    when:
    - ( "grub2-common" in ansible_facts.packages and ("kernel" in ansible_facts.packages
      or "kernel-uek" in ansible_facts.packages) )
    - not ( ansible_virtualization_type in ["docker", "lxc", "openvz", "podman", "container"]
      )
    tags:
    - CJIS-5.5.2.2
    - DISA-STIG-OL09-00-002531
    - NIST-800-171-3.4.5
    - NIST-800-53-AC-6(1)
    - NIST-800-53-CM-6(a)
    - PCI-DSS-Req-7.1
    - PCI-DSSv4-2.2
    - PCI-DSSv4-2.2.6
    - configure_strategy
    - file_owner_grub2_cfg
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

  - name: Ensure owner on /boot/grub2/grub.cfg
    ansible.builtin.file:
      path: /boot/grub2/grub.cfg
      follow: false
      owner: '{{ file_owner_grub2_cfg_newown }}'
    when:
    - ( "grub2-common" in ansible_facts.packages and ("kernel" in ansible_facts.packages
      or "kernel-uek" in ansible_facts.packages) )
    - not ( ansible_virtualization_type in ["docker", "lxc", "openvz", "podman", "container"]
      )
    - file_exists.stat is defined and file_exists.stat.exists
    tags:
    - CJIS-5.5.2.2
    - DISA-STIG-OL09-00-002531
    - NIST-800-171-3.4.5
    - NIST-800-53-AC-6(1)
    - NIST-800-53-CM-6(a)
    - PCI-DSS-Req-7.1
    - PCI-DSSv4-2.2
    - PCI-DSSv4-2.2.6
    - configure_strategy
    - file_owner_grub2_cfg
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

  - name: Ensure cron Is Logging To Rsyslog - Ensure /etc/rsyslog.conf exists
    ansible.builtin.file:
      path: /etc/rsyslog.conf
      state: touch
      modification_time: preserve
      access_time: preserve
    when:
    - '"rsyslog" in ansible_facts.packages'
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-005010
    - NIST-800-53-CM-6(a)
    - configure_strategy
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - rsyslog_cron_logging

  - name: Ensure cron Is Logging To Rsyslog - Ensure /etc/rsyslog.d directory exists
    ansible.builtin.file:
      path: /etc/rsyslog.d
      state: directory
    when:
    - '"rsyslog" in ansible_facts.packages'
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-005010
    - NIST-800-53-CM-6(a)
    - configure_strategy
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - rsyslog_cron_logging

  - name: Ensure cron Is Logging To Rsyslog - Remove multilined cron.* action() entries
      from rsyslog.conf
    ansible.builtin.shell: sed -i '/^[[:space:]]*cron\.\*.*action(/,/)/d' /etc/rsyslog.conf
    changed_when: true
    when:
    - '"rsyslog" in ansible_facts.packages'
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-005010
    - NIST-800-53-CM-6(a)
    - configure_strategy
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - rsyslog_cron_logging

  - name: Ensure cron Is Logging To Rsyslog - Remove multilined cron.* action() entries
      from rsyslog.d/*.conf
    ansible.builtin.shell: find /etc/rsyslog.d -type f -name "*.conf" -exec sed -i
      '/^[[:space:]]*cron\.\*.*action(/,/)/d' {} +
    changed_when: true
    when:
    - '"rsyslog" in ansible_facts.packages'
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-005010
    - NIST-800-53-CM-6(a)
    - configure_strategy
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - rsyslog_cron_logging

  - name: Remove *.* entries pointing to /var/log/cron from rsyslog.conf
    ansible.builtin.lineinfile:
      path: /etc/rsyslog.conf
      create: false
      regexp: (?i)^\s*\*\.\*\s+/var/log/cron\s*$
      state: absent
    when:
    - '"rsyslog" in ansible_facts.packages'
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-005010
    - NIST-800-53-CM-6(a)
    - configure_strategy
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - rsyslog_cron_logging

  - name: Ensure cron Is Logging To Rsyslog - Remove *.* entries pointing to /var/log/cron
      from rsyslog.d/*.conf
    ansible.builtin.shell: find /etc/rsyslog.d -type f -name "*.conf" -exec sed -i
      '\|^\s*\*\.\*\s\+/var/log/cron\s*$|d' {} +
    changed_when: true
    when:
    - '"rsyslog" in ansible_facts.packages'
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-005010
    - NIST-800-53-CM-6(a)
    - configure_strategy
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - rsyslog_cron_logging

  - name: Ensure cron Is Logging To Rsyslog - Check if the parameter cron.* is configured
    ansible.builtin.find:
      paths:
      - /etc/rsyslog.conf
      - /etc/rsyslog.d
      contains: ^\s*{{ "cron.*"| regex_escape }}
    register: _sshd_config_has_parameter
    when:
    - '"rsyslog" in ansible_facts.packages'
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-005010
    - NIST-800-53-CM-6(a)
    - configure_strategy
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - rsyslog_cron_logging

  - name: Ensure cron Is Logging To Rsyslog - Check if the parameter cron.* is configured
      correctly
    ansible.builtin.find:
      paths:
      - /etc/rsyslog.conf
      - /etc/rsyslog.d
      contains: ^\s*{{ "cron.*"| regex_escape }}/var/log/cron$
    register: _sshd_config_correctly
    when:
    - '"rsyslog" in ansible_facts.packages'
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-005010
    - NIST-800-53-CM-6(a)
    - configure_strategy
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - rsyslog_cron_logging

  - name: Ensure cron Is Logging To Rsyslog
    block:

    - name: Deduplicate values from /etc/rsyslog.conf
      ansible.builtin.lineinfile:
        path: /etc/rsyslog.conf
        create: false
        regexp: (?i)^\s*{{ "cron.*"| regex_escape }}
        state: absent

    - name: Check if /etc/rsyslog.d exists
      ansible.builtin.stat:
        path: /etc/rsyslog.d
      register: _etc_rsyslog_d_exists

    - name: Check if the parameter cron.* is present in /etc/rsyslog.d
      ansible.builtin.find:
        paths: /etc/rsyslog.d
        recurse: 'yes'
        follow: 'no'
        contains: ^\s*{{ "cron.*"| regex_escape }}
      register: _etc_rsyslog_d_has_parameter
      when: _etc_rsyslog_d_exists.stat.isdir is defined and _etc_rsyslog_d_exists.stat.isdir

    - name: Remove parameter from files in /etc/rsyslog.d
      ansible.builtin.lineinfile:
        path: '{{ item.path }}'
        create: false
        regexp: (?i)^\s*{{ "cron.*"| regex_escape }}
        state: absent
      with_items: '{{ _etc_rsyslog_d_has_parameter.files }}'
      when: _etc_rsyslog_d_has_parameter.matched > 0

    - name: Insert correct line to /etc/rsyslog.d/cron.conf
      ansible.builtin.lineinfile:
        path: /etc/rsyslog.d/cron.conf
        create: true
        regexp: (?i)^\s*{{ "cron.*"| regex_escape }}
        line: cron.* /var/log/cron
        state: present
    when:
    - '"rsyslog" in ansible_facts.packages'
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - _sshd_config_correctly.matched == 0 or _sshd_config_has_parameter.matched !=
      1
    tags:
    - DISA-STIG-OL09-00-005010
    - NIST-800-53-CM-6(a)
    - configure_strategy
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - rsyslog_cron_logging

  - name: Ensure cron Is Logging To Rsyslog - Restart the rsyslog service now
    ansible.builtin.service:
      name: rsyslog
      state: restarted
    when:
    - '"rsyslog" in ansible_facts.packages'
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-005010
    - NIST-800-53-CM-6(a)
    - configure_strategy
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - rsyslog_cron_logging

  - name: Ensure Rsyslog Authenticates Off-Loaded Audit Records - Ensure /etc/rsyslog.conf
      exists
    ansible.builtin.file:
      path: /etc/rsyslog.conf
      state: touch
      modification_time: preserve
      access_time: preserve
    when:
    - '"rsyslog" in ansible_facts.packages'
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-005015
    - NIST-800-53-AU-4(1)
    - configure_strategy
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - rsyslog_encrypt_offload_actionsendstreamdriverauthmode

  - name: Ensure Rsyslog Authenticates Off-Loaded Audit Records - Ensure /etc/rsyslog.d
      directory exists
    ansible.builtin.file:
      path: /etc/rsyslog.d
      state: directory
    when:
    - '"rsyslog" in ansible_facts.packages'
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-005015
    - NIST-800-53-AU-4(1)
    - configure_strategy
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - rsyslog_encrypt_offload_actionsendstreamdriverauthmode

  - name: Ensure Rsyslog Authenticates Off-Loaded Audit Records - Remove RainerScript
      action() entries with StreamDriverAuthMode from rsyslog.conf
    ansible.builtin.shell: |
      sed -i '/^[[:space:]]*action(/ { :a; N; /)/!ba; /StreamDriverAuthMode/d }' /etc/rsyslog.conf
    changed_when: true
    when:
    - '"rsyslog" in ansible_facts.packages'
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-005015
    - NIST-800-53-AU-4(1)
    - configure_strategy
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - rsyslog_encrypt_offload_actionsendstreamdriverauthmode

  - name: Ensure Rsyslog Authenticates Off-Loaded Audit Records - Remove RainerScript
      action() entries with StreamDriverAuthMode from rsyslog.d/*.conf
    ansible.builtin.shell: |
      find /etc/rsyslog.d -type f -name "*.conf" -exec sed -i '/^[[:space:]]*action(/ { :a; N; /)/!ba; /StreamDriverAuthMode/d }' {} +
    changed_when: true
    when:
    - '"rsyslog" in ansible_facts.packages'
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-005015
    - NIST-800-53-AU-4(1)
    - configure_strategy
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - rsyslog_encrypt_offload_actionsendstreamdriverauthmode

  - name: Ensure Rsyslog Authenticates Off-Loaded Audit Records - Check if the parameter
      $ActionSendStreamDriverAuthMode is configured
    ansible.builtin.find:
      paths:
      - /etc/rsyslog.conf
      - /etc/rsyslog.d
      contains: ^\s*{{ "$ActionSendStreamDriverAuthMode"| regex_escape }}\s
    register: _sshd_config_has_parameter
    when:
    - '"rsyslog" in ansible_facts.packages'
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-005015
    - NIST-800-53-AU-4(1)
    - configure_strategy
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - rsyslog_encrypt_offload_actionsendstreamdriverauthmode

  - name: Ensure Rsyslog Authenticates Off-Loaded Audit Records - Check if the parameter
      $ActionSendStreamDriverAuthMode is configured correctly
    ansible.builtin.find:
      paths:
      - /etc/rsyslog.conf
      - /etc/rsyslog.d
      contains: ^\s*{{ "$ActionSendStreamDriverAuthMode"| regex_escape }}\sx509/name$
    register: _sshd_config_correctly
    when:
    - '"rsyslog" in ansible_facts.packages'
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-005015
    - NIST-800-53-AU-4(1)
    - configure_strategy
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - rsyslog_encrypt_offload_actionsendstreamdriverauthmode

  - name: Ensure Rsyslog Authenticates Off-Loaded Audit Records
    block:

    - name: Deduplicate values from /etc/rsyslog.conf
      ansible.builtin.lineinfile:
        path: /etc/rsyslog.conf
        create: false
        regexp: (?i)^\s*{{ "$ActionSendStreamDriverAuthMode"| regex_escape }}\s
        state: absent

    - name: Check if /etc/rsyslog.d exists
      ansible.builtin.stat:
        path: /etc/rsyslog.d
      register: _etc_rsyslog_d_exists

    - name: Check if the parameter $ActionSendStreamDriverAuthMode is present in /etc/rsyslog.d
      ansible.builtin.find:
        paths: /etc/rsyslog.d
        recurse: 'yes'
        follow: 'no'
        contains: ^\s*{{ "$ActionSendStreamDriverAuthMode"| regex_escape }}\s
      register: _etc_rsyslog_d_has_parameter
      when: _etc_rsyslog_d_exists.stat.isdir is defined and _etc_rsyslog_d_exists.stat.isdir

    - name: Remove parameter from files in /etc/rsyslog.d
      ansible.builtin.lineinfile:
        path: '{{ item.path }}'
        create: false
        regexp: (?i)^\s*{{ "$ActionSendStreamDriverAuthMode"| regex_escape }}\s
        state: absent
      with_items: '{{ _etc_rsyslog_d_has_parameter.files }}'
      when: _etc_rsyslog_d_has_parameter.matched > 0

    - name: Insert correct line to /etc/rsyslog.conf
      ansible.builtin.lineinfile:
        path: /etc/rsyslog.conf
        create: true
        regexp: (?i)^\s*{{ "$ActionSendStreamDriverAuthMode"| regex_escape }}\s
        line: $ActionSendStreamDriverAuthMode x509/name
        state: present
    when:
    - '"rsyslog" in ansible_facts.packages'
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - _sshd_config_correctly.matched == 0 or _sshd_config_has_parameter.matched !=
      1
    tags:
    - DISA-STIG-OL09-00-005015
    - NIST-800-53-AU-4(1)
    - configure_strategy
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - rsyslog_encrypt_offload_actionsendstreamdriverauthmode

  - name: Ensure Rsyslog Encrypts Off-Loaded Audit Records - Ensure /etc/rsyslog.conf
      exists
    ansible.builtin.file:
      path: /etc/rsyslog.conf
      state: touch
      modification_time: preserve
      access_time: preserve
    when:
    - '"rsyslog" in ansible_facts.packages'
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-005020
    - NIST-800-53-AU-4(1)
    - configure_strategy
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - rsyslog_encrypt_offload_actionsendstreamdrivermode

  - name: Ensure Rsyslog Encrypts Off-Loaded Audit Records - Ensure /etc/rsyslog.d
      directory exists
    ansible.builtin.file:
      path: /etc/rsyslog.d
      state: directory
    when:
    - '"rsyslog" in ansible_facts.packages'
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-005020
    - NIST-800-53-AU-4(1)
    - configure_strategy
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - rsyslog_encrypt_offload_actionsendstreamdrivermode

  - name: Ensure Rsyslog Encrypts Off-Loaded Audit Records - Remove RainerScript action()
      entries with StreamDriverMode from rsyslog.conf
    ansible.builtin.shell: |
      sed -i '/^[[:space:]]*action(/ { :a; N; /)/!ba; /StreamDriverMode/d }' /etc/rsyslog.conf
    changed_when: true
    when:
    - '"rsyslog" in ansible_facts.packages'
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-005020
    - NIST-800-53-AU-4(1)
    - configure_strategy
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - rsyslog_encrypt_offload_actionsendstreamdrivermode

  - name: Ensure Rsyslog Encrypts Off-Loaded Audit Records - Remove RainerScript action()
      entries with StreamDriverMode from rsyslog.d/*.conf
    ansible.builtin.shell: |
      find /etc/rsyslog.d -type f -name "*.conf" -exec sed -i '/^[[:space:]]*action(/ { :a; N; /)/!ba; /StreamDriverMode/d }' {} +
    changed_when: true
    when:
    - '"rsyslog" in ansible_facts.packages'
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-005020
    - NIST-800-53-AU-4(1)
    - configure_strategy
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - rsyslog_encrypt_offload_actionsendstreamdrivermode

  - name: Ensure Rsyslog Encrypts Off-Loaded Audit Records - Check if the parameter
      $ActionSendStreamDriverMode is configured
    ansible.builtin.find:
      paths:
      - /etc/rsyslog.conf
      - /etc/rsyslog.d
      contains: ^\s*{{ "$ActionSendStreamDriverMode"| regex_escape }}
    register: _sshd_config_has_parameter
    when:
    - '"rsyslog" in ansible_facts.packages'
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-005020
    - NIST-800-53-AU-4(1)
    - configure_strategy
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - rsyslog_encrypt_offload_actionsendstreamdrivermode

  - name: Ensure Rsyslog Encrypts Off-Loaded Audit Records - Check if the parameter
      $ActionSendStreamDriverMode is configured correctly
    ansible.builtin.find:
      paths:
      - /etc/rsyslog.conf
      - /etc/rsyslog.d
      contains: ^\s*{{ "$ActionSendStreamDriverMode"| regex_escape }} 1$
    register: _sshd_config_correctly
    when:
    - '"rsyslog" in ansible_facts.packages'
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-005020
    - NIST-800-53-AU-4(1)
    - configure_strategy
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - rsyslog_encrypt_offload_actionsendstreamdrivermode

  - name: Ensure Rsyslog Encrypts Off-Loaded Audit Records
    block:

    - name: Deduplicate values from /etc/rsyslog.conf
      ansible.builtin.lineinfile:
        path: /etc/rsyslog.conf
        create: false
        regexp: '(?i)^\s*{{ "$ActionSendStreamDriverMode"| regex_escape }} '
        state: absent

    - name: Check if /etc/rsyslog.d exists
      ansible.builtin.stat:
        path: /etc/rsyslog.d
      register: _etc_rsyslog_d_exists

    - name: Check if the parameter $ActionSendStreamDriverMode is present in /etc/rsyslog.d
      ansible.builtin.find:
        paths: /etc/rsyslog.d
        recurse: 'yes'
        follow: 'no'
        contains: '^\s*{{ "$ActionSendStreamDriverMode"| regex_escape }} '
      register: _etc_rsyslog_d_has_parameter
      when: _etc_rsyslog_d_exists.stat.isdir is defined and _etc_rsyslog_d_exists.stat.isdir

    - name: Remove parameter from files in /etc/rsyslog.d
      ansible.builtin.lineinfile:
        path: '{{ item.path }}'
        create: false
        regexp: '(?i)^\s*{{ "$ActionSendStreamDriverMode"| regex_escape }} '
        state: absent
      with_items: '{{ _etc_rsyslog_d_has_parameter.files }}'
      when: _etc_rsyslog_d_has_parameter.matched > 0

    - name: Insert correct line to /etc/rsyslog.conf
      ansible.builtin.lineinfile:
        path: /etc/rsyslog.conf
        create: true
        regexp: '(?i)^\s*{{ "$ActionSendStreamDriverMode"| regex_escape }} '
        line: $ActionSendStreamDriverMode 1
        state: present
    when:
    - '"rsyslog" in ansible_facts.packages'
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - _sshd_config_correctly.matched == 0 or _sshd_config_has_parameter.matched !=
      1
    tags:
    - DISA-STIG-OL09-00-005020
    - NIST-800-53-AU-4(1)
    - configure_strategy
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - rsyslog_encrypt_offload_actionsendstreamdrivermode

  - name: Ensure Rsyslog Encrypts Off-Loaded Audit Records - Ensure /etc/rsyslog.conf
      exists
    ansible.builtin.file:
      path: /etc/rsyslog.conf
      state: touch
      modification_time: preserve
      access_time: preserve
    when:
    - '"rsyslog" in ansible_facts.packages'
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-005025
    - NIST-800-53-AU-4(1)
    - configure_strategy
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - rsyslog_encrypt_offload_defaultnetstreamdriver

  - name: Ensure Rsyslog Encrypts Off-Loaded Audit Records - Ensure /etc/rsyslog.d
      directory exists
    ansible.builtin.file:
      path: /etc/rsyslog.d
      state: directory
    when:
    - '"rsyslog" in ansible_facts.packages'
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-005025
    - NIST-800-53-AU-4(1)
    - configure_strategy
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - rsyslog_encrypt_offload_defaultnetstreamdriver

  - name: Ensure Rsyslog Encrypts Off-Loaded Audit Records - Remove RainerScript global()
      entries with DefaultNetstreamDriver from rsyslog.conf
    ansible.builtin.shell: |
      sed -i '/^[[:space:]]*global(/ { :a; N; /)/!ba; /DefaultNetstreamDriver/d }' /etc/rsyslog.conf
    changed_when: true
    when:
    - '"rsyslog" in ansible_facts.packages'
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-005025
    - NIST-800-53-AU-4(1)
    - configure_strategy
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - rsyslog_encrypt_offload_defaultnetstreamdriver

  - name: Ensure Rsyslog Encrypts Off-Loaded Audit Records - Remove RainerScript global()
      entries with DefaultNetstreamDriver from rsyslog.d/*.conf
    ansible.builtin.shell: |
      find /etc/rsyslog.d -type f -name "*.conf" -exec sed -i '/^[[:space:]]*global(/ { :a; N; /)/!ba; /DefaultNetstreamDriver/d }' {} +
    changed_when: true
    when:
    - '"rsyslog" in ansible_facts.packages'
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-005025
    - NIST-800-53-AU-4(1)
    - configure_strategy
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - rsyslog_encrypt_offload_defaultnetstreamdriver

  - name: Ensure Rsyslog Encrypts Off-Loaded Audit Records - Check if the parameter
      $DefaultNetstreamDriver is configured
    ansible.builtin.find:
      paths:
      - /etc/rsyslog.conf
      - /etc/rsyslog.d
      contains: ^\s*{{ "$DefaultNetstreamDriver"| regex_escape }}
    register: _sshd_config_has_parameter
    when:
    - '"rsyslog" in ansible_facts.packages'
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-005025
    - NIST-800-53-AU-4(1)
    - configure_strategy
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - rsyslog_encrypt_offload_defaultnetstreamdriver

  - name: Ensure Rsyslog Encrypts Off-Loaded Audit Records - Check if the parameter
      $DefaultNetstreamDriver is configured correctly
    ansible.builtin.find:
      paths:
      - /etc/rsyslog.conf
      - /etc/rsyslog.d
      contains: ^\s*{{ "$DefaultNetstreamDriver"| regex_escape }} gtls$
    register: _sshd_config_correctly
    when:
    - '"rsyslog" in ansible_facts.packages'
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-005025
    - NIST-800-53-AU-4(1)
    - configure_strategy
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - rsyslog_encrypt_offload_defaultnetstreamdriver

  - name: Ensure Rsyslog Encrypts Off-Loaded Audit Records
    block:

    - name: Deduplicate values from /etc/rsyslog.conf
      ansible.builtin.lineinfile:
        path: /etc/rsyslog.conf
        create: false
        regexp: '(?i)^\s*{{ "$DefaultNetstreamDriver"| regex_escape }} '
        state: absent

    - name: Check if /etc/rsyslog.d exists
      ansible.builtin.stat:
        path: /etc/rsyslog.d
      register: _etc_rsyslog_d_exists

    - name: Check if the parameter $DefaultNetstreamDriver is present in /etc/rsyslog.d
      ansible.builtin.find:
        paths: /etc/rsyslog.d
        recurse: 'yes'
        follow: 'no'
        contains: '^\s*{{ "$DefaultNetstreamDriver"| regex_escape }} '
      register: _etc_rsyslog_d_has_parameter
      when: _etc_rsyslog_d_exists.stat.isdir is defined and _etc_rsyslog_d_exists.stat.isdir

    - name: Remove parameter from files in /etc/rsyslog.d
      ansible.builtin.lineinfile:
        path: '{{ item.path }}'
        create: false
        regexp: '(?i)^\s*{{ "$DefaultNetstreamDriver"| regex_escape }} '
        state: absent
      with_items: '{{ _etc_rsyslog_d_has_parameter.files }}'
      when: _etc_rsyslog_d_has_parameter.matched > 0

    - name: Insert correct line to /etc/rsyslog.conf
      ansible.builtin.lineinfile:
        path: /etc/rsyslog.conf
        create: true
        regexp: '(?i)^\s*{{ "$DefaultNetstreamDriver"| regex_escape }} '
        line: $DefaultNetstreamDriver gtls
        state: present
    when:
    - '"rsyslog" in ansible_facts.packages'
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - _sshd_config_correctly.matched == 0 or _sshd_config_has_parameter.matched !=
      1
    tags:
    - DISA-STIG-OL09-00-005025
    - NIST-800-53-AU-4(1)
    - configure_strategy
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - rsyslog_encrypt_offload_defaultnetstreamdriver

  - name: 'Ensure remote access methods are monitored in Rsyslog: Set facts'
    ansible.builtin.set_fact:
      conf_files:
      - /etc/rsyslog.conf
      remote_methods:
      - selector: auth.*
        regexp: ^[^#]*auth\.\*.*$
        location: /var/log/secure
      - selector: authpriv.*
        regexp: ^[^#]*authpriv\.\*.*$
        location: /var/log/secure
      - selector: daemon.*
        regexp: ^[^#]*daemon\.\*.*$
        location: /var/log/messages
    when:
    - '"rsyslog" in ansible_facts.packages'
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-005000
    - NIST-800-53-AC-17(1)
    - configure_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - no_reboot_needed
    - rsyslog_remote_access_monitoring

  - name: 'Ensure remote access methods are monitored in Rsyslog: Ensure rsyslog.conf
      exists'
    ansible.builtin.file:
      path: '{{ conf_files.0 }}'
      state: touch
      access_time: preserve
      modification_time: preserve
    when:
    - '"rsyslog" in ansible_facts.packages'
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-005000
    - NIST-800-53-AC-17(1)
    - configure_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - no_reboot_needed
    - rsyslog_remote_access_monitoring

  - name: 'Ensure remote access methods are monitored in Rsyslog: Gather conf.d files'
    ansible.builtin.find:
      patterns:
      - '*.conf'
      paths:
      - /etc/rsyslog.d
    register: rsyslogd
    when:
    - '"rsyslog" in ansible_facts.packages'
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-005000
    - NIST-800-53-AC-17(1)
    - configure_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - no_reboot_needed
    - rsyslog_remote_access_monitoring

  - name: 'Ensure remote access methods are monitored in Rsyslog: Set conf file(s)'
    ansible.builtin.set_fact:
      conf_files: '{{ conf_files + [item.path] }}'
    loop: '{{ rsyslogd.files }}'
    when:
    - '"rsyslog" in ansible_facts.packages'
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - rsyslogd.matched > 0
    tags:
    - DISA-STIG-OL09-00-005000
    - NIST-800-53-AC-17(1)
    - configure_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - no_reboot_needed
    - rsyslog_remote_access_monitoring

  - name: 'Ensure remote access methods are monitored in Rsyslog: Check for existing
      values'
    ansible.builtin.lineinfile:
      path: '{{ item.1 }}'
      regexp: '{{ item.0.regexp }}'
      state: absent
    check_mode: true
    changed_when: false
    register: remote_method_values
    loop: '{{ remote_methods|product(conf_files)|list }}'
    when:
    - '"rsyslog" in ansible_facts.packages'
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-005000
    - NIST-800-53-AC-17(1)
    - configure_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - no_reboot_needed
    - rsyslog_remote_access_monitoring

  - name: 'Ensure remote access methods are monitored in Rsyslog: Configure'
    ansible.builtin.lineinfile:
      path: /etc/rsyslog.conf
      line: '{{ item.item.0.selector }} {{ item.item.0.location }}'
      insertafter: ^.*\/var\/log\/secure.*$
      create: true
    loop: '{{ remote_method_values.results }}'
    when:
    - '"rsyslog" in ansible_facts.packages'
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - item.found == 0
    tags:
    - DISA-STIG-OL09-00-005000
    - NIST-800-53-AC-17(1)
    - configure_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - no_reboot_needed
    - rsyslog_remote_access_monitoring

  - name: Ensure rsyslog Does Not Accept Remote Messages Unless Acting As Log Server
      - Define Rsyslog Config Lines Regex in Legacy Syntax
    ansible.builtin.set_fact:
      rsyslog_listen_legacy_regex: ^\s*\$(((Input(TCP|RELP)|UDP)ServerRun)|ModLoad\s+(imtcp|imudp|imrelp))
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-005030
    - NIST-800-53-CM-6(a)
    - NIST-800-53-CM-7(a)
    - NIST-800-53-CM-7(b)
    - configure_strategy
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - rsyslog_nolisten

  - name: Ensure rsyslog Does Not Accept Remote Messages Unless Acting As Log Server
      - Search for Legacy Config Lines in Rsyslog Main Config File
    ansible.builtin.find:
      paths: /etc
      pattern: rsyslog.conf
      contains: '{{ rsyslog_listen_legacy_regex }}'
    register: rsyslog_listen_legacy_main_file
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-005030
    - NIST-800-53-CM-6(a)
    - NIST-800-53-CM-7(a)
    - NIST-800-53-CM-7(b)
    - configure_strategy
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - rsyslog_nolisten

  - name: Ensure rsyslog Does Not Accept Remote Messages Unless Acting As Log Server
      - Search for Legacy Config Lines in Rsyslog Include Files
    ansible.builtin.find:
      paths: /etc/rsyslog.d/
      pattern: '*.conf'
      contains: '{{ rsyslog_listen_legacy_regex }}'
    register: rsyslog_listen_legacy_include_files
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-005030
    - NIST-800-53-CM-6(a)
    - NIST-800-53-CM-7(a)
    - NIST-800-53-CM-7(b)
    - configure_strategy
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - rsyslog_nolisten

  - name: Ensure rsyslog Does Not Accept Remote Messages Unless Acting As Log Server
      - Assemble List of Config Files With Listen Lines in Legacy Syntax
    ansible.builtin.set_fact:
      rsyslog_legacy_remote_listen_files: '{{ rsyslog_listen_legacy_main_file.files
        | map(attribute=''path'') | list + rsyslog_listen_legacy_include_files.files
        | map(attribute=''path'') | list }}'
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-005030
    - NIST-800-53-CM-6(a)
    - NIST-800-53-CM-7(a)
    - NIST-800-53-CM-7(b)
    - configure_strategy
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - rsyslog_nolisten

  - name: Ensure rsyslog Does Not Accept Remote Messages Unless Acting As Log Server
      - Comment Listen Config Lines Wherever Defined Using Legacy Syntax
    ansible.builtin.replace:
      path: '{{ item }}'
      regexp: '{{ rsyslog_listen_legacy_regex }}'
      replace: '# \1'
    loop: '{{ rsyslog_legacy_remote_listen_files }}'
    register: rsyslog_listen_legacy_comment
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - rsyslog_legacy_remote_listen_files | length > 0
    tags:
    - DISA-STIG-OL09-00-005030
    - NIST-800-53-CM-6(a)
    - NIST-800-53-CM-7(a)
    - NIST-800-53-CM-7(b)
    - configure_strategy
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - rsyslog_nolisten

  - name: Ensure rsyslog Does Not Accept Remote Messages Unless Acting As Log Server
      - Define Rsyslog Config Lines Regex in RainerScript Syntax
    ansible.builtin.set_fact:
      rsyslog_listen_rainer_regex: ^\s*(module|input)\((load|type)="(imtcp|imudp)".*$
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-005030
    - NIST-800-53-CM-6(a)
    - NIST-800-53-CM-7(a)
    - NIST-800-53-CM-7(b)
    - configure_strategy
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - rsyslog_nolisten

  - name: Ensure rsyslog Does Not Accept Remote Messages Unless Acting As Log Server
      - Search for RainerScript Config Lines in Rsyslog Main Config File
    ansible.builtin.find:
      paths: /etc
      pattern: rsyslog.conf
      contains: '{{ rsyslog_listen_rainer_regex }}'
    register: rsyslog_rainer_remote_main_file
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-005030
    - NIST-800-53-CM-6(a)
    - NIST-800-53-CM-7(a)
    - NIST-800-53-CM-7(b)
    - configure_strategy
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - rsyslog_nolisten

  - name: Ensure rsyslog Does Not Accept Remote Messages Unless Acting As Log Server
      - Search for RainerScript Config Lines in Rsyslog Include Files
    ansible.builtin.find:
      paths: /etc/rsyslog.d/
      pattern: '*.conf'
      contains: '{{ rsyslog_listen_rainer_regex }}'
    register: rsyslog_rainer_remote_include_files
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-005030
    - NIST-800-53-CM-6(a)
    - NIST-800-53-CM-7(a)
    - NIST-800-53-CM-7(b)
    - configure_strategy
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - rsyslog_nolisten

  - name: Ensure rsyslog Does Not Accept Remote Messages Unless Acting As Log Server
      - Assemble List of Config Files With Listen Lines in RainerScript
    ansible.builtin.set_fact:
      rsyslog_rainer_remote_listen_files: '{{ rsyslog_rainer_remote_main_file.files
        | map(attribute=''path'') | list + rsyslog_rainer_remote_include_files.files
        | map(attribute=''path'') | list }}'
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-005030
    - NIST-800-53-CM-6(a)
    - NIST-800-53-CM-7(a)
    - NIST-800-53-CM-7(b)
    - configure_strategy
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - rsyslog_nolisten

  - name: Ensure rsyslog Does Not Accept Remote Messages Unless Acting As Log Server
      - Comment Listen Config Lines Wherever Defined Using RainerScript
    ansible.builtin.replace:
      path: '{{ item }}'
      regexp: '{{ rsyslog_listen_rainer_regex }}'
      replace: '# \1'
    loop: '{{ rsyslog_rainer_remote_listen_files }}'
    register: rsyslog_listen_rainer_comment
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - rsyslog_rainer_remote_listen_files | length > 0
    tags:
    - DISA-STIG-OL09-00-005030
    - NIST-800-53-CM-6(a)
    - NIST-800-53-CM-7(a)
    - NIST-800-53-CM-7(b)
    - configure_strategy
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - rsyslog_nolisten

  - name: Ensure rsyslog Does Not Accept Remote Messages Unless Acting As Log Server
      - Restart Rsyslog if Any Line Were Commented Out
    ansible.builtin.service:
      name: rsyslog
      state: restarted
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - rsyslog_listen_legacy_comment is changed or rsyslog_listen_rainer_comment is
      changed
    tags:
    - DISA-STIG-OL09-00-005030
    - NIST-800-53-CM-6(a)
    - NIST-800-53-CM-7(a)
    - NIST-800-53-CM-7(b)
    - configure_strategy
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - rsyslog_nolisten

  - name: Set rsyslog remote loghost
    ansible.builtin.lineinfile:
      dest: /etc/rsyslog.conf
      regexp: ^\*\.\*
      line: '*.* @@{{ rsyslog_remote_loghost_address }}'
      create: true
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-005005
    - NIST-800-53-AU-4(1)
    - NIST-800-53-AU-9(2)
    - NIST-800-53-CM-6(a)
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy
    - rsyslog_remote_loghost

  - name: Ensure System is Not Acting as a Network Sniffer - Gather network interfaces
    ansible.builtin.command:
      cmd: ip -o link show
    register: network_interfaces
    when: ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman",
      "container"]
    tags:
    - DISA-STIG-OL09-00-006004
    - NIST-800-53-CM-6(a)
    - NIST-800-53-CM-7(2)
    - NIST-800-53-CM-7(a)
    - NIST-800-53-CM-7(b)
    - NIST-800-53-MA-3
    - PCI-DSSv4-1.4
    - PCI-DSSv4-1.4.5
    - low_complexity
    - low_disruption
    - medium_severity
    - network_sniffer_disabled
    - no_reboot_needed
    - restrict_strategy

  - name: Ensure System is Not Acting as a Network Sniffer - Disable promiscuous mode
    ansible.builtin.command:
      cmd: ip link set dev {{ (item.split(':')[1] | trim).split('@')[0] }} multicast
        off promisc off
    loop: '{{ network_interfaces.stdout_lines }}'
    when:
    - ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"]
    - network_interfaces.stdout_lines is defined and item.split(':') | length >= 3
    tags:
    - DISA-STIG-OL09-00-006004
    - NIST-800-53-CM-6(a)
    - NIST-800-53-CM-7(2)
    - NIST-800-53-CM-7(a)
    - NIST-800-53-CM-7(b)
    - NIST-800-53-MA-3
    - PCI-DSSv4-1.4
    - PCI-DSSv4-1.4.5
    - low_complexity
    - low_disruption
    - medium_severity
    - network_sniffer_disabled
    - no_reboot_needed
    - restrict_strategy

  - name: Setting unquoted shell-style assignment of 'FirewallBackend' to 'nftables'
      in '/etc/firewalld/firewalld.conf'
    block:

    - name: Check for duplicate values
      ansible.builtin.lineinfile:
        path: /etc/firewalld/firewalld.conf
        create: true
        regexp: (?i)^\s*FirewallBackend=
        state: absent
      check_mode: true
      changed_when: false
      register: dupes

    - name: Deduplicate values from /etc/firewalld/firewalld.conf
      ansible.builtin.lineinfile:
        path: /etc/firewalld/firewalld.conf
        create: true
        regexp: (?i)^\s*FirewallBackend=
        state: absent
      when: dupes.found is defined and dupes.found > 1

    - name: Insert correct line to /etc/firewalld/firewalld.conf
      ansible.builtin.lineinfile:
        path: /etc/firewalld/firewalld.conf
        create: true
        regexp: (?i)^\s*FirewallBackend=
        line: FirewallBackend=nftables
        state: present
        insertbefore: ^# FirewallBackend
        validate: /usr/bin/bash -n %s
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - '"firewalld" in ansible_facts.packages'
    tags:
    - DISA-STIG-OL09-00-006000
    - NIST-800-53-SC-5
    - firewalld-backend
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Configure Accepting Router Advertisements on All IPv6 Interfaces - Set fact
      for sysctl paths
    ansible.builtin.set_fact:
      sysctl_paths:
      - /etc/sysctl.d/
      - /run/sysctl.d/
      - /usr/local/lib/sysctl.d/
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-006040
    - NIST-800-171-3.1.20
    - NIST-800-53-CM-6(a)
    - NIST-800-53-CM-7(a)
    - NIST-800-53-CM-7(b)
    - disable_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - reboot_required
    - sysctl_net_ipv6_conf_all_accept_ra

  - name: Configure Accepting Router Advertisements on All IPv6 Interfaces - Find
      all files that contain net.ipv6.conf.all.accept_ra
    ansible.builtin.shell:
      cmd: find -L {{ sysctl_paths | join(" ") }} -type f -name '*.conf' | xargs grep
        -HP '^\s*net.ipv6.conf.all.accept_ra\s*=\s*.*$'
    register: find_all_values
    check_mode: false
    changed_when: false
    failed_when: false
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-006040
    - NIST-800-171-3.1.20
    - NIST-800-53-CM-6(a)
    - NIST-800-53-CM-7(a)
    - NIST-800-53-CM-7(b)
    - disable_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - reboot_required
    - sysctl_net_ipv6_conf_all_accept_ra

  - name: Configure Accepting Router Advertisements on All IPv6 Interfaces - Find
      all files that set net.ipv6.conf.all.accept_ra to correct value
    ansible.builtin.shell:
      cmd: find -L {{ sysctl_paths | join(" ") }} -type f -name '*.conf' | xargs grep
        -HP '^\s*net.ipv6.conf.all.accept_ra\s*=\s*{{ sysctl_net_ipv6_conf_all_accept_ra_value
        }}$'
    register: find_correct_value
    check_mode: false
    changed_when: false
    failed_when: false
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-006040
    - NIST-800-171-3.1.20
    - NIST-800-53-CM-6(a)
    - NIST-800-53-CM-7(a)
    - NIST-800-53-CM-7(b)
    - disable_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - reboot_required
    - sysctl_net_ipv6_conf_all_accept_ra

  - name: Configure Accepting Router Advertisements on All IPv6 Interfaces - Comment
      out any occurrences of net.ipv6.conf.all.accept_ra from config files
    ansible.builtin.replace:
      path: '{{ item | split(":") | first }}'
      regexp: ^[\s]*net.ipv6.conf.all.accept_ra
      replace: '#net.ipv6.conf.all.accept_ra'
    loop: '{{ find_all_values.stdout_lines }}'
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - find_correct_value.stdout_lines | length == 0 or find_all_values.stdout_lines
      | length > find_correct_value.stdout_lines | length
    tags:
    - DISA-STIG-OL09-00-006040
    - NIST-800-171-3.1.20
    - NIST-800-53-CM-6(a)
    - NIST-800-53-CM-7(a)
    - NIST-800-53-CM-7(b)
    - disable_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - reboot_required
    - sysctl_net_ipv6_conf_all_accept_ra

  - name: Configure Accepting Router Advertisements on All IPv6 Interfaces - Comment
      out any occurrences of net.ipv6.conf.all.accept_ra from /etc/sysctl.conf
    ansible.builtin.replace:
      path: '{{ item }}'
      regexp: ^[\s]*net.ipv6.conf.all.accept_ra
      replace: '#net.ipv6.conf.all.accept_ra'
    with_fileglob:
    - /etc/sysctl.conf
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-006040
    - NIST-800-171-3.1.20
    - NIST-800-53-CM-6(a)
    - NIST-800-53-CM-7(a)
    - NIST-800-53-CM-7(b)
    - disable_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - reboot_required
    - sysctl_net_ipv6_conf_all_accept_ra

  - name: Configure Accepting Router Advertisements on All IPv6 Interfaces - Ensure
      sysctl net.ipv6.conf.all.accept_ra is set
    ansible.posix.sysctl:
      name: net.ipv6.conf.all.accept_ra
      value: '{{ sysctl_net_ipv6_conf_all_accept_ra_value }}'
      sysctl_file: /etc/sysctl.d/net_ipv6_conf_all_accept_ra.conf
      state: present
      reload: true
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-006040
    - NIST-800-171-3.1.20
    - NIST-800-53-CM-6(a)
    - NIST-800-53-CM-7(a)
    - NIST-800-53-CM-7(b)
    - disable_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - reboot_required
    - sysctl_net_ipv6_conf_all_accept_ra

  - name: Disable Accepting ICMP Redirects for All IPv6 Interfaces - Set fact for
      sysctl paths
    ansible.builtin.set_fact:
      sysctl_paths:
      - /etc/sysctl.d/
      - /run/sysctl.d/
      - /usr/local/lib/sysctl.d/
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-006041
    - NIST-800-171-3.1.20
    - NIST-800-53-CM-6(a)
    - NIST-800-53-CM-6(b)
    - NIST-800-53-CM-6.1(iv)
    - NIST-800-53-CM-7(a)
    - NIST-800-53-CM-7(b)
    - disable_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - reboot_required
    - sysctl_net_ipv6_conf_all_accept_redirects

  - name: Disable Accepting ICMP Redirects for All IPv6 Interfaces - Find all files
      that contain net.ipv6.conf.all.accept_redirects
    ansible.builtin.shell:
      cmd: find -L {{ sysctl_paths | join(" ") }} -type f -name '*.conf' | xargs grep
        -HP '^\s*net.ipv6.conf.all.accept_redirects\s*=\s*.*$'
    register: find_all_values
    check_mode: false
    changed_when: false
    failed_when: false
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-006041
    - NIST-800-171-3.1.20
    - NIST-800-53-CM-6(a)
    - NIST-800-53-CM-6(b)
    - NIST-800-53-CM-6.1(iv)
    - NIST-800-53-CM-7(a)
    - NIST-800-53-CM-7(b)
    - disable_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - reboot_required
    - sysctl_net_ipv6_conf_all_accept_redirects

  - name: Disable Accepting ICMP Redirects for All IPv6 Interfaces - Find all files
      that set net.ipv6.conf.all.accept_redirects to correct value
    ansible.builtin.shell:
      cmd: find -L {{ sysctl_paths | join(" ") }} -type f -name '*.conf' | xargs grep
        -HP '^\s*net.ipv6.conf.all.accept_redirects\s*=\s*{{ sysctl_net_ipv6_conf_all_accept_redirects_value
        }}$'
    register: find_correct_value
    check_mode: false
    changed_when: false
    failed_when: false
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-006041
    - NIST-800-171-3.1.20
    - NIST-800-53-CM-6(a)
    - NIST-800-53-CM-6(b)
    - NIST-800-53-CM-6.1(iv)
    - NIST-800-53-CM-7(a)
    - NIST-800-53-CM-7(b)
    - disable_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - reboot_required
    - sysctl_net_ipv6_conf_all_accept_redirects

  - name: Disable Accepting ICMP Redirects for All IPv6 Interfaces - Comment out any
      occurrences of net.ipv6.conf.all.accept_redirects from config files
    ansible.builtin.replace:
      path: '{{ item | split(":") | first }}'
      regexp: ^[\s]*net.ipv6.conf.all.accept_redirects
      replace: '#net.ipv6.conf.all.accept_redirects'
    loop: '{{ find_all_values.stdout_lines }}'
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - find_correct_value.stdout_lines | length == 0 or find_all_values.stdout_lines
      | length > find_correct_value.stdout_lines | length
    tags:
    - DISA-STIG-OL09-00-006041
    - NIST-800-171-3.1.20
    - NIST-800-53-CM-6(a)
    - NIST-800-53-CM-6(b)
    - NIST-800-53-CM-6.1(iv)
    - NIST-800-53-CM-7(a)
    - NIST-800-53-CM-7(b)
    - disable_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - reboot_required
    - sysctl_net_ipv6_conf_all_accept_redirects

  - name: Disable Accepting ICMP Redirects for All IPv6 Interfaces - Comment out any
      occurrences of net.ipv6.conf.all.accept_redirects from /etc/sysctl.conf
    ansible.builtin.replace:
      path: '{{ item }}'
      regexp: ^[\s]*net.ipv6.conf.all.accept_redirects
      replace: '#net.ipv6.conf.all.accept_redirects'
    with_fileglob:
    - /etc/sysctl.conf
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-006041
    - NIST-800-171-3.1.20
    - NIST-800-53-CM-6(a)
    - NIST-800-53-CM-6(b)
    - NIST-800-53-CM-6.1(iv)
    - NIST-800-53-CM-7(a)
    - NIST-800-53-CM-7(b)
    - disable_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - reboot_required
    - sysctl_net_ipv6_conf_all_accept_redirects

  - name: Disable Accepting ICMP Redirects for All IPv6 Interfaces - Ensure sysctl
      net.ipv6.conf.all.accept_redirects is set
    ansible.posix.sysctl:
      name: net.ipv6.conf.all.accept_redirects
      value: '{{ sysctl_net_ipv6_conf_all_accept_redirects_value }}'
      sysctl_file: /etc/sysctl.d/net_ipv6_conf_all_accept_redirects.conf
      state: present
      reload: true
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-006041
    - NIST-800-171-3.1.20
    - NIST-800-53-CM-6(a)
    - NIST-800-53-CM-6(b)
    - NIST-800-53-CM-6.1(iv)
    - NIST-800-53-CM-7(a)
    - NIST-800-53-CM-7(b)
    - disable_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - reboot_required
    - sysctl_net_ipv6_conf_all_accept_redirects

  - name: Disable Kernel Parameter for Accepting Source-Routed Packets on all IPv6
      Interfaces - Set fact for sysctl paths
    ansible.builtin.set_fact:
      sysctl_paths:
      - /etc/sysctl.d/
      - /run/sysctl.d/
      - /usr/local/lib/sysctl.d/
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-006042
    - NIST-800-171-3.1.20
    - NIST-800-53-CM-6(a)
    - NIST-800-53-CM-7(a)
    - NIST-800-53-CM-7(b)
    - disable_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - reboot_required
    - sysctl_net_ipv6_conf_all_accept_source_route

  - name: Disable Kernel Parameter for Accepting Source-Routed Packets on all IPv6
      Interfaces - Find all files that contain net.ipv6.conf.all.accept_source_route
    ansible.builtin.shell:
      cmd: find -L {{ sysctl_paths | join(" ") }} -type f -name '*.conf' | xargs grep
        -HP '^\s*net.ipv6.conf.all.accept_source_route\s*=\s*.*$'
    register: find_all_values
    check_mode: false
    changed_when: false
    failed_when: false
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-006042
    - NIST-800-171-3.1.20
    - NIST-800-53-CM-6(a)
    - NIST-800-53-CM-7(a)
    - NIST-800-53-CM-7(b)
    - disable_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - reboot_required
    - sysctl_net_ipv6_conf_all_accept_source_route

  - name: Disable Kernel Parameter for Accepting Source-Routed Packets on all IPv6
      Interfaces - Find all files that set net.ipv6.conf.all.accept_source_route to
      correct value
    ansible.builtin.shell:
      cmd: find -L {{ sysctl_paths | join(" ") }} -type f -name '*.conf' | xargs grep
        -HP '^\s*net.ipv6.conf.all.accept_source_route\s*=\s*{{ sysctl_net_ipv6_conf_all_accept_source_route_value
        }}$'
    register: find_correct_value
    check_mode: false
    changed_when: false
    failed_when: false
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-006042
    - NIST-800-171-3.1.20
    - NIST-800-53-CM-6(a)
    - NIST-800-53-CM-7(a)
    - NIST-800-53-CM-7(b)
    - disable_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - reboot_required
    - sysctl_net_ipv6_conf_all_accept_source_route

  - name: Disable Kernel Parameter for Accepting Source-Routed Packets on all IPv6
      Interfaces - Comment out any occurrences of net.ipv6.conf.all.accept_source_route
      from config files
    ansible.builtin.replace:
      path: '{{ item | split(":") | first }}'
      regexp: ^[\s]*net.ipv6.conf.all.accept_source_route
      replace: '#net.ipv6.conf.all.accept_source_route'
    loop: '{{ find_all_values.stdout_lines }}'
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - find_correct_value.stdout_lines | length == 0 or find_all_values.stdout_lines
      | length > find_correct_value.stdout_lines | length
    tags:
    - DISA-STIG-OL09-00-006042
    - NIST-800-171-3.1.20
    - NIST-800-53-CM-6(a)
    - NIST-800-53-CM-7(a)
    - NIST-800-53-CM-7(b)
    - disable_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - reboot_required
    - sysctl_net_ipv6_conf_all_accept_source_route

  - name: Disable Kernel Parameter for Accepting Source-Routed Packets on all IPv6
      Interfaces - Comment out any occurrences of net.ipv6.conf.all.accept_source_route
      from /etc/sysctl.conf
    ansible.builtin.replace:
      path: '{{ item }}'
      regexp: ^[\s]*net.ipv6.conf.all.accept_source_route
      replace: '#net.ipv6.conf.all.accept_source_route'
    with_fileglob:
    - /etc/sysctl.conf
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-006042
    - NIST-800-171-3.1.20
    - NIST-800-53-CM-6(a)
    - NIST-800-53-CM-7(a)
    - NIST-800-53-CM-7(b)
    - disable_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - reboot_required
    - sysctl_net_ipv6_conf_all_accept_source_route

  - name: Disable Kernel Parameter for Accepting Source-Routed Packets on all IPv6
      Interfaces - Ensure sysctl net.ipv6.conf.all.accept_source_route is set
    ansible.posix.sysctl:
      name: net.ipv6.conf.all.accept_source_route
      value: '{{ sysctl_net_ipv6_conf_all_accept_source_route_value }}'
      sysctl_file: /etc/sysctl.d/net_ipv6_conf_all_accept_source_route.conf
      state: present
      reload: true
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-006042
    - NIST-800-171-3.1.20
    - NIST-800-53-CM-6(a)
    - NIST-800-53-CM-7(a)
    - NIST-800-53-CM-7(b)
    - disable_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - reboot_required
    - sysctl_net_ipv6_conf_all_accept_source_route

  - name: Disable Kernel Parameter for IPv6 Forwarding - Set fact for sysctl paths
    ansible.builtin.set_fact:
      sysctl_paths:
      - /etc/sysctl.d/
      - /run/sysctl.d/
      - /usr/local/lib/sysctl.d/
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-006043
    - NIST-800-53-CM-6(a)
    - NIST-800-53-CM-6(b)
    - NIST-800-53-CM-6.1(iv)
    - NIST-800-53-CM-7(a)
    - NIST-800-53-CM-7(b)
    - disable_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - reboot_required
    - sysctl_net_ipv6_conf_all_forwarding

  - name: Disable Kernel Parameter for IPv6 Forwarding - Find all files that contain
      net.ipv6.conf.all.forwarding
    ansible.builtin.shell:
      cmd: find -L {{ sysctl_paths | join(" ") }} -type f -name '*.conf' | xargs grep
        -HP '^\s*net.ipv6.conf.all.forwarding\s*=\s*.*$'
    register: find_all_values
    check_mode: false
    changed_when: false
    failed_when: false
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-006043
    - NIST-800-53-CM-6(a)
    - NIST-800-53-CM-6(b)
    - NIST-800-53-CM-6.1(iv)
    - NIST-800-53-CM-7(a)
    - NIST-800-53-CM-7(b)
    - disable_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - reboot_required
    - sysctl_net_ipv6_conf_all_forwarding

  - name: Disable Kernel Parameter for IPv6 Forwarding - Find all files that set net.ipv6.conf.all.forwarding
      to correct value
    ansible.builtin.shell:
      cmd: find -L {{ sysctl_paths | join(" ") }} -type f -name '*.conf' | xargs grep
        -HP '^\s*net.ipv6.conf.all.forwarding\s*=\s*{{ sysctl_net_ipv6_conf_all_forwarding_value
        }}$'
    register: find_correct_value
    check_mode: false
    changed_when: false
    failed_when: false
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-006043
    - NIST-800-53-CM-6(a)
    - NIST-800-53-CM-6(b)
    - NIST-800-53-CM-6.1(iv)
    - NIST-800-53-CM-7(a)
    - NIST-800-53-CM-7(b)
    - disable_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - reboot_required
    - sysctl_net_ipv6_conf_all_forwarding

  - name: Disable Kernel Parameter for IPv6 Forwarding - Comment out any occurrences
      of net.ipv6.conf.all.forwarding from config files
    ansible.builtin.replace:
      path: '{{ item | split(":") | first }}'
      regexp: ^[\s]*net.ipv6.conf.all.forwarding
      replace: '#net.ipv6.conf.all.forwarding'
    loop: '{{ find_all_values.stdout_lines }}'
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - find_correct_value.stdout_lines | length == 0 or find_all_values.stdout_lines
      | length > find_correct_value.stdout_lines | length
    tags:
    - DISA-STIG-OL09-00-006043
    - NIST-800-53-CM-6(a)
    - NIST-800-53-CM-6(b)
    - NIST-800-53-CM-6.1(iv)
    - NIST-800-53-CM-7(a)
    - NIST-800-53-CM-7(b)
    - disable_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - reboot_required
    - sysctl_net_ipv6_conf_all_forwarding

  - name: Disable Kernel Parameter for IPv6 Forwarding - Comment out any occurrences
      of net.ipv6.conf.all.forwarding from /etc/sysctl.conf
    ansible.builtin.replace:
      path: '{{ item }}'
      regexp: ^[\s]*net.ipv6.conf.all.forwarding
      replace: '#net.ipv6.conf.all.forwarding'
    with_fileglob:
    - /etc/sysctl.conf
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-006043
    - NIST-800-53-CM-6(a)
    - NIST-800-53-CM-6(b)
    - NIST-800-53-CM-6.1(iv)
    - NIST-800-53-CM-7(a)
    - NIST-800-53-CM-7(b)
    - disable_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - reboot_required
    - sysctl_net_ipv6_conf_all_forwarding

  - name: Disable Kernel Parameter for IPv6 Forwarding - Ensure sysctl net.ipv6.conf.all.forwarding
      is set
    ansible.posix.sysctl:
      name: net.ipv6.conf.all.forwarding
      value: '{{ sysctl_net_ipv6_conf_all_forwarding_value }}'
      sysctl_file: /etc/sysctl.d/net_ipv6_conf_all_forwarding.conf
      state: present
      reload: true
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-006043
    - NIST-800-53-CM-6(a)
    - NIST-800-53-CM-6(b)
    - NIST-800-53-CM-6.1(iv)
    - NIST-800-53-CM-7(a)
    - NIST-800-53-CM-7(b)
    - disable_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - reboot_required
    - sysctl_net_ipv6_conf_all_forwarding

  - name: Disable Accepting Router Advertisements on all IPv6 Interfaces by Default
      - Set fact for sysctl paths
    ansible.builtin.set_fact:
      sysctl_paths:
      - /etc/sysctl.d/
      - /run/sysctl.d/
      - /usr/local/lib/sysctl.d/
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-006044
    - NIST-800-171-3.1.20
    - NIST-800-53-CM-6(a)
    - NIST-800-53-CM-7(a)
    - NIST-800-53-CM-7(b)
    - disable_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - reboot_required
    - sysctl_net_ipv6_conf_default_accept_ra

  - name: Disable Accepting Router Advertisements on all IPv6 Interfaces by Default
      - Find all files that contain net.ipv6.conf.default.accept_ra
    ansible.builtin.shell:
      cmd: find -L {{ sysctl_paths | join(" ") }} -type f -name '*.conf' | xargs grep
        -HP '^\s*net.ipv6.conf.default.accept_ra\s*=\s*.*$'
    register: find_all_values
    check_mode: false
    changed_when: false
    failed_when: false
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-006044
    - NIST-800-171-3.1.20
    - NIST-800-53-CM-6(a)
    - NIST-800-53-CM-7(a)
    - NIST-800-53-CM-7(b)
    - disable_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - reboot_required
    - sysctl_net_ipv6_conf_default_accept_ra

  - name: Disable Accepting Router Advertisements on all IPv6 Interfaces by Default
      - Find all files that set net.ipv6.conf.default.accept_ra to correct value
    ansible.builtin.shell:
      cmd: find -L {{ sysctl_paths | join(" ") }} -type f -name '*.conf' | xargs grep
        -HP '^\s*net.ipv6.conf.default.accept_ra\s*=\s*{{ sysctl_net_ipv6_conf_default_accept_ra_value
        }}$'
    register: find_correct_value
    check_mode: false
    changed_when: false
    failed_when: false
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-006044
    - NIST-800-171-3.1.20
    - NIST-800-53-CM-6(a)
    - NIST-800-53-CM-7(a)
    - NIST-800-53-CM-7(b)
    - disable_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - reboot_required
    - sysctl_net_ipv6_conf_default_accept_ra

  - name: Disable Accepting Router Advertisements on all IPv6 Interfaces by Default
      - Comment out any occurrences of net.ipv6.conf.default.accept_ra from config
      files
    ansible.builtin.replace:
      path: '{{ item | split(":") | first }}'
      regexp: ^[\s]*net.ipv6.conf.default.accept_ra
      replace: '#net.ipv6.conf.default.accept_ra'
    loop: '{{ find_all_values.stdout_lines }}'
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - find_correct_value.stdout_lines | length == 0 or find_all_values.stdout_lines
      | length > find_correct_value.stdout_lines | length
    tags:
    - DISA-STIG-OL09-00-006044
    - NIST-800-171-3.1.20
    - NIST-800-53-CM-6(a)
    - NIST-800-53-CM-7(a)
    - NIST-800-53-CM-7(b)
    - disable_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - reboot_required
    - sysctl_net_ipv6_conf_default_accept_ra

  - name: Disable Accepting Router Advertisements on all IPv6 Interfaces by Default
      - Comment out any occurrences of net.ipv6.conf.default.accept_ra from /etc/sysctl.conf
    ansible.builtin.replace:
      path: '{{ item }}'
      regexp: ^[\s]*net.ipv6.conf.default.accept_ra
      replace: '#net.ipv6.conf.default.accept_ra'
    with_fileglob:
    - /etc/sysctl.conf
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-006044
    - NIST-800-171-3.1.20
    - NIST-800-53-CM-6(a)
    - NIST-800-53-CM-7(a)
    - NIST-800-53-CM-7(b)
    - disable_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - reboot_required
    - sysctl_net_ipv6_conf_default_accept_ra

  - name: Disable Accepting Router Advertisements on all IPv6 Interfaces by Default
      - Ensure sysctl net.ipv6.conf.default.accept_ra is set
    ansible.posix.sysctl:
      name: net.ipv6.conf.default.accept_ra
      value: '{{ sysctl_net_ipv6_conf_default_accept_ra_value }}'
      sysctl_file: /etc/sysctl.d/net_ipv6_conf_default_accept_ra.conf
      state: present
      reload: true
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-006044
    - NIST-800-171-3.1.20
    - NIST-800-53-CM-6(a)
    - NIST-800-53-CM-7(a)
    - NIST-800-53-CM-7(b)
    - disable_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - reboot_required
    - sysctl_net_ipv6_conf_default_accept_ra

  - name: Disable Kernel Parameter for Accepting ICMP Redirects by Default on IPv6
      Interfaces - Set fact for sysctl paths
    ansible.builtin.set_fact:
      sysctl_paths:
      - /etc/sysctl.d/
      - /run/sysctl.d/
      - /usr/local/lib/sysctl.d/
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-006045
    - NIST-800-171-3.1.20
    - NIST-800-53-CM-6(a)
    - NIST-800-53-CM-7(a)
    - NIST-800-53-CM-7(b)
    - disable_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - reboot_required
    - sysctl_net_ipv6_conf_default_accept_redirects

  - name: Disable Kernel Parameter for Accepting ICMP Redirects by Default on IPv6
      Interfaces - Find all files that contain net.ipv6.conf.default.accept_redirects
    ansible.builtin.shell:
      cmd: find -L {{ sysctl_paths | join(" ") }} -type f -name '*.conf' | xargs grep
        -HP '^\s*net.ipv6.conf.default.accept_redirects\s*=\s*.*$'
    register: find_all_values
    check_mode: false
    changed_when: false
    failed_when: false
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-006045
    - NIST-800-171-3.1.20
    - NIST-800-53-CM-6(a)
    - NIST-800-53-CM-7(a)
    - NIST-800-53-CM-7(b)
    - disable_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - reboot_required
    - sysctl_net_ipv6_conf_default_accept_redirects

  - name: Disable Kernel Parameter for Accepting ICMP Redirects by Default on IPv6
      Interfaces - Find all files that set net.ipv6.conf.default.accept_redirects
      to correct value
    ansible.builtin.shell:
      cmd: find -L {{ sysctl_paths | join(" ") }} -type f -name '*.conf' | xargs grep
        -HP '^\s*net.ipv6.conf.default.accept_redirects\s*=\s*{{ sysctl_net_ipv6_conf_default_accept_redirects_value
        }}$'
    register: find_correct_value
    check_mode: false
    changed_when: false
    failed_when: false
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-006045
    - NIST-800-171-3.1.20
    - NIST-800-53-CM-6(a)
    - NIST-800-53-CM-7(a)
    - NIST-800-53-CM-7(b)
    - disable_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - reboot_required
    - sysctl_net_ipv6_conf_default_accept_redirects

  - name: Disable Kernel Parameter for Accepting ICMP Redirects by Default on IPv6
      Interfaces - Comment out any occurrences of net.ipv6.conf.default.accept_redirects
      from config files
    ansible.builtin.replace:
      path: '{{ item | split(":") | first }}'
      regexp: ^[\s]*net.ipv6.conf.default.accept_redirects
      replace: '#net.ipv6.conf.default.accept_redirects'
    loop: '{{ find_all_values.stdout_lines }}'
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - find_correct_value.stdout_lines | length == 0 or find_all_values.stdout_lines
      | length > find_correct_value.stdout_lines | length
    tags:
    - DISA-STIG-OL09-00-006045
    - NIST-800-171-3.1.20
    - NIST-800-53-CM-6(a)
    - NIST-800-53-CM-7(a)
    - NIST-800-53-CM-7(b)
    - disable_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - reboot_required
    - sysctl_net_ipv6_conf_default_accept_redirects

  - name: Disable Kernel Parameter for Accepting ICMP Redirects by Default on IPv6
      Interfaces - Comment out any occurrences of net.ipv6.conf.default.accept_redirects
      from /etc/sysctl.conf
    ansible.builtin.replace:
      path: '{{ item }}'
      regexp: ^[\s]*net.ipv6.conf.default.accept_redirects
      replace: '#net.ipv6.conf.default.accept_redirects'
    with_fileglob:
    - /etc/sysctl.conf
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-006045
    - NIST-800-171-3.1.20
    - NIST-800-53-CM-6(a)
    - NIST-800-53-CM-7(a)
    - NIST-800-53-CM-7(b)
    - disable_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - reboot_required
    - sysctl_net_ipv6_conf_default_accept_redirects

  - name: Disable Kernel Parameter for Accepting ICMP Redirects by Default on IPv6
      Interfaces - Ensure sysctl net.ipv6.conf.default.accept_redirects is set
    ansible.posix.sysctl:
      name: net.ipv6.conf.default.accept_redirects
      value: '{{ sysctl_net_ipv6_conf_default_accept_redirects_value }}'
      sysctl_file: /etc/sysctl.d/net_ipv6_conf_default_accept_redirects.conf
      state: present
      reload: true
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-006045
    - NIST-800-171-3.1.20
    - NIST-800-53-CM-6(a)
    - NIST-800-53-CM-7(a)
    - NIST-800-53-CM-7(b)
    - disable_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - reboot_required
    - sysctl_net_ipv6_conf_default_accept_redirects

  - name: Disable Kernel Parameter for Accepting Source-Routed Packets on IPv6 Interfaces
      by Default - Set fact for sysctl paths
    ansible.builtin.set_fact:
      sysctl_paths:
      - /etc/sysctl.d/
      - /run/sysctl.d/
      - /usr/local/lib/sysctl.d/
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-006046
    - NIST-800-171-3.1.20
    - NIST-800-53-CM-6(a)
    - NIST-800-53-CM-6(b)
    - NIST-800-53-CM-6.1(iv)
    - NIST-800-53-CM-7(a)
    - NIST-800-53-CM-7(b)
    - PCI-DSS-Req-1.4.3
    - PCI-DSSv4-1.4
    - PCI-DSSv4-1.4.2
    - disable_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - reboot_required
    - sysctl_net_ipv6_conf_default_accept_source_route

  - name: Disable Kernel Parameter for Accepting Source-Routed Packets on IPv6 Interfaces
      by Default - Find all files that contain net.ipv6.conf.default.accept_source_route
    ansible.builtin.shell:
      cmd: find -L {{ sysctl_paths | join(" ") }} -type f -name '*.conf' | xargs grep
        -HP '^\s*net.ipv6.conf.default.accept_source_route\s*=\s*.*$'
    register: find_all_values
    check_mode: false
    changed_when: false
    failed_when: false
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-006046
    - NIST-800-171-3.1.20
    - NIST-800-53-CM-6(a)
    - NIST-800-53-CM-6(b)
    - NIST-800-53-CM-6.1(iv)
    - NIST-800-53-CM-7(a)
    - NIST-800-53-CM-7(b)
    - PCI-DSS-Req-1.4.3
    - PCI-DSSv4-1.4
    - PCI-DSSv4-1.4.2
    - disable_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - reboot_required
    - sysctl_net_ipv6_conf_default_accept_source_route

  - name: Disable Kernel Parameter for Accepting Source-Routed Packets on IPv6 Interfaces
      by Default - Find all files that set net.ipv6.conf.default.accept_source_route
      to correct value
    ansible.builtin.shell:
      cmd: find -L {{ sysctl_paths | join(" ") }} -type f -name '*.conf' | xargs grep
        -HP '^\s*net.ipv6.conf.default.accept_source_route\s*=\s*{{ sysctl_net_ipv6_conf_default_accept_source_route_value
        }}$'
    register: find_correct_value
    check_mode: false
    changed_when: false
    failed_when: false
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-006046
    - NIST-800-171-3.1.20
    - NIST-800-53-CM-6(a)
    - NIST-800-53-CM-6(b)
    - NIST-800-53-CM-6.1(iv)
    - NIST-800-53-CM-7(a)
    - NIST-800-53-CM-7(b)
    - PCI-DSS-Req-1.4.3
    - PCI-DSSv4-1.4
    - PCI-DSSv4-1.4.2
    - disable_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - reboot_required
    - sysctl_net_ipv6_conf_default_accept_source_route

  - name: Disable Kernel Parameter for Accepting Source-Routed Packets on IPv6 Interfaces
      by Default - Comment out any occurrences of net.ipv6.conf.default.accept_source_route
      from config files
    ansible.builtin.replace:
      path: '{{ item | split(":") | first }}'
      regexp: ^[\s]*net.ipv6.conf.default.accept_source_route
      replace: '#net.ipv6.conf.default.accept_source_route'
    loop: '{{ find_all_values.stdout_lines }}'
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - find_correct_value.stdout_lines | length == 0 or find_all_values.stdout_lines
      | length > find_correct_value.stdout_lines | length
    tags:
    - DISA-STIG-OL09-00-006046
    - NIST-800-171-3.1.20
    - NIST-800-53-CM-6(a)
    - NIST-800-53-CM-6(b)
    - NIST-800-53-CM-6.1(iv)
    - NIST-800-53-CM-7(a)
    - NIST-800-53-CM-7(b)
    - PCI-DSS-Req-1.4.3
    - PCI-DSSv4-1.4
    - PCI-DSSv4-1.4.2
    - disable_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - reboot_required
    - sysctl_net_ipv6_conf_default_accept_source_route

  - name: Disable Kernel Parameter for Accepting Source-Routed Packets on IPv6 Interfaces
      by Default - Comment out any occurrences of net.ipv6.conf.default.accept_source_route
      from /etc/sysctl.conf
    ansible.builtin.replace:
      path: '{{ item }}'
      regexp: ^[\s]*net.ipv6.conf.default.accept_source_route
      replace: '#net.ipv6.conf.default.accept_source_route'
    with_fileglob:
    - /etc/sysctl.conf
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-006046
    - NIST-800-171-3.1.20
    - NIST-800-53-CM-6(a)
    - NIST-800-53-CM-6(b)
    - NIST-800-53-CM-6.1(iv)
    - NIST-800-53-CM-7(a)
    - NIST-800-53-CM-7(b)
    - PCI-DSS-Req-1.4.3
    - PCI-DSSv4-1.4
    - PCI-DSSv4-1.4.2
    - disable_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - reboot_required
    - sysctl_net_ipv6_conf_default_accept_source_route

  - name: Disable Kernel Parameter for Accepting Source-Routed Packets on IPv6 Interfaces
      by Default - Ensure sysctl net.ipv6.conf.default.accept_source_route is set
    ansible.posix.sysctl:
      name: net.ipv6.conf.default.accept_source_route
      value: '{{ sysctl_net_ipv6_conf_default_accept_source_route_value }}'
      sysctl_file: /etc/sysctl.d/net_ipv6_conf_default_accept_source_route.conf
      state: present
      reload: true
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-006046
    - NIST-800-171-3.1.20
    - NIST-800-53-CM-6(a)
    - NIST-800-53-CM-6(b)
    - NIST-800-53-CM-6.1(iv)
    - NIST-800-53-CM-7(a)
    - NIST-800-53-CM-7(b)
    - PCI-DSS-Req-1.4.3
    - PCI-DSSv4-1.4
    - PCI-DSSv4-1.4.2
    - disable_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - reboot_required
    - sysctl_net_ipv6_conf_default_accept_source_route

  - name: Disable Accepting ICMP Redirects for All IPv4 Interfaces - Set fact for
      sysctl paths
    ansible.builtin.set_fact:
      sysctl_paths:
      - /etc/sysctl.d/
      - /run/sysctl.d/
      - /usr/local/lib/sysctl.d/
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - CJIS-5.10.1.1
    - DISA-STIG-OL09-00-006020
    - NIST-800-171-3.1.20
    - NIST-800-53-CM-6(a)
    - NIST-800-53-CM-7(a)
    - NIST-800-53-CM-7(b)
    - NIST-800-53-SC-7(a)
    - disable_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - reboot_required
    - sysctl_net_ipv4_conf_all_accept_redirects

  - name: Disable Accepting ICMP Redirects for All IPv4 Interfaces - Find all files
      that contain net.ipv4.conf.all.accept_redirects
    ansible.builtin.shell:
      cmd: find -L {{ sysctl_paths | join(" ") }} -type f -name '*.conf' | xargs grep
        -HP '^\s*net.ipv4.conf.all.accept_redirects\s*=\s*.*$'
    register: find_all_values
    check_mode: false
    changed_when: false
    failed_when: false
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - CJIS-5.10.1.1
    - DISA-STIG-OL09-00-006020
    - NIST-800-171-3.1.20
    - NIST-800-53-CM-6(a)
    - NIST-800-53-CM-7(a)
    - NIST-800-53-CM-7(b)
    - NIST-800-53-SC-7(a)
    - disable_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - reboot_required
    - sysctl_net_ipv4_conf_all_accept_redirects

  - name: Disable Accepting ICMP Redirects for All IPv4 Interfaces - Find all files
      that set net.ipv4.conf.all.accept_redirects to correct value
    ansible.builtin.shell:
      cmd: find -L {{ sysctl_paths | join(" ") }} -type f -name '*.conf' | xargs grep
        -HP '^\s*net.ipv4.conf.all.accept_redirects\s*=\s*{{ sysctl_net_ipv4_conf_all_accept_redirects_value
        }}$'
    register: find_correct_value
    check_mode: false
    changed_when: false
    failed_when: false
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - CJIS-5.10.1.1
    - DISA-STIG-OL09-00-006020
    - NIST-800-171-3.1.20
    - NIST-800-53-CM-6(a)
    - NIST-800-53-CM-7(a)
    - NIST-800-53-CM-7(b)
    - NIST-800-53-SC-7(a)
    - disable_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - reboot_required
    - sysctl_net_ipv4_conf_all_accept_redirects

  - name: Disable Accepting ICMP Redirects for All IPv4 Interfaces - Comment out any
      occurrences of net.ipv4.conf.all.accept_redirects from config files
    ansible.builtin.replace:
      path: '{{ item | split(":") | first }}'
      regexp: ^[\s]*net.ipv4.conf.all.accept_redirects
      replace: '#net.ipv4.conf.all.accept_redirects'
    loop: '{{ find_all_values.stdout_lines }}'
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - find_correct_value.stdout_lines | length == 0 or find_all_values.stdout_lines
      | length > find_correct_value.stdout_lines | length
    tags:
    - CJIS-5.10.1.1
    - DISA-STIG-OL09-00-006020
    - NIST-800-171-3.1.20
    - NIST-800-53-CM-6(a)
    - NIST-800-53-CM-7(a)
    - NIST-800-53-CM-7(b)
    - NIST-800-53-SC-7(a)
    - disable_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - reboot_required
    - sysctl_net_ipv4_conf_all_accept_redirects

  - name: Disable Accepting ICMP Redirects for All IPv4 Interfaces - Comment out any
      occurrences of net.ipv4.conf.all.accept_redirects from /etc/sysctl.conf
    ansible.builtin.replace:
      path: '{{ item }}'
      regexp: ^[\s]*net.ipv4.conf.all.accept_redirects
      replace: '#net.ipv4.conf.all.accept_redirects'
    with_fileglob:
    - /etc/sysctl.conf
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - CJIS-5.10.1.1
    - DISA-STIG-OL09-00-006020
    - NIST-800-171-3.1.20
    - NIST-800-53-CM-6(a)
    - NIST-800-53-CM-7(a)
    - NIST-800-53-CM-7(b)
    - NIST-800-53-SC-7(a)
    - disable_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - reboot_required
    - sysctl_net_ipv4_conf_all_accept_redirects

  - name: Disable Accepting ICMP Redirects for All IPv4 Interfaces - Ensure sysctl
      net.ipv4.conf.all.accept_redirects is set
    ansible.posix.sysctl:
      name: net.ipv4.conf.all.accept_redirects
      value: '{{ sysctl_net_ipv4_conf_all_accept_redirects_value }}'
      sysctl_file: /etc/sysctl.d/net_ipv4_conf_all_accept_redirects.conf
      state: present
      reload: true
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - CJIS-5.10.1.1
    - DISA-STIG-OL09-00-006020
    - NIST-800-171-3.1.20
    - NIST-800-53-CM-6(a)
    - NIST-800-53-CM-7(a)
    - NIST-800-53-CM-7(b)
    - NIST-800-53-SC-7(a)
    - disable_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - reboot_required
    - sysctl_net_ipv4_conf_all_accept_redirects

  - name: Disable Kernel Parameter for Accepting Source-Routed Packets on all IPv4
      Interfaces - Set fact for sysctl paths
    ansible.builtin.set_fact:
      sysctl_paths:
      - /etc/sysctl.d/
      - /run/sysctl.d/
      - /usr/local/lib/sysctl.d/
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-006021
    - NIST-800-171-3.1.20
    - NIST-800-53-CM-6(a)
    - NIST-800-53-CM-7(a)
    - NIST-800-53-CM-7(b)
    - NIST-800-53-SC-5
    - NIST-800-53-SC-7(a)
    - disable_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - reboot_required
    - sysctl_net_ipv4_conf_all_accept_source_route

  - name: Disable Kernel Parameter for Accepting Source-Routed Packets on all IPv4
      Interfaces - Find all files that contain net.ipv4.conf.all.accept_source_route
    ansible.builtin.shell:
      cmd: find -L {{ sysctl_paths | join(" ") }} -type f -name '*.conf' | xargs grep
        -HP '^\s*net.ipv4.conf.all.accept_source_route\s*=\s*.*$'
    register: find_all_values
    check_mode: false
    changed_when: false
    failed_when: false
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-006021
    - NIST-800-171-3.1.20
    - NIST-800-53-CM-6(a)
    - NIST-800-53-CM-7(a)
    - NIST-800-53-CM-7(b)
    - NIST-800-53-SC-5
    - NIST-800-53-SC-7(a)
    - disable_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - reboot_required
    - sysctl_net_ipv4_conf_all_accept_source_route

  - name: Disable Kernel Parameter for Accepting Source-Routed Packets on all IPv4
      Interfaces - Find all files that set net.ipv4.conf.all.accept_source_route to
      correct value
    ansible.builtin.shell:
      cmd: find -L {{ sysctl_paths | join(" ") }} -type f -name '*.conf' | xargs grep
        -HP '^\s*net.ipv4.conf.all.accept_source_route\s*=\s*{{ sysctl_net_ipv4_conf_all_accept_source_route_value
        }}$'
    register: find_correct_value
    check_mode: false
    changed_when: false
    failed_when: false
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-006021
    - NIST-800-171-3.1.20
    - NIST-800-53-CM-6(a)
    - NIST-800-53-CM-7(a)
    - NIST-800-53-CM-7(b)
    - NIST-800-53-SC-5
    - NIST-800-53-SC-7(a)
    - disable_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - reboot_required
    - sysctl_net_ipv4_conf_all_accept_source_route

  - name: Disable Kernel Parameter for Accepting Source-Routed Packets on all IPv4
      Interfaces - Comment out any occurrences of net.ipv4.conf.all.accept_source_route
      from config files
    ansible.builtin.replace:
      path: '{{ item | split(":") | first }}'
      regexp: ^[\s]*net.ipv4.conf.all.accept_source_route
      replace: '#net.ipv4.conf.all.accept_source_route'
    loop: '{{ find_all_values.stdout_lines }}'
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - find_correct_value.stdout_lines | length == 0 or find_all_values.stdout_lines
      | length > find_correct_value.stdout_lines | length
    tags:
    - DISA-STIG-OL09-00-006021
    - NIST-800-171-3.1.20
    - NIST-800-53-CM-6(a)
    - NIST-800-53-CM-7(a)
    - NIST-800-53-CM-7(b)
    - NIST-800-53-SC-5
    - NIST-800-53-SC-7(a)
    - disable_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - reboot_required
    - sysctl_net_ipv4_conf_all_accept_source_route

  - name: Disable Kernel Parameter for Accepting Source-Routed Packets on all IPv4
      Interfaces - Comment out any occurrences of net.ipv4.conf.all.accept_source_route
      from /etc/sysctl.conf
    ansible.builtin.replace:
      path: '{{ item }}'
      regexp: ^[\s]*net.ipv4.conf.all.accept_source_route
      replace: '#net.ipv4.conf.all.accept_source_route'
    with_fileglob:
    - /etc/sysctl.conf
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-006021
    - NIST-800-171-3.1.20
    - NIST-800-53-CM-6(a)
    - NIST-800-53-CM-7(a)
    - NIST-800-53-CM-7(b)
    - NIST-800-53-SC-5
    - NIST-800-53-SC-7(a)
    - disable_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - reboot_required
    - sysctl_net_ipv4_conf_all_accept_source_route

  - name: Disable Kernel Parameter for Accepting Source-Routed Packets on all IPv4
      Interfaces - Ensure sysctl net.ipv4.conf.all.accept_source_route is set
    ansible.posix.sysctl:
      name: net.ipv4.conf.all.accept_source_route
      value: '{{ sysctl_net_ipv4_conf_all_accept_source_route_value }}'
      sysctl_file: /etc/sysctl.d/net_ipv4_conf_all_accept_source_route.conf
      state: present
      reload: true
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-006021
    - NIST-800-171-3.1.20
    - NIST-800-53-CM-6(a)
    - NIST-800-53-CM-7(a)
    - NIST-800-53-CM-7(b)
    - NIST-800-53-SC-5
    - NIST-800-53-SC-7(a)
    - disable_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - reboot_required
    - sysctl_net_ipv4_conf_all_accept_source_route

  - name: Disable Kernel Parameter for IPv4 Forwarding on all IPv4 Interfaces - Set
      fact for sysctl paths
    ansible.builtin.set_fact:
      sysctl_paths:
      - /etc/sysctl.d/
      - /run/sysctl.d/
      - /usr/local/lib/sysctl.d/
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-006028
    - NIST-800-53-CM-6(b)
    - disable_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - reboot_required
    - sysctl_net_ipv4_conf_all_forwarding

  - name: Disable Kernel Parameter for IPv4 Forwarding on all IPv4 Interfaces - Find
      all files that contain net.ipv4.conf.all.forwarding
    ansible.builtin.shell:
      cmd: find -L {{ sysctl_paths | join(" ") }} -type f -name '*.conf' | xargs grep
        -HP '^\s*net.ipv4.conf.all.forwarding\s*=\s*.*$'
    register: find_all_values
    check_mode: false
    changed_when: false
    failed_when: false
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-006028
    - NIST-800-53-CM-6(b)
    - disable_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - reboot_required
    - sysctl_net_ipv4_conf_all_forwarding

  - name: Disable Kernel Parameter for IPv4 Forwarding on all IPv4 Interfaces - Find
      all files that set net.ipv4.conf.all.forwarding to correct value
    ansible.builtin.shell:
      cmd: find -L {{ sysctl_paths | join(" ") }} -type f -name '*.conf' | xargs grep
        -HP '^\s*net.ipv4.conf.all.forwarding\s*=\s*{{ sysctl_net_ipv4_conf_all_forwarding_value
        }}$'
    register: find_correct_value
    check_mode: false
    changed_when: false
    failed_when: false
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-006028
    - NIST-800-53-CM-6(b)
    - disable_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - reboot_required
    - sysctl_net_ipv4_conf_all_forwarding

  - name: Disable Kernel Parameter for IPv4 Forwarding on all IPv4 Interfaces - Comment
      out any occurrences of net.ipv4.conf.all.forwarding from config files
    ansible.builtin.replace:
      path: '{{ item | split(":") | first }}'
      regexp: ^[\s]*net.ipv4.conf.all.forwarding
      replace: '#net.ipv4.conf.all.forwarding'
    loop: '{{ find_all_values.stdout_lines }}'
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - find_correct_value.stdout_lines | length == 0 or find_all_values.stdout_lines
      | length > find_correct_value.stdout_lines | length
    tags:
    - DISA-STIG-OL09-00-006028
    - NIST-800-53-CM-6(b)
    - disable_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - reboot_required
    - sysctl_net_ipv4_conf_all_forwarding

  - name: Disable Kernel Parameter for IPv4 Forwarding on all IPv4 Interfaces - Comment
      out any occurrences of net.ipv4.conf.all.forwarding from /etc/sysctl.conf
    ansible.builtin.replace:
      path: '{{ item }}'
      regexp: ^[\s]*net.ipv4.conf.all.forwarding
      replace: '#net.ipv4.conf.all.forwarding'
    with_fileglob:
    - /etc/sysctl.conf
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-006028
    - NIST-800-53-CM-6(b)
    - disable_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - reboot_required
    - sysctl_net_ipv4_conf_all_forwarding

  - name: Disable Kernel Parameter for IPv4 Forwarding on all IPv4 Interfaces - Ensure
      sysctl net.ipv4.conf.all.forwarding is set
    ansible.posix.sysctl:
      name: net.ipv4.conf.all.forwarding
      value: '{{ sysctl_net_ipv4_conf_all_forwarding_value }}'
      sysctl_file: /etc/sysctl.d/net_ipv4_conf_all_forwarding.conf
      state: present
      reload: true
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-006028
    - NIST-800-53-CM-6(b)
    - disable_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - reboot_required
    - sysctl_net_ipv4_conf_all_forwarding

  - name: Enable Kernel Parameter to Log Martian Packets on all IPv4 Interfaces -
      Set fact for sysctl paths
    ansible.builtin.set_fact:
      sysctl_paths:
      - /etc/sysctl.d/
      - /run/sysctl.d/
      - /usr/local/lib/sysctl.d/
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-006022
    - NIST-800-171-3.1.20
    - NIST-800-53-CM-7(a)
    - NIST-800-53-CM-7(b)
    - NIST-800-53-SC-5(3)(a)
    - disable_strategy
    - low_complexity
    - medium_disruption
    - reboot_required
    - sysctl_net_ipv4_conf_all_log_martians
    - unknown_severity

  - name: Enable Kernel Parameter to Log Martian Packets on all IPv4 Interfaces -
      Find all files that contain net.ipv4.conf.all.log_martians
    ansible.builtin.shell:
      cmd: find -L {{ sysctl_paths | join(" ") }} -type f -name '*.conf' | xargs grep
        -HP '^\s*net.ipv4.conf.all.log_martians\s*=\s*.*$'
    register: find_all_values
    check_mode: false
    changed_when: false
    failed_when: false
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-006022
    - NIST-800-171-3.1.20
    - NIST-800-53-CM-7(a)
    - NIST-800-53-CM-7(b)
    - NIST-800-53-SC-5(3)(a)
    - disable_strategy
    - low_complexity
    - medium_disruption
    - reboot_required
    - sysctl_net_ipv4_conf_all_log_martians
    - unknown_severity

  - name: Enable Kernel Parameter to Log Martian Packets on all IPv4 Interfaces -
      Find all files that set net.ipv4.conf.all.log_martians to correct value
    ansible.builtin.shell:
      cmd: find -L {{ sysctl_paths | join(" ") }} -type f -name '*.conf' | xargs grep
        -HP '^\s*net.ipv4.conf.all.log_martians\s*=\s*{{ sysctl_net_ipv4_conf_all_log_martians_value
        }}$'
    register: find_correct_value
    check_mode: false
    changed_when: false
    failed_when: false
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-006022
    - NIST-800-171-3.1.20
    - NIST-800-53-CM-7(a)
    - NIST-800-53-CM-7(b)
    - NIST-800-53-SC-5(3)(a)
    - disable_strategy
    - low_complexity
    - medium_disruption
    - reboot_required
    - sysctl_net_ipv4_conf_all_log_martians
    - unknown_severity

  - name: Enable Kernel Parameter to Log Martian Packets on all IPv4 Interfaces -
      Comment out any occurrences of net.ipv4.conf.all.log_martians from config files
    ansible.builtin.replace:
      path: '{{ item | split(":") | first }}'
      regexp: ^[\s]*net.ipv4.conf.all.log_martians
      replace: '#net.ipv4.conf.all.log_martians'
    loop: '{{ find_all_values.stdout_lines }}'
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - find_correct_value.stdout_lines | length == 0 or find_all_values.stdout_lines
      | length > find_correct_value.stdout_lines | length
    tags:
    - DISA-STIG-OL09-00-006022
    - NIST-800-171-3.1.20
    - NIST-800-53-CM-7(a)
    - NIST-800-53-CM-7(b)
    - NIST-800-53-SC-5(3)(a)
    - disable_strategy
    - low_complexity
    - medium_disruption
    - reboot_required
    - sysctl_net_ipv4_conf_all_log_martians
    - unknown_severity

  - name: Enable Kernel Parameter to Log Martian Packets on all IPv4 Interfaces -
      Comment out any occurrences of net.ipv4.conf.all.log_martians from /etc/sysctl.conf
    ansible.builtin.replace:
      path: '{{ item }}'
      regexp: ^[\s]*net.ipv4.conf.all.log_martians
      replace: '#net.ipv4.conf.all.log_martians'
    with_fileglob:
    - /etc/sysctl.conf
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-006022
    - NIST-800-171-3.1.20
    - NIST-800-53-CM-7(a)
    - NIST-800-53-CM-7(b)
    - NIST-800-53-SC-5(3)(a)
    - disable_strategy
    - low_complexity
    - medium_disruption
    - reboot_required
    - sysctl_net_ipv4_conf_all_log_martians
    - unknown_severity

  - name: Enable Kernel Parameter to Log Martian Packets on all IPv4 Interfaces -
      Ensure sysctl net.ipv4.conf.all.log_martians is set
    ansible.posix.sysctl:
      name: net.ipv4.conf.all.log_martians
      value: '{{ sysctl_net_ipv4_conf_all_log_martians_value }}'
      sysctl_file: /etc/sysctl.d/net_ipv4_conf_all_log_martians.conf
      state: present
      reload: true
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-006022
    - NIST-800-171-3.1.20
    - NIST-800-53-CM-7(a)
    - NIST-800-53-CM-7(b)
    - NIST-800-53-SC-5(3)(a)
    - disable_strategy
    - low_complexity
    - medium_disruption
    - reboot_required
    - sysctl_net_ipv4_conf_all_log_martians
    - unknown_severity

  - name: Enable Kernel Parameter to Use Reverse Path Filtering on all IPv4 Interfaces
      - Set fact for sysctl paths
    ansible.builtin.set_fact:
      sysctl_paths:
      - /etc/sysctl.d/
      - /run/sysctl.d/
      - /usr/local/lib/sysctl.d/
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-006024
    - NIST-800-171-3.1.20
    - NIST-800-53-CM-6(a)
    - NIST-800-53-CM-7(a)
    - NIST-800-53-CM-7(b)
    - NIST-800-53-SC-7(a)
    - PCI-DSS-Req-1.4.3
    - PCI-DSSv4-1.4
    - PCI-DSSv4-1.4.3
    - disable_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - reboot_required
    - sysctl_net_ipv4_conf_all_rp_filter

  - name: Enable Kernel Parameter to Use Reverse Path Filtering on all IPv4 Interfaces
      - Find all files that contain net.ipv4.conf.all.rp_filter
    ansible.builtin.shell:
      cmd: find -L {{ sysctl_paths | join(" ") }} -type f -name '*.conf' | xargs grep
        -HP '^\s*net.ipv4.conf.all.rp_filter\s*=\s*.*$'
    register: find_all_values
    check_mode: false
    changed_when: false
    failed_when: false
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-006024
    - NIST-800-171-3.1.20
    - NIST-800-53-CM-6(a)
    - NIST-800-53-CM-7(a)
    - NIST-800-53-CM-7(b)
    - NIST-800-53-SC-7(a)
    - PCI-DSS-Req-1.4.3
    - PCI-DSSv4-1.4
    - PCI-DSSv4-1.4.3
    - disable_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - reboot_required
    - sysctl_net_ipv4_conf_all_rp_filter

  - name: Enable Kernel Parameter to Use Reverse Path Filtering on all IPv4 Interfaces
      - Find all files that set net.ipv4.conf.all.rp_filter to correct value
    ansible.builtin.shell:
      cmd: find -L {{ sysctl_paths | join(" ") }} -type f -name '*.conf' | xargs grep
        -HP '^\s*net.ipv4.conf.all.rp_filter\s*=\s*{{ sysctl_net_ipv4_conf_all_rp_filter_value
        }}$'
    register: find_correct_value
    check_mode: false
    changed_when: false
    failed_when: false
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-006024
    - NIST-800-171-3.1.20
    - NIST-800-53-CM-6(a)
    - NIST-800-53-CM-7(a)
    - NIST-800-53-CM-7(b)
    - NIST-800-53-SC-7(a)
    - PCI-DSS-Req-1.4.3
    - PCI-DSSv4-1.4
    - PCI-DSSv4-1.4.3
    - disable_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - reboot_required
    - sysctl_net_ipv4_conf_all_rp_filter

  - name: Enable Kernel Parameter to Use Reverse Path Filtering on all IPv4 Interfaces
      - Comment out any occurrences of net.ipv4.conf.all.rp_filter from config files
    ansible.builtin.replace:
      path: '{{ item | split(":") | first }}'
      regexp: ^[\s]*net.ipv4.conf.all.rp_filter
      replace: '#net.ipv4.conf.all.rp_filter'
    loop: '{{ find_all_values.stdout_lines }}'
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - find_correct_value.stdout_lines | length == 0 or find_all_values.stdout_lines
      | length > find_correct_value.stdout_lines | length
    tags:
    - DISA-STIG-OL09-00-006024
    - NIST-800-171-3.1.20
    - NIST-800-53-CM-6(a)
    - NIST-800-53-CM-7(a)
    - NIST-800-53-CM-7(b)
    - NIST-800-53-SC-7(a)
    - PCI-DSS-Req-1.4.3
    - PCI-DSSv4-1.4
    - PCI-DSSv4-1.4.3
    - disable_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - reboot_required
    - sysctl_net_ipv4_conf_all_rp_filter

  - name: Enable Kernel Parameter to Use Reverse Path Filtering on all IPv4 Interfaces
      - Comment out any occurrences of net.ipv4.conf.all.rp_filter from /etc/sysctl.conf
    ansible.builtin.replace:
      path: '{{ item }}'
      regexp: ^[\s]*net.ipv4.conf.all.rp_filter
      replace: '#net.ipv4.conf.all.rp_filter'
    with_fileglob:
    - /etc/sysctl.conf
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-006024
    - NIST-800-171-3.1.20
    - NIST-800-53-CM-6(a)
    - NIST-800-53-CM-7(a)
    - NIST-800-53-CM-7(b)
    - NIST-800-53-SC-7(a)
    - PCI-DSS-Req-1.4.3
    - PCI-DSSv4-1.4
    - PCI-DSSv4-1.4.3
    - disable_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - reboot_required
    - sysctl_net_ipv4_conf_all_rp_filter

  - name: Enable Kernel Parameter to Use Reverse Path Filtering on all IPv4 Interfaces
      - Ensure sysctl net.ipv4.conf.all.rp_filter is set
    ansible.posix.sysctl:
      name: net.ipv4.conf.all.rp_filter
      value: '{{ sysctl_net_ipv4_conf_all_rp_filter_value }}'
      sysctl_file: /etc/sysctl.d/net_ipv4_conf_all_rp_filter.conf
      state: present
      reload: true
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-006024
    - NIST-800-171-3.1.20
    - NIST-800-53-CM-6(a)
    - NIST-800-53-CM-7(a)
    - NIST-800-53-CM-7(b)
    - NIST-800-53-SC-7(a)
    - PCI-DSS-Req-1.4.3
    - PCI-DSSv4-1.4
    - PCI-DSSv4-1.4.3
    - disable_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - reboot_required
    - sysctl_net_ipv4_conf_all_rp_filter

  - name: Disable Kernel Parameter for Accepting ICMP Redirects by Default on IPv4
      Interfaces - Set fact for sysctl paths
    ansible.builtin.set_fact:
      sysctl_paths:
      - /etc/sysctl.d/
      - /run/sysctl.d/
      - /usr/local/lib/sysctl.d/
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - CJIS-5.10.1.1
    - DISA-STIG-OL09-00-006025
    - NIST-800-171-3.1.20
    - NIST-800-53-CM-6(a)
    - NIST-800-53-CM-7(a)
    - NIST-800-53-CM-7(b)
    - NIST-800-53-SC-7(a)
    - PCI-DSS-Req-1.4.3
    - PCI-DSSv4-1.4
    - PCI-DSSv4-1.4.3
    - disable_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - reboot_required
    - sysctl_net_ipv4_conf_default_accept_redirects

  - name: Disable Kernel Parameter for Accepting ICMP Redirects by Default on IPv4
      Interfaces - Find all files that contain net.ipv4.conf.default.accept_redirects
    ansible.builtin.shell:
      cmd: find -L {{ sysctl_paths | join(" ") }} -type f -name '*.conf' | xargs grep
        -HP '^\s*net.ipv4.conf.default.accept_redirects\s*=\s*.*$'
    register: find_all_values
    check_mode: false
    changed_when: false
    failed_when: false
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - CJIS-5.10.1.1
    - DISA-STIG-OL09-00-006025
    - NIST-800-171-3.1.20
    - NIST-800-53-CM-6(a)
    - NIST-800-53-CM-7(a)
    - NIST-800-53-CM-7(b)
    - NIST-800-53-SC-7(a)
    - PCI-DSS-Req-1.4.3
    - PCI-DSSv4-1.4
    - PCI-DSSv4-1.4.3
    - disable_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - reboot_required
    - sysctl_net_ipv4_conf_default_accept_redirects

  - name: Disable Kernel Parameter for Accepting ICMP Redirects by Default on IPv4
      Interfaces - Find all files that set net.ipv4.conf.default.accept_redirects
      to correct value
    ansible.builtin.shell:
      cmd: find -L {{ sysctl_paths | join(" ") }} -type f -name '*.conf' | xargs grep
        -HP '^\s*net.ipv4.conf.default.accept_redirects\s*=\s*{{ sysctl_net_ipv4_conf_default_accept_redirects_value
        }}$'
    register: find_correct_value
    check_mode: false
    changed_when: false
    failed_when: false
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - CJIS-5.10.1.1
    - DISA-STIG-OL09-00-006025
    - NIST-800-171-3.1.20
    - NIST-800-53-CM-6(a)
    - NIST-800-53-CM-7(a)
    - NIST-800-53-CM-7(b)
    - NIST-800-53-SC-7(a)
    - PCI-DSS-Req-1.4.3
    - PCI-DSSv4-1.4
    - PCI-DSSv4-1.4.3
    - disable_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - reboot_required
    - sysctl_net_ipv4_conf_default_accept_redirects

  - name: Disable Kernel Parameter for Accepting ICMP Redirects by Default on IPv4
      Interfaces - Comment out any occurrences of net.ipv4.conf.default.accept_redirects
      from config files
    ansible.builtin.replace:
      path: '{{ item | split(":") | first }}'
      regexp: ^[\s]*net.ipv4.conf.default.accept_redirects
      replace: '#net.ipv4.conf.default.accept_redirects'
    loop: '{{ find_all_values.stdout_lines }}'
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - find_correct_value.stdout_lines | length == 0 or find_all_values.stdout_lines
      | length > find_correct_value.stdout_lines | length
    tags:
    - CJIS-5.10.1.1
    - DISA-STIG-OL09-00-006025
    - NIST-800-171-3.1.20
    - NIST-800-53-CM-6(a)
    - NIST-800-53-CM-7(a)
    - NIST-800-53-CM-7(b)
    - NIST-800-53-SC-7(a)
    - PCI-DSS-Req-1.4.3
    - PCI-DSSv4-1.4
    - PCI-DSSv4-1.4.3
    - disable_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - reboot_required
    - sysctl_net_ipv4_conf_default_accept_redirects

  - name: Disable Kernel Parameter for Accepting ICMP Redirects by Default on IPv4
      Interfaces - Comment out any occurrences of net.ipv4.conf.default.accept_redirects
      from /etc/sysctl.conf
    ansible.builtin.replace:
      path: '{{ item }}'
      regexp: ^[\s]*net.ipv4.conf.default.accept_redirects
      replace: '#net.ipv4.conf.default.accept_redirects'
    with_fileglob:
    - /etc/sysctl.conf
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - CJIS-5.10.1.1
    - DISA-STIG-OL09-00-006025
    - NIST-800-171-3.1.20
    - NIST-800-53-CM-6(a)
    - NIST-800-53-CM-7(a)
    - NIST-800-53-CM-7(b)
    - NIST-800-53-SC-7(a)
    - PCI-DSS-Req-1.4.3
    - PCI-DSSv4-1.4
    - PCI-DSSv4-1.4.3
    - disable_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - reboot_required
    - sysctl_net_ipv4_conf_default_accept_redirects

  - name: Disable Kernel Parameter for Accepting ICMP Redirects by Default on IPv4
      Interfaces - Ensure sysctl net.ipv4.conf.default.accept_redirects is set
    ansible.posix.sysctl:
      name: net.ipv4.conf.default.accept_redirects
      value: '{{ sysctl_net_ipv4_conf_default_accept_redirects_value }}'
      sysctl_file: /etc/sysctl.d/net_ipv4_conf_default_accept_redirects.conf
      state: present
      reload: true
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - CJIS-5.10.1.1
    - DISA-STIG-OL09-00-006025
    - NIST-800-171-3.1.20
    - NIST-800-53-CM-6(a)
    - NIST-800-53-CM-7(a)
    - NIST-800-53-CM-7(b)
    - NIST-800-53-SC-7(a)
    - PCI-DSS-Req-1.4.3
    - PCI-DSSv4-1.4
    - PCI-DSSv4-1.4.3
    - disable_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - reboot_required
    - sysctl_net_ipv4_conf_default_accept_redirects

  - name: Disable Kernel Parameter for Accepting Source-Routed Packets on IPv4 Interfaces
      by Default - Set fact for sysctl paths
    ansible.builtin.set_fact:
      sysctl_paths:
      - /etc/sysctl.d/
      - /run/sysctl.d/
      - /usr/local/lib/sysctl.d/
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - CJIS-5.10.1.1
    - DISA-STIG-OL09-00-006026
    - NIST-800-171-3.1.20
    - NIST-800-53-CM-7(a)
    - NIST-800-53-CM-7(b)
    - NIST-800-53-SC-5
    - NIST-800-53-SC-7(a)
    - disable_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - reboot_required
    - sysctl_net_ipv4_conf_default_accept_source_route

  - name: Disable Kernel Parameter for Accepting Source-Routed Packets on IPv4 Interfaces
      by Default - Find all files that contain net.ipv4.conf.default.accept_source_route
    ansible.builtin.shell:
      cmd: find -L {{ sysctl_paths | join(" ") }} -type f -name '*.conf' | xargs grep
        -HP '^\s*net.ipv4.conf.default.accept_source_route\s*=\s*.*$'
    register: find_all_values
    check_mode: false
    changed_when: false
    failed_when: false
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - CJIS-5.10.1.1
    - DISA-STIG-OL09-00-006026
    - NIST-800-171-3.1.20
    - NIST-800-53-CM-7(a)
    - NIST-800-53-CM-7(b)
    - NIST-800-53-SC-5
    - NIST-800-53-SC-7(a)
    - disable_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - reboot_required
    - sysctl_net_ipv4_conf_default_accept_source_route

  - name: Disable Kernel Parameter for Accepting Source-Routed Packets on IPv4 Interfaces
      by Default - Find all files that set net.ipv4.conf.default.accept_source_route
      to correct value
    ansible.builtin.shell:
      cmd: find -L {{ sysctl_paths | join(" ") }} -type f -name '*.conf' | xargs grep
        -HP '^\s*net.ipv4.conf.default.accept_source_route\s*=\s*{{ sysctl_net_ipv4_conf_default_accept_source_route_value
        }}$'
    register: find_correct_value
    check_mode: false
    changed_when: false
    failed_when: false
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - CJIS-5.10.1.1
    - DISA-STIG-OL09-00-006026
    - NIST-800-171-3.1.20
    - NIST-800-53-CM-7(a)
    - NIST-800-53-CM-7(b)
    - NIST-800-53-SC-5
    - NIST-800-53-SC-7(a)
    - disable_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - reboot_required
    - sysctl_net_ipv4_conf_default_accept_source_route

  - name: Disable Kernel Parameter for Accepting Source-Routed Packets on IPv4 Interfaces
      by Default - Comment out any occurrences of net.ipv4.conf.default.accept_source_route
      from config files
    ansible.builtin.replace:
      path: '{{ item | split(":") | first }}'
      regexp: ^[\s]*net.ipv4.conf.default.accept_source_route
      replace: '#net.ipv4.conf.default.accept_source_route'
    loop: '{{ find_all_values.stdout_lines }}'
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - find_correct_value.stdout_lines | length == 0 or find_all_values.stdout_lines
      | length > find_correct_value.stdout_lines | length
    tags:
    - CJIS-5.10.1.1
    - DISA-STIG-OL09-00-006026
    - NIST-800-171-3.1.20
    - NIST-800-53-CM-7(a)
    - NIST-800-53-CM-7(b)
    - NIST-800-53-SC-5
    - NIST-800-53-SC-7(a)
    - disable_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - reboot_required
    - sysctl_net_ipv4_conf_default_accept_source_route

  - name: Disable Kernel Parameter for Accepting Source-Routed Packets on IPv4 Interfaces
      by Default - Comment out any occurrences of net.ipv4.conf.default.accept_source_route
      from /etc/sysctl.conf
    ansible.builtin.replace:
      path: '{{ item }}'
      regexp: ^[\s]*net.ipv4.conf.default.accept_source_route
      replace: '#net.ipv4.conf.default.accept_source_route'
    with_fileglob:
    - /etc/sysctl.conf
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - CJIS-5.10.1.1
    - DISA-STIG-OL09-00-006026
    - NIST-800-171-3.1.20
    - NIST-800-53-CM-7(a)
    - NIST-800-53-CM-7(b)
    - NIST-800-53-SC-5
    - NIST-800-53-SC-7(a)
    - disable_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - reboot_required
    - sysctl_net_ipv4_conf_default_accept_source_route

  - name: Disable Kernel Parameter for Accepting Source-Routed Packets on IPv4 Interfaces
      by Default - Ensure sysctl net.ipv4.conf.default.accept_source_route is set
    ansible.posix.sysctl:
      name: net.ipv4.conf.default.accept_source_route
      value: '{{ sysctl_net_ipv4_conf_default_accept_source_route_value }}'
      sysctl_file: /etc/sysctl.d/net_ipv4_conf_default_accept_source_route.conf
      state: present
      reload: true
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - CJIS-5.10.1.1
    - DISA-STIG-OL09-00-006026
    - NIST-800-171-3.1.20
    - NIST-800-53-CM-7(a)
    - NIST-800-53-CM-7(b)
    - NIST-800-53-SC-5
    - NIST-800-53-SC-7(a)
    - disable_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - reboot_required
    - sysctl_net_ipv4_conf_default_accept_source_route

  - name: Enable Kernel Parameter to Log Martian Packets on all IPv4 Interfaces by
      Default - Set fact for sysctl paths
    ansible.builtin.set_fact:
      sysctl_paths:
      - /etc/sysctl.d/
      - /run/sysctl.d/
      - /usr/local/lib/sysctl.d/
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-006023
    - NIST-800-171-3.1.20
    - NIST-800-53-CM-7(a)
    - NIST-800-53-CM-7(b)
    - NIST-800-53-SC-5(3)(a)
    - disable_strategy
    - low_complexity
    - medium_disruption
    - reboot_required
    - sysctl_net_ipv4_conf_default_log_martians
    - unknown_severity

  - name: Enable Kernel Parameter to Log Martian Packets on all IPv4 Interfaces by
      Default - Find all files that contain net.ipv4.conf.default.log_martians
    ansible.builtin.shell:
      cmd: find -L {{ sysctl_paths | join(" ") }} -type f -name '*.conf' | xargs grep
        -HP '^\s*net.ipv4.conf.default.log_martians\s*=\s*.*$'
    register: find_all_values
    check_mode: false
    changed_when: false
    failed_when: false
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-006023
    - NIST-800-171-3.1.20
    - NIST-800-53-CM-7(a)
    - NIST-800-53-CM-7(b)
    - NIST-800-53-SC-5(3)(a)
    - disable_strategy
    - low_complexity
    - medium_disruption
    - reboot_required
    - sysctl_net_ipv4_conf_default_log_martians
    - unknown_severity

  - name: Enable Kernel Parameter to Log Martian Packets on all IPv4 Interfaces by
      Default - Find all files that set net.ipv4.conf.default.log_martians to correct
      value
    ansible.builtin.shell:
      cmd: find -L {{ sysctl_paths | join(" ") }} -type f -name '*.conf' | xargs grep
        -HP '^\s*net.ipv4.conf.default.log_martians\s*=\s*{{ sysctl_net_ipv4_conf_default_log_martians_value
        }}$'
    register: find_correct_value
    check_mode: false
    changed_when: false
    failed_when: false
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-006023
    - NIST-800-171-3.1.20
    - NIST-800-53-CM-7(a)
    - NIST-800-53-CM-7(b)
    - NIST-800-53-SC-5(3)(a)
    - disable_strategy
    - low_complexity
    - medium_disruption
    - reboot_required
    - sysctl_net_ipv4_conf_default_log_martians
    - unknown_severity

  - name: Enable Kernel Parameter to Log Martian Packets on all IPv4 Interfaces by
      Default - Comment out any occurrences of net.ipv4.conf.default.log_martians
      from config files
    ansible.builtin.replace:
      path: '{{ item | split(":") | first }}'
      regexp: ^[\s]*net.ipv4.conf.default.log_martians
      replace: '#net.ipv4.conf.default.log_martians'
    loop: '{{ find_all_values.stdout_lines }}'
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - find_correct_value.stdout_lines | length == 0 or find_all_values.stdout_lines
      | length > find_correct_value.stdout_lines | length
    tags:
    - DISA-STIG-OL09-00-006023
    - NIST-800-171-3.1.20
    - NIST-800-53-CM-7(a)
    - NIST-800-53-CM-7(b)
    - NIST-800-53-SC-5(3)(a)
    - disable_strategy
    - low_complexity
    - medium_disruption
    - reboot_required
    - sysctl_net_ipv4_conf_default_log_martians
    - unknown_severity

  - name: Enable Kernel Parameter to Log Martian Packets on all IPv4 Interfaces by
      Default - Comment out any occurrences of net.ipv4.conf.default.log_martians
      from /etc/sysctl.conf
    ansible.builtin.replace:
      path: '{{ item }}'
      regexp: ^[\s]*net.ipv4.conf.default.log_martians
      replace: '#net.ipv4.conf.default.log_martians'
    with_fileglob:
    - /etc/sysctl.conf
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-006023
    - NIST-800-171-3.1.20
    - NIST-800-53-CM-7(a)
    - NIST-800-53-CM-7(b)
    - NIST-800-53-SC-5(3)(a)
    - disable_strategy
    - low_complexity
    - medium_disruption
    - reboot_required
    - sysctl_net_ipv4_conf_default_log_martians
    - unknown_severity

  - name: Enable Kernel Parameter to Log Martian Packets on all IPv4 Interfaces by
      Default - Ensure sysctl net.ipv4.conf.default.log_martians is set
    ansible.posix.sysctl:
      name: net.ipv4.conf.default.log_martians
      value: '{{ sysctl_net_ipv4_conf_default_log_martians_value }}'
      sysctl_file: /etc/sysctl.d/net_ipv4_conf_default_log_martians.conf
      state: present
      reload: true
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-006023
    - NIST-800-171-3.1.20
    - NIST-800-53-CM-7(a)
    - NIST-800-53-CM-7(b)
    - NIST-800-53-SC-5(3)(a)
    - disable_strategy
    - low_complexity
    - medium_disruption
    - reboot_required
    - sysctl_net_ipv4_conf_default_log_martians
    - unknown_severity

  - name: Enable Kernel Parameter to Use Reverse Path Filtering on all IPv4 Interfaces
      by Default - Set fact for sysctl paths
    ansible.builtin.set_fact:
      sysctl_paths:
      - /etc/sysctl.d/
      - /run/sysctl.d/
      - /usr/local/lib/sysctl.d/
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-006027
    - NIST-800-171-3.1.20
    - NIST-800-53-CM-6(a)
    - NIST-800-53-CM-7(a)
    - NIST-800-53-CM-7(b)
    - NIST-800-53-SC-7(a)
    - disable_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - reboot_required
    - sysctl_net_ipv4_conf_default_rp_filter

  - name: Enable Kernel Parameter to Use Reverse Path Filtering on all IPv4 Interfaces
      by Default - Find all files that contain net.ipv4.conf.default.rp_filter
    ansible.builtin.shell:
      cmd: find -L {{ sysctl_paths | join(" ") }} -type f -name '*.conf' | xargs grep
        -HP '^\s*net.ipv4.conf.default.rp_filter\s*=\s*.*$'
    register: find_all_values
    check_mode: false
    changed_when: false
    failed_when: false
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-006027
    - NIST-800-171-3.1.20
    - NIST-800-53-CM-6(a)
    - NIST-800-53-CM-7(a)
    - NIST-800-53-CM-7(b)
    - NIST-800-53-SC-7(a)
    - disable_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - reboot_required
    - sysctl_net_ipv4_conf_default_rp_filter

  - name: Enable Kernel Parameter to Use Reverse Path Filtering on all IPv4 Interfaces
      by Default - Find all files that set net.ipv4.conf.default.rp_filter to correct
      value
    ansible.builtin.shell:
      cmd: find -L {{ sysctl_paths | join(" ") }} -type f -name '*.conf' | xargs grep
        -HP '^\s*net.ipv4.conf.default.rp_filter\s*=\s*{{ sysctl_net_ipv4_conf_default_rp_filter_value
        }}$'
    register: find_correct_value
    check_mode: false
    changed_when: false
    failed_when: false
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-006027
    - NIST-800-171-3.1.20
    - NIST-800-53-CM-6(a)
    - NIST-800-53-CM-7(a)
    - NIST-800-53-CM-7(b)
    - NIST-800-53-SC-7(a)
    - disable_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - reboot_required
    - sysctl_net_ipv4_conf_default_rp_filter

  - name: Enable Kernel Parameter to Use Reverse Path Filtering on all IPv4 Interfaces
      by Default - Comment out any occurrences of net.ipv4.conf.default.rp_filter
      from config files
    ansible.builtin.replace:
      path: '{{ item | split(":") | first }}'
      regexp: ^[\s]*net.ipv4.conf.default.rp_filter
      replace: '#net.ipv4.conf.default.rp_filter'
    loop: '{{ find_all_values.stdout_lines }}'
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - find_correct_value.stdout_lines | length == 0 or find_all_values.stdout_lines
      | length > find_correct_value.stdout_lines | length
    tags:
    - DISA-STIG-OL09-00-006027
    - NIST-800-171-3.1.20
    - NIST-800-53-CM-6(a)
    - NIST-800-53-CM-7(a)
    - NIST-800-53-CM-7(b)
    - NIST-800-53-SC-7(a)
    - disable_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - reboot_required
    - sysctl_net_ipv4_conf_default_rp_filter

  - name: Enable Kernel Parameter to Use Reverse Path Filtering on all IPv4 Interfaces
      by Default - Comment out any occurrences of net.ipv4.conf.default.rp_filter
      from /etc/sysctl.conf
    ansible.builtin.replace:
      path: '{{ item }}'
      regexp: ^[\s]*net.ipv4.conf.default.rp_filter
      replace: '#net.ipv4.conf.default.rp_filter'
    with_fileglob:
    - /etc/sysctl.conf
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-006027
    - NIST-800-171-3.1.20
    - NIST-800-53-CM-6(a)
    - NIST-800-53-CM-7(a)
    - NIST-800-53-CM-7(b)
    - NIST-800-53-SC-7(a)
    - disable_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - reboot_required
    - sysctl_net_ipv4_conf_default_rp_filter

  - name: Enable Kernel Parameter to Use Reverse Path Filtering on all IPv4 Interfaces
      by Default - Ensure sysctl net.ipv4.conf.default.rp_filter is set
    ansible.posix.sysctl:
      name: net.ipv4.conf.default.rp_filter
      value: '{{ sysctl_net_ipv4_conf_default_rp_filter_value }}'
      sysctl_file: /etc/sysctl.d/net_ipv4_conf_default_rp_filter.conf
      state: present
      reload: true
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-006027
    - NIST-800-171-3.1.20
    - NIST-800-53-CM-6(a)
    - NIST-800-53-CM-7(a)
    - NIST-800-53-CM-7(b)
    - NIST-800-53-SC-7(a)
    - disable_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - reboot_required
    - sysctl_net_ipv4_conf_default_rp_filter

  - name: Enable Kernel Parameter to Ignore ICMP Broadcast Echo Requests on IPv4 Interfaces
      - Set fact for sysctl paths
    ansible.builtin.set_fact:
      sysctl_paths:
      - /etc/sysctl.d/
      - /run/sysctl.d/
      - /usr/local/lib/sysctl.d/
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - CJIS-5.10.1.1
    - DISA-STIG-OL09-00-006030
    - NIST-800-171-3.1.20
    - NIST-800-53-CM-7(a)
    - NIST-800-53-CM-7(b)
    - NIST-800-53-SC-5
    - PCI-DSS-Req-1.4.3
    - PCI-DSSv4-1.4
    - PCI-DSSv4-1.4.2
    - disable_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - reboot_required
    - sysctl_net_ipv4_icmp_echo_ignore_broadcasts

  - name: Enable Kernel Parameter to Ignore ICMP Broadcast Echo Requests on IPv4 Interfaces
      - Find all files that contain net.ipv4.icmp_echo_ignore_broadcasts
    ansible.builtin.shell:
      cmd: find -L {{ sysctl_paths | join(" ") }} -type f -name '*.conf' | xargs grep
        -HP '^\s*net.ipv4.icmp_echo_ignore_broadcasts\s*=\s*.*$'
    register: find_all_values
    check_mode: false
    changed_when: false
    failed_when: false
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - CJIS-5.10.1.1
    - DISA-STIG-OL09-00-006030
    - NIST-800-171-3.1.20
    - NIST-800-53-CM-7(a)
    - NIST-800-53-CM-7(b)
    - NIST-800-53-SC-5
    - PCI-DSS-Req-1.4.3
    - PCI-DSSv4-1.4
    - PCI-DSSv4-1.4.2
    - disable_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - reboot_required
    - sysctl_net_ipv4_icmp_echo_ignore_broadcasts

  - name: Enable Kernel Parameter to Ignore ICMP Broadcast Echo Requests on IPv4 Interfaces
      - Find all files that set net.ipv4.icmp_echo_ignore_broadcasts to correct value
    ansible.builtin.shell:
      cmd: find -L {{ sysctl_paths | join(" ") }} -type f -name '*.conf' | xargs grep
        -HP '^\s*net.ipv4.icmp_echo_ignore_broadcasts\s*=\s*{{ sysctl_net_ipv4_icmp_echo_ignore_broadcasts_value
        }}$'
    register: find_correct_value
    check_mode: false
    changed_when: false
    failed_when: false
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - CJIS-5.10.1.1
    - DISA-STIG-OL09-00-006030
    - NIST-800-171-3.1.20
    - NIST-800-53-CM-7(a)
    - NIST-800-53-CM-7(b)
    - NIST-800-53-SC-5
    - PCI-DSS-Req-1.4.3
    - PCI-DSSv4-1.4
    - PCI-DSSv4-1.4.2
    - disable_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - reboot_required
    - sysctl_net_ipv4_icmp_echo_ignore_broadcasts

  - name: Enable Kernel Parameter to Ignore ICMP Broadcast Echo Requests on IPv4 Interfaces
      - Comment out any occurrences of net.ipv4.icmp_echo_ignore_broadcasts from config
      files
    ansible.builtin.replace:
      path: '{{ item | split(":") | first }}'
      regexp: ^[\s]*net.ipv4.icmp_echo_ignore_broadcasts
      replace: '#net.ipv4.icmp_echo_ignore_broadcasts'
    loop: '{{ find_all_values.stdout_lines }}'
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - find_correct_value.stdout_lines | length == 0 or find_all_values.stdout_lines
      | length > find_correct_value.stdout_lines | length
    tags:
    - CJIS-5.10.1.1
    - DISA-STIG-OL09-00-006030
    - NIST-800-171-3.1.20
    - NIST-800-53-CM-7(a)
    - NIST-800-53-CM-7(b)
    - NIST-800-53-SC-5
    - PCI-DSS-Req-1.4.3
    - PCI-DSSv4-1.4
    - PCI-DSSv4-1.4.2
    - disable_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - reboot_required
    - sysctl_net_ipv4_icmp_echo_ignore_broadcasts

  - name: Enable Kernel Parameter to Ignore ICMP Broadcast Echo Requests on IPv4 Interfaces
      - Comment out any occurrences of net.ipv4.icmp_echo_ignore_broadcasts from /etc/sysctl.conf
    ansible.builtin.replace:
      path: '{{ item }}'
      regexp: ^[\s]*net.ipv4.icmp_echo_ignore_broadcasts
      replace: '#net.ipv4.icmp_echo_ignore_broadcasts'
    with_fileglob:
    - /etc/sysctl.conf
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - CJIS-5.10.1.1
    - DISA-STIG-OL09-00-006030
    - NIST-800-171-3.1.20
    - NIST-800-53-CM-7(a)
    - NIST-800-53-CM-7(b)
    - NIST-800-53-SC-5
    - PCI-DSS-Req-1.4.3
    - PCI-DSSv4-1.4
    - PCI-DSSv4-1.4.2
    - disable_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - reboot_required
    - sysctl_net_ipv4_icmp_echo_ignore_broadcasts

  - name: Enable Kernel Parameter to Ignore ICMP Broadcast Echo Requests on IPv4 Interfaces
      - Ensure sysctl net.ipv4.icmp_echo_ignore_broadcasts is set
    ansible.posix.sysctl:
      name: net.ipv4.icmp_echo_ignore_broadcasts
      value: '{{ sysctl_net_ipv4_icmp_echo_ignore_broadcasts_value }}'
      sysctl_file: /etc/sysctl.d/net_ipv4_icmp_echo_ignore_broadcasts.conf
      state: present
      reload: true
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - CJIS-5.10.1.1
    - DISA-STIG-OL09-00-006030
    - NIST-800-171-3.1.20
    - NIST-800-53-CM-7(a)
    - NIST-800-53-CM-7(b)
    - NIST-800-53-SC-5
    - PCI-DSS-Req-1.4.3
    - PCI-DSSv4-1.4
    - PCI-DSSv4-1.4.2
    - disable_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - reboot_required
    - sysctl_net_ipv4_icmp_echo_ignore_broadcasts

  - name: Enable Kernel Parameter to Ignore Bogus ICMP Error Responses on IPv4 Interfaces
      - Set fact for sysctl paths
    ansible.builtin.set_fact:
      sysctl_paths:
      - /etc/sysctl.d/
      - /run/sysctl.d/
      - /usr/local/lib/sysctl.d/
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-006031
    - NIST-800-171-3.1.20
    - NIST-800-53-CM-7(a)
    - NIST-800-53-CM-7(b)
    - NIST-800-53-SC-5
    - PCI-DSS-Req-1.4.3
    - PCI-DSSv4-1.4
    - PCI-DSSv4-1.4.2
    - disable_strategy
    - low_complexity
    - medium_disruption
    - reboot_required
    - sysctl_net_ipv4_icmp_ignore_bogus_error_responses
    - unknown_severity

  - name: Enable Kernel Parameter to Ignore Bogus ICMP Error Responses on IPv4 Interfaces
      - Find all files that contain net.ipv4.icmp_ignore_bogus_error_responses
    ansible.builtin.shell:
      cmd: find -L {{ sysctl_paths | join(" ") }} -type f -name '*.conf' | xargs grep
        -HP '^\s*net.ipv4.icmp_ignore_bogus_error_responses\s*=\s*.*$'
    register: find_all_values
    check_mode: false
    changed_when: false
    failed_when: false
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-006031
    - NIST-800-171-3.1.20
    - NIST-800-53-CM-7(a)
    - NIST-800-53-CM-7(b)
    - NIST-800-53-SC-5
    - PCI-DSS-Req-1.4.3
    - PCI-DSSv4-1.4
    - PCI-DSSv4-1.4.2
    - disable_strategy
    - low_complexity
    - medium_disruption
    - reboot_required
    - sysctl_net_ipv4_icmp_ignore_bogus_error_responses
    - unknown_severity

  - name: Enable Kernel Parameter to Ignore Bogus ICMP Error Responses on IPv4 Interfaces
      - Find all files that set net.ipv4.icmp_ignore_bogus_error_responses to correct
      value
    ansible.builtin.shell:
      cmd: find -L {{ sysctl_paths | join(" ") }} -type f -name '*.conf' | xargs grep
        -HP '^\s*net.ipv4.icmp_ignore_bogus_error_responses\s*=\s*{{ sysctl_net_ipv4_icmp_ignore_bogus_error_responses_value
        }}$'
    register: find_correct_value
    check_mode: false
    changed_when: false
    failed_when: false
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-006031
    - NIST-800-171-3.1.20
    - NIST-800-53-CM-7(a)
    - NIST-800-53-CM-7(b)
    - NIST-800-53-SC-5
    - PCI-DSS-Req-1.4.3
    - PCI-DSSv4-1.4
    - PCI-DSSv4-1.4.2
    - disable_strategy
    - low_complexity
    - medium_disruption
    - reboot_required
    - sysctl_net_ipv4_icmp_ignore_bogus_error_responses
    - unknown_severity

  - name: Enable Kernel Parameter to Ignore Bogus ICMP Error Responses on IPv4 Interfaces
      - Comment out any occurrences of net.ipv4.icmp_ignore_bogus_error_responses
      from config files
    ansible.builtin.replace:
      path: '{{ item | split(":") | first }}'
      regexp: ^[\s]*net.ipv4.icmp_ignore_bogus_error_responses
      replace: '#net.ipv4.icmp_ignore_bogus_error_responses'
    loop: '{{ find_all_values.stdout_lines }}'
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - find_correct_value.stdout_lines | length == 0 or find_all_values.stdout_lines
      | length > find_correct_value.stdout_lines | length
    tags:
    - DISA-STIG-OL09-00-006031
    - NIST-800-171-3.1.20
    - NIST-800-53-CM-7(a)
    - NIST-800-53-CM-7(b)
    - NIST-800-53-SC-5
    - PCI-DSS-Req-1.4.3
    - PCI-DSSv4-1.4
    - PCI-DSSv4-1.4.2
    - disable_strategy
    - low_complexity
    - medium_disruption
    - reboot_required
    - sysctl_net_ipv4_icmp_ignore_bogus_error_responses
    - unknown_severity

  - name: Enable Kernel Parameter to Ignore Bogus ICMP Error Responses on IPv4 Interfaces
      - Comment out any occurrences of net.ipv4.icmp_ignore_bogus_error_responses
      from /etc/sysctl.conf
    ansible.builtin.replace:
      path: '{{ item }}'
      regexp: ^[\s]*net.ipv4.icmp_ignore_bogus_error_responses
      replace: '#net.ipv4.icmp_ignore_bogus_error_responses'
    with_fileglob:
    - /etc/sysctl.conf
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-006031
    - NIST-800-171-3.1.20
    - NIST-800-53-CM-7(a)
    - NIST-800-53-CM-7(b)
    - NIST-800-53-SC-5
    - PCI-DSS-Req-1.4.3
    - PCI-DSSv4-1.4
    - PCI-DSSv4-1.4.2
    - disable_strategy
    - low_complexity
    - medium_disruption
    - reboot_required
    - sysctl_net_ipv4_icmp_ignore_bogus_error_responses
    - unknown_severity

  - name: Enable Kernel Parameter to Ignore Bogus ICMP Error Responses on IPv4 Interfaces
      - Ensure sysctl net.ipv4.icmp_ignore_bogus_error_responses is set
    ansible.posix.sysctl:
      name: net.ipv4.icmp_ignore_bogus_error_responses
      value: '{{ sysctl_net_ipv4_icmp_ignore_bogus_error_responses_value }}'
      sysctl_file: /etc/sysctl.d/net_ipv4_icmp_ignore_bogus_error_responses.conf
      state: present
      reload: true
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-006031
    - NIST-800-171-3.1.20
    - NIST-800-53-CM-7(a)
    - NIST-800-53-CM-7(b)
    - NIST-800-53-SC-5
    - PCI-DSS-Req-1.4.3
    - PCI-DSSv4-1.4
    - PCI-DSSv4-1.4.2
    - disable_strategy
    - low_complexity
    - medium_disruption
    - reboot_required
    - sysctl_net_ipv4_icmp_ignore_bogus_error_responses
    - unknown_severity

  - name: Enable Kernel Parameter to Use TCP Syncookies on Network Interfaces - Set
      fact for sysctl paths
    ansible.builtin.set_fact:
      sysctl_paths:
      - /etc/sysctl.d/
      - /run/sysctl.d/
      - /usr/local/lib/sysctl.d/
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - CJIS-5.10.1.1
    - DISA-STIG-OL09-00-006050
    - NIST-800-171-3.1.20
    - NIST-800-53-CM-6(a)
    - NIST-800-53-CM-7(a)
    - NIST-800-53-CM-7(b)
    - NIST-800-53-SC-5(1)
    - NIST-800-53-SC-5(2)
    - NIST-800-53-SC-5(3)(a)
    - PCI-DSS-Req-1.4.1
    - PCI-DSSv4-1.4
    - PCI-DSSv4-1.4.3
    - disable_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - reboot_required
    - sysctl_net_ipv4_tcp_syncookies

  - name: Enable Kernel Parameter to Use TCP Syncookies on Network Interfaces - Find
      all files that contain net.ipv4.tcp_syncookies
    ansible.builtin.shell:
      cmd: find -L {{ sysctl_paths | join(" ") }} -type f -name '*.conf' | xargs grep
        -HP '^\s*net.ipv4.tcp_syncookies\s*=\s*.*$'
    register: find_all_values
    check_mode: false
    changed_when: false
    failed_when: false
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - CJIS-5.10.1.1
    - DISA-STIG-OL09-00-006050
    - NIST-800-171-3.1.20
    - NIST-800-53-CM-6(a)
    - NIST-800-53-CM-7(a)
    - NIST-800-53-CM-7(b)
    - NIST-800-53-SC-5(1)
    - NIST-800-53-SC-5(2)
    - NIST-800-53-SC-5(3)(a)
    - PCI-DSS-Req-1.4.1
    - PCI-DSSv4-1.4
    - PCI-DSSv4-1.4.3
    - disable_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - reboot_required
    - sysctl_net_ipv4_tcp_syncookies

  - name: Enable Kernel Parameter to Use TCP Syncookies on Network Interfaces - Find
      all files that set net.ipv4.tcp_syncookies to correct value
    ansible.builtin.shell:
      cmd: find -L {{ sysctl_paths | join(" ") }} -type f -name '*.conf' | xargs grep
        -HP '^\s*net.ipv4.tcp_syncookies\s*=\s*{{ sysctl_net_ipv4_tcp_syncookies_value
        }}$'
    register: find_correct_value
    check_mode: false
    changed_when: false
    failed_when: false
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - CJIS-5.10.1.1
    - DISA-STIG-OL09-00-006050
    - NIST-800-171-3.1.20
    - NIST-800-53-CM-6(a)
    - NIST-800-53-CM-7(a)
    - NIST-800-53-CM-7(b)
    - NIST-800-53-SC-5(1)
    - NIST-800-53-SC-5(2)
    - NIST-800-53-SC-5(3)(a)
    - PCI-DSS-Req-1.4.1
    - PCI-DSSv4-1.4
    - PCI-DSSv4-1.4.3
    - disable_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - reboot_required
    - sysctl_net_ipv4_tcp_syncookies

  - name: Enable Kernel Parameter to Use TCP Syncookies on Network Interfaces - Comment
      out any occurrences of net.ipv4.tcp_syncookies from config files
    ansible.builtin.replace:
      path: '{{ item | split(":") | first }}'
      regexp: ^[\s]*net.ipv4.tcp_syncookies
      replace: '#net.ipv4.tcp_syncookies'
    loop: '{{ find_all_values.stdout_lines }}'
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - find_correct_value.stdout_lines | length == 0 or find_all_values.stdout_lines
      | length > find_correct_value.stdout_lines | length
    tags:
    - CJIS-5.10.1.1
    - DISA-STIG-OL09-00-006050
    - NIST-800-171-3.1.20
    - NIST-800-53-CM-6(a)
    - NIST-800-53-CM-7(a)
    - NIST-800-53-CM-7(b)
    - NIST-800-53-SC-5(1)
    - NIST-800-53-SC-5(2)
    - NIST-800-53-SC-5(3)(a)
    - PCI-DSS-Req-1.4.1
    - PCI-DSSv4-1.4
    - PCI-DSSv4-1.4.3
    - disable_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - reboot_required
    - sysctl_net_ipv4_tcp_syncookies

  - name: Enable Kernel Parameter to Use TCP Syncookies on Network Interfaces - Comment
      out any occurrences of net.ipv4.tcp_syncookies from /etc/sysctl.conf
    ansible.builtin.replace:
      path: '{{ item }}'
      regexp: ^[\s]*net.ipv4.tcp_syncookies
      replace: '#net.ipv4.tcp_syncookies'
    with_fileglob:
    - /etc/sysctl.conf
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - CJIS-5.10.1.1
    - DISA-STIG-OL09-00-006050
    - NIST-800-171-3.1.20
    - NIST-800-53-CM-6(a)
    - NIST-800-53-CM-7(a)
    - NIST-800-53-CM-7(b)
    - NIST-800-53-SC-5(1)
    - NIST-800-53-SC-5(2)
    - NIST-800-53-SC-5(3)(a)
    - PCI-DSS-Req-1.4.1
    - PCI-DSSv4-1.4
    - PCI-DSSv4-1.4.3
    - disable_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - reboot_required
    - sysctl_net_ipv4_tcp_syncookies

  - name: Enable Kernel Parameter to Use TCP Syncookies on Network Interfaces - Ensure
      sysctl net.ipv4.tcp_syncookies is set
    ansible.posix.sysctl:
      name: net.ipv4.tcp_syncookies
      value: '{{ sysctl_net_ipv4_tcp_syncookies_value }}'
      sysctl_file: /etc/sysctl.d/net_ipv4_tcp_syncookies.conf
      state: present
      reload: true
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - CJIS-5.10.1.1
    - DISA-STIG-OL09-00-006050
    - NIST-800-171-3.1.20
    - NIST-800-53-CM-6(a)
    - NIST-800-53-CM-7(a)
    - NIST-800-53-CM-7(b)
    - NIST-800-53-SC-5(1)
    - NIST-800-53-SC-5(2)
    - NIST-800-53-SC-5(3)(a)
    - PCI-DSS-Req-1.4.1
    - PCI-DSSv4-1.4
    - PCI-DSSv4-1.4.3
    - disable_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - reboot_required
    - sysctl_net_ipv4_tcp_syncookies

  - name: Disable Kernel Parameter for Sending ICMP Redirects on all IPv4 Interfaces
      - Set fact for sysctl paths
    ansible.builtin.set_fact:
      sysctl_paths:
      - /etc/sysctl.d/
      - /run/sysctl.d/
      - /usr/local/lib/sysctl.d/
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - CJIS-5.10.1.1
    - DISA-STIG-OL09-00-006032
    - NIST-800-171-3.1.20
    - NIST-800-53-CM-6(a)
    - NIST-800-53-CM-7(a)
    - NIST-800-53-CM-7(b)
    - NIST-800-53-SC-5
    - NIST-800-53-SC-7(a)
    - PCI-DSSv4-1.4
    - PCI-DSSv4-1.4.5
    - disable_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - reboot_required
    - sysctl_net_ipv4_conf_all_send_redirects

  - name: Disable Kernel Parameter for Sending ICMP Redirects on all IPv4 Interfaces
      - Find all files that contain net.ipv4.conf.all.send_redirects
    ansible.builtin.shell:
      cmd: find -L {{ sysctl_paths | join(" ") }} -type f -name '*.conf' | xargs grep
        -HP '^\s*net.ipv4.conf.all.send_redirects\s*=\s*.*$'
    register: find_all_values
    check_mode: false
    changed_when: false
    failed_when: false
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - CJIS-5.10.1.1
    - DISA-STIG-OL09-00-006032
    - NIST-800-171-3.1.20
    - NIST-800-53-CM-6(a)
    - NIST-800-53-CM-7(a)
    - NIST-800-53-CM-7(b)
    - NIST-800-53-SC-5
    - NIST-800-53-SC-7(a)
    - PCI-DSSv4-1.4
    - PCI-DSSv4-1.4.5
    - disable_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - reboot_required
    - sysctl_net_ipv4_conf_all_send_redirects

  - name: Disable Kernel Parameter for Sending ICMP Redirects on all IPv4 Interfaces
      - Find all files that set net.ipv4.conf.all.send_redirects to correct value
    ansible.builtin.shell:
      cmd: find -L {{ sysctl_paths | join(" ") }} -type f -name '*.conf' | xargs grep
        -HP '^\s*net.ipv4.conf.all.send_redirects\s*=\s*0$'
    register: find_correct_value
    check_mode: false
    changed_when: false
    failed_when: false
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - CJIS-5.10.1.1
    - DISA-STIG-OL09-00-006032
    - NIST-800-171-3.1.20
    - NIST-800-53-CM-6(a)
    - NIST-800-53-CM-7(a)
    - NIST-800-53-CM-7(b)
    - NIST-800-53-SC-5
    - NIST-800-53-SC-7(a)
    - PCI-DSSv4-1.4
    - PCI-DSSv4-1.4.5
    - disable_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - reboot_required
    - sysctl_net_ipv4_conf_all_send_redirects

  - name: Disable Kernel Parameter for Sending ICMP Redirects on all IPv4 Interfaces
      - Comment out any occurrences of net.ipv4.conf.all.send_redirects from config
      files
    ansible.builtin.replace:
      path: '{{ item | split(":") | first }}'
      regexp: ^[\s]*net.ipv4.conf.all.send_redirects
      replace: '#net.ipv4.conf.all.send_redirects'
    loop: '{{ find_all_values.stdout_lines }}'
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - find_correct_value.stdout_lines | length == 0 or find_all_values.stdout_lines
      | length > find_correct_value.stdout_lines | length
    tags:
    - CJIS-5.10.1.1
    - DISA-STIG-OL09-00-006032
    - NIST-800-171-3.1.20
    - NIST-800-53-CM-6(a)
    - NIST-800-53-CM-7(a)
    - NIST-800-53-CM-7(b)
    - NIST-800-53-SC-5
    - NIST-800-53-SC-7(a)
    - PCI-DSSv4-1.4
    - PCI-DSSv4-1.4.5
    - disable_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - reboot_required
    - sysctl_net_ipv4_conf_all_send_redirects

  - name: Disable Kernel Parameter for Sending ICMP Redirects on all IPv4 Interfaces
      - Comment out any occurrences of net.ipv4.conf.all.send_redirects from /etc/sysctl.conf
    ansible.builtin.replace:
      path: '{{ item }}'
      regexp: ^[\s]*net.ipv4.conf.all.send_redirects
      replace: '#net.ipv4.conf.all.send_redirects'
    with_fileglob:
    - /etc/sysctl.conf
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - CJIS-5.10.1.1
    - DISA-STIG-OL09-00-006032
    - NIST-800-171-3.1.20
    - NIST-800-53-CM-6(a)
    - NIST-800-53-CM-7(a)
    - NIST-800-53-CM-7(b)
    - NIST-800-53-SC-5
    - NIST-800-53-SC-7(a)
    - PCI-DSSv4-1.4
    - PCI-DSSv4-1.4.5
    - disable_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - reboot_required
    - sysctl_net_ipv4_conf_all_send_redirects

  - name: Disable Kernel Parameter for Sending ICMP Redirects on all IPv4 Interfaces
      - Ensure sysctl net.ipv4.conf.all.send_redirects is set to 0
    ansible.posix.sysctl:
      name: net.ipv4.conf.all.send_redirects
      value: '0'
      sysctl_file: /etc/sysctl.d/net_ipv4_conf_all_send_redirects.conf
      state: present
      reload: true
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - CJIS-5.10.1.1
    - DISA-STIG-OL09-00-006032
    - NIST-800-171-3.1.20
    - NIST-800-53-CM-6(a)
    - NIST-800-53-CM-7(a)
    - NIST-800-53-CM-7(b)
    - NIST-800-53-SC-5
    - NIST-800-53-SC-7(a)
    - PCI-DSSv4-1.4
    - PCI-DSSv4-1.4.5
    - disable_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - reboot_required
    - sysctl_net_ipv4_conf_all_send_redirects

  - name: Disable Kernel Parameter for Sending ICMP Redirects on all IPv4 Interfaces
      by Default - Set fact for sysctl paths
    ansible.builtin.set_fact:
      sysctl_paths:
      - /etc/sysctl.d/
      - /run/sysctl.d/
      - /usr/local/lib/sysctl.d/
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - CJIS-5.10.1.1
    - DISA-STIG-OL09-00-006033
    - NIST-800-171-3.1.20
    - NIST-800-53-CM-6(a)
    - NIST-800-53-CM-7(a)
    - NIST-800-53-CM-7(b)
    - NIST-800-53-SC-5
    - NIST-800-53-SC-7(a)
    - PCI-DSSv4-1.4
    - PCI-DSSv4-1.4.5
    - disable_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - reboot_required
    - sysctl_net_ipv4_conf_default_send_redirects

  - name: Disable Kernel Parameter for Sending ICMP Redirects on all IPv4 Interfaces
      by Default - Find all files that contain net.ipv4.conf.default.send_redirects
    ansible.builtin.shell:
      cmd: find -L {{ sysctl_paths | join(" ") }} -type f -name '*.conf' | xargs grep
        -HP '^\s*net.ipv4.conf.default.send_redirects\s*=\s*.*$'
    register: find_all_values
    check_mode: false
    changed_when: false
    failed_when: false
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - CJIS-5.10.1.1
    - DISA-STIG-OL09-00-006033
    - NIST-800-171-3.1.20
    - NIST-800-53-CM-6(a)
    - NIST-800-53-CM-7(a)
    - NIST-800-53-CM-7(b)
    - NIST-800-53-SC-5
    - NIST-800-53-SC-7(a)
    - PCI-DSSv4-1.4
    - PCI-DSSv4-1.4.5
    - disable_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - reboot_required
    - sysctl_net_ipv4_conf_default_send_redirects

  - name: Disable Kernel Parameter for Sending ICMP Redirects on all IPv4 Interfaces
      by Default - Find all files that set net.ipv4.conf.default.send_redirects to
      correct value
    ansible.builtin.shell:
      cmd: find -L {{ sysctl_paths | join(" ") }} -type f -name '*.conf' | xargs grep
        -HP '^\s*net.ipv4.conf.default.send_redirects\s*=\s*0$'
    register: find_correct_value
    check_mode: false
    changed_when: false
    failed_when: false
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - CJIS-5.10.1.1
    - DISA-STIG-OL09-00-006033
    - NIST-800-171-3.1.20
    - NIST-800-53-CM-6(a)
    - NIST-800-53-CM-7(a)
    - NIST-800-53-CM-7(b)
    - NIST-800-53-SC-5
    - NIST-800-53-SC-7(a)
    - PCI-DSSv4-1.4
    - PCI-DSSv4-1.4.5
    - disable_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - reboot_required
    - sysctl_net_ipv4_conf_default_send_redirects

  - name: Disable Kernel Parameter for Sending ICMP Redirects on all IPv4 Interfaces
      by Default - Comment out any occurrences of net.ipv4.conf.default.send_redirects
      from config files
    ansible.builtin.replace:
      path: '{{ item | split(":") | first }}'
      regexp: ^[\s]*net.ipv4.conf.default.send_redirects
      replace: '#net.ipv4.conf.default.send_redirects'
    loop: '{{ find_all_values.stdout_lines }}'
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - find_correct_value.stdout_lines | length == 0 or find_all_values.stdout_lines
      | length > find_correct_value.stdout_lines | length
    tags:
    - CJIS-5.10.1.1
    - DISA-STIG-OL09-00-006033
    - NIST-800-171-3.1.20
    - NIST-800-53-CM-6(a)
    - NIST-800-53-CM-7(a)
    - NIST-800-53-CM-7(b)
    - NIST-800-53-SC-5
    - NIST-800-53-SC-7(a)
    - PCI-DSSv4-1.4
    - PCI-DSSv4-1.4.5
    - disable_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - reboot_required
    - sysctl_net_ipv4_conf_default_send_redirects

  - name: Disable Kernel Parameter for Sending ICMP Redirects on all IPv4 Interfaces
      by Default - Comment out any occurrences of net.ipv4.conf.default.send_redirects
      from /etc/sysctl.conf
    ansible.builtin.replace:
      path: '{{ item }}'
      regexp: ^[\s]*net.ipv4.conf.default.send_redirects
      replace: '#net.ipv4.conf.default.send_redirects'
    with_fileglob:
    - /etc/sysctl.conf
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - CJIS-5.10.1.1
    - DISA-STIG-OL09-00-006033
    - NIST-800-171-3.1.20
    - NIST-800-53-CM-6(a)
    - NIST-800-53-CM-7(a)
    - NIST-800-53-CM-7(b)
    - NIST-800-53-SC-5
    - NIST-800-53-SC-7(a)
    - PCI-DSSv4-1.4
    - PCI-DSSv4-1.4.5
    - disable_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - reboot_required
    - sysctl_net_ipv4_conf_default_send_redirects

  - name: Disable Kernel Parameter for Sending ICMP Redirects on all IPv4 Interfaces
      by Default - Ensure sysctl net.ipv4.conf.default.send_redirects is set to 0
    ansible.posix.sysctl:
      name: net.ipv4.conf.default.send_redirects
      value: '0'
      sysctl_file: /etc/sysctl.d/net_ipv4_conf_default_send_redirects.conf
      state: present
      reload: true
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - CJIS-5.10.1.1
    - DISA-STIG-OL09-00-006033
    - NIST-800-171-3.1.20
    - NIST-800-53-CM-6(a)
    - NIST-800-53-CM-7(a)
    - NIST-800-53-CM-7(b)
    - NIST-800-53-SC-5
    - NIST-800-53-SC-7(a)
    - PCI-DSSv4-1.4
    - PCI-DSSv4-1.4.5
    - disable_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - reboot_required
    - sysctl_net_ipv4_conf_default_send_redirects

  - name: Ensure kernel module 'atm' is disabled
    ansible.builtin.lineinfile:
      create: true
      dest: /etc/modprobe.d/atm.conf
      regexp: install\s+atm
      line: install atm /bin/false
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-000040
    - NIST-800-53-AC-18
    - disable_strategy
    - kernel_module_atm_disabled
    - low_complexity
    - medium_disruption
    - medium_severity
    - reboot_required

  - name: Ensure kernel module 'atm' is blacklisted
    ansible.builtin.lineinfile:
      create: true
      dest: /etc/modprobe.d/atm.conf
      regexp: ^blacklist atm$
      line: blacklist atm
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-000040
    - NIST-800-53-AC-18
    - disable_strategy
    - kernel_module_atm_disabled
    - low_complexity
    - medium_disruption
    - medium_severity
    - reboot_required

  - name: Ensure kernel module 'can' is disabled
    ansible.builtin.lineinfile:
      create: true
      dest: /etc/modprobe.d/can.conf
      regexp: install\s+can
      line: install can /bin/false
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-000041
    - NIST-800-53-AC-18
    - disable_strategy
    - kernel_module_can_disabled
    - low_complexity
    - medium_disruption
    - medium_severity
    - reboot_required

  - name: Ensure kernel module 'can' is blacklisted
    ansible.builtin.lineinfile:
      create: true
      dest: /etc/modprobe.d/can.conf
      regexp: ^blacklist can$
      line: blacklist can
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-000041
    - NIST-800-53-AC-18
    - disable_strategy
    - kernel_module_can_disabled
    - low_complexity
    - medium_disruption
    - medium_severity
    - reboot_required

  - name: Ensure kernel module 'firewire-core' is disabled
    ansible.builtin.lineinfile:
      create: true
      dest: /etc/modprobe.d/firewire-core.conf
      regexp: install\s+firewire-core
      line: install firewire-core /bin/false
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-000042
    - NIST-800-53-AC-18
    - disable_strategy
    - kernel_module_firewire-core_disabled
    - low_complexity
    - low_severity
    - medium_disruption
    - reboot_required

  - name: Ensure kernel module 'firewire-core' is blacklisted
    ansible.builtin.lineinfile:
      create: true
      dest: /etc/modprobe.d/firewire-core.conf
      regexp: ^blacklist firewire-core$
      line: blacklist firewire-core
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-000042
    - NIST-800-53-AC-18
    - disable_strategy
    - kernel_module_firewire-core_disabled
    - low_complexity
    - low_severity
    - medium_disruption
    - reboot_required

  - name: Ensure kernel module 'sctp' is disabled
    ansible.builtin.lineinfile:
      create: true
      dest: /etc/modprobe.d/sctp.conf
      regexp: install\s+sctp
      line: install sctp /bin/false
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - CJIS-5.10.1
    - DISA-STIG-OL09-00-000043
    - NIST-800-171-3.4.6
    - NIST-800-53-CM-6(a)
    - NIST-800-53-CM-7(a)
    - NIST-800-53-CM-7(b)
    - PCI-DSS-Req-1.4.2
    - PCI-DSSv4-1.4
    - PCI-DSSv4-1.4.2
    - disable_strategy
    - kernel_module_sctp_disabled
    - low_complexity
    - medium_disruption
    - medium_severity
    - reboot_required

  - name: Ensure kernel module 'sctp' is blacklisted
    ansible.builtin.lineinfile:
      create: true
      dest: /etc/modprobe.d/sctp.conf
      regexp: ^blacklist sctp$
      line: blacklist sctp
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - CJIS-5.10.1
    - DISA-STIG-OL09-00-000043
    - NIST-800-171-3.4.6
    - NIST-800-53-CM-6(a)
    - NIST-800-53-CM-7(a)
    - NIST-800-53-CM-7(b)
    - PCI-DSS-Req-1.4.2
    - PCI-DSSv4-1.4
    - PCI-DSSv4-1.4.2
    - disable_strategy
    - kernel_module_sctp_disabled
    - low_complexity
    - medium_disruption
    - medium_severity
    - reboot_required

  - name: Ensure kernel module 'tipc' is disabled
    ansible.builtin.lineinfile:
      create: true
      dest: /etc/modprobe.d/tipc.conf
      regexp: install\s+tipc
      line: install tipc /bin/false
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-000044
    - NIST-800-53-CM-6(a)
    - NIST-800-53-CM-7(a)
    - NIST-800-53-CM-7(b)
    - disable_strategy
    - kernel_module_tipc_disabled
    - low_complexity
    - low_severity
    - medium_disruption
    - reboot_required

  - name: Ensure kernel module 'tipc' is blacklisted
    ansible.builtin.lineinfile:
      create: true
      dest: /etc/modprobe.d/tipc.conf
      regexp: ^blacklist tipc$
      line: blacklist tipc
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-000044
    - NIST-800-53-CM-6(a)
    - NIST-800-53-CM-7(a)
    - NIST-800-53-CM-7(b)
    - disable_strategy
    - kernel_module_tipc_disabled
    - low_complexity
    - low_severity
    - medium_disruption
    - reboot_required

  - name: Ensure kernel module 'bluetooth' is disabled
    ansible.builtin.lineinfile:
      create: true
      dest: /etc/modprobe.d/bluetooth.conf
      regexp: install\s+bluetooth
      line: install bluetooth /bin/false
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - CJIS-5.13.1.3
    - DISA-STIG-OL09-00-000046
    - NIST-800-171-3.1.16
    - NIST-800-53-AC-18(3)
    - NIST-800-53-AC-18(a)
    - NIST-800-53-CM-6(a)
    - NIST-800-53-CM-7(a)
    - NIST-800-53-CM-7(b)
    - NIST-800-53-MP-7
    - disable_strategy
    - kernel_module_bluetooth_disabled
    - low_complexity
    - medium_disruption
    - medium_severity
    - reboot_required

  - name: Ensure kernel module 'bluetooth' is blacklisted
    ansible.builtin.lineinfile:
      create: true
      dest: /etc/modprobe.d/bluetooth.conf
      regexp: ^blacklist bluetooth$
      line: blacklist bluetooth
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - CJIS-5.13.1.3
    - DISA-STIG-OL09-00-000046
    - NIST-800-171-3.1.16
    - NIST-800-53-AC-18(3)
    - NIST-800-53-AC-18(a)
    - NIST-800-53-CM-6(a)
    - NIST-800-53-CM-7(a)
    - NIST-800-53-CM-7(b)
    - NIST-800-53-MP-7
    - disable_strategy
    - kernel_module_bluetooth_disabled
    - low_complexity
    - medium_disruption
    - medium_severity
    - reboot_required

  - name: Deactivate Wireless Network Interfaces - NetworkManager Deactivate Wireless
      Network Interfaces
    ansible.builtin.command: nmcli radio wifi off
    when:
    - ( not ( ansible_virtualization_type in ["docker", "lxc", "openvz", "podman",
      "container"] ) )
    - '''NetworkManager'' in ansible_facts.packages'
    - ansible_facts.services['NetworkManager.service'].state == 'running'
    tags:
    - DISA-STIG-OL09-00-006001
    - NIST-800-171-3.1.16
    - NIST-800-53-AC-18(3)
    - NIST-800-53-AC-18(a)
    - NIST-800-53-CM-6(a)
    - NIST-800-53-CM-7(a)
    - NIST-800-53-CM-7(b)
    - NIST-800-53-MP-7
    - PCI-DSS-Req-1.3.3
    - PCI-DSSv4-1.3
    - PCI-DSSv4-1.3.3
    - low_complexity
    - medium_disruption
    - medium_severity
    - no_reboot_needed
    - unknown_strategy
    - wireless_disable_interfaces

  - name: NetworkManager DNS Mode Must Be Must Configured - Search for a section in
      files
    ansible.builtin.find:
      paths: '{{item.path}}'
      patterns: '{{item.pattern}}'
      contains: ^\s*\[main\]
      read_whole_file: true
      use_regex: true
    register: systemd_dropin_files_with_section
    loop:
    - path: '{{ ''/etc/NetworkManager/NetworkManager.conf'' | dirname }}'
      pattern: '{{ ''/etc/NetworkManager/NetworkManager.conf'' | basename | regex_escape
        }}'
    - path: /etc/NetworkManager/conf.d
      pattern: .*\.conf
    when: '"NetworkManager" in ansible_facts.packages'
    tags:
    - DISA-STIG-OL09-00-006002
    - NIST-800-53-CM-6(b)
    - low_complexity
    - low_disruption
    - medium_severity
    - networkmanager_dns_mode
    - no_reboot_needed
    - restrict_strategy

  - name: NetworkManager DNS Mode Must Be Must Configured - Count number of files
      which contain the correct section
    ansible.builtin.set_fact:
      count_of_systemd_dropin_files_with_section: '{{systemd_dropin_files_with_section.results
        | map(attribute=''matched'') | list | map(''int'') | sum}}'
    when: '"NetworkManager" in ansible_facts.packages'
    tags:
    - DISA-STIG-OL09-00-006002
    - NIST-800-53-CM-6(b)
    - low_complexity
    - low_disruption
    - medium_severity
    - networkmanager_dns_mode
    - no_reboot_needed
    - restrict_strategy

  - name: NetworkManager DNS Mode Must Be Must Configured - Add missing configuration
      to correct section
    community.general.ini_file:
      path: '{{item}}'
      section: main
      option: dns
      value: '{{var_networkmanager_dns_mode}}'
      state: present
      no_extra_spaces: true
    when:
    - '"NetworkManager" in ansible_facts.packages'
    - count_of_systemd_dropin_files_with_section | int > 0
    loop: '{{systemd_dropin_files_with_section.results | sum(attribute=''files'',
      start=[]) | map(attribute=''path'') | list }}'
    tags:
    - DISA-STIG-OL09-00-006002
    - NIST-800-53-CM-6(b)
    - low_complexity
    - low_disruption
    - medium_severity
    - networkmanager_dns_mode
    - no_reboot_needed
    - restrict_strategy

  - name: NetworkManager DNS Mode Must Be Must Configured - Add configuration to new
      remediation file
    community.general.ini_file:
      path: /etc/NetworkManager/conf.d/complianceascode_hardening.conf
      section: main
      option: dns
      value: '{{var_networkmanager_dns_mode}}'
      state: present
      no_extra_spaces: true
      create: true
    when:
    - '"NetworkManager" in ansible_facts.packages'
    - count_of_systemd_dropin_files_with_section | int == 0
    tags:
    - DISA-STIG-OL09-00-006002
    - NIST-800-53-CM-6(b)
    - low_complexity
    - low_disruption
    - medium_severity
    - networkmanager_dns_mode
    - no_reboot_needed
    - restrict_strategy

  - name: Verify that All World-Writable Directories Have Sticky Bits Set - Define
      Excluded (Non-Local) File Systems and Paths
    ansible.builtin.set_fact:
      excluded_fstypes:
      - afs
      - autofs
      - ceph
      - cifs
      - smb3
      - smbfs
      - sshfs
      - ncpfs
      - ncp
      - nfs
      - nfs4
      - gfs
      - gfs2
      - glusterfs
      - gpfs
      - pvfs2
      - ocfs2
      - lustre
      - davfs
      - fuse.sshfs
      excluded_paths:
      - dev
      - proc
      - run
      - sys
      search_paths: []
    tags:
    - DISA-STIG-OL09-00-002510
    - NIST-800-53-AC-6(1)
    - NIST-800-53-CM-6(a)
    - PCI-DSSv4-2.2
    - PCI-DSSv4-2.2.6
    - dir_perms_world_writable_sticky_bits
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Verify that All World-Writable Directories Have Sticky Bits Set - Find Relevant
      Root Directories Ignoring Pre-Defined Excluded Paths
    ansible.builtin.find:
      paths: /
      file_type: directory
      excludes: '{{ excluded_paths }}'
      hidden: true
      recurse: false
    register: result_relevant_root_dirs
    tags:
    - DISA-STIG-OL09-00-002510
    - NIST-800-53-AC-6(1)
    - NIST-800-53-CM-6(a)
    - PCI-DSSv4-2.2
    - PCI-DSSv4-2.2.6
    - dir_perms_world_writable_sticky_bits
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Verify that All World-Writable Directories Have Sticky Bits Set - Include
      Relevant Root Directories in a List of Paths to be Searched
    ansible.builtin.set_fact:
      search_paths: '{{ search_paths | union([item.path]) }}'
    loop: '{{ result_relevant_root_dirs.files }}'
    tags:
    - DISA-STIG-OL09-00-002510
    - NIST-800-53-AC-6(1)
    - NIST-800-53-CM-6(a)
    - PCI-DSSv4-2.2
    - PCI-DSSv4-2.2.6
    - dir_perms_world_writable_sticky_bits
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Verify that All World-Writable Directories Have Sticky Bits Set - Increment
      Search Paths List with Local Partitions Mount Points
    ansible.builtin.set_fact:
      search_paths: '{{ search_paths | union([item.mount]) }}'
    loop: '{{ ansible_mounts }}'
    when:
    - item.fstype not in excluded_fstypes
    - item.mount != '/'
    tags:
    - DISA-STIG-OL09-00-002510
    - NIST-800-53-AC-6(1)
    - NIST-800-53-CM-6(a)
    - PCI-DSSv4-2.2
    - PCI-DSSv4-2.2.6
    - dir_perms_world_writable_sticky_bits
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Verify that All World-Writable Directories Have Sticky Bits Set - Increment
      Search Paths List with Local NFS File System Targets
    ansible.builtin.set_fact:
      search_paths: '{{ search_paths | union([item.device.split('':'')[1]]) }}'
    loop: '{{ ansible_mounts }}'
    when: item.device is search("localhost:")
    tags:
    - DISA-STIG-OL09-00-002510
    - NIST-800-53-AC-6(1)
    - NIST-800-53-CM-6(a)
    - PCI-DSSv4-2.2
    - PCI-DSSv4-2.2.6
    - dir_perms_world_writable_sticky_bits
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Verify that All World-Writable Directories Have Sticky Bits Set - Define
      Rule Specific Facts
    ansible.builtin.set_fact:
      world_writable_dirs: []
    tags:
    - DISA-STIG-OL09-00-002510
    - NIST-800-53-AC-6(1)
    - NIST-800-53-CM-6(a)
    - PCI-DSSv4-2.2
    - PCI-DSSv4-2.2.6
    - dir_perms_world_writable_sticky_bits
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Verify that All World-Writable Directories Have Sticky Bits Set - Find All
      Uncompliant Directories in Local File Systems
    ansible.builtin.command:
      cmd: find {{ item }} -xdev -type d ( -perm -0002 -a ! -perm -1000 )
    loop: '{{ search_paths }}'
    changed_when: false
    register: result_found_dirs
    tags:
    - DISA-STIG-OL09-00-002510
    - NIST-800-53-AC-6(1)
    - NIST-800-53-CM-6(a)
    - PCI-DSSv4-2.2
    - PCI-DSSv4-2.2.6
    - dir_perms_world_writable_sticky_bits
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Verify that All World-Writable Directories Have Sticky Bits Set - Create
      List of World Writable Directories Without Sticky Bit
    ansible.builtin.set_fact:
      world_writable_dirs: '{{ world_writable_dirs | union(item.stdout_lines) | list
        }}'
    loop: '{{ result_found_dirs.results }}'
    when: result_found_dirs is not skipped and item is not skipped
    tags:
    - DISA-STIG-OL09-00-002510
    - NIST-800-53-AC-6(1)
    - NIST-800-53-CM-6(a)
    - PCI-DSSv4-2.2
    - PCI-DSSv4-2.2.6
    - dir_perms_world_writable_sticky_bits
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Verify that All World-Writable Directories Have Sticky Bits Set - Ensure
      Sticky Bit is Set on Local World Writable Directories
    ansible.builtin.file:
      path: '{{ item }}'
      mode: a+t
    loop: '{{ world_writable_dirs }}'
    tags:
    - DISA-STIG-OL09-00-002510
    - NIST-800-53-AC-6(1)
    - NIST-800-53-CM-6(a)
    - PCI-DSSv4-2.2
    - PCI-DSSv4-2.2.6
    - dir_perms_world_writable_sticky_bits
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Enable Kernel Parameter to Enforce DAC on Hardlinks - Set fact for sysctl
      paths
    ansible.builtin.set_fact:
      sysctl_paths:
      - /etc/sysctl.d/
      - /run/sysctl.d/
      - /usr/local/lib/sysctl.d/
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-002401
    - NIST-800-53-AC-6(1)
    - NIST-800-53-CM-6(a)
    - disable_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - reboot_required
    - sysctl_fs_protected_hardlinks

  - name: Enable Kernel Parameter to Enforce DAC on Hardlinks - Find all files that
      contain fs.protected_hardlinks
    ansible.builtin.shell:
      cmd: find -L {{ sysctl_paths | join(" ") }} -type f -name '*.conf' | xargs grep
        -HP '^\s*fs.protected_hardlinks\s*=\s*.*$'
    register: find_all_values
    check_mode: false
    changed_when: false
    failed_when: false
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-002401
    - NIST-800-53-AC-6(1)
    - NIST-800-53-CM-6(a)
    - disable_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - reboot_required
    - sysctl_fs_protected_hardlinks

  - name: Enable Kernel Parameter to Enforce DAC on Hardlinks - Find all files that
      set fs.protected_hardlinks to correct value
    ansible.builtin.shell:
      cmd: find -L {{ sysctl_paths | join(" ") }} -type f -name '*.conf' | xargs grep
        -HP '^\s*fs.protected_hardlinks\s*=\s*1$'
    register: find_correct_value
    check_mode: false
    changed_when: false
    failed_when: false
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-002401
    - NIST-800-53-AC-6(1)
    - NIST-800-53-CM-6(a)
    - disable_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - reboot_required
    - sysctl_fs_protected_hardlinks

  - name: Enable Kernel Parameter to Enforce DAC on Hardlinks - Comment out any occurrences
      of fs.protected_hardlinks from config files
    ansible.builtin.replace:
      path: '{{ item | split(":") | first }}'
      regexp: ^[\s]*fs.protected_hardlinks
      replace: '#fs.protected_hardlinks'
    loop: '{{ find_all_values.stdout_lines }}'
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - find_correct_value.stdout_lines | length == 0 or find_all_values.stdout_lines
      | length > find_correct_value.stdout_lines | length
    tags:
    - DISA-STIG-OL09-00-002401
    - NIST-800-53-AC-6(1)
    - NIST-800-53-CM-6(a)
    - disable_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - reboot_required
    - sysctl_fs_protected_hardlinks

  - name: Enable Kernel Parameter to Enforce DAC on Hardlinks - Comment out any occurrences
      of fs.protected_hardlinks from /etc/sysctl.conf
    ansible.builtin.replace:
      path: '{{ item }}'
      regexp: ^[\s]*fs.protected_hardlinks
      replace: '#fs.protected_hardlinks'
    with_fileglob:
    - /etc/sysctl.conf
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-002401
    - NIST-800-53-AC-6(1)
    - NIST-800-53-CM-6(a)
    - disable_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - reboot_required
    - sysctl_fs_protected_hardlinks

  - name: Enable Kernel Parameter to Enforce DAC on Hardlinks - Ensure sysctl fs.protected_hardlinks
      is set to 1
    ansible.posix.sysctl:
      name: fs.protected_hardlinks
      value: '1'
      sysctl_file: /etc/sysctl.d/fs_protected_hardlinks.conf
      state: present
      reload: true
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-002401
    - NIST-800-53-AC-6(1)
    - NIST-800-53-CM-6(a)
    - disable_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - reboot_required
    - sysctl_fs_protected_hardlinks

  - name: Enable Kernel Parameter to Enforce DAC on Symlinks - Set fact for sysctl
      paths
    ansible.builtin.set_fact:
      sysctl_paths:
      - /etc/sysctl.d/
      - /run/sysctl.d/
      - /usr/local/lib/sysctl.d/
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-002402
    - NIST-800-53-AC-6(1)
    - NIST-800-53-CM-6(a)
    - disable_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - reboot_required
    - sysctl_fs_protected_symlinks

  - name: Enable Kernel Parameter to Enforce DAC on Symlinks - Find all files that
      contain fs.protected_symlinks
    ansible.builtin.shell:
      cmd: find -L {{ sysctl_paths | join(" ") }} -type f -name '*.conf' | xargs grep
        -HP '^\s*fs.protected_symlinks\s*=\s*.*$'
    register: find_all_values
    check_mode: false
    changed_when: false
    failed_when: false
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-002402
    - NIST-800-53-AC-6(1)
    - NIST-800-53-CM-6(a)
    - disable_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - reboot_required
    - sysctl_fs_protected_symlinks

  - name: Enable Kernel Parameter to Enforce DAC on Symlinks - Find all files that
      set fs.protected_symlinks to correct value
    ansible.builtin.shell:
      cmd: find -L {{ sysctl_paths | join(" ") }} -type f -name '*.conf' | xargs grep
        -HP '^\s*fs.protected_symlinks\s*=\s*1$'
    register: find_correct_value
    check_mode: false
    changed_when: false
    failed_when: false
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-002402
    - NIST-800-53-AC-6(1)
    - NIST-800-53-CM-6(a)
    - disable_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - reboot_required
    - sysctl_fs_protected_symlinks

  - name: Enable Kernel Parameter to Enforce DAC on Symlinks - Comment out any occurrences
      of fs.protected_symlinks from config files
    ansible.builtin.replace:
      path: '{{ item | split(":") | first }}'
      regexp: ^[\s]*fs.protected_symlinks
      replace: '#fs.protected_symlinks'
    loop: '{{ find_all_values.stdout_lines }}'
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - find_correct_value.stdout_lines | length == 0 or find_all_values.stdout_lines
      | length > find_correct_value.stdout_lines | length
    tags:
    - DISA-STIG-OL09-00-002402
    - NIST-800-53-AC-6(1)
    - NIST-800-53-CM-6(a)
    - disable_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - reboot_required
    - sysctl_fs_protected_symlinks

  - name: Enable Kernel Parameter to Enforce DAC on Symlinks - Comment out any occurrences
      of fs.protected_symlinks from /etc/sysctl.conf
    ansible.builtin.replace:
      path: '{{ item }}'
      regexp: ^[\s]*fs.protected_symlinks
      replace: '#fs.protected_symlinks'
    with_fileglob:
    - /etc/sysctl.conf
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-002402
    - NIST-800-53-AC-6(1)
    - NIST-800-53-CM-6(a)
    - disable_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - reboot_required
    - sysctl_fs_protected_symlinks

  - name: Enable Kernel Parameter to Enforce DAC on Symlinks - Ensure sysctl fs.protected_symlinks
      is set to 1
    ansible.posix.sysctl:
      name: fs.protected_symlinks
      value: '1'
      sysctl_file: /etc/sysctl.d/fs_protected_symlinks.conf
      state: present
      reload: true
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-002402
    - NIST-800-53-AC-6(1)
    - NIST-800-53-CM-6(a)
    - disable_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - reboot_required
    - sysctl_fs_protected_symlinks

  - name: Set the file_groupowner_backup_etc_group_newgroup variable if represented
      by gid
    ansible.builtin.set_fact:
      file_groupowner_backup_etc_group_newgroup: '0'
    tags:
    - DISA-STIG-OL09-00-002533
    - NIST-800-53-AC-6 (1)
    - PCI-DSS-Req-8.7
    - PCI-DSSv4-2.2
    - PCI-DSSv4-2.2.6
    - configure_strategy
    - file_groupowner_backup_etc_group
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

  - name: Test for existence /etc/group-
    ansible.builtin.stat:
      path: /etc/group-
    register: file_exists
    tags:
    - DISA-STIG-OL09-00-002533
    - NIST-800-53-AC-6 (1)
    - PCI-DSS-Req-8.7
    - PCI-DSSv4-2.2
    - PCI-DSSv4-2.2.6
    - configure_strategy
    - file_groupowner_backup_etc_group
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

  - name: Ensure group owner on /etc/group-
    ansible.builtin.file:
      path: /etc/group-
      follow: false
      group: '{{ file_groupowner_backup_etc_group_newgroup }}'
    when: file_exists.stat is defined and file_exists.stat.exists
    tags:
    - DISA-STIG-OL09-00-002533
    - NIST-800-53-AC-6 (1)
    - PCI-DSS-Req-8.7
    - PCI-DSSv4-2.2
    - PCI-DSSv4-2.2.6
    - configure_strategy
    - file_groupowner_backup_etc_group
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

  - name: Set the file_groupowner_backup_etc_gshadow_newgroup variable if represented
      by gid
    ansible.builtin.set_fact:
      file_groupowner_backup_etc_gshadow_newgroup: '0'
    tags:
    - DISA-STIG-OL09-00-002539
    - NIST-800-53-AC-6 (1)
    - PCI-DSS-Req-8.7
    - configure_strategy
    - file_groupowner_backup_etc_gshadow
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

  - name: Test for existence /etc/gshadow-
    ansible.builtin.stat:
      path: /etc/gshadow-
    register: file_exists
    tags:
    - DISA-STIG-OL09-00-002539
    - NIST-800-53-AC-6 (1)
    - PCI-DSS-Req-8.7
    - configure_strategy
    - file_groupowner_backup_etc_gshadow
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

  - name: Ensure group owner on /etc/gshadow-
    ansible.builtin.file:
      path: /etc/gshadow-
      follow: false
      group: '{{ file_groupowner_backup_etc_gshadow_newgroup }}'
    when: file_exists.stat is defined and file_exists.stat.exists
    tags:
    - DISA-STIG-OL09-00-002539
    - NIST-800-53-AC-6 (1)
    - PCI-DSS-Req-8.7
    - configure_strategy
    - file_groupowner_backup_etc_gshadow
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

  - name: Set the file_groupowner_backup_etc_passwd_newgroup variable if represented
      by gid
    ansible.builtin.set_fact:
      file_groupowner_backup_etc_passwd_newgroup: '0'
    tags:
    - DISA-STIG-OL09-00-002545
    - NIST-800-53-AC-6 (1)
    - PCI-DSS-Req-8.7
    - PCI-DSSv4-2.2
    - PCI-DSSv4-2.2.6
    - configure_strategy
    - file_groupowner_backup_etc_passwd
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

  - name: Test for existence /etc/passwd-
    ansible.builtin.stat:
      path: /etc/passwd-
    register: file_exists
    tags:
    - DISA-STIG-OL09-00-002545
    - NIST-800-53-AC-6 (1)
    - PCI-DSS-Req-8.7
    - PCI-DSSv4-2.2
    - PCI-DSSv4-2.2.6
    - configure_strategy
    - file_groupowner_backup_etc_passwd
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

  - name: Ensure group owner on /etc/passwd-
    ansible.builtin.file:
      path: /etc/passwd-
      follow: false
      group: '{{ file_groupowner_backup_etc_passwd_newgroup }}'
    when: file_exists.stat is defined and file_exists.stat.exists
    tags:
    - DISA-STIG-OL09-00-002545
    - NIST-800-53-AC-6 (1)
    - PCI-DSS-Req-8.7
    - PCI-DSSv4-2.2
    - PCI-DSSv4-2.2.6
    - configure_strategy
    - file_groupowner_backup_etc_passwd
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

  - name: Set the file_groupowner_backup_etc_shadow_newgroup variable if represented
      by gid
    ansible.builtin.set_fact:
      file_groupowner_backup_etc_shadow_newgroup: '0'
    tags:
    - DISA-STIG-OL09-00-002551
    - PCI-DSS-Req-8.7
    - PCI-DSSv4-2.2
    - PCI-DSSv4-2.2.6
    - configure_strategy
    - file_groupowner_backup_etc_shadow
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

  - name: Test for existence /etc/shadow-
    ansible.builtin.stat:
      path: /etc/shadow-
    register: file_exists
    tags:
    - DISA-STIG-OL09-00-002551
    - PCI-DSS-Req-8.7
    - PCI-DSSv4-2.2
    - PCI-DSSv4-2.2.6
    - configure_strategy
    - file_groupowner_backup_etc_shadow
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

  - name: Ensure group owner on /etc/shadow-
    ansible.builtin.file:
      path: /etc/shadow-
      follow: false
      group: '{{ file_groupowner_backup_etc_shadow_newgroup }}'
    when: file_exists.stat is defined and file_exists.stat.exists
    tags:
    - DISA-STIG-OL09-00-002551
    - PCI-DSS-Req-8.7
    - PCI-DSSv4-2.2
    - PCI-DSSv4-2.2.6
    - configure_strategy
    - file_groupowner_backup_etc_shadow
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

  - name: Set the file_groupowner_etc_group_newgroup variable if represented by gid
    ansible.builtin.set_fact:
      file_groupowner_etc_group_newgroup: '0'
    tags:
    - CJIS-5.5.2.2
    - DISA-STIG-OL09-00-002532
    - NIST-800-53-AC-6(1)
    - NIST-800-53-CM-6(a)
    - PCI-DSS-Req-8.7.c
    - PCI-DSSv4-2.2
    - PCI-DSSv4-2.2.6
    - configure_strategy
    - file_groupowner_etc_group
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

  - name: Test for existence /etc/group
    ansible.builtin.stat:
      path: /etc/group
    register: file_exists
    tags:
    - CJIS-5.5.2.2
    - DISA-STIG-OL09-00-002532
    - NIST-800-53-AC-6(1)
    - NIST-800-53-CM-6(a)
    - PCI-DSS-Req-8.7.c
    - PCI-DSSv4-2.2
    - PCI-DSSv4-2.2.6
    - configure_strategy
    - file_groupowner_etc_group
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

  - name: Ensure group owner on /etc/group
    ansible.builtin.file:
      path: /etc/group
      follow: false
      group: '{{ file_groupowner_etc_group_newgroup }}'
    when: file_exists.stat is defined and file_exists.stat.exists
    tags:
    - CJIS-5.5.2.2
    - DISA-STIG-OL09-00-002532
    - NIST-800-53-AC-6(1)
    - NIST-800-53-CM-6(a)
    - PCI-DSS-Req-8.7.c
    - PCI-DSSv4-2.2
    - PCI-DSSv4-2.2.6
    - configure_strategy
    - file_groupowner_etc_group
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

  - name: Set the file_groupowner_etc_gshadow_newgroup variable if represented by
      gid
    ansible.builtin.set_fact:
      file_groupowner_etc_gshadow_newgroup: '0'
    tags:
    - DISA-STIG-OL09-00-002538
    - NIST-800-53-AC-6(1)
    - NIST-800-53-CM-6(a)
    - configure_strategy
    - file_groupowner_etc_gshadow
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

  - name: Test for existence /etc/gshadow
    ansible.builtin.stat:
      path: /etc/gshadow
    register: file_exists
    tags:
    - DISA-STIG-OL09-00-002538
    - NIST-800-53-AC-6(1)
    - NIST-800-53-CM-6(a)
    - configure_strategy
    - file_groupowner_etc_gshadow
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

  - name: Ensure group owner on /etc/gshadow
    ansible.builtin.file:
      path: /etc/gshadow
      follow: false
      group: '{{ file_groupowner_etc_gshadow_newgroup }}'
    when: file_exists.stat is defined and file_exists.stat.exists
    tags:
    - DISA-STIG-OL09-00-002538
    - NIST-800-53-AC-6(1)
    - NIST-800-53-CM-6(a)
    - configure_strategy
    - file_groupowner_etc_gshadow
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

  - name: Set the file_groupowner_etc_passwd_newgroup variable if represented by gid
    ansible.builtin.set_fact:
      file_groupowner_etc_passwd_newgroup: '0'
    tags:
    - CJIS-5.5.2.2
    - DISA-STIG-OL09-00-002544
    - NIST-800-53-AC-6(1)
    - NIST-800-53-CM-6(a)
    - PCI-DSS-Req-8.7.c
    - PCI-DSSv4-2.2
    - PCI-DSSv4-2.2.6
    - configure_strategy
    - file_groupowner_etc_passwd
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

  - name: Test for existence /etc/passwd
    ansible.builtin.stat:
      path: /etc/passwd
    register: file_exists
    tags:
    - CJIS-5.5.2.2
    - DISA-STIG-OL09-00-002544
    - NIST-800-53-AC-6(1)
    - NIST-800-53-CM-6(a)
    - PCI-DSS-Req-8.7.c
    - PCI-DSSv4-2.2
    - PCI-DSSv4-2.2.6
    - configure_strategy
    - file_groupowner_etc_passwd
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

  - name: Ensure group owner on /etc/passwd
    ansible.builtin.file:
      path: /etc/passwd
      follow: false
      group: '{{ file_groupowner_etc_passwd_newgroup }}'
    when: file_exists.stat is defined and file_exists.stat.exists
    tags:
    - CJIS-5.5.2.2
    - DISA-STIG-OL09-00-002544
    - NIST-800-53-AC-6(1)
    - NIST-800-53-CM-6(a)
    - PCI-DSS-Req-8.7.c
    - PCI-DSSv4-2.2
    - PCI-DSSv4-2.2.6
    - configure_strategy
    - file_groupowner_etc_passwd
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

  - name: Set the file_groupowner_etc_shadow_newgroup variable if represented by gid
    ansible.builtin.set_fact:
      file_groupowner_etc_shadow_newgroup: '0'
    tags:
    - CJIS-5.5.2.2
    - DISA-STIG-OL09-00-002550
    - NIST-800-53-AC-6(1)
    - NIST-800-53-CM-6(a)
    - PCI-DSS-Req-8.7.c
    - PCI-DSSv4-2.2
    - PCI-DSSv4-2.2.6
    - configure_strategy
    - file_groupowner_etc_shadow
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

  - name: Test for existence /etc/shadow
    ansible.builtin.stat:
      path: /etc/shadow
    register: file_exists
    tags:
    - CJIS-5.5.2.2
    - DISA-STIG-OL09-00-002550
    - NIST-800-53-AC-6(1)
    - NIST-800-53-CM-6(a)
    - PCI-DSS-Req-8.7.c
    - PCI-DSSv4-2.2
    - PCI-DSSv4-2.2.6
    - configure_strategy
    - file_groupowner_etc_shadow
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

  - name: Ensure group owner on /etc/shadow
    ansible.builtin.file:
      path: /etc/shadow
      follow: false
      group: '{{ file_groupowner_etc_shadow_newgroup }}'
    when: file_exists.stat is defined and file_exists.stat.exists
    tags:
    - CJIS-5.5.2.2
    - DISA-STIG-OL09-00-002550
    - NIST-800-53-AC-6(1)
    - NIST-800-53-CM-6(a)
    - PCI-DSS-Req-8.7.c
    - PCI-DSSv4-2.2
    - PCI-DSSv4-2.2.6
    - configure_strategy
    - file_groupowner_etc_shadow
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

  - name: Set the file_owner_backup_etc_group_newown variable if represented by uid
    ansible.builtin.set_fact:
      file_owner_backup_etc_group_newown: '0'
    tags:
    - DISA-STIG-OL09-00-002535
    - NIST-800-53-AC-6 (1)
    - PCI-DSS-Req-8.7.c
    - PCI-DSSv4-2.2
    - PCI-DSSv4-2.2.6
    - configure_strategy
    - file_owner_backup_etc_group
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

  - name: Test for existence /etc/group-
    ansible.builtin.stat:
      path: /etc/group-
    register: file_exists
    tags:
    - DISA-STIG-OL09-00-002535
    - NIST-800-53-AC-6 (1)
    - PCI-DSS-Req-8.7.c
    - PCI-DSSv4-2.2
    - PCI-DSSv4-2.2.6
    - configure_strategy
    - file_owner_backup_etc_group
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

  - name: Ensure owner on /etc/group-
    ansible.builtin.file:
      path: /etc/group-
      follow: false
      owner: '{{ file_owner_backup_etc_group_newown }}'
    when: file_exists.stat is defined and file_exists.stat.exists
    tags:
    - DISA-STIG-OL09-00-002535
    - NIST-800-53-AC-6 (1)
    - PCI-DSS-Req-8.7.c
    - PCI-DSSv4-2.2
    - PCI-DSSv4-2.2.6
    - configure_strategy
    - file_owner_backup_etc_group
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

  - name: Set the file_owner_backup_etc_gshadow_newown variable if represented by
      uid
    ansible.builtin.set_fact:
      file_owner_backup_etc_gshadow_newown: '0'
    tags:
    - DISA-STIG-OL09-00-002541
    - NIST-800-53-AC-6 (1)
    - PCI-DSS-Req-8.7
    - configure_strategy
    - file_owner_backup_etc_gshadow
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

  - name: Test for existence /etc/gshadow-
    ansible.builtin.stat:
      path: /etc/gshadow-
    register: file_exists
    tags:
    - DISA-STIG-OL09-00-002541
    - NIST-800-53-AC-6 (1)
    - PCI-DSS-Req-8.7
    - configure_strategy
    - file_owner_backup_etc_gshadow
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

  - name: Ensure owner on /etc/gshadow-
    ansible.builtin.file:
      path: /etc/gshadow-
      follow: false
      owner: '{{ file_owner_backup_etc_gshadow_newown }}'
    when: file_exists.stat is defined and file_exists.stat.exists
    tags:
    - DISA-STIG-OL09-00-002541
    - NIST-800-53-AC-6 (1)
    - PCI-DSS-Req-8.7
    - configure_strategy
    - file_owner_backup_etc_gshadow
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

  - name: Set the file_owner_backup_etc_passwd_newown variable if represented by uid
    ansible.builtin.set_fact:
      file_owner_backup_etc_passwd_newown: '0'
    tags:
    - DISA-STIG-OL09-00-002547
    - NIST-800-53-AC-6 (1)
    - PCI-DSS-Req-8.7.c
    - PCI-DSSv4-2.2
    - PCI-DSSv4-2.2.6
    - configure_strategy
    - file_owner_backup_etc_passwd
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

  - name: Test for existence /etc/passwd-
    ansible.builtin.stat:
      path: /etc/passwd-
    register: file_exists
    tags:
    - DISA-STIG-OL09-00-002547
    - NIST-800-53-AC-6 (1)
    - PCI-DSS-Req-8.7.c
    - PCI-DSSv4-2.2
    - PCI-DSSv4-2.2.6
    - configure_strategy
    - file_owner_backup_etc_passwd
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

  - name: Ensure owner on /etc/passwd-
    ansible.builtin.file:
      path: /etc/passwd-
      follow: false
      owner: '{{ file_owner_backup_etc_passwd_newown }}'
    when: file_exists.stat is defined and file_exists.stat.exists
    tags:
    - DISA-STIG-OL09-00-002547
    - NIST-800-53-AC-6 (1)
    - PCI-DSS-Req-8.7.c
    - PCI-DSSv4-2.2
    - PCI-DSSv4-2.2.6
    - configure_strategy
    - file_owner_backup_etc_passwd
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

  - name: Set the file_owner_backup_etc_shadow_newown variable if represented by uid
    ansible.builtin.set_fact:
      file_owner_backup_etc_shadow_newown: '0'
    tags:
    - DISA-STIG-OL09-00-002553
    - NIST-800-53-AC-6 (1)
    - PCI-DSS-Req-8.7.c
    - PCI-DSSv4-2.2
    - PCI-DSSv4-2.2.6
    - configure_strategy
    - file_owner_backup_etc_shadow
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

  - name: Test for existence /etc/shadow-
    ansible.builtin.stat:
      path: /etc/shadow-
    register: file_exists
    tags:
    - DISA-STIG-OL09-00-002553
    - NIST-800-53-AC-6 (1)
    - PCI-DSS-Req-8.7.c
    - PCI-DSSv4-2.2
    - PCI-DSSv4-2.2.6
    - configure_strategy
    - file_owner_backup_etc_shadow
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

  - name: Ensure owner on /etc/shadow-
    ansible.builtin.file:
      path: /etc/shadow-
      follow: false
      owner: '{{ file_owner_backup_etc_shadow_newown }}'
    when: file_exists.stat is defined and file_exists.stat.exists
    tags:
    - DISA-STIG-OL09-00-002553
    - NIST-800-53-AC-6 (1)
    - PCI-DSS-Req-8.7.c
    - PCI-DSSv4-2.2
    - PCI-DSSv4-2.2.6
    - configure_strategy
    - file_owner_backup_etc_shadow
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

  - name: Set the file_owner_etc_group_newown variable if represented by uid
    ansible.builtin.set_fact:
      file_owner_etc_group_newown: '0'
    tags:
    - CJIS-5.5.2.2
    - DISA-STIG-OL09-00-002534
    - NIST-800-53-AC-6(1)
    - NIST-800-53-CM-6(a)
    - PCI-DSS-Req-8.7.c
    - PCI-DSSv4-2.2
    - PCI-DSSv4-2.2.6
    - configure_strategy
    - file_owner_etc_group
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

  - name: Test for existence /etc/group
    ansible.builtin.stat:
      path: /etc/group
    register: file_exists
    tags:
    - CJIS-5.5.2.2
    - DISA-STIG-OL09-00-002534
    - NIST-800-53-AC-6(1)
    - NIST-800-53-CM-6(a)
    - PCI-DSS-Req-8.7.c
    - PCI-DSSv4-2.2
    - PCI-DSSv4-2.2.6
    - configure_strategy
    - file_owner_etc_group
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

  - name: Ensure owner on /etc/group
    ansible.builtin.file:
      path: /etc/group
      follow: false
      owner: '{{ file_owner_etc_group_newown }}'
    when: file_exists.stat is defined and file_exists.stat.exists
    tags:
    - CJIS-5.5.2.2
    - DISA-STIG-OL09-00-002534
    - NIST-800-53-AC-6(1)
    - NIST-800-53-CM-6(a)
    - PCI-DSS-Req-8.7.c
    - PCI-DSSv4-2.2
    - PCI-DSSv4-2.2.6
    - configure_strategy
    - file_owner_etc_group
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

  - name: Set the file_owner_etc_gshadow_newown variable if represented by uid
    ansible.builtin.set_fact:
      file_owner_etc_gshadow_newown: '0'
    tags:
    - DISA-STIG-OL09-00-002540
    - NIST-800-53-AC-6(1)
    - NIST-800-53-CM-6(a)
    - configure_strategy
    - file_owner_etc_gshadow
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

  - name: Test for existence /etc/gshadow
    ansible.builtin.stat:
      path: /etc/gshadow
    register: file_exists
    tags:
    - DISA-STIG-OL09-00-002540
    - NIST-800-53-AC-6(1)
    - NIST-800-53-CM-6(a)
    - configure_strategy
    - file_owner_etc_gshadow
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

  - name: Ensure owner on /etc/gshadow
    ansible.builtin.file:
      path: /etc/gshadow
      follow: false
      owner: '{{ file_owner_etc_gshadow_newown }}'
    when: file_exists.stat is defined and file_exists.stat.exists
    tags:
    - DISA-STIG-OL09-00-002540
    - NIST-800-53-AC-6(1)
    - NIST-800-53-CM-6(a)
    - configure_strategy
    - file_owner_etc_gshadow
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

  - name: Set the file_owner_etc_passwd_newown variable if represented by uid
    ansible.builtin.set_fact:
      file_owner_etc_passwd_newown: '0'
    tags:
    - CJIS-5.5.2.2
    - DISA-STIG-OL09-00-002546
    - NIST-800-53-AC-6(1)
    - NIST-800-53-CM-6(a)
    - PCI-DSS-Req-8.7.c
    - PCI-DSSv4-2.2
    - PCI-DSSv4-2.2.6
    - configure_strategy
    - file_owner_etc_passwd
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

  - name: Test for existence /etc/passwd
    ansible.builtin.stat:
      path: /etc/passwd
    register: file_exists
    tags:
    - CJIS-5.5.2.2
    - DISA-STIG-OL09-00-002546
    - NIST-800-53-AC-6(1)
    - NIST-800-53-CM-6(a)
    - PCI-DSS-Req-8.7.c
    - PCI-DSSv4-2.2
    - PCI-DSSv4-2.2.6
    - configure_strategy
    - file_owner_etc_passwd
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

  - name: Ensure owner on /etc/passwd
    ansible.builtin.file:
      path: /etc/passwd
      follow: false
      owner: '{{ file_owner_etc_passwd_newown }}'
    when: file_exists.stat is defined and file_exists.stat.exists
    tags:
    - CJIS-5.5.2.2
    - DISA-STIG-OL09-00-002546
    - NIST-800-53-AC-6(1)
    - NIST-800-53-CM-6(a)
    - PCI-DSS-Req-8.7.c
    - PCI-DSSv4-2.2
    - PCI-DSSv4-2.2.6
    - configure_strategy
    - file_owner_etc_passwd
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

  - name: Set the file_owner_etc_shadow_newown variable if represented by uid
    ansible.builtin.set_fact:
      file_owner_etc_shadow_newown: '0'
    tags:
    - CJIS-5.5.2.2
    - DISA-STIG-OL09-00-002552
    - NIST-800-53-AC-6(1)
    - NIST-800-53-CM-6(a)
    - PCI-DSS-Req-8.7.c
    - PCI-DSSv4-2.2
    - PCI-DSSv4-2.2.6
    - configure_strategy
    - file_owner_etc_shadow
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

  - name: Test for existence /etc/shadow
    ansible.builtin.stat:
      path: /etc/shadow
    register: file_exists
    tags:
    - CJIS-5.5.2.2
    - DISA-STIG-OL09-00-002552
    - NIST-800-53-AC-6(1)
    - NIST-800-53-CM-6(a)
    - PCI-DSS-Req-8.7.c
    - PCI-DSSv4-2.2
    - PCI-DSSv4-2.2.6
    - configure_strategy
    - file_owner_etc_shadow
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

  - name: Ensure owner on /etc/shadow
    ansible.builtin.file:
      path: /etc/shadow
      follow: false
      owner: '{{ file_owner_etc_shadow_newown }}'
    when: file_exists.stat is defined and file_exists.stat.exists
    tags:
    - CJIS-5.5.2.2
    - DISA-STIG-OL09-00-002552
    - NIST-800-53-AC-6(1)
    - NIST-800-53-CM-6(a)
    - PCI-DSS-Req-8.7.c
    - PCI-DSSv4-2.2
    - PCI-DSSv4-2.2.6
    - configure_strategy
    - file_owner_etc_shadow
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

  - name: Test for existence /etc/group-
    ansible.builtin.stat:
      path: /etc/group-
    register: file_exists
    tags:
    - DISA-STIG-OL09-00-002537
    - NIST-800-53-AC-6 (1)
    - PCI-DSS-Req-8.7.c
    - PCI-DSSv4-2.2
    - PCI-DSSv4-2.2.6
    - configure_strategy
    - file_permissions_backup_etc_group
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

  - name: Ensure permission u-xs,g-xws,o-xwt on /etc/group-
    ansible.builtin.file:
      path: /etc/group-
      mode: u-xs,g-xws,o-xwt
    when: file_exists.stat is defined and file_exists.stat.exists
    tags:
    - DISA-STIG-OL09-00-002537
    - NIST-800-53-AC-6 (1)
    - PCI-DSS-Req-8.7.c
    - PCI-DSSv4-2.2
    - PCI-DSSv4-2.2.6
    - configure_strategy
    - file_permissions_backup_etc_group
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

  - name: Test for existence /etc/gshadow-
    ansible.builtin.stat:
      path: /etc/gshadow-
    register: file_exists
    tags:
    - DISA-STIG-OL09-00-002543
    - NIST-800-53-AC-6 (1)
    - configure_strategy
    - file_permissions_backup_etc_gshadow
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

  - name: Ensure permission u-xwrs,g-xwrs,o-xwrt on /etc/gshadow-
    ansible.builtin.file:
      path: /etc/gshadow-
      mode: u-xwrs,g-xwrs,o-xwrt
    when: file_exists.stat is defined and file_exists.stat.exists
    tags:
    - DISA-STIG-OL09-00-002543
    - NIST-800-53-AC-6 (1)
    - configure_strategy
    - file_permissions_backup_etc_gshadow
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

  - name: Test for existence /etc/passwd-
    ansible.builtin.stat:
      path: /etc/passwd-
    register: file_exists
    tags:
    - DISA-STIG-OL09-00-002549
    - NIST-800-53-AC-6 (1)
    - PCI-DSS-Req-8.7.c
    - PCI-DSSv4-2.2
    - PCI-DSSv4-2.2.6
    - configure_strategy
    - file_permissions_backup_etc_passwd
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

  - name: Ensure permission u-xs,g-xws,o-xwt on /etc/passwd-
    ansible.builtin.file:
      path: /etc/passwd-
      mode: u-xs,g-xws,o-xwt
    when: file_exists.stat is defined and file_exists.stat.exists
    tags:
    - DISA-STIG-OL09-00-002549
    - NIST-800-53-AC-6 (1)
    - PCI-DSS-Req-8.7.c
    - PCI-DSSv4-2.2
    - PCI-DSSv4-2.2.6
    - configure_strategy
    - file_permissions_backup_etc_passwd
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

  - name: Test for existence /etc/shadow-
    ansible.builtin.stat:
      path: /etc/shadow-
    register: file_exists
    tags:
    - DISA-STIG-OL09-00-002554
    - NIST-800-53-AC-6 (1)
    - PCI-DSS-Req-8.7.c
    - PCI-DSSv4-2.2
    - PCI-DSSv4-2.2.6
    - configure_strategy
    - file_permissions_backup_etc_shadow
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

  - name: Ensure permission u-xwrs,g-xwrs,o-xwrt on /etc/shadow-
    ansible.builtin.file:
      path: /etc/shadow-
      mode: u-xwrs,g-xwrs,o-xwrt
    when: file_exists.stat is defined and file_exists.stat.exists
    tags:
    - DISA-STIG-OL09-00-002554
    - NIST-800-53-AC-6 (1)
    - PCI-DSS-Req-8.7.c
    - PCI-DSSv4-2.2
    - PCI-DSSv4-2.2.6
    - configure_strategy
    - file_permissions_backup_etc_shadow
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

  - name: Test for existence /etc/group
    ansible.builtin.stat:
      path: /etc/group
    register: file_exists
    tags:
    - CJIS-5.5.2.2
    - DISA-STIG-OL09-00-002536
    - NIST-800-53-AC-6(1)
    - NIST-800-53-CM-6(a)
    - PCI-DSS-Req-8.7.c
    - PCI-DSSv4-2.2
    - PCI-DSSv4-2.2.6
    - configure_strategy
    - file_permissions_etc_group
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

  - name: Ensure permission u-xs,g-xws,o-xwt on /etc/group
    ansible.builtin.file:
      path: /etc/group
      mode: u-xs,g-xws,o-xwt
    when: file_exists.stat is defined and file_exists.stat.exists
    tags:
    - CJIS-5.5.2.2
    - DISA-STIG-OL09-00-002536
    - NIST-800-53-AC-6(1)
    - NIST-800-53-CM-6(a)
    - PCI-DSS-Req-8.7.c
    - PCI-DSSv4-2.2
    - PCI-DSSv4-2.2.6
    - configure_strategy
    - file_permissions_etc_group
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

  - name: Test for existence /etc/gshadow
    ansible.builtin.stat:
      path: /etc/gshadow
    register: file_exists
    tags:
    - DISA-STIG-OL09-00-002542
    - NIST-800-53-AC-6(1)
    - NIST-800-53-CM-6(a)
    - configure_strategy
    - file_permissions_etc_gshadow
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

  - name: Ensure permission u-xwrs,g-xwrs,o-xwrt on /etc/gshadow
    ansible.builtin.file:
      path: /etc/gshadow
      mode: u-xwrs,g-xwrs,o-xwrt
    when: file_exists.stat is defined and file_exists.stat.exists
    tags:
    - DISA-STIG-OL09-00-002542
    - NIST-800-53-AC-6(1)
    - NIST-800-53-CM-6(a)
    - configure_strategy
    - file_permissions_etc_gshadow
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

  - name: Test for existence /etc/passwd
    ansible.builtin.stat:
      path: /etc/passwd
    register: file_exists
    tags:
    - CJIS-5.5.2.2
    - DISA-STIG-OL09-00-002548
    - NIST-800-53-AC-6(1)
    - NIST-800-53-CM-6(a)
    - PCI-DSS-Req-8.7.c
    - PCI-DSSv4-2.2
    - PCI-DSSv4-2.2.6
    - configure_strategy
    - file_permissions_etc_passwd
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

  - name: Ensure permission u-xs,g-xws,o-xwt on /etc/passwd
    ansible.builtin.file:
      path: /etc/passwd
      mode: u-xs,g-xws,o-xwt
    when: file_exists.stat is defined and file_exists.stat.exists
    tags:
    - CJIS-5.5.2.2
    - DISA-STIG-OL09-00-002548
    - NIST-800-53-AC-6(1)
    - NIST-800-53-CM-6(a)
    - PCI-DSS-Req-8.7.c
    - PCI-DSSv4-2.2
    - PCI-DSSv4-2.2.6
    - configure_strategy
    - file_permissions_etc_passwd
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

  - name: Test for existence /etc/shadow
    ansible.builtin.stat:
      path: /etc/shadow
    register: file_exists
    tags:
    - CJIS-5.5.2.2
    - DISA-STIG-OL09-00-002555
    - NIST-800-53-AC-6(1)
    - NIST-800-53-CM-6(a)
    - PCI-DSS-Req-8.7.c
    - PCI-DSSv4-2.2
    - PCI-DSSv4-2.2.6
    - configure_strategy
    - file_permissions_etc_shadow
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

  - name: Ensure permission u-xwrs,g-xwrs,o-xwrt on /etc/shadow
    ansible.builtin.file:
      path: /etc/shadow
      mode: u-xwrs,g-xwrs,o-xwrt
    when: file_exists.stat is defined and file_exists.stat.exists
    tags:
    - CJIS-5.5.2.2
    - DISA-STIG-OL09-00-002555
    - NIST-800-53-AC-6(1)
    - NIST-800-53-CM-6(a)
    - PCI-DSS-Req-8.7.c
    - PCI-DSSv4-2.2
    - PCI-DSSv4-2.2.6
    - configure_strategy
    - file_permissions_etc_shadow
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

  - name: Set the file_groupowner_var_log_newgroup variable if represented by gid
    ansible.builtin.set_fact:
      file_groupowner_var_log_newgroup: '0'
    tags:
    - DISA-STIG-OL09-00-002560
    - configure_strategy
    - file_groupowner_var_log
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

  - name: Ensure group owner on /var/log/
    ansible.builtin.file:
      path: /var/log/
      follow: false
      state: directory
      group: '{{ file_groupowner_var_log_newgroup }}'
    tags:
    - DISA-STIG-OL09-00-002560
    - configure_strategy
    - file_groupowner_var_log
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

  - name: Set the file_groupowner_var_log_messages_newgroup variable if represented
      by gid
    ansible.builtin.set_fact:
      file_groupowner_var_log_messages_newgroup: '0'
    tags:
    - DISA-STIG-OL09-00-002563
    - configure_strategy
    - file_groupowner_var_log_messages
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

  - name: Test for existence /var/log/messages
    ansible.builtin.stat:
      path: /var/log/messages
    register: file_exists
    tags:
    - DISA-STIG-OL09-00-002563
    - configure_strategy
    - file_groupowner_var_log_messages
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

  - name: Ensure group owner on /var/log/messages
    ansible.builtin.file:
      path: /var/log/messages
      follow: false
      group: '{{ file_groupowner_var_log_messages_newgroup }}'
    when: file_exists.stat is defined and file_exists.stat.exists
    tags:
    - DISA-STIG-OL09-00-002563
    - configure_strategy
    - file_groupowner_var_log_messages
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

  - name: Set the file_owner_var_log_newown variable if represented by uid
    ansible.builtin.set_fact:
      file_owner_var_log_newown: '0'
    tags:
    - DISA-STIG-OL09-00-002561
    - configure_strategy
    - file_owner_var_log
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

  - name: Ensure owner on directory /var/log/
    ansible.builtin.file:
      path: /var/log/
      follow: false
      state: directory
      owner: '{{ file_owner_var_log_newown }}'
    tags:
    - DISA-STIG-OL09-00-002561
    - configure_strategy
    - file_owner_var_log
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

  - name: Set the file_owner_var_log_messages_newown variable if represented by uid
    ansible.builtin.set_fact:
      file_owner_var_log_messages_newown: '0'
    tags:
    - DISA-STIG-OL09-00-002564
    - configure_strategy
    - file_owner_var_log_messages
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

  - name: Test for existence /var/log/messages
    ansible.builtin.stat:
      path: /var/log/messages
    register: file_exists
    tags:
    - DISA-STIG-OL09-00-002564
    - configure_strategy
    - file_owner_var_log_messages
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

  - name: Ensure owner on /var/log/messages
    ansible.builtin.file:
      path: /var/log/messages
      follow: false
      owner: '{{ file_owner_var_log_messages_newown }}'
    when: file_exists.stat is defined and file_exists.stat.exists
    tags:
    - DISA-STIG-OL09-00-002564
    - configure_strategy
    - file_owner_var_log_messages
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

  - name: Find /var/log/ file(s)
    ansible.builtin.command: 'find -P /var/log/ -maxdepth 0 -perm /u+s,g+ws,o+wt  -type
      d '
    register: files_found
    changed_when: false
    failed_when: false
    check_mode: false
    tags:
    - DISA-STIG-OL09-00-002562
    - configure_strategy
    - file_permissions_var_log
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

  - name: Set permissions for /var/log/ file(s)
    ansible.builtin.file:
      path: '{{ item }}'
      mode: u-s,g-ws,o-wt
      state: directory
    with_items:
    - '{{ files_found.stdout_lines }}'
    tags:
    - DISA-STIG-OL09-00-002562
    - configure_strategy
    - file_permissions_var_log
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

  - name: Test for existence /var/log/messages
    ansible.builtin.stat:
      path: /var/log/messages
    register: file_exists
    tags:
    - DISA-STIG-OL09-00-002565
    - configure_strategy
    - file_permissions_var_log_messages
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

  - name: Ensure permission u-xs,g-xws,o-xwrt on /var/log/messages
    ansible.builtin.file:
      path: /var/log/messages
      mode: u-xs,g-xws,o-xwrt
    when: file_exists.stat is defined and file_exists.stat.exists
    tags:
    - DISA-STIG-OL09-00-002565
    - configure_strategy
    - file_permissions_var_log_messages
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

  - name: Set the dir_group_ownership_library_dirs_newgroup variable if represented
      by gid
    ansible.builtin.set_fact:
      dir_group_ownership_library_dirs_newgroup: '0'
    tags:
    - DISA-STIG-OL09-00-002520
    - NIST-800-53-CM-5(6)
    - NIST-800-53-CM-5(6).1
    - configure_strategy
    - dir_group_ownership_library_dirs
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

  - name: Ensure group owner on /lib/ recursively
    ansible.builtin.file:
      path: /lib/
      follow: false
      state: directory
      recurse: true
      group: '{{ dir_group_ownership_library_dirs_newgroup }}'
    tags:
    - DISA-STIG-OL09-00-002520
    - NIST-800-53-CM-5(6)
    - NIST-800-53-CM-5(6).1
    - configure_strategy
    - dir_group_ownership_library_dirs
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

  - name: Ensure group owner on /lib64/ recursively
    ansible.builtin.file:
      path: /lib64/
      follow: false
      state: directory
      recurse: true
      group: '{{ dir_group_ownership_library_dirs_newgroup }}'
    tags:
    - DISA-STIG-OL09-00-002520
    - NIST-800-53-CM-5(6)
    - NIST-800-53-CM-5(6).1
    - configure_strategy
    - dir_group_ownership_library_dirs
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

  - name: Ensure group owner on /usr/lib/ recursively
    ansible.builtin.file:
      path: /usr/lib/
      follow: false
      state: directory
      recurse: true
      group: '{{ dir_group_ownership_library_dirs_newgroup }}'
    tags:
    - DISA-STIG-OL09-00-002520
    - NIST-800-53-CM-5(6)
    - NIST-800-53-CM-5(6).1
    - configure_strategy
    - dir_group_ownership_library_dirs
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

  - name: Ensure group owner on /usr/lib64/ recursively
    ansible.builtin.file:
      path: /usr/lib64/
      follow: false
      state: directory
      recurse: true
      group: '{{ dir_group_ownership_library_dirs_newgroup }}'
    tags:
    - DISA-STIG-OL09-00-002520
    - NIST-800-53-CM-5(6)
    - NIST-800-53-CM-5(6).1
    - configure_strategy
    - dir_group_ownership_library_dirs
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

  - name: Set the dir_ownership_library_dirs_newown variable if represented by uid
    ansible.builtin.set_fact:
      dir_ownership_library_dirs_newown: '0'
    tags:
    - DISA-STIG-OL09-00-002521
    - NIST-800-53-CM-5(6)
    - NIST-800-53-CM-5(6).1
    - configure_strategy
    - dir_ownership_library_dirs
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

  - name: Ensure owner on directory /lib/ recursively
    ansible.builtin.file:
      path: /lib/
      follow: false
      state: directory
      recurse: true
      owner: '{{ dir_ownership_library_dirs_newown }}'
    tags:
    - DISA-STIG-OL09-00-002521
    - NIST-800-53-CM-5(6)
    - NIST-800-53-CM-5(6).1
    - configure_strategy
    - dir_ownership_library_dirs
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

  - name: Ensure owner on directory /lib64/ recursively
    ansible.builtin.file:
      path: /lib64/
      follow: false
      state: directory
      recurse: true
      owner: '{{ dir_ownership_library_dirs_newown }}'
    tags:
    - DISA-STIG-OL09-00-002521
    - NIST-800-53-CM-5(6)
    - NIST-800-53-CM-5(6).1
    - configure_strategy
    - dir_ownership_library_dirs
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

  - name: Ensure owner on directory /usr/lib/ recursively
    ansible.builtin.file:
      path: /usr/lib/
      follow: false
      state: directory
      recurse: true
      owner: '{{ dir_ownership_library_dirs_newown }}'
    tags:
    - DISA-STIG-OL09-00-002521
    - NIST-800-53-CM-5(6)
    - NIST-800-53-CM-5(6).1
    - configure_strategy
    - dir_ownership_library_dirs
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

  - name: Ensure owner on directory /usr/lib64/ recursively
    ansible.builtin.file:
      path: /usr/lib64/
      follow: false
      state: directory
      recurse: true
      owner: '{{ dir_ownership_library_dirs_newown }}'
    tags:
    - DISA-STIG-OL09-00-002521
    - NIST-800-53-CM-5(6)
    - NIST-800-53-CM-5(6).1
    - configure_strategy
    - dir_ownership_library_dirs
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

  - name: Find /lib/ file(s) recursively
    ansible.builtin.command: 'find -P /lib/  -perm /g+w,o+w  -type d '
    register: files_found
    changed_when: false
    failed_when: false
    check_mode: false
    tags:
    - DISA-STIG-OL09-00-002522
    - NIST-800-53-CM-5
    - NIST-800-53-CM-5(6)
    - NIST-800-53-CM-5(6).1
    - configure_strategy
    - dir_permissions_library_dirs
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

  - name: Set permissions for /lib/ file(s)
    ansible.builtin.file:
      path: '{{ item }}'
      mode: g-w,o-w
      state: directory
    with_items:
    - '{{ files_found.stdout_lines }}'
    tags:
    - DISA-STIG-OL09-00-002522
    - NIST-800-53-CM-5
    - NIST-800-53-CM-5(6)
    - NIST-800-53-CM-5(6).1
    - configure_strategy
    - dir_permissions_library_dirs
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

  - name: Find /lib64/ file(s) recursively
    ansible.builtin.command: 'find -P /lib64/  -perm /g+w,o+w  -type d '
    register: files_found
    changed_when: false
    failed_when: false
    check_mode: false
    tags:
    - DISA-STIG-OL09-00-002522
    - NIST-800-53-CM-5
    - NIST-800-53-CM-5(6)
    - NIST-800-53-CM-5(6).1
    - configure_strategy
    - dir_permissions_library_dirs
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

  - name: Set permissions for /lib64/ file(s)
    ansible.builtin.file:
      path: '{{ item }}'
      mode: g-w,o-w
      state: directory
    with_items:
    - '{{ files_found.stdout_lines }}'
    tags:
    - DISA-STIG-OL09-00-002522
    - NIST-800-53-CM-5
    - NIST-800-53-CM-5(6)
    - NIST-800-53-CM-5(6).1
    - configure_strategy
    - dir_permissions_library_dirs
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

  - name: Find /usr/lib/ file(s) recursively
    ansible.builtin.command: 'find -P /usr/lib/  -perm /g+w,o+w  -type d '
    register: files_found
    changed_when: false
    failed_when: false
    check_mode: false
    tags:
    - DISA-STIG-OL09-00-002522
    - NIST-800-53-CM-5
    - NIST-800-53-CM-5(6)
    - NIST-800-53-CM-5(6).1
    - configure_strategy
    - dir_permissions_library_dirs
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

  - name: Set permissions for /usr/lib/ file(s)
    ansible.builtin.file:
      path: '{{ item }}'
      mode: g-w,o-w
      state: directory
    with_items:
    - '{{ files_found.stdout_lines }}'
    tags:
    - DISA-STIG-OL09-00-002522
    - NIST-800-53-CM-5
    - NIST-800-53-CM-5(6)
    - NIST-800-53-CM-5(6).1
    - configure_strategy
    - dir_permissions_library_dirs
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

  - name: Find /usr/lib64/ file(s) recursively
    ansible.builtin.command: 'find -P /usr/lib64/  -perm /g+w,o+w  -type d '
    register: files_found
    changed_when: false
    failed_when: false
    check_mode: false
    tags:
    - DISA-STIG-OL09-00-002522
    - NIST-800-53-CM-5
    - NIST-800-53-CM-5(6)
    - NIST-800-53-CM-5(6).1
    - configure_strategy
    - dir_permissions_library_dirs
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

  - name: Set permissions for /usr/lib64/ file(s)
    ansible.builtin.file:
      path: '{{ item }}'
      mode: g-w,o-w
      state: directory
    with_items:
    - '{{ files_found.stdout_lines }}'
    tags:
    - DISA-STIG-OL09-00-002522
    - NIST-800-53-CM-5
    - NIST-800-53-CM-5(6)
    - NIST-800-53-CM-5(6).1
    - configure_strategy
    - dir_permissions_library_dirs
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

  - name: Verify that system commands files are group owned by root or a system account
      - Find system command files with incorrect group ownership
    ansible.builtin.find:
      paths: '{{ item }}'
      file_type: file
      follow: false
      recurse: false
    register: system_command_files_found
    with_items:
    - /bin
    - /sbin
    - /usr/bin
    - /usr/sbin
    - /usr/libexec
    - /usr/local/bin
    - /usr/local/sbin
    changed_when: false
    tags:
    - DISA-STIG-OL09-00-002504
    - NIST-800-53-CM-5(6)
    - NIST-800-53-CM-5(6).1
    - file_groupownership_system_commands_dirs
    - medium_complexity
    - medium_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Verify that system commands files are group owned by root or a system account
      - Set group ownership to root for system command files
    ansible.builtin.file:
      path: '{{ item.path }}'
      group: root
    with_items: '{{ system_command_files_found.results | map(attribute=''files'')
      | flatten | rejectattr(''gr_name'', ''equalto'', ''root'') | list }}'
    tags:
    - DISA-STIG-OL09-00-002504
    - NIST-800-53-CM-5(6)
    - NIST-800-53-CM-5(6).1
    - file_groupownership_system_commands_dirs
    - medium_complexity
    - medium_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Read list of system executables without root ownership
    ansible.builtin.command: find /bin/ /usr/bin/ /usr/local/bin/ /sbin/ /usr/sbin/
      /usr/local/sbin/ /usr/libexec \! -user root
    register: no_root_system_executables
    changed_when: false
    failed_when: false
    check_mode: false
    tags:
    - DISA-STIG-OL09-00-002505
    - NIST-800-53-AC-6(1)
    - NIST-800-53-CM-5(6)
    - NIST-800-53-CM-5(6).1
    - NIST-800-53-CM-6(a)
    - file_ownership_binary_dirs
    - medium_complexity
    - medium_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Set ownership to root of system executables
    ansible.builtin.file:
      path: '{{ item }}'
      owner: root
    with_items: '{{ no_root_system_executables.stdout_lines }}'
    when: no_root_system_executables.stdout_lines | length > 0
    tags:
    - DISA-STIG-OL09-00-002505
    - NIST-800-53-AC-6(1)
    - NIST-800-53-CM-5(6)
    - NIST-800-53-CM-5(6).1
    - NIST-800-53-CM-6(a)
    - file_ownership_binary_dirs
    - medium_complexity
    - medium_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Set the file_ownership_library_dirs_newown variable if represented by uid
    ansible.builtin.set_fact:
      file_ownership_library_dirs_newown: '0'
    tags:
    - DISA-STIG-OL09-00-002524
    - NIST-800-53-AC-6(1)
    - NIST-800-53-CM-5(6)
    - NIST-800-53-CM-5(6).1
    - NIST-800-53-CM-6(a)
    - configure_strategy
    - file_ownership_library_dirs
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

  - name: Find /lib/ file(s) matching ^.*\.so.*$ recursively
    ansible.builtin.command: find -P /lib/  -type f  ! -user 0 -regextype posix-extended
      -regex "^.*\.so.*$"
    register: files_found
    changed_when: false
    failed_when: false
    check_mode: false
    tags:
    - DISA-STIG-OL09-00-002524
    - NIST-800-53-AC-6(1)
    - NIST-800-53-CM-5(6)
    - NIST-800-53-CM-5(6).1
    - NIST-800-53-CM-6(a)
    - configure_strategy
    - file_ownership_library_dirs
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

  - name: Ensure owner on /lib/ file(s) matching ^.*\.so.*$
    ansible.builtin.file:
      path: '{{ item }}'
      follow: false
      owner: '{{ file_ownership_library_dirs_newown }}'
      state: file
    with_items:
    - '{{ files_found.stdout_lines }}'
    tags:
    - DISA-STIG-OL09-00-002524
    - NIST-800-53-AC-6(1)
    - NIST-800-53-CM-5(6)
    - NIST-800-53-CM-5(6).1
    - NIST-800-53-CM-6(a)
    - configure_strategy
    - file_ownership_library_dirs
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

  - name: Find /lib64/ file(s) matching ^.*\.so.*$ recursively
    ansible.builtin.command: find -P /lib64/  -type f  ! -user 0 -regextype posix-extended
      -regex "^.*\.so.*$"
    register: files_found
    changed_when: false
    failed_when: false
    check_mode: false
    tags:
    - DISA-STIG-OL09-00-002524
    - NIST-800-53-AC-6(1)
    - NIST-800-53-CM-5(6)
    - NIST-800-53-CM-5(6).1
    - NIST-800-53-CM-6(a)
    - configure_strategy
    - file_ownership_library_dirs
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

  - name: Ensure owner on /lib64/ file(s) matching ^.*\.so.*$
    ansible.builtin.file:
      path: '{{ item }}'
      follow: false
      owner: '{{ file_ownership_library_dirs_newown }}'
      state: file
    with_items:
    - '{{ files_found.stdout_lines }}'
    tags:
    - DISA-STIG-OL09-00-002524
    - NIST-800-53-AC-6(1)
    - NIST-800-53-CM-5(6)
    - NIST-800-53-CM-5(6).1
    - NIST-800-53-CM-6(a)
    - configure_strategy
    - file_ownership_library_dirs
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

  - name: Find /usr/lib/ file(s) matching ^.*\.so.*$ recursively
    ansible.builtin.command: find -P /usr/lib/  -type f  ! -user 0 -regextype posix-extended
      -regex "^.*\.so.*$"
    register: files_found
    changed_when: false
    failed_when: false
    check_mode: false
    tags:
    - DISA-STIG-OL09-00-002524
    - NIST-800-53-AC-6(1)
    - NIST-800-53-CM-5(6)
    - NIST-800-53-CM-5(6).1
    - NIST-800-53-CM-6(a)
    - configure_strategy
    - file_ownership_library_dirs
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

  - name: Ensure owner on /usr/lib/ file(s) matching ^.*\.so.*$
    ansible.builtin.file:
      path: '{{ item }}'
      follow: false
      owner: '{{ file_ownership_library_dirs_newown }}'
      state: file
    with_items:
    - '{{ files_found.stdout_lines }}'
    tags:
    - DISA-STIG-OL09-00-002524
    - NIST-800-53-AC-6(1)
    - NIST-800-53-CM-5(6)
    - NIST-800-53-CM-5(6).1
    - NIST-800-53-CM-6(a)
    - configure_strategy
    - file_ownership_library_dirs
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

  - name: Find /usr/lib64/ file(s) matching ^.*\.so.*$ recursively
    ansible.builtin.command: find -P /usr/lib64/  -type f  ! -user 0 -regextype posix-extended
      -regex "^.*\.so.*$"
    register: files_found
    changed_when: false
    failed_when: false
    check_mode: false
    tags:
    - DISA-STIG-OL09-00-002524
    - NIST-800-53-AC-6(1)
    - NIST-800-53-CM-5(6)
    - NIST-800-53-CM-5(6).1
    - NIST-800-53-CM-6(a)
    - configure_strategy
    - file_ownership_library_dirs
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

  - name: Ensure owner on /usr/lib64/ file(s) matching ^.*\.so.*$
    ansible.builtin.file:
      path: '{{ item }}'
      follow: false
      owner: '{{ file_ownership_library_dirs_newown }}'
      state: file
    with_items:
    - '{{ files_found.stdout_lines }}'
    tags:
    - DISA-STIG-OL09-00-002524
    - NIST-800-53-AC-6(1)
    - NIST-800-53-CM-5(6)
    - NIST-800-53-CM-5(6).1
    - NIST-800-53-CM-6(a)
    - configure_strategy
    - file_ownership_library_dirs
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

  - name: Read list of world and group writable system executables
    ansible.builtin.command: find -L /bin /usr/bin /usr/local/bin /sbin /usr/sbin
      /usr/local/sbin /usr/libexec -perm /022 \( -type l -o -type f \)
    register: world_writable_library_files
    changed_when: false
    failed_when: false
    check_mode: false
    tags:
    - DISA-STIG-OL09-00-002506
    - NIST-800-53-AC-6(1)
    - NIST-800-53-CM-5(6)
    - NIST-800-53-CM-5(6).1
    - NIST-800-53-CM-6(a)
    - file_permissions_binary_dirs
    - medium_complexity
    - medium_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Remove world/group writability of system executables
    ansible.builtin.file:
      path: '{{ item }}'
      mode: go-w
      state: file
    with_items: '{{ world_writable_library_files.stdout_lines }}'
    when: world_writable_library_files.stdout_lines | length > 0
    tags:
    - DISA-STIG-OL09-00-002506
    - NIST-800-53-AC-6(1)
    - NIST-800-53-CM-5(6)
    - NIST-800-53-CM-5(6).1
    - NIST-800-53-CM-6(a)
    - file_permissions_binary_dirs
    - medium_complexity
    - medium_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Find /lib/ file(s) recursively
    ansible.builtin.command: find -P /lib/  -perm /g+w,o+w  -type f -regextype posix-extended
      -regex "^.*\.so.*$"
    register: files_found
    changed_when: false
    failed_when: false
    check_mode: false
    tags:
    - DISA-STIG-OL09-00-002525
    - NIST-800-53-AC-6(1)
    - NIST-800-53-CM-5(6)
    - NIST-800-53-CM-5(6).1
    - NIST-800-53-CM-6(a)
    - configure_strategy
    - file_permissions_library_dirs
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

  - name: Set permissions for /lib/ file(s)
    ansible.builtin.file:
      path: '{{ item }}'
      mode: g-w,o-w
      state: file
    with_items:
    - '{{ files_found.stdout_lines }}'
    tags:
    - DISA-STIG-OL09-00-002525
    - NIST-800-53-AC-6(1)
    - NIST-800-53-CM-5(6)
    - NIST-800-53-CM-5(6).1
    - NIST-800-53-CM-6(a)
    - configure_strategy
    - file_permissions_library_dirs
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

  - name: Find /lib64/ file(s) recursively
    ansible.builtin.command: find -P /lib64/  -perm /g+w,o+w  -type f -regextype posix-extended
      -regex "^.*\.so.*$"
    register: files_found
    changed_when: false
    failed_when: false
    check_mode: false
    tags:
    - DISA-STIG-OL09-00-002525
    - NIST-800-53-AC-6(1)
    - NIST-800-53-CM-5(6)
    - NIST-800-53-CM-5(6).1
    - NIST-800-53-CM-6(a)
    - configure_strategy
    - file_permissions_library_dirs
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

  - name: Set permissions for /lib64/ file(s)
    ansible.builtin.file:
      path: '{{ item }}'
      mode: g-w,o-w
      state: file
    with_items:
    - '{{ files_found.stdout_lines }}'
    tags:
    - DISA-STIG-OL09-00-002525
    - NIST-800-53-AC-6(1)
    - NIST-800-53-CM-5(6)
    - NIST-800-53-CM-5(6).1
    - NIST-800-53-CM-6(a)
    - configure_strategy
    - file_permissions_library_dirs
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

  - name: Find /usr/lib/ file(s) recursively
    ansible.builtin.command: find -P /usr/lib/  -perm /g+w,o+w  -type f -regextype
      posix-extended -regex "^.*\.so.*$"
    register: files_found
    changed_when: false
    failed_when: false
    check_mode: false
    tags:
    - DISA-STIG-OL09-00-002525
    - NIST-800-53-AC-6(1)
    - NIST-800-53-CM-5(6)
    - NIST-800-53-CM-5(6).1
    - NIST-800-53-CM-6(a)
    - configure_strategy
    - file_permissions_library_dirs
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

  - name: Set permissions for /usr/lib/ file(s)
    ansible.builtin.file:
      path: '{{ item }}'
      mode: g-w,o-w
      state: file
    with_items:
    - '{{ files_found.stdout_lines }}'
    tags:
    - DISA-STIG-OL09-00-002525
    - NIST-800-53-AC-6(1)
    - NIST-800-53-CM-5(6)
    - NIST-800-53-CM-5(6).1
    - NIST-800-53-CM-6(a)
    - configure_strategy
    - file_permissions_library_dirs
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

  - name: Find /usr/lib64/ file(s) recursively
    ansible.builtin.command: find -P /usr/lib64/  -perm /g+w,o+w  -type f -regextype
      posix-extended -regex "^.*\.so.*$"
    register: files_found
    changed_when: false
    failed_when: false
    check_mode: false
    tags:
    - DISA-STIG-OL09-00-002525
    - NIST-800-53-AC-6(1)
    - NIST-800-53-CM-5(6)
    - NIST-800-53-CM-5(6).1
    - NIST-800-53-CM-6(a)
    - configure_strategy
    - file_permissions_library_dirs
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

  - name: Set permissions for /usr/lib64/ file(s)
    ansible.builtin.file:
      path: '{{ item }}'
      mode: g-w,o-w
      state: file
    with_items:
    - '{{ files_found.stdout_lines }}'
    tags:
    - DISA-STIG-OL09-00-002525
    - NIST-800-53-AC-6(1)
    - NIST-800-53-CM-5(6)
    - NIST-800-53-CM-5(6).1
    - NIST-800-53-CM-6(a)
    - configure_strategy
    - file_permissions_library_dirs
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

  - name: Set the root_permissions_syslibrary_files_newgroup variable if represented
      by gid
    ansible.builtin.set_fact:
      root_permissions_syslibrary_files_newgroup: '0'
    tags:
    - DISA-STIG-OL09-00-002523
    - NIST-800-53-CM-5(6)
    - NIST-800-53-CM-5(6).1
    - configure_strategy
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - root_permissions_syslibrary_files

  - name: Find /lib/ file(s) matching ^.*\.so.*$ recursively
    ansible.builtin.command: find -P /lib/  -type f  ! -group 0 -regextype posix-extended
      -regex "^.*\.so.*$"
    register: files_found
    changed_when: false
    failed_when: false
    check_mode: false
    tags:
    - DISA-STIG-OL09-00-002523
    - NIST-800-53-CM-5(6)
    - NIST-800-53-CM-5(6).1
    - configure_strategy
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - root_permissions_syslibrary_files

  - name: Ensure group owner on /lib/ file(s) matching ^.*\.so.*$
    ansible.builtin.file:
      path: '{{ item }}'
      follow: false
      group: '{{ root_permissions_syslibrary_files_newgroup }}'
      state: file
    with_items:
    - '{{ files_found.stdout_lines }}'
    tags:
    - DISA-STIG-OL09-00-002523
    - NIST-800-53-CM-5(6)
    - NIST-800-53-CM-5(6).1
    - configure_strategy
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - root_permissions_syslibrary_files

  - name: Find /lib64/ file(s) matching ^.*\.so.*$ recursively
    ansible.builtin.command: find -P /lib64/  -type f  ! -group 0 -regextype posix-extended
      -regex "^.*\.so.*$"
    register: files_found
    changed_when: false
    failed_when: false
    check_mode: false
    tags:
    - DISA-STIG-OL09-00-002523
    - NIST-800-53-CM-5(6)
    - NIST-800-53-CM-5(6).1
    - configure_strategy
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - root_permissions_syslibrary_files

  - name: Ensure group owner on /lib64/ file(s) matching ^.*\.so.*$
    ansible.builtin.file:
      path: '{{ item }}'
      follow: false
      group: '{{ root_permissions_syslibrary_files_newgroup }}'
      state: file
    with_items:
    - '{{ files_found.stdout_lines }}'
    tags:
    - DISA-STIG-OL09-00-002523
    - NIST-800-53-CM-5(6)
    - NIST-800-53-CM-5(6).1
    - configure_strategy
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - root_permissions_syslibrary_files

  - name: Find /usr/lib/ file(s) matching ^.*\.so.*$ recursively
    ansible.builtin.command: find -P /usr/lib/  -type f  ! -group 0 -regextype posix-extended
      -regex "^.*\.so.*$"
    register: files_found
    changed_when: false
    failed_when: false
    check_mode: false
    tags:
    - DISA-STIG-OL09-00-002523
    - NIST-800-53-CM-5(6)
    - NIST-800-53-CM-5(6).1
    - configure_strategy
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - root_permissions_syslibrary_files

  - name: Ensure group owner on /usr/lib/ file(s) matching ^.*\.so.*$
    ansible.builtin.file:
      path: '{{ item }}'
      follow: false
      group: '{{ root_permissions_syslibrary_files_newgroup }}'
      state: file
    with_items:
    - '{{ files_found.stdout_lines }}'
    tags:
    - DISA-STIG-OL09-00-002523
    - NIST-800-53-CM-5(6)
    - NIST-800-53-CM-5(6).1
    - configure_strategy
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - root_permissions_syslibrary_files

  - name: Find /usr/lib64/ file(s) matching ^.*\.so.*$ recursively
    ansible.builtin.command: find -P /usr/lib64/  -type f  ! -group 0 -regextype posix-extended
      -regex "^.*\.so.*$"
    register: files_found
    changed_when: false
    failed_when: false
    check_mode: false
    tags:
    - DISA-STIG-OL09-00-002523
    - NIST-800-53-CM-5(6)
    - NIST-800-53-CM-5(6).1
    - configure_strategy
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - root_permissions_syslibrary_files

  - name: Ensure group owner on /usr/lib64/ file(s) matching ^.*\.so.*$
    ansible.builtin.file:
      path: '{{ item }}'
      follow: false
      group: '{{ root_permissions_syslibrary_files_newgroup }}'
      state: file
    with_items:
    - '{{ files_found.stdout_lines }}'
    tags:
    - DISA-STIG-OL09-00-002523
    - NIST-800-53-CM-5(6)
    - NIST-800-53-CM-5(6).1
    - configure_strategy
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - root_permissions_syslibrary_files

  - name: Ensure rootfiles tmpfile.d is Configured Correctly - Find configuration
      files
    ansible.builtin.find:
      paths: /etc/tmpfiles.d/
      file_type: file
      patterns: '*.conf'
    register: rootfiles_configured_bash_logout_found_files
    when: '"rootfiles" in ansible_facts.packages'
    tags:
    - DISA-STIG-OL09-00-002513
    - configure_strategy
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - rootfiles_configured

  - name: Ensure rootfiles tmpfile.d is Configured Correctly - Remove existing configuration
    ansible.builtin.lineinfile:
      path: '{{ item.path }}'
      regexp: ^C\s+/root/\.bash_logout.+$
      state: absent
    loop: '{{ rootfiles_configured_bash_logout_found_files.files }}'
    when: '"rootfiles" in ansible_facts.packages'
    tags:
    - DISA-STIG-OL09-00-002513
    - configure_strategy
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - rootfiles_configured

  - name: Ensure rootfiles tmpfile.d is Configured Correctly
    ansible.builtin.lineinfile:
      path: /etc/tmpfiles.d/rootfiles.conf
      create: true
      regexp: (?i)/usr/share/rootfiles/.bash_logout
      line: C /root/.bash_logout 600 root root - /usr/share/rootfiles/.bash_logout
      state: present
    when: '"rootfiles" in ansible_facts.packages'
    tags:
    - DISA-STIG-OL09-00-002513
    - configure_strategy
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - rootfiles_configured

  - name: Ensure rootfiles tmpfile.d is Configured Correctly - Find configuration
      files
    ansible.builtin.find:
      paths: /etc/tmpfiles.d/
      file_type: file
      patterns: '*.conf'
    register: rootfiles_configured_bash_profile_found_files
    when: '"rootfiles" in ansible_facts.packages'
    tags:
    - DISA-STIG-OL09-00-002513
    - configure_strategy
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - rootfiles_configured

  - name: Ensure rootfiles tmpfile.d is Configured Correctly - Remove existing configuration
    ansible.builtin.lineinfile:
      path: '{{ item.path }}'
      regexp: ^C\s+/root/\.bash_profile.+$
      state: absent
    loop: '{{ rootfiles_configured_bash_profile_found_files.files }}'
    when: '"rootfiles" in ansible_facts.packages'
    tags:
    - DISA-STIG-OL09-00-002513
    - configure_strategy
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - rootfiles_configured

  - name: Ensure rootfiles tmpfile.d is Configured Correctly
    ansible.builtin.lineinfile:
      path: /etc/tmpfiles.d/rootfiles.conf
      create: true
      regexp: (?i)/usr/share/rootfiles/.bash_profile
      line: C /root/.bash_profile 600 root root - /usr/share/rootfiles/.bash_profile
      state: present
    when: '"rootfiles" in ansible_facts.packages'
    tags:
    - DISA-STIG-OL09-00-002513
    - configure_strategy
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - rootfiles_configured

  - name: Ensure rootfiles tmpfile.d is Configured Correctly - Find configuration
      files
    ansible.builtin.find:
      paths: /etc/tmpfiles.d/
      file_type: file
      patterns: '*.conf'
    register: rootfiles_configured_bashrc_found_files
    when: '"rootfiles" in ansible_facts.packages'
    tags:
    - DISA-STIG-OL09-00-002513
    - configure_strategy
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - rootfiles_configured

  - name: Ensure rootfiles tmpfile.d is Configured Correctly - Remove existing configuration
    ansible.builtin.lineinfile:
      path: '{{ item.path }}'
      regexp: ^C\s+/root/\.bashrc.+$
      state: absent
    loop: '{{ rootfiles_configured_bashrc_found_files.files }}'
    when: '"rootfiles" in ansible_facts.packages'
    tags:
    - DISA-STIG-OL09-00-002513
    - configure_strategy
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - rootfiles_configured

  - name: Ensure rootfiles tmpfile.d is Configured Correctly
    ansible.builtin.lineinfile:
      path: /etc/tmpfiles.d/rootfiles.conf
      create: true
      regexp: (?i)/usr/share/rootfiles/.bashrc
      line: C /root/.bashrc 600 root root - /usr/share/rootfiles/.bashrc
      state: present
    when: '"rootfiles" in ansible_facts.packages'
    tags:
    - DISA-STIG-OL09-00-002513
    - configure_strategy
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - rootfiles_configured

  - name: Ensure rootfiles tmpfile.d is Configured Correctly - Find configuration
      files
    ansible.builtin.find:
      paths: /etc/tmpfiles.d/
      file_type: file
      patterns: '*.conf'
    register: rootfiles_configured_cshrc_found_files
    when: '"rootfiles" in ansible_facts.packages'
    tags:
    - DISA-STIG-OL09-00-002513
    - configure_strategy
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - rootfiles_configured

  - name: Ensure rootfiles tmpfile.d is Configured Correctly - Remove existing configuration
    ansible.builtin.lineinfile:
      path: '{{ item.path }}'
      regexp: ^C\s+/root/\.cshrc.+$
      state: absent
    loop: '{{ rootfiles_configured_cshrc_found_files.files }}'
    when: '"rootfiles" in ansible_facts.packages'
    tags:
    - DISA-STIG-OL09-00-002513
    - configure_strategy
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - rootfiles_configured

  - name: Ensure rootfiles tmpfile.d is Configured Correctly
    ansible.builtin.lineinfile:
      path: /etc/tmpfiles.d/rootfiles.conf
      create: true
      regexp: (?i)/usr/share/rootfiles/.cshrc
      line: C /root/.cshrc 600 root root - /usr/share/rootfiles/.cshrc
      state: present
    when: '"rootfiles" in ansible_facts.packages'
    tags:
    - DISA-STIG-OL09-00-002513
    - configure_strategy
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - rootfiles_configured

  - name: Ensure rootfiles tmpfile.d is Configured Correctly - Find configuration
      files
    ansible.builtin.find:
      paths: /etc/tmpfiles.d/
      file_type: file
      patterns: '*.conf'
    register: rootfiles_configured_tcshrc_found_files
    when: '"rootfiles" in ansible_facts.packages'
    tags:
    - DISA-STIG-OL09-00-002513
    - configure_strategy
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - rootfiles_configured

  - name: Ensure rootfiles tmpfile.d is Configured Correctly - Remove existing configuration
    ansible.builtin.lineinfile:
      path: '{{ item.path }}'
      regexp: ^C\s+/root/\.tcshrc.+$
      state: absent
    loop: '{{ rootfiles_configured_tcshrc_found_files.files }}'
    when: '"rootfiles" in ansible_facts.packages'
    tags:
    - DISA-STIG-OL09-00-002513
    - configure_strategy
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - rootfiles_configured

  - name: Ensure rootfiles tmpfile.d is Configured Correctly
    ansible.builtin.lineinfile:
      path: /etc/tmpfiles.d/rootfiles.conf
      create: true
      regexp: (?i)/usr/share/rootfiles/.tcshrc
      line: C /root/.tcshrc 600 root root - /usr/share/rootfiles/.tcshrc
      state: present
    when: '"rootfiles" in ansible_facts.packages'
    tags:
    - DISA-STIG-OL09-00-002513
    - configure_strategy
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - rootfiles_configured

  - name: Ensure kernel module 'cramfs' is disabled
    ansible.builtin.lineinfile:
      create: true
      dest: /etc/modprobe.d/cramfs.conf
      regexp: install\s+cramfs
      line: install cramfs /bin/false
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-000045
    - NIST-800-171-3.4.6
    - NIST-800-53-CM-6(a)
    - NIST-800-53-CM-7(a)
    - NIST-800-53-CM-7(b)
    - disable_strategy
    - kernel_module_cramfs_disabled
    - low_complexity
    - low_severity
    - medium_disruption
    - reboot_required

  - name: Ensure kernel module 'cramfs' is blacklisted
    ansible.builtin.lineinfile:
      create: true
      dest: /etc/modprobe.d/cramfs.conf
      regexp: ^blacklist cramfs$
      line: blacklist cramfs
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-000045
    - NIST-800-171-3.4.6
    - NIST-800-53-CM-6(a)
    - NIST-800-53-CM-7(a)
    - NIST-800-53-CM-7(b)
    - disable_strategy
    - kernel_module_cramfs_disabled
    - low_complexity
    - low_severity
    - medium_disruption
    - reboot_required

  - name: Ensure kernel module 'usb-storage' is disabled
    ansible.builtin.lineinfile:
      create: true
      dest: /etc/modprobe.d/usb-storage.conf
      regexp: install\s+usb-storage
      line: install usb-storage /bin/false
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-000047
    - NIST-800-171-3.1.21
    - NIST-800-53-CM-6(a)
    - NIST-800-53-CM-7(a)
    - NIST-800-53-CM-7(b)
    - NIST-800-53-MP-7
    - PCI-DSSv4-3.4
    - PCI-DSSv4-3.4.2
    - disable_strategy
    - kernel_module_usb-storage_disabled
    - low_complexity
    - medium_disruption
    - medium_severity
    - reboot_required

  - name: Ensure kernel module 'usb-storage' is blacklisted
    ansible.builtin.lineinfile:
      create: true
      dest: /etc/modprobe.d/usb-storage.conf
      regexp: ^blacklist usb-storage$
      line: blacklist usb-storage
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-000047
    - NIST-800-171-3.1.21
    - NIST-800-53-CM-6(a)
    - NIST-800-53-CM-7(a)
    - NIST-800-53-CM-7(b)
    - NIST-800-53-MP-7
    - PCI-DSSv4-3.4
    - PCI-DSSv4-3.4.2
    - disable_strategy
    - kernel_module_usb-storage_disabled
    - low_complexity
    - medium_disruption
    - medium_severity
    - reboot_required

  - name: 'Add nosuid Option to /boot/efi: Check filesystem type of /boot/efi'
    ansible.builtin.command: findmnt --kernel --raw --evaluate --output=FSTYPE '/boot/efi'
    register: fs_type_check
    failed_when: fs_type_check.rc > 1
    changed_when: false
    check_mode: false
    when:
    - ( not ( "kernel" in ansible_facts.packages and "rpm-ostree" in ansible_facts.packages
      and "bootc" in ansible_facts.packages and not "openshift-kubelet" in ansible_facts.packages
      and "ostree" in ansible_proc_cmdline ) and not ( ansible_virtualization_type
      in ["docker", "lxc", "openvz", "podman", "container"] ) )
    - '"/boot/efi" in ansible_mounts | map(attribute="mount") | list'
    tags:
    - DISA-STIG-OL09-00-002032
    - NIST-800-53-CM-6(b)
    - NIST-800-53-CM-6.1(iv)
    - configure_strategy
    - high_disruption
    - low_complexity
    - medium_severity
    - mount_option_boot_efi_nosuid
    - no_reboot_needed

  - name: 'Add nosuid Option to /boot/efi: Set fact for excluded filesystem'
    set_fact:
      is_excluded_fstype: '{{ fs_type_check.rc == 0 and ''vfat'' in fs_type_check.stdout_lines
        }}'
    when:
    - ( not ( "kernel" in ansible_facts.packages and "rpm-ostree" in ansible_facts.packages
      and "bootc" in ansible_facts.packages and not "openshift-kubelet" in ansible_facts.packages
      and "ostree" in ansible_proc_cmdline ) and not ( ansible_virtualization_type
      in ["docker", "lxc", "openvz", "podman", "container"] ) )
    - '"/boot/efi" in ansible_mounts | map(attribute="mount") | list'
    tags:
    - DISA-STIG-OL09-00-002032
    - NIST-800-53-CM-6(b)
    - NIST-800-53-CM-6.1(iv)
    - configure_strategy
    - high_disruption
    - low_complexity
    - medium_severity
    - mount_option_boot_efi_nosuid
    - no_reboot_needed

  - name: 'Add nosuid Option to /boot/efi: Check information associated to mountpoint'
    ansible.builtin.command: findmnt --fstab '/boot/efi'
    register: device_name
    failed_when: device_name.rc > 1
    changed_when: false
    check_mode: false
    when:
    - ( not ( "kernel" in ansible_facts.packages and "rpm-ostree" in ansible_facts.packages
      and "bootc" in ansible_facts.packages and not "openshift-kubelet" in ansible_facts.packages
      and "ostree" in ansible_proc_cmdline ) and not ( ansible_virtualization_type
      in ["docker", "lxc", "openvz", "podman", "container"] ) )
    - '"/boot/efi" in ansible_mounts | map(attribute="mount") | list'
    - not is_excluded_fstype | default(false)
    tags:
    - DISA-STIG-OL09-00-002032
    - NIST-800-53-CM-6(b)
    - NIST-800-53-CM-6.1(iv)
    - configure_strategy
    - high_disruption
    - low_complexity
    - medium_severity
    - mount_option_boot_efi_nosuid
    - no_reboot_needed

  - name: 'Add nosuid Option to /boot/efi: Create mount_info dictionary variable'
    set_fact:
      mount_info: '{{ mount_info|default({})|combine({item.0: item.1}) }}'
    with_together:
    - '{{ device_name.stdout_lines[0].split() | map(''lower'') | list }}'
    - '{{ device_name.stdout_lines[1].split() | list }}'
    when:
    - ( not ( "kernel" in ansible_facts.packages and "rpm-ostree" in ansible_facts.packages
      and "bootc" in ansible_facts.packages and not "openshift-kubelet" in ansible_facts.packages
      and "ostree" in ansible_proc_cmdline ) and not ( ansible_virtualization_type
      in ["docker", "lxc", "openvz", "podman", "container"] ) )
    - '"/boot/efi" in ansible_mounts | map(attribute="mount") | list'
    - device_name.stdout is defined and device_name.stdout_lines is defined
    - (device_name.stdout | length > 0)
    - not is_excluded_fstype | default(false)
    tags:
    - DISA-STIG-OL09-00-002032
    - NIST-800-53-CM-6(b)
    - NIST-800-53-CM-6.1(iv)
    - configure_strategy
    - high_disruption
    - low_complexity
    - medium_severity
    - mount_option_boot_efi_nosuid
    - no_reboot_needed

  - name: 'Add nosuid Option to /boot/efi: If /boot/efi not mounted, craft mount_info
      manually'
    set_fact:
      mount_info: '{{ mount_info|default({})|combine({item.0: item.1}) }}'
    with_together:
    - - target
      - source
      - fstype
      - options
    - - /boot/efi
      - ''
      - ''
      - defaults
    when:
    - ( not ( "kernel" in ansible_facts.packages and "rpm-ostree" in ansible_facts.packages
      and "bootc" in ansible_facts.packages and not "openshift-kubelet" in ansible_facts.packages
      and "ostree" in ansible_proc_cmdline ) and not ( ansible_virtualization_type
      in ["docker", "lxc", "openvz", "podman", "container"] ) )
    - '"/boot/efi" in ansible_mounts | map(attribute="mount") | list'
    - ("--fstab" | length == 0)
    - device_name.stdout is defined and device_name.stdout_lines is defined
    - (device_name.stdout | length == 0)
    - not is_excluded_fstype | default(false)
    tags:
    - DISA-STIG-OL09-00-002032
    - NIST-800-53-CM-6(b)
    - NIST-800-53-CM-6.1(iv)
    - configure_strategy
    - high_disruption
    - low_complexity
    - medium_severity
    - mount_option_boot_efi_nosuid
    - no_reboot_needed

  - name: 'Add nosuid Option to /boot/efi: Make sure nosuid option is part of the
      to /boot/efi options'
    set_fact:
      mount_info: '{{ mount_info | combine( {''options'':''''~(mount_info.options
        | default(''''))~('','' if (mount_info.options | default('''')) else '''')~''nosuid''
        }) }}'
    when:
    - ( not ( "kernel" in ansible_facts.packages and "rpm-ostree" in ansible_facts.packages
      and "bootc" in ansible_facts.packages and not "openshift-kubelet" in ansible_facts.packages
      and "ostree" in ansible_proc_cmdline ) and not ( ansible_virtualization_type
      in ["docker", "lxc", "openvz", "podman", "container"] ) )
    - '"/boot/efi" in ansible_mounts | map(attribute="mount") | list'
    - mount_info is defined and "nosuid" not in (mount_info.options | default(''))
    - not is_excluded_fstype | default(false)
    tags:
    - DISA-STIG-OL09-00-002032
    - NIST-800-53-CM-6(b)
    - NIST-800-53-CM-6.1(iv)
    - configure_strategy
    - high_disruption
    - low_complexity
    - medium_severity
    - mount_option_boot_efi_nosuid
    - no_reboot_needed

  - name: 'Add nosuid Option to /boot/efi: Ensure /boot/efi is mounted with nosuid
      option'
    ansible.posix.mount:
      path: /boot/efi
      src: '{{ mount_info.source | default('''') }}'
      opts: '{{ mount_info.options | default('''') }}'
      state: mounted
      fstype: '{{ mount_info.fstype | default('''') }}'
    register: mount_result
    failed_when:
    - mount_result is failed
    - '''target is busy'' not in (mount_result.msg | default(''''))'
    - '''already mounted'' not in (mount_result.msg | default(''''))'
    when:
    - ( not ( "kernel" in ansible_facts.packages and "rpm-ostree" in ansible_facts.packages
      and "bootc" in ansible_facts.packages and not "openshift-kubelet" in ansible_facts.packages
      and "ostree" in ansible_proc_cmdline ) and not ( ansible_virtualization_type
      in ["docker", "lxc", "openvz", "podman", "container"] ) )
    - '"/boot/efi" in ansible_mounts | map(attribute="mount") | list'
    - mount_info is defined
    - (device_name.stdout is defined and (device_name.stdout | length > 0)) or ("--fstab"
      | length == 0)
    - not is_excluded_fstype | default(false)
    tags:
    - DISA-STIG-OL09-00-002032
    - NIST-800-53-CM-6(b)
    - NIST-800-53-CM-6.1(iv)
    - configure_strategy
    - high_disruption
    - low_complexity
    - medium_severity
    - mount_option_boot_efi_nosuid
    - no_reboot_needed

  - name: 'Add nodev Option to /boot: Check information associated to mountpoint'
    ansible.builtin.command: findmnt --fstab '/boot'
    register: device_name
    failed_when: device_name.rc > 1
    changed_when: false
    check_mode: false
    when: ( not ( "kernel" in ansible_facts.packages and "rpm-ostree" in ansible_facts.packages
      and "bootc" in ansible_facts.packages and not "openshift-kubelet" in ansible_facts.packages
      and "ostree" in ansible_proc_cmdline ) and not ( ansible_virtualization_type
      in ["docker", "lxc", "openvz", "podman", "container"] ) )
    tags:
    - DISA-STIG-OL09-00-002030
    - NIST-800-53-AC-6
    - NIST-800-53-AC-6(1)
    - NIST-800-53-CM-6(a)
    - NIST-800-53-CM-7(a)
    - NIST-800-53-CM-7(b)
    - NIST-800-53-MP-7
    - configure_strategy
    - high_disruption
    - low_complexity
    - medium_severity
    - mount_option_boot_nodev
    - no_reboot_needed

  - name: 'Add nodev Option to /boot: Create mount_info dictionary variable'
    set_fact:
      mount_info: '{{ mount_info|default({})|combine({item.0: item.1}) }}'
    with_together:
    - '{{ device_name.stdout_lines[0].split() | map(''lower'') | list }}'
    - '{{ device_name.stdout_lines[1].split() | list }}'
    when:
    - ( not ( "kernel" in ansible_facts.packages and "rpm-ostree" in ansible_facts.packages
      and "bootc" in ansible_facts.packages and not "openshift-kubelet" in ansible_facts.packages
      and "ostree" in ansible_proc_cmdline ) and not ( ansible_virtualization_type
      in ["docker", "lxc", "openvz", "podman", "container"] ) )
    - device_name.stdout is defined and device_name.stdout_lines is defined
    - (device_name.stdout | length > 0)
    tags:
    - DISA-STIG-OL09-00-002030
    - NIST-800-53-AC-6
    - NIST-800-53-AC-6(1)
    - NIST-800-53-CM-6(a)
    - NIST-800-53-CM-7(a)
    - NIST-800-53-CM-7(b)
    - NIST-800-53-MP-7
    - configure_strategy
    - high_disruption
    - low_complexity
    - medium_severity
    - mount_option_boot_nodev
    - no_reboot_needed

  - name: 'Add nodev Option to /boot: If /boot not mounted, craft mount_info manually'
    set_fact:
      mount_info: '{{ mount_info|default({})|combine({item.0: item.1}) }}'
    with_together:
    - - target
      - source
      - fstype
      - options
    - - /boot
      - ''
      - ''
      - defaults
    when:
    - ( not ( "kernel" in ansible_facts.packages and "rpm-ostree" in ansible_facts.packages
      and "bootc" in ansible_facts.packages and not "openshift-kubelet" in ansible_facts.packages
      and "ostree" in ansible_proc_cmdline ) and not ( ansible_virtualization_type
      in ["docker", "lxc", "openvz", "podman", "container"] ) )
    - ("--fstab" | length == 0)
    - device_name.stdout is defined and device_name.stdout_lines is defined
    - (device_name.stdout | length == 0)
    tags:
    - DISA-STIG-OL09-00-002030
    - NIST-800-53-AC-6
    - NIST-800-53-AC-6(1)
    - NIST-800-53-CM-6(a)
    - NIST-800-53-CM-7(a)
    - NIST-800-53-CM-7(b)
    - NIST-800-53-MP-7
    - configure_strategy
    - high_disruption
    - low_complexity
    - medium_severity
    - mount_option_boot_nodev
    - no_reboot_needed

  - name: 'Add nodev Option to /boot: Make sure nodev option is part of the to /boot
      options'
    set_fact:
      mount_info: '{{ mount_info | combine( {''options'':''''~(mount_info.options
        | default(''''))~('','' if (mount_info.options | default('''')) else '''')~''nodev''
        }) }}'
    when:
    - ( not ( "kernel" in ansible_facts.packages and "rpm-ostree" in ansible_facts.packages
      and "bootc" in ansible_facts.packages and not "openshift-kubelet" in ansible_facts.packages
      and "ostree" in ansible_proc_cmdline ) and not ( ansible_virtualization_type
      in ["docker", "lxc", "openvz", "podman", "container"] ) )
    - mount_info is defined and "nodev" not in (mount_info.options | default(''))
    tags:
    - DISA-STIG-OL09-00-002030
    - NIST-800-53-AC-6
    - NIST-800-53-AC-6(1)
    - NIST-800-53-CM-6(a)
    - NIST-800-53-CM-7(a)
    - NIST-800-53-CM-7(b)
    - NIST-800-53-MP-7
    - configure_strategy
    - high_disruption
    - low_complexity
    - medium_severity
    - mount_option_boot_nodev
    - no_reboot_needed

  - name: 'Add nodev Option to /boot: Ensure /boot is mounted with nodev option'
    ansible.posix.mount:
      path: /boot
      src: '{{ mount_info.source | default('''') }}'
      opts: '{{ mount_info.options | default('''') }}'
      state: mounted
      fstype: '{{ mount_info.fstype | default('''') }}'
    register: mount_result
    failed_when:
    - mount_result is failed
    - '''target is busy'' not in (mount_result.msg | default(''''))'
    - '''already mounted'' not in (mount_result.msg | default(''''))'
    when:
    - ( not ( "kernel" in ansible_facts.packages and "rpm-ostree" in ansible_facts.packages
      and "bootc" in ansible_facts.packages and not "openshift-kubelet" in ansible_facts.packages
      and "ostree" in ansible_proc_cmdline ) and not ( ansible_virtualization_type
      in ["docker", "lxc", "openvz", "podman", "container"] ) )
    - mount_info is defined
    - (device_name.stdout is defined and (device_name.stdout | length > 0)) or ("--fstab"
      | length == 0)
    tags:
    - DISA-STIG-OL09-00-002030
    - NIST-800-53-AC-6
    - NIST-800-53-AC-6(1)
    - NIST-800-53-CM-6(a)
    - NIST-800-53-CM-7(a)
    - NIST-800-53-CM-7(b)
    - NIST-800-53-MP-7
    - configure_strategy
    - high_disruption
    - low_complexity
    - medium_severity
    - mount_option_boot_nodev
    - no_reboot_needed

  - name: 'Add nosuid Option to /boot: Check information associated to mountpoint'
    ansible.builtin.command: findmnt --fstab '/boot'
    register: device_name
    failed_when: device_name.rc > 1
    changed_when: false
    check_mode: false
    when: ( not ( "kernel" in ansible_facts.packages and "rpm-ostree" in ansible_facts.packages
      and "bootc" in ansible_facts.packages and not "openshift-kubelet" in ansible_facts.packages
      and "ostree" in ansible_proc_cmdline ) and not ( ansible_virtualization_type
      in ["docker", "lxc", "openvz", "podman", "container"] ) )
    tags:
    - DISA-STIG-OL09-00-002031
    - NIST-800-53-AC-6
    - NIST-800-53-AC-6(1)
    - NIST-800-53-CM-6(a)
    - NIST-800-53-CM-7(a)
    - NIST-800-53-CM-7(b)
    - NIST-800-53-MP-7
    - configure_strategy
    - high_disruption
    - low_complexity
    - medium_severity
    - mount_option_boot_nosuid
    - no_reboot_needed

  - name: 'Add nosuid Option to /boot: Create mount_info dictionary variable'
    set_fact:
      mount_info: '{{ mount_info|default({})|combine({item.0: item.1}) }}'
    with_together:
    - '{{ device_name.stdout_lines[0].split() | map(''lower'') | list }}'
    - '{{ device_name.stdout_lines[1].split() | list }}'
    when:
    - ( not ( "kernel" in ansible_facts.packages and "rpm-ostree" in ansible_facts.packages
      and "bootc" in ansible_facts.packages and not "openshift-kubelet" in ansible_facts.packages
      and "ostree" in ansible_proc_cmdline ) and not ( ansible_virtualization_type
      in ["docker", "lxc", "openvz", "podman", "container"] ) )
    - device_name.stdout is defined and device_name.stdout_lines is defined
    - (device_name.stdout | length > 0)
    tags:
    - DISA-STIG-OL09-00-002031
    - NIST-800-53-AC-6
    - NIST-800-53-AC-6(1)
    - NIST-800-53-CM-6(a)
    - NIST-800-53-CM-7(a)
    - NIST-800-53-CM-7(b)
    - NIST-800-53-MP-7
    - configure_strategy
    - high_disruption
    - low_complexity
    - medium_severity
    - mount_option_boot_nosuid
    - no_reboot_needed

  - name: 'Add nosuid Option to /boot: If /boot not mounted, craft mount_info manually'
    set_fact:
      mount_info: '{{ mount_info|default({})|combine({item.0: item.1}) }}'
    with_together:
    - - target
      - source
      - fstype
      - options
    - - /boot
      - ''
      - ''
      - defaults
    when:
    - ( not ( "kernel" in ansible_facts.packages and "rpm-ostree" in ansible_facts.packages
      and "bootc" in ansible_facts.packages and not "openshift-kubelet" in ansible_facts.packages
      and "ostree" in ansible_proc_cmdline ) and not ( ansible_virtualization_type
      in ["docker", "lxc", "openvz", "podman", "container"] ) )
    - ("--fstab" | length == 0)
    - device_name.stdout is defined and device_name.stdout_lines is defined
    - (device_name.stdout | length == 0)
    tags:
    - DISA-STIG-OL09-00-002031
    - NIST-800-53-AC-6
    - NIST-800-53-AC-6(1)
    - NIST-800-53-CM-6(a)
    - NIST-800-53-CM-7(a)
    - NIST-800-53-CM-7(b)
    - NIST-800-53-MP-7
    - configure_strategy
    - high_disruption
    - low_complexity
    - medium_severity
    - mount_option_boot_nosuid
    - no_reboot_needed

  - name: 'Add nosuid Option to /boot: Make sure nosuid option is part of the to /boot
      options'
    set_fact:
      mount_info: '{{ mount_info | combine( {''options'':''''~(mount_info.options
        | default(''''))~('','' if (mount_info.options | default('''')) else '''')~''nosuid''
        }) }}'
    when:
    - ( not ( "kernel" in ansible_facts.packages and "rpm-ostree" in ansible_facts.packages
      and "bootc" in ansible_facts.packages and not "openshift-kubelet" in ansible_facts.packages
      and "ostree" in ansible_proc_cmdline ) and not ( ansible_virtualization_type
      in ["docker", "lxc", "openvz", "podman", "container"] ) )
    - mount_info is defined and "nosuid" not in (mount_info.options | default(''))
    tags:
    - DISA-STIG-OL09-00-002031
    - NIST-800-53-AC-6
    - NIST-800-53-AC-6(1)
    - NIST-800-53-CM-6(a)
    - NIST-800-53-CM-7(a)
    - NIST-800-53-CM-7(b)
    - NIST-800-53-MP-7
    - configure_strategy
    - high_disruption
    - low_complexity
    - medium_severity
    - mount_option_boot_nosuid
    - no_reboot_needed

  - name: 'Add nosuid Option to /boot: Ensure /boot is mounted with nosuid option'
    ansible.posix.mount:
      path: /boot
      src: '{{ mount_info.source | default('''') }}'
      opts: '{{ mount_info.options | default('''') }}'
      state: mounted
      fstype: '{{ mount_info.fstype | default('''') }}'
    register: mount_result
    failed_when:
    - mount_result is failed
    - '''target is busy'' not in (mount_result.msg | default(''''))'
    - '''already mounted'' not in (mount_result.msg | default(''''))'
    when:
    - ( not ( "kernel" in ansible_facts.packages and "rpm-ostree" in ansible_facts.packages
      and "bootc" in ansible_facts.packages and not "openshift-kubelet" in ansible_facts.packages
      and "ostree" in ansible_proc_cmdline ) and not ( ansible_virtualization_type
      in ["docker", "lxc", "openvz", "podman", "container"] ) )
    - mount_info is defined
    - (device_name.stdout is defined and (device_name.stdout | length > 0)) or ("--fstab"
      | length == 0)
    tags:
    - DISA-STIG-OL09-00-002031
    - NIST-800-53-AC-6
    - NIST-800-53-AC-6(1)
    - NIST-800-53-CM-6(a)
    - NIST-800-53-CM-7(a)
    - NIST-800-53-CM-7(b)
    - NIST-800-53-MP-7
    - configure_strategy
    - high_disruption
    - low_complexity
    - medium_severity
    - mount_option_boot_nosuid
    - no_reboot_needed

  - name: 'Add nodev Option to /dev/shm: Check information associated to mountpoint'
    ansible.builtin.command: findmnt  '/dev/shm'
    register: device_name
    failed_when: device_name.rc > 1
    changed_when: false
    check_mode: false
    when: ( not ( "kernel" in ansible_facts.packages and "rpm-ostree" in ansible_facts.packages
      and "bootc" in ansible_facts.packages and not "openshift-kubelet" in ansible_facts.packages
      and "ostree" in ansible_proc_cmdline ) and not ( ansible_virtualization_type
      in ["docker", "lxc", "openvz", "podman", "container"] ) )
    tags:
    - DISA-STIG-OL09-00-002040
    - NIST-800-53-AC-6
    - NIST-800-53-AC-6(1)
    - NIST-800-53-CM-6(a)
    - NIST-800-53-CM-7(a)
    - NIST-800-53-CM-7(b)
    - NIST-800-53-MP-7
    - configure_strategy
    - high_disruption
    - low_complexity
    - medium_severity
    - mount_option_dev_shm_nodev
    - no_reboot_needed

  - name: 'Add nodev Option to /dev/shm: Create mount_info dictionary variable'
    set_fact:
      mount_info: '{{ mount_info|default({})|combine({item.0: item.1}) }}'
    with_together:
    - '{{ device_name.stdout_lines[0].split() | map(''lower'') | list }}'
    - '{{ device_name.stdout_lines[1].split() | list }}'
    when:
    - ( not ( "kernel" in ansible_facts.packages and "rpm-ostree" in ansible_facts.packages
      and "bootc" in ansible_facts.packages and not "openshift-kubelet" in ansible_facts.packages
      and "ostree" in ansible_proc_cmdline ) and not ( ansible_virtualization_type
      in ["docker", "lxc", "openvz", "podman", "container"] ) )
    - device_name.stdout is defined and device_name.stdout_lines is defined
    - (device_name.stdout | length > 0)
    tags:
    - DISA-STIG-OL09-00-002040
    - NIST-800-53-AC-6
    - NIST-800-53-AC-6(1)
    - NIST-800-53-CM-6(a)
    - NIST-800-53-CM-7(a)
    - NIST-800-53-CM-7(b)
    - NIST-800-53-MP-7
    - configure_strategy
    - high_disruption
    - low_complexity
    - medium_severity
    - mount_option_dev_shm_nodev
    - no_reboot_needed

  - name: 'Add nodev Option to /dev/shm: If /dev/shm not mounted, craft mount_info
      manually'
    set_fact:
      mount_info: '{{ mount_info|default({})|combine({item.0: item.1}) }}'
    with_together:
    - - target
      - source
      - fstype
      - options
    - - /dev/shm
      - tmpfs
      - tmpfs
      - defaults
    when:
    - ( not ( "kernel" in ansible_facts.packages and "rpm-ostree" in ansible_facts.packages
      and "bootc" in ansible_facts.packages and not "openshift-kubelet" in ansible_facts.packages
      and "ostree" in ansible_proc_cmdline ) and not ( ansible_virtualization_type
      in ["docker", "lxc", "openvz", "podman", "container"] ) )
    - ("" | length == 0)
    - device_name.stdout is defined and device_name.stdout_lines is defined
    - (device_name.stdout | length == 0)
    tags:
    - DISA-STIG-OL09-00-002040
    - NIST-800-53-AC-6
    - NIST-800-53-AC-6(1)
    - NIST-800-53-CM-6(a)
    - NIST-800-53-CM-7(a)
    - NIST-800-53-CM-7(b)
    - NIST-800-53-MP-7
    - configure_strategy
    - high_disruption
    - low_complexity
    - medium_severity
    - mount_option_dev_shm_nodev
    - no_reboot_needed

  - name: 'Add nodev Option to /dev/shm: Make sure nodev option is part of the to
      /dev/shm options'
    set_fact:
      mount_info: '{{ mount_info | combine( {''options'':''''~(mount_info.options
        | default(''''))~('','' if (mount_info.options | default('''')) else '''')~''nodev''
        }) }}'
    when:
    - ( not ( "kernel" in ansible_facts.packages and "rpm-ostree" in ansible_facts.packages
      and "bootc" in ansible_facts.packages and not "openshift-kubelet" in ansible_facts.packages
      and "ostree" in ansible_proc_cmdline ) and not ( ansible_virtualization_type
      in ["docker", "lxc", "openvz", "podman", "container"] ) )
    - mount_info is defined and "nodev" not in (mount_info.options | default(''))
    tags:
    - DISA-STIG-OL09-00-002040
    - NIST-800-53-AC-6
    - NIST-800-53-AC-6(1)
    - NIST-800-53-CM-6(a)
    - NIST-800-53-CM-7(a)
    - NIST-800-53-CM-7(b)
    - NIST-800-53-MP-7
    - configure_strategy
    - high_disruption
    - low_complexity
    - medium_severity
    - mount_option_dev_shm_nodev
    - no_reboot_needed

  - name: 'Add nodev Option to /dev/shm: Ensure /dev/shm is mounted with nodev option'
    ansible.posix.mount:
      path: /dev/shm
      src: '{{ mount_info.source | default('''') }}'
      opts: '{{ mount_info.options | default('''') }}'
      state: mounted
      fstype: '{{ mount_info.fstype | default('''') }}'
    register: mount_result
    failed_when:
    - mount_result is failed
    - '''target is busy'' not in (mount_result.msg | default(''''))'
    - '''already mounted'' not in (mount_result.msg | default(''''))'
    when:
    - ( not ( "kernel" in ansible_facts.packages and "rpm-ostree" in ansible_facts.packages
      and "bootc" in ansible_facts.packages and not "openshift-kubelet" in ansible_facts.packages
      and "ostree" in ansible_proc_cmdline ) and not ( ansible_virtualization_type
      in ["docker", "lxc", "openvz", "podman", "container"] ) )
    - mount_info is defined
    - (device_name.stdout is defined and (device_name.stdout | length > 0)) or (""
      | length == 0)
    tags:
    - DISA-STIG-OL09-00-002040
    - NIST-800-53-AC-6
    - NIST-800-53-AC-6(1)
    - NIST-800-53-CM-6(a)
    - NIST-800-53-CM-7(a)
    - NIST-800-53-CM-7(b)
    - NIST-800-53-MP-7
    - configure_strategy
    - high_disruption
    - low_complexity
    - medium_severity
    - mount_option_dev_shm_nodev
    - no_reboot_needed

  - name: 'Add noexec Option to /dev/shm: Check information associated to mountpoint'
    ansible.builtin.command: findmnt  '/dev/shm'
    register: device_name
    failed_when: device_name.rc > 1
    changed_when: false
    check_mode: false
    when: ( not ( "kernel" in ansible_facts.packages and "rpm-ostree" in ansible_facts.packages
      and "bootc" in ansible_facts.packages and not "openshift-kubelet" in ansible_facts.packages
      and "ostree" in ansible_proc_cmdline ) and not ( ansible_virtualization_type
      in ["docker", "lxc", "openvz", "podman", "container"] ) )
    tags:
    - DISA-STIG-OL09-00-002041
    - NIST-800-53-AC-6
    - NIST-800-53-AC-6(1)
    - NIST-800-53-CM-6(a)
    - NIST-800-53-CM-7(a)
    - NIST-800-53-CM-7(b)
    - NIST-800-53-MP-7
    - configure_strategy
    - high_disruption
    - low_complexity
    - medium_severity
    - mount_option_dev_shm_noexec
    - no_reboot_needed

  - name: 'Add noexec Option to /dev/shm: Create mount_info dictionary variable'
    set_fact:
      mount_info: '{{ mount_info|default({})|combine({item.0: item.1}) }}'
    with_together:
    - '{{ device_name.stdout_lines[0].split() | map(''lower'') | list }}'
    - '{{ device_name.stdout_lines[1].split() | list }}'
    when:
    - ( not ( "kernel" in ansible_facts.packages and "rpm-ostree" in ansible_facts.packages
      and "bootc" in ansible_facts.packages and not "openshift-kubelet" in ansible_facts.packages
      and "ostree" in ansible_proc_cmdline ) and not ( ansible_virtualization_type
      in ["docker", "lxc", "openvz", "podman", "container"] ) )
    - device_name.stdout is defined and device_name.stdout_lines is defined
    - (device_name.stdout | length > 0)
    tags:
    - DISA-STIG-OL09-00-002041
    - NIST-800-53-AC-6
    - NIST-800-53-AC-6(1)
    - NIST-800-53-CM-6(a)
    - NIST-800-53-CM-7(a)
    - NIST-800-53-CM-7(b)
    - NIST-800-53-MP-7
    - configure_strategy
    - high_disruption
    - low_complexity
    - medium_severity
    - mount_option_dev_shm_noexec
    - no_reboot_needed

  - name: 'Add noexec Option to /dev/shm: If /dev/shm not mounted, craft mount_info
      manually'
    set_fact:
      mount_info: '{{ mount_info|default({})|combine({item.0: item.1}) }}'
    with_together:
    - - target
      - source
      - fstype
      - options
    - - /dev/shm
      - tmpfs
      - tmpfs
      - defaults
    when:
    - ( not ( "kernel" in ansible_facts.packages and "rpm-ostree" in ansible_facts.packages
      and "bootc" in ansible_facts.packages and not "openshift-kubelet" in ansible_facts.packages
      and "ostree" in ansible_proc_cmdline ) and not ( ansible_virtualization_type
      in ["docker", "lxc", "openvz", "podman", "container"] ) )
    - ("" | length == 0)
    - device_name.stdout is defined and device_name.stdout_lines is defined
    - (device_name.stdout | length == 0)
    tags:
    - DISA-STIG-OL09-00-002041
    - NIST-800-53-AC-6
    - NIST-800-53-AC-6(1)
    - NIST-800-53-CM-6(a)
    - NIST-800-53-CM-7(a)
    - NIST-800-53-CM-7(b)
    - NIST-800-53-MP-7
    - configure_strategy
    - high_disruption
    - low_complexity
    - medium_severity
    - mount_option_dev_shm_noexec
    - no_reboot_needed

  - name: 'Add noexec Option to /dev/shm: Make sure noexec option is part of the to
      /dev/shm options'
    set_fact:
      mount_info: '{{ mount_info | combine( {''options'':''''~(mount_info.options
        | default(''''))~('','' if (mount_info.options | default('''')) else '''')~''noexec''
        }) }}'
    when:
    - ( not ( "kernel" in ansible_facts.packages and "rpm-ostree" in ansible_facts.packages
      and "bootc" in ansible_facts.packages and not "openshift-kubelet" in ansible_facts.packages
      and "ostree" in ansible_proc_cmdline ) and not ( ansible_virtualization_type
      in ["docker", "lxc", "openvz", "podman", "container"] ) )
    - mount_info is defined and "noexec" not in (mount_info.options | default(''))
    tags:
    - DISA-STIG-OL09-00-002041
    - NIST-800-53-AC-6
    - NIST-800-53-AC-6(1)
    - NIST-800-53-CM-6(a)
    - NIST-800-53-CM-7(a)
    - NIST-800-53-CM-7(b)
    - NIST-800-53-MP-7
    - configure_strategy
    - high_disruption
    - low_complexity
    - medium_severity
    - mount_option_dev_shm_noexec
    - no_reboot_needed

  - name: 'Add noexec Option to /dev/shm: Ensure /dev/shm is mounted with noexec option'
    ansible.posix.mount:
      path: /dev/shm
      src: '{{ mount_info.source | default('''') }}'
      opts: '{{ mount_info.options | default('''') }}'
      state: mounted
      fstype: '{{ mount_info.fstype | default('''') }}'
    register: mount_result
    failed_when:
    - mount_result is failed
    - '''target is busy'' not in (mount_result.msg | default(''''))'
    - '''already mounted'' not in (mount_result.msg | default(''''))'
    when:
    - ( not ( "kernel" in ansible_facts.packages and "rpm-ostree" in ansible_facts.packages
      and "bootc" in ansible_facts.packages and not "openshift-kubelet" in ansible_facts.packages
      and "ostree" in ansible_proc_cmdline ) and not ( ansible_virtualization_type
      in ["docker", "lxc", "openvz", "podman", "container"] ) )
    - mount_info is defined
    - (device_name.stdout is defined and (device_name.stdout | length > 0)) or (""
      | length == 0)
    tags:
    - DISA-STIG-OL09-00-002041
    - NIST-800-53-AC-6
    - NIST-800-53-AC-6(1)
    - NIST-800-53-CM-6(a)
    - NIST-800-53-CM-7(a)
    - NIST-800-53-CM-7(b)
    - NIST-800-53-MP-7
    - configure_strategy
    - high_disruption
    - low_complexity
    - medium_severity
    - mount_option_dev_shm_noexec
    - no_reboot_needed

  - name: 'Add nosuid Option to /dev/shm: Check information associated to mountpoint'
    ansible.builtin.command: findmnt  '/dev/shm'
    register: device_name
    failed_when: device_name.rc > 1
    changed_when: false
    check_mode: false
    when: ( not ( "kernel" in ansible_facts.packages and "rpm-ostree" in ansible_facts.packages
      and "bootc" in ansible_facts.packages and not "openshift-kubelet" in ansible_facts.packages
      and "ostree" in ansible_proc_cmdline ) and not ( ansible_virtualization_type
      in ["docker", "lxc", "openvz", "podman", "container"] ) )
    tags:
    - DISA-STIG-OL09-00-002042
    - NIST-800-53-AC-6
    - NIST-800-53-AC-6(1)
    - NIST-800-53-CM-6(a)
    - NIST-800-53-CM-7(a)
    - NIST-800-53-CM-7(b)
    - NIST-800-53-MP-7
    - configure_strategy
    - high_disruption
    - low_complexity
    - medium_severity
    - mount_option_dev_shm_nosuid
    - no_reboot_needed

  - name: 'Add nosuid Option to /dev/shm: Create mount_info dictionary variable'
    set_fact:
      mount_info: '{{ mount_info|default({})|combine({item.0: item.1}) }}'
    with_together:
    - '{{ device_name.stdout_lines[0].split() | map(''lower'') | list }}'
    - '{{ device_name.stdout_lines[1].split() | list }}'
    when:
    - ( not ( "kernel" in ansible_facts.packages and "rpm-ostree" in ansible_facts.packages
      and "bootc" in ansible_facts.packages and not "openshift-kubelet" in ansible_facts.packages
      and "ostree" in ansible_proc_cmdline ) and not ( ansible_virtualization_type
      in ["docker", "lxc", "openvz", "podman", "container"] ) )
    - device_name.stdout is defined and device_name.stdout_lines is defined
    - (device_name.stdout | length > 0)
    tags:
    - DISA-STIG-OL09-00-002042
    - NIST-800-53-AC-6
    - NIST-800-53-AC-6(1)
    - NIST-800-53-CM-6(a)
    - NIST-800-53-CM-7(a)
    - NIST-800-53-CM-7(b)
    - NIST-800-53-MP-7
    - configure_strategy
    - high_disruption
    - low_complexity
    - medium_severity
    - mount_option_dev_shm_nosuid
    - no_reboot_needed

  - name: 'Add nosuid Option to /dev/shm: If /dev/shm not mounted, craft mount_info
      manually'
    set_fact:
      mount_info: '{{ mount_info|default({})|combine({item.0: item.1}) }}'
    with_together:
    - - target
      - source
      - fstype
      - options
    - - /dev/shm
      - tmpfs
      - tmpfs
      - defaults
    when:
    - ( not ( "kernel" in ansible_facts.packages and "rpm-ostree" in ansible_facts.packages
      and "bootc" in ansible_facts.packages and not "openshift-kubelet" in ansible_facts.packages
      and "ostree" in ansible_proc_cmdline ) and not ( ansible_virtualization_type
      in ["docker", "lxc", "openvz", "podman", "container"] ) )
    - ("" | length == 0)
    - device_name.stdout is defined and device_name.stdout_lines is defined
    - (device_name.stdout | length == 0)
    tags:
    - DISA-STIG-OL09-00-002042
    - NIST-800-53-AC-6
    - NIST-800-53-AC-6(1)
    - NIST-800-53-CM-6(a)
    - NIST-800-53-CM-7(a)
    - NIST-800-53-CM-7(b)
    - NIST-800-53-MP-7
    - configure_strategy
    - high_disruption
    - low_complexity
    - medium_severity
    - mount_option_dev_shm_nosuid
    - no_reboot_needed

  - name: 'Add nosuid Option to /dev/shm: Make sure nosuid option is part of the to
      /dev/shm options'
    set_fact:
      mount_info: '{{ mount_info | combine( {''options'':''''~(mount_info.options
        | default(''''))~('','' if (mount_info.options | default('''')) else '''')~''nosuid''
        }) }}'
    when:
    - ( not ( "kernel" in ansible_facts.packages and "rpm-ostree" in ansible_facts.packages
      and "bootc" in ansible_facts.packages and not "openshift-kubelet" in ansible_facts.packages
      and "ostree" in ansible_proc_cmdline ) and not ( ansible_virtualization_type
      in ["docker", "lxc", "openvz", "podman", "container"] ) )
    - mount_info is defined and "nosuid" not in (mount_info.options | default(''))
    tags:
    - DISA-STIG-OL09-00-002042
    - NIST-800-53-AC-6
    - NIST-800-53-AC-6(1)
    - NIST-800-53-CM-6(a)
    - NIST-800-53-CM-7(a)
    - NIST-800-53-CM-7(b)
    - NIST-800-53-MP-7
    - configure_strategy
    - high_disruption
    - low_complexity
    - medium_severity
    - mount_option_dev_shm_nosuid
    - no_reboot_needed

  - name: 'Add nosuid Option to /dev/shm: Ensure /dev/shm is mounted with nosuid option'
    ansible.posix.mount:
      path: /dev/shm
      src: '{{ mount_info.source | default('''') }}'
      opts: '{{ mount_info.options | default('''') }}'
      state: mounted
      fstype: '{{ mount_info.fstype | default('''') }}'
    register: mount_result
    failed_when:
    - mount_result is failed
    - '''target is busy'' not in (mount_result.msg | default(''''))'
    - '''already mounted'' not in (mount_result.msg | default(''''))'
    when:
    - ( not ( "kernel" in ansible_facts.packages and "rpm-ostree" in ansible_facts.packages
      and "bootc" in ansible_facts.packages and not "openshift-kubelet" in ansible_facts.packages
      and "ostree" in ansible_proc_cmdline ) and not ( ansible_virtualization_type
      in ["docker", "lxc", "openvz", "podman", "container"] ) )
    - mount_info is defined
    - (device_name.stdout is defined and (device_name.stdout | length > 0)) or (""
      | length == 0)
    tags:
    - DISA-STIG-OL09-00-002042
    - NIST-800-53-AC-6
    - NIST-800-53-AC-6(1)
    - NIST-800-53-CM-6(a)
    - NIST-800-53-CM-7(a)
    - NIST-800-53-CM-7(b)
    - NIST-800-53-MP-7
    - configure_strategy
    - high_disruption
    - low_complexity
    - medium_severity
    - mount_option_dev_shm_nosuid
    - no_reboot_needed

  - name: Add nodev Option to /home - Initialize variables
    ansible.builtin.set_fact:
      non_allowed_partitions:
      - /
      - /lib
      - /opt
      - /usr
      - /bin
      - /sbin
      - /boot
      - /dev
      - /proc
      home_directories: []
      allowed_mount_point: []
      fstab_mount_point_info: []
    when:
    - ( not ( "kernel" in ansible_facts.packages and "rpm-ostree" in ansible_facts.packages
      and "bootc" in ansible_facts.packages and not "openshift-kubelet" in ansible_facts.packages
      and "ostree" in ansible_proc_cmdline ) and not ( ansible_virtualization_type
      in ["docker", "lxc", "openvz", "podman", "container"] ) )
    - '"/home" in ansible_mounts | map(attribute="mount") | list'
    tags:
    - DISA-STIG-OL09-00-002070
    - configure_strategy
    - high_disruption
    - low_complexity
    - mount_option_home_nodev
    - no_reboot_needed
    - unknown_severity

  - name: Add nodev Option to /home - Get home directories from passwd
    ansible.builtin.getent:
      database: passwd
    when:
    - ( not ( "kernel" in ansible_facts.packages and "rpm-ostree" in ansible_facts.packages
      and "bootc" in ansible_facts.packages and not "openshift-kubelet" in ansible_facts.packages
      and "ostree" in ansible_proc_cmdline ) and not ( ansible_virtualization_type
      in ["docker", "lxc", "openvz", "podman", "container"] ) )
    - '"/home" in ansible_mounts | map(attribute="mount") | list'
    tags:
    - DISA-STIG-OL09-00-002070
    - configure_strategy
    - high_disruption
    - low_complexity
    - mount_option_home_nodev
    - no_reboot_needed
    - unknown_severity

  - name: Add nodev Option to /home - Filter home directories based on UID range
    ansible.builtin.set_fact:
      home_directories: '{{ home_directories + [item.data[4]] }}'
    when:
    - ( not ( "kernel" in ansible_facts.packages and "rpm-ostree" in ansible_facts.packages
      and "bootc" in ansible_facts.packages and not "openshift-kubelet" in ansible_facts.packages
      and "ostree" in ansible_proc_cmdline ) and not ( ansible_virtualization_type
      in ["docker", "lxc", "openvz", "podman", "container"] ) )
    - '"/home" in ansible_mounts | map(attribute="mount") | list'
    - item.data[4] is defined
    - item.data[2]|int >= 1000
    - item.data[2]|int != 65534
    - item.data[4] not in non_allowed_partitions
    with_items: '{{ ansible_facts.getent_passwd | dict2items(key_name=''user'', value_name=''data'')}}'
    tags:
    - DISA-STIG-OL09-00-002070
    - configure_strategy
    - high_disruption
    - low_complexity
    - mount_option_home_nodev
    - no_reboot_needed
    - unknown_severity

  - name: Add nodev Option to /home - Gather mount points
    ansible.builtin.setup:
      filter: ansible_mounts
    when:
    - ( not ( "kernel" in ansible_facts.packages and "rpm-ostree" in ansible_facts.packages
      and "bootc" in ansible_facts.packages and not "openshift-kubelet" in ansible_facts.packages
      and "ostree" in ansible_proc_cmdline ) and not ( ansible_virtualization_type
      in ["docker", "lxc", "openvz", "podman", "container"] ) )
    - '"/home" in ansible_mounts | map(attribute="mount") | list'
    tags:
    - DISA-STIG-OL09-00-002070
    - configure_strategy
    - high_disruption
    - low_complexity
    - mount_option_home_nodev
    - no_reboot_needed
    - unknown_severity

  - name: Add nodev Option to /home - Ensure mount options for home directories
    block:

    - name: ' Add nodev Option to /home - Obtain mount point using df and shell'
      ansible.builtin.shell: |
        df {{ item }} | awk '/^\/dev/ {print $6}'
      register: df_output
      with_items: '{{ home_directories }}'

    - name: Add nodev Option to /home - Set mount point for each home directory
      ansible.builtin.set_fact:
        allowed_mount_point: '{{ allowed_mount_point + [item.stdout_lines[0]] }}'
      with_items: '{{ df_output.results }}'
      when:
      - item.stdout_lines is defined
      - item.stdout_lines | length > 0
      - item.stdout_lines[0] != ""

    - name: Add nodev Option to /home - Obtain full mount information for allowed
        mount point
      ansible.builtin.set_fact:
        fstab_mount_point_info: '{{ fstab_mount_point_info + [ ansible_mounts | selectattr(''mount'',
          ''equalto'', item) | first ]}}'
      with_items: '{{ allowed_mount_point }}'
      when: allowed_mount_point is defined

    - name: Add nodev Option to /home - Ensure mount option nodev is in fstab for
        allowed mount point
      ansible.posix.mount:
        path: '{{ item.mount }}'
        src: '{{ item.device }}'
        opts: '{{ item.options }},nodev'
        state: mounted
        fstype: '{{ item.fstype }}'
      with_items: '{{ fstab_mount_point_info }}'
      when:
      - allowed_mount_point is defined
      - item.mount not in non_allowed_partitions
      - '''nodev'' not in item.options'
    when:
    - ( not ( "kernel" in ansible_facts.packages and "rpm-ostree" in ansible_facts.packages
      and "bootc" in ansible_facts.packages and not "openshift-kubelet" in ansible_facts.packages
      and "ostree" in ansible_proc_cmdline ) and not ( ansible_virtualization_type
      in ["docker", "lxc", "openvz", "podman", "container"] ) )
    - '"/home" in ansible_mounts | map(attribute="mount") | list'
    tags:
    - DISA-STIG-OL09-00-002070
    - configure_strategy
    - high_disruption
    - low_complexity
    - mount_option_home_nodev
    - no_reboot_needed
    - unknown_severity

  - name: Add noexec Option to /home - Initialize variables
    ansible.builtin.set_fact:
      non_allowed_partitions:
      - /
      - /lib
      - /opt
      - /usr
      - /bin
      - /sbin
      - /boot
      - /dev
      - /proc
      home_directories: []
      allowed_mount_point: []
      fstab_mount_point_info: []
    when: ( not ( "kernel" in ansible_facts.packages and "rpm-ostree" in ansible_facts.packages
      and "bootc" in ansible_facts.packages and not "openshift-kubelet" in ansible_facts.packages
      and "ostree" in ansible_proc_cmdline ) and not ( ansible_virtualization_type
      in ["docker", "lxc", "openvz", "podman", "container"] ) )
    tags:
    - DISA-STIG-OL09-00-002072
    - NIST-800-53-CM-6(b)
    - configure_strategy
    - high_disruption
    - low_complexity
    - medium_severity
    - mount_option_home_noexec
    - no_reboot_needed

  - name: Add noexec Option to /home - Get home directories from passwd
    ansible.builtin.getent:
      database: passwd
    when: ( not ( "kernel" in ansible_facts.packages and "rpm-ostree" in ansible_facts.packages
      and "bootc" in ansible_facts.packages and not "openshift-kubelet" in ansible_facts.packages
      and "ostree" in ansible_proc_cmdline ) and not ( ansible_virtualization_type
      in ["docker", "lxc", "openvz", "podman", "container"] ) )
    tags:
    - DISA-STIG-OL09-00-002072
    - NIST-800-53-CM-6(b)
    - configure_strategy
    - high_disruption
    - low_complexity
    - medium_severity
    - mount_option_home_noexec
    - no_reboot_needed

  - name: Add noexec Option to /home - Filter home directories based on UID range
    ansible.builtin.set_fact:
      home_directories: '{{ home_directories + [item.data[4]] }}'
    when:
    - ( not ( "kernel" in ansible_facts.packages and "rpm-ostree" in ansible_facts.packages
      and "bootc" in ansible_facts.packages and not "openshift-kubelet" in ansible_facts.packages
      and "ostree" in ansible_proc_cmdline ) and not ( ansible_virtualization_type
      in ["docker", "lxc", "openvz", "podman", "container"] ) )
    - item.data[4] is defined
    - item.data[2]|int >= 1000
    - item.data[2]|int != 65534
    - item.data[4] not in non_allowed_partitions
    with_items: '{{ ansible_facts.getent_passwd | dict2items(key_name=''user'', value_name=''data'')}}'
    tags:
    - DISA-STIG-OL09-00-002072
    - NIST-800-53-CM-6(b)
    - configure_strategy
    - high_disruption
    - low_complexity
    - medium_severity
    - mount_option_home_noexec
    - no_reboot_needed

  - name: Add noexec Option to /home - Gather mount points
    ansible.builtin.setup:
      filter: ansible_mounts
    when: ( not ( "kernel" in ansible_facts.packages and "rpm-ostree" in ansible_facts.packages
      and "bootc" in ansible_facts.packages and not "openshift-kubelet" in ansible_facts.packages
      and "ostree" in ansible_proc_cmdline ) and not ( ansible_virtualization_type
      in ["docker", "lxc", "openvz", "podman", "container"] ) )
    tags:
    - DISA-STIG-OL09-00-002072
    - NIST-800-53-CM-6(b)
    - configure_strategy
    - high_disruption
    - low_complexity
    - medium_severity
    - mount_option_home_noexec
    - no_reboot_needed

  - name: Add noexec Option to /home - Ensure mount options for home directories
    block:

    - name: ' Add noexec Option to /home - Obtain mount point using df and shell'
      ansible.builtin.shell: |
        df {{ item }} | awk '/^\/dev/ {print $6}'
      register: df_output
      with_items: '{{ home_directories }}'

    - name: Add noexec Option to /home - Set mount point for each home directory
      ansible.builtin.set_fact:
        allowed_mount_point: '{{ allowed_mount_point + [item.stdout_lines[0]] }}'
      with_items: '{{ df_output.results }}'
      when:
      - item.stdout_lines is defined
      - item.stdout_lines | length > 0
      - item.stdout_lines[0] != ""

    - name: Add noexec Option to /home - Obtain full mount information for allowed
        mount point
      ansible.builtin.set_fact:
        fstab_mount_point_info: '{{ fstab_mount_point_info + [ ansible_mounts | selectattr(''mount'',
          ''equalto'', item) | first ]}}'
      with_items: '{{ allowed_mount_point }}'
      when: allowed_mount_point is defined

    - name: Add noexec Option to /home - Ensure mount option noexec is in fstab for
        allowed mount point
      ansible.posix.mount:
        path: '{{ item.mount }}'
        src: '{{ item.device }}'
        opts: '{{ item.options }},noexec'
        state: mounted
        fstype: '{{ item.fstype }}'
      with_items: '{{ fstab_mount_point_info }}'
      when:
      - allowed_mount_point is defined
      - item.mount not in non_allowed_partitions
      - '''noexec'' not in item.options'
    when: ( not ( "kernel" in ansible_facts.packages and "rpm-ostree" in ansible_facts.packages
      and "bootc" in ansible_facts.packages and not "openshift-kubelet" in ansible_facts.packages
      and "ostree" in ansible_proc_cmdline ) and not ( ansible_virtualization_type
      in ["docker", "lxc", "openvz", "podman", "container"] ) )
    tags:
    - DISA-STIG-OL09-00-002072
    - NIST-800-53-CM-6(b)
    - configure_strategy
    - high_disruption
    - low_complexity
    - medium_severity
    - mount_option_home_noexec
    - no_reboot_needed

  - name: Add nosuid Option to /home - Initialize variables
    ansible.builtin.set_fact:
      non_allowed_partitions:
      - /
      - /lib
      - /opt
      - /usr
      - /bin
      - /sbin
      - /boot
      - /dev
      - /proc
      home_directories: []
      allowed_mount_point: []
      fstab_mount_point_info: []
    when: ( not ( "kernel" in ansible_facts.packages and "rpm-ostree" in ansible_facts.packages
      and "bootc" in ansible_facts.packages and not "openshift-kubelet" in ansible_facts.packages
      and "ostree" in ansible_proc_cmdline ) and not ( ansible_virtualization_type
      in ["docker", "lxc", "openvz", "podman", "container"] ) )
    tags:
    - DISA-STIG-OL09-00-002071
    - NIST-800-53-AC-6
    - NIST-800-53-AC-6(1)
    - NIST-800-53-CM-6(a)
    - NIST-800-53-CM-7(a)
    - NIST-800-53-CM-7(b)
    - NIST-800-53-MP-7
    - configure_strategy
    - high_disruption
    - low_complexity
    - medium_severity
    - mount_option_home_nosuid
    - no_reboot_needed

  - name: Add nosuid Option to /home - Get home directories from passwd
    ansible.builtin.getent:
      database: passwd
    when: ( not ( "kernel" in ansible_facts.packages and "rpm-ostree" in ansible_facts.packages
      and "bootc" in ansible_facts.packages and not "openshift-kubelet" in ansible_facts.packages
      and "ostree" in ansible_proc_cmdline ) and not ( ansible_virtualization_type
      in ["docker", "lxc", "openvz", "podman", "container"] ) )
    tags:
    - DISA-STIG-OL09-00-002071
    - NIST-800-53-AC-6
    - NIST-800-53-AC-6(1)
    - NIST-800-53-CM-6(a)
    - NIST-800-53-CM-7(a)
    - NIST-800-53-CM-7(b)
    - NIST-800-53-MP-7
    - configure_strategy
    - high_disruption
    - low_complexity
    - medium_severity
    - mount_option_home_nosuid
    - no_reboot_needed

  - name: Add nosuid Option to /home - Filter home directories based on UID range
    ansible.builtin.set_fact:
      home_directories: '{{ home_directories + [item.data[4]] }}'
    when:
    - ( not ( "kernel" in ansible_facts.packages and "rpm-ostree" in ansible_facts.packages
      and "bootc" in ansible_facts.packages and not "openshift-kubelet" in ansible_facts.packages
      and "ostree" in ansible_proc_cmdline ) and not ( ansible_virtualization_type
      in ["docker", "lxc", "openvz", "podman", "container"] ) )
    - item.data[4] is defined
    - item.data[2]|int >= 1000
    - item.data[2]|int != 65534
    - item.data[4] not in non_allowed_partitions
    with_items: '{{ ansible_facts.getent_passwd | dict2items(key_name=''user'', value_name=''data'')}}'
    tags:
    - DISA-STIG-OL09-00-002071
    - NIST-800-53-AC-6
    - NIST-800-53-AC-6(1)
    - NIST-800-53-CM-6(a)
    - NIST-800-53-CM-7(a)
    - NIST-800-53-CM-7(b)
    - NIST-800-53-MP-7
    - configure_strategy
    - high_disruption
    - low_complexity
    - medium_severity
    - mount_option_home_nosuid
    - no_reboot_needed

  - name: Add nosuid Option to /home - Gather mount points
    ansible.builtin.setup:
      filter: ansible_mounts
    when: ( not ( "kernel" in ansible_facts.packages and "rpm-ostree" in ansible_facts.packages
      and "bootc" in ansible_facts.packages and not "openshift-kubelet" in ansible_facts.packages
      and "ostree" in ansible_proc_cmdline ) and not ( ansible_virtualization_type
      in ["docker", "lxc", "openvz", "podman", "container"] ) )
    tags:
    - DISA-STIG-OL09-00-002071
    - NIST-800-53-AC-6
    - NIST-800-53-AC-6(1)
    - NIST-800-53-CM-6(a)
    - NIST-800-53-CM-7(a)
    - NIST-800-53-CM-7(b)
    - NIST-800-53-MP-7
    - configure_strategy
    - high_disruption
    - low_complexity
    - medium_severity
    - mount_option_home_nosuid
    - no_reboot_needed

  - name: Add nosuid Option to /home - Ensure mount options for home directories
    block:

    - name: ' Add nosuid Option to /home - Obtain mount point using df and shell'
      ansible.builtin.shell: |
        df {{ item }} | awk '/^\/dev/ {print $6}'
      register: df_output
      with_items: '{{ home_directories }}'

    - name: Add nosuid Option to /home - Set mount point for each home directory
      ansible.builtin.set_fact:
        allowed_mount_point: '{{ allowed_mount_point + [item.stdout_lines[0]] }}'
      with_items: '{{ df_output.results }}'
      when:
      - item.stdout_lines is defined
      - item.stdout_lines | length > 0
      - item.stdout_lines[0] != ""

    - name: Add nosuid Option to /home - Obtain full mount information for allowed
        mount point
      ansible.builtin.set_fact:
        fstab_mount_point_info: '{{ fstab_mount_point_info + [ ansible_mounts | selectattr(''mount'',
          ''equalto'', item) | first ]}}'
      with_items: '{{ allowed_mount_point }}'
      when: allowed_mount_point is defined

    - name: Add nosuid Option to /home - Ensure mount option nosuid is in fstab for
        allowed mount point
      ansible.posix.mount:
        path: '{{ item.mount }}'
        src: '{{ item.device }}'
        opts: '{{ item.options }},nosuid'
        state: mounted
        fstype: '{{ item.fstype }}'
      with_items: '{{ fstab_mount_point_info }}'
      when:
      - allowed_mount_point is defined
      - item.mount not in non_allowed_partitions
      - '''nosuid'' not in item.options'
    when: ( not ( "kernel" in ansible_facts.packages and "rpm-ostree" in ansible_facts.packages
      and "bootc" in ansible_facts.packages and not "openshift-kubelet" in ansible_facts.packages
      and "ostree" in ansible_proc_cmdline ) and not ( ansible_virtualization_type
      in ["docker", "lxc", "openvz", "podman", "container"] ) )
    tags:
    - DISA-STIG-OL09-00-002071
    - NIST-800-53-AC-6
    - NIST-800-53-AC-6(1)
    - NIST-800-53-CM-6(a)
    - NIST-800-53-CM-7(a)
    - NIST-800-53-CM-7(b)
    - NIST-800-53-MP-7
    - configure_strategy
    - high_disruption
    - low_complexity
    - medium_severity
    - mount_option_home_nosuid
    - no_reboot_needed

  - name: 'Add nodev Option to Non-Root Local Partitions: Refresh facts'
    ansible.builtin.setup:
      gather_subset: mounts
    when: ( not ( "kernel" in ansible_facts.packages and "rpm-ostree" in ansible_facts.packages
      and "bootc" in ansible_facts.packages and not "openshift-kubelet" in ansible_facts.packages
      and "ostree" in ansible_proc_cmdline ) and not ( ansible_virtualization_type
      in ["docker", "lxc", "openvz", "podman", "container"] ) )
    tags:
    - DISA-STIG-OL09-00-002080
    - NIST-800-53-AC-6
    - NIST-800-53-AC-6(1)
    - NIST-800-53-CM-6(a)
    - NIST-800-53-CM-7(a)
    - NIST-800-53-CM-7(b)
    - NIST-800-53-MP-7
    - configure_strategy
    - high_disruption
    - low_complexity
    - medium_severity
    - mount_option_nodev_nonroot_local_partitions
    - no_reboot_needed

  - name: 'Add nodev Option to Non-Root Local Partitions: Define excluded (non-local)
      file systems'
    ansible.builtin.set_fact:
      excluded_fstypes:
      - afs
      - autofs
      - ceph
      - cifs
      - smb3
      - smbfs
      - sshfs
      - ncpfs
      - ncp
      - nfs
      - nfs4
      - gfs
      - gfs2
      - glusterfs
      - gpfs
      - pvfs2
      - ocfs2
      - lustre
      - davfs
      - fuse.sshfs
      - vfat
    when: ( not ( "kernel" in ansible_facts.packages and "rpm-ostree" in ansible_facts.packages
      and "bootc" in ansible_facts.packages and not "openshift-kubelet" in ansible_facts.packages
      and "ostree" in ansible_proc_cmdline ) and not ( ansible_virtualization_type
      in ["docker", "lxc", "openvz", "podman", "container"] ) )
    tags:
    - DISA-STIG-OL09-00-002080
    - NIST-800-53-AC-6
    - NIST-800-53-AC-6(1)
    - NIST-800-53-CM-6(a)
    - NIST-800-53-CM-7(a)
    - NIST-800-53-CM-7(b)
    - NIST-800-53-MP-7
    - configure_strategy
    - high_disruption
    - low_complexity
    - medium_severity
    - mount_option_nodev_nonroot_local_partitions
    - no_reboot_needed

  - name: 'Add nodev Option to Non-Root Local Partitions: Ensure non-root local partitions
      are mounted with nodev option'
    ansible.posix.mount:
      path: '{{ item.mount }}'
      src: '{{ item.device }}'
      opts: '{{ item.options }},nodev'
      state: mounted
      fstype: '{{ item.fstype }}'
    when:
    - ( not ( "kernel" in ansible_facts.packages and "rpm-ostree" in ansible_facts.packages
      and "bootc" in ansible_facts.packages and not "openshift-kubelet" in ansible_facts.packages
      and "ostree" in ansible_proc_cmdline ) and not ( ansible_virtualization_type
      in ["docker", "lxc", "openvz", "podman", "container"] ) )
    - item.mount is match('/\w')
    - item.mount is not match('/(boot|efi)')
    - item.options is not search('nodev')
    - item.fstype not in excluded_fstypes
    - (not accounts_polyinstantiated_var_tmp | default(false)) or item.mount != '/var/tmp/tmp-inst'
    - (not accounts_polyinstantiated_tmp | default(false)) or item.mount != '/tmp/tmp-inst'
    with_items:
    - '{{ ansible_facts.mounts }}'
    tags:
    - DISA-STIG-OL09-00-002080
    - NIST-800-53-AC-6
    - NIST-800-53-AC-6(1)
    - NIST-800-53-CM-6(a)
    - NIST-800-53-CM-7(a)
    - NIST-800-53-CM-7(b)
    - NIST-800-53-MP-7
    - configure_strategy
    - high_disruption
    - low_complexity
    - medium_severity
    - mount_option_nodev_nonroot_local_partitions
    - no_reboot_needed

  - name: 'Add nodev Option to Non-Root Local Partitions: Ensure non-root local partitions
      are present with nodev option in /etc/fstab'
    ansible.builtin.replace:
      path: /etc/fstab
      regexp: ^\s*(?!#)(/dev/\S+|UUID=\S+)\s+(/(?!boot|efi)\w\S*)\s+(?!vfat\s)(\S+)\s+(?!.*\bnodev\b)(\S+)(.*)$
      replace: \1 \2 \3 \4,nodev \5
    when: ( not ( "kernel" in ansible_facts.packages and "rpm-ostree" in ansible_facts.packages
      and "bootc" in ansible_facts.packages and not "openshift-kubelet" in ansible_facts.packages
      and "ostree" in ansible_proc_cmdline ) and not ( ansible_virtualization_type
      in ["docker", "lxc", "openvz", "podman", "container"] ) )
    tags:
    - DISA-STIG-OL09-00-002080
    - NIST-800-53-AC-6
    - NIST-800-53-AC-6(1)
    - NIST-800-53-CM-6(a)
    - NIST-800-53-CM-7(a)
    - NIST-800-53-CM-7(b)
    - NIST-800-53-MP-7
    - configure_strategy
    - high_disruption
    - low_complexity
    - medium_severity
    - mount_option_nodev_nonroot_local_partitions
    - no_reboot_needed

  - name: Ensure permission nodev are set on var_removable_partition
    ansible.builtin.lineinfile:
      path: /etc/fstab
      regexp: ^\s*({{ var_removable_partition }})\s+([^\s]*)\s+([^\s]*)\s+([^\s]*)(.*)$
      backrefs: true
      line: \1 \2 \3 \4,nodev \5
    when: ( not ( "kernel" in ansible_facts.packages and "rpm-ostree" in ansible_facts.packages
      and "bootc" in ansible_facts.packages and not "openshift-kubelet" in ansible_facts.packages
      and "ostree" in ansible_proc_cmdline ) and not ( ansible_virtualization_type
      in ["docker", "lxc", "openvz", "podman", "container"] ) )
    tags:
    - DISA-STIG-OL09-00-002021
    - NIST-800-53-AC-6
    - NIST-800-53-AC-6(1)
    - NIST-800-53-CM-6(a)
    - NIST-800-53-CM-7(a)
    - NIST-800-53-CM-7(b)
    - NIST-800-53-MP-7
    - configure_strategy
    - high_disruption
    - low_complexity
    - medium_severity
    - mount_option_nodev_removable_partitions
    - no_reboot_needed

  - name: Ensure permission noexec are set on var_removable_partition
    ansible.builtin.lineinfile:
      path: /etc/fstab
      regexp: ^\s*({{ var_removable_partition }})\s+([^\s]*)\s+([^\s]*)\s+([^\s]*)(.*)$
      backrefs: true
      line: \1 \2 \3 \4,noexec \5
    when: ( not ( "kernel" in ansible_facts.packages and "rpm-ostree" in ansible_facts.packages
      and "bootc" in ansible_facts.packages and not "openshift-kubelet" in ansible_facts.packages
      and "ostree" in ansible_proc_cmdline ) and not ( ansible_virtualization_type
      in ["docker", "lxc", "openvz", "podman", "container"] ) )
    tags:
    - DISA-STIG-OL09-00-002020
    - NIST-800-53-AC-6
    - NIST-800-53-AC-6(1)
    - NIST-800-53-CM-6(a)
    - NIST-800-53-CM-7(a)
    - NIST-800-53-CM-7(b)
    - NIST-800-53-MP-7
    - configure_strategy
    - high_disruption
    - low_complexity
    - medium_severity
    - mount_option_noexec_removable_partitions
    - no_reboot_needed

  - name: Ensure permission nosuid are set on var_removable_partition
    ansible.builtin.lineinfile:
      path: /etc/fstab
      regexp: ^\s*({{ var_removable_partition }})\s+([^\s]*)\s+([^\s]*)\s+([^\s]*)(.*)$
      backrefs: true
      line: \1 \2 \3 \4,nosuid \5
    when: ( not ( "kernel" in ansible_facts.packages and "rpm-ostree" in ansible_facts.packages
      and "bootc" in ansible_facts.packages and not "openshift-kubelet" in ansible_facts.packages
      and "ostree" in ansible_proc_cmdline ) and not ( ansible_virtualization_type
      in ["docker", "lxc", "openvz", "podman", "container"] ) )
    tags:
    - DISA-STIG-OL09-00-002022
    - NIST-800-53-AC-6
    - NIST-800-53-AC-6(1)
    - NIST-800-53-CM-6(a)
    - NIST-800-53-CM-7(a)
    - NIST-800-53-CM-7(b)
    - NIST-800-53-MP-7
    - configure_strategy
    - high_disruption
    - low_complexity
    - medium_severity
    - mount_option_nosuid_removable_partitions
    - no_reboot_needed

  - name: 'Add nodev Option to /tmp: Check information associated to mountpoint'
    ansible.builtin.command: findmnt --fstab '/tmp'
    register: device_name
    failed_when: device_name.rc > 1
    changed_when: false
    check_mode: false
    when:
    - ( not ( "kernel" in ansible_facts.packages and "rpm-ostree" in ansible_facts.packages
      and "bootc" in ansible_facts.packages and not "openshift-kubelet" in ansible_facts.packages
      and "ostree" in ansible_proc_cmdline ) and not ( ansible_virtualization_type
      in ["docker", "lxc", "openvz", "podman", "container"] ) )
    - '"/tmp" in ansible_mounts | map(attribute="mount") | list'
    tags:
    - DISA-STIG-OL09-00-002050
    - NIST-800-53-AC-6
    - NIST-800-53-AC-6(1)
    - NIST-800-53-CM-6(a)
    - NIST-800-53-CM-7(a)
    - NIST-800-53-CM-7(b)
    - NIST-800-53-MP-7
    - configure_strategy
    - high_disruption
    - low_complexity
    - medium_severity
    - mount_option_tmp_nodev
    - no_reboot_needed

  - name: 'Add nodev Option to /tmp: Create mount_info dictionary variable'
    set_fact:
      mount_info: '{{ mount_info|default({})|combine({item.0: item.1}) }}'
    with_together:
    - '{{ device_name.stdout_lines[0].split() | map(''lower'') | list }}'
    - '{{ device_name.stdout_lines[1].split() | list }}'
    when:
    - ( not ( "kernel" in ansible_facts.packages and "rpm-ostree" in ansible_facts.packages
      and "bootc" in ansible_facts.packages and not "openshift-kubelet" in ansible_facts.packages
      and "ostree" in ansible_proc_cmdline ) and not ( ansible_virtualization_type
      in ["docker", "lxc", "openvz", "podman", "container"] ) )
    - '"/tmp" in ansible_mounts | map(attribute="mount") | list'
    - device_name.stdout is defined and device_name.stdout_lines is defined
    - (device_name.stdout | length > 0)
    tags:
    - DISA-STIG-OL09-00-002050
    - NIST-800-53-AC-6
    - NIST-800-53-AC-6(1)
    - NIST-800-53-CM-6(a)
    - NIST-800-53-CM-7(a)
    - NIST-800-53-CM-7(b)
    - NIST-800-53-MP-7
    - configure_strategy
    - high_disruption
    - low_complexity
    - medium_severity
    - mount_option_tmp_nodev
    - no_reboot_needed

  - name: 'Add nodev Option to /tmp: If /tmp not mounted, craft mount_info manually'
    set_fact:
      mount_info: '{{ mount_info|default({})|combine({item.0: item.1}) }}'
    with_together:
    - - target
      - source
      - fstype
      - options
    - - /tmp
      - ''
      - ''
      - defaults
    when:
    - ( not ( "kernel" in ansible_facts.packages and "rpm-ostree" in ansible_facts.packages
      and "bootc" in ansible_facts.packages and not "openshift-kubelet" in ansible_facts.packages
      and "ostree" in ansible_proc_cmdline ) and not ( ansible_virtualization_type
      in ["docker", "lxc", "openvz", "podman", "container"] ) )
    - '"/tmp" in ansible_mounts | map(attribute="mount") | list'
    - ("--fstab" | length == 0)
    - device_name.stdout is defined and device_name.stdout_lines is defined
    - (device_name.stdout | length == 0)
    tags:
    - DISA-STIG-OL09-00-002050
    - NIST-800-53-AC-6
    - NIST-800-53-AC-6(1)
    - NIST-800-53-CM-6(a)
    - NIST-800-53-CM-7(a)
    - NIST-800-53-CM-7(b)
    - NIST-800-53-MP-7
    - configure_strategy
    - high_disruption
    - low_complexity
    - medium_severity
    - mount_option_tmp_nodev
    - no_reboot_needed

  - name: 'Add nodev Option to /tmp: Make sure nodev option is part of the to /tmp
      options'
    set_fact:
      mount_info: '{{ mount_info | combine( {''options'':''''~(mount_info.options
        | default(''''))~('','' if (mount_info.options | default('''')) else '''')~''nodev''
        }) }}'
    when:
    - ( not ( "kernel" in ansible_facts.packages and "rpm-ostree" in ansible_facts.packages
      and "bootc" in ansible_facts.packages and not "openshift-kubelet" in ansible_facts.packages
      and "ostree" in ansible_proc_cmdline ) and not ( ansible_virtualization_type
      in ["docker", "lxc", "openvz", "podman", "container"] ) )
    - '"/tmp" in ansible_mounts | map(attribute="mount") | list'
    - mount_info is defined and "nodev" not in (mount_info.options | default(''))
    tags:
    - DISA-STIG-OL09-00-002050
    - NIST-800-53-AC-6
    - NIST-800-53-AC-6(1)
    - NIST-800-53-CM-6(a)
    - NIST-800-53-CM-7(a)
    - NIST-800-53-CM-7(b)
    - NIST-800-53-MP-7
    - configure_strategy
    - high_disruption
    - low_complexity
    - medium_severity
    - mount_option_tmp_nodev
    - no_reboot_needed

  - name: 'Add nodev Option to /tmp: Ensure /tmp is mounted with nodev option'
    ansible.posix.mount:
      path: /tmp
      src: '{{ mount_info.source | default('''') }}'
      opts: '{{ mount_info.options | default('''') }}'
      state: mounted
      fstype: '{{ mount_info.fstype | default('''') }}'
    register: mount_result
    failed_when:
    - mount_result is failed
    - '''target is busy'' not in (mount_result.msg | default(''''))'
    - '''already mounted'' not in (mount_result.msg | default(''''))'
    when:
    - ( not ( "kernel" in ansible_facts.packages and "rpm-ostree" in ansible_facts.packages
      and "bootc" in ansible_facts.packages and not "openshift-kubelet" in ansible_facts.packages
      and "ostree" in ansible_proc_cmdline ) and not ( ansible_virtualization_type
      in ["docker", "lxc", "openvz", "podman", "container"] ) )
    - '"/tmp" in ansible_mounts | map(attribute="mount") | list'
    - mount_info is defined
    - (device_name.stdout is defined and (device_name.stdout | length > 0)) or ("--fstab"
      | length == 0)
    tags:
    - DISA-STIG-OL09-00-002050
    - NIST-800-53-AC-6
    - NIST-800-53-AC-6(1)
    - NIST-800-53-CM-6(a)
    - NIST-800-53-CM-7(a)
    - NIST-800-53-CM-7(b)
    - NIST-800-53-MP-7
    - configure_strategy
    - high_disruption
    - low_complexity
    - medium_severity
    - mount_option_tmp_nodev
    - no_reboot_needed

  - name: 'Add noexec Option to /tmp: Check information associated to mountpoint'
    ansible.builtin.command: findmnt --fstab '/tmp'
    register: device_name
    failed_when: device_name.rc > 1
    changed_when: false
    check_mode: false
    when:
    - ( not ( "kernel" in ansible_facts.packages and "rpm-ostree" in ansible_facts.packages
      and "bootc" in ansible_facts.packages and not "openshift-kubelet" in ansible_facts.packages
      and "ostree" in ansible_proc_cmdline ) and not ( ansible_virtualization_type
      in ["docker", "lxc", "openvz", "podman", "container"] ) )
    - '"/tmp" in ansible_mounts | map(attribute="mount") | list'
    tags:
    - DISA-STIG-OL09-00-002051
    - NIST-800-53-AC-6
    - NIST-800-53-AC-6(1)
    - NIST-800-53-CM-6(a)
    - NIST-800-53-CM-7(a)
    - NIST-800-53-CM-7(b)
    - NIST-800-53-MP-7
    - configure_strategy
    - high_disruption
    - low_complexity
    - medium_severity
    - mount_option_tmp_noexec
    - no_reboot_needed

  - name: 'Add noexec Option to /tmp: Create mount_info dictionary variable'
    set_fact:
      mount_info: '{{ mount_info|default({})|combine({item.0: item.1}) }}'
    with_together:
    - '{{ device_name.stdout_lines[0].split() | map(''lower'') | list }}'
    - '{{ device_name.stdout_lines[1].split() | list }}'
    when:
    - ( not ( "kernel" in ansible_facts.packages and "rpm-ostree" in ansible_facts.packages
      and "bootc" in ansible_facts.packages and not "openshift-kubelet" in ansible_facts.packages
      and "ostree" in ansible_proc_cmdline ) and not ( ansible_virtualization_type
      in ["docker", "lxc", "openvz", "podman", "container"] ) )
    - '"/tmp" in ansible_mounts | map(attribute="mount") | list'
    - device_name.stdout is defined and device_name.stdout_lines is defined
    - (device_name.stdout | length > 0)
    tags:
    - DISA-STIG-OL09-00-002051
    - NIST-800-53-AC-6
    - NIST-800-53-AC-6(1)
    - NIST-800-53-CM-6(a)
    - NIST-800-53-CM-7(a)
    - NIST-800-53-CM-7(b)
    - NIST-800-53-MP-7
    - configure_strategy
    - high_disruption
    - low_complexity
    - medium_severity
    - mount_option_tmp_noexec
    - no_reboot_needed

  - name: 'Add noexec Option to /tmp: If /tmp not mounted, craft mount_info manually'
    set_fact:
      mount_info: '{{ mount_info|default({})|combine({item.0: item.1}) }}'
    with_together:
    - - target
      - source
      - fstype
      - options
    - - /tmp
      - ''
      - ''
      - defaults
    when:
    - ( not ( "kernel" in ansible_facts.packages and "rpm-ostree" in ansible_facts.packages
      and "bootc" in ansible_facts.packages and not "openshift-kubelet" in ansible_facts.packages
      and "ostree" in ansible_proc_cmdline ) and not ( ansible_virtualization_type
      in ["docker", "lxc", "openvz", "podman", "container"] ) )
    - '"/tmp" in ansible_mounts | map(attribute="mount") | list'
    - ("--fstab" | length == 0)
    - device_name.stdout is defined and device_name.stdout_lines is defined
    - (device_name.stdout | length == 0)
    tags:
    - DISA-STIG-OL09-00-002051
    - NIST-800-53-AC-6
    - NIST-800-53-AC-6(1)
    - NIST-800-53-CM-6(a)
    - NIST-800-53-CM-7(a)
    - NIST-800-53-CM-7(b)
    - NIST-800-53-MP-7
    - configure_strategy
    - high_disruption
    - low_complexity
    - medium_severity
    - mount_option_tmp_noexec
    - no_reboot_needed

  - name: 'Add noexec Option to /tmp: Make sure noexec option is part of the to /tmp
      options'
    set_fact:
      mount_info: '{{ mount_info | combine( {''options'':''''~(mount_info.options
        | default(''''))~('','' if (mount_info.options | default('''')) else '''')~''noexec''
        }) }}'
    when:
    - ( not ( "kernel" in ansible_facts.packages and "rpm-ostree" in ansible_facts.packages
      and "bootc" in ansible_facts.packages and not "openshift-kubelet" in ansible_facts.packages
      and "ostree" in ansible_proc_cmdline ) and not ( ansible_virtualization_type
      in ["docker", "lxc", "openvz", "podman", "container"] ) )
    - '"/tmp" in ansible_mounts | map(attribute="mount") | list'
    - mount_info is defined and "noexec" not in (mount_info.options | default(''))
    tags:
    - DISA-STIG-OL09-00-002051
    - NIST-800-53-AC-6
    - NIST-800-53-AC-6(1)
    - NIST-800-53-CM-6(a)
    - NIST-800-53-CM-7(a)
    - NIST-800-53-CM-7(b)
    - NIST-800-53-MP-7
    - configure_strategy
    - high_disruption
    - low_complexity
    - medium_severity
    - mount_option_tmp_noexec
    - no_reboot_needed

  - name: 'Add noexec Option to /tmp: Ensure /tmp is mounted with noexec option'
    ansible.posix.mount:
      path: /tmp
      src: '{{ mount_info.source | default('''') }}'
      opts: '{{ mount_info.options | default('''') }}'
      state: mounted
      fstype: '{{ mount_info.fstype | default('''') }}'
    register: mount_result
    failed_when:
    - mount_result is failed
    - '''target is busy'' not in (mount_result.msg | default(''''))'
    - '''already mounted'' not in (mount_result.msg | default(''''))'
    when:
    - ( not ( "kernel" in ansible_facts.packages and "rpm-ostree" in ansible_facts.packages
      and "bootc" in ansible_facts.packages and not "openshift-kubelet" in ansible_facts.packages
      and "ostree" in ansible_proc_cmdline ) and not ( ansible_virtualization_type
      in ["docker", "lxc", "openvz", "podman", "container"] ) )
    - '"/tmp" in ansible_mounts | map(attribute="mount") | list'
    - mount_info is defined
    - (device_name.stdout is defined and (device_name.stdout | length > 0)) or ("--fstab"
      | length == 0)
    tags:
    - DISA-STIG-OL09-00-002051
    - NIST-800-53-AC-6
    - NIST-800-53-AC-6(1)
    - NIST-800-53-CM-6(a)
    - NIST-800-53-CM-7(a)
    - NIST-800-53-CM-7(b)
    - NIST-800-53-MP-7
    - configure_strategy
    - high_disruption
    - low_complexity
    - medium_severity
    - mount_option_tmp_noexec
    - no_reboot_needed

  - name: 'Add nosuid Option to /tmp: Check information associated to mountpoint'
    ansible.builtin.command: findmnt --fstab '/tmp'
    register: device_name
    failed_when: device_name.rc > 1
    changed_when: false
    check_mode: false
    when:
    - ( not ( "kernel" in ansible_facts.packages and "rpm-ostree" in ansible_facts.packages
      and "bootc" in ansible_facts.packages and not "openshift-kubelet" in ansible_facts.packages
      and "ostree" in ansible_proc_cmdline ) and not ( ansible_virtualization_type
      in ["docker", "lxc", "openvz", "podman", "container"] ) )
    - '"/tmp" in ansible_mounts | map(attribute="mount") | list'
    tags:
    - DISA-STIG-OL09-00-002052
    - NIST-800-53-AC-6
    - NIST-800-53-AC-6(1)
    - NIST-800-53-CM-6(a)
    - NIST-800-53-CM-7(a)
    - NIST-800-53-CM-7(b)
    - NIST-800-53-MP-7
    - configure_strategy
    - high_disruption
    - low_complexity
    - medium_severity
    - mount_option_tmp_nosuid
    - no_reboot_needed

  - name: 'Add nosuid Option to /tmp: Create mount_info dictionary variable'
    set_fact:
      mount_info: '{{ mount_info|default({})|combine({item.0: item.1}) }}'
    with_together:
    - '{{ device_name.stdout_lines[0].split() | map(''lower'') | list }}'
    - '{{ device_name.stdout_lines[1].split() | list }}'
    when:
    - ( not ( "kernel" in ansible_facts.packages and "rpm-ostree" in ansible_facts.packages
      and "bootc" in ansible_facts.packages and not "openshift-kubelet" in ansible_facts.packages
      and "ostree" in ansible_proc_cmdline ) and not ( ansible_virtualization_type
      in ["docker", "lxc", "openvz", "podman", "container"] ) )
    - '"/tmp" in ansible_mounts | map(attribute="mount") | list'
    - device_name.stdout is defined and device_name.stdout_lines is defined
    - (device_name.stdout | length > 0)
    tags:
    - DISA-STIG-OL09-00-002052
    - NIST-800-53-AC-6
    - NIST-800-53-AC-6(1)
    - NIST-800-53-CM-6(a)
    - NIST-800-53-CM-7(a)
    - NIST-800-53-CM-7(b)
    - NIST-800-53-MP-7
    - configure_strategy
    - high_disruption
    - low_complexity
    - medium_severity
    - mount_option_tmp_nosuid
    - no_reboot_needed

  - name: 'Add nosuid Option to /tmp: If /tmp not mounted, craft mount_info manually'
    set_fact:
      mount_info: '{{ mount_info|default({})|combine({item.0: item.1}) }}'
    with_together:
    - - target
      - source
      - fstype
      - options
    - - /tmp
      - ''
      - ''
      - defaults
    when:
    - ( not ( "kernel" in ansible_facts.packages and "rpm-ostree" in ansible_facts.packages
      and "bootc" in ansible_facts.packages and not "openshift-kubelet" in ansible_facts.packages
      and "ostree" in ansible_proc_cmdline ) and not ( ansible_virtualization_type
      in ["docker", "lxc", "openvz", "podman", "container"] ) )
    - '"/tmp" in ansible_mounts | map(attribute="mount") | list'
    - ("--fstab" | length == 0)
    - device_name.stdout is defined and device_name.stdout_lines is defined
    - (device_name.stdout | length == 0)
    tags:
    - DISA-STIG-OL09-00-002052
    - NIST-800-53-AC-6
    - NIST-800-53-AC-6(1)
    - NIST-800-53-CM-6(a)
    - NIST-800-53-CM-7(a)
    - NIST-800-53-CM-7(b)
    - NIST-800-53-MP-7
    - configure_strategy
    - high_disruption
    - low_complexity
    - medium_severity
    - mount_option_tmp_nosuid
    - no_reboot_needed

  - name: 'Add nosuid Option to /tmp: Make sure nosuid option is part of the to /tmp
      options'
    set_fact:
      mount_info: '{{ mount_info | combine( {''options'':''''~(mount_info.options
        | default(''''))~('','' if (mount_info.options | default('''')) else '''')~''nosuid''
        }) }}'
    when:
    - ( not ( "kernel" in ansible_facts.packages and "rpm-ostree" in ansible_facts.packages
      and "bootc" in ansible_facts.packages and not "openshift-kubelet" in ansible_facts.packages
      and "ostree" in ansible_proc_cmdline ) and not ( ansible_virtualization_type
      in ["docker", "lxc", "openvz", "podman", "container"] ) )
    - '"/tmp" in ansible_mounts | map(attribute="mount") | list'
    - mount_info is defined and "nosuid" not in (mount_info.options | default(''))
    tags:
    - DISA-STIG-OL09-00-002052
    - NIST-800-53-AC-6
    - NIST-800-53-AC-6(1)
    - NIST-800-53-CM-6(a)
    - NIST-800-53-CM-7(a)
    - NIST-800-53-CM-7(b)
    - NIST-800-53-MP-7
    - configure_strategy
    - high_disruption
    - low_complexity
    - medium_severity
    - mount_option_tmp_nosuid
    - no_reboot_needed

  - name: 'Add nosuid Option to /tmp: Ensure /tmp is mounted with nosuid option'
    ansible.posix.mount:
      path: /tmp
      src: '{{ mount_info.source | default('''') }}'
      opts: '{{ mount_info.options | default('''') }}'
      state: mounted
      fstype: '{{ mount_info.fstype | default('''') }}'
    register: mount_result
    failed_when:
    - mount_result is failed
    - '''target is busy'' not in (mount_result.msg | default(''''))'
    - '''already mounted'' not in (mount_result.msg | default(''''))'
    when:
    - ( not ( "kernel" in ansible_facts.packages and "rpm-ostree" in ansible_facts.packages
      and "bootc" in ansible_facts.packages and not "openshift-kubelet" in ansible_facts.packages
      and "ostree" in ansible_proc_cmdline ) and not ( ansible_virtualization_type
      in ["docker", "lxc", "openvz", "podman", "container"] ) )
    - '"/tmp" in ansible_mounts | map(attribute="mount") | list'
    - mount_info is defined
    - (device_name.stdout is defined and (device_name.stdout | length > 0)) or ("--fstab"
      | length == 0)
    tags:
    - DISA-STIG-OL09-00-002052
    - NIST-800-53-AC-6
    - NIST-800-53-AC-6(1)
    - NIST-800-53-CM-6(a)
    - NIST-800-53-CM-7(a)
    - NIST-800-53-CM-7(b)
    - NIST-800-53-MP-7
    - configure_strategy
    - high_disruption
    - low_complexity
    - medium_severity
    - mount_option_tmp_nosuid
    - no_reboot_needed

  - name: 'Add nodev Option to /var/log/audit: Check information associated to mountpoint'
    ansible.builtin.command: findmnt --fstab '/var/log/audit'
    register: device_name
    failed_when: device_name.rc > 1
    changed_when: false
    check_mode: false
    when:
    - ( not ( "kernel" in ansible_facts.packages and "rpm-ostree" in ansible_facts.packages
      and "bootc" in ansible_facts.packages and not "openshift-kubelet" in ansible_facts.packages
      and "ostree" in ansible_proc_cmdline ) and not ( ansible_virtualization_type
      in ["docker", "lxc", "openvz", "podman", "container"] ) )
    - '"/var/log/audit" in ansible_mounts | map(attribute="mount") | list'
    tags:
    - DISA-STIG-OL09-00-002064
    - NIST-800-53-AC-6
    - NIST-800-53-AC-6(1)
    - NIST-800-53-CM-6(a)
    - NIST-800-53-CM-7(a)
    - NIST-800-53-CM-7(b)
    - NIST-800-53-MP-7
    - configure_strategy
    - high_disruption
    - low_complexity
    - medium_severity
    - mount_option_var_log_audit_nodev
    - no_reboot_needed

  - name: 'Add nodev Option to /var/log/audit: Create mount_info dictionary variable'
    set_fact:
      mount_info: '{{ mount_info|default({})|combine({item.0: item.1}) }}'
    with_together:
    - '{{ device_name.stdout_lines[0].split() | map(''lower'') | list }}'
    - '{{ device_name.stdout_lines[1].split() | list }}'
    when:
    - ( not ( "kernel" in ansible_facts.packages and "rpm-ostree" in ansible_facts.packages
      and "bootc" in ansible_facts.packages and not "openshift-kubelet" in ansible_facts.packages
      and "ostree" in ansible_proc_cmdline ) and not ( ansible_virtualization_type
      in ["docker", "lxc", "openvz", "podman", "container"] ) )
    - '"/var/log/audit" in ansible_mounts | map(attribute="mount") | list'
    - device_name.stdout is defined and device_name.stdout_lines is defined
    - (device_name.stdout | length > 0)
    tags:
    - DISA-STIG-OL09-00-002064
    - NIST-800-53-AC-6
    - NIST-800-53-AC-6(1)
    - NIST-800-53-CM-6(a)
    - NIST-800-53-CM-7(a)
    - NIST-800-53-CM-7(b)
    - NIST-800-53-MP-7
    - configure_strategy
    - high_disruption
    - low_complexity
    - medium_severity
    - mount_option_var_log_audit_nodev
    - no_reboot_needed

  - name: 'Add nodev Option to /var/log/audit: If /var/log/audit not mounted, craft
      mount_info manually'
    set_fact:
      mount_info: '{{ mount_info|default({})|combine({item.0: item.1}) }}'
    with_together:
    - - target
      - source
      - fstype
      - options
    - - /var/log/audit
      - ''
      - ''
      - defaults
    when:
    - ( not ( "kernel" in ansible_facts.packages and "rpm-ostree" in ansible_facts.packages
      and "bootc" in ansible_facts.packages and not "openshift-kubelet" in ansible_facts.packages
      and "ostree" in ansible_proc_cmdline ) and not ( ansible_virtualization_type
      in ["docker", "lxc", "openvz", "podman", "container"] ) )
    - '"/var/log/audit" in ansible_mounts | map(attribute="mount") | list'
    - ("--fstab" | length == 0)
    - device_name.stdout is defined and device_name.stdout_lines is defined
    - (device_name.stdout | length == 0)
    tags:
    - DISA-STIG-OL09-00-002064
    - NIST-800-53-AC-6
    - NIST-800-53-AC-6(1)
    - NIST-800-53-CM-6(a)
    - NIST-800-53-CM-7(a)
    - NIST-800-53-CM-7(b)
    - NIST-800-53-MP-7
    - configure_strategy
    - high_disruption
    - low_complexity
    - medium_severity
    - mount_option_var_log_audit_nodev
    - no_reboot_needed

  - name: 'Add nodev Option to /var/log/audit: Make sure nodev option is part of the
      to /var/log/audit options'
    set_fact:
      mount_info: '{{ mount_info | combine( {''options'':''''~(mount_info.options
        | default(''''))~('','' if (mount_info.options | default('''')) else '''')~''nodev''
        }) }}'
    when:
    - ( not ( "kernel" in ansible_facts.packages and "rpm-ostree" in ansible_facts.packages
      and "bootc" in ansible_facts.packages and not "openshift-kubelet" in ansible_facts.packages
      and "ostree" in ansible_proc_cmdline ) and not ( ansible_virtualization_type
      in ["docker", "lxc", "openvz", "podman", "container"] ) )
    - '"/var/log/audit" in ansible_mounts | map(attribute="mount") | list'
    - mount_info is defined and "nodev" not in (mount_info.options | default(''))
    tags:
    - DISA-STIG-OL09-00-002064
    - NIST-800-53-AC-6
    - NIST-800-53-AC-6(1)
    - NIST-800-53-CM-6(a)
    - NIST-800-53-CM-7(a)
    - NIST-800-53-CM-7(b)
    - NIST-800-53-MP-7
    - configure_strategy
    - high_disruption
    - low_complexity
    - medium_severity
    - mount_option_var_log_audit_nodev
    - no_reboot_needed

  - name: 'Add nodev Option to /var/log/audit: Ensure /var/log/audit is mounted with
      nodev option'
    ansible.posix.mount:
      path: /var/log/audit
      src: '{{ mount_info.source | default('''') }}'
      opts: '{{ mount_info.options | default('''') }}'
      state: mounted
      fstype: '{{ mount_info.fstype | default('''') }}'
    register: mount_result
    failed_when:
    - mount_result is failed
    - '''target is busy'' not in (mount_result.msg | default(''''))'
    - '''already mounted'' not in (mount_result.msg | default(''''))'
    when:
    - ( not ( "kernel" in ansible_facts.packages and "rpm-ostree" in ansible_facts.packages
      and "bootc" in ansible_facts.packages and not "openshift-kubelet" in ansible_facts.packages
      and "ostree" in ansible_proc_cmdline ) and not ( ansible_virtualization_type
      in ["docker", "lxc", "openvz", "podman", "container"] ) )
    - '"/var/log/audit" in ansible_mounts | map(attribute="mount") | list'
    - mount_info is defined
    - (device_name.stdout is defined and (device_name.stdout | length > 0)) or ("--fstab"
      | length == 0)
    tags:
    - DISA-STIG-OL09-00-002064
    - NIST-800-53-AC-6
    - NIST-800-53-AC-6(1)
    - NIST-800-53-CM-6(a)
    - NIST-800-53-CM-7(a)
    - NIST-800-53-CM-7(b)
    - NIST-800-53-MP-7
    - configure_strategy
    - high_disruption
    - low_complexity
    - medium_severity
    - mount_option_var_log_audit_nodev
    - no_reboot_needed

  - name: 'Add noexec Option to /var/log/audit: Check information associated to mountpoint'
    ansible.builtin.command: findmnt --fstab '/var/log/audit'
    register: device_name
    failed_when: device_name.rc > 1
    changed_when: false
    check_mode: false
    when:
    - ( not ( "kernel" in ansible_facts.packages and "rpm-ostree" in ansible_facts.packages
      and "bootc" in ansible_facts.packages and not "openshift-kubelet" in ansible_facts.packages
      and "ostree" in ansible_proc_cmdline ) and not ( ansible_virtualization_type
      in ["docker", "lxc", "openvz", "podman", "container"] ) )
    - '"/var/log/audit" in ansible_mounts | map(attribute="mount") | list'
    tags:
    - DISA-STIG-OL09-00-002065
    - NIST-800-53-AC-6
    - NIST-800-53-AC-6(1)
    - NIST-800-53-CM-6(a)
    - NIST-800-53-CM-7(a)
    - NIST-800-53-CM-7(b)
    - NIST-800-53-MP-7
    - configure_strategy
    - high_disruption
    - low_complexity
    - medium_severity
    - mount_option_var_log_audit_noexec
    - no_reboot_needed

  - name: 'Add noexec Option to /var/log/audit: Create mount_info dictionary variable'
    set_fact:
      mount_info: '{{ mount_info|default({})|combine({item.0: item.1}) }}'
    with_together:
    - '{{ device_name.stdout_lines[0].split() | map(''lower'') | list }}'
    - '{{ device_name.stdout_lines[1].split() | list }}'
    when:
    - ( not ( "kernel" in ansible_facts.packages and "rpm-ostree" in ansible_facts.packages
      and "bootc" in ansible_facts.packages and not "openshift-kubelet" in ansible_facts.packages
      and "ostree" in ansible_proc_cmdline ) and not ( ansible_virtualization_type
      in ["docker", "lxc", "openvz", "podman", "container"] ) )
    - '"/var/log/audit" in ansible_mounts | map(attribute="mount") | list'
    - device_name.stdout is defined and device_name.stdout_lines is defined
    - (device_name.stdout | length > 0)
    tags:
    - DISA-STIG-OL09-00-002065
    - NIST-800-53-AC-6
    - NIST-800-53-AC-6(1)
    - NIST-800-53-CM-6(a)
    - NIST-800-53-CM-7(a)
    - NIST-800-53-CM-7(b)
    - NIST-800-53-MP-7
    - configure_strategy
    - high_disruption
    - low_complexity
    - medium_severity
    - mount_option_var_log_audit_noexec
    - no_reboot_needed

  - name: 'Add noexec Option to /var/log/audit: If /var/log/audit not mounted, craft
      mount_info manually'
    set_fact:
      mount_info: '{{ mount_info|default({})|combine({item.0: item.1}) }}'
    with_together:
    - - target
      - source
      - fstype
      - options
    - - /var/log/audit
      - ''
      - ''
      - defaults
    when:
    - ( not ( "kernel" in ansible_facts.packages and "rpm-ostree" in ansible_facts.packages
      and "bootc" in ansible_facts.packages and not "openshift-kubelet" in ansible_facts.packages
      and "ostree" in ansible_proc_cmdline ) and not ( ansible_virtualization_type
      in ["docker", "lxc", "openvz", "podman", "container"] ) )
    - '"/var/log/audit" in ansible_mounts | map(attribute="mount") | list'
    - ("--fstab" | length == 0)
    - device_name.stdout is defined and device_name.stdout_lines is defined
    - (device_name.stdout | length == 0)
    tags:
    - DISA-STIG-OL09-00-002065
    - NIST-800-53-AC-6
    - NIST-800-53-AC-6(1)
    - NIST-800-53-CM-6(a)
    - NIST-800-53-CM-7(a)
    - NIST-800-53-CM-7(b)
    - NIST-800-53-MP-7
    - configure_strategy
    - high_disruption
    - low_complexity
    - medium_severity
    - mount_option_var_log_audit_noexec
    - no_reboot_needed

  - name: 'Add noexec Option to /var/log/audit: Make sure noexec option is part of
      the to /var/log/audit options'
    set_fact:
      mount_info: '{{ mount_info | combine( {''options'':''''~(mount_info.options
        | default(''''))~('','' if (mount_info.options | default('''')) else '''')~''noexec''
        }) }}'
    when:
    - ( not ( "kernel" in ansible_facts.packages and "rpm-ostree" in ansible_facts.packages
      and "bootc" in ansible_facts.packages and not "openshift-kubelet" in ansible_facts.packages
      and "ostree" in ansible_proc_cmdline ) and not ( ansible_virtualization_type
      in ["docker", "lxc", "openvz", "podman", "container"] ) )
    - '"/var/log/audit" in ansible_mounts | map(attribute="mount") | list'
    - mount_info is defined and "noexec" not in (mount_info.options | default(''))
    tags:
    - DISA-STIG-OL09-00-002065
    - NIST-800-53-AC-6
    - NIST-800-53-AC-6(1)
    - NIST-800-53-CM-6(a)
    - NIST-800-53-CM-7(a)
    - NIST-800-53-CM-7(b)
    - NIST-800-53-MP-7
    - configure_strategy
    - high_disruption
    - low_complexity
    - medium_severity
    - mount_option_var_log_audit_noexec
    - no_reboot_needed

  - name: 'Add noexec Option to /var/log/audit: Ensure /var/log/audit is mounted with
      noexec option'
    ansible.posix.mount:
      path: /var/log/audit
      src: '{{ mount_info.source | default('''') }}'
      opts: '{{ mount_info.options | default('''') }}'
      state: mounted
      fstype: '{{ mount_info.fstype | default('''') }}'
    register: mount_result
    failed_when:
    - mount_result is failed
    - '''target is busy'' not in (mount_result.msg | default(''''))'
    - '''already mounted'' not in (mount_result.msg | default(''''))'
    when:
    - ( not ( "kernel" in ansible_facts.packages and "rpm-ostree" in ansible_facts.packages
      and "bootc" in ansible_facts.packages and not "openshift-kubelet" in ansible_facts.packages
      and "ostree" in ansible_proc_cmdline ) and not ( ansible_virtualization_type
      in ["docker", "lxc", "openvz", "podman", "container"] ) )
    - '"/var/log/audit" in ansible_mounts | map(attribute="mount") | list'
    - mount_info is defined
    - (device_name.stdout is defined and (device_name.stdout | length > 0)) or ("--fstab"
      | length == 0)
    tags:
    - DISA-STIG-OL09-00-002065
    - NIST-800-53-AC-6
    - NIST-800-53-AC-6(1)
    - NIST-800-53-CM-6(a)
    - NIST-800-53-CM-7(a)
    - NIST-800-53-CM-7(b)
    - NIST-800-53-MP-7
    - configure_strategy
    - high_disruption
    - low_complexity
    - medium_severity
    - mount_option_var_log_audit_noexec
    - no_reboot_needed

  - name: 'Add nosuid Option to /var/log/audit: Check information associated to mountpoint'
    ansible.builtin.command: findmnt --fstab '/var/log/audit'
    register: device_name
    failed_when: device_name.rc > 1
    changed_when: false
    check_mode: false
    when:
    - ( not ( "kernel" in ansible_facts.packages and "rpm-ostree" in ansible_facts.packages
      and "bootc" in ansible_facts.packages and not "openshift-kubelet" in ansible_facts.packages
      and "ostree" in ansible_proc_cmdline ) and not ( ansible_virtualization_type
      in ["docker", "lxc", "openvz", "podman", "container"] ) )
    - '"/var/log/audit" in ansible_mounts | map(attribute="mount") | list'
    tags:
    - DISA-STIG-OL09-00-002066
    - NIST-800-53-AC-6
    - NIST-800-53-AC-6(1)
    - NIST-800-53-CM-6(a)
    - NIST-800-53-CM-7(a)
    - NIST-800-53-CM-7(b)
    - NIST-800-53-MP-7
    - configure_strategy
    - high_disruption
    - low_complexity
    - medium_severity
    - mount_option_var_log_audit_nosuid
    - no_reboot_needed

  - name: 'Add nosuid Option to /var/log/audit: Create mount_info dictionary variable'
    set_fact:
      mount_info: '{{ mount_info|default({})|combine({item.0: item.1}) }}'
    with_together:
    - '{{ device_name.stdout_lines[0].split() | map(''lower'') | list }}'
    - '{{ device_name.stdout_lines[1].split() | list }}'
    when:
    - ( not ( "kernel" in ansible_facts.packages and "rpm-ostree" in ansible_facts.packages
      and "bootc" in ansible_facts.packages and not "openshift-kubelet" in ansible_facts.packages
      and "ostree" in ansible_proc_cmdline ) and not ( ansible_virtualization_type
      in ["docker", "lxc", "openvz", "podman", "container"] ) )
    - '"/var/log/audit" in ansible_mounts | map(attribute="mount") | list'
    - device_name.stdout is defined and device_name.stdout_lines is defined
    - (device_name.stdout | length > 0)
    tags:
    - DISA-STIG-OL09-00-002066
    - NIST-800-53-AC-6
    - NIST-800-53-AC-6(1)
    - NIST-800-53-CM-6(a)
    - NIST-800-53-CM-7(a)
    - NIST-800-53-CM-7(b)
    - NIST-800-53-MP-7
    - configure_strategy
    - high_disruption
    - low_complexity
    - medium_severity
    - mount_option_var_log_audit_nosuid
    - no_reboot_needed

  - name: 'Add nosuid Option to /var/log/audit: If /var/log/audit not mounted, craft
      mount_info manually'
    set_fact:
      mount_info: '{{ mount_info|default({})|combine({item.0: item.1}) }}'
    with_together:
    - - target
      - source
      - fstype
      - options
    - - /var/log/audit
      - ''
      - ''
      - defaults
    when:
    - ( not ( "kernel" in ansible_facts.packages and "rpm-ostree" in ansible_facts.packages
      and "bootc" in ansible_facts.packages and not "openshift-kubelet" in ansible_facts.packages
      and "ostree" in ansible_proc_cmdline ) and not ( ansible_virtualization_type
      in ["docker", "lxc", "openvz", "podman", "container"] ) )
    - '"/var/log/audit" in ansible_mounts | map(attribute="mount") | list'
    - ("--fstab" | length == 0)
    - device_name.stdout is defined and device_name.stdout_lines is defined
    - (device_name.stdout | length == 0)
    tags:
    - DISA-STIG-OL09-00-002066
    - NIST-800-53-AC-6
    - NIST-800-53-AC-6(1)
    - NIST-800-53-CM-6(a)
    - NIST-800-53-CM-7(a)
    - NIST-800-53-CM-7(b)
    - NIST-800-53-MP-7
    - configure_strategy
    - high_disruption
    - low_complexity
    - medium_severity
    - mount_option_var_log_audit_nosuid
    - no_reboot_needed

  - name: 'Add nosuid Option to /var/log/audit: Make sure nosuid option is part of
      the to /var/log/audit options'
    set_fact:
      mount_info: '{{ mount_info | combine( {''options'':''''~(mount_info.options
        | default(''''))~('','' if (mount_info.options | default('''')) else '''')~''nosuid''
        }) }}'
    when:
    - ( not ( "kernel" in ansible_facts.packages and "rpm-ostree" in ansible_facts.packages
      and "bootc" in ansible_facts.packages and not "openshift-kubelet" in ansible_facts.packages
      and "ostree" in ansible_proc_cmdline ) and not ( ansible_virtualization_type
      in ["docker", "lxc", "openvz", "podman", "container"] ) )
    - '"/var/log/audit" in ansible_mounts | map(attribute="mount") | list'
    - mount_info is defined and "nosuid" not in (mount_info.options | default(''))
    tags:
    - DISA-STIG-OL09-00-002066
    - NIST-800-53-AC-6
    - NIST-800-53-AC-6(1)
    - NIST-800-53-CM-6(a)
    - NIST-800-53-CM-7(a)
    - NIST-800-53-CM-7(b)
    - NIST-800-53-MP-7
    - configure_strategy
    - high_disruption
    - low_complexity
    - medium_severity
    - mount_option_var_log_audit_nosuid
    - no_reboot_needed

  - name: 'Add nosuid Option to /var/log/audit: Ensure /var/log/audit is mounted with
      nosuid option'
    ansible.posix.mount:
      path: /var/log/audit
      src: '{{ mount_info.source | default('''') }}'
      opts: '{{ mount_info.options | default('''') }}'
      state: mounted
      fstype: '{{ mount_info.fstype | default('''') }}'
    register: mount_result
    failed_when:
    - mount_result is failed
    - '''target is busy'' not in (mount_result.msg | default(''''))'
    - '''already mounted'' not in (mount_result.msg | default(''''))'
    when:
    - ( not ( "kernel" in ansible_facts.packages and "rpm-ostree" in ansible_facts.packages
      and "bootc" in ansible_facts.packages and not "openshift-kubelet" in ansible_facts.packages
      and "ostree" in ansible_proc_cmdline ) and not ( ansible_virtualization_type
      in ["docker", "lxc", "openvz", "podman", "container"] ) )
    - '"/var/log/audit" in ansible_mounts | map(attribute="mount") | list'
    - mount_info is defined
    - (device_name.stdout is defined and (device_name.stdout | length > 0)) or ("--fstab"
      | length == 0)
    tags:
    - DISA-STIG-OL09-00-002066
    - NIST-800-53-AC-6
    - NIST-800-53-AC-6(1)
    - NIST-800-53-CM-6(a)
    - NIST-800-53-CM-7(a)
    - NIST-800-53-CM-7(b)
    - NIST-800-53-MP-7
    - configure_strategy
    - high_disruption
    - low_complexity
    - medium_severity
    - mount_option_var_log_audit_nosuid
    - no_reboot_needed

  - name: 'Add nodev Option to /var/log: Check information associated to mountpoint'
    ansible.builtin.command: findmnt --fstab '/var/log'
    register: device_name
    failed_when: device_name.rc > 1
    changed_when: false
    check_mode: false
    when:
    - ( not ( "kernel" in ansible_facts.packages and "rpm-ostree" in ansible_facts.packages
      and "bootc" in ansible_facts.packages and not "openshift-kubelet" in ansible_facts.packages
      and "ostree" in ansible_proc_cmdline ) and not ( ansible_virtualization_type
      in ["docker", "lxc", "openvz", "podman", "container"] ) )
    - '"/var/log" in ansible_mounts | map(attribute="mount") | list'
    tags:
    - DISA-STIG-OL09-00-002061
    - NIST-800-53-AC-6
    - NIST-800-53-AC-6(1)
    - NIST-800-53-CM-6(a)
    - NIST-800-53-CM-7(a)
    - NIST-800-53-CM-7(b)
    - NIST-800-53-MP-7
    - configure_strategy
    - high_disruption
    - low_complexity
    - medium_severity
    - mount_option_var_log_nodev
    - no_reboot_needed

  - name: 'Add nodev Option to /var/log: Create mount_info dictionary variable'
    set_fact:
      mount_info: '{{ mount_info|default({})|combine({item.0: item.1}) }}'
    with_together:
    - '{{ device_name.stdout_lines[0].split() | map(''lower'') | list }}'
    - '{{ device_name.stdout_lines[1].split() | list }}'
    when:
    - ( not ( "kernel" in ansible_facts.packages and "rpm-ostree" in ansible_facts.packages
      and "bootc" in ansible_facts.packages and not "openshift-kubelet" in ansible_facts.packages
      and "ostree" in ansible_proc_cmdline ) and not ( ansible_virtualization_type
      in ["docker", "lxc", "openvz", "podman", "container"] ) )
    - '"/var/log" in ansible_mounts | map(attribute="mount") | list'
    - device_name.stdout is defined and device_name.stdout_lines is defined
    - (device_name.stdout | length > 0)
    tags:
    - DISA-STIG-OL09-00-002061
    - NIST-800-53-AC-6
    - NIST-800-53-AC-6(1)
    - NIST-800-53-CM-6(a)
    - NIST-800-53-CM-7(a)
    - NIST-800-53-CM-7(b)
    - NIST-800-53-MP-7
    - configure_strategy
    - high_disruption
    - low_complexity
    - medium_severity
    - mount_option_var_log_nodev
    - no_reboot_needed

  - name: 'Add nodev Option to /var/log: If /var/log not mounted, craft mount_info
      manually'
    set_fact:
      mount_info: '{{ mount_info|default({})|combine({item.0: item.1}) }}'
    with_together:
    - - target
      - source
      - fstype
      - options
    - - /var/log
      - ''
      - ''
      - defaults
    when:
    - ( not ( "kernel" in ansible_facts.packages and "rpm-ostree" in ansible_facts.packages
      and "bootc" in ansible_facts.packages and not "openshift-kubelet" in ansible_facts.packages
      and "ostree" in ansible_proc_cmdline ) and not ( ansible_virtualization_type
      in ["docker", "lxc", "openvz", "podman", "container"] ) )
    - '"/var/log" in ansible_mounts | map(attribute="mount") | list'
    - ("--fstab" | length == 0)
    - device_name.stdout is defined and device_name.stdout_lines is defined
    - (device_name.stdout | length == 0)
    tags:
    - DISA-STIG-OL09-00-002061
    - NIST-800-53-AC-6
    - NIST-800-53-AC-6(1)
    - NIST-800-53-CM-6(a)
    - NIST-800-53-CM-7(a)
    - NIST-800-53-CM-7(b)
    - NIST-800-53-MP-7
    - configure_strategy
    - high_disruption
    - low_complexity
    - medium_severity
    - mount_option_var_log_nodev
    - no_reboot_needed

  - name: 'Add nodev Option to /var/log: Make sure nodev option is part of the to
      /var/log options'
    set_fact:
      mount_info: '{{ mount_info | combine( {''options'':''''~(mount_info.options
        | default(''''))~('','' if (mount_info.options | default('''')) else '''')~''nodev''
        }) }}'
    when:
    - ( not ( "kernel" in ansible_facts.packages and "rpm-ostree" in ansible_facts.packages
      and "bootc" in ansible_facts.packages and not "openshift-kubelet" in ansible_facts.packages
      and "ostree" in ansible_proc_cmdline ) and not ( ansible_virtualization_type
      in ["docker", "lxc", "openvz", "podman", "container"] ) )
    - '"/var/log" in ansible_mounts | map(attribute="mount") | list'
    - mount_info is defined and "nodev" not in (mount_info.options | default(''))
    tags:
    - DISA-STIG-OL09-00-002061
    - NIST-800-53-AC-6
    - NIST-800-53-AC-6(1)
    - NIST-800-53-CM-6(a)
    - NIST-800-53-CM-7(a)
    - NIST-800-53-CM-7(b)
    - NIST-800-53-MP-7
    - configure_strategy
    - high_disruption
    - low_complexity
    - medium_severity
    - mount_option_var_log_nodev
    - no_reboot_needed

  - name: 'Add nodev Option to /var/log: Ensure /var/log is mounted with nodev option'
    ansible.posix.mount:
      path: /var/log
      src: '{{ mount_info.source | default('''') }}'
      opts: '{{ mount_info.options | default('''') }}'
      state: mounted
      fstype: '{{ mount_info.fstype | default('''') }}'
    register: mount_result
    failed_when:
    - mount_result is failed
    - '''target is busy'' not in (mount_result.msg | default(''''))'
    - '''already mounted'' not in (mount_result.msg | default(''''))'
    when:
    - ( not ( "kernel" in ansible_facts.packages and "rpm-ostree" in ansible_facts.packages
      and "bootc" in ansible_facts.packages and not "openshift-kubelet" in ansible_facts.packages
      and "ostree" in ansible_proc_cmdline ) and not ( ansible_virtualization_type
      in ["docker", "lxc", "openvz", "podman", "container"] ) )
    - '"/var/log" in ansible_mounts | map(attribute="mount") | list'
    - mount_info is defined
    - (device_name.stdout is defined and (device_name.stdout | length > 0)) or ("--fstab"
      | length == 0)
    tags:
    - DISA-STIG-OL09-00-002061
    - NIST-800-53-AC-6
    - NIST-800-53-AC-6(1)
    - NIST-800-53-CM-6(a)
    - NIST-800-53-CM-7(a)
    - NIST-800-53-CM-7(b)
    - NIST-800-53-MP-7
    - configure_strategy
    - high_disruption
    - low_complexity
    - medium_severity
    - mount_option_var_log_nodev
    - no_reboot_needed

  - name: 'Add noexec Option to /var/log: Check information associated to mountpoint'
    ansible.builtin.command: findmnt --fstab '/var/log'
    register: device_name
    failed_when: device_name.rc > 1
    changed_when: false
    check_mode: false
    when:
    - ( not ( "kernel" in ansible_facts.packages and "rpm-ostree" in ansible_facts.packages
      and "bootc" in ansible_facts.packages and not "openshift-kubelet" in ansible_facts.packages
      and "ostree" in ansible_proc_cmdline ) and not ( ansible_virtualization_type
      in ["docker", "lxc", "openvz", "podman", "container"] ) )
    - '"/var/log" in ansible_mounts | map(attribute="mount") | list'
    tags:
    - DISA-STIG-OL09-00-002062
    - NIST-800-53-AC-6
    - NIST-800-53-AC-6(1)
    - NIST-800-53-CM-6(a)
    - NIST-800-53-CM-7(a)
    - NIST-800-53-CM-7(b)
    - NIST-800-53-MP-7
    - configure_strategy
    - high_disruption
    - low_complexity
    - medium_severity
    - mount_option_var_log_noexec
    - no_reboot_needed

  - name: 'Add noexec Option to /var/log: Create mount_info dictionary variable'
    set_fact:
      mount_info: '{{ mount_info|default({})|combine({item.0: item.1}) }}'
    with_together:
    - '{{ device_name.stdout_lines[0].split() | map(''lower'') | list }}'
    - '{{ device_name.stdout_lines[1].split() | list }}'
    when:
    - ( not ( "kernel" in ansible_facts.packages and "rpm-ostree" in ansible_facts.packages
      and "bootc" in ansible_facts.packages and not "openshift-kubelet" in ansible_facts.packages
      and "ostree" in ansible_proc_cmdline ) and not ( ansible_virtualization_type
      in ["docker", "lxc", "openvz", "podman", "container"] ) )
    - '"/var/log" in ansible_mounts | map(attribute="mount") | list'
    - device_name.stdout is defined and device_name.stdout_lines is defined
    - (device_name.stdout | length > 0)
    tags:
    - DISA-STIG-OL09-00-002062
    - NIST-800-53-AC-6
    - NIST-800-53-AC-6(1)
    - NIST-800-53-CM-6(a)
    - NIST-800-53-CM-7(a)
    - NIST-800-53-CM-7(b)
    - NIST-800-53-MP-7
    - configure_strategy
    - high_disruption
    - low_complexity
    - medium_severity
    - mount_option_var_log_noexec
    - no_reboot_needed

  - name: 'Add noexec Option to /var/log: If /var/log not mounted, craft mount_info
      manually'
    set_fact:
      mount_info: '{{ mount_info|default({})|combine({item.0: item.1}) }}'
    with_together:
    - - target
      - source
      - fstype
      - options
    - - /var/log
      - ''
      - ''
      - defaults
    when:
    - ( not ( "kernel" in ansible_facts.packages and "rpm-ostree" in ansible_facts.packages
      and "bootc" in ansible_facts.packages and not "openshift-kubelet" in ansible_facts.packages
      and "ostree" in ansible_proc_cmdline ) and not ( ansible_virtualization_type
      in ["docker", "lxc", "openvz", "podman", "container"] ) )
    - '"/var/log" in ansible_mounts | map(attribute="mount") | list'
    - ("--fstab" | length == 0)
    - device_name.stdout is defined and device_name.stdout_lines is defined
    - (device_name.stdout | length == 0)
    tags:
    - DISA-STIG-OL09-00-002062
    - NIST-800-53-AC-6
    - NIST-800-53-AC-6(1)
    - NIST-800-53-CM-6(a)
    - NIST-800-53-CM-7(a)
    - NIST-800-53-CM-7(b)
    - NIST-800-53-MP-7
    - configure_strategy
    - high_disruption
    - low_complexity
    - medium_severity
    - mount_option_var_log_noexec
    - no_reboot_needed

  - name: 'Add noexec Option to /var/log: Make sure noexec option is part of the to
      /var/log options'
    set_fact:
      mount_info: '{{ mount_info | combine( {''options'':''''~(mount_info.options
        | default(''''))~('','' if (mount_info.options | default('''')) else '''')~''noexec''
        }) }}'
    when:
    - ( not ( "kernel" in ansible_facts.packages and "rpm-ostree" in ansible_facts.packages
      and "bootc" in ansible_facts.packages and not "openshift-kubelet" in ansible_facts.packages
      and "ostree" in ansible_proc_cmdline ) and not ( ansible_virtualization_type
      in ["docker", "lxc", "openvz", "podman", "container"] ) )
    - '"/var/log" in ansible_mounts | map(attribute="mount") | list'
    - mount_info is defined and "noexec" not in (mount_info.options | default(''))
    tags:
    - DISA-STIG-OL09-00-002062
    - NIST-800-53-AC-6
    - NIST-800-53-AC-6(1)
    - NIST-800-53-CM-6(a)
    - NIST-800-53-CM-7(a)
    - NIST-800-53-CM-7(b)
    - NIST-800-53-MP-7
    - configure_strategy
    - high_disruption
    - low_complexity
    - medium_severity
    - mount_option_var_log_noexec
    - no_reboot_needed

  - name: 'Add noexec Option to /var/log: Ensure /var/log is mounted with noexec option'
    ansible.posix.mount:
      path: /var/log
      src: '{{ mount_info.source | default('''') }}'
      opts: '{{ mount_info.options | default('''') }}'
      state: mounted
      fstype: '{{ mount_info.fstype | default('''') }}'
    register: mount_result
    failed_when:
    - mount_result is failed
    - '''target is busy'' not in (mount_result.msg | default(''''))'
    - '''already mounted'' not in (mount_result.msg | default(''''))'
    when:
    - ( not ( "kernel" in ansible_facts.packages and "rpm-ostree" in ansible_facts.packages
      and "bootc" in ansible_facts.packages and not "openshift-kubelet" in ansible_facts.packages
      and "ostree" in ansible_proc_cmdline ) and not ( ansible_virtualization_type
      in ["docker", "lxc", "openvz", "podman", "container"] ) )
    - '"/var/log" in ansible_mounts | map(attribute="mount") | list'
    - mount_info is defined
    - (device_name.stdout is defined and (device_name.stdout | length > 0)) or ("--fstab"
      | length == 0)
    tags:
    - DISA-STIG-OL09-00-002062
    - NIST-800-53-AC-6
    - NIST-800-53-AC-6(1)
    - NIST-800-53-CM-6(a)
    - NIST-800-53-CM-7(a)
    - NIST-800-53-CM-7(b)
    - NIST-800-53-MP-7
    - configure_strategy
    - high_disruption
    - low_complexity
    - medium_severity
    - mount_option_var_log_noexec
    - no_reboot_needed

  - name: 'Add nosuid Option to /var/log: Check information associated to mountpoint'
    ansible.builtin.command: findmnt --fstab '/var/log'
    register: device_name
    failed_when: device_name.rc > 1
    changed_when: false
    check_mode: false
    when:
    - ( not ( "kernel" in ansible_facts.packages and "rpm-ostree" in ansible_facts.packages
      and "bootc" in ansible_facts.packages and not "openshift-kubelet" in ansible_facts.packages
      and "ostree" in ansible_proc_cmdline ) and not ( ansible_virtualization_type
      in ["docker", "lxc", "openvz", "podman", "container"] ) )
    - '"/var/log" in ansible_mounts | map(attribute="mount") | list'
    tags:
    - DISA-STIG-OL09-00-002063
    - NIST-800-53-AC-6
    - NIST-800-53-AC-6(1)
    - NIST-800-53-CM-6(a)
    - NIST-800-53-CM-7(a)
    - NIST-800-53-CM-7(b)
    - NIST-800-53-MP-7
    - configure_strategy
    - high_disruption
    - low_complexity
    - medium_severity
    - mount_option_var_log_nosuid
    - no_reboot_needed

  - name: 'Add nosuid Option to /var/log: Create mount_info dictionary variable'
    set_fact:
      mount_info: '{{ mount_info|default({})|combine({item.0: item.1}) }}'
    with_together:
    - '{{ device_name.stdout_lines[0].split() | map(''lower'') | list }}'
    - '{{ device_name.stdout_lines[1].split() | list }}'
    when:
    - ( not ( "kernel" in ansible_facts.packages and "rpm-ostree" in ansible_facts.packages
      and "bootc" in ansible_facts.packages and not "openshift-kubelet" in ansible_facts.packages
      and "ostree" in ansible_proc_cmdline ) and not ( ansible_virtualization_type
      in ["docker", "lxc", "openvz", "podman", "container"] ) )
    - '"/var/log" in ansible_mounts | map(attribute="mount") | list'
    - device_name.stdout is defined and device_name.stdout_lines is defined
    - (device_name.stdout | length > 0)
    tags:
    - DISA-STIG-OL09-00-002063
    - NIST-800-53-AC-6
    - NIST-800-53-AC-6(1)
    - NIST-800-53-CM-6(a)
    - NIST-800-53-CM-7(a)
    - NIST-800-53-CM-7(b)
    - NIST-800-53-MP-7
    - configure_strategy
    - high_disruption
    - low_complexity
    - medium_severity
    - mount_option_var_log_nosuid
    - no_reboot_needed

  - name: 'Add nosuid Option to /var/log: If /var/log not mounted, craft mount_info
      manually'
    set_fact:
      mount_info: '{{ mount_info|default({})|combine({item.0: item.1}) }}'
    with_together:
    - - target
      - source
      - fstype
      - options
    - - /var/log
      - ''
      - ''
      - defaults
    when:
    - ( not ( "kernel" in ansible_facts.packages and "rpm-ostree" in ansible_facts.packages
      and "bootc" in ansible_facts.packages and not "openshift-kubelet" in ansible_facts.packages
      and "ostree" in ansible_proc_cmdline ) and not ( ansible_virtualization_type
      in ["docker", "lxc", "openvz", "podman", "container"] ) )
    - '"/var/log" in ansible_mounts | map(attribute="mount") | list'
    - ("--fstab" | length == 0)
    - device_name.stdout is defined and device_name.stdout_lines is defined
    - (device_name.stdout | length == 0)
    tags:
    - DISA-STIG-OL09-00-002063
    - NIST-800-53-AC-6
    - NIST-800-53-AC-6(1)
    - NIST-800-53-CM-6(a)
    - NIST-800-53-CM-7(a)
    - NIST-800-53-CM-7(b)
    - NIST-800-53-MP-7
    - configure_strategy
    - high_disruption
    - low_complexity
    - medium_severity
    - mount_option_var_log_nosuid
    - no_reboot_needed

  - name: 'Add nosuid Option to /var/log: Make sure nosuid option is part of the to
      /var/log options'
    set_fact:
      mount_info: '{{ mount_info | combine( {''options'':''''~(mount_info.options
        | default(''''))~('','' if (mount_info.options | default('''')) else '''')~''nosuid''
        }) }}'
    when:
    - ( not ( "kernel" in ansible_facts.packages and "rpm-ostree" in ansible_facts.packages
      and "bootc" in ansible_facts.packages and not "openshift-kubelet" in ansible_facts.packages
      and "ostree" in ansible_proc_cmdline ) and not ( ansible_virtualization_type
      in ["docker", "lxc", "openvz", "podman", "container"] ) )
    - '"/var/log" in ansible_mounts | map(attribute="mount") | list'
    - mount_info is defined and "nosuid" not in (mount_info.options | default(''))
    tags:
    - DISA-STIG-OL09-00-002063
    - NIST-800-53-AC-6
    - NIST-800-53-AC-6(1)
    - NIST-800-53-CM-6(a)
    - NIST-800-53-CM-7(a)
    - NIST-800-53-CM-7(b)
    - NIST-800-53-MP-7
    - configure_strategy
    - high_disruption
    - low_complexity
    - medium_severity
    - mount_option_var_log_nosuid
    - no_reboot_needed

  - name: 'Add nosuid Option to /var/log: Ensure /var/log is mounted with nosuid option'
    ansible.posix.mount:
      path: /var/log
      src: '{{ mount_info.source | default('''') }}'
      opts: '{{ mount_info.options | default('''') }}'
      state: mounted
      fstype: '{{ mount_info.fstype | default('''') }}'
    register: mount_result
    failed_when:
    - mount_result is failed
    - '''target is busy'' not in (mount_result.msg | default(''''))'
    - '''already mounted'' not in (mount_result.msg | default(''''))'
    when:
    - ( not ( "kernel" in ansible_facts.packages and "rpm-ostree" in ansible_facts.packages
      and "bootc" in ansible_facts.packages and not "openshift-kubelet" in ansible_facts.packages
      and "ostree" in ansible_proc_cmdline ) and not ( ansible_virtualization_type
      in ["docker", "lxc", "openvz", "podman", "container"] ) )
    - '"/var/log" in ansible_mounts | map(attribute="mount") | list'
    - mount_info is defined
    - (device_name.stdout is defined and (device_name.stdout | length > 0)) or ("--fstab"
      | length == 0)
    tags:
    - DISA-STIG-OL09-00-002063
    - NIST-800-53-AC-6
    - NIST-800-53-AC-6(1)
    - NIST-800-53-CM-6(a)
    - NIST-800-53-CM-7(a)
    - NIST-800-53-CM-7(b)
    - NIST-800-53-MP-7
    - configure_strategy
    - high_disruption
    - low_complexity
    - medium_severity
    - mount_option_var_log_nosuid
    - no_reboot_needed

  - name: 'Add nodev Option to /var: Check information associated to mountpoint'
    ansible.builtin.command: findmnt --fstab '/var'
    register: device_name
    failed_when: device_name.rc > 1
    changed_when: false
    check_mode: false
    when:
    - ( not ( "kernel" in ansible_facts.packages and "rpm-ostree" in ansible_facts.packages
      and "bootc" in ansible_facts.packages and not "openshift-kubelet" in ansible_facts.packages
      and "ostree" in ansible_proc_cmdline ) and not ( ansible_virtualization_type
      in ["docker", "lxc", "openvz", "podman", "container"] ) )
    - '"/var" in ansible_mounts | map(attribute="mount") | list'
    tags:
    - DISA-STIG-OL09-00-002060
    - NIST-800-53-AC-6
    - NIST-800-53-AC-6(1)
    - NIST-800-53-CM-6(a)
    - NIST-800-53-CM-7(a)
    - NIST-800-53-CM-7(b)
    - NIST-800-53-MP-7
    - configure_strategy
    - high_disruption
    - low_complexity
    - medium_severity
    - mount_option_var_nodev
    - no_reboot_needed

  - name: 'Add nodev Option to /var: Create mount_info dictionary variable'
    set_fact:
      mount_info: '{{ mount_info|default({})|combine({item.0: item.1}) }}'
    with_together:
    - '{{ device_name.stdout_lines[0].split() | map(''lower'') | list }}'
    - '{{ device_name.stdout_lines[1].split() | list }}'
    when:
    - ( not ( "kernel" in ansible_facts.packages and "rpm-ostree" in ansible_facts.packages
      and "bootc" in ansible_facts.packages and not "openshift-kubelet" in ansible_facts.packages
      and "ostree" in ansible_proc_cmdline ) and not ( ansible_virtualization_type
      in ["docker", "lxc", "openvz", "podman", "container"] ) )
    - '"/var" in ansible_mounts | map(attribute="mount") | list'
    - device_name.stdout is defined and device_name.stdout_lines is defined
    - (device_name.stdout | length > 0)
    tags:
    - DISA-STIG-OL09-00-002060
    - NIST-800-53-AC-6
    - NIST-800-53-AC-6(1)
    - NIST-800-53-CM-6(a)
    - NIST-800-53-CM-7(a)
    - NIST-800-53-CM-7(b)
    - NIST-800-53-MP-7
    - configure_strategy
    - high_disruption
    - low_complexity
    - medium_severity
    - mount_option_var_nodev
    - no_reboot_needed

  - name: 'Add nodev Option to /var: If /var not mounted, craft mount_info manually'
    set_fact:
      mount_info: '{{ mount_info|default({})|combine({item.0: item.1}) }}'
    with_together:
    - - target
      - source
      - fstype
      - options
    - - /var
      - ''
      - ''
      - defaults
    when:
    - ( not ( "kernel" in ansible_facts.packages and "rpm-ostree" in ansible_facts.packages
      and "bootc" in ansible_facts.packages and not "openshift-kubelet" in ansible_facts.packages
      and "ostree" in ansible_proc_cmdline ) and not ( ansible_virtualization_type
      in ["docker", "lxc", "openvz", "podman", "container"] ) )
    - '"/var" in ansible_mounts | map(attribute="mount") | list'
    - ("--fstab" | length == 0)
    - device_name.stdout is defined and device_name.stdout_lines is defined
    - (device_name.stdout | length == 0)
    tags:
    - DISA-STIG-OL09-00-002060
    - NIST-800-53-AC-6
    - NIST-800-53-AC-6(1)
    - NIST-800-53-CM-6(a)
    - NIST-800-53-CM-7(a)
    - NIST-800-53-CM-7(b)
    - NIST-800-53-MP-7
    - configure_strategy
    - high_disruption
    - low_complexity
    - medium_severity
    - mount_option_var_nodev
    - no_reboot_needed

  - name: 'Add nodev Option to /var: Make sure nodev option is part of the to /var
      options'
    set_fact:
      mount_info: '{{ mount_info | combine( {''options'':''''~(mount_info.options
        | default(''''))~('','' if (mount_info.options | default('''')) else '''')~''nodev''
        }) }}'
    when:
    - ( not ( "kernel" in ansible_facts.packages and "rpm-ostree" in ansible_facts.packages
      and "bootc" in ansible_facts.packages and not "openshift-kubelet" in ansible_facts.packages
      and "ostree" in ansible_proc_cmdline ) and not ( ansible_virtualization_type
      in ["docker", "lxc", "openvz", "podman", "container"] ) )
    - '"/var" in ansible_mounts | map(attribute="mount") | list'
    - mount_info is defined and "nodev" not in (mount_info.options | default(''))
    tags:
    - DISA-STIG-OL09-00-002060
    - NIST-800-53-AC-6
    - NIST-800-53-AC-6(1)
    - NIST-800-53-CM-6(a)
    - NIST-800-53-CM-7(a)
    - NIST-800-53-CM-7(b)
    - NIST-800-53-MP-7
    - configure_strategy
    - high_disruption
    - low_complexity
    - medium_severity
    - mount_option_var_nodev
    - no_reboot_needed

  - name: 'Add nodev Option to /var: Ensure /var is mounted with nodev option'
    ansible.posix.mount:
      path: /var
      src: '{{ mount_info.source | default('''') }}'
      opts: '{{ mount_info.options | default('''') }}'
      state: mounted
      fstype: '{{ mount_info.fstype | default('''') }}'
    register: mount_result
    failed_when:
    - mount_result is failed
    - '''target is busy'' not in (mount_result.msg | default(''''))'
    - '''already mounted'' not in (mount_result.msg | default(''''))'
    when:
    - ( not ( "kernel" in ansible_facts.packages and "rpm-ostree" in ansible_facts.packages
      and "bootc" in ansible_facts.packages and not "openshift-kubelet" in ansible_facts.packages
      and "ostree" in ansible_proc_cmdline ) and not ( ansible_virtualization_type
      in ["docker", "lxc", "openvz", "podman", "container"] ) )
    - '"/var" in ansible_mounts | map(attribute="mount") | list'
    - mount_info is defined
    - (device_name.stdout is defined and (device_name.stdout | length > 0)) or ("--fstab"
      | length == 0)
    tags:
    - DISA-STIG-OL09-00-002060
    - NIST-800-53-AC-6
    - NIST-800-53-AC-6(1)
    - NIST-800-53-CM-6(a)
    - NIST-800-53-CM-7(a)
    - NIST-800-53-CM-7(b)
    - NIST-800-53-MP-7
    - configure_strategy
    - high_disruption
    - low_complexity
    - medium_severity
    - mount_option_var_nodev
    - no_reboot_needed

  - name: 'Add nodev Option to /var/tmp: Check information associated to mountpoint'
    ansible.builtin.command: findmnt --fstab '/var/tmp'
    register: device_name
    failed_when: device_name.rc > 1
    changed_when: false
    check_mode: false
    when:
    - ( not ( "kernel" in ansible_facts.packages and "rpm-ostree" in ansible_facts.packages
      and "bootc" in ansible_facts.packages and not "openshift-kubelet" in ansible_facts.packages
      and "ostree" in ansible_proc_cmdline ) and not ( ansible_virtualization_type
      in ["docker", "lxc", "openvz", "podman", "container"] ) )
    - '"/var/tmp" in ansible_mounts | map(attribute="mount") | list'
    tags:
    - DISA-STIG-OL09-00-002067
    - configure_strategy
    - high_disruption
    - low_complexity
    - medium_severity
    - mount_option_var_tmp_nodev
    - no_reboot_needed

  - name: 'Add nodev Option to /var/tmp: Create mount_info dictionary variable'
    set_fact:
      mount_info: '{{ mount_info|default({})|combine({item.0: item.1}) }}'
    with_together:
    - '{{ device_name.stdout_lines[0].split() | map(''lower'') | list }}'
    - '{{ device_name.stdout_lines[1].split() | list }}'
    when:
    - ( not ( "kernel" in ansible_facts.packages and "rpm-ostree" in ansible_facts.packages
      and "bootc" in ansible_facts.packages and not "openshift-kubelet" in ansible_facts.packages
      and "ostree" in ansible_proc_cmdline ) and not ( ansible_virtualization_type
      in ["docker", "lxc", "openvz", "podman", "container"] ) )
    - '"/var/tmp" in ansible_mounts | map(attribute="mount") | list'
    - device_name.stdout is defined and device_name.stdout_lines is defined
    - (device_name.stdout | length > 0)
    tags:
    - DISA-STIG-OL09-00-002067
    - configure_strategy
    - high_disruption
    - low_complexity
    - medium_severity
    - mount_option_var_tmp_nodev
    - no_reboot_needed

  - name: 'Add nodev Option to /var/tmp: If /var/tmp not mounted, craft mount_info
      manually'
    set_fact:
      mount_info: '{{ mount_info|default({})|combine({item.0: item.1}) }}'
    with_together:
    - - target
      - source
      - fstype
      - options
    - - /var/tmp
      - ''
      - ''
      - defaults
    when:
    - ( not ( "kernel" in ansible_facts.packages and "rpm-ostree" in ansible_facts.packages
      and "bootc" in ansible_facts.packages and not "openshift-kubelet" in ansible_facts.packages
      and "ostree" in ansible_proc_cmdline ) and not ( ansible_virtualization_type
      in ["docker", "lxc", "openvz", "podman", "container"] ) )
    - '"/var/tmp" in ansible_mounts | map(attribute="mount") | list'
    - ("--fstab" | length == 0)
    - device_name.stdout is defined and device_name.stdout_lines is defined
    - (device_name.stdout | length == 0)
    tags:
    - DISA-STIG-OL09-00-002067
    - configure_strategy
    - high_disruption
    - low_complexity
    - medium_severity
    - mount_option_var_tmp_nodev
    - no_reboot_needed

  - name: 'Add nodev Option to /var/tmp: Make sure nodev option is part of the to
      /var/tmp options'
    set_fact:
      mount_info: '{{ mount_info | combine( {''options'':''''~(mount_info.options
        | default(''''))~('','' if (mount_info.options | default('''')) else '''')~''nodev''
        }) }}'
    when:
    - ( not ( "kernel" in ansible_facts.packages and "rpm-ostree" in ansible_facts.packages
      and "bootc" in ansible_facts.packages and not "openshift-kubelet" in ansible_facts.packages
      and "ostree" in ansible_proc_cmdline ) and not ( ansible_virtualization_type
      in ["docker", "lxc", "openvz", "podman", "container"] ) )
    - '"/var/tmp" in ansible_mounts | map(attribute="mount") | list'
    - mount_info is defined and "nodev" not in (mount_info.options | default(''))
    tags:
    - DISA-STIG-OL09-00-002067
    - configure_strategy
    - high_disruption
    - low_complexity
    - medium_severity
    - mount_option_var_tmp_nodev
    - no_reboot_needed

  - name: 'Add nodev Option to /var/tmp: Ensure /var/tmp is mounted with nodev option'
    ansible.posix.mount:
      path: /var/tmp
      src: '{{ mount_info.source | default('''') }}'
      opts: '{{ mount_info.options | default('''') }}'
      state: mounted
      fstype: '{{ mount_info.fstype | default('''') }}'
    register: mount_result
    failed_when:
    - mount_result is failed
    - '''target is busy'' not in (mount_result.msg | default(''''))'
    - '''already mounted'' not in (mount_result.msg | default(''''))'
    when:
    - ( not ( "kernel" in ansible_facts.packages and "rpm-ostree" in ansible_facts.packages
      and "bootc" in ansible_facts.packages and not "openshift-kubelet" in ansible_facts.packages
      and "ostree" in ansible_proc_cmdline ) and not ( ansible_virtualization_type
      in ["docker", "lxc", "openvz", "podman", "container"] ) )
    - '"/var/tmp" in ansible_mounts | map(attribute="mount") | list'
    - mount_info is defined
    - (device_name.stdout is defined and (device_name.stdout | length > 0)) or ("--fstab"
      | length == 0)
    tags:
    - DISA-STIG-OL09-00-002067
    - configure_strategy
    - high_disruption
    - low_complexity
    - medium_severity
    - mount_option_var_tmp_nodev
    - no_reboot_needed

  - name: 'Add noexec Option to /var/tmp: Check information associated to mountpoint'
    ansible.builtin.command: findmnt --fstab '/var/tmp'
    register: device_name
    failed_when: device_name.rc > 1
    changed_when: false
    check_mode: false
    when:
    - ( not ( "kernel" in ansible_facts.packages and "rpm-ostree" in ansible_facts.packages
      and "bootc" in ansible_facts.packages and not "openshift-kubelet" in ansible_facts.packages
      and "ostree" in ansible_proc_cmdline ) and not ( ansible_virtualization_type
      in ["docker", "lxc", "openvz", "podman", "container"] ) )
    - '"/var/tmp" in ansible_mounts | map(attribute="mount") | list'
    tags:
    - DISA-STIG-OL09-00-002068
    - configure_strategy
    - high_disruption
    - low_complexity
    - medium_severity
    - mount_option_var_tmp_noexec
    - no_reboot_needed

  - name: 'Add noexec Option to /var/tmp: Create mount_info dictionary variable'
    set_fact:
      mount_info: '{{ mount_info|default({})|combine({item.0: item.1}) }}'
    with_together:
    - '{{ device_name.stdout_lines[0].split() | map(''lower'') | list }}'
    - '{{ device_name.stdout_lines[1].split() | list }}'
    when:
    - ( not ( "kernel" in ansible_facts.packages and "rpm-ostree" in ansible_facts.packages
      and "bootc" in ansible_facts.packages and not "openshift-kubelet" in ansible_facts.packages
      and "ostree" in ansible_proc_cmdline ) and not ( ansible_virtualization_type
      in ["docker", "lxc", "openvz", "podman", "container"] ) )
    - '"/var/tmp" in ansible_mounts | map(attribute="mount") | list'
    - device_name.stdout is defined and device_name.stdout_lines is defined
    - (device_name.stdout | length > 0)
    tags:
    - DISA-STIG-OL09-00-002068
    - configure_strategy
    - high_disruption
    - low_complexity
    - medium_severity
    - mount_option_var_tmp_noexec
    - no_reboot_needed

  - name: 'Add noexec Option to /var/tmp: If /var/tmp not mounted, craft mount_info
      manually'
    set_fact:
      mount_info: '{{ mount_info|default({})|combine({item.0: item.1}) }}'
    with_together:
    - - target
      - source
      - fstype
      - options
    - - /var/tmp
      - ''
      - ''
      - defaults
    when:
    - ( not ( "kernel" in ansible_facts.packages and "rpm-ostree" in ansible_facts.packages
      and "bootc" in ansible_facts.packages and not "openshift-kubelet" in ansible_facts.packages
      and "ostree" in ansible_proc_cmdline ) and not ( ansible_virtualization_type
      in ["docker", "lxc", "openvz", "podman", "container"] ) )
    - '"/var/tmp" in ansible_mounts | map(attribute="mount") | list'
    - ("--fstab" | length == 0)
    - device_name.stdout is defined and device_name.stdout_lines is defined
    - (device_name.stdout | length == 0)
    tags:
    - DISA-STIG-OL09-00-002068
    - configure_strategy
    - high_disruption
    - low_complexity
    - medium_severity
    - mount_option_var_tmp_noexec
    - no_reboot_needed

  - name: 'Add noexec Option to /var/tmp: Make sure noexec option is part of the to
      /var/tmp options'
    set_fact:
      mount_info: '{{ mount_info | combine( {''options'':''''~(mount_info.options
        | default(''''))~('','' if (mount_info.options | default('''')) else '''')~''noexec''
        }) }}'
    when:
    - ( not ( "kernel" in ansible_facts.packages and "rpm-ostree" in ansible_facts.packages
      and "bootc" in ansible_facts.packages and not "openshift-kubelet" in ansible_facts.packages
      and "ostree" in ansible_proc_cmdline ) and not ( ansible_virtualization_type
      in ["docker", "lxc", "openvz", "podman", "container"] ) )
    - '"/var/tmp" in ansible_mounts | map(attribute="mount") | list'
    - mount_info is defined and "noexec" not in (mount_info.options | default(''))
    tags:
    - DISA-STIG-OL09-00-002068
    - configure_strategy
    - high_disruption
    - low_complexity
    - medium_severity
    - mount_option_var_tmp_noexec
    - no_reboot_needed

  - name: 'Add noexec Option to /var/tmp: Ensure /var/tmp is mounted with noexec option'
    ansible.posix.mount:
      path: /var/tmp
      src: '{{ mount_info.source | default('''') }}'
      opts: '{{ mount_info.options | default('''') }}'
      state: mounted
      fstype: '{{ mount_info.fstype | default('''') }}'
    register: mount_result
    failed_when:
    - mount_result is failed
    - '''target is busy'' not in (mount_result.msg | default(''''))'
    - '''already mounted'' not in (mount_result.msg | default(''''))'
    when:
    - ( not ( "kernel" in ansible_facts.packages and "rpm-ostree" in ansible_facts.packages
      and "bootc" in ansible_facts.packages and not "openshift-kubelet" in ansible_facts.packages
      and "ostree" in ansible_proc_cmdline ) and not ( ansible_virtualization_type
      in ["docker", "lxc", "openvz", "podman", "container"] ) )
    - '"/var/tmp" in ansible_mounts | map(attribute="mount") | list'
    - mount_info is defined
    - (device_name.stdout is defined and (device_name.stdout | length > 0)) or ("--fstab"
      | length == 0)
    tags:
    - DISA-STIG-OL09-00-002068
    - configure_strategy
    - high_disruption
    - low_complexity
    - medium_severity
    - mount_option_var_tmp_noexec
    - no_reboot_needed

  - name: 'Add nosuid Option to /var/tmp: Check information associated to mountpoint'
    ansible.builtin.command: findmnt --fstab '/var/tmp'
    register: device_name
    failed_when: device_name.rc > 1
    changed_when: false
    check_mode: false
    when:
    - ( not ( "kernel" in ansible_facts.packages and "rpm-ostree" in ansible_facts.packages
      and "bootc" in ansible_facts.packages and not "openshift-kubelet" in ansible_facts.packages
      and "ostree" in ansible_proc_cmdline ) and not ( ansible_virtualization_type
      in ["docker", "lxc", "openvz", "podman", "container"] ) )
    - '"/var/tmp" in ansible_mounts | map(attribute="mount") | list'
    tags:
    - DISA-STIG-OL09-00-002069
    - configure_strategy
    - high_disruption
    - low_complexity
    - medium_severity
    - mount_option_var_tmp_nosuid
    - no_reboot_needed

  - name: 'Add nosuid Option to /var/tmp: Create mount_info dictionary variable'
    set_fact:
      mount_info: '{{ mount_info|default({})|combine({item.0: item.1}) }}'
    with_together:
    - '{{ device_name.stdout_lines[0].split() | map(''lower'') | list }}'
    - '{{ device_name.stdout_lines[1].split() | list }}'
    when:
    - ( not ( "kernel" in ansible_facts.packages and "rpm-ostree" in ansible_facts.packages
      and "bootc" in ansible_facts.packages and not "openshift-kubelet" in ansible_facts.packages
      and "ostree" in ansible_proc_cmdline ) and not ( ansible_virtualization_type
      in ["docker", "lxc", "openvz", "podman", "container"] ) )
    - '"/var/tmp" in ansible_mounts | map(attribute="mount") | list'
    - device_name.stdout is defined and device_name.stdout_lines is defined
    - (device_name.stdout | length > 0)
    tags:
    - DISA-STIG-OL09-00-002069
    - configure_strategy
    - high_disruption
    - low_complexity
    - medium_severity
    - mount_option_var_tmp_nosuid
    - no_reboot_needed

  - name: 'Add nosuid Option to /var/tmp: If /var/tmp not mounted, craft mount_info
      manually'
    set_fact:
      mount_info: '{{ mount_info|default({})|combine({item.0: item.1}) }}'
    with_together:
    - - target
      - source
      - fstype
      - options
    - - /var/tmp
      - ''
      - ''
      - defaults
    when:
    - ( not ( "kernel" in ansible_facts.packages and "rpm-ostree" in ansible_facts.packages
      and "bootc" in ansible_facts.packages and not "openshift-kubelet" in ansible_facts.packages
      and "ostree" in ansible_proc_cmdline ) and not ( ansible_virtualization_type
      in ["docker", "lxc", "openvz", "podman", "container"] ) )
    - '"/var/tmp" in ansible_mounts | map(attribute="mount") | list'
    - ("--fstab" | length == 0)
    - device_name.stdout is defined and device_name.stdout_lines is defined
    - (device_name.stdout | length == 0)
    tags:
    - DISA-STIG-OL09-00-002069
    - configure_strategy
    - high_disruption
    - low_complexity
    - medium_severity
    - mount_option_var_tmp_nosuid
    - no_reboot_needed

  - name: 'Add nosuid Option to /var/tmp: Make sure nosuid option is part of the to
      /var/tmp options'
    set_fact:
      mount_info: '{{ mount_info | combine( {''options'':''''~(mount_info.options
        | default(''''))~('','' if (mount_info.options | default('''')) else '''')~''nosuid''
        }) }}'
    when:
    - ( not ( "kernel" in ansible_facts.packages and "rpm-ostree" in ansible_facts.packages
      and "bootc" in ansible_facts.packages and not "openshift-kubelet" in ansible_facts.packages
      and "ostree" in ansible_proc_cmdline ) and not ( ansible_virtualization_type
      in ["docker", "lxc", "openvz", "podman", "container"] ) )
    - '"/var/tmp" in ansible_mounts | map(attribute="mount") | list'
    - mount_info is defined and "nosuid" not in (mount_info.options | default(''))
    tags:
    - DISA-STIG-OL09-00-002069
    - configure_strategy
    - high_disruption
    - low_complexity
    - medium_severity
    - mount_option_var_tmp_nosuid
    - no_reboot_needed

  - name: 'Add nosuid Option to /var/tmp: Ensure /var/tmp is mounted with nosuid option'
    ansible.posix.mount:
      path: /var/tmp
      src: '{{ mount_info.source | default('''') }}'
      opts: '{{ mount_info.options | default('''') }}'
      state: mounted
      fstype: '{{ mount_info.fstype | default('''') }}'
    register: mount_result
    failed_when:
    - mount_result is failed
    - '''target is busy'' not in (mount_result.msg | default(''''))'
    - '''already mounted'' not in (mount_result.msg | default(''''))'
    when:
    - ( not ( "kernel" in ansible_facts.packages and "rpm-ostree" in ansible_facts.packages
      and "bootc" in ansible_facts.packages and not "openshift-kubelet" in ansible_facts.packages
      and "ostree" in ansible_proc_cmdline ) and not ( ansible_virtualization_type
      in ["docker", "lxc", "openvz", "podman", "container"] ) )
    - '"/var/tmp" in ansible_mounts | map(attribute="mount") | list'
    - mount_info is defined
    - (device_name.stdout is defined and (device_name.stdout | length > 0)) or ("--fstab"
      | length == 0)
    tags:
    - DISA-STIG-OL09-00-002069
    - configure_strategy
    - high_disruption
    - low_complexity
    - medium_severity
    - mount_option_var_tmp_nosuid
    - no_reboot_needed

  - name: Disable storing core dumps - Set fact for sysctl paths
    ansible.builtin.set_fact:
      sysctl_paths:
      - /etc/sysctl.d/
      - /run/sysctl.d/
      - /usr/local/lib/sysctl.d/
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-002380
    - NIST-800-53-SC-7(10)
    - PCI-DSSv4-3.3
    - PCI-DSSv4-3.3.1
    - PCI-DSSv4-3.3.1.1
    - disable_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - reboot_required
    - sysctl_kernel_core_pattern

  - name: Disable storing core dumps - Find all files that contain kernel.core_pattern
    ansible.builtin.shell:
      cmd: find -L {{ sysctl_paths | join(" ") }} -type f -name '*.conf' | xargs grep
        -HP '^\s*kernel.core_pattern\s*=\s*.*$'
    register: find_all_values
    check_mode: false
    changed_when: false
    failed_when: false
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-002380
    - NIST-800-53-SC-7(10)
    - PCI-DSSv4-3.3
    - PCI-DSSv4-3.3.1
    - PCI-DSSv4-3.3.1.1
    - disable_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - reboot_required
    - sysctl_kernel_core_pattern

  - name: Disable storing core dumps - Find all files that set kernel.core_pattern
      to correct value
    ansible.builtin.shell:
      cmd: find -L {{ sysctl_paths | join(" ") }} -type f -name '*.conf' | xargs grep
        -HP '^\s*kernel.core_pattern\s*=\s*\|/bin/false$'
    register: find_correct_value
    check_mode: false
    changed_when: false
    failed_when: false
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-002380
    - NIST-800-53-SC-7(10)
    - PCI-DSSv4-3.3
    - PCI-DSSv4-3.3.1
    - PCI-DSSv4-3.3.1.1
    - disable_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - reboot_required
    - sysctl_kernel_core_pattern

  - name: Disable storing core dumps - Comment out any occurrences of kernel.core_pattern
      from config files
    ansible.builtin.replace:
      path: '{{ item | split(":") | first }}'
      regexp: ^[\s]*kernel.core_pattern
      replace: '#kernel.core_pattern'
    loop: '{{ find_all_values.stdout_lines }}'
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - find_correct_value.stdout_lines | length == 0 or find_all_values.stdout_lines
      | length > find_correct_value.stdout_lines | length
    tags:
    - DISA-STIG-OL09-00-002380
    - NIST-800-53-SC-7(10)
    - PCI-DSSv4-3.3
    - PCI-DSSv4-3.3.1
    - PCI-DSSv4-3.3.1.1
    - disable_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - reboot_required
    - sysctl_kernel_core_pattern

  - name: Disable storing core dumps - Comment out any occurrences of kernel.core_pattern
      from /etc/sysctl.conf
    ansible.builtin.replace:
      path: '{{ item }}'
      regexp: ^[\s]*kernel.core_pattern
      replace: '#kernel.core_pattern'
    with_fileglob:
    - /etc/sysctl.conf
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-002380
    - NIST-800-53-SC-7(10)
    - PCI-DSSv4-3.3
    - PCI-DSSv4-3.3.1
    - PCI-DSSv4-3.3.1.1
    - disable_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - reboot_required
    - sysctl_kernel_core_pattern

  - name: Disable storing core dumps - Ensure sysctl kernel.core_pattern is set to
      |/bin/false
    ansible.posix.sysctl:
      name: kernel.core_pattern
      value: '|/bin/false'
      sysctl_file: /etc/sysctl.d/kernel_core_pattern.conf
      state: present
      reload: true
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-002380
    - NIST-800-53-SC-7(10)
    - PCI-DSSv4-3.3
    - PCI-DSSv4-3.3.1
    - PCI-DSSv4-3.3.1.1
    - disable_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - reboot_required
    - sysctl_kernel_core_pattern

  - name: Restrict Access to Kernel Message Buffer - Set fact for sysctl paths
    ansible.builtin.set_fact:
      sysctl_paths:
      - /etc/sysctl.d/
      - /run/sysctl.d/
      - /usr/local/lib/sysctl.d/
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-002406
    - NIST-800-171-3.1.5
    - NIST-800-53-SI-11(a)
    - NIST-800-53-SI-11(b)
    - disable_strategy
    - low_complexity
    - low_severity
    - medium_disruption
    - reboot_required
    - sysctl_kernel_dmesg_restrict

  - name: Restrict Access to Kernel Message Buffer - Find all files that contain kernel.dmesg_restrict
    ansible.builtin.shell:
      cmd: find -L {{ sysctl_paths | join(" ") }} -type f -name '*.conf' | xargs grep
        -HP '^\s*kernel.dmesg_restrict\s*=\s*.*$'
    register: find_all_values
    check_mode: false
    changed_when: false
    failed_when: false
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-002406
    - NIST-800-171-3.1.5
    - NIST-800-53-SI-11(a)
    - NIST-800-53-SI-11(b)
    - disable_strategy
    - low_complexity
    - low_severity
    - medium_disruption
    - reboot_required
    - sysctl_kernel_dmesg_restrict

  - name: Restrict Access to Kernel Message Buffer - Find all files that set kernel.dmesg_restrict
      to correct value
    ansible.builtin.shell:
      cmd: find -L {{ sysctl_paths | join(" ") }} -type f -name '*.conf' | xargs grep
        -HP '^\s*kernel.dmesg_restrict\s*=\s*1$'
    register: find_correct_value
    check_mode: false
    changed_when: false
    failed_when: false
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-002406
    - NIST-800-171-3.1.5
    - NIST-800-53-SI-11(a)
    - NIST-800-53-SI-11(b)
    - disable_strategy
    - low_complexity
    - low_severity
    - medium_disruption
    - reboot_required
    - sysctl_kernel_dmesg_restrict

  - name: Restrict Access to Kernel Message Buffer - Comment out any occurrences of
      kernel.dmesg_restrict from config files
    ansible.builtin.replace:
      path: '{{ item | split(":") | first }}'
      regexp: ^[\s]*kernel.dmesg_restrict
      replace: '#kernel.dmesg_restrict'
    loop: '{{ find_all_values.stdout_lines }}'
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - find_correct_value.stdout_lines | length == 0 or find_all_values.stdout_lines
      | length > find_correct_value.stdout_lines | length
    tags:
    - DISA-STIG-OL09-00-002406
    - NIST-800-171-3.1.5
    - NIST-800-53-SI-11(a)
    - NIST-800-53-SI-11(b)
    - disable_strategy
    - low_complexity
    - low_severity
    - medium_disruption
    - reboot_required
    - sysctl_kernel_dmesg_restrict

  - name: Restrict Access to Kernel Message Buffer - Comment out any occurrences of
      kernel.dmesg_restrict from /etc/sysctl.conf
    ansible.builtin.replace:
      path: '{{ item }}'
      regexp: ^[\s]*kernel.dmesg_restrict
      replace: '#kernel.dmesg_restrict'
    with_fileglob:
    - /etc/sysctl.conf
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-002406
    - NIST-800-171-3.1.5
    - NIST-800-53-SI-11(a)
    - NIST-800-53-SI-11(b)
    - disable_strategy
    - low_complexity
    - low_severity
    - medium_disruption
    - reboot_required
    - sysctl_kernel_dmesg_restrict

  - name: Restrict Access to Kernel Message Buffer - Ensure sysctl kernel.dmesg_restrict
      is set to 1
    ansible.posix.sysctl:
      name: kernel.dmesg_restrict
      value: '1'
      sysctl_file: /etc/sysctl.d/kernel_dmesg_restrict.conf
      state: present
      reload: true
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-002406
    - NIST-800-171-3.1.5
    - NIST-800-53-SI-11(a)
    - NIST-800-53-SI-11(b)
    - disable_strategy
    - low_complexity
    - low_severity
    - medium_disruption
    - reboot_required
    - sysctl_kernel_dmesg_restrict

  - name: Disable Kernel Image Loading - Set fact for sysctl paths
    ansible.builtin.set_fact:
      sysctl_paths:
      - /etc/sysctl.d/
      - /run/sysctl.d/
      - /usr/local/lib/sysctl.d/
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-002428
    - NIST-800-53-CM-6
    - disable_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - reboot_required
    - sysctl_kernel_kexec_load_disabled

  - name: Disable Kernel Image Loading - Find all files that contain kernel.kexec_load_disabled
    ansible.builtin.shell:
      cmd: find -L {{ sysctl_paths | join(" ") }} -type f -name '*.conf' | xargs grep
        -HP '^\s*kernel.kexec_load_disabled\s*=\s*.*$'
    register: find_all_values
    check_mode: false
    changed_when: false
    failed_when: false
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-002428
    - NIST-800-53-CM-6
    - disable_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - reboot_required
    - sysctl_kernel_kexec_load_disabled

  - name: Disable Kernel Image Loading - Find all files that set kernel.kexec_load_disabled
      to correct value
    ansible.builtin.shell:
      cmd: find -L {{ sysctl_paths | join(" ") }} -type f -name '*.conf' | xargs grep
        -HP '^\s*kernel.kexec_load_disabled\s*=\s*1$'
    register: find_correct_value
    check_mode: false
    changed_when: false
    failed_when: false
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-002428
    - NIST-800-53-CM-6
    - disable_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - reboot_required
    - sysctl_kernel_kexec_load_disabled

  - name: Disable Kernel Image Loading - Comment out any occurrences of kernel.kexec_load_disabled
      from config files
    ansible.builtin.replace:
      path: '{{ item | split(":") | first }}'
      regexp: ^[\s]*kernel.kexec_load_disabled
      replace: '#kernel.kexec_load_disabled'
    loop: '{{ find_all_values.stdout_lines }}'
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - find_correct_value.stdout_lines | length == 0 or find_all_values.stdout_lines
      | length > find_correct_value.stdout_lines | length
    tags:
    - DISA-STIG-OL09-00-002428
    - NIST-800-53-CM-6
    - disable_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - reboot_required
    - sysctl_kernel_kexec_load_disabled

  - name: Disable Kernel Image Loading - Comment out any occurrences of kernel.kexec_load_disabled
      from /etc/sysctl.conf
    ansible.builtin.replace:
      path: '{{ item }}'
      regexp: ^[\s]*kernel.kexec_load_disabled
      replace: '#kernel.kexec_load_disabled'
    with_fileglob:
    - /etc/sysctl.conf
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-002428
    - NIST-800-53-CM-6
    - disable_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - reboot_required
    - sysctl_kernel_kexec_load_disabled

  - name: Disable Kernel Image Loading - Ensure sysctl kernel.kexec_load_disabled
      is set to 1
    ansible.posix.sysctl:
      name: kernel.kexec_load_disabled
      value: '1'
      sysctl_file: /etc/sysctl.d/kernel_kexec_load_disabled.conf
      state: present
      reload: true
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-002428
    - NIST-800-53-CM-6
    - disable_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - reboot_required
    - sysctl_kernel_kexec_load_disabled

  - name: Disallow kernel profiling by unprivileged users - Set fact for sysctl paths
    ansible.builtin.set_fact:
      sysctl_paths:
      - /etc/sysctl.d/
      - /run/sysctl.d/
      - /usr/local/lib/sysctl.d/
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-002407
    - NIST-800-53-AC-6
    - disable_strategy
    - low_complexity
    - low_severity
    - medium_disruption
    - reboot_required
    - sysctl_kernel_perf_event_paranoid

  - name: Disallow kernel profiling by unprivileged users - Find all files that contain
      kernel.perf_event_paranoid
    ansible.builtin.shell:
      cmd: find -L {{ sysctl_paths | join(" ") }} -type f -name '*.conf' | xargs grep
        -HP '^\s*kernel.perf_event_paranoid\s*=\s*.*$'
    register: find_all_values
    check_mode: false
    changed_when: false
    failed_when: false
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-002407
    - NIST-800-53-AC-6
    - disable_strategy
    - low_complexity
    - low_severity
    - medium_disruption
    - reboot_required
    - sysctl_kernel_perf_event_paranoid

  - name: Disallow kernel profiling by unprivileged users - Find all files that set
      kernel.perf_event_paranoid to correct value
    ansible.builtin.shell:
      cmd: find -L {{ sysctl_paths | join(" ") }} -type f -name '*.conf' | xargs grep
        -HP '^\s*kernel.perf_event_paranoid\s*=\s*2$'
    register: find_correct_value
    check_mode: false
    changed_when: false
    failed_when: false
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-002407
    - NIST-800-53-AC-6
    - disable_strategy
    - low_complexity
    - low_severity
    - medium_disruption
    - reboot_required
    - sysctl_kernel_perf_event_paranoid

  - name: Disallow kernel profiling by unprivileged users - Comment out any occurrences
      of kernel.perf_event_paranoid from config files
    ansible.builtin.replace:
      path: '{{ item | split(":") | first }}'
      regexp: ^[\s]*kernel.perf_event_paranoid
      replace: '#kernel.perf_event_paranoid'
    loop: '{{ find_all_values.stdout_lines }}'
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - find_correct_value.stdout_lines | length == 0 or find_all_values.stdout_lines
      | length > find_correct_value.stdout_lines | length
    tags:
    - DISA-STIG-OL09-00-002407
    - NIST-800-53-AC-6
    - disable_strategy
    - low_complexity
    - low_severity
    - medium_disruption
    - reboot_required
    - sysctl_kernel_perf_event_paranoid

  - name: Disallow kernel profiling by unprivileged users - Comment out any occurrences
      of kernel.perf_event_paranoid from /etc/sysctl.conf
    ansible.builtin.replace:
      path: '{{ item }}'
      regexp: ^[\s]*kernel.perf_event_paranoid
      replace: '#kernel.perf_event_paranoid'
    with_fileglob:
    - /etc/sysctl.conf
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-002407
    - NIST-800-53-AC-6
    - disable_strategy
    - low_complexity
    - low_severity
    - medium_disruption
    - reboot_required
    - sysctl_kernel_perf_event_paranoid

  - name: Disallow kernel profiling by unprivileged users - Ensure sysctl kernel.perf_event_paranoid
      is set to 2
    ansible.posix.sysctl:
      name: kernel.perf_event_paranoid
      value: '2'
      sysctl_file: /etc/sysctl.d/kernel_perf_event_paranoid.conf
      state: present
      reload: true
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-002407
    - NIST-800-53-AC-6
    - disable_strategy
    - low_complexity
    - low_severity
    - medium_disruption
    - reboot_required
    - sysctl_kernel_perf_event_paranoid

  - name: Disable Access to Network bpf() Syscall From Unprivileged Processes - Set
      fact for sysctl paths
    ansible.builtin.set_fact:
      sysctl_paths:
      - /etc/sysctl.d/
      - /run/sysctl.d/
      - /usr/local/lib/sysctl.d/
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-002409
    - NIST-800-53-AC-6
    - NIST-800-53-SC-7(10)
    - disable_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - reboot_required
    - sysctl_kernel_unprivileged_bpf_disabled

  - name: Disable Access to Network bpf() Syscall From Unprivileged Processes - Find
      all files that contain kernel.unprivileged_bpf_disabled
    ansible.builtin.shell:
      cmd: find -L {{ sysctl_paths | join(" ") }} -type f -name '*.conf' | xargs grep
        -HP '^\s*kernel.unprivileged_bpf_disabled\s*=\s*.*$'
    register: find_all_values
    check_mode: false
    changed_when: false
    failed_when: false
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-002409
    - NIST-800-53-AC-6
    - NIST-800-53-SC-7(10)
    - disable_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - reboot_required
    - sysctl_kernel_unprivileged_bpf_disabled

  - name: Disable Access to Network bpf() Syscall From Unprivileged Processes - Find
      all files that set kernel.unprivileged_bpf_disabled to correct value
    ansible.builtin.shell:
      cmd: find -L {{ sysctl_paths | join(" ") }} -type f -name '*.conf' | xargs grep
        -HP '^\s*kernel.unprivileged_bpf_disabled\s*=\s*1$'
    register: find_correct_value
    check_mode: false
    changed_when: false
    failed_when: false
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-002409
    - NIST-800-53-AC-6
    - NIST-800-53-SC-7(10)
    - disable_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - reboot_required
    - sysctl_kernel_unprivileged_bpf_disabled

  - name: Disable Access to Network bpf() Syscall From Unprivileged Processes - Comment
      out any occurrences of kernel.unprivileged_bpf_disabled from config files
    ansible.builtin.replace:
      path: '{{ item | split(":") | first }}'
      regexp: ^[\s]*kernel.unprivileged_bpf_disabled
      replace: '#kernel.unprivileged_bpf_disabled'
    loop: '{{ find_all_values.stdout_lines }}'
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - find_correct_value.stdout_lines | length == 0 or find_all_values.stdout_lines
      | length > find_correct_value.stdout_lines | length
    tags:
    - DISA-STIG-OL09-00-002409
    - NIST-800-53-AC-6
    - NIST-800-53-SC-7(10)
    - disable_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - reboot_required
    - sysctl_kernel_unprivileged_bpf_disabled

  - name: Disable Access to Network bpf() Syscall From Unprivileged Processes - Comment
      out any occurrences of kernel.unprivileged_bpf_disabled from /etc/sysctl.conf
    ansible.builtin.replace:
      path: '{{ item }}'
      regexp: ^[\s]*kernel.unprivileged_bpf_disabled
      replace: '#kernel.unprivileged_bpf_disabled'
    with_fileglob:
    - /etc/sysctl.conf
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-002409
    - NIST-800-53-AC-6
    - NIST-800-53-SC-7(10)
    - disable_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - reboot_required
    - sysctl_kernel_unprivileged_bpf_disabled

  - name: Disable Access to Network bpf() Syscall From Unprivileged Processes - Ensure
      sysctl kernel.unprivileged_bpf_disabled is set to 1
    ansible.posix.sysctl:
      name: kernel.unprivileged_bpf_disabled
      value: '1'
      sysctl_file: /etc/sysctl.d/kernel_unprivileged_bpf_disabled.conf
      state: present
      reload: true
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-002409
    - NIST-800-53-AC-6
    - NIST-800-53-SC-7(10)
    - disable_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - reboot_required
    - sysctl_kernel_unprivileged_bpf_disabled

  - name: Restrict usage of ptrace to descendant processes - Set fact for sysctl paths
    ansible.builtin.set_fact:
      sysctl_paths:
      - /etc/sysctl.d/
      - /run/sysctl.d/
      - /usr/local/lib/sysctl.d/
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-002410
    - NIST-800-53-SC-7(10)
    - disable_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - reboot_required
    - sysctl_kernel_yama_ptrace_scope

  - name: Restrict usage of ptrace to descendant processes - Find all files that contain
      kernel.yama.ptrace_scope
    ansible.builtin.shell:
      cmd: find -L {{ sysctl_paths | join(" ") }} -type f -name '*.conf' | xargs grep
        -HP '^\s*kernel.yama.ptrace_scope\s*=\s*.*$'
    register: find_all_values
    check_mode: false
    changed_when: false
    failed_when: false
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-002410
    - NIST-800-53-SC-7(10)
    - disable_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - reboot_required
    - sysctl_kernel_yama_ptrace_scope

  - name: Restrict usage of ptrace to descendant processes - Find all files that set
      kernel.yama.ptrace_scope to correct value
    ansible.builtin.shell:
      cmd: find -L {{ sysctl_paths | join(" ") }} -type f -name '*.conf' | xargs grep
        -HP '^\s*kernel.yama.ptrace_scope\s*=\s*1$'
    register: find_correct_value
    check_mode: false
    changed_when: false
    failed_when: false
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-002410
    - NIST-800-53-SC-7(10)
    - disable_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - reboot_required
    - sysctl_kernel_yama_ptrace_scope

  - name: Restrict usage of ptrace to descendant processes - Comment out any occurrences
      of kernel.yama.ptrace_scope from config files
    ansible.builtin.replace:
      path: '{{ item | split(":") | first }}'
      regexp: ^[\s]*kernel.yama.ptrace_scope
      replace: '#kernel.yama.ptrace_scope'
    loop: '{{ find_all_values.stdout_lines }}'
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - find_correct_value.stdout_lines | length == 0 or find_all_values.stdout_lines
      | length > find_correct_value.stdout_lines | length
    tags:
    - DISA-STIG-OL09-00-002410
    - NIST-800-53-SC-7(10)
    - disable_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - reboot_required
    - sysctl_kernel_yama_ptrace_scope

  - name: Restrict usage of ptrace to descendant processes - Comment out any occurrences
      of kernel.yama.ptrace_scope from /etc/sysctl.conf
    ansible.builtin.replace:
      path: '{{ item }}'
      regexp: ^[\s]*kernel.yama.ptrace_scope
      replace: '#kernel.yama.ptrace_scope'
    with_fileglob:
    - /etc/sysctl.conf
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-002410
    - NIST-800-53-SC-7(10)
    - disable_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - reboot_required
    - sysctl_kernel_yama_ptrace_scope

  - name: Restrict usage of ptrace to descendant processes - Ensure sysctl kernel.yama.ptrace_scope
      is set to 1
    ansible.posix.sysctl:
      name: kernel.yama.ptrace_scope
      value: '1'
      sysctl_file: /etc/sysctl.d/kernel_yama_ptrace_scope.conf
      state: present
      reload: true
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-002410
    - NIST-800-53-SC-7(10)
    - disable_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - reboot_required
    - sysctl_kernel_yama_ptrace_scope

  - name: Harden the operation of the BPF just-in-time compiler - Set fact for sysctl
      paths
    ansible.builtin.set_fact:
      sysctl_paths:
      - /etc/sysctl.d/
      - /run/sysctl.d/
      - /usr/local/lib/sysctl.d/
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-002430
    - NIST-800-53-CM-6
    - NIST-800-53-SC-7(10)
    - disable_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - reboot_required
    - sysctl_net_core_bpf_jit_harden

  - name: Harden the operation of the BPF just-in-time compiler - Find all files that
      contain net.core.bpf_jit_harden
    ansible.builtin.shell:
      cmd: find -L {{ sysctl_paths | join(" ") }} -type f -name '*.conf' | xargs grep
        -HP '^\s*net.core.bpf_jit_harden\s*=\s*.*$'
    register: find_all_values
    check_mode: false
    changed_when: false
    failed_when: false
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-002430
    - NIST-800-53-CM-6
    - NIST-800-53-SC-7(10)
    - disable_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - reboot_required
    - sysctl_net_core_bpf_jit_harden

  - name: Harden the operation of the BPF just-in-time compiler - Find all files that
      set net.core.bpf_jit_harden to correct value
    ansible.builtin.shell:
      cmd: find -L {{ sysctl_paths | join(" ") }} -type f -name '*.conf' | xargs grep
        -HP '^\s*net.core.bpf_jit_harden\s*=\s*2$'
    register: find_correct_value
    check_mode: false
    changed_when: false
    failed_when: false
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-002430
    - NIST-800-53-CM-6
    - NIST-800-53-SC-7(10)
    - disable_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - reboot_required
    - sysctl_net_core_bpf_jit_harden

  - name: Harden the operation of the BPF just-in-time compiler - Comment out any
      occurrences of net.core.bpf_jit_harden from config files
    ansible.builtin.replace:
      path: '{{ item | split(":") | first }}'
      regexp: ^[\s]*net.core.bpf_jit_harden
      replace: '#net.core.bpf_jit_harden'
    loop: '{{ find_all_values.stdout_lines }}'
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - find_correct_value.stdout_lines | length == 0 or find_all_values.stdout_lines
      | length > find_correct_value.stdout_lines | length
    tags:
    - DISA-STIG-OL09-00-002430
    - NIST-800-53-CM-6
    - NIST-800-53-SC-7(10)
    - disable_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - reboot_required
    - sysctl_net_core_bpf_jit_harden

  - name: Harden the operation of the BPF just-in-time compiler - Comment out any
      occurrences of net.core.bpf_jit_harden from /etc/sysctl.conf
    ansible.builtin.replace:
      path: '{{ item }}'
      regexp: ^[\s]*net.core.bpf_jit_harden
      replace: '#net.core.bpf_jit_harden'
    with_fileglob:
    - /etc/sysctl.conf
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-002430
    - NIST-800-53-CM-6
    - NIST-800-53-SC-7(10)
    - disable_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - reboot_required
    - sysctl_net_core_bpf_jit_harden

  - name: Harden the operation of the BPF just-in-time compiler - Ensure sysctl net.core.bpf_jit_harden
      is set to 2
    ansible.posix.sysctl:
      name: net.core.bpf_jit_harden
      value: '2'
      sysctl_file: /etc/sysctl.d/net_core_bpf_jit_harden.conf
      state: present
      reload: true
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-002430
    - NIST-800-53-CM-6
    - NIST-800-53-SC-7(10)
    - disable_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - reboot_required
    - sysctl_net_core_bpf_jit_harden

  - name: Disable acquiring, saving, and processing core dumps - Collect systemd Socket
      Units Present in the System
    ansible.builtin.command:
      cmd: systemctl -q list-unit-files --type socket
    register: result_systemd_unit_files
    changed_when: false
    check_mode: false
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-002384
    - NIST-800-53-SC-7(10)
    - disable_strategy
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - service_systemd-coredump_disabled

  - name: Disable acquiring, saving, and processing core dumps - Ensure systemd-coredump.socket
      is Masked
    ansible.builtin.systemd:
      name: systemd-coredump.socket
      state: stopped
      enabled: false
      masked: true
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - result_systemd_unit_files.stdout_lines is search("systemd-coredump.socket")
    tags:
    - DISA-STIG-OL09-00-002384
    - NIST-800-53-SC-7(10)
    - disable_strategy
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - service_systemd-coredump_disabled

  - name: Disable core dump backtraces - Search for a section in files
    ansible.builtin.find:
      paths: '{{item.path}}'
      patterns: '{{item.pattern}}'
      contains: ^\s*\[Coredump\]
      read_whole_file: true
      use_regex: true
    register: systemd_dropin_files_with_section
    loop:
    - path: '{{ ''/etc/systemd/coredump.conf'' | dirname }}'
      pattern: '{{ ''/etc/systemd/coredump.conf'' | basename | regex_escape }}'
    - path: /etc/systemd/coredump.conf.d
      pattern: .*\.conf
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - '"systemd" in ansible_facts.packages'
    tags:
    - DISA-STIG-OL09-00-002381
    - NIST-800-53-CM-6
    - PCI-DSS-Req-3.2
    - PCI-DSSv4-3.3
    - PCI-DSSv4-3.3.1
    - PCI-DSSv4-3.3.1.1
    - coredump_disable_backtraces
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Disable core dump backtraces - Count number of files which contain the correct
      section
    ansible.builtin.set_fact:
      count_of_systemd_dropin_files_with_section: '{{systemd_dropin_files_with_section.results
        | map(attribute=''matched'') | list | map(''int'') | sum}}'
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - '"systemd" in ansible_facts.packages'
    tags:
    - DISA-STIG-OL09-00-002381
    - NIST-800-53-CM-6
    - PCI-DSS-Req-3.2
    - PCI-DSSv4-3.3
    - PCI-DSSv4-3.3.1
    - PCI-DSSv4-3.3.1.1
    - coredump_disable_backtraces
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Disable core dump backtraces - Add missing configuration to correct section
    community.general.ini_file:
      path: '{{item}}'
      section: Coredump
      option: ProcessSizeMax
      value: '0'
      state: present
      no_extra_spaces: true
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - '"systemd" in ansible_facts.packages'
    - count_of_systemd_dropin_files_with_section | int > 0
    loop: '{{systemd_dropin_files_with_section.results | sum(attribute=''files'',
      start=[]) | map(attribute=''path'') | list }}'
    tags:
    - DISA-STIG-OL09-00-002381
    - NIST-800-53-CM-6
    - PCI-DSS-Req-3.2
    - PCI-DSSv4-3.3
    - PCI-DSSv4-3.3.1
    - PCI-DSSv4-3.3.1.1
    - coredump_disable_backtraces
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Disable core dump backtraces - Add configuration to new remediation file
    community.general.ini_file:
      path: /etc/systemd/coredump.conf.d/complianceascode_hardening.conf
      section: Coredump
      option: ProcessSizeMax
      value: '0'
      state: present
      no_extra_spaces: true
      create: true
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - '"systemd" in ansible_facts.packages'
    - count_of_systemd_dropin_files_with_section | int == 0
    tags:
    - DISA-STIG-OL09-00-002381
    - NIST-800-53-CM-6
    - PCI-DSS-Req-3.2
    - PCI-DSSv4-3.3
    - PCI-DSSv4-3.3.1
    - PCI-DSSv4-3.3.1.1
    - coredump_disable_backtraces
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Disable storing core dump - Search for a section in files
    ansible.builtin.find:
      paths: '{{item.path}}'
      patterns: '{{item.pattern}}'
      contains: ^\s*\[Coredump\]
      read_whole_file: true
      use_regex: true
    register: systemd_dropin_files_with_section
    loop:
    - path: '{{ ''/etc/systemd/coredump.conf'' | dirname }}'
      pattern: '{{ ''/etc/systemd/coredump.conf'' | basename | regex_escape }}'
    - path: /etc/systemd/coredump.conf.d
      pattern: .*\.conf
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - '"systemd" in ansible_facts.packages'
    tags:
    - DISA-STIG-OL09-00-002382
    - NIST-800-53-CM-6
    - PCI-DSS-Req-3.2
    - PCI-DSSv4-3.3
    - PCI-DSSv4-3.3.1
    - PCI-DSSv4-3.3.1.1
    - coredump_disable_storage
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Disable storing core dump - Count number of files which contain the correct
      section
    ansible.builtin.set_fact:
      count_of_systemd_dropin_files_with_section: '{{systemd_dropin_files_with_section.results
        | map(attribute=''matched'') | list | map(''int'') | sum}}'
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - '"systemd" in ansible_facts.packages'
    tags:
    - DISA-STIG-OL09-00-002382
    - NIST-800-53-CM-6
    - PCI-DSS-Req-3.2
    - PCI-DSSv4-3.3
    - PCI-DSSv4-3.3.1
    - PCI-DSSv4-3.3.1.1
    - coredump_disable_storage
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Disable storing core dump - Add missing configuration to correct section
    community.general.ini_file:
      path: '{{item}}'
      section: Coredump
      option: Storage
      value: none
      state: present
      no_extra_spaces: true
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - '"systemd" in ansible_facts.packages'
    - count_of_systemd_dropin_files_with_section | int > 0
    loop: '{{systemd_dropin_files_with_section.results | sum(attribute=''files'',
      start=[]) | map(attribute=''path'') | list }}'
    tags:
    - DISA-STIG-OL09-00-002382
    - NIST-800-53-CM-6
    - PCI-DSS-Req-3.2
    - PCI-DSSv4-3.3
    - PCI-DSSv4-3.3.1
    - PCI-DSSv4-3.3.1.1
    - coredump_disable_storage
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Disable storing core dump - Add configuration to new remediation file
    community.general.ini_file:
      path: /etc/systemd/coredump.conf.d/complianceascode_hardening.conf
      section: Coredump
      option: Storage
      value: none
      state: present
      no_extra_spaces: true
      create: true
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - '"systemd" in ansible_facts.packages'
    - count_of_systemd_dropin_files_with_section | int == 0
    tags:
    - DISA-STIG-OL09-00-002382
    - NIST-800-53-CM-6
    - PCI-DSS-Req-3.2
    - PCI-DSSv4-3.3
    - PCI-DSSv4-3.3.1
    - PCI-DSSv4-3.3.1.1
    - coredump_disable_storage
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Disable Core Dumps for All Users - Set dirs, files and regex variables
    ansible.builtin.set_fact:
      limits_dropin_dir: /etc/security/limits.d
      limits_dropin_file: /etc/security/limits.d/10-ssg-hardening.conf
      limits_main_file: /etc/security/limits.conf
      limits_correct_regex: ^\s*\*\s+hard\s+core\s+0\s*$
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - '"pam" in ansible_facts.packages'
    tags:
    - DISA-STIG-OL09-00-002383
    - NIST-800-53-CM-6
    - NIST-800-53-SC-7(10)
    - PCI-DSSv4-3.3
    - PCI-DSSv4-3.3.1
    - PCI-DSSv4-3.3.1.1
    - disable_users_coredumps
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Disable Core Dumps for All Users - Find valid drop-ins for core limit
    ansible.builtin.find:
      paths: '{{ limits_dropin_dir }}'
      patterns: '*.conf'
      contains: '{{ limits_correct_regex }}'
      file_type: file
    register: valid_dropins
    failed_when: false
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - '"pam" in ansible_facts.packages'
    tags:
    - DISA-STIG-OL09-00-002383
    - NIST-800-53-CM-6
    - NIST-800-53-SC-7(10)
    - PCI-DSSv4-3.3
    - PCI-DSSv4-3.3.1
    - PCI-DSSv4-3.3.1.1
    - disable_users_coredumps
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Disable Core Dumps for All Users - Find all drop-ins with any core limit
    ansible.builtin.find:
      paths: '{{ limits_dropin_dir }}'
      patterns: '*.conf'
      contains: ^\s*\*\s+hard\s+core\s+
      file_type: file
    register: all_dropins
    failed_when: false
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - '"pam" in ansible_facts.packages'
    tags:
    - DISA-STIG-OL09-00-002383
    - NIST-800-53-CM-6
    - NIST-800-53-SC-7(10)
    - PCI-DSSv4-3.3
    - PCI-DSSv4-3.3.1
    - PCI-DSSv4-3.3.1.1
    - disable_users_coredumps
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Disable Core Dumps for All Users - Get invalid drop-ins
    ansible.builtin.set_fact:
      invalid_dropins: '{{ all_dropins.files | rejectattr(''path'', ''in'', valid_dropins.files
        | map(attribute=''path'') | list) | map(attribute=''path'') | list }}'
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - '"pam" in ansible_facts.packages'
    tags:
    - DISA-STIG-OL09-00-002383
    - NIST-800-53-CM-6
    - NIST-800-53-SC-7(10)
    - PCI-DSSv4-3.3
    - PCI-DSSv4-3.3.1
    - PCI-DSSv4-3.3.1.1
    - disable_users_coredumps
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Disable Core Dumps for All Users - Comment invalid * hard core lines in
      drop-ins
    ansible.builtin.replace:
      path: '{{ item }}'
      regexp: (^\s*\*\s+hard\s+core\s+.*$)
      replace: '#\1'
    loop: '{{ invalid_dropins }}'
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - '"pam" in ansible_facts.packages'
    - invalid_dropins | length > 0
    tags:
    - DISA-STIG-OL09-00-002383
    - NIST-800-53-CM-6
    - NIST-800-53-SC-7(10)
    - PCI-DSSv4-3.3
    - PCI-DSSv4-3.3.1
    - PCI-DSSv4-3.3.1.1
    - disable_users_coredumps
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Disable Core Dumps for All Users - Check if main limits.conf contains correct
      core limit
    ansible.builtin.find:
      paths: /etc/security
      patterns: limits.conf
      contains: '{{ limits_correct_regex }}'
      file_type: file
    register: main_valid
    failed_when: false
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - '"pam" in ansible_facts.packages'
    - not (valid_dropins.matched | default(0) > 0)
    tags:
    - DISA-STIG-OL09-00-002383
    - NIST-800-53-CM-6
    - NIST-800-53-SC-7(10)
    - PCI-DSSv4-3.3
    - PCI-DSSv4-3.3.1
    - PCI-DSSv4-3.3.1.1
    - disable_users_coredumps
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Disable Core Dumps for All Users - Set fact if configuration is valid
    ansible.builtin.set_fact:
      core_limit_valid: '{{ (valid_dropins.matched | default(0)) > 0 or (main_valid.matched
        | default(0)) > 0 }}'
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - '"pam" in ansible_facts.packages'
    tags:
    - DISA-STIG-OL09-00-002383
    - NIST-800-53-CM-6
    - NIST-800-53-SC-7(10)
    - PCI-DSSv4-3.3
    - PCI-DSSv4-3.3.1
    - PCI-DSSv4-3.3.1.1
    - disable_users_coredumps
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Disable Core Dumps for All Users - Ensure drop-in directory exists
    ansible.builtin.file:
      path: '{{ limits_dropin_dir }}'
      state: directory
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - '"pam" in ansible_facts.packages'
    - not core_limit_valid
    tags:
    - DISA-STIG-OL09-00-002383
    - NIST-800-53-CM-6
    - NIST-800-53-SC-7(10)
    - PCI-DSSv4-3.3
    - PCI-DSSv4-3.3.1
    - PCI-DSSv4-3.3.1.1
    - disable_users_coredumps
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Disable Core Dumps for All Users - Deploy 10-ssg-hardening.conf drop-in
      with correct core limit
    ansible.builtin.copy:
      dest: '{{ limits_dropin_file }}'
      content: |
        *     hard   core    0
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - '"pam" in ansible_facts.packages'
    - not core_limit_valid
    tags:
    - DISA-STIG-OL09-00-002383
    - NIST-800-53-CM-6
    - NIST-800-53-SC-7(10)
    - PCI-DSSv4-3.3
    - PCI-DSSv4-3.3.1
    - PCI-DSSv4-3.3.1.1
    - disable_users_coredumps
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Check if noexec argument is already present in /etc/default/grub
    ansible.builtin.slurp:
      src: /etc/default/grub
    register: etc_default_grub
    when: ( ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
      and ansible_architecture == "x86_64" )
    tags:
    - DISA-STIG-OL09-00-002422
    - NIST-800-171-3.1.7
    - NIST-800-53-CM-6(a)
    - NIST-800-53-SC-39
    - low_complexity
    - low_disruption
    - medium_severity
    - reboot_required
    - restrict_strategy
    - sysctl_kernel_exec_shield

  - name: Check if noexec argument is present
    ansible.builtin.command: /sbin/grubby --info=ALL
    register: grubby_info
    check_mode: false
    changed_when: false
    failed_when: false
    when: ( ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
      and ansible_architecture == "x86_64" )
    tags:
    - DISA-STIG-OL09-00-002422
    - NIST-800-171-3.1.7
    - NIST-800-53-CM-6(a)
    - NIST-800-53-SC-39
    - low_complexity
    - low_disruption
    - medium_severity
    - reboot_required
    - restrict_strategy
    - sysctl_kernel_exec_shield

  - name: Update grub defaults and the bootloader menu
    ansible.builtin.command: /sbin/grubby --update-kernel=ALL --remove-args="noexec"
    when:
    - ( ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
      and ansible_architecture == "x86_64" )
    - (grubby_info.stdout is search('noexec')) or ((etc_default_grub['content'] |
      b64decode) is search('noexec'))
    tags:
    - DISA-STIG-OL09-00-002422
    - NIST-800-171-3.1.7
    - NIST-800-53-CM-6(a)
    - NIST-800-53-SC-39
    - low_complexity
    - low_disruption
    - medium_severity
    - reboot_required
    - restrict_strategy
    - sysctl_kernel_exec_shield

  - name: Restrict Exposed Kernel Pointer Addresses Access - Set fact for sysctl paths
    ansible.builtin.set_fact:
      sysctl_paths:
      - /etc/sysctl.d/
      - /run/sysctl.d/
      - /usr/local/lib/sysctl.d/
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-002408
    - NIST-800-53-CM-6(a)
    - NIST-800-53-SC-30
    - NIST-800-53-SC-30(2)
    - NIST-800-53-SC-30(5)
    - disable_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - reboot_required
    - sysctl_kernel_kptr_restrict

  - name: Restrict Exposed Kernel Pointer Addresses Access - Find all files that contain
      kernel.kptr_restrict
    ansible.builtin.shell:
      cmd: find -L {{ sysctl_paths | join(" ") }} -type f -name '*.conf' | xargs grep
        -HP '^\s*kernel.kptr_restrict\s*=\s*.*$'
    register: find_all_values
    check_mode: false
    changed_when: false
    failed_when: false
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-002408
    - NIST-800-53-CM-6(a)
    - NIST-800-53-SC-30
    - NIST-800-53-SC-30(2)
    - NIST-800-53-SC-30(5)
    - disable_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - reboot_required
    - sysctl_kernel_kptr_restrict

  - name: Restrict Exposed Kernel Pointer Addresses Access - Find all files that set
      kernel.kptr_restrict to correct value
    ansible.builtin.shell:
      cmd: find -L {{ sysctl_paths | join(" ") }} -type f -name '*.conf' | xargs grep
        -HP '^\s*kernel.kptr_restrict\s*=\s*{{ sysctl_kernel_kptr_restrict_value }}$'
    register: find_correct_value
    check_mode: false
    changed_when: false
    failed_when: false
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-002408
    - NIST-800-53-CM-6(a)
    - NIST-800-53-SC-30
    - NIST-800-53-SC-30(2)
    - NIST-800-53-SC-30(5)
    - disable_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - reboot_required
    - sysctl_kernel_kptr_restrict

  - name: Restrict Exposed Kernel Pointer Addresses Access - Comment out any occurrences
      of kernel.kptr_restrict from config files
    ansible.builtin.replace:
      path: '{{ item | split(":") | first }}'
      regexp: ^[\s]*kernel.kptr_restrict
      replace: '#kernel.kptr_restrict'
    loop: '{{ find_all_values.stdout_lines }}'
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - find_correct_value.stdout_lines | length == 0 or find_all_values.stdout_lines
      | length > find_correct_value.stdout_lines | length
    tags:
    - DISA-STIG-OL09-00-002408
    - NIST-800-53-CM-6(a)
    - NIST-800-53-SC-30
    - NIST-800-53-SC-30(2)
    - NIST-800-53-SC-30(5)
    - disable_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - reboot_required
    - sysctl_kernel_kptr_restrict

  - name: Restrict Exposed Kernel Pointer Addresses Access - Comment out any occurrences
      of kernel.kptr_restrict from /etc/sysctl.conf
    ansible.builtin.replace:
      path: '{{ item }}'
      regexp: ^[\s]*kernel.kptr_restrict
      replace: '#kernel.kptr_restrict'
    with_fileglob:
    - /etc/sysctl.conf
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-002408
    - NIST-800-53-CM-6(a)
    - NIST-800-53-SC-30
    - NIST-800-53-SC-30(2)
    - NIST-800-53-SC-30(5)
    - disable_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - reboot_required
    - sysctl_kernel_kptr_restrict

  - name: Restrict Exposed Kernel Pointer Addresses Access - Ensure sysctl kernel.kptr_restrict
      is set
    ansible.posix.sysctl:
      name: kernel.kptr_restrict
      value: '{{ sysctl_kernel_kptr_restrict_value }}'
      sysctl_file: /etc/sysctl.d/kernel_kptr_restrict.conf
      state: present
      reload: true
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-002408
    - NIST-800-53-CM-6(a)
    - NIST-800-53-SC-30
    - NIST-800-53-SC-30(2)
    - NIST-800-53-SC-30(5)
    - disable_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - reboot_required
    - sysctl_kernel_kptr_restrict

  - name: Enable Randomized Layout of Virtual Address Space - Set fact for sysctl
      paths
    ansible.builtin.set_fact:
      sysctl_paths:
      - /etc/sysctl.d/
      - /run/sysctl.d/
      - /usr/local/lib/sysctl.d/
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-002423
    - NIST-800-171-3.1.7
    - NIST-800-53-CM-6(a)
    - NIST-800-53-SC-30
    - NIST-800-53-SC-30(2)
    - PCI-DSS-Req-2.2.1
    - PCI-DSSv4-3.3
    - PCI-DSSv4-3.3.1
    - PCI-DSSv4-3.3.1.1
    - disable_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - reboot_required
    - sysctl_kernel_randomize_va_space

  - name: Enable Randomized Layout of Virtual Address Space - Find all files that
      contain kernel.randomize_va_space
    ansible.builtin.shell:
      cmd: find -L {{ sysctl_paths | join(" ") }} -type f -name '*.conf' | xargs grep
        -HP '^\s*kernel.randomize_va_space\s*=\s*.*$'
    register: find_all_values
    check_mode: false
    changed_when: false
    failed_when: false
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-002423
    - NIST-800-171-3.1.7
    - NIST-800-53-CM-6(a)
    - NIST-800-53-SC-30
    - NIST-800-53-SC-30(2)
    - PCI-DSS-Req-2.2.1
    - PCI-DSSv4-3.3
    - PCI-DSSv4-3.3.1
    - PCI-DSSv4-3.3.1.1
    - disable_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - reboot_required
    - sysctl_kernel_randomize_va_space

  - name: Enable Randomized Layout of Virtual Address Space - Find all files that
      set kernel.randomize_va_space to correct value
    ansible.builtin.shell:
      cmd: find -L {{ sysctl_paths | join(" ") }} -type f -name '*.conf' | xargs grep
        -HP '^\s*kernel.randomize_va_space\s*=\s*2$'
    register: find_correct_value
    check_mode: false
    changed_when: false
    failed_when: false
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-002423
    - NIST-800-171-3.1.7
    - NIST-800-53-CM-6(a)
    - NIST-800-53-SC-30
    - NIST-800-53-SC-30(2)
    - PCI-DSS-Req-2.2.1
    - PCI-DSSv4-3.3
    - PCI-DSSv4-3.3.1
    - PCI-DSSv4-3.3.1.1
    - disable_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - reboot_required
    - sysctl_kernel_randomize_va_space

  - name: Enable Randomized Layout of Virtual Address Space - Comment out any occurrences
      of kernel.randomize_va_space from config files
    ansible.builtin.replace:
      path: '{{ item | split(":") | first }}'
      regexp: ^[\s]*kernel.randomize_va_space
      replace: '#kernel.randomize_va_space'
    loop: '{{ find_all_values.stdout_lines }}'
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - find_correct_value.stdout_lines | length == 0 or find_all_values.stdout_lines
      | length > find_correct_value.stdout_lines | length
    tags:
    - DISA-STIG-OL09-00-002423
    - NIST-800-171-3.1.7
    - NIST-800-53-CM-6(a)
    - NIST-800-53-SC-30
    - NIST-800-53-SC-30(2)
    - PCI-DSS-Req-2.2.1
    - PCI-DSSv4-3.3
    - PCI-DSSv4-3.3.1
    - PCI-DSSv4-3.3.1.1
    - disable_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - reboot_required
    - sysctl_kernel_randomize_va_space

  - name: Enable Randomized Layout of Virtual Address Space - Comment out any occurrences
      of kernel.randomize_va_space from /etc/sysctl.conf
    ansible.builtin.replace:
      path: '{{ item }}'
      regexp: ^[\s]*kernel.randomize_va_space
      replace: '#kernel.randomize_va_space'
    with_fileglob:
    - /etc/sysctl.conf
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-002423
    - NIST-800-171-3.1.7
    - NIST-800-53-CM-6(a)
    - NIST-800-53-SC-30
    - NIST-800-53-SC-30(2)
    - PCI-DSS-Req-2.2.1
    - PCI-DSSv4-3.3
    - PCI-DSSv4-3.3.1
    - PCI-DSSv4-3.3.1.1
    - disable_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - reboot_required
    - sysctl_kernel_randomize_va_space

  - name: Enable Randomized Layout of Virtual Address Space - Ensure sysctl kernel.randomize_va_space
      is set to 2
    ansible.posix.sysctl:
      name: kernel.randomize_va_space
      value: '2'
      sysctl_file: /etc/sysctl.d/kernel_randomize_va_space.conf
      state: present
      reload: true
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-002423
    - NIST-800-171-3.1.7
    - NIST-800-53-CM-6(a)
    - NIST-800-53-SC-30
    - NIST-800-53-SC-30(2)
    - PCI-DSS-Req-2.2.1
    - PCI-DSSv4-3.3
    - PCI-DSSv4-3.3.1
    - PCI-DSSv4-3.3.1.1
    - disable_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - reboot_required
    - sysctl_kernel_randomize_va_space

  - name: Check if page_poison argument is already present in /etc/default/grub
    ansible.builtin.slurp:
      src: /etc/default/grub
    register: etc_default_grub
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - '"grub2-common" in ansible_facts.packages'
    tags:
    - DISA-STIG-OL09-00-002394
    - NIST-800-53-CM-6(a)
    - grub2_page_poison_argument
    - low_disruption
    - medium_complexity
    - medium_severity
    - reboot_required
    - restrict_strategy

  - name: Check if page_poison argument is already present
    ansible.builtin.command: /sbin/grubby --info=ALL
    register: grubby_info
    check_mode: false
    changed_when: false
    failed_when: false
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - '"grub2-common" in ansible_facts.packages'
    tags:
    - DISA-STIG-OL09-00-002394
    - NIST-800-53-CM-6(a)
    - grub2_page_poison_argument
    - low_disruption
    - medium_complexity
    - medium_severity
    - reboot_required
    - restrict_strategy

  - name: Update grub defaults and the bootloader menu
    ansible.builtin.command: /sbin/grubby --update-kernel=ALL --args="page_poison=1"
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - '"grub2-common" in ansible_facts.packages'
    - (grubby_info.stdout is not search('page_poison=1')) or ((etc_default_grub['content']
      | b64decode) is not search('page_poison=1'))
    tags:
    - DISA-STIG-OL09-00-002394
    - NIST-800-53-CM-6(a)
    - grub2_page_poison_argument
    - low_disruption
    - medium_complexity
    - medium_severity
    - reboot_required
    - restrict_strategy

  - name: Check if slub_debug argument is already present in /etc/default/grub
    ansible.builtin.slurp:
      src: /etc/default/grub
    register: etc_default_grub
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - '"grub2-common" in ansible_facts.packages'
    tags:
    - DISA-STIG-OL09-00-002390
    - NIST-800-53-CM-6(a)
    - grub2_slub_debug_argument
    - low_disruption
    - medium_complexity
    - medium_severity
    - reboot_required
    - restrict_strategy

  - name: Check if slub_debug argument is already present
    ansible.builtin.command: /sbin/grubby --info=ALL
    register: grubby_info
    check_mode: false
    changed_when: false
    failed_when: false
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - '"grub2-common" in ansible_facts.packages'
    tags:
    - DISA-STIG-OL09-00-002390
    - NIST-800-53-CM-6(a)
    - grub2_slub_debug_argument
    - low_disruption
    - medium_complexity
    - medium_severity
    - reboot_required
    - restrict_strategy

  - name: Update grub defaults and the bootloader menu
    ansible.builtin.command: /sbin/grubby --update-kernel=ALL --args="slub_debug={{
      var_slub_debug_options }}"
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - '"grub2-common" in ansible_facts.packages'
    - (grubby_info.stdout is not search('slub_debug=' ~ var_slub_debug_options)) or
      ((etc_default_grub['content'] | b64decode) is not search('slub_debug=' ~ var_slub_debug_options))
    tags:
    - DISA-STIG-OL09-00-002390
    - NIST-800-53-CM-6(a)
    - grub2_slub_debug_argument
    - low_disruption
    - medium_complexity
    - medium_severity
    - reboot_required
    - restrict_strategy

  - name: Configure SELinux Policy
    block:

    - name: Check for duplicate values
      ansible.builtin.lineinfile:
        path: /etc/selinux/config
        create: true
        regexp: (?i)^SELINUXTYPE=
        state: absent
      check_mode: true
      changed_when: false
      register: dupes

    - name: Deduplicate values from /etc/selinux/config
      ansible.builtin.lineinfile:
        path: /etc/selinux/config
        create: true
        regexp: (?i)^SELINUXTYPE=
        state: absent
      when: dupes.found is defined and dupes.found > 1

    - name: Insert correct line to /etc/selinux/config
      ansible.builtin.lineinfile:
        path: /etc/selinux/config
        create: true
        regexp: (?i)^SELINUXTYPE=
        line: SELINUXTYPE={{ var_selinux_policy_name }}
        state: present
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-000065
    - NIST-800-171-3.1.2
    - NIST-800-171-3.7.2
    - NIST-800-53-AC-3
    - NIST-800-53-AC-3(3)(a)
    - NIST-800-53-AU-9
    - NIST-800-53-SC-7(21)
    - PCI-DSSv4-1.2
    - PCI-DSSv4-1.2.6
    - configure_strategy
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - selinux_policytype

  - name: Ensure SELinux State is Enforcing - Check current SELinux state
    ansible.builtin.command:
      cmd: getenforce
    register: current_selinux_state
    check_mode: false
    changed_when: false
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-000060
    - NIST-800-171-3.1.2
    - NIST-800-171-3.7.2
    - NIST-800-53-AC-3
    - NIST-800-53-AC-3(3)(a)
    - NIST-800-53-AU-9
    - NIST-800-53-SC-7(21)
    - PCI-DSSv4-1.2
    - PCI-DSSv4-1.2.6
    - high_severity
    - low_complexity
    - low_disruption
    - no_reboot_needed
    - restrict_strategy
    - selinux_state

  - name: Ensure SELinux State is Enforcing
    block:

    - name: Check for duplicate values
      ansible.builtin.lineinfile:
        path: /etc/selinux/config
        create: true
        regexp: (?i)^SELINUX=
        state: absent
      check_mode: true
      changed_when: false
      register: dupes

    - name: Deduplicate values from /etc/selinux/config
      ansible.builtin.lineinfile:
        path: /etc/selinux/config
        create: true
        regexp: (?i)^SELINUX=
        state: absent
      when: dupes.found is defined and dupes.found > 1

    - name: Insert correct line to /etc/selinux/config
      ansible.builtin.lineinfile:
        path: /etc/selinux/config
        create: true
        regexp: (?i)^SELINUX=
        line: SELINUX={{ var_selinux_state }}
        state: present
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-000060
    - NIST-800-171-3.1.2
    - NIST-800-171-3.7.2
    - NIST-800-53-AC-3
    - NIST-800-53-AC-3(3)(a)
    - NIST-800-53-AU-9
    - NIST-800-53-SC-7(21)
    - PCI-DSSv4-1.2
    - PCI-DSSv4-1.2.6
    - high_severity
    - low_complexity
    - low_disruption
    - no_reboot_needed
    - restrict_strategy
    - selinux_state

  - name: Ensure SELinux State is Enforcing - Mark system to relabel SELinux on next
      boot
    ansible.builtin.file:
      path: /.autorelabel
      state: touch
      access_time: preserve
      modification_time: preserve
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - current_selinux_state.stdout | lower != var_selinux_state
    tags:
    - DISA-STIG-OL09-00-000060
    - NIST-800-171-3.1.2
    - NIST-800-171-3.7.2
    - NIST-800-53-AC-3
    - NIST-800-53-AC-3(3)(a)
    - NIST-800-53-AU-9
    - NIST-800-53-SC-7(21)
    - PCI-DSSv4-1.2
    - PCI-DSSv4-1.2.6
    - high_severity
    - low_complexity
    - low_disruption
    - no_reboot_needed
    - restrict_strategy
    - selinux_state

  - name: Set the file_groupowner_cron_d_newgroup variable if represented by gid
    ansible.builtin.set_fact:
      file_groupowner_cron_d_newgroup: '0'
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-002581
    - NIST-800-53-AC-6(1)
    - NIST-800-53-CM-6(a)
    - PCI-DSSv4-2.2
    - PCI-DSSv4-2.2.6
    - configure_strategy
    - file_groupowner_cron_d
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

  - name: Ensure group owner on /etc/cron.d/
    ansible.builtin.file:
      path: /etc/cron.d/
      follow: false
      state: directory
      group: '{{ file_groupowner_cron_d_newgroup }}'
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-002581
    - NIST-800-53-AC-6(1)
    - NIST-800-53-CM-6(a)
    - PCI-DSSv4-2.2
    - PCI-DSSv4-2.2.6
    - configure_strategy
    - file_groupowner_cron_d
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

  - name: Set the file_groupowner_cron_daily_newgroup variable if represented by gid
    ansible.builtin.set_fact:
      file_groupowner_cron_daily_newgroup: '0'
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-002581
    - NIST-800-53-AC-6(1)
    - NIST-800-53-CM-6(a)
    - PCI-DSSv4-2.2
    - PCI-DSSv4-2.2.6
    - configure_strategy
    - file_groupowner_cron_daily
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

  - name: Ensure group owner on /etc/cron.daily/
    ansible.builtin.file:
      path: /etc/cron.daily/
      follow: false
      state: directory
      group: '{{ file_groupowner_cron_daily_newgroup }}'
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-002581
    - NIST-800-53-AC-6(1)
    - NIST-800-53-CM-6(a)
    - PCI-DSSv4-2.2
    - PCI-DSSv4-2.2.6
    - configure_strategy
    - file_groupowner_cron_daily
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

  - name: Set the file_groupowner_cron_deny_newgroup variable if represented by gid
    ansible.builtin.set_fact:
      file_groupowner_cron_deny_newgroup: '0'
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-002581
    - NIST-800-53-CM-6 b
    - configure_strategy
    - file_groupowner_cron_deny
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

  - name: Test for existence /etc/cron.deny
    ansible.builtin.stat:
      path: /etc/cron.deny
    register: file_exists
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-002581
    - NIST-800-53-CM-6 b
    - configure_strategy
    - file_groupowner_cron_deny
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

  - name: Ensure group owner on /etc/cron.deny
    ansible.builtin.file:
      path: /etc/cron.deny
      follow: false
      group: '{{ file_groupowner_cron_deny_newgroup }}'
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - file_exists.stat is defined and file_exists.stat.exists
    tags:
    - DISA-STIG-OL09-00-002581
    - NIST-800-53-CM-6 b
    - configure_strategy
    - file_groupowner_cron_deny
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

  - name: Set the file_groupowner_cron_hourly_newgroup variable if represented by
      gid
    ansible.builtin.set_fact:
      file_groupowner_cron_hourly_newgroup: '0'
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-002581
    - NIST-800-53-AC-6(1)
    - NIST-800-53-CM-6(a)
    - PCI-DSSv4-2.2
    - PCI-DSSv4-2.2.6
    - configure_strategy
    - file_groupowner_cron_hourly
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

  - name: Ensure group owner on /etc/cron.hourly/
    ansible.builtin.file:
      path: /etc/cron.hourly/
      follow: false
      state: directory
      group: '{{ file_groupowner_cron_hourly_newgroup }}'
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-002581
    - NIST-800-53-AC-6(1)
    - NIST-800-53-CM-6(a)
    - PCI-DSSv4-2.2
    - PCI-DSSv4-2.2.6
    - configure_strategy
    - file_groupowner_cron_hourly
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

  - name: Set the file_groupowner_cron_monthly_newgroup variable if represented by
      gid
    ansible.builtin.set_fact:
      file_groupowner_cron_monthly_newgroup: '0'
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-002581
    - NIST-800-53-AC-6(1)
    - NIST-800-53-CM-6(a)
    - PCI-DSSv4-2.2
    - PCI-DSSv4-2.2.6
    - configure_strategy
    - file_groupowner_cron_monthly
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

  - name: Ensure group owner on /etc/cron.monthly/
    ansible.builtin.file:
      path: /etc/cron.monthly/
      follow: false
      state: directory
      group: '{{ file_groupowner_cron_monthly_newgroup }}'
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-002581
    - NIST-800-53-AC-6(1)
    - NIST-800-53-CM-6(a)
    - PCI-DSSv4-2.2
    - PCI-DSSv4-2.2.6
    - configure_strategy
    - file_groupowner_cron_monthly
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

  - name: Set the file_groupowner_cron_weekly_newgroup variable if represented by
      gid
    ansible.builtin.set_fact:
      file_groupowner_cron_weekly_newgroup: '0'
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-002581
    - NIST-800-53-AC-6(1)
    - NIST-800-53-CM-6(a)
    - PCI-DSSv4-2.2
    - PCI-DSSv4-2.2.6
    - configure_strategy
    - file_groupowner_cron_weekly
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

  - name: Ensure group owner on /etc/cron.weekly/
    ansible.builtin.file:
      path: /etc/cron.weekly/
      follow: false
      state: directory
      group: '{{ file_groupowner_cron_weekly_newgroup }}'
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-002581
    - NIST-800-53-AC-6(1)
    - NIST-800-53-CM-6(a)
    - PCI-DSSv4-2.2
    - PCI-DSSv4-2.2.6
    - configure_strategy
    - file_groupowner_cron_weekly
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

  - name: Set the file_groupowner_crontab_newgroup variable if represented by gid
    ansible.builtin.set_fact:
      file_groupowner_crontab_newgroup: '0'
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-002581
    - NIST-800-53-AC-6(1)
    - NIST-800-53-CM-6(a)
    - PCI-DSSv4-2.2
    - PCI-DSSv4-2.2.6
    - configure_strategy
    - file_groupowner_crontab
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

  - name: Test for existence /etc/crontab
    ansible.builtin.stat:
      path: /etc/crontab
    register: file_exists
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-002581
    - NIST-800-53-AC-6(1)
    - NIST-800-53-CM-6(a)
    - PCI-DSSv4-2.2
    - PCI-DSSv4-2.2.6
    - configure_strategy
    - file_groupowner_crontab
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

  - name: Ensure group owner on /etc/crontab
    ansible.builtin.file:
      path: /etc/crontab
      follow: false
      group: '{{ file_groupowner_crontab_newgroup }}'
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - file_exists.stat is defined and file_exists.stat.exists
    tags:
    - DISA-STIG-OL09-00-002581
    - NIST-800-53-AC-6(1)
    - NIST-800-53-CM-6(a)
    - PCI-DSSv4-2.2
    - PCI-DSSv4-2.2.6
    - configure_strategy
    - file_groupowner_crontab
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

  - name: Set the file_owner_cron_d_newown variable if represented by uid
    ansible.builtin.set_fact:
      file_owner_cron_d_newown: '0'
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-002582
    - NIST-800-53-AC-6(1)
    - NIST-800-53-CM-6(a)
    - PCI-DSSv4-2.2
    - PCI-DSSv4-2.2.6
    - configure_strategy
    - file_owner_cron_d
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

  - name: Ensure owner on directory /etc/cron.d/
    ansible.builtin.file:
      path: /etc/cron.d/
      follow: false
      state: directory
      owner: '{{ file_owner_cron_d_newown }}'
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-002582
    - NIST-800-53-AC-6(1)
    - NIST-800-53-CM-6(a)
    - PCI-DSSv4-2.2
    - PCI-DSSv4-2.2.6
    - configure_strategy
    - file_owner_cron_d
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

  - name: Set the file_owner_cron_daily_newown variable if represented by uid
    ansible.builtin.set_fact:
      file_owner_cron_daily_newown: '0'
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-002582
    - NIST-800-53-AC-6(1)
    - NIST-800-53-CM-6(a)
    - PCI-DSSv4-2.2
    - PCI-DSSv4-2.2.6
    - configure_strategy
    - file_owner_cron_daily
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

  - name: Ensure owner on directory /etc/cron.daily/
    ansible.builtin.file:
      path: /etc/cron.daily/
      follow: false
      state: directory
      owner: '{{ file_owner_cron_daily_newown }}'
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-002582
    - NIST-800-53-AC-6(1)
    - NIST-800-53-CM-6(a)
    - PCI-DSSv4-2.2
    - PCI-DSSv4-2.2.6
    - configure_strategy
    - file_owner_cron_daily
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

  - name: Set the file_owner_cron_deny_newown variable if represented by uid
    ansible.builtin.set_fact:
      file_owner_cron_deny_newown: '0'
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-002582
    - NIST-800-53-CM-6 b
    - configure_strategy
    - file_owner_cron_deny
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

  - name: Test for existence /etc/cron.deny
    ansible.builtin.stat:
      path: /etc/cron.deny
    register: file_exists
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-002582
    - NIST-800-53-CM-6 b
    - configure_strategy
    - file_owner_cron_deny
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

  - name: Ensure owner on /etc/cron.deny
    ansible.builtin.file:
      path: /etc/cron.deny
      follow: false
      owner: '{{ file_owner_cron_deny_newown }}'
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - file_exists.stat is defined and file_exists.stat.exists
    tags:
    - DISA-STIG-OL09-00-002582
    - NIST-800-53-CM-6 b
    - configure_strategy
    - file_owner_cron_deny
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

  - name: Set the file_owner_cron_hourly_newown variable if represented by uid
    ansible.builtin.set_fact:
      file_owner_cron_hourly_newown: '0'
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-002582
    - NIST-800-53-AC-6(1)
    - NIST-800-53-CM-6(a)
    - PCI-DSSv4-2.2
    - PCI-DSSv4-2.2.6
    - configure_strategy
    - file_owner_cron_hourly
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

  - name: Ensure owner on directory /etc/cron.hourly/
    ansible.builtin.file:
      path: /etc/cron.hourly/
      follow: false
      state: directory
      owner: '{{ file_owner_cron_hourly_newown }}'
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-002582
    - NIST-800-53-AC-6(1)
    - NIST-800-53-CM-6(a)
    - PCI-DSSv4-2.2
    - PCI-DSSv4-2.2.6
    - configure_strategy
    - file_owner_cron_hourly
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

  - name: Set the file_owner_cron_monthly_newown variable if represented by uid
    ansible.builtin.set_fact:
      file_owner_cron_monthly_newown: '0'
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-002582
    - NIST-800-53-AC-6(1)
    - NIST-800-53-CM-6(a)
    - PCI-DSSv4-2.2
    - PCI-DSSv4-2.2.6
    - configure_strategy
    - file_owner_cron_monthly
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

  - name: Ensure owner on directory /etc/cron.monthly/
    ansible.builtin.file:
      path: /etc/cron.monthly/
      follow: false
      state: directory
      owner: '{{ file_owner_cron_monthly_newown }}'
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-002582
    - NIST-800-53-AC-6(1)
    - NIST-800-53-CM-6(a)
    - PCI-DSSv4-2.2
    - PCI-DSSv4-2.2.6
    - configure_strategy
    - file_owner_cron_monthly
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

  - name: Set the file_owner_cron_weekly_newown variable if represented by uid
    ansible.builtin.set_fact:
      file_owner_cron_weekly_newown: '0'
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-002582
    - NIST-800-53-AC-6(1)
    - NIST-800-53-CM-6(a)
    - PCI-DSSv4-2.2
    - PCI-DSSv4-2.2.6
    - configure_strategy
    - file_owner_cron_weekly
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

  - name: Ensure owner on directory /etc/cron.weekly/
    ansible.builtin.file:
      path: /etc/cron.weekly/
      follow: false
      state: directory
      owner: '{{ file_owner_cron_weekly_newown }}'
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-002582
    - NIST-800-53-AC-6(1)
    - NIST-800-53-CM-6(a)
    - PCI-DSSv4-2.2
    - PCI-DSSv4-2.2.6
    - configure_strategy
    - file_owner_cron_weekly
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

  - name: Set the file_owner_crontab_newown variable if represented by uid
    ansible.builtin.set_fact:
      file_owner_crontab_newown: '0'
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-002582
    - NIST-800-53-AC-6(1)
    - NIST-800-53-CM-6(a)
    - PCI-DSSv4-2.2
    - PCI-DSSv4-2.2.6
    - configure_strategy
    - file_owner_crontab
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

  - name: Test for existence /etc/crontab
    ansible.builtin.stat:
      path: /etc/crontab
    register: file_exists
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-002582
    - NIST-800-53-AC-6(1)
    - NIST-800-53-CM-6(a)
    - PCI-DSSv4-2.2
    - PCI-DSSv4-2.2.6
    - configure_strategy
    - file_owner_crontab
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

  - name: Ensure owner on /etc/crontab
    ansible.builtin.file:
      path: /etc/crontab
      follow: false
      owner: '{{ file_owner_crontab_newown }}'
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - file_exists.stat is defined and file_exists.stat.exists
    tags:
    - DISA-STIG-OL09-00-002582
    - NIST-800-53-AC-6(1)
    - NIST-800-53-CM-6(a)
    - PCI-DSSv4-2.2
    - PCI-DSSv4-2.2.6
    - configure_strategy
    - file_owner_crontab
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

  - name: Find /etc/cron.d/ file(s)
    ansible.builtin.command: 'find -P /etc/cron.d/ -maxdepth 0 -perm /u+s,g+xwrs,o+xwrt  -type
      d '
    register: files_found
    changed_when: false
    failed_when: false
    check_mode: false
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-002580
    - NIST-800-53-AC-6(1)
    - NIST-800-53-CM-6(a)
    - PCI-DSSv4-2.2
    - PCI-DSSv4-2.2.6
    - configure_strategy
    - file_permissions_cron_d
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

  - name: Set permissions for /etc/cron.d/ file(s)
    ansible.builtin.file:
      path: '{{ item }}'
      mode: u-s,g-xwrs,o-xwrt
      state: directory
    with_items:
    - '{{ files_found.stdout_lines }}'
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-002580
    - NIST-800-53-AC-6(1)
    - NIST-800-53-CM-6(a)
    - PCI-DSSv4-2.2
    - PCI-DSSv4-2.2.6
    - configure_strategy
    - file_permissions_cron_d
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

  - name: Find /etc/cron.daily/ file(s)
    ansible.builtin.command: 'find -P /etc/cron.daily/ -maxdepth 0 -perm /u+s,g+xwrs,o+xwrt  -type
      d '
    register: files_found
    changed_when: false
    failed_when: false
    check_mode: false
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-002580
    - NIST-800-53-AC-6(1)
    - NIST-800-53-CM-6(a)
    - PCI-DSSv4-2.2
    - PCI-DSSv4-2.2.6
    - configure_strategy
    - file_permissions_cron_daily
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

  - name: Set permissions for /etc/cron.daily/ file(s)
    ansible.builtin.file:
      path: '{{ item }}'
      mode: u-s,g-xwrs,o-xwrt
      state: directory
    with_items:
    - '{{ files_found.stdout_lines }}'
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-002580
    - NIST-800-53-AC-6(1)
    - NIST-800-53-CM-6(a)
    - PCI-DSSv4-2.2
    - PCI-DSSv4-2.2.6
    - configure_strategy
    - file_permissions_cron_daily
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

  - name: Find /etc/cron.hourly/ file(s)
    ansible.builtin.command: 'find -P /etc/cron.hourly/ -maxdepth 0 -perm /u+s,g+xwrs,o+xwrt  -type
      d '
    register: files_found
    changed_when: false
    failed_when: false
    check_mode: false
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-002580
    - NIST-800-53-AC-6(1)
    - NIST-800-53-CM-6(a)
    - PCI-DSSv4-2.2
    - PCI-DSSv4-2.2.6
    - configure_strategy
    - file_permissions_cron_hourly
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

  - name: Set permissions for /etc/cron.hourly/ file(s)
    ansible.builtin.file:
      path: '{{ item }}'
      mode: u-s,g-xwrs,o-xwrt
      state: directory
    with_items:
    - '{{ files_found.stdout_lines }}'
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-002580
    - NIST-800-53-AC-6(1)
    - NIST-800-53-CM-6(a)
    - PCI-DSSv4-2.2
    - PCI-DSSv4-2.2.6
    - configure_strategy
    - file_permissions_cron_hourly
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

  - name: Find /etc/cron.monthly/ file(s)
    ansible.builtin.command: 'find -P /etc/cron.monthly/ -maxdepth 0 -perm /u+s,g+xwrs,o+xwrt  -type
      d '
    register: files_found
    changed_when: false
    failed_when: false
    check_mode: false
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-002580
    - NIST-800-53-AC-6(1)
    - NIST-800-53-CM-6(a)
    - PCI-DSSv4-2.2
    - PCI-DSSv4-2.2.6
    - configure_strategy
    - file_permissions_cron_monthly
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

  - name: Set permissions for /etc/cron.monthly/ file(s)
    ansible.builtin.file:
      path: '{{ item }}'
      mode: u-s,g-xwrs,o-xwrt
      state: directory
    with_items:
    - '{{ files_found.stdout_lines }}'
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-002580
    - NIST-800-53-AC-6(1)
    - NIST-800-53-CM-6(a)
    - PCI-DSSv4-2.2
    - PCI-DSSv4-2.2.6
    - configure_strategy
    - file_permissions_cron_monthly
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

  - name: Find /etc/cron.weekly/ file(s)
    ansible.builtin.command: 'find -P /etc/cron.weekly/ -maxdepth 0 -perm /u+s,g+xwrs,o+xwrt  -type
      d '
    register: files_found
    changed_when: false
    failed_when: false
    check_mode: false
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-002580
    - NIST-800-53-AC-6(1)
    - NIST-800-53-CM-6(a)
    - PCI-DSSv4-2.2
    - PCI-DSSv4-2.2.6
    - configure_strategy
    - file_permissions_cron_weekly
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

  - name: Set permissions for /etc/cron.weekly/ file(s)
    ansible.builtin.file:
      path: '{{ item }}'
      mode: u-s,g-xwrs,o-xwrt
      state: directory
    with_items:
    - '{{ files_found.stdout_lines }}'
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-002580
    - NIST-800-53-AC-6(1)
    - NIST-800-53-CM-6(a)
    - PCI-DSSv4-2.2
    - PCI-DSSv4-2.2.6
    - configure_strategy
    - file_permissions_cron_weekly
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

  - name: Test for existence /etc/crontab
    ansible.builtin.stat:
      path: /etc/crontab
    register: file_exists
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-002583
    - NIST-800-53-AC-6(1)
    - NIST-800-53-CM-6(a)
    - PCI-DSSv4-2.2
    - PCI-DSSv4-2.2.6
    - configure_strategy
    - file_permissions_crontab
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

  - name: Ensure permission u-xs,g-xwrs,o-xwrt on /etc/crontab
    ansible.builtin.file:
      path: /etc/crontab
      mode: u-xs,g-xwrs,o-xwrt
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - file_exists.stat is defined and file_exists.stat.exists
    tags:
    - DISA-STIG-OL09-00-002583
    - NIST-800-53-AC-6(1)
    - NIST-800-53-CM-6(a)
    - PCI-DSSv4-2.2
    - PCI-DSSv4-2.2.6
    - configure_strategy
    - file_permissions_crontab
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

  - name: Configure System to Forward All Mail From Postmaster to The Root Account
    block:

    - name: Check for duplicate values
      ansible.builtin.lineinfile:
        path: /etc/aliases
        create: true
        regexp: (?i)^\s*postmaster\s*:\s*
        state: absent
      check_mode: true
      changed_when: false
      register: dupes

    - name: Deduplicate values from /etc/aliases
      ansible.builtin.lineinfile:
        path: /etc/aliases
        create: true
        regexp: (?i)^\s*postmaster\s*:\s*
        state: absent
      when: dupes.found is defined and dupes.found > 1

    - name: Insert correct line to /etc/aliases
      ansible.builtin.lineinfile:
        path: /etc/aliases
        create: true
        regexp: (?i)^\s*postmaster\s*:\s*
        line: 'postmaster: root'
        state: present
      register: aliases_postmaster_changed
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-000815
    - NIST-800-53-AU-5(a)
    - NIST-800-53-AU-5.1(ii)
    - configure_strategy
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - postfix_client_configure_mail_alias_postmaster

  - name: Configure System to Forward All Mail From Postmaster to The Root Account
      - Check if newaliases command is available
    ansible.builtin.stat:
      path: /usr/bin/newaliases
    register: result_newaliases_present
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-000815
    - NIST-800-53-AU-5(a)
    - NIST-800-53-AU-5.1(ii)
    - configure_strategy
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - postfix_client_configure_mail_alias_postmaster

  - name: Configure System to Forward All Mail From Postmaster to The Root Account
      - Update postfix aliases
    ansible.builtin.command:
      cmd: newaliases
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - result_newaliases_present.stat.exists
    - aliases_postmaster_changed is changed
    tags:
    - DISA-STIG-OL09-00-000815
    - NIST-800-53-AU-5(a)
    - NIST-800-53-AU-5.1(ii)
    - configure_strategy
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - postfix_client_configure_mail_alias_postmaster

  - name: Prevent Unrestricted Mail Relaying
    block:

    - name: Check for duplicate values
      ansible.builtin.lineinfile:
        path: /etc/postfix/main.cf
        create: true
        regexp: (?i)^[ \t]*smtpd_client_restrictions\s*=\s*
        state: absent
      check_mode: true
      changed_when: false
      register: dupes

    - name: Deduplicate values from /etc/postfix/main.cf
      ansible.builtin.lineinfile:
        path: /etc/postfix/main.cf
        create: true
        regexp: (?i)^[ \t]*smtpd_client_restrictions\s*=\s*
        state: absent
      when: dupes.found is defined and dupes.found > 1

    - name: Insert correct line to /etc/postfix/main.cf
      ansible.builtin.lineinfile:
        path: /etc/postfix/main.cf
        create: true
        regexp: (?i)^[ \t]*smtpd_client_restrictions\s*=\s*
        line: smtpd_client_restrictions = permit_mynetworks,reject
        state: present
    when:
    - '"postfix" in ansible_facts.packages'
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-002425
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - postfix_prevent_unrestricted_relay
    - restrict_strategy

  - name: Get nfs and nfs4 mount points, that don't have nodev
    ansible.builtin.command: findmnt --fstab --types nfs,nfs4 -O nonodev -n -P
    register: points_register
    check_mode: false
    changed_when: false
    failed_when: false
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-002011
    - NIST-800-53-CM-6(a)
    - NIST-800-53-MP-2
    - configure_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - mount_option_nodev_remote_filesystems
    - no_reboot_needed

  - name: Add nodev to nfs and nfs4 mount points
    ansible.posix.mount:
      path: '{{ item | regex_search(''TARGET="([^"]+)"'',''\1'') | first }}'
      src: '{{ item | regex_search(''SOURCE="([^"]+)"'',''\1'') | first }}'
      fstype: '{{ item | regex_search(''FSTYPE="([^"]+)"'',''\1'') | first }}'
      state: present
      opts: '{{ item | regex_search(''OPTIONS="([^"]+)"'',''\1'') | first }},nodev'
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - (points_register.stdout | length > 0) and '\\x09' not in item
    with_items: '{{ points_register.stdout_lines }}'
    tags:
    - DISA-STIG-OL09-00-002011
    - NIST-800-53-CM-6(a)
    - NIST-800-53-MP-2
    - configure_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - mount_option_nodev_remote_filesystems
    - no_reboot_needed

  - name: Get nfs and nfs4 mount points, that don't have noexec
    ansible.builtin.command: findmnt --fstab --types nfs,nfs4 -O nonoexec -n -P
    register: points_register
    check_mode: false
    changed_when: false
    failed_when: false
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-002012
    - NIST-800-53-AC-6
    - NIST-800-53-AC-6(10)
    - NIST-800-53-AC-6(8)
    - NIST-800-53-CM-6(a)
    - configure_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - mount_option_noexec_remote_filesystems
    - no_reboot_needed

  - name: Add noexec to nfs and nfs4 mount points
    ansible.posix.mount:
      path: '{{ item | regex_search(''TARGET="([^"]+)"'',''\1'') | first }}'
      src: '{{ item | regex_search(''SOURCE="([^"]+)"'',''\1'') | first }}'
      fstype: '{{ item | regex_search(''FSTYPE="([^"]+)"'',''\1'') | first }}'
      state: present
      opts: '{{ item | regex_search(''OPTIONS="([^"]+)"'',''\1'') | first }},noexec'
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - (points_register.stdout | length > 0) and '\\x09' not in item
    with_items: '{{ points_register.stdout_lines }}'
    tags:
    - DISA-STIG-OL09-00-002012
    - NIST-800-53-AC-6
    - NIST-800-53-AC-6(10)
    - NIST-800-53-AC-6(8)
    - NIST-800-53-CM-6(a)
    - configure_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - mount_option_noexec_remote_filesystems
    - no_reboot_needed

  - name: Get nfs and nfs4 mount points, that don't have nosuid
    ansible.builtin.command: findmnt --fstab --types nfs,nfs4 -O nonosuid -n -P
    register: points_register
    check_mode: false
    changed_when: false
    failed_when: false
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-002013
    - NIST-800-53-AC-6
    - NIST-800-53-AC-6(1)
    - NIST-800-53-CM6(a)
    - configure_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - mount_option_nosuid_remote_filesystems
    - no_reboot_needed

  - name: Add nosuid to nfs and nfs4 mount points
    ansible.posix.mount:
      path: '{{ item | regex_search(''TARGET="([^"]+)"'',''\1'') | first }}'
      src: '{{ item | regex_search(''SOURCE="([^"]+)"'',''\1'') | first }}'
      fstype: '{{ item | regex_search(''FSTYPE="([^"]+)"'',''\1'') | first }}'
      state: present
      opts: '{{ item | regex_search(''OPTIONS="([^"]+)"'',''\1'') | first }},nosuid'
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - (points_register.stdout | length > 0) and '\\x09' not in item
    with_items: '{{ points_register.stdout_lines }}'
    tags:
    - DISA-STIG-OL09-00-002013
    - NIST-800-53-AC-6
    - NIST-800-53-AC-6(1)
    - NIST-800-53-CM6(a)
    - configure_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - mount_option_nosuid_remote_filesystems
    - no_reboot_needed

  - name: Disable chrony daemon from acting as server
    block:

    - name: Check for duplicate values
      ansible.builtin.lineinfile:
        path: /etc/chrony.conf
        create: true
        regexp: (?i)^\s*port\s+
        state: absent
      check_mode: true
      changed_when: false
      register: dupes

    - name: Deduplicate values from /etc/chrony.conf
      ansible.builtin.lineinfile:
        path: /etc/chrony.conf
        create: true
        regexp: (?i)^\s*port\s+
        state: absent
      when: dupes.found is defined and dupes.found > 1

    - name: Insert correct line to /etc/chrony.conf
      ansible.builtin.lineinfile:
        path: /etc/chrony.conf
        create: true
        regexp: (?i)^\s*port\s+
        line: port 0
        state: present
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - '"chrony" in ansible_facts.packages'
    tags:
    - DISA-STIG-OL09-00-002320
    - NIST-800-53-AU-12(1)
    - NIST-800-53-AU-8(1)
    - chronyd_client_only
    - low_complexity
    - low_disruption
    - low_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Disable network management of chrony daemon
    block:

    - name: Check for duplicate values
      ansible.builtin.lineinfile:
        path: /etc/chrony.conf
        create: true
        regexp: (?i)^\s*cmdport\s+
        state: absent
      check_mode: true
      changed_when: false
      register: dupes

    - name: Deduplicate values from /etc/chrony.conf
      ansible.builtin.lineinfile:
        path: /etc/chrony.conf
        create: true
        regexp: (?i)^\s*cmdport\s+
        state: absent
      when: dupes.found is defined and dupes.found > 1

    - name: Insert correct line to /etc/chrony.conf
      ansible.builtin.lineinfile:
        path: /etc/chrony.conf
        create: true
        regexp: (?i)^\s*cmdport\s+
        line: cmdport 0
        state: present
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - '"chrony" in ansible_facts.packages'
    tags:
    - DISA-STIG-OL09-00-002321
    - NIST-800-53-CM-7(1)
    - chronyd_no_chronyc_network
    - low_complexity
    - low_disruption
    - low_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Configure Time Service Maxpoll Interval - Check That /etc/ntp.conf Exist
    ansible.builtin.stat:
      path: /etc/ntp.conf
    register: ntp_conf_exist_result
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - ( "chrony" in ansible_facts.packages or "ntp" in ansible_facts.packages )
    tags:
    - DISA-STIG-OL09-00-002323
    - NIST-800-53-AU-12(1)
    - NIST-800-53-AU-8(1)(b)
    - NIST-800-53-CM-6(a)
    - chronyd_or_ntpd_set_maxpoll
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Configure Time Service Maxpoll Interval - Update the maxpoll Values in /etc/ntp.conf
    ansible.builtin.replace:
      path: /etc/ntp.conf
      regexp: ^(server.*maxpoll)[ ]+[0-9]+(.*)$
      replace: \1 {{ var_time_service_set_maxpoll }}\2
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - ( "chrony" in ansible_facts.packages or "ntp" in ansible_facts.packages )
    - ntp_conf_exist_result.stat.exists
    tags:
    - DISA-STIG-OL09-00-002323
    - NIST-800-53-AU-12(1)
    - NIST-800-53-AU-8(1)(b)
    - NIST-800-53-CM-6(a)
    - chronyd_or_ntpd_set_maxpoll
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Configure Time Service Maxpoll Interval - Set the maxpoll Values in /etc/ntp.conf
    ansible.builtin.replace:
      path: /etc/ntp.conf
      regexp: (^server\s+((?!maxpoll).)*)$
      replace: \1 maxpoll {{ var_time_service_set_maxpoll }}\n
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - ( "chrony" in ansible_facts.packages or "ntp" in ansible_facts.packages )
    - ntp_conf_exist_result.stat.exists
    tags:
    - DISA-STIG-OL09-00-002323
    - NIST-800-53-AU-12(1)
    - NIST-800-53-AU-8(1)(b)
    - NIST-800-53-CM-6(a)
    - chronyd_or_ntpd_set_maxpoll
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Configure Time Service Maxpoll Interval - Check That /etc/chrony.conf Exist
    ansible.builtin.stat:
      path: /etc/chrony.conf
    register: chrony_conf_exist_result
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - ( "chrony" in ansible_facts.packages or "ntp" in ansible_facts.packages )
    tags:
    - DISA-STIG-OL09-00-002323
    - NIST-800-53-AU-12(1)
    - NIST-800-53-AU-8(1)(b)
    - NIST-800-53-CM-6(a)
    - chronyd_or_ntpd_set_maxpoll
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Configure Time Service Maxpoll Interval - Update the maxpoll Values in /etc/chrony.conf
    ansible.builtin.replace:
      path: /etc/chrony.conf
      regexp: ^((?:server|pool|peer).*maxpoll)[ ]+[0-9]+(.*)$
      replace: \1 {{ var_time_service_set_maxpoll }}\2
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - ( "chrony" in ansible_facts.packages or "ntp" in ansible_facts.packages )
    - chrony_conf_exist_result.stat.exists
    tags:
    - DISA-STIG-OL09-00-002323
    - NIST-800-53-AU-12(1)
    - NIST-800-53-AU-8(1)(b)
    - NIST-800-53-CM-6(a)
    - chronyd_or_ntpd_set_maxpoll
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Configure Time Service Maxpoll Interval - Set the maxpoll Values in /etc/chrony.conf
    ansible.builtin.replace:
      path: /etc/chrony.conf
      regexp: (^(?:server|pool|peer)\s+((?!maxpoll).)*)$
      replace: \1 maxpoll {{ var_time_service_set_maxpoll }}\n
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - ( "chrony" in ansible_facts.packages or "ntp" in ansible_facts.packages )
    - chrony_conf_exist_result.stat.exists
    tags:
    - DISA-STIG-OL09-00-002323
    - NIST-800-53-AU-12(1)
    - NIST-800-53-AU-8(1)(b)
    - NIST-800-53-CM-6(a)
    - chronyd_or_ntpd_set_maxpoll
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Configure Time Service Maxpoll Interval - Get Conf Files from /etc/chrony.d/
    ansible.builtin.find:
      path: /etc/chrony.d/
      patterns: '*.conf'
      file_type: file
    register: chrony_d_conf_files
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - ( "chrony" in ansible_facts.packages or "ntp" in ansible_facts.packages )
    tags:
    - DISA-STIG-OL09-00-002323
    - NIST-800-53-AU-12(1)
    - NIST-800-53-AU-8(1)(b)
    - NIST-800-53-CM-6(a)
    - chronyd_or_ntpd_set_maxpoll
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Configure Time Service Maxpoll Interval - Update the maxpoll Values in /etc/chrony.d/
    ansible.builtin.replace:
      path: '{{ item.path }}'
      regexp: ^((?:server|pool|peer).*maxpoll)[ ]+[0-9,-]+(.*)$
      replace: \1 {{ var_time_service_set_maxpoll }}\2
    loop: '{{ chrony_d_conf_files.files }}'
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - ( "chrony" in ansible_facts.packages or "ntp" in ansible_facts.packages )
    - chrony_d_conf_files.matched
    tags:
    - DISA-STIG-OL09-00-002323
    - NIST-800-53-AU-12(1)
    - NIST-800-53-AU-8(1)(b)
    - NIST-800-53-CM-6(a)
    - chronyd_or_ntpd_set_maxpoll
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Configure Time Service Maxpoll Interval - Set the maxpoll Values in /etc/chrony.d/
    ansible.builtin.replace:
      path: '{{ item.path }}'
      regexp: (^(?:server|pool|peer)\s+((?!maxpoll).)*)$
      replace: \1 maxpoll {{ var_time_service_set_maxpoll }}\n
    loop: '{{ chrony_d_conf_files.files }}'
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - ( "chrony" in ansible_facts.packages or "ntp" in ansible_facts.packages )
    - chrony_d_conf_files.matched
    tags:
    - DISA-STIG-OL09-00-002323
    - NIST-800-53-AU-12(1)
    - NIST-800-53-AU-8(1)(b)
    - NIST-800-53-CM-6(a)
    - chronyd_or_ntpd_set_maxpoll
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Remove Host-Based Authentication Files - Define Excluded (Non-Local) File
      Systems and Paths
    ansible.builtin.set_fact:
      excluded_fstypes:
      - afs
      - autofs
      - ceph
      - cifs
      - smb3
      - smbfs
      - sshfs
      - ncpfs
      - ncp
      - nfs
      - nfs4
      - gfs
      - gfs2
      - glusterfs
      - gpfs
      - pvfs2
      - ocfs2
      - lustre
      - davfs
      - fuse.sshfs
      excluded_paths:
      - dev
      - proc
      - run
      - sys
      search_paths: []
    tags:
    - DISA-STIG-OL09-00-002419
    - high_severity
    - low_complexity
    - low_disruption
    - no_host_based_files
    - no_reboot_needed
    - restrict_strategy

  - name: Remove Host-Based Authentication Files - Find Relevant Root Directories
      Ignoring Pre-Defined Excluded Paths
    ansible.builtin.find:
      paths: /
      file_type: directory
      excludes: '{{ excluded_paths }}'
      hidden: true
      recurse: false
    register: result_relevant_root_dirs
    tags:
    - DISA-STIG-OL09-00-002419
    - high_severity
    - low_complexity
    - low_disruption
    - no_host_based_files
    - no_reboot_needed
    - restrict_strategy

  - name: Remove Host-Based Authentication Files - Include Relevant Root Directories
      in a List of Paths to be Searched
    ansible.builtin.set_fact:
      search_paths: '{{ search_paths | union([item.path]) }}'
    loop: '{{ result_relevant_root_dirs.files }}'
    tags:
    - DISA-STIG-OL09-00-002419
    - high_severity
    - low_complexity
    - low_disruption
    - no_host_based_files
    - no_reboot_needed
    - restrict_strategy

  - name: Remove Host-Based Authentication Files - Increment Search Paths List with
      Local Partitions Mount Points
    ansible.builtin.set_fact:
      search_paths: '{{ search_paths | union([item.mount]) }}'
    loop: '{{ ansible_mounts }}'
    when:
    - item.fstype not in excluded_fstypes
    - item.mount != '/'
    tags:
    - DISA-STIG-OL09-00-002419
    - high_severity
    - low_complexity
    - low_disruption
    - no_host_based_files
    - no_reboot_needed
    - restrict_strategy

  - name: Remove Host-Based Authentication Files - Increment Search Paths List with
      Local NFS File System Targets
    ansible.builtin.set_fact:
      search_paths: '{{ search_paths | union([item.device.split('':'')[1]]) }}'
    loop: '{{ ansible_mounts }}'
    when: item.device is search("localhost:")
    tags:
    - DISA-STIG-OL09-00-002419
    - high_severity
    - low_complexity
    - low_disruption
    - no_host_based_files
    - no_reboot_needed
    - restrict_strategy

  - name: Remove Host-Based Authentication Files - Define Rule Specific Facts
    ansible.builtin.set_fact:
      shosts_equiv_files:
      - /shosts.equiv
    tags:
    - DISA-STIG-OL09-00-002419
    - high_severity
    - low_complexity
    - low_disruption
    - no_host_based_files
    - no_reboot_needed
    - restrict_strategy

  - name: Remove Host-Based Authentication Files - Find All shosts.equiv Files in
      Local File Systems
    ansible.builtin.command:
      cmd: find {{ item }} -xdev -type f -name "shosts.equiv"
    loop: '{{ search_paths }}'
    changed_when: false
    register: result_found_shosts_equiv_files
    tags:
    - DISA-STIG-OL09-00-002419
    - high_severity
    - low_complexity
    - low_disruption
    - no_host_based_files
    - no_reboot_needed
    - restrict_strategy

  - name: Remove Host-Based Authentication Files - Create List of shosts.equiv Files
      Present in Local File Systems
    ansible.builtin.set_fact:
      shosts_equiv_files: '{{ shosts_equiv_files | union(item.stdout_lines) | list
        }}'
    loop: '{{ result_found_shosts_equiv_files.results }}'
    tags:
    - DISA-STIG-OL09-00-002419
    - high_severity
    - low_complexity
    - low_disruption
    - no_host_based_files
    - no_reboot_needed
    - restrict_strategy

  - name: Remove Host-Based Authentication Files - Ensure No shosts.equiv Files Are
      Present in the System
    ansible.builtin.file:
      path: '{{ item }}'
      state: absent
    loop: '{{ shosts_equiv_files }}'
    tags:
    - DISA-STIG-OL09-00-002419
    - high_severity
    - low_complexity
    - low_disruption
    - no_host_based_files
    - no_reboot_needed
    - restrict_strategy

  - name: Remove User Host-Based Authentication Files - Define Excluded (Non-Local)
      File Systems and Paths
    ansible.builtin.set_fact:
      excluded_fstypes:
      - afs
      - autofs
      - ceph
      - cifs
      - smb3
      - smbfs
      - sshfs
      - ncpfs
      - ncp
      - nfs
      - nfs4
      - gfs
      - gfs2
      - glusterfs
      - gpfs
      - pvfs2
      - ocfs2
      - lustre
      - davfs
      - fuse.sshfs
      excluded_paths:
      - dev
      - proc
      - run
      - sys
      search_paths: []
    tags:
    - DISA-STIG-OL09-00-002420
    - high_severity
    - low_complexity
    - low_disruption
    - no_reboot_needed
    - no_user_host_based_files
    - restrict_strategy

  - name: Remove User Host-Based Authentication Files - Find Relevant Root Directories
      Ignoring Pre-Defined Excluded Paths
    ansible.builtin.find:
      paths: /
      file_type: directory
      excludes: '{{ excluded_paths }}'
      hidden: true
      recurse: false
    register: result_relevant_root_dirs
    tags:
    - DISA-STIG-OL09-00-002420
    - high_severity
    - low_complexity
    - low_disruption
    - no_reboot_needed
    - no_user_host_based_files
    - restrict_strategy

  - name: Remove User Host-Based Authentication Files - Include Relevant Root Directories
      in a List of Paths to be Searched
    ansible.builtin.set_fact:
      search_paths: '{{ search_paths | union([item.path]) }}'
    loop: '{{ result_relevant_root_dirs.files }}'
    tags:
    - DISA-STIG-OL09-00-002420
    - high_severity
    - low_complexity
    - low_disruption
    - no_reboot_needed
    - no_user_host_based_files
    - restrict_strategy

  - name: Remove User Host-Based Authentication Files - Increment Search Paths List
      with Local Partitions Mount Points
    ansible.builtin.set_fact:
      search_paths: '{{ search_paths | union([item.mount]) }}'
    loop: '{{ ansible_mounts }}'
    when:
    - item.fstype not in excluded_fstypes
    - item.mount != '/'
    tags:
    - DISA-STIG-OL09-00-002420
    - high_severity
    - low_complexity
    - low_disruption
    - no_reboot_needed
    - no_user_host_based_files
    - restrict_strategy

  - name: Remove User Host-Based Authentication Files - Increment Search Paths List
      with Local NFS File System Targets
    ansible.builtin.set_fact:
      search_paths: '{{ search_paths | union([item.device.split('':'')[1]]) }}'
    loop: '{{ ansible_mounts }}'
    when: item.device is search("localhost:")
    tags:
    - DISA-STIG-OL09-00-002420
    - high_severity
    - low_complexity
    - low_disruption
    - no_reboot_needed
    - no_user_host_based_files
    - restrict_strategy

  - name: Remove User Host-Based Authentication Files - Define Rule Specific Facts
    ansible.builtin.set_fact:
      user_shosts_files:
      - /.shosts
    tags:
    - DISA-STIG-OL09-00-002420
    - high_severity
    - low_complexity
    - low_disruption
    - no_reboot_needed
    - no_user_host_based_files
    - restrict_strategy

  - name: Remove User Host-Based Authentication Files - Find All .shosts Files in
      Local File Systems
    ansible.builtin.command:
      cmd: find {{ item }} -xdev -type f -name ".shosts"
    loop: '{{ search_paths }}'
    changed_when: false
    register: result_found_shosts_files
    tags:
    - DISA-STIG-OL09-00-002420
    - high_severity
    - low_complexity
    - low_disruption
    - no_reboot_needed
    - no_user_host_based_files
    - restrict_strategy

  - name: Remove User Host-Based Authentication Files - Create List of .shosts Files
      Present in Local File Systems
    ansible.builtin.set_fact:
      user_shosts_files: '{{ user_shosts_files | union(item.stdout_lines) | list }}'
    loop: '{{ result_found_shosts_files.results }}'
    tags:
    - DISA-STIG-OL09-00-002420
    - high_severity
    - low_complexity
    - low_disruption
    - no_reboot_needed
    - no_user_host_based_files
    - restrict_strategy

  - name: Remove User Host-Based Authentication Files - Ensure No .shosts Files Are
      Present in the System
    ansible.builtin.file:
      path: '{{ item }}'
      state: absent
    loop: '{{ user_shosts_files }}'
    tags:
    - DISA-STIG-OL09-00-002420
    - high_severity
    - low_complexity
    - low_disruption
    - no_reboot_needed
    - no_user_host_based_files
    - restrict_strategy

  - name: Ensure tftp systemd Service Uses Secure Mode - Find valid drop-ins
    ansible.builtin.find:
      paths: /etc/systemd/system/tftp.service.d
      patterns: '*.conf'
      contains: ^\s*ExecStart\s*=\s*/\S+\s+-s\s+/\S+$
    register: valid_dropins
    failed_when: false
    when: '"tftp-server" in ansible_facts.packages'
    tags:
    - DISA-STIG-OL09-00-002426
    - NIST-800-53-IA-5 (1) (c)
    - configure_strategy
    - low_disruption
    - medium_complexity
    - medium_severity
    - no_reboot_needed
    - tftp_uses_secure_mode_systemd

  - name: Ensure tftp systemd Service Uses Secure Mode - Find all drop-in files
    ansible.builtin.find:
      paths: /etc/systemd/system/tftp.service.d
      patterns: '*.conf'
      contains: ^\s*ExecStart\s*=.*$
      file_type: file
    register: all_dropins
    failed_when: false
    when: '"tftp-server" in ansible_facts.packages'
    tags:
    - DISA-STIG-OL09-00-002426
    - NIST-800-53-IA-5 (1) (c)
    - configure_strategy
    - low_disruption
    - medium_complexity
    - medium_severity
    - no_reboot_needed
    - tftp_uses_secure_mode_systemd

  - name: Ensure tftp systemd Service Uses Secure Mode - Get invalid drop-ins
    ansible.builtin.set_fact:
      invalid_dropins: '{{ all_dropins.files | rejectattr(''path'', ''in'', valid_dropins.files
        | map(attribute=''path'') | list) | map(attribute=''path'') | list }}'
    when: '"tftp-server" in ansible_facts.packages'
    tags:
    - DISA-STIG-OL09-00-002426
    - NIST-800-53-IA-5 (1) (c)
    - configure_strategy
    - low_disruption
    - medium_complexity
    - medium_severity
    - no_reboot_needed
    - tftp_uses_secure_mode_systemd

  - name: Ensure tftp systemd Service Uses Secure Mode - Comment all ExecStart in
      invalid drop-ins
    ansible.builtin.lineinfile:
      path: '{{ item }}'
      regexp: ^\s*ExecStart\s*=.*
      state: absent
    loop: '{{ invalid_dropins }}'
    when:
    - '"tftp-server" in ansible_facts.packages'
    - invalid_dropins | length > 0
    tags:
    - DISA-STIG-OL09-00-002426
    - NIST-800-53-IA-5 (1) (c)
    - configure_strategy
    - low_disruption
    - medium_complexity
    - medium_severity
    - no_reboot_needed
    - tftp_uses_secure_mode_systemd

  - name: Ensure tftp systemd Service Uses Secure Mode - Check if a valid drop-in
      exists
    ansible.builtin.set_fact:
      tftp_config_valid: '{{ (valid_dropins.matched | default(0)) > 0 }}'
    when: '"tftp-server" in ansible_facts.packages'
    tags:
    - DISA-STIG-OL09-00-002426
    - NIST-800-53-IA-5 (1) (c)
    - configure_strategy
    - low_disruption
    - medium_complexity
    - medium_severity
    - no_reboot_needed
    - tftp_uses_secure_mode_systemd

  - name: Ensure tftp systemd Service Uses Secure Mode - Check if tftp.service contains
      valid ExecStart
    ansible.builtin.find:
      paths: /usr/lib/systemd/system
      patterns: tftp.service
      contains: ^\s*ExecStart\s*=\s*/\S+\s+-s\s+/\S+
    register: valid_tftp_service
    when:
    - '"tftp-server" in ansible_facts.packages'
    - not tftp_config_valid
    tags:
    - DISA-STIG-OL09-00-002426
    - NIST-800-53-IA-5 (1) (c)
    - configure_strategy
    - low_disruption
    - medium_complexity
    - medium_severity
    - no_reboot_needed
    - tftp_uses_secure_mode_systemd

  - name: Ensure tftp systemd Service Uses Secure Mode - Check if a valid tftp.service
      exists
    ansible.builtin.set_fact:
      original_valid: '{{ (valid_tftp_service.matched | default(0)) > 0 }}'
    when:
    - '"tftp-server" in ansible_facts.packages'
    - not tftp_config_valid
    tags:
    - DISA-STIG-OL09-00-002426
    - NIST-800-53-IA-5 (1) (c)
    - configure_strategy
    - low_disruption
    - medium_complexity
    - medium_severity
    - no_reboot_needed
    - tftp_uses_secure_mode_systemd

  - name: Ensure tftp systemd Service Uses Secure Mode - Recalculate global config
      validity
    ansible.builtin.set_fact:
      tftp_config_valid: '{{ tftp_config_valid or original_valid | default(false)
        }}'
    when: '"tftp-server" in ansible_facts.packages'
    tags:
    - DISA-STIG-OL09-00-002426
    - NIST-800-53-IA-5 (1) (c)
    - configure_strategy
    - low_disruption
    - medium_complexity
    - medium_severity
    - no_reboot_needed
    - tftp_uses_secure_mode_systemd

  - name: Ensure tftp systemd Service Uses Secure Mode - Remediate only if necessary
    block:

    - name: Ensure drop-in directory exists
      ansible.builtin.file:
        path: /etc/systemd/system/tftp.service.d
        state: directory

    - name: Deploy 10-ssg-hardening.conf drop-in
      ansible.builtin.copy:
        dest: /etc/systemd/system/tftp.service.d/10-ssg-hardening.conf
        content: |-
          [Service]
          # clear any existing ExecStart in the original unit
          ExecStart=
          ExecStart=/usr/sbin/in.tftpd -s {{ var_tftpd_secure_directory }}

    - name: Reload systemd and restart tftp service
      ansible.builtin.systemd:
        daemon_reload: true
        name: tftp
        state: restarted
        enabled: true
    when:
    - '"tftp-server" in ansible_facts.packages'
    - not tftp_config_valid
    tags:
    - DISA-STIG-OL09-00-002426
    - NIST-800-53-IA-5 (1) (c)
    - configure_strategy
    - low_disruption
    - medium_complexity
    - medium_severity
    - no_reboot_needed
    - tftp_uses_secure_mode_systemd

  - name: Set the directory_groupowner_sshd_config_d_newgroup variable if represented
      by gid
    ansible.builtin.set_fact:
      directory_groupowner_sshd_config_d_newgroup: '0'
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-002507
    - NIST-800-53-AC-17(a)
    - NIST-800-53-AC-6(1)
    - NIST-800-53-CM-6(a)
    - configure_strategy
    - directory_groupowner_sshd_config_d
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

  - name: Ensure group owner on /etc/ssh/sshd_config.d/
    ansible.builtin.file:
      path: /etc/ssh/sshd_config.d/
      follow: false
      state: directory
      group: '{{ directory_groupowner_sshd_config_d_newgroup }}'
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-002507
    - NIST-800-53-AC-17(a)
    - NIST-800-53-AC-6(1)
    - NIST-800-53-CM-6(a)
    - configure_strategy
    - directory_groupowner_sshd_config_d
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

  - name: Set the directory_owner_sshd_config_d_newown variable if represented by
      uid
    ansible.builtin.set_fact:
      directory_owner_sshd_config_d_newown: '0'
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-002508
    - NIST-800-53-AC-17(a)
    - NIST-800-53-AC-6(1)
    - NIST-800-53-CM-6(a)
    - configure_strategy
    - directory_owner_sshd_config_d
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

  - name: Ensure owner on directory /etc/ssh/sshd_config.d/
    ansible.builtin.file:
      path: /etc/ssh/sshd_config.d/
      follow: false
      state: directory
      owner: '{{ directory_owner_sshd_config_d_newown }}'
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-002508
    - NIST-800-53-AC-17(a)
    - NIST-800-53-AC-6(1)
    - NIST-800-53-CM-6(a)
    - configure_strategy
    - directory_owner_sshd_config_d
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

  - name: Find /etc/ssh/sshd_config.d/ file(s)
    ansible.builtin.command: 'find -P /etc/ssh/sshd_config.d/ -maxdepth 0 -perm /u+s,g+xwrs,o+xwrt  -type
      d '
    register: files_found
    changed_when: false
    failed_when: false
    check_mode: false
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-002509
    - NIST-800-53-AC-17(a)
    - NIST-800-53-AC-6(1)
    - NIST-800-53-CM-6(a)
    - configure_strategy
    - directory_permissions_sshd_config_d
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

  - name: Set permissions for /etc/ssh/sshd_config.d/ file(s)
    ansible.builtin.file:
      path: '{{ item }}'
      mode: u-s,g-xwrs,o-xwrt
      state: directory
    with_items:
    - '{{ files_found.stdout_lines }}'
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-002509
    - NIST-800-53-AC-17(a)
    - NIST-800-53-AC-6(1)
    - NIST-800-53-CM-6(a)
    - configure_strategy
    - directory_permissions_sshd_config_d
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

  - name: Set the file_groupowner_sshd_config_newgroup variable if represented by
      gid
    ansible.builtin.set_fact:
      file_groupowner_sshd_config_newgroup: '0'
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-002507
    - NIST-800-53-AC-17(a)
    - NIST-800-53-AC-6(1)
    - NIST-800-53-CM-6(a)
    - configure_strategy
    - file_groupowner_sshd_config
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

  - name: Test for existence /etc/ssh/sshd_config
    ansible.builtin.stat:
      path: /etc/ssh/sshd_config
    register: file_exists
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-002507
    - NIST-800-53-AC-17(a)
    - NIST-800-53-AC-6(1)
    - NIST-800-53-CM-6(a)
    - configure_strategy
    - file_groupowner_sshd_config
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

  - name: Ensure group owner on /etc/ssh/sshd_config
    ansible.builtin.file:
      path: /etc/ssh/sshd_config
      follow: false
      group: '{{ file_groupowner_sshd_config_newgroup }}'
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - file_exists.stat is defined and file_exists.stat.exists
    tags:
    - DISA-STIG-OL09-00-002507
    - NIST-800-53-AC-17(a)
    - NIST-800-53-AC-6(1)
    - NIST-800-53-CM-6(a)
    - configure_strategy
    - file_groupowner_sshd_config
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

  - name: Set the file_groupowner_sshd_drop_in_config_newgroup variable if represented
      by gid
    ansible.builtin.set_fact:
      file_groupowner_sshd_drop_in_config_newgroup: '0'
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-002507
    - NIST-800-53-AC-17(a)
    - NIST-800-53-AC-6(1)
    - NIST-800-53-CM-6(a)
    - configure_strategy
    - file_groupowner_sshd_drop_in_config
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

  - name: Find /etc/ssh/sshd_config.d/ file(s) matching ^.*$
    ansible.builtin.command: find -P /etc/ssh/sshd_config.d/ -maxdepth 1 -type f  !
      -group 0 -regextype posix-extended -regex "^.*$"
    register: files_found
    changed_when: false
    failed_when: false
    check_mode: false
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-002507
    - NIST-800-53-AC-17(a)
    - NIST-800-53-AC-6(1)
    - NIST-800-53-CM-6(a)
    - configure_strategy
    - file_groupowner_sshd_drop_in_config
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

  - name: Ensure group owner on /etc/ssh/sshd_config.d/ file(s) matching ^.*$
    ansible.builtin.file:
      path: '{{ item }}'
      follow: false
      group: '{{ file_groupowner_sshd_drop_in_config_newgroup }}'
      state: file
    with_items:
    - '{{ files_found.stdout_lines }}'
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-002507
    - NIST-800-53-AC-17(a)
    - NIST-800-53-AC-6(1)
    - NIST-800-53-CM-6(a)
    - configure_strategy
    - file_groupowner_sshd_drop_in_config
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

  - name: Set the file_owner_sshd_config_newown variable if represented by uid
    ansible.builtin.set_fact:
      file_owner_sshd_config_newown: '0'
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-002508
    - NIST-800-53-AC-17(a)
    - NIST-800-53-AC-6(1)
    - NIST-800-53-CM-6(a)
    - configure_strategy
    - file_owner_sshd_config
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

  - name: Test for existence /etc/ssh/sshd_config
    ansible.builtin.stat:
      path: /etc/ssh/sshd_config
    register: file_exists
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-002508
    - NIST-800-53-AC-17(a)
    - NIST-800-53-AC-6(1)
    - NIST-800-53-CM-6(a)
    - configure_strategy
    - file_owner_sshd_config
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

  - name: Ensure owner on /etc/ssh/sshd_config
    ansible.builtin.file:
      path: /etc/ssh/sshd_config
      follow: false
      owner: '{{ file_owner_sshd_config_newown }}'
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - file_exists.stat is defined and file_exists.stat.exists
    tags:
    - DISA-STIG-OL09-00-002508
    - NIST-800-53-AC-17(a)
    - NIST-800-53-AC-6(1)
    - NIST-800-53-CM-6(a)
    - configure_strategy
    - file_owner_sshd_config
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

  - name: Set the file_owner_sshd_drop_in_config_newown variable if represented by
      uid
    ansible.builtin.set_fact:
      file_owner_sshd_drop_in_config_newown: '0'
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-002508
    - NIST-800-53-AC-17(a)
    - NIST-800-53-AC-6(1)
    - NIST-800-53-CM-6(a)
    - configure_strategy
    - file_owner_sshd_drop_in_config
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

  - name: Find /etc/ssh/sshd_config.d/ file(s) matching ^.*$
    ansible.builtin.command: find -P /etc/ssh/sshd_config.d/ -maxdepth 1 -type f  !
      -user 0 -regextype posix-extended -regex "^.*$"
    register: files_found
    changed_when: false
    failed_when: false
    check_mode: false
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-002508
    - NIST-800-53-AC-17(a)
    - NIST-800-53-AC-6(1)
    - NIST-800-53-CM-6(a)
    - configure_strategy
    - file_owner_sshd_drop_in_config
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

  - name: Ensure owner on /etc/ssh/sshd_config.d/ file(s) matching ^.*$
    ansible.builtin.file:
      path: '{{ item }}'
      follow: false
      owner: '{{ file_owner_sshd_drop_in_config_newown }}'
      state: file
    with_items:
    - '{{ files_found.stdout_lines }}'
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-002508
    - NIST-800-53-AC-17(a)
    - NIST-800-53-AC-6(1)
    - NIST-800-53-CM-6(a)
    - configure_strategy
    - file_owner_sshd_drop_in_config
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

  - name: Test for existence /etc/ssh/sshd_config
    ansible.builtin.stat:
      path: /etc/ssh/sshd_config
    register: file_exists
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-002509
    - NIST-800-53-AC-17(a)
    - NIST-800-53-AC-6(1)
    - NIST-800-53-CM-6(a)
    - PCI-DSSv4-2.2
    - PCI-DSSv4-2.2.6
    - configure_strategy
    - file_permissions_sshd_config
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

  - name: Ensure permission u-xs,g-xwrs,o-xwrt on /etc/ssh/sshd_config
    ansible.builtin.file:
      path: /etc/ssh/sshd_config
      mode: u-xs,g-xwrs,o-xwrt
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - file_exists.stat is defined and file_exists.stat.exists
    tags:
    - DISA-STIG-OL09-00-002509
    - NIST-800-53-AC-17(a)
    - NIST-800-53-AC-6(1)
    - NIST-800-53-CM-6(a)
    - PCI-DSSv4-2.2
    - PCI-DSSv4-2.2.6
    - configure_strategy
    - file_permissions_sshd_config
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

  - name: Find /etc/ssh/sshd_config.d/ file(s)
    ansible.builtin.command: find -P /etc/ssh/sshd_config.d/ -maxdepth 1 -perm /u+xs,g+xwrs,o+xwrt  -type
      f -regextype posix-extended -regex "^.*$"
    register: files_found
    changed_when: false
    failed_when: false
    check_mode: false
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-002509
    - NIST-800-53-AC-17(a)
    - NIST-800-53-AC-6(1)
    - NIST-800-53-CM-6(a)
    - configure_strategy
    - file_permissions_sshd_drop_in_config
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

  - name: Set permissions for /etc/ssh/sshd_config.d/ file(s)
    ansible.builtin.file:
      path: '{{ item }}'
      mode: u-xs,g-xwrs,o-xwrt
      state: file
    with_items:
    - '{{ files_found.stdout_lines }}'
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-002509
    - NIST-800-53-AC-17(a)
    - NIST-800-53-AC-6(1)
    - NIST-800-53-CM-6(a)
    - configure_strategy
    - file_permissions_sshd_drop_in_config
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

  - name: Find root:root-owned keys
    ansible.builtin.command: find -H /etc/ssh/ -maxdepth 1 -user root -regex ".*_key$"
      -type f -group root -perm /u+xs,g+xws,o+xwrt
    register: root_owned_keys
    changed_when: false
    failed_when: false
    check_mode: false
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-002502
    - NIST-800-171-3.1.13
    - NIST-800-171-3.13.10
    - NIST-800-53-AC-17(a)
    - NIST-800-53-AC-6(1)
    - NIST-800-53-CM-6(a)
    - PCI-DSS-Req-2.2.4
    - PCI-DSSv4-2.2
    - PCI-DSSv4-2.2.6
    - configure_strategy
    - file_permissions_sshd_private_key
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

  - name: Set permissions for root:root-owned keys
    ansible.builtin.file:
      path: '{{ item }}'
      mode: u-xs,g-xws,o-xwrt
      state: file
    with_items:
    - '{{ root_owned_keys.stdout_lines }}'
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-002502
    - NIST-800-171-3.1.13
    - NIST-800-171-3.13.10
    - NIST-800-53-AC-17(a)
    - NIST-800-53-AC-6(1)
    - NIST-800-53-CM-6(a)
    - PCI-DSS-Req-2.2.4
    - PCI-DSSv4-2.2
    - PCI-DSSv4-2.2.6
    - configure_strategy
    - file_permissions_sshd_private_key
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

  - name: Find root:ssh_keys-owned keys
    ansible.builtin.command: find -H /etc/ssh/ -maxdepth 1 -user root -regex ".*_key$"
      -type f -group ssh_keys -perm /u+xs,g+xws,o+xwrt
    register: dedicated_group_owned_keys
    changed_when: false
    failed_when: false
    check_mode: false
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-002502
    - NIST-800-171-3.1.13
    - NIST-800-171-3.13.10
    - NIST-800-53-AC-17(a)
    - NIST-800-53-AC-6(1)
    - NIST-800-53-CM-6(a)
    - PCI-DSS-Req-2.2.4
    - PCI-DSSv4-2.2
    - PCI-DSSv4-2.2.6
    - configure_strategy
    - file_permissions_sshd_private_key
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

  - name: Set permissions for root:ssh_keys-owned keys
    ansible.builtin.file:
      path: '{{ item }}'
      mode: u-xs,g-xws,o-xwrt
      state: file
    with_items:
    - '{{ dedicated_group_owned_keys.stdout_lines }}'
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-002502
    - NIST-800-171-3.1.13
    - NIST-800-171-3.13.10
    - NIST-800-53-AC-17(a)
    - NIST-800-53-AC-6(1)
    - NIST-800-53-CM-6(a)
    - PCI-DSS-Req-2.2.4
    - PCI-DSSv4-2.2
    - PCI-DSSv4-2.2.6
    - configure_strategy
    - file_permissions_sshd_private_key
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

  - name: Find /etc/ssh/ file(s)
    ansible.builtin.command: find -P /etc/ssh/ -maxdepth 1 -perm /u+xs,g+xws,o+xwt  -type
      f -regextype posix-extended -regex "^.*\.pub$"
    register: files_found
    changed_when: false
    failed_when: false
    check_mode: false
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-002503
    - NIST-800-171-3.1.13
    - NIST-800-171-3.13.10
    - NIST-800-53-AC-17(a)
    - NIST-800-53-AC-6(1)
    - NIST-800-53-CM-6(a)
    - PCI-DSS-Req-2.2.4
    - PCI-DSSv4-2.2
    - PCI-DSSv4-2.2.6
    - configure_strategy
    - file_permissions_sshd_pub_key
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

  - name: Set permissions for /etc/ssh/ file(s)
    ansible.builtin.file:
      path: '{{ item }}'
      mode: u-xs,g-xws,o-xwt
      state: file
    with_items:
    - '{{ files_found.stdout_lines }}'
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-002503
    - NIST-800-171-3.1.13
    - NIST-800-171-3.13.10
    - NIST-800-53-AC-17(a)
    - NIST-800-53-AC-6(1)
    - NIST-800-53-CM-6(a)
    - PCI-DSS-Req-2.2.4
    - PCI-DSSv4-2.2
    - PCI-DSSv4-2.2.6
    - configure_strategy
    - file_permissions_sshd_pub_key
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

  - name: Find sshd_config included files
    ansible.builtin.shell: |-
      included_files=$(grep -oP "^\s*(?i)include.*" /etc/ssh/sshd_config | sed -e 's/\s*Include\s*//i' | sed -e 's|^[^/]|/etc/ssh/&|')
      [[ -n $included_files ]] && ls $included_files || true
    register: sshd_config_included_files
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - CJIS-5.5.6
    - DISA-STIG-OL09-00-002346
    - NIST-800-171-3.1.11
    - NIST-800-53-AC-12
    - NIST-800-53-AC-17(a)
    - NIST-800-53-AC-2(5)
    - NIST-800-53-CM-6(a)
    - NIST-800-53-SC-10
    - PCI-DSS-Req-8.1.8
    - PCI-DSSv4-8.2
    - PCI-DSSv4-8.2.8
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy
    - sshd_set_keepalive

  - name: Comment conf from included files
    ansible.builtin.replace:
      path: '{{ item }}'
      regexp: ^(\s*ClientAliveCountMax.*)$
      replace: '# \1'
    loop: '{{ sshd_config_included_files.stdout_lines }}'
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - CJIS-5.5.6
    - DISA-STIG-OL09-00-002346
    - NIST-800-171-3.1.11
    - NIST-800-53-AC-12
    - NIST-800-53-AC-17(a)
    - NIST-800-53-AC-2(5)
    - NIST-800-53-CM-6(a)
    - NIST-800-53-SC-10
    - PCI-DSS-Req-8.1.8
    - PCI-DSSv4-8.2
    - PCI-DSSv4-8.2.8
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy
    - sshd_set_keepalive

  - name: Set SSH Client Alive Count Max - Check if the parameter ClientAliveCountMax
      is configured
    ansible.builtin.find:
      paths:
      - /etc/ssh/sshd_config
      - /etc/ssh/sshd_config.d
      contains: (?i)^\s*{{ "ClientAliveCountMax"| regex_escape }}\s+
    register: _sshd_config_has_parameter
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - CJIS-5.5.6
    - DISA-STIG-OL09-00-002346
    - NIST-800-171-3.1.11
    - NIST-800-53-AC-12
    - NIST-800-53-AC-17(a)
    - NIST-800-53-AC-2(5)
    - NIST-800-53-CM-6(a)
    - NIST-800-53-SC-10
    - PCI-DSS-Req-8.1.8
    - PCI-DSSv4-8.2
    - PCI-DSSv4-8.2.8
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy
    - sshd_set_keepalive

  - name: Set SSH Client Alive Count Max - Check if the parameter ClientAliveCountMax
      is configured correctly
    ansible.builtin.find:
      paths:
      - /etc/ssh/sshd_config
      - /etc/ssh/sshd_config.d
      contains: (?i)^\s*{{ "ClientAliveCountMax"| regex_escape }}\s+{{ var_sshd_set_keepalive
        }}$
    register: _sshd_config_correctly
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - CJIS-5.5.6
    - DISA-STIG-OL09-00-002346
    - NIST-800-171-3.1.11
    - NIST-800-53-AC-12
    - NIST-800-53-AC-17(a)
    - NIST-800-53-AC-2(5)
    - NIST-800-53-CM-6(a)
    - NIST-800-53-SC-10
    - PCI-DSS-Req-8.1.8
    - PCI-DSSv4-8.2
    - PCI-DSSv4-8.2.8
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy
    - sshd_set_keepalive

  - name: Set SSH Client Alive Count Max
    block:

    - name: Deduplicate values from /etc/ssh/sshd_config
      ansible.builtin.lineinfile:
        path: /etc/ssh/sshd_config
        create: false
        regexp: (?i)(?i)^\s*{{ "ClientAliveCountMax"| regex_escape }}\s+
        state: absent

    - name: Check if /etc/ssh/sshd_config.d exists
      ansible.builtin.stat:
        path: /etc/ssh/sshd_config.d
      register: _etc_ssh_sshd_config_d_exists

    - name: Check if the parameter ClientAliveCountMax is present in /etc/ssh/sshd_config.d
      ansible.builtin.find:
        paths: /etc/ssh/sshd_config.d
        recurse: 'yes'
        follow: 'no'
        contains: (?i)^\s*{{ "ClientAliveCountMax"| regex_escape }}\s+
      register: _etc_ssh_sshd_config_d_has_parameter
      when: _etc_ssh_sshd_config_d_exists.stat.isdir is defined and _etc_ssh_sshd_config_d_exists.stat.isdir

    - name: Remove parameter from files in /etc/ssh/sshd_config.d
      ansible.builtin.lineinfile:
        path: '{{ item.path }}'
        create: false
        regexp: (?i)(?i)^\s*{{ "ClientAliveCountMax"| regex_escape }}\s+
        state: absent
      with_items: '{{ _etc_ssh_sshd_config_d_has_parameter.files }}'
      when: _etc_ssh_sshd_config_d_has_parameter.matched > 0

    - name: Insert correct line to /etc/ssh/sshd_config.d/00-complianceascode-hardening.conf
      ansible.builtin.lineinfile:
        path: /etc/ssh/sshd_config.d/00-complianceascode-hardening.conf
        create: true
        regexp: (?i)(?i)^\s*{{ "ClientAliveCountMax"| regex_escape }}\s+
        line: ClientAliveCountMax {{ var_sshd_set_keepalive }}
        state: present
        insertbefore: BOF
        validate: /usr/sbin/sshd -t -f %s
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - _sshd_config_correctly.matched == 0 or _sshd_config_has_parameter.matched !=
      1
    tags:
    - CJIS-5.5.6
    - DISA-STIG-OL09-00-002346
    - NIST-800-171-3.1.11
    - NIST-800-53-AC-12
    - NIST-800-53-AC-17(a)
    - NIST-800-53-AC-2(5)
    - NIST-800-53-CM-6(a)
    - NIST-800-53-SC-10
    - PCI-DSS-Req-8.1.8
    - PCI-DSSv4-8.2
    - PCI-DSSv4-8.2.8
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy
    - sshd_set_keepalive

  - name: Set SSH Client Alive Count Max - set file mode for /etc/ssh/sshd_config.d/00-complianceascode-hardening.conf
    ansible.builtin.file:
      path: /etc/ssh/sshd_config.d/00-complianceascode-hardening.conf
      mode: '0600'
      state: touch
      modification_time: preserve
      access_time: preserve
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - CJIS-5.5.6
    - DISA-STIG-OL09-00-002346
    - NIST-800-171-3.1.11
    - NIST-800-53-AC-12
    - NIST-800-53-AC-17(a)
    - NIST-800-53-AC-2(5)
    - NIST-800-53-CM-6(a)
    - NIST-800-53-SC-10
    - PCI-DSS-Req-8.1.8
    - PCI-DSSv4-8.2
    - PCI-DSSv4-8.2.8
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy
    - sshd_set_keepalive

  - name: Find sshd_config included files
    ansible.builtin.shell: |-
      included_files=$(grep -oP "^\s*(?i)include.*" /etc/ssh/sshd_config | sed -e 's/\s*Include\s*//i' | sed -e 's|^[^/]|/etc/ssh/&|')
      [[ -n $included_files ]] && ls $included_files || true
    register: sshd_config_included_files
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - CJIS-5.5.6
    - DISA-STIG-OL09-00-002347
    - NIST-800-171-3.1.11
    - NIST-800-53-AC-12
    - NIST-800-53-AC-17(a)
    - NIST-800-53-AC-17(a)
    - NIST-800-53-AC-2(5)
    - NIST-800-53-CM-6(a)
    - NIST-800-53-CM-6(a)
    - NIST-800-53-SC-10
    - PCI-DSS-Req-8.1.8
    - PCI-DSSv4-8.2
    - PCI-DSSv4-8.2.8
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy
    - sshd_set_idle_timeout

  - name: Comment conf from included files
    ansible.builtin.replace:
      path: '{{ item }}'
      regexp: ^(\s*ClientAliveInterval.*)$
      replace: '# \1'
    loop: '{{ sshd_config_included_files.stdout_lines }}'
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - CJIS-5.5.6
    - DISA-STIG-OL09-00-002347
    - NIST-800-171-3.1.11
    - NIST-800-53-AC-12
    - NIST-800-53-AC-17(a)
    - NIST-800-53-AC-17(a)
    - NIST-800-53-AC-2(5)
    - NIST-800-53-CM-6(a)
    - NIST-800-53-CM-6(a)
    - NIST-800-53-SC-10
    - PCI-DSS-Req-8.1.8
    - PCI-DSSv4-8.2
    - PCI-DSSv4-8.2.8
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy
    - sshd_set_idle_timeout

  - name: Set SSH Client Alive Interval - Check if the parameter ClientAliveInterval
      is configured
    ansible.builtin.find:
      paths:
      - /etc/ssh/sshd_config
      - /etc/ssh/sshd_config.d
      contains: (?i)^\s*{{ "ClientAliveInterval"| regex_escape }}\s+
    register: _sshd_config_has_parameter
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - CJIS-5.5.6
    - DISA-STIG-OL09-00-002347
    - NIST-800-171-3.1.11
    - NIST-800-53-AC-12
    - NIST-800-53-AC-17(a)
    - NIST-800-53-AC-17(a)
    - NIST-800-53-AC-2(5)
    - NIST-800-53-CM-6(a)
    - NIST-800-53-CM-6(a)
    - NIST-800-53-SC-10
    - PCI-DSS-Req-8.1.8
    - PCI-DSSv4-8.2
    - PCI-DSSv4-8.2.8
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy
    - sshd_set_idle_timeout

  - name: Set SSH Client Alive Interval - Check if the parameter ClientAliveInterval
      is configured correctly
    ansible.builtin.find:
      paths:
      - /etc/ssh/sshd_config
      - /etc/ssh/sshd_config.d
      contains: (?i)^\s*{{ "ClientAliveInterval"| regex_escape }}\s+{{ sshd_idle_timeout_value
        }}$
    register: _sshd_config_correctly
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - CJIS-5.5.6
    - DISA-STIG-OL09-00-002347
    - NIST-800-171-3.1.11
    - NIST-800-53-AC-12
    - NIST-800-53-AC-17(a)
    - NIST-800-53-AC-17(a)
    - NIST-800-53-AC-2(5)
    - NIST-800-53-CM-6(a)
    - NIST-800-53-CM-6(a)
    - NIST-800-53-SC-10
    - PCI-DSS-Req-8.1.8
    - PCI-DSSv4-8.2
    - PCI-DSSv4-8.2.8
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy
    - sshd_set_idle_timeout

  - name: Set SSH Client Alive Interval
    block:

    - name: Deduplicate values from /etc/ssh/sshd_config
      ansible.builtin.lineinfile:
        path: /etc/ssh/sshd_config
        create: false
        regexp: (?i)(?i)^\s*{{ "ClientAliveInterval"| regex_escape }}\s+
        state: absent

    - name: Check if /etc/ssh/sshd_config.d exists
      ansible.builtin.stat:
        path: /etc/ssh/sshd_config.d
      register: _etc_ssh_sshd_config_d_exists

    - name: Check if the parameter ClientAliveInterval is present in /etc/ssh/sshd_config.d
      ansible.builtin.find:
        paths: /etc/ssh/sshd_config.d
        recurse: 'yes'
        follow: 'no'
        contains: (?i)^\s*{{ "ClientAliveInterval"| regex_escape }}\s+
      register: _etc_ssh_sshd_config_d_has_parameter
      when: _etc_ssh_sshd_config_d_exists.stat.isdir is defined and _etc_ssh_sshd_config_d_exists.stat.isdir

    - name: Remove parameter from files in /etc/ssh/sshd_config.d
      ansible.builtin.lineinfile:
        path: '{{ item.path }}'
        create: false
        regexp: (?i)(?i)^\s*{{ "ClientAliveInterval"| regex_escape }}\s+
        state: absent
      with_items: '{{ _etc_ssh_sshd_config_d_has_parameter.files }}'
      when: _etc_ssh_sshd_config_d_has_parameter.matched > 0

    - name: Insert correct line to /etc/ssh/sshd_config.d/00-complianceascode-hardening.conf
      ansible.builtin.lineinfile:
        path: /etc/ssh/sshd_config.d/00-complianceascode-hardening.conf
        create: true
        regexp: (?i)(?i)^\s*{{ "ClientAliveInterval"| regex_escape }}\s+
        line: ClientAliveInterval {{ sshd_idle_timeout_value }}
        state: present
        insertbefore: BOF
        validate: /usr/sbin/sshd -t -f %s
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - _sshd_config_correctly.matched == 0 or _sshd_config_has_parameter.matched !=
      1
    tags:
    - CJIS-5.5.6
    - DISA-STIG-OL09-00-002347
    - NIST-800-171-3.1.11
    - NIST-800-53-AC-12
    - NIST-800-53-AC-17(a)
    - NIST-800-53-AC-17(a)
    - NIST-800-53-AC-2(5)
    - NIST-800-53-CM-6(a)
    - NIST-800-53-CM-6(a)
    - NIST-800-53-SC-10
    - PCI-DSS-Req-8.1.8
    - PCI-DSSv4-8.2
    - PCI-DSSv4-8.2.8
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy
    - sshd_set_idle_timeout

  - name: Set SSH Client Alive Interval - set file mode for /etc/ssh/sshd_config.d/00-complianceascode-hardening.conf
    ansible.builtin.file:
      path: /etc/ssh/sshd_config.d/00-complianceascode-hardening.conf
      mode: '0600'
      state: touch
      modification_time: preserve
      access_time: preserve
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - CJIS-5.5.6
    - DISA-STIG-OL09-00-002347
    - NIST-800-171-3.1.11
    - NIST-800-53-AC-12
    - NIST-800-53-AC-17(a)
    - NIST-800-53-AC-17(a)
    - NIST-800-53-AC-2(5)
    - NIST-800-53-CM-6(a)
    - NIST-800-53-CM-6(a)
    - NIST-800-53-SC-10
    - PCI-DSS-Req-8.1.8
    - PCI-DSSv4-8.2
    - PCI-DSSv4-8.2.8
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy
    - sshd_set_idle_timeout

  - name: Find sshd_config included files
    ansible.builtin.shell: |-
      included_files=$(grep -oP "^\s*(?i)include.*" /etc/ssh/sshd_config | sed -e 's/\s*Include\s*//i' | sed -e 's|^[^/]|/etc/ssh/&|')
      [[ -n $included_files ]] && ls $included_files || true
    register: sshd_config_included_files
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - CJIS-5.5.6
    - DISA-STIG-OL09-00-002357
    - NIST-800-171-3.1.12
    - NIST-800-53-AC-17(a)
    - NIST-800-53-AC-3
    - NIST-800-53-CM-6(a)
    - NIST-800-53-CM-7(a)
    - NIST-800-53-CM-7(b)
    - PCI-DSSv4-8.3
    - PCI-DSSv4-8.3.1
    - disable_host_auth
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Comment conf from included files
    ansible.builtin.replace:
      path: '{{ item }}'
      regexp: ^(\s*HostbasedAuthentication.*)$
      replace: '# \1'
    loop: '{{ sshd_config_included_files.stdout_lines }}'
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - CJIS-5.5.6
    - DISA-STIG-OL09-00-002357
    - NIST-800-171-3.1.12
    - NIST-800-53-AC-17(a)
    - NIST-800-53-AC-3
    - NIST-800-53-CM-6(a)
    - NIST-800-53-CM-7(a)
    - NIST-800-53-CM-7(b)
    - PCI-DSSv4-8.3
    - PCI-DSSv4-8.3.1
    - disable_host_auth
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Disable Host-Based Authentication - Check if the parameter HostbasedAuthentication
      is configured
    ansible.builtin.find:
      paths:
      - /etc/ssh/sshd_config
      - /etc/ssh/sshd_config.d
      contains: (?i)^\s*{{ "HostbasedAuthentication"| regex_escape }}\s+
    register: _sshd_config_has_parameter
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - CJIS-5.5.6
    - DISA-STIG-OL09-00-002357
    - NIST-800-171-3.1.12
    - NIST-800-53-AC-17(a)
    - NIST-800-53-AC-3
    - NIST-800-53-CM-6(a)
    - NIST-800-53-CM-7(a)
    - NIST-800-53-CM-7(b)
    - PCI-DSSv4-8.3
    - PCI-DSSv4-8.3.1
    - disable_host_auth
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Disable Host-Based Authentication - Check if the parameter HostbasedAuthentication
      is configured correctly
    ansible.builtin.find:
      paths:
      - /etc/ssh/sshd_config
      - /etc/ssh/sshd_config.d
      contains: (?i)^\s*{{ "HostbasedAuthentication"| regex_escape }}\s+no$
    register: _sshd_config_correctly
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - CJIS-5.5.6
    - DISA-STIG-OL09-00-002357
    - NIST-800-171-3.1.12
    - NIST-800-53-AC-17(a)
    - NIST-800-53-AC-3
    - NIST-800-53-CM-6(a)
    - NIST-800-53-CM-7(a)
    - NIST-800-53-CM-7(b)
    - PCI-DSSv4-8.3
    - PCI-DSSv4-8.3.1
    - disable_host_auth
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Disable Host-Based Authentication
    block:

    - name: Deduplicate values from /etc/ssh/sshd_config
      ansible.builtin.lineinfile:
        path: /etc/ssh/sshd_config
        create: false
        regexp: (?i)(?i)^\s*{{ "HostbasedAuthentication"| regex_escape }}\s+
        state: absent

    - name: Check if /etc/ssh/sshd_config.d exists
      ansible.builtin.stat:
        path: /etc/ssh/sshd_config.d
      register: _etc_ssh_sshd_config_d_exists

    - name: Check if the parameter HostbasedAuthentication is present in /etc/ssh/sshd_config.d
      ansible.builtin.find:
        paths: /etc/ssh/sshd_config.d
        recurse: 'yes'
        follow: 'no'
        contains: (?i)^\s*{{ "HostbasedAuthentication"| regex_escape }}\s+
      register: _etc_ssh_sshd_config_d_has_parameter
      when: _etc_ssh_sshd_config_d_exists.stat.isdir is defined and _etc_ssh_sshd_config_d_exists.stat.isdir

    - name: Remove parameter from files in /etc/ssh/sshd_config.d
      ansible.builtin.lineinfile:
        path: '{{ item.path }}'
        create: false
        regexp: (?i)(?i)^\s*{{ "HostbasedAuthentication"| regex_escape }}\s+
        state: absent
      with_items: '{{ _etc_ssh_sshd_config_d_has_parameter.files }}'
      when: _etc_ssh_sshd_config_d_has_parameter.matched > 0

    - name: Insert correct line to /etc/ssh/sshd_config.d/01-complianceascode-reinforce-os-defaults.conf
      ansible.builtin.lineinfile:
        path: /etc/ssh/sshd_config.d/01-complianceascode-reinforce-os-defaults.conf
        create: true
        regexp: (?i)(?i)^\s*{{ "HostbasedAuthentication"| regex_escape }}\s+
        line: HostbasedAuthentication no
        state: present
        insertbefore: BOF
        validate: /usr/sbin/sshd -t -f %s
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - _sshd_config_correctly.matched == 0 or _sshd_config_has_parameter.matched !=
      1
    tags:
    - CJIS-5.5.6
    - DISA-STIG-OL09-00-002357
    - NIST-800-171-3.1.12
    - NIST-800-53-AC-17(a)
    - NIST-800-53-AC-3
    - NIST-800-53-CM-6(a)
    - NIST-800-53-CM-7(a)
    - NIST-800-53-CM-7(b)
    - PCI-DSSv4-8.3
    - PCI-DSSv4-8.3.1
    - disable_host_auth
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Disable Host-Based Authentication - set file mode for /etc/ssh/sshd_config.d/01-complianceascode-reinforce-os-defaults.conf
    ansible.builtin.file:
      path: /etc/ssh/sshd_config.d/01-complianceascode-reinforce-os-defaults.conf
      mode: '0600'
      state: touch
      modification_time: preserve
      access_time: preserve
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - CJIS-5.5.6
    - DISA-STIG-OL09-00-002357
    - NIST-800-171-3.1.12
    - NIST-800-53-AC-17(a)
    - NIST-800-53-AC-3
    - NIST-800-53-CM-6(a)
    - NIST-800-53-CM-7(a)
    - NIST-800-53-CM-7(b)
    - PCI-DSSv4-8.3
    - PCI-DSSv4-8.3.1
    - disable_host_auth
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Find sshd_config included files
    ansible.builtin.shell: |-
      included_files=$(grep -oP "^\s*(?i)include.*" /etc/ssh/sshd_config | sed -e 's/\s*Include\s*//i' | sed -e 's|^[^/]|/etc/ssh/&|')
      [[ -n $included_files ]] && ls $included_files || true
    register: sshd_config_included_files
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-002355
    - NIST-800-171-3.1.12
    - NIST-800-53-AC-17(a)
    - NIST-800-53-CM-6(a)
    - NIST-800-53-CM-7(a)
    - NIST-800-53-CM-7(b)
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy
    - sshd_disable_compression

  - name: Comment conf from included files
    ansible.builtin.replace:
      path: '{{ item }}'
      regexp: ^(\s*Compression.*)$
      replace: '# \1'
    loop: '{{ sshd_config_included_files.stdout_lines }}'
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-002355
    - NIST-800-171-3.1.12
    - NIST-800-53-AC-17(a)
    - NIST-800-53-CM-6(a)
    - NIST-800-53-CM-7(a)
    - NIST-800-53-CM-7(b)
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy
    - sshd_disable_compression

  - name: Disable Compression Or Set Compression to delayed - Check if the parameter
      Compression is configured
    ansible.builtin.find:
      paths:
      - /etc/ssh/sshd_config
      - /etc/ssh/sshd_config.d
      contains: (?i)^\s*{{ "Compression"| regex_escape }}\s+
    register: _sshd_config_has_parameter
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-002355
    - NIST-800-171-3.1.12
    - NIST-800-53-AC-17(a)
    - NIST-800-53-CM-6(a)
    - NIST-800-53-CM-7(a)
    - NIST-800-53-CM-7(b)
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy
    - sshd_disable_compression

  - name: Disable Compression Or Set Compression to delayed - Check if the parameter
      Compression is configured correctly
    ansible.builtin.find:
      paths:
      - /etc/ssh/sshd_config
      - /etc/ssh/sshd_config.d
      contains: (?i)^\s*{{ "Compression"| regex_escape }}\s+{{ var_sshd_disable_compression
        }}$
    register: _sshd_config_correctly
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-002355
    - NIST-800-171-3.1.12
    - NIST-800-53-AC-17(a)
    - NIST-800-53-CM-6(a)
    - NIST-800-53-CM-7(a)
    - NIST-800-53-CM-7(b)
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy
    - sshd_disable_compression

  - name: Disable Compression Or Set Compression to delayed
    block:

    - name: Deduplicate values from /etc/ssh/sshd_config
      ansible.builtin.lineinfile:
        path: /etc/ssh/sshd_config
        create: false
        regexp: (?i)(?i)^\s*{{ "Compression"| regex_escape }}\s+
        state: absent

    - name: Check if /etc/ssh/sshd_config.d exists
      ansible.builtin.stat:
        path: /etc/ssh/sshd_config.d
      register: _etc_ssh_sshd_config_d_exists

    - name: Check if the parameter Compression is present in /etc/ssh/sshd_config.d
      ansible.builtin.find:
        paths: /etc/ssh/sshd_config.d
        recurse: 'yes'
        follow: 'no'
        contains: (?i)^\s*{{ "Compression"| regex_escape }}\s+
      register: _etc_ssh_sshd_config_d_has_parameter
      when: _etc_ssh_sshd_config_d_exists.stat.isdir is defined and _etc_ssh_sshd_config_d_exists.stat.isdir

    - name: Remove parameter from files in /etc/ssh/sshd_config.d
      ansible.builtin.lineinfile:
        path: '{{ item.path }}'
        create: false
        regexp: (?i)(?i)^\s*{{ "Compression"| regex_escape }}\s+
        state: absent
      with_items: '{{ _etc_ssh_sshd_config_d_has_parameter.files }}'
      when: _etc_ssh_sshd_config_d_has_parameter.matched > 0

    - name: Insert correct line to /etc/ssh/sshd_config.d/00-complianceascode-hardening.conf
      ansible.builtin.lineinfile:
        path: /etc/ssh/sshd_config.d/00-complianceascode-hardening.conf
        create: true
        regexp: (?i)(?i)^\s*{{ "Compression"| regex_escape }}\s+
        line: Compression {{ var_sshd_disable_compression }}
        state: present
        insertbefore: BOF
        validate: /usr/sbin/sshd -t -f %s
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - _sshd_config_correctly.matched == 0 or _sshd_config_has_parameter.matched !=
      1
    tags:
    - DISA-STIG-OL09-00-002355
    - NIST-800-171-3.1.12
    - NIST-800-53-AC-17(a)
    - NIST-800-53-CM-6(a)
    - NIST-800-53-CM-7(a)
    - NIST-800-53-CM-7(b)
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy
    - sshd_disable_compression

  - name: Disable Compression Or Set Compression to delayed - set file mode for /etc/ssh/sshd_config.d/00-complianceascode-hardening.conf
    ansible.builtin.file:
      path: /etc/ssh/sshd_config.d/00-complianceascode-hardening.conf
      mode: '0600'
      state: touch
      modification_time: preserve
      access_time: preserve
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-002355
    - NIST-800-171-3.1.12
    - NIST-800-53-AC-17(a)
    - NIST-800-53-CM-6(a)
    - NIST-800-53-CM-7(a)
    - NIST-800-53-CM-7(b)
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy
    - sshd_disable_compression

  - name: Find sshd_config included files
    ansible.builtin.shell: |-
      included_files=$(grep -oP "^\s*(?i)include.*" /etc/ssh/sshd_config | sed -e 's/\s*Include\s*//i' | sed -e 's|^[^/]|/etc/ssh/&|')
      [[ -n $included_files ]] && ls $included_files || true
    register: sshd_config_included_files
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - CJIS-5.5.6
    - DISA-STIG-OL09-00-002343
    - NIST-800-171-3.1.1
    - NIST-800-171-3.1.5
    - NIST-800-53-AC-17(a)
    - NIST-800-53-CM-6(a)
    - NIST-800-53-CM-7(a)
    - NIST-800-53-CM-7(b)
    - PCI-DSS-Req-2.2.4
    - PCI-DSSv4-2.2
    - PCI-DSSv4-2.2.6
    - high_severity
    - low_complexity
    - low_disruption
    - no_reboot_needed
    - restrict_strategy
    - sshd_disable_empty_passwords

  - name: Comment conf from included files
    ansible.builtin.replace:
      path: '{{ item }}'
      regexp: ^(\s*PermitEmptyPasswords.*)$
      replace: '# \1'
    loop: '{{ sshd_config_included_files.stdout_lines }}'
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - CJIS-5.5.6
    - DISA-STIG-OL09-00-002343
    - NIST-800-171-3.1.1
    - NIST-800-171-3.1.5
    - NIST-800-53-AC-17(a)
    - NIST-800-53-CM-6(a)
    - NIST-800-53-CM-7(a)
    - NIST-800-53-CM-7(b)
    - PCI-DSS-Req-2.2.4
    - PCI-DSSv4-2.2
    - PCI-DSSv4-2.2.6
    - high_severity
    - low_complexity
    - low_disruption
    - no_reboot_needed
    - restrict_strategy
    - sshd_disable_empty_passwords

  - name: Disable SSH Access via Empty Passwords - Check if the parameter PermitEmptyPasswords
      is configured
    ansible.builtin.find:
      paths:
      - /etc/ssh/sshd_config
      - /etc/ssh/sshd_config.d
      contains: (?i)^\s*{{ "PermitEmptyPasswords"| regex_escape }}\s+
    register: _sshd_config_has_parameter
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - CJIS-5.5.6
    - DISA-STIG-OL09-00-002343
    - NIST-800-171-3.1.1
    - NIST-800-171-3.1.5
    - NIST-800-53-AC-17(a)
    - NIST-800-53-CM-6(a)
    - NIST-800-53-CM-7(a)
    - NIST-800-53-CM-7(b)
    - PCI-DSS-Req-2.2.4
    - PCI-DSSv4-2.2
    - PCI-DSSv4-2.2.6
    - high_severity
    - low_complexity
    - low_disruption
    - no_reboot_needed
    - restrict_strategy
    - sshd_disable_empty_passwords

  - name: Disable SSH Access via Empty Passwords - Check if the parameter PermitEmptyPasswords
      is configured correctly
    ansible.builtin.find:
      paths:
      - /etc/ssh/sshd_config
      - /etc/ssh/sshd_config.d
      contains: (?i)^\s*{{ "PermitEmptyPasswords"| regex_escape }}\s+no$
    register: _sshd_config_correctly
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - CJIS-5.5.6
    - DISA-STIG-OL09-00-002343
    - NIST-800-171-3.1.1
    - NIST-800-171-3.1.5
    - NIST-800-53-AC-17(a)
    - NIST-800-53-CM-6(a)
    - NIST-800-53-CM-7(a)
    - NIST-800-53-CM-7(b)
    - PCI-DSS-Req-2.2.4
    - PCI-DSSv4-2.2
    - PCI-DSSv4-2.2.6
    - high_severity
    - low_complexity
    - low_disruption
    - no_reboot_needed
    - restrict_strategy
    - sshd_disable_empty_passwords

  - name: Disable SSH Access via Empty Passwords
    block:

    - name: Deduplicate values from /etc/ssh/sshd_config
      ansible.builtin.lineinfile:
        path: /etc/ssh/sshd_config
        create: false
        regexp: (?i)(?i)^\s*{{ "PermitEmptyPasswords"| regex_escape }}\s+
        state: absent

    - name: Check if /etc/ssh/sshd_config.d exists
      ansible.builtin.stat:
        path: /etc/ssh/sshd_config.d
      register: _etc_ssh_sshd_config_d_exists

    - name: Check if the parameter PermitEmptyPasswords is present in /etc/ssh/sshd_config.d
      ansible.builtin.find:
        paths: /etc/ssh/sshd_config.d
        recurse: 'yes'
        follow: 'no'
        contains: (?i)^\s*{{ "PermitEmptyPasswords"| regex_escape }}\s+
      register: _etc_ssh_sshd_config_d_has_parameter
      when: _etc_ssh_sshd_config_d_exists.stat.isdir is defined and _etc_ssh_sshd_config_d_exists.stat.isdir

    - name: Remove parameter from files in /etc/ssh/sshd_config.d
      ansible.builtin.lineinfile:
        path: '{{ item.path }}'
        create: false
        regexp: (?i)(?i)^\s*{{ "PermitEmptyPasswords"| regex_escape }}\s+
        state: absent
      with_items: '{{ _etc_ssh_sshd_config_d_has_parameter.files }}'
      when: _etc_ssh_sshd_config_d_has_parameter.matched > 0

    - name: Insert correct line to /etc/ssh/sshd_config.d/01-complianceascode-reinforce-os-defaults.conf
      ansible.builtin.lineinfile:
        path: /etc/ssh/sshd_config.d/01-complianceascode-reinforce-os-defaults.conf
        create: true
        regexp: (?i)(?i)^\s*{{ "PermitEmptyPasswords"| regex_escape }}\s+
        line: PermitEmptyPasswords no
        state: present
        insertbefore: BOF
        validate: /usr/sbin/sshd -t -f %s
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - _sshd_config_correctly.matched == 0 or _sshd_config_has_parameter.matched !=
      1
    tags:
    - CJIS-5.5.6
    - DISA-STIG-OL09-00-002343
    - NIST-800-171-3.1.1
    - NIST-800-171-3.1.5
    - NIST-800-53-AC-17(a)
    - NIST-800-53-CM-6(a)
    - NIST-800-53-CM-7(a)
    - NIST-800-53-CM-7(b)
    - PCI-DSS-Req-2.2.4
    - PCI-DSSv4-2.2
    - PCI-DSSv4-2.2.6
    - high_severity
    - low_complexity
    - low_disruption
    - no_reboot_needed
    - restrict_strategy
    - sshd_disable_empty_passwords

  - name: Disable SSH Access via Empty Passwords - set file mode for /etc/ssh/sshd_config.d/01-complianceascode-reinforce-os-defaults.conf
    ansible.builtin.file:
      path: /etc/ssh/sshd_config.d/01-complianceascode-reinforce-os-defaults.conf
      mode: '0600'
      state: touch
      modification_time: preserve
      access_time: preserve
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - CJIS-5.5.6
    - DISA-STIG-OL09-00-002343
    - NIST-800-171-3.1.1
    - NIST-800-171-3.1.5
    - NIST-800-53-AC-17(a)
    - NIST-800-53-CM-6(a)
    - NIST-800-53-CM-7(a)
    - NIST-800-53-CM-7(b)
    - PCI-DSS-Req-2.2.4
    - PCI-DSSv4-2.2
    - PCI-DSSv4-2.2.6
    - high_severity
    - low_complexity
    - low_disruption
    - no_reboot_needed
    - restrict_strategy
    - sshd_disable_empty_passwords

  - name: Find sshd_config included files
    ansible.builtin.shell: |-
      included_files=$(grep -oP "^\s*(?i)include.*" /etc/ssh/sshd_config | sed -e 's/\s*Include\s*//i' | sed -e 's|^[^/]|/etc/ssh/&|')
      [[ -n $included_files ]] && ls $included_files || true
    register: sshd_config_included_files
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-002341
    - NIST-800-171-3.1.12
    - NIST-800-53-AC-17(a)
    - NIST-800-53-CM-6(a)
    - NIST-800-53-CM-7(a)
    - NIST-800-53-CM-7(b)
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy
    - sshd_disable_gssapi_auth

  - name: Comment conf from included files
    ansible.builtin.replace:
      path: '{{ item }}'
      regexp: ^(\s*GSSAPIAuthentication.*)$
      replace: '# \1'
    loop: '{{ sshd_config_included_files.stdout_lines }}'
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-002341
    - NIST-800-171-3.1.12
    - NIST-800-53-AC-17(a)
    - NIST-800-53-CM-6(a)
    - NIST-800-53-CM-7(a)
    - NIST-800-53-CM-7(b)
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy
    - sshd_disable_gssapi_auth

  - name: Disable GSSAPI Authentication - Check if the parameter GSSAPIAuthentication
      is configured
    ansible.builtin.find:
      paths:
      - /etc/ssh/sshd_config
      - /etc/ssh/sshd_config.d
      contains: (?i)^\s*{{ "GSSAPIAuthentication"| regex_escape }}\s+
    register: _sshd_config_has_parameter
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-002341
    - NIST-800-171-3.1.12
    - NIST-800-53-AC-17(a)
    - NIST-800-53-CM-6(a)
    - NIST-800-53-CM-7(a)
    - NIST-800-53-CM-7(b)
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy
    - sshd_disable_gssapi_auth

  - name: Disable GSSAPI Authentication - Check if the parameter GSSAPIAuthentication
      is configured correctly
    ansible.builtin.find:
      paths:
      - /etc/ssh/sshd_config
      - /etc/ssh/sshd_config.d
      contains: (?i)^\s*{{ "GSSAPIAuthentication"| regex_escape }}\s+no$
    register: _sshd_config_correctly
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-002341
    - NIST-800-171-3.1.12
    - NIST-800-53-AC-17(a)
    - NIST-800-53-CM-6(a)
    - NIST-800-53-CM-7(a)
    - NIST-800-53-CM-7(b)
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy
    - sshd_disable_gssapi_auth

  - name: Disable GSSAPI Authentication
    block:

    - name: Deduplicate values from /etc/ssh/sshd_config
      ansible.builtin.lineinfile:
        path: /etc/ssh/sshd_config
        create: false
        regexp: (?i)(?i)^\s*{{ "GSSAPIAuthentication"| regex_escape }}\s+
        state: absent

    - name: Check if /etc/ssh/sshd_config.d exists
      ansible.builtin.stat:
        path: /etc/ssh/sshd_config.d
      register: _etc_ssh_sshd_config_d_exists

    - name: Check if the parameter GSSAPIAuthentication is present in /etc/ssh/sshd_config.d
      ansible.builtin.find:
        paths: /etc/ssh/sshd_config.d
        recurse: 'yes'
        follow: 'no'
        contains: (?i)^\s*{{ "GSSAPIAuthentication"| regex_escape }}\s+
      register: _etc_ssh_sshd_config_d_has_parameter
      when: _etc_ssh_sshd_config_d_exists.stat.isdir is defined and _etc_ssh_sshd_config_d_exists.stat.isdir

    - name: Remove parameter from files in /etc/ssh/sshd_config.d
      ansible.builtin.lineinfile:
        path: '{{ item.path }}'
        create: false
        regexp: (?i)(?i)^\s*{{ "GSSAPIAuthentication"| regex_escape }}\s+
        state: absent
      with_items: '{{ _etc_ssh_sshd_config_d_has_parameter.files }}'
      when: _etc_ssh_sshd_config_d_has_parameter.matched > 0

    - name: Insert correct line to /etc/ssh/sshd_config.d/01-complianceascode-reinforce-os-defaults.conf
      ansible.builtin.lineinfile:
        path: /etc/ssh/sshd_config.d/01-complianceascode-reinforce-os-defaults.conf
        create: true
        regexp: (?i)(?i)^\s*{{ "GSSAPIAuthentication"| regex_escape }}\s+
        line: GSSAPIAuthentication no
        state: present
        insertbefore: BOF
        validate: /usr/sbin/sshd -t -f %s
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - _sshd_config_correctly.matched == 0 or _sshd_config_has_parameter.matched !=
      1
    tags:
    - DISA-STIG-OL09-00-002341
    - NIST-800-171-3.1.12
    - NIST-800-53-AC-17(a)
    - NIST-800-53-CM-6(a)
    - NIST-800-53-CM-7(a)
    - NIST-800-53-CM-7(b)
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy
    - sshd_disable_gssapi_auth

  - name: Disable GSSAPI Authentication - set file mode for /etc/ssh/sshd_config.d/01-complianceascode-reinforce-os-defaults.conf
    ansible.builtin.file:
      path: /etc/ssh/sshd_config.d/01-complianceascode-reinforce-os-defaults.conf
      mode: '0600'
      state: touch
      modification_time: preserve
      access_time: preserve
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-002341
    - NIST-800-171-3.1.12
    - NIST-800-53-AC-17(a)
    - NIST-800-53-CM-6(a)
    - NIST-800-53-CM-7(a)
    - NIST-800-53-CM-7(b)
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy
    - sshd_disable_gssapi_auth

  - name: Find sshd_config included files
    ansible.builtin.shell: |-
      included_files=$(grep -oP "^\s*(?i)include.*" /etc/ssh/sshd_config | sed -e 's/\s*Include\s*//i' | sed -e 's|^[^/]|/etc/ssh/&|')
      [[ -n $included_files ]] && ls $included_files || true
    register: sshd_config_included_files
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-002356
    - NIST-800-171-3.1.12
    - NIST-800-53-AC-17(a)
    - NIST-800-53-CM-6(a)
    - NIST-800-53-CM-7(a)
    - NIST-800-53-CM-7(b)
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy
    - sshd_disable_kerb_auth

  - name: Comment conf from included files
    ansible.builtin.replace:
      path: '{{ item }}'
      regexp: ^(\s*KerberosAuthentication.*)$
      replace: '# \1'
    loop: '{{ sshd_config_included_files.stdout_lines }}'
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-002356
    - NIST-800-171-3.1.12
    - NIST-800-53-AC-17(a)
    - NIST-800-53-CM-6(a)
    - NIST-800-53-CM-7(a)
    - NIST-800-53-CM-7(b)
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy
    - sshd_disable_kerb_auth

  - name: Disable Kerberos Authentication - Check if the parameter KerberosAuthentication
      is configured
    ansible.builtin.find:
      paths:
      - /etc/ssh/sshd_config
      - /etc/ssh/sshd_config.d
      contains: (?i)^\s*{{ "KerberosAuthentication"| regex_escape }}\s+
    register: _sshd_config_has_parameter
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-002356
    - NIST-800-171-3.1.12
    - NIST-800-53-AC-17(a)
    - NIST-800-53-CM-6(a)
    - NIST-800-53-CM-7(a)
    - NIST-800-53-CM-7(b)
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy
    - sshd_disable_kerb_auth

  - name: Disable Kerberos Authentication - Check if the parameter KerberosAuthentication
      is configured correctly
    ansible.builtin.find:
      paths:
      - /etc/ssh/sshd_config
      - /etc/ssh/sshd_config.d
      contains: (?i)^\s*{{ "KerberosAuthentication"| regex_escape }}\s+no$
    register: _sshd_config_correctly
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-002356
    - NIST-800-171-3.1.12
    - NIST-800-53-AC-17(a)
    - NIST-800-53-CM-6(a)
    - NIST-800-53-CM-7(a)
    - NIST-800-53-CM-7(b)
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy
    - sshd_disable_kerb_auth

  - name: Disable Kerberos Authentication
    block:

    - name: Deduplicate values from /etc/ssh/sshd_config
      ansible.builtin.lineinfile:
        path: /etc/ssh/sshd_config
        create: false
        regexp: (?i)(?i)^\s*{{ "KerberosAuthentication"| regex_escape }}\s+
        state: absent

    - name: Check if /etc/ssh/sshd_config.d exists
      ansible.builtin.stat:
        path: /etc/ssh/sshd_config.d
      register: _etc_ssh_sshd_config_d_exists

    - name: Check if the parameter KerberosAuthentication is present in /etc/ssh/sshd_config.d
      ansible.builtin.find:
        paths: /etc/ssh/sshd_config.d
        recurse: 'yes'
        follow: 'no'
        contains: (?i)^\s*{{ "KerberosAuthentication"| regex_escape }}\s+
      register: _etc_ssh_sshd_config_d_has_parameter
      when: _etc_ssh_sshd_config_d_exists.stat.isdir is defined and _etc_ssh_sshd_config_d_exists.stat.isdir

    - name: Remove parameter from files in /etc/ssh/sshd_config.d
      ansible.builtin.lineinfile:
        path: '{{ item.path }}'
        create: false
        regexp: (?i)(?i)^\s*{{ "KerberosAuthentication"| regex_escape }}\s+
        state: absent
      with_items: '{{ _etc_ssh_sshd_config_d_has_parameter.files }}'
      when: _etc_ssh_sshd_config_d_has_parameter.matched > 0

    - name: Insert correct line to /etc/ssh/sshd_config.d/01-complianceascode-reinforce-os-defaults.conf
      ansible.builtin.lineinfile:
        path: /etc/ssh/sshd_config.d/01-complianceascode-reinforce-os-defaults.conf
        create: true
        regexp: (?i)(?i)^\s*{{ "KerberosAuthentication"| regex_escape }}\s+
        line: KerberosAuthentication no
        state: present
        insertbefore: BOF
        validate: /usr/sbin/sshd -t -f %s
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - _sshd_config_correctly.matched == 0 or _sshd_config_has_parameter.matched !=
      1
    tags:
    - DISA-STIG-OL09-00-002356
    - NIST-800-171-3.1.12
    - NIST-800-53-AC-17(a)
    - NIST-800-53-CM-6(a)
    - NIST-800-53-CM-7(a)
    - NIST-800-53-CM-7(b)
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy
    - sshd_disable_kerb_auth

  - name: Disable Kerberos Authentication - set file mode for /etc/ssh/sshd_config.d/01-complianceascode-reinforce-os-defaults.conf
    ansible.builtin.file:
      path: /etc/ssh/sshd_config.d/01-complianceascode-reinforce-os-defaults.conf
      mode: '0600'
      state: touch
      modification_time: preserve
      access_time: preserve
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-002356
    - NIST-800-171-3.1.12
    - NIST-800-53-AC-17(a)
    - NIST-800-53-CM-6(a)
    - NIST-800-53-CM-7(a)
    - NIST-800-53-CM-7(b)
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy
    - sshd_disable_kerb_auth

  - name: Find sshd_config included files
    ansible.builtin.shell: |-
      included_files=$(grep -oP "^\s*(?i)include.*" /etc/ssh/sshd_config | sed -e 's/\s*Include\s*//i' | sed -e 's|^[^/]|/etc/ssh/&|')
      [[ -n $included_files ]] && ls $included_files || true
    register: sshd_config_included_files
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - CJIS-5.5.6
    - DISA-STIG-OL09-00-002348
    - NIST-800-171-3.1.12
    - NIST-800-53-AC-17(a)
    - NIST-800-53-CM-6(a)
    - NIST-800-53-CM-7(a)
    - NIST-800-53-CM-7(b)
    - PCI-DSSv4-2.2
    - PCI-DSSv4-2.2.6
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy
    - sshd_disable_rhosts

  - name: Comment conf from included files
    ansible.builtin.replace:
      path: '{{ item }}'
      regexp: ^(\s*IgnoreRhosts.*)$
      replace: '# \1'
    loop: '{{ sshd_config_included_files.stdout_lines }}'
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - CJIS-5.5.6
    - DISA-STIG-OL09-00-002348
    - NIST-800-171-3.1.12
    - NIST-800-53-AC-17(a)
    - NIST-800-53-CM-6(a)
    - NIST-800-53-CM-7(a)
    - NIST-800-53-CM-7(b)
    - PCI-DSSv4-2.2
    - PCI-DSSv4-2.2.6
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy
    - sshd_disable_rhosts

  - name: Disable SSH Support for .rhosts Files - Check if the parameter IgnoreRhosts
      is configured
    ansible.builtin.find:
      paths:
      - /etc/ssh/sshd_config
      - /etc/ssh/sshd_config.d
      contains: (?i)^\s*{{ "IgnoreRhosts"| regex_escape }}\s+
    register: _sshd_config_has_parameter
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - CJIS-5.5.6
    - DISA-STIG-OL09-00-002348
    - NIST-800-171-3.1.12
    - NIST-800-53-AC-17(a)
    - NIST-800-53-CM-6(a)
    - NIST-800-53-CM-7(a)
    - NIST-800-53-CM-7(b)
    - PCI-DSSv4-2.2
    - PCI-DSSv4-2.2.6
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy
    - sshd_disable_rhosts

  - name: Disable SSH Support for .rhosts Files - Check if the parameter IgnoreRhosts
      is configured correctly
    ansible.builtin.find:
      paths:
      - /etc/ssh/sshd_config
      - /etc/ssh/sshd_config.d
      contains: (?i)^\s*{{ "IgnoreRhosts"| regex_escape }}\s+yes$
    register: _sshd_config_correctly
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - CJIS-5.5.6
    - DISA-STIG-OL09-00-002348
    - NIST-800-171-3.1.12
    - NIST-800-53-AC-17(a)
    - NIST-800-53-CM-6(a)
    - NIST-800-53-CM-7(a)
    - NIST-800-53-CM-7(b)
    - PCI-DSSv4-2.2
    - PCI-DSSv4-2.2.6
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy
    - sshd_disable_rhosts

  - name: Disable SSH Support for .rhosts Files
    block:

    - name: Deduplicate values from /etc/ssh/sshd_config
      ansible.builtin.lineinfile:
        path: /etc/ssh/sshd_config
        create: false
        regexp: (?i)(?i)^\s*{{ "IgnoreRhosts"| regex_escape }}\s+
        state: absent

    - name: Check if /etc/ssh/sshd_config.d exists
      ansible.builtin.stat:
        path: /etc/ssh/sshd_config.d
      register: _etc_ssh_sshd_config_d_exists

    - name: Check if the parameter IgnoreRhosts is present in /etc/ssh/sshd_config.d
      ansible.builtin.find:
        paths: /etc/ssh/sshd_config.d
        recurse: 'yes'
        follow: 'no'
        contains: (?i)^\s*{{ "IgnoreRhosts"| regex_escape }}\s+
      register: _etc_ssh_sshd_config_d_has_parameter
      when: _etc_ssh_sshd_config_d_exists.stat.isdir is defined and _etc_ssh_sshd_config_d_exists.stat.isdir

    - name: Remove parameter from files in /etc/ssh/sshd_config.d
      ansible.builtin.lineinfile:
        path: '{{ item.path }}'
        create: false
        regexp: (?i)(?i)^\s*{{ "IgnoreRhosts"| regex_escape }}\s+
        state: absent
      with_items: '{{ _etc_ssh_sshd_config_d_has_parameter.files }}'
      when: _etc_ssh_sshd_config_d_has_parameter.matched > 0

    - name: Insert correct line to /etc/ssh/sshd_config.d/01-complianceascode-reinforce-os-defaults.conf
      ansible.builtin.lineinfile:
        path: /etc/ssh/sshd_config.d/01-complianceascode-reinforce-os-defaults.conf
        create: true
        regexp: (?i)(?i)^\s*{{ "IgnoreRhosts"| regex_escape }}\s+
        line: IgnoreRhosts yes
        state: present
        insertbefore: BOF
        validate: /usr/sbin/sshd -t -f %s
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - _sshd_config_correctly.matched == 0 or _sshd_config_has_parameter.matched !=
      1
    tags:
    - CJIS-5.5.6
    - DISA-STIG-OL09-00-002348
    - NIST-800-171-3.1.12
    - NIST-800-53-AC-17(a)
    - NIST-800-53-CM-6(a)
    - NIST-800-53-CM-7(a)
    - NIST-800-53-CM-7(b)
    - PCI-DSSv4-2.2
    - PCI-DSSv4-2.2.6
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy
    - sshd_disable_rhosts

  - name: Disable SSH Support for .rhosts Files - set file mode for /etc/ssh/sshd_config.d/01-complianceascode-reinforce-os-defaults.conf
    ansible.builtin.file:
      path: /etc/ssh/sshd_config.d/01-complianceascode-reinforce-os-defaults.conf
      mode: '0600'
      state: touch
      modification_time: preserve
      access_time: preserve
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - CJIS-5.5.6
    - DISA-STIG-OL09-00-002348
    - NIST-800-171-3.1.12
    - NIST-800-53-AC-17(a)
    - NIST-800-53-CM-6(a)
    - NIST-800-53-CM-7(a)
    - NIST-800-53-CM-7(b)
    - PCI-DSSv4-2.2
    - PCI-DSSv4-2.2.6
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy
    - sshd_disable_rhosts

  - name: Find sshd_config included files
    ansible.builtin.shell: |-
      included_files=$(grep -oP "^\s*(?i)include.*" /etc/ssh/sshd_config | sed -e 's/\s*Include\s*//i' | sed -e 's|^[^/]|/etc/ssh/&|')
      [[ -n $included_files ]] && ls $included_files || true
    register: sshd_config_included_files
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - CJIS-5.5.6
    - DISA-STIG-OL09-00-002345
    - NIST-800-171-3.1.1
    - NIST-800-171-3.1.5
    - NIST-800-53-AC-17(a)
    - NIST-800-53-AC-6(2)
    - NIST-800-53-CM-6(a)
    - NIST-800-53-CM-7(a)
    - NIST-800-53-CM-7(b)
    - NIST-800-53-IA-2
    - NIST-800-53-IA-2(5)
    - PCI-DSS-Req-2.2.4
    - PCI-DSSv4-2.2
    - PCI-DSSv4-2.2.6
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy
    - sshd_disable_root_login

  - name: Comment conf from included files
    ansible.builtin.replace:
      path: '{{ item }}'
      regexp: ^(\s*PermitRootLogin.*)$
      replace: '# \1'
    loop: '{{ sshd_config_included_files.stdout_lines }}'
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - CJIS-5.5.6
    - DISA-STIG-OL09-00-002345
    - NIST-800-171-3.1.1
    - NIST-800-171-3.1.5
    - NIST-800-53-AC-17(a)
    - NIST-800-53-AC-6(2)
    - NIST-800-53-CM-6(a)
    - NIST-800-53-CM-7(a)
    - NIST-800-53-CM-7(b)
    - NIST-800-53-IA-2
    - NIST-800-53-IA-2(5)
    - PCI-DSS-Req-2.2.4
    - PCI-DSSv4-2.2
    - PCI-DSSv4-2.2.6
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy
    - sshd_disable_root_login

  - name: Disable SSH Root Login - Check if the parameter PermitRootLogin is configured
    ansible.builtin.find:
      paths:
      - /etc/ssh/sshd_config
      - /etc/ssh/sshd_config.d
      contains: (?i)^\s*{{ "PermitRootLogin"| regex_escape }}\s+
    register: _sshd_config_has_parameter
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - CJIS-5.5.6
    - DISA-STIG-OL09-00-002345
    - NIST-800-171-3.1.1
    - NIST-800-171-3.1.5
    - NIST-800-53-AC-17(a)
    - NIST-800-53-AC-6(2)
    - NIST-800-53-CM-6(a)
    - NIST-800-53-CM-7(a)
    - NIST-800-53-CM-7(b)
    - NIST-800-53-IA-2
    - NIST-800-53-IA-2(5)
    - PCI-DSS-Req-2.2.4
    - PCI-DSSv4-2.2
    - PCI-DSSv4-2.2.6
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy
    - sshd_disable_root_login

  - name: Disable SSH Root Login - Check if the parameter PermitRootLogin is configured
      correctly
    ansible.builtin.find:
      paths:
      - /etc/ssh/sshd_config
      - /etc/ssh/sshd_config.d
      contains: (?i)^\s*{{ "PermitRootLogin"| regex_escape }}\s+no$
    register: _sshd_config_correctly
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - CJIS-5.5.6
    - DISA-STIG-OL09-00-002345
    - NIST-800-171-3.1.1
    - NIST-800-171-3.1.5
    - NIST-800-53-AC-17(a)
    - NIST-800-53-AC-6(2)
    - NIST-800-53-CM-6(a)
    - NIST-800-53-CM-7(a)
    - NIST-800-53-CM-7(b)
    - NIST-800-53-IA-2
    - NIST-800-53-IA-2(5)
    - PCI-DSS-Req-2.2.4
    - PCI-DSSv4-2.2
    - PCI-DSSv4-2.2.6
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy
    - sshd_disable_root_login

  - name: Disable SSH Root Login
    block:

    - name: Deduplicate values from /etc/ssh/sshd_config
      ansible.builtin.lineinfile:
        path: /etc/ssh/sshd_config
        create: false
        regexp: (?i)(?i)^\s*{{ "PermitRootLogin"| regex_escape }}\s+
        state: absent

    - name: Check if /etc/ssh/sshd_config.d exists
      ansible.builtin.stat:
        path: /etc/ssh/sshd_config.d
      register: _etc_ssh_sshd_config_d_exists

    - name: Check if the parameter PermitRootLogin is present in /etc/ssh/sshd_config.d
      ansible.builtin.find:
        paths: /etc/ssh/sshd_config.d
        recurse: 'yes'
        follow: 'no'
        contains: (?i)^\s*{{ "PermitRootLogin"| regex_escape }}\s+
      register: _etc_ssh_sshd_config_d_has_parameter
      when: _etc_ssh_sshd_config_d_exists.stat.isdir is defined and _etc_ssh_sshd_config_d_exists.stat.isdir

    - name: Remove parameter from files in /etc/ssh/sshd_config.d
      ansible.builtin.lineinfile:
        path: '{{ item.path }}'
        create: false
        regexp: (?i)(?i)^\s*{{ "PermitRootLogin"| regex_escape }}\s+
        state: absent
      with_items: '{{ _etc_ssh_sshd_config_d_has_parameter.files }}'
      when: _etc_ssh_sshd_config_d_has_parameter.matched > 0

    - name: Insert correct line to /etc/ssh/sshd_config.d/00-complianceascode-hardening.conf
      ansible.builtin.lineinfile:
        path: /etc/ssh/sshd_config.d/00-complianceascode-hardening.conf
        create: true
        regexp: (?i)(?i)^\s*{{ "PermitRootLogin"| regex_escape }}\s+
        line: PermitRootLogin no
        state: present
        insertbefore: BOF
        validate: /usr/sbin/sshd -t -f %s
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - _sshd_config_correctly.matched == 0 or _sshd_config_has_parameter.matched !=
      1
    tags:
    - CJIS-5.5.6
    - DISA-STIG-OL09-00-002345
    - NIST-800-171-3.1.1
    - NIST-800-171-3.1.5
    - NIST-800-53-AC-17(a)
    - NIST-800-53-AC-6(2)
    - NIST-800-53-CM-6(a)
    - NIST-800-53-CM-7(a)
    - NIST-800-53-CM-7(b)
    - NIST-800-53-IA-2
    - NIST-800-53-IA-2(5)
    - PCI-DSS-Req-2.2.4
    - PCI-DSSv4-2.2
    - PCI-DSSv4-2.2.6
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy
    - sshd_disable_root_login

  - name: Disable SSH Root Login - set file mode for /etc/ssh/sshd_config.d/00-complianceascode-hardening.conf
    ansible.builtin.file:
      path: /etc/ssh/sshd_config.d/00-complianceascode-hardening.conf
      mode: '0600'
      state: touch
      modification_time: preserve
      access_time: preserve
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - CJIS-5.5.6
    - DISA-STIG-OL09-00-002345
    - NIST-800-171-3.1.1
    - NIST-800-171-3.1.5
    - NIST-800-53-AC-17(a)
    - NIST-800-53-AC-6(2)
    - NIST-800-53-CM-6(a)
    - NIST-800-53-CM-7(a)
    - NIST-800-53-CM-7(b)
    - NIST-800-53-IA-2
    - NIST-800-53-IA-2(5)
    - PCI-DSS-Req-2.2.4
    - PCI-DSSv4-2.2
    - PCI-DSSv4-2.2.6
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy
    - sshd_disable_root_login

  - name: Find sshd_config included files
    ansible.builtin.shell: |-
      included_files=$(grep -oP "^\s*(?i)include.*" /etc/ssh/sshd_config | sed -e 's/\s*Include\s*//i' | sed -e 's|^[^/]|/etc/ssh/&|')
      [[ -n $included_files ]] && ls $included_files || true
    register: sshd_config_included_files
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-002349
    - NIST-800-171-3.1.12
    - NIST-800-53-AC-17(a)
    - NIST-800-53-CM-6(a)
    - NIST-800-53-CM-7(a)
    - NIST-800-53-CM-7(b)
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy
    - sshd_disable_user_known_hosts

  - name: Comment conf from included files
    ansible.builtin.replace:
      path: '{{ item }}'
      regexp: ^(\s*IgnoreUserKnownHosts.*)$
      replace: '# \1'
    loop: '{{ sshd_config_included_files.stdout_lines }}'
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-002349
    - NIST-800-171-3.1.12
    - NIST-800-53-AC-17(a)
    - NIST-800-53-CM-6(a)
    - NIST-800-53-CM-7(a)
    - NIST-800-53-CM-7(b)
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy
    - sshd_disable_user_known_hosts

  - name: Disable SSH Support for User Known Hosts - Check if the parameter IgnoreUserKnownHosts
      is configured
    ansible.builtin.find:
      paths:
      - /etc/ssh/sshd_config
      - /etc/ssh/sshd_config.d
      contains: (?i)^\s*{{ "IgnoreUserKnownHosts"| regex_escape }}\s+
    register: _sshd_config_has_parameter
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-002349
    - NIST-800-171-3.1.12
    - NIST-800-53-AC-17(a)
    - NIST-800-53-CM-6(a)
    - NIST-800-53-CM-7(a)
    - NIST-800-53-CM-7(b)
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy
    - sshd_disable_user_known_hosts

  - name: Disable SSH Support for User Known Hosts - Check if the parameter IgnoreUserKnownHosts
      is configured correctly
    ansible.builtin.find:
      paths:
      - /etc/ssh/sshd_config
      - /etc/ssh/sshd_config.d
      contains: (?i)^\s*{{ "IgnoreUserKnownHosts"| regex_escape }}\s+yes$
    register: _sshd_config_correctly
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-002349
    - NIST-800-171-3.1.12
    - NIST-800-53-AC-17(a)
    - NIST-800-53-CM-6(a)
    - NIST-800-53-CM-7(a)
    - NIST-800-53-CM-7(b)
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy
    - sshd_disable_user_known_hosts

  - name: Disable SSH Support for User Known Hosts
    block:

    - name: Deduplicate values from /etc/ssh/sshd_config
      ansible.builtin.lineinfile:
        path: /etc/ssh/sshd_config
        create: false
        regexp: (?i)(?i)^\s*{{ "IgnoreUserKnownHosts"| regex_escape }}\s+
        state: absent

    - name: Check if /etc/ssh/sshd_config.d exists
      ansible.builtin.stat:
        path: /etc/ssh/sshd_config.d
      register: _etc_ssh_sshd_config_d_exists

    - name: Check if the parameter IgnoreUserKnownHosts is present in /etc/ssh/sshd_config.d
      ansible.builtin.find:
        paths: /etc/ssh/sshd_config.d
        recurse: 'yes'
        follow: 'no'
        contains: (?i)^\s*{{ "IgnoreUserKnownHosts"| regex_escape }}\s+
      register: _etc_ssh_sshd_config_d_has_parameter
      when: _etc_ssh_sshd_config_d_exists.stat.isdir is defined and _etc_ssh_sshd_config_d_exists.stat.isdir

    - name: Remove parameter from files in /etc/ssh/sshd_config.d
      ansible.builtin.lineinfile:
        path: '{{ item.path }}'
        create: false
        regexp: (?i)(?i)^\s*{{ "IgnoreUserKnownHosts"| regex_escape }}\s+
        state: absent
      with_items: '{{ _etc_ssh_sshd_config_d_has_parameter.files }}'
      when: _etc_ssh_sshd_config_d_has_parameter.matched > 0

    - name: Insert correct line to /etc/ssh/sshd_config.d/00-complianceascode-hardening.conf
      ansible.builtin.lineinfile:
        path: /etc/ssh/sshd_config.d/00-complianceascode-hardening.conf
        create: true
        regexp: (?i)(?i)^\s*{{ "IgnoreUserKnownHosts"| regex_escape }}\s+
        line: IgnoreUserKnownHosts yes
        state: present
        insertbefore: BOF
        validate: /usr/sbin/sshd -t -f %s
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - _sshd_config_correctly.matched == 0 or _sshd_config_has_parameter.matched !=
      1
    tags:
    - DISA-STIG-OL09-00-002349
    - NIST-800-171-3.1.12
    - NIST-800-53-AC-17(a)
    - NIST-800-53-CM-6(a)
    - NIST-800-53-CM-7(a)
    - NIST-800-53-CM-7(b)
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy
    - sshd_disable_user_known_hosts

  - name: Disable SSH Support for User Known Hosts - set file mode for /etc/ssh/sshd_config.d/00-complianceascode-hardening.conf
    ansible.builtin.file:
      path: /etc/ssh/sshd_config.d/00-complianceascode-hardening.conf
      mode: '0600'
      state: touch
      modification_time: preserve
      access_time: preserve
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-002349
    - NIST-800-171-3.1.12
    - NIST-800-53-AC-17(a)
    - NIST-800-53-CM-6(a)
    - NIST-800-53-CM-7(a)
    - NIST-800-53-CM-7(b)
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy
    - sshd_disable_user_known_hosts

  - name: Find sshd_config included files
    ansible.builtin.shell: |-
      included_files=$(grep -oP "^\s*(?i)include.*" /etc/ssh/sshd_config | sed -e 's/\s*Include\s*//i' | sed -e 's|^[^/]|/etc/ssh/&|')
      [[ -n $included_files ]] && ls $included_files || true
    register: sshd_config_included_files
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-002350
    - NIST-800-53-CM-6(b)
    - PCI-DSSv4-2.2
    - PCI-DSSv4-2.2.6
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy
    - sshd_disable_x11_forwarding

  - name: Comment conf from included files
    ansible.builtin.replace:
      path: '{{ item }}'
      regexp: ^(\s*X11Forwarding.*)$
      replace: '# \1'
    loop: '{{ sshd_config_included_files.stdout_lines }}'
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-002350
    - NIST-800-53-CM-6(b)
    - PCI-DSSv4-2.2
    - PCI-DSSv4-2.2.6
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy
    - sshd_disable_x11_forwarding

  - name: Disable X11 Forwarding - Check if the parameter X11Forwarding is configured
    ansible.builtin.find:
      paths:
      - /etc/ssh/sshd_config
      - /etc/ssh/sshd_config.d
      contains: (?i)^\s*{{ "X11Forwarding"| regex_escape }}\s+
    register: _sshd_config_has_parameter
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-002350
    - NIST-800-53-CM-6(b)
    - PCI-DSSv4-2.2
    - PCI-DSSv4-2.2.6
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy
    - sshd_disable_x11_forwarding

  - name: Disable X11 Forwarding - Check if the parameter X11Forwarding is configured
      correctly
    ansible.builtin.find:
      paths:
      - /etc/ssh/sshd_config
      - /etc/ssh/sshd_config.d
      contains: (?i)^\s*{{ "X11Forwarding"| regex_escape }}\s+no$
    register: _sshd_config_correctly
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-002350
    - NIST-800-53-CM-6(b)
    - PCI-DSSv4-2.2
    - PCI-DSSv4-2.2.6
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy
    - sshd_disable_x11_forwarding

  - name: Disable X11 Forwarding
    block:

    - name: Deduplicate values from /etc/ssh/sshd_config
      ansible.builtin.lineinfile:
        path: /etc/ssh/sshd_config
        create: false
        regexp: (?i)(?i)^\s*{{ "X11Forwarding"| regex_escape }}\s+
        state: absent

    - name: Check if /etc/ssh/sshd_config.d exists
      ansible.builtin.stat:
        path: /etc/ssh/sshd_config.d
      register: _etc_ssh_sshd_config_d_exists

    - name: Check if the parameter X11Forwarding is present in /etc/ssh/sshd_config.d
      ansible.builtin.find:
        paths: /etc/ssh/sshd_config.d
        recurse: 'yes'
        follow: 'no'
        contains: (?i)^\s*{{ "X11Forwarding"| regex_escape }}\s+
      register: _etc_ssh_sshd_config_d_has_parameter
      when: _etc_ssh_sshd_config_d_exists.stat.isdir is defined and _etc_ssh_sshd_config_d_exists.stat.isdir

    - name: Remove parameter from files in /etc/ssh/sshd_config.d
      ansible.builtin.lineinfile:
        path: '{{ item.path }}'
        create: false
        regexp: (?i)(?i)^\s*{{ "X11Forwarding"| regex_escape }}\s+
        state: absent
      with_items: '{{ _etc_ssh_sshd_config_d_has_parameter.files }}'
      when: _etc_ssh_sshd_config_d_has_parameter.matched > 0

    - name: Insert correct line to /etc/ssh/sshd_config.d/01-complianceascode-reinforce-os-defaults.conf
      ansible.builtin.lineinfile:
        path: /etc/ssh/sshd_config.d/01-complianceascode-reinforce-os-defaults.conf
        create: true
        regexp: (?i)(?i)^\s*{{ "X11Forwarding"| regex_escape }}\s+
        line: X11Forwarding no
        state: present
        insertbefore: BOF
        validate: /usr/sbin/sshd -t -f %s
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - _sshd_config_correctly.matched == 0 or _sshd_config_has_parameter.matched !=
      1
    tags:
    - DISA-STIG-OL09-00-002350
    - NIST-800-53-CM-6(b)
    - PCI-DSSv4-2.2
    - PCI-DSSv4-2.2.6
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy
    - sshd_disable_x11_forwarding

  - name: Disable X11 Forwarding - set file mode for /etc/ssh/sshd_config.d/01-complianceascode-reinforce-os-defaults.conf
    ansible.builtin.file:
      path: /etc/ssh/sshd_config.d/01-complianceascode-reinforce-os-defaults.conf
      mode: '0600'
      state: touch
      modification_time: preserve
      access_time: preserve
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-002350
    - NIST-800-53-CM-6(b)
    - PCI-DSSv4-2.2
    - PCI-DSSv4-2.2.6
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy
    - sshd_disable_x11_forwarding

  - name: Find sshd_config included files
    ansible.builtin.shell: |-
      included_files=$(grep -oP "^\s*(?i)include.*" /etc/ssh/sshd_config | sed -e 's/\s*Include\s*//i' | sed -e 's|^[^/]|/etc/ssh/&|')
      [[ -n $included_files ]] && ls $included_files || true
    register: sshd_config_included_files
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - CJIS-5.5.6
    - DISA-STIG-OL09-00-002358
    - NIST-800-171-3.1.12
    - NIST-800-53-AC-17(a)
    - NIST-800-53-CM-6(a)
    - NIST-800-53-CM-7(a)
    - NIST-800-53-CM-7(b)
    - PCI-DSS-Req-2.2.4
    - PCI-DSSv4-2.2
    - PCI-DSSv4-2.2.6
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy
    - sshd_do_not_permit_user_env

  - name: Comment conf from included files
    ansible.builtin.replace:
      path: '{{ item }}'
      regexp: ^(\s*PermitUserEnvironment.*)$
      replace: '# \1'
    loop: '{{ sshd_config_included_files.stdout_lines }}'
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - CJIS-5.5.6
    - DISA-STIG-OL09-00-002358
    - NIST-800-171-3.1.12
    - NIST-800-53-AC-17(a)
    - NIST-800-53-CM-6(a)
    - NIST-800-53-CM-7(a)
    - NIST-800-53-CM-7(b)
    - PCI-DSS-Req-2.2.4
    - PCI-DSSv4-2.2
    - PCI-DSSv4-2.2.6
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy
    - sshd_do_not_permit_user_env

  - name: Do Not Allow SSH Environment Options - Check if the parameter PermitUserEnvironment
      is configured
    ansible.builtin.find:
      paths:
      - /etc/ssh/sshd_config
      - /etc/ssh/sshd_config.d
      contains: (?i)^\s*{{ "PermitUserEnvironment"| regex_escape }}\s+
    register: _sshd_config_has_parameter
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - CJIS-5.5.6
    - DISA-STIG-OL09-00-002358
    - NIST-800-171-3.1.12
    - NIST-800-53-AC-17(a)
    - NIST-800-53-CM-6(a)
    - NIST-800-53-CM-7(a)
    - NIST-800-53-CM-7(b)
    - PCI-DSS-Req-2.2.4
    - PCI-DSSv4-2.2
    - PCI-DSSv4-2.2.6
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy
    - sshd_do_not_permit_user_env

  - name: Do Not Allow SSH Environment Options - Check if the parameter PermitUserEnvironment
      is configured correctly
    ansible.builtin.find:
      paths:
      - /etc/ssh/sshd_config
      - /etc/ssh/sshd_config.d
      contains: (?i)^\s*{{ "PermitUserEnvironment"| regex_escape }}\s+no$
    register: _sshd_config_correctly
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - CJIS-5.5.6
    - DISA-STIG-OL09-00-002358
    - NIST-800-171-3.1.12
    - NIST-800-53-AC-17(a)
    - NIST-800-53-CM-6(a)
    - NIST-800-53-CM-7(a)
    - NIST-800-53-CM-7(b)
    - PCI-DSS-Req-2.2.4
    - PCI-DSSv4-2.2
    - PCI-DSSv4-2.2.6
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy
    - sshd_do_not_permit_user_env

  - name: Do Not Allow SSH Environment Options
    block:

    - name: Deduplicate values from /etc/ssh/sshd_config
      ansible.builtin.lineinfile:
        path: /etc/ssh/sshd_config
        create: false
        regexp: (?i)(?i)^\s*{{ "PermitUserEnvironment"| regex_escape }}\s+
        state: absent

    - name: Check if /etc/ssh/sshd_config.d exists
      ansible.builtin.stat:
        path: /etc/ssh/sshd_config.d
      register: _etc_ssh_sshd_config_d_exists

    - name: Check if the parameter PermitUserEnvironment is present in /etc/ssh/sshd_config.d
      ansible.builtin.find:
        paths: /etc/ssh/sshd_config.d
        recurse: 'yes'
        follow: 'no'
        contains: (?i)^\s*{{ "PermitUserEnvironment"| regex_escape }}\s+
      register: _etc_ssh_sshd_config_d_has_parameter
      when: _etc_ssh_sshd_config_d_exists.stat.isdir is defined and _etc_ssh_sshd_config_d_exists.stat.isdir

    - name: Remove parameter from files in /etc/ssh/sshd_config.d
      ansible.builtin.lineinfile:
        path: '{{ item.path }}'
        create: false
        regexp: (?i)(?i)^\s*{{ "PermitUserEnvironment"| regex_escape }}\s+
        state: absent
      with_items: '{{ _etc_ssh_sshd_config_d_has_parameter.files }}'
      when: _etc_ssh_sshd_config_d_has_parameter.matched > 0

    - name: Insert correct line to /etc/ssh/sshd_config.d/01-complianceascode-reinforce-os-defaults.conf
      ansible.builtin.lineinfile:
        path: /etc/ssh/sshd_config.d/01-complianceascode-reinforce-os-defaults.conf
        create: true
        regexp: (?i)(?i)^\s*{{ "PermitUserEnvironment"| regex_escape }}\s+
        line: PermitUserEnvironment no
        state: present
        insertbefore: BOF
        validate: /usr/sbin/sshd -t -f %s
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - _sshd_config_correctly.matched == 0 or _sshd_config_has_parameter.matched !=
      1
    tags:
    - CJIS-5.5.6
    - DISA-STIG-OL09-00-002358
    - NIST-800-171-3.1.12
    - NIST-800-53-AC-17(a)
    - NIST-800-53-CM-6(a)
    - NIST-800-53-CM-7(a)
    - NIST-800-53-CM-7(b)
    - PCI-DSS-Req-2.2.4
    - PCI-DSSv4-2.2
    - PCI-DSSv4-2.2.6
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy
    - sshd_do_not_permit_user_env

  - name: Do Not Allow SSH Environment Options - set file mode for /etc/ssh/sshd_config.d/01-complianceascode-reinforce-os-defaults.conf
    ansible.builtin.file:
      path: /etc/ssh/sshd_config.d/01-complianceascode-reinforce-os-defaults.conf
      mode: '0600'
      state: touch
      modification_time: preserve
      access_time: preserve
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - CJIS-5.5.6
    - DISA-STIG-OL09-00-002358
    - NIST-800-171-3.1.12
    - NIST-800-53-AC-17(a)
    - NIST-800-53-CM-6(a)
    - NIST-800-53-CM-7(a)
    - NIST-800-53-CM-7(b)
    - PCI-DSS-Req-2.2.4
    - PCI-DSSv4-2.2
    - PCI-DSSv4-2.2.6
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy
    - sshd_do_not_permit_user_env

  - name: Find sshd_config included files
    ansible.builtin.shell: |-
      included_files=$(grep -oP "^\s*(?i)include.*" /etc/ssh/sshd_config | sed -e 's/\s*Include\s*//i' | sed -e 's|^[^/]|/etc/ssh/&|')
      [[ -n $included_files ]] && ls $included_files || true
    register: sshd_config_included_files
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-002344
    - PCI-DSSv4-2.2
    - PCI-DSSv4-2.2.6
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy
    - sshd_enable_pam

  - name: Comment conf from included files
    ansible.builtin.replace:
      path: '{{ item }}'
      regexp: ^(\s*UsePAM.*)$
      replace: '# \1'
    loop: '{{ sshd_config_included_files.stdout_lines }}'
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-002344
    - PCI-DSSv4-2.2
    - PCI-DSSv4-2.2.6
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy
    - sshd_enable_pam

  - name: Enable PAM - Check if the parameter UsePAM is configured
    ansible.builtin.find:
      paths:
      - /etc/ssh/sshd_config
      - /etc/ssh/sshd_config.d
      contains: (?i)^\s*{{ "UsePAM"| regex_escape }}\s+
    register: _sshd_config_has_parameter
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-002344
    - PCI-DSSv4-2.2
    - PCI-DSSv4-2.2.6
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy
    - sshd_enable_pam

  - name: Enable PAM - Check if the parameter UsePAM is configured correctly
    ansible.builtin.find:
      paths:
      - /etc/ssh/sshd_config
      - /etc/ssh/sshd_config.d
      contains: (?i)^\s*{{ "UsePAM"| regex_escape }}\s+yes$
    register: _sshd_config_correctly
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-002344
    - PCI-DSSv4-2.2
    - PCI-DSSv4-2.2.6
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy
    - sshd_enable_pam

  - name: Enable PAM
    block:

    - name: Deduplicate values from /etc/ssh/sshd_config
      ansible.builtin.lineinfile:
        path: /etc/ssh/sshd_config
        create: false
        regexp: (?i)(?i)^\s*{{ "UsePAM"| regex_escape }}\s+
        state: absent

    - name: Check if /etc/ssh/sshd_config.d exists
      ansible.builtin.stat:
        path: /etc/ssh/sshd_config.d
      register: _etc_ssh_sshd_config_d_exists

    - name: Check if the parameter UsePAM is present in /etc/ssh/sshd_config.d
      ansible.builtin.find:
        paths: /etc/ssh/sshd_config.d
        recurse: 'yes'
        follow: 'no'
        contains: (?i)^\s*{{ "UsePAM"| regex_escape }}\s+
      register: _etc_ssh_sshd_config_d_has_parameter
      when: _etc_ssh_sshd_config_d_exists.stat.isdir is defined and _etc_ssh_sshd_config_d_exists.stat.isdir

    - name: Remove parameter from files in /etc/ssh/sshd_config.d
      ansible.builtin.lineinfile:
        path: '{{ item.path }}'
        create: false
        regexp: (?i)(?i)^\s*{{ "UsePAM"| regex_escape }}\s+
        state: absent
      with_items: '{{ _etc_ssh_sshd_config_d_has_parameter.files }}'
      when: _etc_ssh_sshd_config_d_has_parameter.matched > 0

    - name: Insert correct line to /etc/ssh/sshd_config.d/00-complianceascode-hardening.conf
      ansible.builtin.lineinfile:
        path: /etc/ssh/sshd_config.d/00-complianceascode-hardening.conf
        create: true
        regexp: (?i)(?i)^\s*{{ "UsePAM"| regex_escape }}\s+
        line: UsePAM yes
        state: present
        insertbefore: BOF
        validate: /usr/sbin/sshd -t -f %s
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - _sshd_config_correctly.matched == 0 or _sshd_config_has_parameter.matched !=
      1
    tags:
    - DISA-STIG-OL09-00-002344
    - PCI-DSSv4-2.2
    - PCI-DSSv4-2.2.6
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy
    - sshd_enable_pam

  - name: Enable PAM - set file mode for /etc/ssh/sshd_config.d/00-complianceascode-hardening.conf
    ansible.builtin.file:
      path: /etc/ssh/sshd_config.d/00-complianceascode-hardening.conf
      mode: '0600'
      state: touch
      modification_time: preserve
      access_time: preserve
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-002344
    - PCI-DSSv4-2.2
    - PCI-DSSv4-2.2.6
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy
    - sshd_enable_pam

  - name: Find sshd_config included files
    ansible.builtin.shell: |-
      included_files=$(grep -oP "^\s*(?i)include.*" /etc/ssh/sshd_config | sed -e 's/\s*Include\s*//i' | sed -e 's|^[^/]|/etc/ssh/&|')
      [[ -n $included_files ]] && ls $included_files || true
    register: sshd_config_included_files
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-002359
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy
    - sshd_enable_pubkey_auth

  - name: Comment conf from included files
    ansible.builtin.replace:
      path: '{{ item }}'
      regexp: ^(\s*PubkeyAuthentication.*)$
      replace: '# \1'
    loop: '{{ sshd_config_included_files.stdout_lines }}'
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-002359
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy
    - sshd_enable_pubkey_auth

  - name: Enable Public Key Authentication - Check if the parameter PubkeyAuthentication
      is configured
    ansible.builtin.find:
      paths:
      - /etc/ssh/sshd_config
      - /etc/ssh/sshd_config.d
      contains: (?i)^\s*{{ "PubkeyAuthentication"| regex_escape }}\s+
    register: _sshd_config_has_parameter
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-002359
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy
    - sshd_enable_pubkey_auth

  - name: Enable Public Key Authentication - Check if the parameter PubkeyAuthentication
      is configured correctly
    ansible.builtin.find:
      paths:
      - /etc/ssh/sshd_config
      - /etc/ssh/sshd_config.d
      contains: (?i)^\s*{{ "PubkeyAuthentication"| regex_escape }}\s+yes$
    register: _sshd_config_correctly
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-002359
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy
    - sshd_enable_pubkey_auth

  - name: Enable Public Key Authentication
    block:

    - name: Deduplicate values from /etc/ssh/sshd_config
      ansible.builtin.lineinfile:
        path: /etc/ssh/sshd_config
        create: false
        regexp: (?i)(?i)^\s*{{ "PubkeyAuthentication"| regex_escape }}\s+
        state: absent

    - name: Check if /etc/ssh/sshd_config.d exists
      ansible.builtin.stat:
        path: /etc/ssh/sshd_config.d
      register: _etc_ssh_sshd_config_d_exists

    - name: Check if the parameter PubkeyAuthentication is present in /etc/ssh/sshd_config.d
      ansible.builtin.find:
        paths: /etc/ssh/sshd_config.d
        recurse: 'yes'
        follow: 'no'
        contains: (?i)^\s*{{ "PubkeyAuthentication"| regex_escape }}\s+
      register: _etc_ssh_sshd_config_d_has_parameter
      when: _etc_ssh_sshd_config_d_exists.stat.isdir is defined and _etc_ssh_sshd_config_d_exists.stat.isdir

    - name: Remove parameter from files in /etc/ssh/sshd_config.d
      ansible.builtin.lineinfile:
        path: '{{ item.path }}'
        create: false
        regexp: (?i)(?i)^\s*{{ "PubkeyAuthentication"| regex_escape }}\s+
        state: absent
      with_items: '{{ _etc_ssh_sshd_config_d_has_parameter.files }}'
      when: _etc_ssh_sshd_config_d_has_parameter.matched > 0

    - name: Insert correct line to /etc/ssh/sshd_config.d/00-complianceascode-hardening.conf
      ansible.builtin.lineinfile:
        path: /etc/ssh/sshd_config.d/00-complianceascode-hardening.conf
        create: true
        regexp: (?i)(?i)^\s*{{ "PubkeyAuthentication"| regex_escape }}\s+
        line: PubkeyAuthentication yes
        state: present
        insertbefore: BOF
        validate: /usr/sbin/sshd -t -f %s
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - _sshd_config_correctly.matched == 0 or _sshd_config_has_parameter.matched !=
      1
    tags:
    - DISA-STIG-OL09-00-002359
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy
    - sshd_enable_pubkey_auth

  - name: Enable Public Key Authentication - set file mode for /etc/ssh/sshd_config.d/00-complianceascode-hardening.conf
    ansible.builtin.file:
      path: /etc/ssh/sshd_config.d/00-complianceascode-hardening.conf
      mode: '0600'
      state: touch
      modification_time: preserve
      access_time: preserve
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-002359
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy
    - sshd_enable_pubkey_auth

  - name: Find sshd_config included files
    ansible.builtin.shell: |-
      included_files=$(grep -oP "^\s*(?i)include.*" /etc/ssh/sshd_config | sed -e 's/\s*Include\s*//i' | sed -e 's|^[^/]|/etc/ssh/&|')
      [[ -n $included_files ]] && ls $included_files || true
    register: sshd_config_included_files
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-002351
    - NIST-800-171-3.1.12
    - NIST-800-53-AC-17(a)
    - NIST-800-53-AC-6
    - NIST-800-53-CM-6(a)
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy
    - sshd_enable_strictmodes

  - name: Comment conf from included files
    ansible.builtin.replace:
      path: '{{ item }}'
      regexp: ^(\s*StrictModes.*)$
      replace: '# \1'
    loop: '{{ sshd_config_included_files.stdout_lines }}'
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-002351
    - NIST-800-171-3.1.12
    - NIST-800-53-AC-17(a)
    - NIST-800-53-AC-6
    - NIST-800-53-CM-6(a)
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy
    - sshd_enable_strictmodes

  - name: Enable Use of Strict Mode Checking - Check if the parameter StrictModes
      is configured
    ansible.builtin.find:
      paths:
      - /etc/ssh/sshd_config
      - /etc/ssh/sshd_config.d
      contains: (?i)^\s*{{ "StrictModes"| regex_escape }}\s+
    register: _sshd_config_has_parameter
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-002351
    - NIST-800-171-3.1.12
    - NIST-800-53-AC-17(a)
    - NIST-800-53-AC-6
    - NIST-800-53-CM-6(a)
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy
    - sshd_enable_strictmodes

  - name: Enable Use of Strict Mode Checking - Check if the parameter StrictModes
      is configured correctly
    ansible.builtin.find:
      paths:
      - /etc/ssh/sshd_config
      - /etc/ssh/sshd_config.d
      contains: (?i)^\s*{{ "StrictModes"| regex_escape }}\s+yes$
    register: _sshd_config_correctly
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-002351
    - NIST-800-171-3.1.12
    - NIST-800-53-AC-17(a)
    - NIST-800-53-AC-6
    - NIST-800-53-CM-6(a)
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy
    - sshd_enable_strictmodes

  - name: Enable Use of Strict Mode Checking
    block:

    - name: Deduplicate values from /etc/ssh/sshd_config
      ansible.builtin.lineinfile:
        path: /etc/ssh/sshd_config
        create: false
        regexp: (?i)(?i)^\s*{{ "StrictModes"| regex_escape }}\s+
        state: absent

    - name: Check if /etc/ssh/sshd_config.d exists
      ansible.builtin.stat:
        path: /etc/ssh/sshd_config.d
      register: _etc_ssh_sshd_config_d_exists

    - name: Check if the parameter StrictModes is present in /etc/ssh/sshd_config.d
      ansible.builtin.find:
        paths: /etc/ssh/sshd_config.d
        recurse: 'yes'
        follow: 'no'
        contains: (?i)^\s*{{ "StrictModes"| regex_escape }}\s+
      register: _etc_ssh_sshd_config_d_has_parameter
      when: _etc_ssh_sshd_config_d_exists.stat.isdir is defined and _etc_ssh_sshd_config_d_exists.stat.isdir

    - name: Remove parameter from files in /etc/ssh/sshd_config.d
      ansible.builtin.lineinfile:
        path: '{{ item.path }}'
        create: false
        regexp: (?i)(?i)^\s*{{ "StrictModes"| regex_escape }}\s+
        state: absent
      with_items: '{{ _etc_ssh_sshd_config_d_has_parameter.files }}'
      when: _etc_ssh_sshd_config_d_has_parameter.matched > 0

    - name: Insert correct line to /etc/ssh/sshd_config.d/01-complianceascode-reinforce-os-defaults.conf
      ansible.builtin.lineinfile:
        path: /etc/ssh/sshd_config.d/01-complianceascode-reinforce-os-defaults.conf
        create: true
        regexp: (?i)(?i)^\s*{{ "StrictModes"| regex_escape }}\s+
        line: StrictModes yes
        state: present
        insertbefore: BOF
        validate: /usr/sbin/sshd -t -f %s
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - _sshd_config_correctly.matched == 0 or _sshd_config_has_parameter.matched !=
      1
    tags:
    - DISA-STIG-OL09-00-002351
    - NIST-800-171-3.1.12
    - NIST-800-53-AC-17(a)
    - NIST-800-53-AC-6
    - NIST-800-53-CM-6(a)
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy
    - sshd_enable_strictmodes

  - name: Enable Use of Strict Mode Checking - set file mode for /etc/ssh/sshd_config.d/01-complianceascode-reinforce-os-defaults.conf
    ansible.builtin.file:
      path: /etc/ssh/sshd_config.d/01-complianceascode-reinforce-os-defaults.conf
      mode: '0600'
      state: touch
      modification_time: preserve
      access_time: preserve
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-002351
    - NIST-800-171-3.1.12
    - NIST-800-53-AC-17(a)
    - NIST-800-53-AC-6
    - NIST-800-53-CM-6(a)
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy
    - sshd_enable_strictmodes

  - name: Find sshd_config included files
    ansible.builtin.shell: |-
      included_files=$(grep -oP "^\s*(?i)include.*" /etc/ssh/sshd_config | sed -e 's/\s*Include\s*//i' | sed -e 's|^[^/]|/etc/ssh/&|')
      [[ -n $included_files ]] && ls $included_files || true
    register: sshd_config_included_files
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - CJIS-5.5.6
    - DISA-STIG-OL09-00-000256
    - NIST-800-171-3.1.9
    - NIST-800-53-AC-17(a)
    - NIST-800-53-AC-8(a)
    - NIST-800-53-AC-8(c)
    - NIST-800-53-CM-6(a)
    - PCI-DSS-Req-2.2.4
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy
    - sshd_enable_warning_banner

  - name: Comment conf from included files
    ansible.builtin.replace:
      path: '{{ item }}'
      regexp: ^(\s*Banner.*)$
      replace: '# \1'
    loop: '{{ sshd_config_included_files.stdout_lines }}'
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - CJIS-5.5.6
    - DISA-STIG-OL09-00-000256
    - NIST-800-171-3.1.9
    - NIST-800-53-AC-17(a)
    - NIST-800-53-AC-8(a)
    - NIST-800-53-AC-8(c)
    - NIST-800-53-CM-6(a)
    - PCI-DSS-Req-2.2.4
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy
    - sshd_enable_warning_banner

  - name: Enable SSH Warning Banner - Check if the parameter Banner is configured
    ansible.builtin.find:
      paths:
      - /etc/ssh/sshd_config
      - /etc/ssh/sshd_config.d
      contains: (?i)^\s*{{ "Banner"| regex_escape }}\s+
    register: _sshd_config_has_parameter
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - CJIS-5.5.6
    - DISA-STIG-OL09-00-000256
    - NIST-800-171-3.1.9
    - NIST-800-53-AC-17(a)
    - NIST-800-53-AC-8(a)
    - NIST-800-53-AC-8(c)
    - NIST-800-53-CM-6(a)
    - PCI-DSS-Req-2.2.4
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy
    - sshd_enable_warning_banner

  - name: Enable SSH Warning Banner - Check if the parameter Banner is configured
      correctly
    ansible.builtin.find:
      paths:
      - /etc/ssh/sshd_config
      - /etc/ssh/sshd_config.d
      contains: (?i)^\s*{{ "Banner"| regex_escape }}\s+/etc/issue$
    register: _sshd_config_correctly
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - CJIS-5.5.6
    - DISA-STIG-OL09-00-000256
    - NIST-800-171-3.1.9
    - NIST-800-53-AC-17(a)
    - NIST-800-53-AC-8(a)
    - NIST-800-53-AC-8(c)
    - NIST-800-53-CM-6(a)
    - PCI-DSS-Req-2.2.4
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy
    - sshd_enable_warning_banner

  - name: Enable SSH Warning Banner
    block:

    - name: Deduplicate values from /etc/ssh/sshd_config
      ansible.builtin.lineinfile:
        path: /etc/ssh/sshd_config
        create: false
        regexp: (?i)(?i)^\s*{{ "Banner"| regex_escape }}\s+
        state: absent

    - name: Check if /etc/ssh/sshd_config.d exists
      ansible.builtin.stat:
        path: /etc/ssh/sshd_config.d
      register: _etc_ssh_sshd_config_d_exists

    - name: Check if the parameter Banner is present in /etc/ssh/sshd_config.d
      ansible.builtin.find:
        paths: /etc/ssh/sshd_config.d
        recurse: 'yes'
        follow: 'no'
        contains: (?i)^\s*{{ "Banner"| regex_escape }}\s+
      register: _etc_ssh_sshd_config_d_has_parameter
      when: _etc_ssh_sshd_config_d_exists.stat.isdir is defined and _etc_ssh_sshd_config_d_exists.stat.isdir

    - name: Remove parameter from files in /etc/ssh/sshd_config.d
      ansible.builtin.lineinfile:
        path: '{{ item.path }}'
        create: false
        regexp: (?i)(?i)^\s*{{ "Banner"| regex_escape }}\s+
        state: absent
      with_items: '{{ _etc_ssh_sshd_config_d_has_parameter.files }}'
      when: _etc_ssh_sshd_config_d_has_parameter.matched > 0

    - name: Insert correct line to /etc/ssh/sshd_config.d/00-complianceascode-hardening.conf
      ansible.builtin.lineinfile:
        path: /etc/ssh/sshd_config.d/00-complianceascode-hardening.conf
        create: true
        regexp: (?i)(?i)^\s*{{ "Banner"| regex_escape }}\s+
        line: Banner /etc/issue
        state: present
        insertbefore: BOF
        validate: /usr/sbin/sshd -t -f %s
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - _sshd_config_correctly.matched == 0 or _sshd_config_has_parameter.matched !=
      1
    tags:
    - CJIS-5.5.6
    - DISA-STIG-OL09-00-000256
    - NIST-800-171-3.1.9
    - NIST-800-53-AC-17(a)
    - NIST-800-53-AC-8(a)
    - NIST-800-53-AC-8(c)
    - NIST-800-53-CM-6(a)
    - PCI-DSS-Req-2.2.4
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy
    - sshd_enable_warning_banner

  - name: Enable SSH Warning Banner - set file mode for /etc/ssh/sshd_config.d/00-complianceascode-hardening.conf
    ansible.builtin.file:
      path: /etc/ssh/sshd_config.d/00-complianceascode-hardening.conf
      mode: '0600'
      state: touch
      modification_time: preserve
      access_time: preserve
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - CJIS-5.5.6
    - DISA-STIG-OL09-00-000256
    - NIST-800-171-3.1.9
    - NIST-800-53-AC-17(a)
    - NIST-800-53-AC-8(a)
    - NIST-800-53-AC-8(c)
    - NIST-800-53-CM-6(a)
    - PCI-DSS-Req-2.2.4
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy
    - sshd_enable_warning_banner

  - name: Find sshd_config included files
    ansible.builtin.shell: |-
      included_files=$(grep -oP "^\s*(?i)include.*" /etc/ssh/sshd_config | sed -e 's/\s*Include\s*//i' | sed -e 's|^[^/]|/etc/ssh/&|')
      [[ -n $included_files ]] && ls $included_files || true
    register: sshd_config_included_files
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-002352
    - NIST-800-53-AC-9
    - NIST-800-53-AC-9(1)
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy
    - sshd_print_last_log

  - name: Comment conf from included files
    ansible.builtin.replace:
      path: '{{ item }}'
      regexp: ^(\s*PrintLastLog.*)$
      replace: '# \1'
    loop: '{{ sshd_config_included_files.stdout_lines }}'
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-002352
    - NIST-800-53-AC-9
    - NIST-800-53-AC-9(1)
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy
    - sshd_print_last_log

  - name: Enable SSH Print Last Log - Check if the parameter PrintLastLog is configured
    ansible.builtin.find:
      paths:
      - /etc/ssh/sshd_config
      - /etc/ssh/sshd_config.d
      contains: (?i)^\s*{{ "PrintLastLog"| regex_escape }}\s+
    register: _sshd_config_has_parameter
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-002352
    - NIST-800-53-AC-9
    - NIST-800-53-AC-9(1)
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy
    - sshd_print_last_log

  - name: Enable SSH Print Last Log - Check if the parameter PrintLastLog is configured
      correctly
    ansible.builtin.find:
      paths:
      - /etc/ssh/sshd_config
      - /etc/ssh/sshd_config.d
      contains: (?i)^\s*{{ "PrintLastLog"| regex_escape }}\s+yes$
    register: _sshd_config_correctly
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-002352
    - NIST-800-53-AC-9
    - NIST-800-53-AC-9(1)
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy
    - sshd_print_last_log

  - name: Enable SSH Print Last Log
    block:

    - name: Deduplicate values from /etc/ssh/sshd_config
      ansible.builtin.lineinfile:
        path: /etc/ssh/sshd_config
        create: false
        regexp: (?i)(?i)^\s*{{ "PrintLastLog"| regex_escape }}\s+
        state: absent

    - name: Check if /etc/ssh/sshd_config.d exists
      ansible.builtin.stat:
        path: /etc/ssh/sshd_config.d
      register: _etc_ssh_sshd_config_d_exists

    - name: Check if the parameter PrintLastLog is present in /etc/ssh/sshd_config.d
      ansible.builtin.find:
        paths: /etc/ssh/sshd_config.d
        recurse: 'yes'
        follow: 'no'
        contains: (?i)^\s*{{ "PrintLastLog"| regex_escape }}\s+
      register: _etc_ssh_sshd_config_d_has_parameter
      when: _etc_ssh_sshd_config_d_exists.stat.isdir is defined and _etc_ssh_sshd_config_d_exists.stat.isdir

    - name: Remove parameter from files in /etc/ssh/sshd_config.d
      ansible.builtin.lineinfile:
        path: '{{ item.path }}'
        create: false
        regexp: (?i)(?i)^\s*{{ "PrintLastLog"| regex_escape }}\s+
        state: absent
      with_items: '{{ _etc_ssh_sshd_config_d_has_parameter.files }}'
      when: _etc_ssh_sshd_config_d_has_parameter.matched > 0

    - name: Insert correct line to /etc/ssh/sshd_config.d/01-complianceascode-reinforce-os-defaults.conf
      ansible.builtin.lineinfile:
        path: /etc/ssh/sshd_config.d/01-complianceascode-reinforce-os-defaults.conf
        create: true
        regexp: (?i)(?i)^\s*{{ "PrintLastLog"| regex_escape }}\s+
        line: PrintLastLog yes
        state: present
        insertbefore: BOF
        validate: /usr/sbin/sshd -t -f %s
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - _sshd_config_correctly.matched == 0 or _sshd_config_has_parameter.matched !=
      1
    tags:
    - DISA-STIG-OL09-00-002352
    - NIST-800-53-AC-9
    - NIST-800-53-AC-9(1)
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy
    - sshd_print_last_log

  - name: Enable SSH Print Last Log - set file mode for /etc/ssh/sshd_config.d/01-complianceascode-reinforce-os-defaults.conf
    ansible.builtin.file:
      path: /etc/ssh/sshd_config.d/01-complianceascode-reinforce-os-defaults.conf
      mode: '0600'
      state: touch
      modification_time: preserve
      access_time: preserve
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-002352
    - NIST-800-53-AC-9
    - NIST-800-53-AC-9(1)
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy
    - sshd_print_last_log

  - name: Find sshd_config included files
    ansible.builtin.shell: |-
      included_files=$(grep -oP "^\s*(?i)include.*" /etc/ssh/sshd_config | sed -e 's/\s*Include\s*//i' | sed -e 's|^[^/]|/etc/ssh/&|')
      [[ -n $included_files ]] && ls $included_files || true
    register: sshd_config_included_files
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-002342
    - configure_strategy
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - sshd_rekey_limit

  - name: Comment conf from included files
    ansible.builtin.replace:
      path: '{{ item }}'
      regexp: ^(\s*RekeyLimit.*)$
      replace: '# \1'
    loop: '{{ sshd_config_included_files.stdout_lines }}'
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-002342
    - configure_strategy
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - sshd_rekey_limit

  - name: Force frequent session key renegotiation - Check if the parameter RekeyLimit
      is configured
    ansible.builtin.find:
      paths:
      - /etc/ssh/sshd_config
      - /etc/ssh/sshd_config.d
      contains: (?i)^\s*{{ "RekeyLimit"| regex_escape }}\s+
    register: _sshd_config_has_parameter
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-002342
    - configure_strategy
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - sshd_rekey_limit

  - name: Force frequent session key renegotiation - Check if the parameter RekeyLimit
      is configured correctly
    ansible.builtin.find:
      paths:
      - /etc/ssh/sshd_config
      - /etc/ssh/sshd_config.d
      contains: (?i)^\s*{{ "RekeyLimit"| regex_escape }}\s+{{ var_rekey_limit_size
        }} {{ var_rekey_limit_time }}$
    register: _sshd_config_correctly
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-002342
    - configure_strategy
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - sshd_rekey_limit

  - name: Force frequent session key renegotiation
    block:

    - name: Deduplicate values from /etc/ssh/sshd_config
      ansible.builtin.lineinfile:
        path: /etc/ssh/sshd_config
        create: false
        regexp: (?i)(?i)^\s*{{ "RekeyLimit"| regex_escape }}\s+
        state: absent

    - name: Check if /etc/ssh/sshd_config.d exists
      ansible.builtin.stat:
        path: /etc/ssh/sshd_config.d
      register: _etc_ssh_sshd_config_d_exists

    - name: Check if the parameter RekeyLimit is present in /etc/ssh/sshd_config.d
      ansible.builtin.find:
        paths: /etc/ssh/sshd_config.d
        recurse: 'yes'
        follow: 'no'
        contains: (?i)^\s*{{ "RekeyLimit"| regex_escape }}\s+
      register: _etc_ssh_sshd_config_d_has_parameter
      when: _etc_ssh_sshd_config_d_exists.stat.isdir is defined and _etc_ssh_sshd_config_d_exists.stat.isdir

    - name: Remove parameter from files in /etc/ssh/sshd_config.d
      ansible.builtin.lineinfile:
        path: '{{ item.path }}'
        create: false
        regexp: (?i)(?i)^\s*{{ "RekeyLimit"| regex_escape }}\s+
        state: absent
      with_items: '{{ _etc_ssh_sshd_config_d_has_parameter.files }}'
      when: _etc_ssh_sshd_config_d_has_parameter.matched > 0

    - name: Insert correct line to /etc/ssh/sshd_config.d/00-complianceascode-hardening.conf
      ansible.builtin.lineinfile:
        path: /etc/ssh/sshd_config.d/00-complianceascode-hardening.conf
        create: true
        regexp: (?i)(?i)^\s*{{ "RekeyLimit"| regex_escape }}\s+
        line: RekeyLimit {{ var_rekey_limit_size }} {{ var_rekey_limit_time }}
        state: present
        insertbefore: BOF
        validate: /usr/sbin/sshd -t -f %s
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - _sshd_config_correctly.matched == 0 or _sshd_config_has_parameter.matched !=
      1
    tags:
    - DISA-STIG-OL09-00-002342
    - configure_strategy
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - sshd_rekey_limit

  - name: Force frequent session key renegotiation - set file mode for /etc/ssh/sshd_config.d/00-complianceascode-hardening.conf
    ansible.builtin.file:
      path: /etc/ssh/sshd_config.d/00-complianceascode-hardening.conf
      mode: '0600'
      state: touch
      modification_time: preserve
      access_time: preserve
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-002342
    - configure_strategy
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - sshd_rekey_limit

  - name: Find sshd_config included files
    ansible.builtin.shell: |-
      included_files=$(grep -oP "^\s*(?i)include.*" /etc/ssh/sshd_config | sed -e 's/\s*Include\s*//i' | sed -e 's|^[^/]|/etc/ssh/&|')
      [[ -n $included_files ]] && ls $included_files || true
    register: sshd_config_included_files
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-002340
    - NIST-800-53-AC-17(1)
    - NIST-800-53-AC-17(a)
    - NIST-800-53-CM-6(a)
    - PCI-DSS-Req-2.2.4
    - PCI-DSSv4-2.2
    - PCI-DSSv4-2.2.6
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy
    - sshd_set_loglevel_verbose

  - name: Comment conf from included files
    ansible.builtin.replace:
      path: '{{ item }}'
      regexp: ^(\s*LogLevel.*)$
      replace: '# \1'
    loop: '{{ sshd_config_included_files.stdout_lines }}'
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-002340
    - NIST-800-53-AC-17(1)
    - NIST-800-53-AC-17(a)
    - NIST-800-53-CM-6(a)
    - PCI-DSS-Req-2.2.4
    - PCI-DSSv4-2.2
    - PCI-DSSv4-2.2.6
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy
    - sshd_set_loglevel_verbose

  - name: Set SSH Daemon LogLevel to VERBOSE - Check if the parameter LogLevel is
      configured
    ansible.builtin.find:
      paths:
      - /etc/ssh/sshd_config
      - /etc/ssh/sshd_config.d
      contains: (?i)^\s*{{ "LogLevel"| regex_escape }}\s+
    register: _sshd_config_has_parameter
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-002340
    - NIST-800-53-AC-17(1)
    - NIST-800-53-AC-17(a)
    - NIST-800-53-CM-6(a)
    - PCI-DSS-Req-2.2.4
    - PCI-DSSv4-2.2
    - PCI-DSSv4-2.2.6
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy
    - sshd_set_loglevel_verbose

  - name: Set SSH Daemon LogLevel to VERBOSE - Check if the parameter LogLevel is
      configured correctly
    ansible.builtin.find:
      paths:
      - /etc/ssh/sshd_config
      - /etc/ssh/sshd_config.d
      contains: (?i)^\s*{{ "LogLevel"| regex_escape }}\s+VERBOSE$
    register: _sshd_config_correctly
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-002340
    - NIST-800-53-AC-17(1)
    - NIST-800-53-AC-17(a)
    - NIST-800-53-CM-6(a)
    - PCI-DSS-Req-2.2.4
    - PCI-DSSv4-2.2
    - PCI-DSSv4-2.2.6
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy
    - sshd_set_loglevel_verbose

  - name: Set SSH Daemon LogLevel to VERBOSE
    block:

    - name: Deduplicate values from /etc/ssh/sshd_config
      ansible.builtin.lineinfile:
        path: /etc/ssh/sshd_config
        create: false
        regexp: (?i)(?i)^\s*{{ "LogLevel"| regex_escape }}\s+
        state: absent

    - name: Check if /etc/ssh/sshd_config.d exists
      ansible.builtin.stat:
        path: /etc/ssh/sshd_config.d
      register: _etc_ssh_sshd_config_d_exists

    - name: Check if the parameter LogLevel is present in /etc/ssh/sshd_config.d
      ansible.builtin.find:
        paths: /etc/ssh/sshd_config.d
        recurse: 'yes'
        follow: 'no'
        contains: (?i)^\s*{{ "LogLevel"| regex_escape }}\s+
      register: _etc_ssh_sshd_config_d_has_parameter
      when: _etc_ssh_sshd_config_d_exists.stat.isdir is defined and _etc_ssh_sshd_config_d_exists.stat.isdir

    - name: Remove parameter from files in /etc/ssh/sshd_config.d
      ansible.builtin.lineinfile:
        path: '{{ item.path }}'
        create: false
        regexp: (?i)(?i)^\s*{{ "LogLevel"| regex_escape }}\s+
        state: absent
      with_items: '{{ _etc_ssh_sshd_config_d_has_parameter.files }}'
      when: _etc_ssh_sshd_config_d_has_parameter.matched > 0

    - name: Insert correct line to /etc/ssh/sshd_config.d/00-complianceascode-hardening.conf
      ansible.builtin.lineinfile:
        path: /etc/ssh/sshd_config.d/00-complianceascode-hardening.conf
        create: true
        regexp: (?i)(?i)^\s*{{ "LogLevel"| regex_escape }}\s+
        line: LogLevel VERBOSE
        state: present
        insertbefore: BOF
        validate: /usr/sbin/sshd -t -f %s
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - _sshd_config_correctly.matched == 0 or _sshd_config_has_parameter.matched !=
      1
    tags:
    - DISA-STIG-OL09-00-002340
    - NIST-800-53-AC-17(1)
    - NIST-800-53-AC-17(a)
    - NIST-800-53-CM-6(a)
    - PCI-DSS-Req-2.2.4
    - PCI-DSSv4-2.2
    - PCI-DSSv4-2.2.6
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy
    - sshd_set_loglevel_verbose

  - name: Set SSH Daemon LogLevel to VERBOSE - set file mode for /etc/ssh/sshd_config.d/00-complianceascode-hardening.conf
    ansible.builtin.file:
      path: /etc/ssh/sshd_config.d/00-complianceascode-hardening.conf
      mode: '0600'
      state: touch
      modification_time: preserve
      access_time: preserve
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-002340
    - NIST-800-53-AC-17(1)
    - NIST-800-53-AC-17(a)
    - NIST-800-53-CM-6(a)
    - PCI-DSS-Req-2.2.4
    - PCI-DSSv4-2.2
    - PCI-DSSv4-2.2.6
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy
    - sshd_set_loglevel_verbose

  - name: Find sshd_config included files
    ansible.builtin.shell: |-
      included_files=$(grep -oP "^\s*(?i)include.*" /etc/ssh/sshd_config | sed -e 's/\s*Include\s*//i' | sed -e 's|^[^/]|/etc/ssh/&|')
      [[ -n $included_files ]] && ls $included_files || true
    register: sshd_config_included_files
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-002354
    - NIST-800-53-CM-6(b)
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy
    - sshd_x11_use_localhost

  - name: Comment conf from included files
    ansible.builtin.replace:
      path: '{{ item }}'
      regexp: ^(\s*X11UseLocalhost.*)$
      replace: '# \1'
    loop: '{{ sshd_config_included_files.stdout_lines }}'
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-002354
    - NIST-800-53-CM-6(b)
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy
    - sshd_x11_use_localhost

  - name: Prevent remote hosts from connecting to the proxy display - Check if the
      parameter X11UseLocalhost is configured
    ansible.builtin.find:
      paths:
      - /etc/ssh/sshd_config
      - /etc/ssh/sshd_config.d
      contains: (?i)^\s*{{ "X11UseLocalhost"| regex_escape }}\s+
    register: _sshd_config_has_parameter
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-002354
    - NIST-800-53-CM-6(b)
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy
    - sshd_x11_use_localhost

  - name: Prevent remote hosts from connecting to the proxy display - Check if the
      parameter X11UseLocalhost is configured correctly
    ansible.builtin.find:
      paths:
      - /etc/ssh/sshd_config
      - /etc/ssh/sshd_config.d
      contains: (?i)^\s*{{ "X11UseLocalhost"| regex_escape }}\s+yes$
    register: _sshd_config_correctly
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-002354
    - NIST-800-53-CM-6(b)
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy
    - sshd_x11_use_localhost

  - name: Prevent remote hosts from connecting to the proxy display
    block:

    - name: Deduplicate values from /etc/ssh/sshd_config
      ansible.builtin.lineinfile:
        path: /etc/ssh/sshd_config
        create: false
        regexp: (?i)(?i)^\s*{{ "X11UseLocalhost"| regex_escape }}\s+
        state: absent

    - name: Check if /etc/ssh/sshd_config.d exists
      ansible.builtin.stat:
        path: /etc/ssh/sshd_config.d
      register: _etc_ssh_sshd_config_d_exists

    - name: Check if the parameter X11UseLocalhost is present in /etc/ssh/sshd_config.d
      ansible.builtin.find:
        paths: /etc/ssh/sshd_config.d
        recurse: 'yes'
        follow: 'no'
        contains: (?i)^\s*{{ "X11UseLocalhost"| regex_escape }}\s+
      register: _etc_ssh_sshd_config_d_has_parameter
      when: _etc_ssh_sshd_config_d_exists.stat.isdir is defined and _etc_ssh_sshd_config_d_exists.stat.isdir

    - name: Remove parameter from files in /etc/ssh/sshd_config.d
      ansible.builtin.lineinfile:
        path: '{{ item.path }}'
        create: false
        regexp: (?i)(?i)^\s*{{ "X11UseLocalhost"| regex_escape }}\s+
        state: absent
      with_items: '{{ _etc_ssh_sshd_config_d_has_parameter.files }}'
      when: _etc_ssh_sshd_config_d_has_parameter.matched > 0

    - name: Insert correct line to /etc/ssh/sshd_config.d/01-complianceascode-reinforce-os-defaults.conf
      ansible.builtin.lineinfile:
        path: /etc/ssh/sshd_config.d/01-complianceascode-reinforce-os-defaults.conf
        create: true
        regexp: (?i)(?i)^\s*{{ "X11UseLocalhost"| regex_escape }}\s+
        line: X11UseLocalhost yes
        state: present
        insertbefore: BOF
        validate: /usr/sbin/sshd -t -f %s
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - _sshd_config_correctly.matched == 0 or _sshd_config_has_parameter.matched !=
      1
    tags:
    - DISA-STIG-OL09-00-002354
    - NIST-800-53-CM-6(b)
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy
    - sshd_x11_use_localhost

  - name: Prevent remote hosts from connecting to the proxy display - set file mode
      for /etc/ssh/sshd_config.d/01-complianceascode-reinforce-os-defaults.conf
    ansible.builtin.file:
      path: /etc/ssh/sshd_config.d/01-complianceascode-reinforce-os-defaults.conf
      mode: '0600'
      state: touch
      modification_time: preserve
      access_time: preserve
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-002354
    - NIST-800-53-CM-6(b)
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy
    - sshd_x11_use_localhost

  - name: Ensure that "certificate_verification" is not set in /etc/sssd/sssd.conf
    community.general.ini_file:
      path: /etc/sssd/sssd.conf
      section: sssd
      option: certificate_verification
      state: absent
      mode: 384
    when: '"sssd-common" in ansible_facts.packages'
    tags:
    - DISA-STIG-OL09-00-000930
    - NIST-800-53-IA-2(11)
    - configure_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - no_reboot_needed
    - sssd_certificate_verification

  - name: Ensure that "certificate_verification" is not set in  /etc/sssd/conf.d/*.conf
    community.general.ini_file:
      path: /etc/sssd/conf.d/*.conf
      section: sssd
      option: certificate_verification
      state: absent
      mode: 384
    when: '"sssd-common" in ansible_facts.packages'
    tags:
    - DISA-STIG-OL09-00-000930
    - NIST-800-53-IA-2(11)
    - configure_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - no_reboot_needed
    - sssd_certificate_verification

  - name: Ensure that "certificate_verification" is set
    community.general.ini_file:
      path: /etc/sssd/conf.d/certificate_verification.conf
      section: sssd
      option: certificate_verification
      value: ocsp_dgst={{ var_sssd_certificate_verification_digest_function }}
      state: present
      mode: 384
    when: '"sssd-common" in ansible_facts.packages'
    tags:
    - DISA-STIG-OL09-00-000930
    - NIST-800-53-IA-2(11)
    - configure_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - no_reboot_needed
    - sssd_certificate_verification

  - name: Test for domain group
    ansible.builtin.command: grep '^\s*\[domain\/[^]]*]' /etc/sssd/sssd.conf
    register: test_grep_domain
    failed_when: false
    changed_when: false
    check_mode: false
    when: '"sssd-common" in ansible_facts.packages'
    tags:
    - DISA-STIG-OL09-00-000925
    - PCI-DSS-Req-8.3
    - configure_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - no_reboot_needed
    - sssd_enable_smartcards

  - name: Add default domain group (if no domain there)
    community.general.ini_file:
      path: /etc/sssd/sssd.conf
      section: '{{ item.section }}'
      option: '{{ item.option }}'
      value: '{{ item.value }}'
      create: true
      mode: 384
    with_items:
    - section: sssd
      option: domains
      value: default
    - section: domain/default
      option: id_provider
      value: files
    when:
    - '"sssd-common" in ansible_facts.packages'
    - test_grep_domain.stdout is defined
    - test_grep_domain.stdout | length < 1
    tags:
    - DISA-STIG-OL09-00-000925
    - PCI-DSS-Req-8.3
    - configure_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - no_reboot_needed
    - sssd_enable_smartcards

  - name: Enable Smartcards in SSSD
    community.general.ini_file:
      dest: /etc/sssd/sssd.conf
      section: pam
      option: pam_cert_auth
      value: 'True'
      create: true
      mode: 384
    when: '"sssd-common" in ansible_facts.packages'
    tags:
    - DISA-STIG-OL09-00-000925
    - PCI-DSS-Req-8.3
    - configure_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - no_reboot_needed
    - sssd_enable_smartcards

  - name: Find all the conf files inside /etc/sssd/conf.d/
    ansible.builtin.find:
      paths: /etc/sssd/conf.d/
      patterns: '*.conf'
    register: sssd_conf_d_files
    when: '"sssd-common" in ansible_facts.packages'
    tags:
    - DISA-STIG-OL09-00-000925
    - PCI-DSS-Req-8.3
    - configure_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - no_reboot_needed
    - sssd_enable_smartcards

  - name: Fix pam_cert_auth configuration in /etc/sssd/conf.d/
    ansible.builtin.replace:
      path: '{{ item.path }}'
      regexp: '[^#]*pam_cert_auth.*'
      replace: pam_cert_auth = True
    with_items: '{{ sssd_conf_d_files.files }}'
    when: '"sssd-common" in ansible_facts.packages'
    tags:
    - DISA-STIG-OL09-00-000925
    - PCI-DSS-Req-8.3
    - configure_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - no_reboot_needed
    - sssd_enable_smartcards

  - name: Enable Smartcards in SSSD - Check if system relies on authselect
    ansible.builtin.stat:
      path: /usr/bin/authselect
    register: result_authselect_present
    when: '"sssd-common" in ansible_facts.packages'
    tags:
    - DISA-STIG-OL09-00-000925
    - PCI-DSS-Req-8.3
    - configure_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - no_reboot_needed
    - sssd_enable_smartcards

  - name: Enable Smartcards in SSSD - Remediate using authselect
    block:

    - name: Enable Smartcards in SSSD - Check integrity of authselect current profile
      ansible.builtin.command:
        cmd: authselect check
      register: result_authselect_check_cmd
      changed_when: false
      check_mode: false
      failed_when: false

    - name: Enable Smartcards in SSSD - Informative message based on the authselect
        integrity check result
      ansible.builtin.assert:
        that:
        - ansible_check_mode or result_authselect_check_cmd.rc == 0
        fail_msg:
        - authselect integrity check failed. Remediation aborted!
        - This remediation could not be applied because an authselect profile was
          not selected or the selected profile is not intact.
        - It is not recommended to manually edit the PAM files when authselect tool
          is available.
        - In cases where the default authselect profile does not cover a specific
          demand, a custom authselect profile is recommended.
        success_msg:
        - authselect integrity check passed

    - name: Enable Smartcards in SSSD - Get authselect current features
      ansible.builtin.shell:
        cmd: authselect current | tail -n+3 | awk '{ print $2 }'
      register: result_authselect_features
      changed_when: false
      check_mode: false
      when:
      - result_authselect_check_cmd is success

    - name: Enable Smartcards in SSSD - Ensure "with-smartcard" feature is enabled
        using authselect tool
      ansible.builtin.command:
        cmd: authselect enable-feature with-smartcard
      register: result_authselect_enable_feature_cmd
      when:
      - result_authselect_check_cmd is success
      - result_authselect_features.stdout is not search("with-smartcard")

    - name: Enable Smartcards in SSSD - Ensure authselect changes are applied
      ansible.builtin.command:
        cmd: authselect apply-changes -b
      when:
      - result_authselect_enable_feature_cmd is not skipped
      - result_authselect_enable_feature_cmd is success
    when:
    - '"sssd-common" in ansible_facts.packages'
    - result_authselect_present.stat.exists
    tags:
    - DISA-STIG-OL09-00-000925
    - PCI-DSS-Req-8.3
    - configure_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - no_reboot_needed
    - sssd_enable_smartcards

  - name: Enable Smartcards in SSSD - Remediate by directly editing PAM files
    block:

    - name: Enable Smartcards in SSSD - Define a fact for control already filtered
        in case filters are used
      ansible.builtin.set_fact:
        pam_module_control: sufficient

    - name: Enable Smartcards in SSSD - Check if expected PAM module line is present
        in /etc/pam.d/smartcard-auth
      ansible.builtin.lineinfile:
        path: /etc/pam.d/smartcard-auth
        regexp: ^\s*auth\s+{{ pam_module_control | regex_escape() }}\s+pam_sss.so\s*.*
        state: absent
      check_mode: true
      changed_when: false
      register: result_pam_line_present

    - name: Enable Smartcards in SSSD - Include or update the PAM module line in /etc/pam.d/smartcard-auth
      block:

      - name: Enable Smartcards in SSSD - Check if required PAM module line is present
          in /etc/pam.d/smartcard-auth with different control
        ansible.builtin.lineinfile:
          path: /etc/pam.d/smartcard-auth
          regexp: ^\s*auth\s+.*\s+pam_sss.so\s*
          state: absent
        check_mode: true
        changed_when: false
        register: result_pam_line_other_control_present

      - name: Enable Smartcards in SSSD - Ensure the correct control for the required
          PAM module line in /etc/pam.d/smartcard-auth
        ansible.builtin.replace:
          dest: /etc/pam.d/smartcard-auth
          regexp: ^(\s*auth\s+).*(\bpam_sss.so.*)
          replace: \1{{ pam_module_control }} \2
        register: result_pam_module_edit
        when:
        - result_pam_line_other_control_present.found == 1

      - name: Enable Smartcards in SSSD - Ensure the required PAM module line is included
          in /etc/pam.d/smartcard-auth
        ansible.builtin.lineinfile:
          dest: /etc/pam.d/smartcard-auth
          line: auth    {{ pam_module_control }}    pam_sss.so
        register: result_pam_module_add
        when:
        - result_pam_line_other_control_present.found == 0 or result_pam_line_other_control_present.found
          > 1

      - name: Enable Smartcards in SSSD - Ensure authselect changes are applied
        ansible.builtin.command:
          cmd: authselect apply-changes -b
        when:
        - result_authselect_present is defined
        - result_authselect_present.stat.exists
        - |-
          (result_pam_module_add is defined and result_pam_module_add.changed)
           or (result_pam_module_edit is defined and result_pam_module_edit.changed)
      when:
      - result_pam_line_present.found is defined
      - result_pam_line_present.found == 0

    - name: Enable Smartcards in SSSD - Define a fact for control already filtered
        in case filters are used
      ansible.builtin.set_fact:
        pam_module_control: sufficient

    - name: Enable Smartcards in SSSD - Check if the required PAM module option is
        present in /etc/pam.d/smartcard-auth
      ansible.builtin.lineinfile:
        path: /etc/pam.d/smartcard-auth
        regexp: ^\s*auth\s+{{ pam_module_control | regex_escape() }}\s+pam_sss.so\s*.*\sallow_missing_name\b
        state: absent
      check_mode: true
      changed_when: false
      register: result_pam_module_sssd_enable_smartcards_option_present

    - name: Enable Smartcards in SSSD - Ensure the "allow_missing_name" PAM option
        for "pam_sss.so" is included in /etc/pam.d/smartcard-auth
      ansible.builtin.lineinfile:
        path: /etc/pam.d/smartcard-auth
        backrefs: true
        regexp: ^(\s*auth\s+{{ pam_module_control | regex_escape() }}\s+pam_sss.so.*)
        line: \1 allow_missing_name
        state: present
      register: result_pam_sssd_enable_smartcards_add
      when:
      - result_pam_module_sssd_enable_smartcards_option_present.found is defined
      - result_pam_module_sssd_enable_smartcards_option_present.found == 0

    - name: Enable Smartcards in SSSD - Define a fact for control already filtered
        in case filters are used
      ansible.builtin.set_fact:
        pam_module_control: '[success=done authinfo_unavail=ignore ignore=ignore default=die]'

    - name: Enable Smartcards in SSSD - Check if expected PAM module line is present
        in /etc/pam.d/system-auth
      ansible.builtin.lineinfile:
        path: /etc/pam.d/system-auth
        regexp: ^\s*auth\s+{{ pam_module_control | regex_escape() }}\s+pam_sss.so\s*.*
        state: absent
      check_mode: true
      changed_when: false
      register: result_pam_line_present

    - name: Enable Smartcards in SSSD - Include or update the PAM module line in /etc/pam.d/system-auth
      block:

      - name: Enable Smartcards in SSSD - Check if required PAM module line is present
          in /etc/pam.d/system-auth with different control
        ansible.builtin.lineinfile:
          path: /etc/pam.d/system-auth
          regexp: ^\s*auth\s+.*\s+pam_sss.so\s*
          state: absent
        check_mode: true
        changed_when: false
        register: result_pam_line_other_control_present

      - name: Enable Smartcards in SSSD - Ensure the correct control for the required
          PAM module line in /etc/pam.d/system-auth
        ansible.builtin.replace:
          dest: /etc/pam.d/system-auth
          regexp: ^(\s*auth\s+).*(\bpam_sss.so.*)
          replace: \1{{ pam_module_control }} \2
        register: result_pam_module_edit
        when:
        - result_pam_line_other_control_present.found == 1

      - name: Enable Smartcards in SSSD - Ensure the required PAM module line is included
          in /etc/pam.d/system-auth
        ansible.builtin.lineinfile:
          dest: /etc/pam.d/system-auth
          line: auth    {{ pam_module_control }}    pam_sss.so
        register: result_pam_module_add
        when:
        - result_pam_line_other_control_present.found == 0 or result_pam_line_other_control_present.found
          > 1

      - name: Enable Smartcards in SSSD - Ensure authselect changes are applied
        ansible.builtin.command:
          cmd: authselect apply-changes -b
        when:
        - result_authselect_present is defined
        - result_authselect_present.stat.exists
        - |-
          (result_pam_module_add is defined and result_pam_module_add.changed)
           or (result_pam_module_edit is defined and result_pam_module_edit.changed)
      when:
      - result_pam_line_present.found is defined
      - result_pam_line_present.found == 0

    - name: Enable Smartcards in SSSD - Define a fact for control already filtered
        in case filters are used
      ansible.builtin.set_fact:
        pam_module_control: '[success=done authinfo_unavail=ignore ignore=ignore default=die]'

    - name: Enable Smartcards in SSSD - Check if the required PAM module option is
        present in /etc/pam.d/system-auth
      ansible.builtin.lineinfile:
        path: /etc/pam.d/system-auth
        regexp: ^\s*auth\s+{{ pam_module_control | regex_escape() }}\s+pam_sss.so\s*.*\stry_cert_auth\b
        state: absent
      check_mode: true
      changed_when: false
      register: result_pam_module_sssd_enable_smartcards_option_present

    - name: Enable Smartcards in SSSD - Ensure the "try_cert_auth" PAM option for
        "pam_sss.so" is included in /etc/pam.d/system-auth
      ansible.builtin.lineinfile:
        path: /etc/pam.d/system-auth
        backrefs: true
        regexp: ^(\s*auth\s+{{ pam_module_control | regex_escape() }}\s+pam_sss.so.*)
        line: \1 try_cert_auth
        state: present
      register: result_pam_sssd_enable_smartcards_add
      when:
      - result_pam_module_sssd_enable_smartcards_option_present.found is defined
      - result_pam_module_sssd_enable_smartcards_option_present.found == 0
    when:
    - '"sssd-common" in ansible_facts.packages'
    - not result_authselect_present.stat.exists
    tags:
    - DISA-STIG-OL09-00-000925
    - PCI-DSS-Req-8.3
    - configure_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - no_reboot_needed
    - sssd_enable_smartcards

  - name: Test for domain group
    ansible.builtin.command: grep '\s*\[domain\/[^]]*]' /etc/sssd/sssd.conf
    register: test_grep_domain
    failed_when: false
    changed_when: false
    check_mode: false
    when: '"sssd-common" in ansible_facts.packages'
    tags:
    - DISA-STIG-OL09-00-000935
    - NIST-800-53-CM-6(a)
    - NIST-800-53-IA-5(13)
    - configure_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - no_reboot_needed
    - sssd_offline_cred_expiration

  - name: Add default domain group (if no domain there)
    community.general.ini_file:
      path: /etc/sssd/sssd.conf
      section: '{{ item.section }}'
      option: '{{ item.option }}'
      value: '{{ item.value }}'
      create: true
      mode: 384
    with_items:
    - section: sssd
      option: domains
      value: default
    - section: domain/default
      option: id_provider
      value: files
    when:
    - '"sssd-common" in ansible_facts.packages'
    - test_grep_domain.stdout is defined
    - test_grep_domain.stdout | length < 1
    tags:
    - DISA-STIG-OL09-00-000935
    - NIST-800-53-CM-6(a)
    - NIST-800-53-IA-5(13)
    - configure_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - no_reboot_needed
    - sssd_offline_cred_expiration

  - name: Configure SSD to Expire Offline Credentials
    community.general.ini_file:
      dest: /etc/sssd/sssd.conf
      section: pam
      option: offline_credentials_expiration
      value: 1
      create: true
      mode: 384
    when: '"sssd-common" in ansible_facts.packages'
    tags:
    - DISA-STIG-OL09-00-000935
    - NIST-800-53-CM-6(a)
    - NIST-800-53-IA-5(13)
    - configure_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - no_reboot_needed
    - sssd_offline_cred_expiration

  - name: Find all the conf files inside /etc/sssd/conf.d/
    ansible.builtin.find:
      paths: /etc/sssd/conf.d/
      patterns: '*.conf'
    register: sssd_conf_d_files
    when: '"sssd-common" in ansible_facts.packages'
    tags:
    - DISA-STIG-OL09-00-000935
    - NIST-800-53-CM-6(a)
    - NIST-800-53-IA-5(13)
    - configure_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - no_reboot_needed
    - sssd_offline_cred_expiration

  - name: Fix offline_credentials_expiration configuration in /etc/sssd/conf.d/
    ansible.builtin.replace:
      path: '{{ item.path }}'
      regexp: '[^#]*offline_credentials_expiration.*'
      replace: offline_credentials_expiration = 1
    with_items: '{{ sssd_conf_d_files.files }}'
    when: '"sssd-common" in ansible_facts.packages'
    tags:
    - DISA-STIG-OL09-00-000935
    - NIST-800-53-CM-6(a)
    - NIST-800-53-IA-5(13)
    - configure_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - no_reboot_needed
    - sssd_offline_cred_expiration

  - name: Log USBGuard daemon audit events using Linux Audit
    block:

    - name: Check for duplicate values
      ansible.builtin.lineinfile:
        path: /etc/usbguard/usbguard-daemon.conf
        create: true
        regexp: (?i)^[ \\t]*AuditBackend=
        state: absent
      check_mode: true
      changed_when: false
      register: dupes

    - name: Deduplicate values from /etc/usbguard/usbguard-daemon.conf
      ansible.builtin.lineinfile:
        path: /etc/usbguard/usbguard-daemon.conf
        create: true
        regexp: (?i)^[ \\t]*AuditBackend=
        state: absent
      when: dupes.found is defined and dupes.found > 1

    - name: Insert correct line to /etc/usbguard/usbguard-daemon.conf
      ansible.builtin.lineinfile:
        path: /etc/usbguard/usbguard-daemon.conf
        create: true
        regexp: (?i)^[ \\t]*AuditBackend=
        line: AuditBackend=LinuxAudit
        state: present
    when:
    - ( ansible_architecture != "s390x" and ("kernel" in ansible_facts.packages or
      "kernel-uek" in ansible_facts.packages) )
    - '"usbguard" in ansible_facts.packages'
    tags:
    - DISA-STIG-OL09-00-002330
    - NIST-800-53-AU-2
    - NIST-800-53-CM-8(3)
    - NIST-800-53-IA-3
    - configure_strategy
    - configure_usbguard_auditbackend
    - low_complexity
    - low_disruption
    - low_severity
    - no_reboot_needed

  - name: Generate USBGuard Policy
    block:

    - name: Check that the /etc/usbguard/rules.conf exists
      ansible.builtin.stat:
        path: /etc/usbguard/rules.conf
      register: policy_file

    - name: Create USBGuard Policy configuration
      ansible.builtin.command: usbguard generate-policy
      register: policy
      when: not policy_file.stat.exists or policy_file.stat.size == 0

    - name: Copy the Generated Policy configuration to a persistent file
      ansible.builtin.copy:
        content: '{{ policy.stdout }}'
        dest: /etc/usbguard/rules.conf
        mode: 384
      when: not policy_file.stat.exists or policy_file.stat.size == 0

    - name: Add comment into /etc/usbguard/rules.conf when system has no USB devices
      ansible.builtin.lineinfile:
        path: /etc/usbguard/rules.conf
        line: '# No USB devices found'
        state: present
      when: not policy_file.stat.exists or policy_file.stat.size == 0

    - name: Enable service usbguard
      ansible.builtin.systemd:
        name: usbguard
        enabled: 'yes'
        state: started
        masked: 'no'
    when:
    - ( ansible_architecture != "s390x" and ("kernel" in ansible_facts.packages or
      "kernel-uek" in ansible_facts.packages) )
    - '"usbguard" in ansible_facts.packages'
    tags:
    - DISA-STIG-OL09-00-002331
    - NIST-800-53-CM-8(3)(a)
    - NIST-800-53-IA-3
    - configure_strategy
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - usbguard_generate_policy

  - name: Switch to multi-user runlevel
    ansible.builtin.file:
      src: /usr/lib/systemd/system/multi-user.target
      dest: /etc/systemd/system/default.target
      state: link
      force: true
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-000020
    - NIST-800-53-CM-6(a)
    - NIST-800-53-CM-7(a)
    - NIST-800-53-CM-7(b)
    - low_complexity
    - low_disruption
    - medium_severity
    - reboot_required
    - restrict_strategy
    - xwindows_runlevel_target

  - name: Check if audit argument is already present in /etc/default/grub
    ansible.builtin.slurp:
      src: /etc/default/grub
    register: etc_default_grub
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - '"grub2-common" in ansible_facts.packages'
    tags:
    - CJIS-5.4.1.1
    - DISA-STIG-OL09-00-000750
    - NIST-800-171-3.3.1
    - NIST-800-53-AC-17(1)
    - NIST-800-53-AU-10
    - NIST-800-53-AU-14(1)
    - NIST-800-53-CM-6(a)
    - NIST-800-53-IR-5(1)
    - PCI-DSS-Req-10.3
    - PCI-DSSv4-10.7
    - PCI-DSSv4-10.7.2
    - grub2_audit_argument
    - low_disruption
    - low_severity
    - medium_complexity
    - reboot_required
    - restrict_strategy

  - name: Check if audit argument is already present
    ansible.builtin.command: /sbin/grubby --info=ALL
    register: grubby_info
    check_mode: false
    changed_when: false
    failed_when: false
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - '"grub2-common" in ansible_facts.packages'
    tags:
    - CJIS-5.4.1.1
    - DISA-STIG-OL09-00-000750
    - NIST-800-171-3.3.1
    - NIST-800-53-AC-17(1)
    - NIST-800-53-AU-10
    - NIST-800-53-AU-14(1)
    - NIST-800-53-CM-6(a)
    - NIST-800-53-IR-5(1)
    - PCI-DSS-Req-10.3
    - PCI-DSSv4-10.7
    - PCI-DSSv4-10.7.2
    - grub2_audit_argument
    - low_disruption
    - low_severity
    - medium_complexity
    - reboot_required
    - restrict_strategy

  - name: Update grub defaults and the bootloader menu
    ansible.builtin.command: /sbin/grubby --update-kernel=ALL --args="audit=1"
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - '"grub2-common" in ansible_facts.packages'
    - (grubby_info.stdout is not search('audit=1')) or ((etc_default_grub['content']
      | b64decode) is not search('audit=1'))
    tags:
    - CJIS-5.4.1.1
    - DISA-STIG-OL09-00-000750
    - NIST-800-171-3.3.1
    - NIST-800-53-AC-17(1)
    - NIST-800-53-AU-10
    - NIST-800-53-AU-14(1)
    - NIST-800-53-CM-6(a)
    - NIST-800-53-IR-5(1)
    - PCI-DSS-Req-10.3
    - PCI-DSSv4-10.7
    - PCI-DSSv4-10.7.2
    - grub2_audit_argument
    - low_disruption
    - low_severity
    - medium_complexity
    - reboot_required
    - restrict_strategy

  - name: Check if audit_backlog_limit argument is already present in /etc/default/grub
    ansible.builtin.slurp:
      src: /etc/default/grub
    register: etc_default_grub
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - '"grub2-common" in ansible_facts.packages'
    tags:
    - DISA-STIG-OL09-00-000830
    - NIST-800-53-CM-6(a)
    - PCI-DSSv4-10.7
    - PCI-DSSv4-10.7.2
    - grub2_audit_backlog_limit_argument
    - low_disruption
    - low_severity
    - medium_complexity
    - reboot_required
    - restrict_strategy

  - name: Check if audit_backlog_limit argument is already present
    ansible.builtin.command: /sbin/grubby --info=ALL
    register: grubby_info
    check_mode: false
    changed_when: false
    failed_when: false
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - '"grub2-common" in ansible_facts.packages'
    tags:
    - DISA-STIG-OL09-00-000830
    - NIST-800-53-CM-6(a)
    - PCI-DSSv4-10.7
    - PCI-DSSv4-10.7.2
    - grub2_audit_backlog_limit_argument
    - low_disruption
    - low_severity
    - medium_complexity
    - reboot_required
    - restrict_strategy

  - name: Update grub defaults and the bootloader menu
    ansible.builtin.command: /sbin/grubby --update-kernel=ALL --args="audit_backlog_limit={{
      var_audit_backlog_limit }}"
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - '"grub2-common" in ansible_facts.packages'
    - (grubby_info.stdout is not search('audit_backlog_limit=' ~ var_audit_backlog_limit))
      or ((etc_default_grub['content'] | b64decode) is not search('audit_backlog_limit='
      ~ var_audit_backlog_limit))
    tags:
    - DISA-STIG-OL09-00-000830
    - NIST-800-53-CM-6(a)
    - PCI-DSSv4-10.7
    - PCI-DSSv4-10.7.2
    - grub2_audit_backlog_limit_argument
    - low_disruption
    - low_severity
    - medium_complexity
    - reboot_required
    - restrict_strategy

  - name: Ensure auditd Collects Changes to Cron Jobs - /etc/cron.d/ - Check if watch
      rule for /etc/cron.d/ already exists in /etc/audit/rules.d/
    ansible.builtin.find:
      paths: /etc/audit/rules.d
      contains: ^\s*-w\s+/etc/cron.d/\s+-p\s+wa(\s|$)+
      patterns: '*.rules'
    register: find_existing_watch_rules_d
    when:
    - '"audit" in ansible_facts.packages'
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-002584
    - audit_rules_etc_cron_d
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Ensure auditd Collects Changes to Cron Jobs - /etc/cron.d/ - Search /etc/audit/rules.d
      for other rules with specified key cronjobs
    ansible.builtin.find:
      paths: /etc/audit/rules.d
      contains: ^.*(?:-F key=|-k\s+)cronjobs$
      patterns: '*.rules'
    register: find_watch_key
    when:
    - '"audit" in ansible_facts.packages'
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - find_existing_watch_rules_d.matched is defined and find_existing_watch_rules_d.matched
      == 0
    tags:
    - DISA-STIG-OL09-00-002584
    - audit_rules_etc_cron_d
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Ensure auditd Collects Changes to Cron Jobs - /etc/cron.d/ - Use /etc/audit/rules.d/cronjobs.rules
      as the recipient for the rule
    ansible.builtin.set_fact:
      all_files:
      - /etc/audit/rules.d/cronjobs.rules
    when:
    - '"audit" in ansible_facts.packages'
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - find_watch_key.matched is defined and find_watch_key.matched == 0 and find_existing_watch_rules_d.matched
      is defined and find_existing_watch_rules_d.matched == 0
    tags:
    - DISA-STIG-OL09-00-002584
    - audit_rules_etc_cron_d
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Ensure auditd Collects Changes to Cron Jobs - /etc/cron.d/ - Use matched
      file as the recipient for the rule
    ansible.builtin.set_fact:
      all_files:
      - '{{ find_watch_key.files | map(attribute=''path'') | list | first }}'
    when:
    - '"audit" in ansible_facts.packages'
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - find_watch_key.matched is defined and find_watch_key.matched > 0 and find_existing_watch_rules_d.matched
      is defined and find_existing_watch_rules_d.matched == 0
    tags:
    - DISA-STIG-OL09-00-002584
    - audit_rules_etc_cron_d
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Ensure auditd Collects Changes to Cron Jobs - /etc/cron.d/ - Add watch rule
      for /etc/cron.d/ in /etc/audit/rules.d/
    ansible.builtin.lineinfile:
      path: '{{ all_files[0] }}'
      line: -w /etc/cron.d/ -p wa -k cronjobs
      create: true
      mode: '0600'
    when:
    - '"audit" in ansible_facts.packages'
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - find_existing_watch_rules_d.matched is defined and find_existing_watch_rules_d.matched
      == 0
    tags:
    - DISA-STIG-OL09-00-002584
    - audit_rules_etc_cron_d
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Ensure auditd Collects Changes to Cron Jobs - /etc/cron.d/ - Check if watch
      rule for /etc/cron.d/ already exists in /etc/audit/audit.rules
    ansible.builtin.find:
      paths: /etc/audit/
      contains: ^\s*-w\s+/etc/cron.d/\s+-p\s+wa(\s|$)+
      patterns: audit.rules
    register: find_existing_watch_audit_rules
    when:
    - '"audit" in ansible_facts.packages'
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-002584
    - audit_rules_etc_cron_d
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Ensure auditd Collects Changes to Cron Jobs - /etc/cron.d/ - Add watch rule
      for /etc/cron.d/ in /etc/audit/audit.rules
    ansible.builtin.lineinfile:
      line: -w /etc/cron.d/ -p wa -k cronjobs
      state: present
      dest: /etc/audit/audit.rules
      create: true
      mode: '0600'
    when:
    - '"audit" in ansible_facts.packages'
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - find_existing_watch_audit_rules.matched is defined and find_existing_watch_audit_rules.matched
      == 0
    tags:
    - DISA-STIG-OL09-00-002584
    - audit_rules_etc_cron_d
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Make the auditd Configuration Immutable - Collect all files from /etc/audit/rules.d
      with .rules extension
    ansible.builtin.find:
      paths: /etc/audit/rules.d/
      patterns: '*.rules'
    register: find_rules_d
    when:
    - '"audit" in ansible_facts.packages'
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - CJIS-5.4.1.1
    - DISA-STIG-OL09-00-008005
    - NIST-800-171-3.3.1
    - NIST-800-171-3.4.3
    - NIST-800-53-AC-6(9)
    - NIST-800-53-CM-6(a)
    - PCI-DSS-Req-10.5.2
    - PCI-DSSv4-10.3
    - PCI-DSSv4-10.3.2
    - audit_rules_immutable
    - low_complexity
    - low_disruption
    - medium_severity
    - reboot_required
    - restrict_strategy

  - name: Make the auditd Configuration Immutable - Check if target files exist and
      get their content
    ansible.builtin.stat:
      path: '{{ item }}'
    register: audit_files_stat
    loop:
    - /etc/audit/audit.rules
    - /etc/audit/rules.d/immutable.rules
    when:
    - '"audit" in ansible_facts.packages'
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - CJIS-5.4.1.1
    - DISA-STIG-OL09-00-008005
    - NIST-800-171-3.3.1
    - NIST-800-171-3.4.3
    - NIST-800-53-AC-6(9)
    - NIST-800-53-CM-6(a)
    - PCI-DSS-Req-10.5.2
    - PCI-DSSv4-10.3
    - PCI-DSSv4-10.3.2
    - audit_rules_immutable
    - low_complexity
    - low_disruption
    - medium_severity
    - reboot_required
    - restrict_strategy

  - name: Make the auditd Configuration Immutable - Read content of existing audit
      files
    ansible.builtin.slurp:
      src: '{{ item.item }}'
    register: audit_files_content
    loop: '{{ audit_files_stat.results }}'
    when:
    - '"audit" in ansible_facts.packages'
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - item.stat.exists
    tags:
    - CJIS-5.4.1.1
    - DISA-STIG-OL09-00-008005
    - NIST-800-171-3.3.1
    - NIST-800-171-3.4.3
    - NIST-800-53-AC-6(9)
    - NIST-800-53-CM-6(a)
    - PCI-DSS-Req-10.5.2
    - PCI-DSSv4-10.3
    - PCI-DSSv4-10.3.2
    - audit_rules_immutable
    - low_complexity
    - low_disruption
    - medium_severity
    - reboot_required
    - restrict_strategy

  - name: Make the auditd Configuration Immutable - Check if -e 2 is already correctly
      set in target files
    ansible.builtin.set_fact:
      immutable_correctly_set: |-
        {{
          audit_files_content.results
          | selectattr('content', 'defined')
          | map(attribute='content')
          | map('b64decode')
          | select('search', '^-e 2$', multiline=True)
          | list
          | length == 2
        }}
    when:
    - '"audit" in ansible_facts.packages'
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - CJIS-5.4.1.1
    - DISA-STIG-OL09-00-008005
    - NIST-800-171-3.3.1
    - NIST-800-171-3.4.3
    - NIST-800-53-AC-6(9)
    - NIST-800-53-CM-6(a)
    - PCI-DSS-Req-10.5.2
    - PCI-DSSv4-10.3
    - PCI-DSSv4-10.3.2
    - audit_rules_immutable
    - low_complexity
    - low_disruption
    - medium_severity
    - reboot_required
    - restrict_strategy

  - name: Make the auditd Configuration Immutable - Remove any existing -e option
      from all Audit config files
    ansible.builtin.lineinfile:
      path: '{{ item }}'
      regexp: ^\s*-e\s+.*$
      state: absent
    loop: '{{ find_rules_d.files | map(attribute=''path'') | list + [''/etc/audit/audit.rules'']
      }}'
    when:
    - '"audit" in ansible_facts.packages'
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - not immutable_correctly_set
    tags:
    - CJIS-5.4.1.1
    - DISA-STIG-OL09-00-008005
    - NIST-800-171-3.3.1
    - NIST-800-171-3.4.3
    - NIST-800-53-AC-6(9)
    - NIST-800-53-CM-6(a)
    - PCI-DSS-Req-10.5.2
    - PCI-DSSv4-10.3
    - PCI-DSSv4-10.3.2
    - audit_rules_immutable
    - low_complexity
    - low_disruption
    - medium_severity
    - reboot_required
    - restrict_strategy

  - name: Make the auditd Configuration Immutable - Ensure target directories exist
    ansible.builtin.file:
      path: '{{ item | dirname }}'
      state: directory
      mode: '0750'
    loop:
    - /etc/audit/audit.rules
    - /etc/audit/rules.d/immutable.rules
    when:
    - '"audit" in ansible_facts.packages'
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - not immutable_correctly_set
    tags:
    - CJIS-5.4.1.1
    - DISA-STIG-OL09-00-008005
    - NIST-800-171-3.3.1
    - NIST-800-171-3.4.3
    - NIST-800-53-AC-6(9)
    - NIST-800-53-CM-6(a)
    - PCI-DSS-Req-10.5.2
    - PCI-DSSv4-10.3
    - PCI-DSSv4-10.3.2
    - audit_rules_immutable
    - low_complexity
    - low_disruption
    - medium_severity
    - reboot_required
    - restrict_strategy

  - name: Make the auditd Configuration Immutable - Add Audit -e 2 option to make
      rules immutable
    ansible.builtin.lineinfile:
      path: '{{ item }}'
      create: true
      line: -e 2
      regexp: ^\s*-e\s+.*$
      mode: g-rwx,o-rwx
    loop:
    - /etc/audit/audit.rules
    - /etc/audit/rules.d/immutable.rules
    when:
    - '"audit" in ansible_facts.packages'
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - not immutable_correctly_set
    tags:
    - CJIS-5.4.1.1
    - DISA-STIG-OL09-00-008005
    - NIST-800-171-3.3.1
    - NIST-800-171-3.4.3
    - NIST-800-53-AC-6(9)
    - NIST-800-53-CM-6(a)
    - PCI-DSS-Req-10.5.2
    - PCI-DSSv4-10.3
    - PCI-DSSv4-10.3.2
    - audit_rules_immutable
    - low_complexity
    - low_disruption
    - medium_severity
    - reboot_required
    - restrict_strategy

  - name: 'Configure immutable Audit login UIDs: Determine if rules are loaded by
      auditctl'
    ansible.builtin.find:
      paths: /usr/lib/systemd/system
      patterns: auditd.service
      contains: ^\s*ExecStartPost=-/sbin/auditctl
    register: auditctl_used
    when:
    - '"audit" in ansible_facts.packages'
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-008000
    - audit_rules_immutable_login_uids
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: 'Configure immutable Audit login UIDs: Configure immutable login UIDs in
      /etc/audit/audit.rules'
    ansible.builtin.lineinfile:
      path: /etc/audit/audit.rules
      line: --loginuid-immutable
      regexp: ^\s*--loginuid-immutable\s*$
      mode: '0600'
      create: true
    when:
    - '"audit" in ansible_facts.packages'
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - auditctl_used is defined and auditctl_used.matched >= 1
    tags:
    - DISA-STIG-OL09-00-008000
    - audit_rules_immutable_login_uids
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: 'Configure immutable Audit login UIDs: In case Augen-rules is used'
    block:

    - name: 'Configure immutable Audit login UIDs: Detect if immutable login UIDs
        are already defined in /etc/audit/rules.d/*.rules'
      ansible.builtin.find:
        paths: /etc/audit/rules.d
        patterns: '*.rules'
        contains: ^\s*--loginuid-immutable\s*$
      register: immutable_found_in_rules_d

    - name: 'Configure immutable Audit login UIDs: set immutable login UIDS in /etc/audit/rules.d/immutable.rules'
      ansible.builtin.lineinfile:
        path: /etc/audit/rules.d/immutable.rules
        line: --loginuid-immutable
        regexp: ^\s*--loginuid-immutable\s*$
        mode: '0600'
        create: true
      when: immutable_found_in_rules_d is defined and immutable_found_in_rules_d.matched
        == 0
    when:
    - '"audit" in ansible_facts.packages'
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - auditctl_used is defined and auditctl_used.matched == 0
    tags:
    - DISA-STIG-OL09-00-008000
    - audit_rules_immutable_login_uids
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Ensure auditd Collects System Administrator Actions - /etc/sudoers - Check
      if watch rule for /etc/sudoers already exists in /etc/audit/rules.d/
    ansible.builtin.find:
      paths: /etc/audit/rules.d
      contains: ^\s*-w\s+/etc/sudoers\s+-p\s+wa(\s|$)+
      patterns: '*.rules'
    register: find_existing_watch_rules_d
    when:
    - '"audit" in ansible_facts.packages'
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-000500
    - audit_rules_sudoers
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Ensure auditd Collects System Administrator Actions - /etc/sudoers - Search
      /etc/audit/rules.d for other rules with specified key actions
    ansible.builtin.find:
      paths: /etc/audit/rules.d
      contains: ^.*(?:-F key=|-k\s+)actions$
      patterns: '*.rules'
    register: find_watch_key
    when:
    - '"audit" in ansible_facts.packages'
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - find_existing_watch_rules_d.matched is defined and find_existing_watch_rules_d.matched
      == 0
    tags:
    - DISA-STIG-OL09-00-000500
    - audit_rules_sudoers
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Ensure auditd Collects System Administrator Actions - /etc/sudoers - Use
      /etc/audit/rules.d/actions.rules as the recipient for the rule
    ansible.builtin.set_fact:
      all_files:
      - /etc/audit/rules.d/actions.rules
    when:
    - '"audit" in ansible_facts.packages'
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - find_watch_key.matched is defined and find_watch_key.matched == 0 and find_existing_watch_rules_d.matched
      is defined and find_existing_watch_rules_d.matched == 0
    tags:
    - DISA-STIG-OL09-00-000500
    - audit_rules_sudoers
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Ensure auditd Collects System Administrator Actions - /etc/sudoers - Use
      matched file as the recipient for the rule
    ansible.builtin.set_fact:
      all_files:
      - '{{ find_watch_key.files | map(attribute=''path'') | list | first }}'
    when:
    - '"audit" in ansible_facts.packages'
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - find_watch_key.matched is defined and find_watch_key.matched > 0 and find_existing_watch_rules_d.matched
      is defined and find_existing_watch_rules_d.matched == 0
    tags:
    - DISA-STIG-OL09-00-000500
    - audit_rules_sudoers
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Ensure auditd Collects System Administrator Actions - /etc/sudoers - Add
      watch rule for /etc/sudoers in /etc/audit/rules.d/
    ansible.builtin.lineinfile:
      path: '{{ all_files[0] }}'
      line: -w /etc/sudoers -p wa -k actions
      create: true
      mode: '0600'
    when:
    - '"audit" in ansible_facts.packages'
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - find_existing_watch_rules_d.matched is defined and find_existing_watch_rules_d.matched
      == 0
    tags:
    - DISA-STIG-OL09-00-000500
    - audit_rules_sudoers
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Ensure auditd Collects System Administrator Actions - /etc/sudoers - Check
      if watch rule for /etc/sudoers already exists in /etc/audit/audit.rules
    ansible.builtin.find:
      paths: /etc/audit/
      contains: ^\s*-w\s+/etc/sudoers\s+-p\s+wa(\s|$)+
      patterns: audit.rules
    register: find_existing_watch_audit_rules
    when:
    - '"audit" in ansible_facts.packages'
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-000500
    - audit_rules_sudoers
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Ensure auditd Collects System Administrator Actions - /etc/sudoers - Add
      watch rule for /etc/sudoers in /etc/audit/audit.rules
    ansible.builtin.lineinfile:
      line: -w /etc/sudoers -p wa -k actions
      state: present
      dest: /etc/audit/audit.rules
      create: true
      mode: '0600'
    when:
    - '"audit" in ansible_facts.packages'
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - find_existing_watch_audit_rules.matched is defined and find_existing_watch_audit_rules.matched
      == 0
    tags:
    - DISA-STIG-OL09-00-000500
    - audit_rules_sudoers
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Ensure auditd Collects System Administrator Actions - /etc/sudoers.d/ -
      Check if watch rule for /etc/sudoers.d/ already exists in /etc/audit/rules.d/
    ansible.builtin.find:
      paths: /etc/audit/rules.d
      contains: ^\s*-w\s+/etc/sudoers.d/\s+-p\s+wa(\s|$)+
      patterns: '*.rules'
    register: find_existing_watch_rules_d
    when:
    - '"audit" in ansible_facts.packages'
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-000505
    - audit_rules_sudoers_d
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Ensure auditd Collects System Administrator Actions - /etc/sudoers.d/ -
      Search /etc/audit/rules.d for other rules with specified key actions
    ansible.builtin.find:
      paths: /etc/audit/rules.d
      contains: ^.*(?:-F key=|-k\s+)actions$
      patterns: '*.rules'
    register: find_watch_key
    when:
    - '"audit" in ansible_facts.packages'
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - find_existing_watch_rules_d.matched is defined and find_existing_watch_rules_d.matched
      == 0
    tags:
    - DISA-STIG-OL09-00-000505
    - audit_rules_sudoers_d
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Ensure auditd Collects System Administrator Actions - /etc/sudoers.d/ -
      Use /etc/audit/rules.d/actions.rules as the recipient for the rule
    ansible.builtin.set_fact:
      all_files:
      - /etc/audit/rules.d/actions.rules
    when:
    - '"audit" in ansible_facts.packages'
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - find_watch_key.matched is defined and find_watch_key.matched == 0 and find_existing_watch_rules_d.matched
      is defined and find_existing_watch_rules_d.matched == 0
    tags:
    - DISA-STIG-OL09-00-000505
    - audit_rules_sudoers_d
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Ensure auditd Collects System Administrator Actions - /etc/sudoers.d/ -
      Use matched file as the recipient for the rule
    ansible.builtin.set_fact:
      all_files:
      - '{{ find_watch_key.files | map(attribute=''path'') | list | first }}'
    when:
    - '"audit" in ansible_facts.packages'
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - find_watch_key.matched is defined and find_watch_key.matched > 0 and find_existing_watch_rules_d.matched
      is defined and find_existing_watch_rules_d.matched == 0
    tags:
    - DISA-STIG-OL09-00-000505
    - audit_rules_sudoers_d
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Ensure auditd Collects System Administrator Actions - /etc/sudoers.d/ -
      Add watch rule for /etc/sudoers.d/ in /etc/audit/rules.d/
    ansible.builtin.lineinfile:
      path: '{{ all_files[0] }}'
      line: -w /etc/sudoers.d/ -p wa -k actions
      create: true
      mode: '0600'
    when:
    - '"audit" in ansible_facts.packages'
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - find_existing_watch_rules_d.matched is defined and find_existing_watch_rules_d.matched
      == 0
    tags:
    - DISA-STIG-OL09-00-000505
    - audit_rules_sudoers_d
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Ensure auditd Collects System Administrator Actions - /etc/sudoers.d/ -
      Check if watch rule for /etc/sudoers.d/ already exists in /etc/audit/audit.rules
    ansible.builtin.find:
      paths: /etc/audit/
      contains: ^\s*-w\s+/etc/sudoers.d/\s+-p\s+wa(\s|$)+
      patterns: audit.rules
    register: find_existing_watch_audit_rules
    when:
    - '"audit" in ansible_facts.packages'
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-000505
    - audit_rules_sudoers_d
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Ensure auditd Collects System Administrator Actions - /etc/sudoers.d/ -
      Add watch rule for /etc/sudoers.d/ in /etc/audit/audit.rules
    ansible.builtin.lineinfile:
      line: -w /etc/sudoers.d/ -p wa -k actions
      state: present
      dest: /etc/audit/audit.rules
      create: true
      mode: '0600'
    when:
    - '"audit" in ansible_facts.packages'
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - find_existing_watch_audit_rules.matched is defined and find_existing_watch_audit_rules.matched
      == 0
    tags:
    - DISA-STIG-OL09-00-000505
    - audit_rules_sudoers_d
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Set suid_audit_rules fact
    ansible.builtin.set_fact:
      suid_audit_rules:
      - rule: -a always,exit -F arch=b32 -S execve -C gid!=egid -F egid=0 -k setgid
        regex: ^[\s]*-a[\s]+always,exit[\s]+-F[\s]+arch=b32[\s]+-S[\s]+execve[\s]+-C[\s]+gid!=egid[\s]+-F[\s]+egid=0[\s]+(?:-k[\s]+|-F[\s]+key=)[\S]+[\s]*$
      - rule: -a always,exit -F arch=b64 -S execve -C gid!=egid -F egid=0 -k setgid
        regex: ^[\s]*-a[\s]+always,exit[\s]+-F[\s]+arch=b64[\s]+-S[\s]+execve[\s]+-C[\s]+gid!=egid[\s]+-F[\s]+egid=0[\s]+(?:-k[\s]+|-F[\s]+key=)[\S]+[\s]*$
      - rule: -a always,exit -F arch=b32 -S execve -C uid!=euid -F euid=0 -k setuid
        regex: ^[\s]*-a[\s]+always,exit[\s]+-F[\s]+arch=b32[\s]+-S[\s]+execve[\s]+-C[\s]+uid!=euid[\s]+-F[\s]+euid=0[\s]+(?:-k[\s]+|-F[\s]+key=)[\S]+[\s]*$
      - rule: -a always,exit -F arch=b64 -S execve -C uid!=euid -F euid=0 -k setuid
        regex: ^[\s]*-a[\s]+always,exit[\s]+-F[\s]+arch=b64[\s]+-S[\s]+execve[\s]+-C[\s]+uid!=euid[\s]+-F[\s]+euid=0[\s]+(?:-k[\s]+|-F[\s]+key=)[\S]+[\s]*$
    when:
    - '"audit" in ansible_facts.packages'
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-000715
    - NIST-800-53-AC-6(9)
    - NIST-800-53-AU-12(3)
    - NIST-800-53-AU-7(a)
    - NIST-800-53-AU-7(b)
    - NIST-800-53-AU-8(b)
    - NIST-800-53-CM-5(1)
    - PCI-DSSv4-10.2
    - PCI-DSSv4-10.2.1
    - PCI-DSSv4-10.2.1.2
    - audit_rules_suid_privilege_function
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Update /etc/audit/rules.d/privileged.rules to audit privileged functions
    ansible.builtin.lineinfile:
      path: /etc/audit/rules.d/privileged.rules
      line: '{{  item.rule  }}'
      regexp: '{{ item.regex }}'
      mode: '0600'
      create: true
    when:
    - '"audit" in ansible_facts.packages'
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - ('"auditd.service" in ansible_facts.services' or '"augenrules.service" in ansible_facts.services')
    register: augenrules_audit_rules_privilege_function_update_result
    with_items: '{{ suid_audit_rules }}'
    tags:
    - DISA-STIG-OL09-00-000715
    - NIST-800-53-AC-6(9)
    - NIST-800-53-AU-12(3)
    - NIST-800-53-AU-7(a)
    - NIST-800-53-AU-7(b)
    - NIST-800-53-AU-8(b)
    - NIST-800-53-CM-5(1)
    - PCI-DSSv4-10.2
    - PCI-DSSv4-10.2.1
    - PCI-DSSv4-10.2.1.2
    - audit_rules_suid_privilege_function
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Update /etc/audit/audit.rules to audit privileged functions
    ansible.builtin.lineinfile:
      path: /etc/audit/audit.rules
      line: '{{  item.rule  }}'
      regexp: '{{ item.regex }}'
      create: true
    when:
    - '"audit" in ansible_facts.packages'
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - ('"auditd.service" in ansible_facts.services' or '"augenrules.service" in ansible_facts.services')
    register: auditctl_audit_rules_privilege_function_update_result
    with_items: '{{ suid_audit_rules }}'
    tags:
    - DISA-STIG-OL09-00-000715
    - NIST-800-53-AC-6(9)
    - NIST-800-53-AU-12(3)
    - NIST-800-53-AU-7(a)
    - NIST-800-53-AU-7(b)
    - NIST-800-53-AU-8(b)
    - NIST-800-53-CM-5(1)
    - PCI-DSSv4-10.2
    - PCI-DSSv4-10.2.1
    - PCI-DSSv4-10.2.1.2
    - audit_rules_suid_privilege_function
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Restart Auditd
    ansible.builtin.command: /usr/sbin/service auditd restart
    when:
    - '"audit" in ansible_facts.packages'
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - (augenrules_audit_rules_privilege_function_update_result.changed or auditctl_audit_rules_privilege_function_update_result.changed)
    - ansible_facts.services["auditd.service"].state == "running"
    tags:
    - DISA-STIG-OL09-00-000715
    - NIST-800-53-AC-6(9)
    - NIST-800-53-AU-12(3)
    - NIST-800-53-AU-7(a)
    - NIST-800-53-AU-7(b)
    - NIST-800-53-AU-8(b)
    - NIST-800-53-CM-5(1)
    - PCI-DSSv4-10.2
    - PCI-DSSv4-10.2.1
    - PCI-DSSv4-10.2.1.2
    - audit_rules_suid_privilege_function
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Collect all files from /etc/audit/rules.d with .rules extension
    ansible.builtin.find:
      paths: /etc/audit/rules.d/
      patterns: '*.rules'
    register: find_rules_d
    when:
    - '"audit" in ansible_facts.packages'
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-000820
    - NIST-800-171-3.3.1
    - NIST-800-171-3.3.4
    - NIST-800-53-AU-5(b)
    - NIST-800-53-CM-6(a)
    - NIST-800-53-SC-24
    - audit_rules_system_shutdown
    - low_complexity
    - low_disruption
    - medium_severity
    - reboot_required
    - restrict_strategy

  - name: Remove the -f option from all Audit config files
    ansible.builtin.lineinfile:
      path: '{{ item }}'
      regexp: ^\s*(?:-f)\s+.*$
      state: absent
    loop: '{{ find_rules_d.files | map(attribute=''path'') | list + [''/etc/audit/audit.rules'']
      }}'
    when:
    - '"audit" in ansible_facts.packages'
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-000820
    - NIST-800-171-3.3.1
    - NIST-800-171-3.3.4
    - NIST-800-53-AU-5(b)
    - NIST-800-53-CM-6(a)
    - NIST-800-53-SC-24
    - audit_rules_system_shutdown
    - low_complexity
    - low_disruption
    - medium_severity
    - reboot_required
    - restrict_strategy

  - name: Add Audit -f option into /etc/audit/rules.d/immutable.rules and /etc/audit/audit.rules
    ansible.builtin.lineinfile:
      path: '{{ item }}'
      create: true
      mode: '0600'
      line: -f {{ var_audit_failure_mode }}
    loop:
    - /etc/audit/audit.rules
    - /etc/audit/rules.d/immutable.rules
    when:
    - '"audit" in ansible_facts.packages'
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-000820
    - NIST-800-171-3.3.1
    - NIST-800-171-3.3.4
    - NIST-800-53-AU-5(b)
    - NIST-800-53-CM-6(a)
    - NIST-800-53-SC-24
    - audit_rules_system_shutdown
    - low_complexity
    - low_disruption
    - medium_severity
    - reboot_required
    - restrict_strategy

  - name: Record Events that Modify User/Group Information - /etc/group - Check if
      watch rule for /etc/group already exists in /etc/audit/rules.d/
    ansible.builtin.find:
      paths: /etc/audit/rules.d
      contains: ^\s*-w\s+/etc/group\s+-p\s+wa(\s|$)+
      patterns: '*.rules'
    register: find_existing_watch_rules_d
    when:
    - '"audit" in ansible_facts.packages'
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - CJIS-5.4.1.1
    - DISA-STIG-OL09-00-000510
    - NIST-800-171-3.1.7
    - NIST-800-53-AC-2(4)
    - NIST-800-53-AC-6(9)
    - NIST-800-53-AU-12(c)
    - NIST-800-53-AU-2(d)
    - NIST-800-53-CM-6(a)
    - PCI-DSS-Req-10.2.5
    - PCI-DSSv4-10.2
    - PCI-DSSv4-10.2.1
    - PCI-DSSv4-10.2.1.5
    - audit_rules_usergroup_modification_group
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Record Events that Modify User/Group Information - /etc/group - Search /etc/audit/rules.d
      for other rules with specified key audit_rules_usergroup_modification
    ansible.builtin.find:
      paths: /etc/audit/rules.d
      contains: ^.*(?:-F key=|-k\s+)audit_rules_usergroup_modification$
      patterns: '*.rules'
    register: find_watch_key
    when:
    - '"audit" in ansible_facts.packages'
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - find_existing_watch_rules_d.matched is defined and find_existing_watch_rules_d.matched
      == 0
    tags:
    - CJIS-5.4.1.1
    - DISA-STIG-OL09-00-000510
    - NIST-800-171-3.1.7
    - NIST-800-53-AC-2(4)
    - NIST-800-53-AC-6(9)
    - NIST-800-53-AU-12(c)
    - NIST-800-53-AU-2(d)
    - NIST-800-53-CM-6(a)
    - PCI-DSS-Req-10.2.5
    - PCI-DSSv4-10.2
    - PCI-DSSv4-10.2.1
    - PCI-DSSv4-10.2.1.5
    - audit_rules_usergroup_modification_group
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Record Events that Modify User/Group Information - /etc/group - Use /etc/audit/rules.d/audit_rules_usergroup_modification.rules
      as the recipient for the rule
    ansible.builtin.set_fact:
      all_files:
      - /etc/audit/rules.d/audit_rules_usergroup_modification.rules
    when:
    - '"audit" in ansible_facts.packages'
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - find_watch_key.matched is defined and find_watch_key.matched == 0 and find_existing_watch_rules_d.matched
      is defined and find_existing_watch_rules_d.matched == 0
    tags:
    - CJIS-5.4.1.1
    - DISA-STIG-OL09-00-000510
    - NIST-800-171-3.1.7
    - NIST-800-53-AC-2(4)
    - NIST-800-53-AC-6(9)
    - NIST-800-53-AU-12(c)
    - NIST-800-53-AU-2(d)
    - NIST-800-53-CM-6(a)
    - PCI-DSS-Req-10.2.5
    - PCI-DSSv4-10.2
    - PCI-DSSv4-10.2.1
    - PCI-DSSv4-10.2.1.5
    - audit_rules_usergroup_modification_group
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Record Events that Modify User/Group Information - /etc/group - Use matched
      file as the recipient for the rule
    ansible.builtin.set_fact:
      all_files:
      - '{{ find_watch_key.files | map(attribute=''path'') | list | first }}'
    when:
    - '"audit" in ansible_facts.packages'
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - find_watch_key.matched is defined and find_watch_key.matched > 0 and find_existing_watch_rules_d.matched
      is defined and find_existing_watch_rules_d.matched == 0
    tags:
    - CJIS-5.4.1.1
    - DISA-STIG-OL09-00-000510
    - NIST-800-171-3.1.7
    - NIST-800-53-AC-2(4)
    - NIST-800-53-AC-6(9)
    - NIST-800-53-AU-12(c)
    - NIST-800-53-AU-2(d)
    - NIST-800-53-CM-6(a)
    - PCI-DSS-Req-10.2.5
    - PCI-DSSv4-10.2
    - PCI-DSSv4-10.2.1
    - PCI-DSSv4-10.2.1.5
    - audit_rules_usergroup_modification_group
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Record Events that Modify User/Group Information - /etc/group - Add watch
      rule for /etc/group in /etc/audit/rules.d/
    ansible.builtin.lineinfile:
      path: '{{ all_files[0] }}'
      line: -w /etc/group -p wa -k audit_rules_usergroup_modification
      create: true
      mode: '0600'
    when:
    - '"audit" in ansible_facts.packages'
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - find_existing_watch_rules_d.matched is defined and find_existing_watch_rules_d.matched
      == 0
    tags:
    - CJIS-5.4.1.1
    - DISA-STIG-OL09-00-000510
    - NIST-800-171-3.1.7
    - NIST-800-53-AC-2(4)
    - NIST-800-53-AC-6(9)
    - NIST-800-53-AU-12(c)
    - NIST-800-53-AU-2(d)
    - NIST-800-53-CM-6(a)
    - PCI-DSS-Req-10.2.5
    - PCI-DSSv4-10.2
    - PCI-DSSv4-10.2.1
    - PCI-DSSv4-10.2.1.5
    - audit_rules_usergroup_modification_group
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Record Events that Modify User/Group Information - /etc/group - Check if
      watch rule for /etc/group already exists in /etc/audit/audit.rules
    ansible.builtin.find:
      paths: /etc/audit/
      contains: ^\s*-w\s+/etc/group\s+-p\s+wa(\s|$)+
      patterns: audit.rules
    register: find_existing_watch_audit_rules
    when:
    - '"audit" in ansible_facts.packages'
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - CJIS-5.4.1.1
    - DISA-STIG-OL09-00-000510
    - NIST-800-171-3.1.7
    - NIST-800-53-AC-2(4)
    - NIST-800-53-AC-6(9)
    - NIST-800-53-AU-12(c)
    - NIST-800-53-AU-2(d)
    - NIST-800-53-CM-6(a)
    - PCI-DSS-Req-10.2.5
    - PCI-DSSv4-10.2
    - PCI-DSSv4-10.2.1
    - PCI-DSSv4-10.2.1.5
    - audit_rules_usergroup_modification_group
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Record Events that Modify User/Group Information - /etc/group - Add watch
      rule for /etc/group in /etc/audit/audit.rules
    ansible.builtin.lineinfile:
      line: -w /etc/group -p wa -k audit_rules_usergroup_modification
      state: present
      dest: /etc/audit/audit.rules
      create: true
      mode: '0600'
    when:
    - '"audit" in ansible_facts.packages'
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - find_existing_watch_audit_rules.matched is defined and find_existing_watch_audit_rules.matched
      == 0
    tags:
    - CJIS-5.4.1.1
    - DISA-STIG-OL09-00-000510
    - NIST-800-171-3.1.7
    - NIST-800-53-AC-2(4)
    - NIST-800-53-AC-6(9)
    - NIST-800-53-AU-12(c)
    - NIST-800-53-AU-2(d)
    - NIST-800-53-CM-6(a)
    - PCI-DSS-Req-10.2.5
    - PCI-DSSv4-10.2
    - PCI-DSSv4-10.2.1
    - PCI-DSSv4-10.2.1.5
    - audit_rules_usergroup_modification_group
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Record Events that Modify User/Group Information - /etc/gshadow - Check
      if watch rule for /etc/gshadow already exists in /etc/audit/rules.d/
    ansible.builtin.find:
      paths: /etc/audit/rules.d
      contains: ^\s*-w\s+/etc/gshadow\s+-p\s+wa(\s|$)+
      patterns: '*.rules'
    register: find_existing_watch_rules_d
    when:
    - '"audit" in ansible_facts.packages'
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - CJIS-5.4.1.1
    - DISA-STIG-OL09-00-000515
    - NIST-800-171-3.1.7
    - NIST-800-53-AC-2(4)
    - NIST-800-53-AC-6(9)
    - NIST-800-53-AU-12(c)
    - NIST-800-53-AU-2(d)
    - NIST-800-53-CM-6(a)
    - PCI-DSS-Req-10.2.5
    - PCI-DSSv4-10.2
    - PCI-DSSv4-10.2.1
    - PCI-DSSv4-10.2.1.5
    - audit_rules_usergroup_modification_gshadow
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Record Events that Modify User/Group Information - /etc/gshadow - Search
      /etc/audit/rules.d for other rules with specified key audit_rules_usergroup_modification
    ansible.builtin.find:
      paths: /etc/audit/rules.d
      contains: ^.*(?:-F key=|-k\s+)audit_rules_usergroup_modification$
      patterns: '*.rules'
    register: find_watch_key
    when:
    - '"audit" in ansible_facts.packages'
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - find_existing_watch_rules_d.matched is defined and find_existing_watch_rules_d.matched
      == 0
    tags:
    - CJIS-5.4.1.1
    - DISA-STIG-OL09-00-000515
    - NIST-800-171-3.1.7
    - NIST-800-53-AC-2(4)
    - NIST-800-53-AC-6(9)
    - NIST-800-53-AU-12(c)
    - NIST-800-53-AU-2(d)
    - NIST-800-53-CM-6(a)
    - PCI-DSS-Req-10.2.5
    - PCI-DSSv4-10.2
    - PCI-DSSv4-10.2.1
    - PCI-DSSv4-10.2.1.5
    - audit_rules_usergroup_modification_gshadow
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Record Events that Modify User/Group Information - /etc/gshadow - Use /etc/audit/rules.d/audit_rules_usergroup_modification.rules
      as the recipient for the rule
    ansible.builtin.set_fact:
      all_files:
      - /etc/audit/rules.d/audit_rules_usergroup_modification.rules
    when:
    - '"audit" in ansible_facts.packages'
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - find_watch_key.matched is defined and find_watch_key.matched == 0 and find_existing_watch_rules_d.matched
      is defined and find_existing_watch_rules_d.matched == 0
    tags:
    - CJIS-5.4.1.1
    - DISA-STIG-OL09-00-000515
    - NIST-800-171-3.1.7
    - NIST-800-53-AC-2(4)
    - NIST-800-53-AC-6(9)
    - NIST-800-53-AU-12(c)
    - NIST-800-53-AU-2(d)
    - NIST-800-53-CM-6(a)
    - PCI-DSS-Req-10.2.5
    - PCI-DSSv4-10.2
    - PCI-DSSv4-10.2.1
    - PCI-DSSv4-10.2.1.5
    - audit_rules_usergroup_modification_gshadow
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Record Events that Modify User/Group Information - /etc/gshadow - Use matched
      file as the recipient for the rule
    ansible.builtin.set_fact:
      all_files:
      - '{{ find_watch_key.files | map(attribute=''path'') | list | first }}'
    when:
    - '"audit" in ansible_facts.packages'
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - find_watch_key.matched is defined and find_watch_key.matched > 0 and find_existing_watch_rules_d.matched
      is defined and find_existing_watch_rules_d.matched == 0
    tags:
    - CJIS-5.4.1.1
    - DISA-STIG-OL09-00-000515
    - NIST-800-171-3.1.7
    - NIST-800-53-AC-2(4)
    - NIST-800-53-AC-6(9)
    - NIST-800-53-AU-12(c)
    - NIST-800-53-AU-2(d)
    - NIST-800-53-CM-6(a)
    - PCI-DSS-Req-10.2.5
    - PCI-DSSv4-10.2
    - PCI-DSSv4-10.2.1
    - PCI-DSSv4-10.2.1.5
    - audit_rules_usergroup_modification_gshadow
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Record Events that Modify User/Group Information - /etc/gshadow - Add watch
      rule for /etc/gshadow in /etc/audit/rules.d/
    ansible.builtin.lineinfile:
      path: '{{ all_files[0] }}'
      line: -w /etc/gshadow -p wa -k audit_rules_usergroup_modification
      create: true
      mode: '0600'
    when:
    - '"audit" in ansible_facts.packages'
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - find_existing_watch_rules_d.matched is defined and find_existing_watch_rules_d.matched
      == 0
    tags:
    - CJIS-5.4.1.1
    - DISA-STIG-OL09-00-000515
    - NIST-800-171-3.1.7
    - NIST-800-53-AC-2(4)
    - NIST-800-53-AC-6(9)
    - NIST-800-53-AU-12(c)
    - NIST-800-53-AU-2(d)
    - NIST-800-53-CM-6(a)
    - PCI-DSS-Req-10.2.5
    - PCI-DSSv4-10.2
    - PCI-DSSv4-10.2.1
    - PCI-DSSv4-10.2.1.5
    - audit_rules_usergroup_modification_gshadow
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Record Events that Modify User/Group Information - /etc/gshadow - Check
      if watch rule for /etc/gshadow already exists in /etc/audit/audit.rules
    ansible.builtin.find:
      paths: /etc/audit/
      contains: ^\s*-w\s+/etc/gshadow\s+-p\s+wa(\s|$)+
      patterns: audit.rules
    register: find_existing_watch_audit_rules
    when:
    - '"audit" in ansible_facts.packages'
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - CJIS-5.4.1.1
    - DISA-STIG-OL09-00-000515
    - NIST-800-171-3.1.7
    - NIST-800-53-AC-2(4)
    - NIST-800-53-AC-6(9)
    - NIST-800-53-AU-12(c)
    - NIST-800-53-AU-2(d)
    - NIST-800-53-CM-6(a)
    - PCI-DSS-Req-10.2.5
    - PCI-DSSv4-10.2
    - PCI-DSSv4-10.2.1
    - PCI-DSSv4-10.2.1.5
    - audit_rules_usergroup_modification_gshadow
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Record Events that Modify User/Group Information - /etc/gshadow - Add watch
      rule for /etc/gshadow in /etc/audit/audit.rules
    ansible.builtin.lineinfile:
      line: -w /etc/gshadow -p wa -k audit_rules_usergroup_modification
      state: present
      dest: /etc/audit/audit.rules
      create: true
      mode: '0600'
    when:
    - '"audit" in ansible_facts.packages'
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - find_existing_watch_audit_rules.matched is defined and find_existing_watch_audit_rules.matched
      == 0
    tags:
    - CJIS-5.4.1.1
    - DISA-STIG-OL09-00-000515
    - NIST-800-171-3.1.7
    - NIST-800-53-AC-2(4)
    - NIST-800-53-AC-6(9)
    - NIST-800-53-AU-12(c)
    - NIST-800-53-AU-2(d)
    - NIST-800-53-CM-6(a)
    - PCI-DSS-Req-10.2.5
    - PCI-DSSv4-10.2
    - PCI-DSSv4-10.2.1
    - PCI-DSSv4-10.2.1.5
    - audit_rules_usergroup_modification_gshadow
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Record Events that Modify User/Group Information - /etc/security/opasswd
      - Check if watch rule for /etc/security/opasswd already exists in /etc/audit/rules.d/
    ansible.builtin.find:
      paths: /etc/audit/rules.d
      contains: ^\s*-w\s+/etc/security/opasswd\s+-p\s+wa(\s|$)+
      patterns: '*.rules'
    register: find_existing_watch_rules_d
    when:
    - '"audit" in ansible_facts.packages'
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - CJIS-5.4.1.1
    - DISA-STIG-OL09-00-000520
    - NIST-800-171-3.1.7
    - NIST-800-53-AC-2(4)
    - NIST-800-53-AC-6(9)
    - NIST-800-53-AU-12(c)
    - NIST-800-53-AU-2(d)
    - NIST-800-53-CM-6(a)
    - PCI-DSS-Req-10.2.5
    - PCI-DSSv4-10.2
    - PCI-DSSv4-10.2.1
    - PCI-DSSv4-10.2.1.5
    - audit_rules_usergroup_modification_opasswd
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Record Events that Modify User/Group Information - /etc/security/opasswd
      - Search /etc/audit/rules.d for other rules with specified key audit_rules_usergroup_modification
    ansible.builtin.find:
      paths: /etc/audit/rules.d
      contains: ^.*(?:-F key=|-k\s+)audit_rules_usergroup_modification$
      patterns: '*.rules'
    register: find_watch_key
    when:
    - '"audit" in ansible_facts.packages'
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - find_existing_watch_rules_d.matched is defined and find_existing_watch_rules_d.matched
      == 0
    tags:
    - CJIS-5.4.1.1
    - DISA-STIG-OL09-00-000520
    - NIST-800-171-3.1.7
    - NIST-800-53-AC-2(4)
    - NIST-800-53-AC-6(9)
    - NIST-800-53-AU-12(c)
    - NIST-800-53-AU-2(d)
    - NIST-800-53-CM-6(a)
    - PCI-DSS-Req-10.2.5
    - PCI-DSSv4-10.2
    - PCI-DSSv4-10.2.1
    - PCI-DSSv4-10.2.1.5
    - audit_rules_usergroup_modification_opasswd
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Record Events that Modify User/Group Information - /etc/security/opasswd
      - Use /etc/audit/rules.d/audit_rules_usergroup_modification.rules as the recipient
      for the rule
    ansible.builtin.set_fact:
      all_files:
      - /etc/audit/rules.d/audit_rules_usergroup_modification.rules
    when:
    - '"audit" in ansible_facts.packages'
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - find_watch_key.matched is defined and find_watch_key.matched == 0 and find_existing_watch_rules_d.matched
      is defined and find_existing_watch_rules_d.matched == 0
    tags:
    - CJIS-5.4.1.1
    - DISA-STIG-OL09-00-000520
    - NIST-800-171-3.1.7
    - NIST-800-53-AC-2(4)
    - NIST-800-53-AC-6(9)
    - NIST-800-53-AU-12(c)
    - NIST-800-53-AU-2(d)
    - NIST-800-53-CM-6(a)
    - PCI-DSS-Req-10.2.5
    - PCI-DSSv4-10.2
    - PCI-DSSv4-10.2.1
    - PCI-DSSv4-10.2.1.5
    - audit_rules_usergroup_modification_opasswd
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Record Events that Modify User/Group Information - /etc/security/opasswd
      - Use matched file as the recipient for the rule
    ansible.builtin.set_fact:
      all_files:
      - '{{ find_watch_key.files | map(attribute=''path'') | list | first }}'
    when:
    - '"audit" in ansible_facts.packages'
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - find_watch_key.matched is defined and find_watch_key.matched > 0 and find_existing_watch_rules_d.matched
      is defined and find_existing_watch_rules_d.matched == 0
    tags:
    - CJIS-5.4.1.1
    - DISA-STIG-OL09-00-000520
    - NIST-800-171-3.1.7
    - NIST-800-53-AC-2(4)
    - NIST-800-53-AC-6(9)
    - NIST-800-53-AU-12(c)
    - NIST-800-53-AU-2(d)
    - NIST-800-53-CM-6(a)
    - PCI-DSS-Req-10.2.5
    - PCI-DSSv4-10.2
    - PCI-DSSv4-10.2.1
    - PCI-DSSv4-10.2.1.5
    - audit_rules_usergroup_modification_opasswd
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Record Events that Modify User/Group Information - /etc/security/opasswd
      - Add watch rule for /etc/security/opasswd in /etc/audit/rules.d/
    ansible.builtin.lineinfile:
      path: '{{ all_files[0] }}'
      line: -w /etc/security/opasswd -p wa -k audit_rules_usergroup_modification
      create: true
      mode: '0600'
    when:
    - '"audit" in ansible_facts.packages'
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - find_existing_watch_rules_d.matched is defined and find_existing_watch_rules_d.matched
      == 0
    tags:
    - CJIS-5.4.1.1
    - DISA-STIG-OL09-00-000520
    - NIST-800-171-3.1.7
    - NIST-800-53-AC-2(4)
    - NIST-800-53-AC-6(9)
    - NIST-800-53-AU-12(c)
    - NIST-800-53-AU-2(d)
    - NIST-800-53-CM-6(a)
    - PCI-DSS-Req-10.2.5
    - PCI-DSSv4-10.2
    - PCI-DSSv4-10.2.1
    - PCI-DSSv4-10.2.1.5
    - audit_rules_usergroup_modification_opasswd
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Record Events that Modify User/Group Information - /etc/security/opasswd
      - Check if watch rule for /etc/security/opasswd already exists in /etc/audit/audit.rules
    ansible.builtin.find:
      paths: /etc/audit/
      contains: ^\s*-w\s+/etc/security/opasswd\s+-p\s+wa(\s|$)+
      patterns: audit.rules
    register: find_existing_watch_audit_rules
    when:
    - '"audit" in ansible_facts.packages'
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - CJIS-5.4.1.1
    - DISA-STIG-OL09-00-000520
    - NIST-800-171-3.1.7
    - NIST-800-53-AC-2(4)
    - NIST-800-53-AC-6(9)
    - NIST-800-53-AU-12(c)
    - NIST-800-53-AU-2(d)
    - NIST-800-53-CM-6(a)
    - PCI-DSS-Req-10.2.5
    - PCI-DSSv4-10.2
    - PCI-DSSv4-10.2.1
    - PCI-DSSv4-10.2.1.5
    - audit_rules_usergroup_modification_opasswd
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Record Events that Modify User/Group Information - /etc/security/opasswd
      - Add watch rule for /etc/security/opasswd in /etc/audit/audit.rules
    ansible.builtin.lineinfile:
      line: -w /etc/security/opasswd -p wa -k audit_rules_usergroup_modification
      state: present
      dest: /etc/audit/audit.rules
      create: true
      mode: '0600'
    when:
    - '"audit" in ansible_facts.packages'
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - find_existing_watch_audit_rules.matched is defined and find_existing_watch_audit_rules.matched
      == 0
    tags:
    - CJIS-5.4.1.1
    - DISA-STIG-OL09-00-000520
    - NIST-800-171-3.1.7
    - NIST-800-53-AC-2(4)
    - NIST-800-53-AC-6(9)
    - NIST-800-53-AU-12(c)
    - NIST-800-53-AU-2(d)
    - NIST-800-53-CM-6(a)
    - PCI-DSS-Req-10.2.5
    - PCI-DSSv4-10.2
    - PCI-DSSv4-10.2.1
    - PCI-DSSv4-10.2.1.5
    - audit_rules_usergroup_modification_opasswd
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Record Events that Modify User/Group Information - /etc/passwd - Check if
      watch rule for /etc/passwd already exists in /etc/audit/rules.d/
    ansible.builtin.find:
      paths: /etc/audit/rules.d
      contains: ^\s*-w\s+/etc/passwd\s+-p\s+wa(\s|$)+
      patterns: '*.rules'
    register: find_existing_watch_rules_d
    when:
    - '"audit" in ansible_facts.packages'
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - CJIS-5.4.1.1
    - DISA-STIG-OL09-00-000525
    - NIST-800-171-3.1.7
    - NIST-800-53-AC-2(4)
    - NIST-800-53-AC-6(9)
    - NIST-800-53-AU-12(c)
    - NIST-800-53-AU-2(d)
    - NIST-800-53-CM-6(a)
    - PCI-DSS-Req-10.2.5
    - PCI-DSSv4-10.2
    - PCI-DSSv4-10.2.1
    - PCI-DSSv4-10.2.1.5
    - audit_rules_usergroup_modification_passwd
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Record Events that Modify User/Group Information - /etc/passwd - Search
      /etc/audit/rules.d for other rules with specified key audit_rules_usergroup_modification
    ansible.builtin.find:
      paths: /etc/audit/rules.d
      contains: ^.*(?:-F key=|-k\s+)audit_rules_usergroup_modification$
      patterns: '*.rules'
    register: find_watch_key
    when:
    - '"audit" in ansible_facts.packages'
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - find_existing_watch_rules_d.matched is defined and find_existing_watch_rules_d.matched
      == 0
    tags:
    - CJIS-5.4.1.1
    - DISA-STIG-OL09-00-000525
    - NIST-800-171-3.1.7
    - NIST-800-53-AC-2(4)
    - NIST-800-53-AC-6(9)
    - NIST-800-53-AU-12(c)
    - NIST-800-53-AU-2(d)
    - NIST-800-53-CM-6(a)
    - PCI-DSS-Req-10.2.5
    - PCI-DSSv4-10.2
    - PCI-DSSv4-10.2.1
    - PCI-DSSv4-10.2.1.5
    - audit_rules_usergroup_modification_passwd
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Record Events that Modify User/Group Information - /etc/passwd - Use /etc/audit/rules.d/audit_rules_usergroup_modification.rules
      as the recipient for the rule
    ansible.builtin.set_fact:
      all_files:
      - /etc/audit/rules.d/audit_rules_usergroup_modification.rules
    when:
    - '"audit" in ansible_facts.packages'
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - find_watch_key.matched is defined and find_watch_key.matched == 0 and find_existing_watch_rules_d.matched
      is defined and find_existing_watch_rules_d.matched == 0
    tags:
    - CJIS-5.4.1.1
    - DISA-STIG-OL09-00-000525
    - NIST-800-171-3.1.7
    - NIST-800-53-AC-2(4)
    - NIST-800-53-AC-6(9)
    - NIST-800-53-AU-12(c)
    - NIST-800-53-AU-2(d)
    - NIST-800-53-CM-6(a)
    - PCI-DSS-Req-10.2.5
    - PCI-DSSv4-10.2
    - PCI-DSSv4-10.2.1
    - PCI-DSSv4-10.2.1.5
    - audit_rules_usergroup_modification_passwd
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Record Events that Modify User/Group Information - /etc/passwd - Use matched
      file as the recipient for the rule
    ansible.builtin.set_fact:
      all_files:
      - '{{ find_watch_key.files | map(attribute=''path'') | list | first }}'
    when:
    - '"audit" in ansible_facts.packages'
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - find_watch_key.matched is defined and find_watch_key.matched > 0 and find_existing_watch_rules_d.matched
      is defined and find_existing_watch_rules_d.matched == 0
    tags:
    - CJIS-5.4.1.1
    - DISA-STIG-OL09-00-000525
    - NIST-800-171-3.1.7
    - NIST-800-53-AC-2(4)
    - NIST-800-53-AC-6(9)
    - NIST-800-53-AU-12(c)
    - NIST-800-53-AU-2(d)
    - NIST-800-53-CM-6(a)
    - PCI-DSS-Req-10.2.5
    - PCI-DSSv4-10.2
    - PCI-DSSv4-10.2.1
    - PCI-DSSv4-10.2.1.5
    - audit_rules_usergroup_modification_passwd
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Record Events that Modify User/Group Information - /etc/passwd - Add watch
      rule for /etc/passwd in /etc/audit/rules.d/
    ansible.builtin.lineinfile:
      path: '{{ all_files[0] }}'
      line: -w /etc/passwd -p wa -k audit_rules_usergroup_modification
      create: true
      mode: '0600'
    when:
    - '"audit" in ansible_facts.packages'
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - find_existing_watch_rules_d.matched is defined and find_existing_watch_rules_d.matched
      == 0
    tags:
    - CJIS-5.4.1.1
    - DISA-STIG-OL09-00-000525
    - NIST-800-171-3.1.7
    - NIST-800-53-AC-2(4)
    - NIST-800-53-AC-6(9)
    - NIST-800-53-AU-12(c)
    - NIST-800-53-AU-2(d)
    - NIST-800-53-CM-6(a)
    - PCI-DSS-Req-10.2.5
    - PCI-DSSv4-10.2
    - PCI-DSSv4-10.2.1
    - PCI-DSSv4-10.2.1.5
    - audit_rules_usergroup_modification_passwd
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Record Events that Modify User/Group Information - /etc/passwd - Check if
      watch rule for /etc/passwd already exists in /etc/audit/audit.rules
    ansible.builtin.find:
      paths: /etc/audit/
      contains: ^\s*-w\s+/etc/passwd\s+-p\s+wa(\s|$)+
      patterns: audit.rules
    register: find_existing_watch_audit_rules
    when:
    - '"audit" in ansible_facts.packages'
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - CJIS-5.4.1.1
    - DISA-STIG-OL09-00-000525
    - NIST-800-171-3.1.7
    - NIST-800-53-AC-2(4)
    - NIST-800-53-AC-6(9)
    - NIST-800-53-AU-12(c)
    - NIST-800-53-AU-2(d)
    - NIST-800-53-CM-6(a)
    - PCI-DSS-Req-10.2.5
    - PCI-DSSv4-10.2
    - PCI-DSSv4-10.2.1
    - PCI-DSSv4-10.2.1.5
    - audit_rules_usergroup_modification_passwd
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Record Events that Modify User/Group Information - /etc/passwd - Add watch
      rule for /etc/passwd in /etc/audit/audit.rules
    ansible.builtin.lineinfile:
      line: -w /etc/passwd -p wa -k audit_rules_usergroup_modification
      state: present
      dest: /etc/audit/audit.rules
      create: true
      mode: '0600'
    when:
    - '"audit" in ansible_facts.packages'
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - find_existing_watch_audit_rules.matched is defined and find_existing_watch_audit_rules.matched
      == 0
    tags:
    - CJIS-5.4.1.1
    - DISA-STIG-OL09-00-000525
    - NIST-800-171-3.1.7
    - NIST-800-53-AC-2(4)
    - NIST-800-53-AC-6(9)
    - NIST-800-53-AU-12(c)
    - NIST-800-53-AU-2(d)
    - NIST-800-53-CM-6(a)
    - PCI-DSS-Req-10.2.5
    - PCI-DSSv4-10.2
    - PCI-DSSv4-10.2.1
    - PCI-DSSv4-10.2.1.5
    - audit_rules_usergroup_modification_passwd
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Record Events that Modify User/Group Information - /etc/shadow - Check if
      watch rule for /etc/shadow already exists in /etc/audit/rules.d/
    ansible.builtin.find:
      paths: /etc/audit/rules.d
      contains: ^\s*-w\s+/etc/shadow\s+-p\s+wa(\s|$)+
      patterns: '*.rules'
    register: find_existing_watch_rules_d
    when:
    - '"audit" in ansible_facts.packages'
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - CJIS-5.4.1.1
    - DISA-STIG-OL09-00-000530
    - NIST-800-171-3.1.7
    - NIST-800-53-AC-2(4)
    - NIST-800-53-AC-6(9)
    - NIST-800-53-AU-12(c)
    - NIST-800-53-AU-2(d)
    - NIST-800-53-CM-6(a)
    - PCI-DSS-Req-10.2.5
    - PCI-DSSv4-10.2
    - PCI-DSSv4-10.2.1
    - PCI-DSSv4-10.2.1.5
    - audit_rules_usergroup_modification_shadow
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Record Events that Modify User/Group Information - /etc/shadow - Search
      /etc/audit/rules.d for other rules with specified key audit_rules_usergroup_modification
    ansible.builtin.find:
      paths: /etc/audit/rules.d
      contains: ^.*(?:-F key=|-k\s+)audit_rules_usergroup_modification$
      patterns: '*.rules'
    register: find_watch_key
    when:
    - '"audit" in ansible_facts.packages'
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - find_existing_watch_rules_d.matched is defined and find_existing_watch_rules_d.matched
      == 0
    tags:
    - CJIS-5.4.1.1
    - DISA-STIG-OL09-00-000530
    - NIST-800-171-3.1.7
    - NIST-800-53-AC-2(4)
    - NIST-800-53-AC-6(9)
    - NIST-800-53-AU-12(c)
    - NIST-800-53-AU-2(d)
    - NIST-800-53-CM-6(a)
    - PCI-DSS-Req-10.2.5
    - PCI-DSSv4-10.2
    - PCI-DSSv4-10.2.1
    - PCI-DSSv4-10.2.1.5
    - audit_rules_usergroup_modification_shadow
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Record Events that Modify User/Group Information - /etc/shadow - Use /etc/audit/rules.d/audit_rules_usergroup_modification.rules
      as the recipient for the rule
    ansible.builtin.set_fact:
      all_files:
      - /etc/audit/rules.d/audit_rules_usergroup_modification.rules
    when:
    - '"audit" in ansible_facts.packages'
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - find_watch_key.matched is defined and find_watch_key.matched == 0 and find_existing_watch_rules_d.matched
      is defined and find_existing_watch_rules_d.matched == 0
    tags:
    - CJIS-5.4.1.1
    - DISA-STIG-OL09-00-000530
    - NIST-800-171-3.1.7
    - NIST-800-53-AC-2(4)
    - NIST-800-53-AC-6(9)
    - NIST-800-53-AU-12(c)
    - NIST-800-53-AU-2(d)
    - NIST-800-53-CM-6(a)
    - PCI-DSS-Req-10.2.5
    - PCI-DSSv4-10.2
    - PCI-DSSv4-10.2.1
    - PCI-DSSv4-10.2.1.5
    - audit_rules_usergroup_modification_shadow
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Record Events that Modify User/Group Information - /etc/shadow - Use matched
      file as the recipient for the rule
    ansible.builtin.set_fact:
      all_files:
      - '{{ find_watch_key.files | map(attribute=''path'') | list | first }}'
    when:
    - '"audit" in ansible_facts.packages'
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - find_watch_key.matched is defined and find_watch_key.matched > 0 and find_existing_watch_rules_d.matched
      is defined and find_existing_watch_rules_d.matched == 0
    tags:
    - CJIS-5.4.1.1
    - DISA-STIG-OL09-00-000530
    - NIST-800-171-3.1.7
    - NIST-800-53-AC-2(4)
    - NIST-800-53-AC-6(9)
    - NIST-800-53-AU-12(c)
    - NIST-800-53-AU-2(d)
    - NIST-800-53-CM-6(a)
    - PCI-DSS-Req-10.2.5
    - PCI-DSSv4-10.2
    - PCI-DSSv4-10.2.1
    - PCI-DSSv4-10.2.1.5
    - audit_rules_usergroup_modification_shadow
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Record Events that Modify User/Group Information - /etc/shadow - Add watch
      rule for /etc/shadow in /etc/audit/rules.d/
    ansible.builtin.lineinfile:
      path: '{{ all_files[0] }}'
      line: -w /etc/shadow -p wa -k audit_rules_usergroup_modification
      create: true
      mode: '0600'
    when:
    - '"audit" in ansible_facts.packages'
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - find_existing_watch_rules_d.matched is defined and find_existing_watch_rules_d.matched
      == 0
    tags:
    - CJIS-5.4.1.1
    - DISA-STIG-OL09-00-000530
    - NIST-800-171-3.1.7
    - NIST-800-53-AC-2(4)
    - NIST-800-53-AC-6(9)
    - NIST-800-53-AU-12(c)
    - NIST-800-53-AU-2(d)
    - NIST-800-53-CM-6(a)
    - PCI-DSS-Req-10.2.5
    - PCI-DSSv4-10.2
    - PCI-DSSv4-10.2.1
    - PCI-DSSv4-10.2.1.5
    - audit_rules_usergroup_modification_shadow
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Record Events that Modify User/Group Information - /etc/shadow - Check if
      watch rule for /etc/shadow already exists in /etc/audit/audit.rules
    ansible.builtin.find:
      paths: /etc/audit/
      contains: ^\s*-w\s+/etc/shadow\s+-p\s+wa(\s|$)+
      patterns: audit.rules
    register: find_existing_watch_audit_rules
    when:
    - '"audit" in ansible_facts.packages'
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - CJIS-5.4.1.1
    - DISA-STIG-OL09-00-000530
    - NIST-800-171-3.1.7
    - NIST-800-53-AC-2(4)
    - NIST-800-53-AC-6(9)
    - NIST-800-53-AU-12(c)
    - NIST-800-53-AU-2(d)
    - NIST-800-53-CM-6(a)
    - PCI-DSS-Req-10.2.5
    - PCI-DSSv4-10.2
    - PCI-DSSv4-10.2.1
    - PCI-DSSv4-10.2.1.5
    - audit_rules_usergroup_modification_shadow
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Record Events that Modify User/Group Information - /etc/shadow - Add watch
      rule for /etc/shadow in /etc/audit/audit.rules
    ansible.builtin.lineinfile:
      line: -w /etc/shadow -p wa -k audit_rules_usergroup_modification
      state: present
      dest: /etc/audit/audit.rules
      create: true
      mode: '0600'
    when:
    - '"audit" in ansible_facts.packages'
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - find_existing_watch_audit_rules.matched is defined and find_existing_watch_audit_rules.matched
      == 0
    tags:
    - CJIS-5.4.1.1
    - DISA-STIG-OL09-00-000530
    - NIST-800-171-3.1.7
    - NIST-800-53-AC-2(4)
    - NIST-800-53-AC-6(9)
    - NIST-800-53-AU-12(c)
    - NIST-800-53-AU-2(d)
    - NIST-800-53-CM-6(a)
    - PCI-DSS-Req-10.2.5
    - PCI-DSSv4-10.2
    - PCI-DSSv4-10.2.1
    - PCI-DSSv4-10.2.1.5
    - audit_rules_usergroup_modification_shadow
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Ensure auditd Collects Changes to Cron Jobs - /var/spool/cron - Check if
      watch rule for /var/spool/cron already exists in /etc/audit/rules.d/
    ansible.builtin.find:
      paths: /etc/audit/rules.d
      contains: ^\s*-w\s+/var/spool/cron\s+-p\s+wa(\s|$)+
      patterns: '*.rules'
    register: find_existing_watch_rules_d
    when:
    - '"audit" in ansible_facts.packages'
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-002584
    - audit_rules_var_spool_cron
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Ensure auditd Collects Changes to Cron Jobs - /var/spool/cron - Search /etc/audit/rules.d
      for other rules with specified key cronjobs
    ansible.builtin.find:
      paths: /etc/audit/rules.d
      contains: ^.*(?:-F key=|-k\s+)cronjobs$
      patterns: '*.rules'
    register: find_watch_key
    when:
    - '"audit" in ansible_facts.packages'
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - find_existing_watch_rules_d.matched is defined and find_existing_watch_rules_d.matched
      == 0
    tags:
    - DISA-STIG-OL09-00-002584
    - audit_rules_var_spool_cron
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Ensure auditd Collects Changes to Cron Jobs - /var/spool/cron - Use /etc/audit/rules.d/cronjobs.rules
      as the recipient for the rule
    ansible.builtin.set_fact:
      all_files:
      - /etc/audit/rules.d/cronjobs.rules
    when:
    - '"audit" in ansible_facts.packages'
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - find_watch_key.matched is defined and find_watch_key.matched == 0 and find_existing_watch_rules_d.matched
      is defined and find_existing_watch_rules_d.matched == 0
    tags:
    - DISA-STIG-OL09-00-002584
    - audit_rules_var_spool_cron
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Ensure auditd Collects Changes to Cron Jobs - /var/spool/cron - Use matched
      file as the recipient for the rule
    ansible.builtin.set_fact:
      all_files:
      - '{{ find_watch_key.files | map(attribute=''path'') | list | first }}'
    when:
    - '"audit" in ansible_facts.packages'
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - find_watch_key.matched is defined and find_watch_key.matched > 0 and find_existing_watch_rules_d.matched
      is defined and find_existing_watch_rules_d.matched == 0
    tags:
    - DISA-STIG-OL09-00-002584
    - audit_rules_var_spool_cron
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Ensure auditd Collects Changes to Cron Jobs - /var/spool/cron - Add watch
      rule for /var/spool/cron in /etc/audit/rules.d/
    ansible.builtin.lineinfile:
      path: '{{ all_files[0] }}'
      line: -w /var/spool/cron -p wa -k cronjobs
      create: true
      mode: '0600'
    when:
    - '"audit" in ansible_facts.packages'
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - find_existing_watch_rules_d.matched is defined and find_existing_watch_rules_d.matched
      == 0
    tags:
    - DISA-STIG-OL09-00-002584
    - audit_rules_var_spool_cron
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Ensure auditd Collects Changes to Cron Jobs - /var/spool/cron - Check if
      watch rule for /var/spool/cron already exists in /etc/audit/audit.rules
    ansible.builtin.find:
      paths: /etc/audit/
      contains: ^\s*-w\s+/var/spool/cron\s+-p\s+wa(\s|$)+
      patterns: audit.rules
    register: find_existing_watch_audit_rules
    when:
    - '"audit" in ansible_facts.packages'
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-002584
    - audit_rules_var_spool_cron
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Ensure auditd Collects Changes to Cron Jobs - /var/spool/cron - Add watch
      rule for /var/spool/cron in /etc/audit/audit.rules
    ansible.builtin.lineinfile:
      line: -w /var/spool/cron -p wa -k cronjobs
      state: present
      dest: /etc/audit/audit.rules
      create: true
      mode: '0600'
    when:
    - '"audit" in ansible_facts.packages'
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - find_existing_watch_audit_rules.matched is defined and find_existing_watch_audit_rules.matched
      == 0
    tags:
    - DISA-STIG-OL09-00-002584
    - audit_rules_var_spool_cron
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: System Audit Directories Must Be Group Owned By Root - Register Audit Configuration
      Text
    ansible.builtin.slurp:
      src: /etc/audit/auditd.conf
    register: auditd_config_slurp
    when:
    - '"audit" in ansible_facts.packages'
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - CJIS-5.4.1.1
    - DISA-STIG-OL09-00-000785
    - NIST-800-171-3.3.1
    - NIST-800-53-AC-6(1)
    - NIST-800-53-AU-9(4)
    - NIST-800-53-CM-6(a)
    - PCI-DSS-Req-10.5.1
    - configure_strategy
    - directory_group_ownership_var_log_audit
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

  - name: System Audit Directories Must Be Group Owned By Root - Set Permissions Custom
      Location
    ansible.builtin.file:
      group: |-
        {{ auditd_config_slurp['content'] | b64decode | regex_findall('
        log_group\s*=\s*(.+)') | default(['root',], boolean=True) | first }}
      path: |-
        {{ auditd_config_slurp['content'] | b64decode | regex_findall('
        log_file\s*=\s*(.+)') | default(['/var/log/audit/audit.log',], boolean=True) | first | dirname }}
    when:
    - '"audit" in ansible_facts.packages'
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - CJIS-5.4.1.1
    - DISA-STIG-OL09-00-000785
    - NIST-800-171-3.3.1
    - NIST-800-53-AC-6(1)
    - NIST-800-53-AU-9(4)
    - NIST-800-53-CM-6(a)
    - PCI-DSS-Req-10.5.1
    - configure_strategy
    - directory_group_ownership_var_log_audit
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

  - name: System Audit Directories Must Be Owned By Root - Register Audit Configuration
      Text
    ansible.builtin.slurp:
      src: /etc/audit/auditd.conf
    register: auditd_config_slurp
    when:
    - '"audit" in ansible_facts.packages'
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - CJIS-5.4.1.1
    - DISA-STIG-OL09-00-000790
    - NIST-800-171-3.3.1
    - NIST-800-53-AC-6(1)
    - NIST-800-53-AU-9(4)
    - NIST-800-53-CM-6(a)
    - PCI-DSS-Req-10.5.1
    - configure_strategy
    - directory_ownership_var_log_audit
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

  - name: System Audit Directories Must Be Owned By Root - Set Permissions Custom
      Location
    ansible.builtin.file:
      owner: root
      path: |-
        {{ auditd_config_slurp['content'] | b64decode | regex_findall('
        log_file\s*=\s*(.+)') | default(['/var/log/audit/audit.log',], boolean=True) | first | dirname }}
    when:
    - '"audit" in ansible_facts.packages'
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - CJIS-5.4.1.1
    - DISA-STIG-OL09-00-000790
    - NIST-800-171-3.3.1
    - NIST-800-53-AC-6(1)
    - NIST-800-53-AU-9(4)
    - NIST-800-53-CM-6(a)
    - PCI-DSS-Req-10.5.1
    - configure_strategy
    - directory_ownership_var_log_audit
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

  - name: Find /etc/audit/ file(s)
    ansible.builtin.command: find -P /etc/audit/ -maxdepth 1 -perm /u+xs,g+xws,o+xwrt  -type
      f -regextype posix-extended -regex "^.*audit(\.rules|d\.conf)$"
    register: files_found
    changed_when: false
    failed_when: false
    check_mode: false
    when:
    - '"audit" in ansible_facts.packages'
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-000805
    - NIST-800-53-AU-12 b
    - configure_strategy
    - file_permissions_audit_configuration
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

  - name: Set permissions for /etc/audit/ file(s)
    ansible.builtin.file:
      path: '{{ item }}'
      mode: u-xs,g-xws,o-xwrt
      state: file
    with_items:
    - '{{ files_found.stdout_lines }}'
    when:
    - '"audit" in ansible_facts.packages'
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-000805
    - NIST-800-53-AU-12 b
    - configure_strategy
    - file_permissions_audit_configuration
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

  - name: Find /etc/audit/rules.d/ file(s)
    ansible.builtin.command: find -P /etc/audit/rules.d/ -maxdepth 1 -perm /u+xs,g+xws,o+xwrt  -type
      f -regextype posix-extended -regex "^.*\.rules$"
    register: files_found
    changed_when: false
    failed_when: false
    check_mode: false
    when:
    - '"audit" in ansible_facts.packages'
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-000805
    - NIST-800-53-AU-12 b
    - configure_strategy
    - file_permissions_audit_configuration
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

  - name: Set permissions for /etc/audit/rules.d/ file(s)
    ansible.builtin.file:
      path: '{{ item }}'
      mode: u-xs,g-xws,o-xwrt
      state: file
    with_items:
    - '{{ files_found.stdout_lines }}'
    when:
    - '"audit" in ansible_facts.packages'
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-000805
    - NIST-800-53-AU-12 b
    - configure_strategy
    - file_permissions_audit_configuration
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

  - name: System Audit Logs Must Have Mode 0640 or Less Permissive - Get audit log
      file from /etc/audit/auditd.conf
    ansible.builtin.command: grep -iw ^log_file /etc/audit/auditd.conf
    check_mode: false
    failed_when: false
    changed_when: false
    register: log_file_exists
    when:
    - '"audit" in ansible_facts.packages'
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - CJIS-5.4.1.1
    - DISA-STIG-OL09-00-000795
    - NIST-800-171-3.3.1
    - NIST-800-53-AC-6(1)
    - NIST-800-53-AU-9(4)
    - NIST-800-53-CM-6(a)
    - PCI-DSS-Req-10.5
    - PCI-DSSv4-10.3
    - PCI-DSSv4-10.3.1
    - file_permissions_var_log_audit
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: System Audit Logs Must Have Mode 0640 or Less Permissive - Set audit log
      file path
    ansible.builtin.set_fact:
      log_file_path: '{{ (log_file_exists.stdout | default('''') | split('' '') |
        last) | default(''/var/log/audit/audit.log'', true) }}'
    when:
    - '"audit" in ansible_facts.packages'
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - CJIS-5.4.1.1
    - DISA-STIG-OL09-00-000795
    - NIST-800-171-3.3.1
    - NIST-800-53-AC-6(1)
    - NIST-800-53-AU-9(4)
    - NIST-800-53-CM-6(a)
    - PCI-DSS-Req-10.5
    - PCI-DSSv4-10.3
    - PCI-DSSv4-10.3.1
    - file_permissions_var_log_audit
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: System Audit Logs Must Have Mode 0640 or Less Permissive - Get audit log
      group from /etc/audit/auditd.conf
    ansible.builtin.command: grep -iw ^log_group /etc/audit/auditd.conf
    check_mode: false
    failed_when: false
    changed_when: false
    register: log_group_exists
    when:
    - '"audit" in ansible_facts.packages'
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - CJIS-5.4.1.1
    - DISA-STIG-OL09-00-000795
    - NIST-800-171-3.3.1
    - NIST-800-53-AC-6(1)
    - NIST-800-53-AU-9(4)
    - NIST-800-53-CM-6(a)
    - PCI-DSS-Req-10.5
    - PCI-DSSv4-10.3
    - PCI-DSSv4-10.3.1
    - file_permissions_var_log_audit
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: System Audit Logs Must Have Mode 0640 or Less Permissive - Set audit log
      group
    ansible.builtin.set_fact:
      log_group: '{{ (log_group_exists.stdout | default('''') | split('' '') | last)
        | default(''root'', true) }}'
    when:
    - '"audit" in ansible_facts.packages'
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - CJIS-5.4.1.1
    - DISA-STIG-OL09-00-000795
    - NIST-800-171-3.3.1
    - NIST-800-53-AC-6(1)
    - NIST-800-53-AU-9(4)
    - NIST-800-53-CM-6(a)
    - PCI-DSS-Req-10.5
    - PCI-DSSv4-10.3
    - PCI-DSSv4-10.3.1
    - file_permissions_var_log_audit
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: System Audit Logs Must Have Mode 0640 or Less Permissive - Set audit log
      file permissions
    ansible.builtin.file:
      path: '{{ log_file_path }}'
      state: file
      mode: '{{ ''0600'' if log_group == ''root'' else ''0640'' }}'
    when:
    - '"audit" in ansible_facts.packages'
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - CJIS-5.4.1.1
    - DISA-STIG-OL09-00-000795
    - NIST-800-171-3.3.1
    - NIST-800-53-AC-6(1)
    - NIST-800-53-AU-9(4)
    - NIST-800-53-CM-6(a)
    - PCI-DSS-Req-10.5
    - PCI-DSSv4-10.3
    - PCI-DSSv4-10.3.1
    - file_permissions_var_log_audit
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Set architecture for audit chmod tasks
    ansible.builtin.set_fact:
      audit_arch: b64
    when:
    - '"audit" in ansible_facts.packages'
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - not ( ansible_architecture == "aarch64" )
    - ansible_architecture == "aarch64" or ansible_architecture == "ppc64" or ansible_architecture
      == "ppc64le" or ansible_architecture == "s390x" or ansible_architecture == "x86_64"
    tags:
    - CJIS-5.4.1.1
    - DISA-STIG-OL09-00-000640
    - NIST-800-171-3.1.7
    - NIST-800-53-AU-12(c)
    - NIST-800-53-AU-2(d)
    - NIST-800-53-CM-6(a)
    - PCI-DSS-Req-10.5.5
    - PCI-DSSv4-10.3
    - PCI-DSSv4-10.3.4
    - audit_rules_dac_modification_chmod
    - low_complexity
    - low_disruption
    - medium_severity
    - reboot_required
    - restrict_strategy

  - name: Perform remediation of Audit rules for chmod for 32bit platform
    block:

    - name: Declare list of syscalls
      ansible.builtin.set_fact:
        syscalls:
        - chmod
        syscall_grouping:
        - chmod
        - fchmod
        - fchmodat

    - name: Check existence of chmod in /etc/audit/rules.d/
      ansible.builtin.find:
        paths: /etc/audit/rules.d
        contains: -a always,exit -F arch=b32(( -S |,)\w+)*(( -S |,){{ item }})+((
          -S |,)\w+)* -F auid>=1000 -F auid!=unset (-k\s+|-F\s+key=)\S+\s*$
        patterns: '*.rules'
      register: find_command
      loop: '{{ (syscall_grouping + syscalls) | unique }}'

    - name: Reset syscalls found per file
      ansible.builtin.set_fact:
        syscalls_per_file: {}
        found_paths_dict: {}

    - name: Declare syscalls found per file
      ansible.builtin.set_fact: syscalls_per_file="{{ syscalls_per_file | combine(
        {item.files[0].path :[item.item] + syscalls_per_file.get(item.files[0].path,
        []) } ) }}"
      loop: '{{ find_command.results | selectattr(''matched'') | list }}'

    - name: Declare files where syscalls were found
      ansible.builtin.set_fact: found_paths="{{ find_command.results | map(attribute='files')
        | flatten | map(attribute='path') | list }}"

    - name: Count occurrences of syscalls in paths
      ansible.builtin.set_fact: found_paths_dict="{{ found_paths_dict | combine({
        item:1+found_paths_dict.get(item, 0) }) }}"
      loop: '{{ find_command.results | map(attribute=''files'') | flatten | map(attribute=''path'')
        | list }}'

    - name: Get path with most syscalls
      ansible.builtin.set_fact: audit_file="{{ (found_paths_dict | dict2items() |
        sort(attribute='value') | last).key }}"
      when: found_paths | length >= 1

    - name: No file with syscall found, set path to /etc/audit/rules.d/perm_mod.rules
      ansible.builtin.set_fact: audit_file="/etc/audit/rules.d/perm_mod.rules"
      when: found_paths | length == 0

    - name: Declare found syscalls
      ansible.builtin.set_fact: syscalls_found="{{ find_command.results | selectattr('matched')
        | map(attribute='item') | list }}"

    - name: Declare missing syscalls
      ansible.builtin.set_fact: missing_syscalls="{{ syscalls | difference(syscalls_found)
        }}"

    - name: Replace the audit rule in {{ audit_file }}
      ansible.builtin.lineinfile:
        path: '{{ audit_file }}'
        regexp: (-a always,exit -F arch=b32)(?=.*(?:(?:-S |,)(?:{{ syscalls_per_file[audit_file]
          | join("|") }}))\b)((?:( -S |,)\w+)+)( -F auid>=1000 -F auid!=unset (?:-k
          |-F key=)\w+)
        line: \1\2\3{{ missing_syscalls | join("\3") }}\4
        backrefs: true
        state: present
        mode: g-rwx,o-rwx
      when: syscalls_found | length > 0 and missing_syscalls | length > 0

    - name: Add the audit rule to {{ audit_file }}
      ansible.builtin.lineinfile:
        path: '{{ audit_file }}'
        line: -a always,exit -F arch=b32 -S {{ syscalls | join(',') }} -F auid>=1000
          -F auid!=unset -F key=perm_mod
        create: true
        mode: g-rwx,o-rwx
        state: present
      when: syscalls_found | length == 0

    - name: Declare list of syscalls
      ansible.builtin.set_fact:
        syscalls:
        - chmod
        syscall_grouping:
        - chmod
        - fchmod
        - fchmodat

    - name: Check existence of chmod in /etc/audit/audit.rules
      ansible.builtin.find:
        paths: /etc/audit
        contains: -a always,exit -F arch=b32(( -S |,)\w+)*(( -S |,){{ item }})+((
          -S |,)\w+)* -F auid>=1000 -F auid!=unset (-k\s+|-F\s+key=)\S+\s*$
        patterns: audit.rules
      register: find_command
      loop: '{{ (syscall_grouping + syscalls) | unique }}'

    - name: Set path to /etc/audit/audit.rules
      ansible.builtin.set_fact: audit_file="/etc/audit/audit.rules"

    - name: Declare found syscalls
      ansible.builtin.set_fact: syscalls_found="{{ find_command.results | selectattr('matched')
        | map(attribute='item') | list }}"

    - name: Declare missing syscalls
      ansible.builtin.set_fact: missing_syscalls="{{ syscalls | difference(syscalls_found)
        }}"

    - name: Replace the audit rule in {{ audit_file }}
      ansible.builtin.lineinfile:
        path: '{{ audit_file }}'
        regexp: (-a always,exit -F arch=b32)(?=.*(?:(?:-S |,)(?:{{ syscalls_found
          | join("|") }}))\b)((?:( -S |,)\w+)+)( -F auid>=1000 -F auid!=unset (?:-k
          |-F key=)\w+)
        line: \1\2\3{{ missing_syscalls | join("\3") }}\4
        backrefs: true
        state: present
        mode: g-rwx,o-rwx
      when: syscalls_found | length > 0 and missing_syscalls | length > 0

    - name: Add the audit rule to {{ audit_file }}
      ansible.builtin.lineinfile:
        path: '{{ audit_file }}'
        line: -a always,exit -F arch=b32 -S {{ syscalls | join(',') }} -F auid>=1000
          -F auid!=unset -F key=perm_mod
        create: true
        mode: g-rwx,o-rwx
        state: present
      when: syscalls_found | length == 0
    when:
    - '"audit" in ansible_facts.packages'
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - not ( ansible_architecture == "aarch64" )
    tags:
    - CJIS-5.4.1.1
    - DISA-STIG-OL09-00-000640
    - NIST-800-171-3.1.7
    - NIST-800-53-AU-12(c)
    - NIST-800-53-AU-2(d)
    - NIST-800-53-CM-6(a)
    - PCI-DSS-Req-10.5.5
    - PCI-DSSv4-10.3
    - PCI-DSSv4-10.3.4
    - audit_rules_dac_modification_chmod
    - low_complexity
    - low_disruption
    - medium_severity
    - reboot_required
    - restrict_strategy

  - name: Perform remediation of Audit rules for chmod for 64bit platform
    block:

    - name: Declare list of syscalls
      ansible.builtin.set_fact:
        syscalls:
        - chmod
        syscall_grouping:
        - chmod
        - fchmod
        - fchmodat

    - name: Check existence of chmod in /etc/audit/rules.d/
      ansible.builtin.find:
        paths: /etc/audit/rules.d
        contains: -a always,exit -F arch=b64(( -S |,)\w+)*(( -S |,){{ item }})+((
          -S |,)\w+)* -F auid>=1000 -F auid!=unset (-k\s+|-F\s+key=)\S+\s*$
        patterns: '*.rules'
      register: find_command
      loop: '{{ (syscall_grouping + syscalls) | unique }}'

    - name: Reset syscalls found per file
      ansible.builtin.set_fact:
        syscalls_per_file: {}
        found_paths_dict: {}

    - name: Declare syscalls found per file
      ansible.builtin.set_fact: syscalls_per_file="{{ syscalls_per_file | combine(
        {item.files[0].path :[item.item] + syscalls_per_file.get(item.files[0].path,
        []) } ) }}"
      loop: '{{ find_command.results | selectattr(''matched'') | list }}'

    - name: Declare files where syscalls were found
      ansible.builtin.set_fact: found_paths="{{ find_command.results | map(attribute='files')
        | flatten | map(attribute='path') | list }}"

    - name: Count occurrences of syscalls in paths
      ansible.builtin.set_fact: found_paths_dict="{{ found_paths_dict | combine({
        item:1+found_paths_dict.get(item, 0) }) }}"
      loop: '{{ find_command.results | map(attribute=''files'') | flatten | map(attribute=''path'')
        | list }}'

    - name: Get path with most syscalls
      ansible.builtin.set_fact: audit_file="{{ (found_paths_dict | dict2items() |
        sort(attribute='value') | last).key }}"
      when: found_paths | length >= 1

    - name: No file with syscall found, set path to /etc/audit/rules.d/perm_mod.rules
      ansible.builtin.set_fact: audit_file="/etc/audit/rules.d/perm_mod.rules"
      when: found_paths | length == 0

    - name: Declare found syscalls
      ansible.builtin.set_fact: syscalls_found="{{ find_command.results | selectattr('matched')
        | map(attribute='item') | list }}"

    - name: Declare missing syscalls
      ansible.builtin.set_fact: missing_syscalls="{{ syscalls | difference(syscalls_found)
        }}"

    - name: Replace the audit rule in {{ audit_file }}
      ansible.builtin.lineinfile:
        path: '{{ audit_file }}'
        regexp: (-a always,exit -F arch=b64)(?=.*(?:(?:-S |,)(?:{{ syscalls_per_file[audit_file]
          | join("|") }}))\b)((?:( -S |,)\w+)+)( -F auid>=1000 -F auid!=unset (?:-k
          |-F key=)\w+)
        line: \1\2\3{{ missing_syscalls | join("\3") }}\4
        backrefs: true
        state: present
        mode: g-rwx,o-rwx
      when: syscalls_found | length > 0 and missing_syscalls | length > 0

    - name: Add the audit rule to {{ audit_file }}
      ansible.builtin.lineinfile:
        path: '{{ audit_file }}'
        line: -a always,exit -F arch=b64 -S {{ syscalls | join(',') }} -F auid>=1000
          -F auid!=unset -F key=perm_mod
        create: true
        mode: g-rwx,o-rwx
        state: present
      when: syscalls_found | length == 0

    - name: Declare list of syscalls
      ansible.builtin.set_fact:
        syscalls:
        - chmod
        syscall_grouping:
        - chmod
        - fchmod
        - fchmodat

    - name: Check existence of chmod in /etc/audit/audit.rules
      ansible.builtin.find:
        paths: /etc/audit
        contains: -a always,exit -F arch=b64(( -S |,)\w+)*(( -S |,){{ item }})+((
          -S |,)\w+)* -F auid>=1000 -F auid!=unset (-k\s+|-F\s+key=)\S+\s*$
        patterns: audit.rules
      register: find_command
      loop: '{{ (syscall_grouping + syscalls) | unique }}'

    - name: Set path to /etc/audit/audit.rules
      ansible.builtin.set_fact: audit_file="/etc/audit/audit.rules"

    - name: Declare found syscalls
      ansible.builtin.set_fact: syscalls_found="{{ find_command.results | selectattr('matched')
        | map(attribute='item') | list }}"

    - name: Declare missing syscalls
      ansible.builtin.set_fact: missing_syscalls="{{ syscalls | difference(syscalls_found)
        }}"

    - name: Replace the audit rule in {{ audit_file }}
      ansible.builtin.lineinfile:
        path: '{{ audit_file }}'
        regexp: (-a always,exit -F arch=b64)(?=.*(?:(?:-S |,)(?:{{ syscalls_found
          | join("|") }}))\b)((?:( -S |,)\w+)+)( -F auid>=1000 -F auid!=unset (?:-k
          |-F key=)\w+)
        line: \1\2\3{{ missing_syscalls | join("\3") }}\4
        backrefs: true
        state: present
        mode: g-rwx,o-rwx
      when: syscalls_found | length > 0 and missing_syscalls | length > 0

    - name: Add the audit rule to {{ audit_file }}
      ansible.builtin.lineinfile:
        path: '{{ audit_file }}'
        line: -a always,exit -F arch=b64 -S {{ syscalls | join(',') }} -F auid>=1000
          -F auid!=unset -F key=perm_mod
        create: true
        mode: g-rwx,o-rwx
        state: present
      when: syscalls_found | length == 0
    when:
    - '"audit" in ansible_facts.packages'
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - not ( ansible_architecture == "aarch64" )
    - audit_arch == "b64"
    tags:
    - CJIS-5.4.1.1
    - DISA-STIG-OL09-00-000640
    - NIST-800-171-3.1.7
    - NIST-800-53-AU-12(c)
    - NIST-800-53-AU-2(d)
    - NIST-800-53-CM-6(a)
    - PCI-DSS-Req-10.5.5
    - PCI-DSSv4-10.3
    - PCI-DSSv4-10.3.4
    - audit_rules_dac_modification_chmod
    - low_complexity
    - low_disruption
    - medium_severity
    - reboot_required
    - restrict_strategy

  - name: Set architecture for audit chown tasks
    ansible.builtin.set_fact:
      audit_arch: b64
    when:
    - '"audit" in ansible_facts.packages'
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - not ( ansible_architecture == "aarch64" )
    - ansible_architecture == "aarch64" or ansible_architecture == "ppc64" or ansible_architecture
      == "ppc64le" or ansible_architecture == "s390x" or ansible_architecture == "x86_64"
    tags:
    - CJIS-5.4.1.1
    - DISA-STIG-OL09-00-000645
    - NIST-800-171-3.1.7
    - NIST-800-53-AU-12(c)
    - NIST-800-53-AU-2(d)
    - NIST-800-53-CM-6(a)
    - PCI-DSS-Req-10.5.5
    - PCI-DSSv4-10.3
    - PCI-DSSv4-10.3.4
    - audit_rules_dac_modification_chown
    - low_complexity
    - low_disruption
    - medium_severity
    - reboot_required
    - restrict_strategy

  - name: Perform remediation of Audit rules for chown for 32bit platform
    block:

    - name: Declare list of syscalls
      ansible.builtin.set_fact:
        syscalls:
        - chown
        syscall_grouping:
        - chown
        - fchown
        - fchownat
        - lchown

    - name: Check existence of chown in /etc/audit/rules.d/
      ansible.builtin.find:
        paths: /etc/audit/rules.d
        contains: -a always,exit -F arch=b32(( -S |,)\w+)*(( -S |,){{ item }})+((
          -S |,)\w+)* -F auid>=1000 -F auid!=unset (-k\s+|-F\s+key=)\S+\s*$
        patterns: '*.rules'
      register: find_command
      loop: '{{ (syscall_grouping + syscalls) | unique }}'

    - name: Reset syscalls found per file
      ansible.builtin.set_fact:
        syscalls_per_file: {}
        found_paths_dict: {}

    - name: Declare syscalls found per file
      ansible.builtin.set_fact: syscalls_per_file="{{ syscalls_per_file | combine(
        {item.files[0].path :[item.item] + syscalls_per_file.get(item.files[0].path,
        []) } ) }}"
      loop: '{{ find_command.results | selectattr(''matched'') | list }}'

    - name: Declare files where syscalls were found
      ansible.builtin.set_fact: found_paths="{{ find_command.results | map(attribute='files')
        | flatten | map(attribute='path') | list }}"

    - name: Count occurrences of syscalls in paths
      ansible.builtin.set_fact: found_paths_dict="{{ found_paths_dict | combine({
        item:1+found_paths_dict.get(item, 0) }) }}"
      loop: '{{ find_command.results | map(attribute=''files'') | flatten | map(attribute=''path'')
        | list }}'

    - name: Get path with most syscalls
      ansible.builtin.set_fact: audit_file="{{ (found_paths_dict | dict2items() |
        sort(attribute='value') | last).key }}"
      when: found_paths | length >= 1

    - name: No file with syscall found, set path to /etc/audit/rules.d/perm_mod.rules
      ansible.builtin.set_fact: audit_file="/etc/audit/rules.d/perm_mod.rules"
      when: found_paths | length == 0

    - name: Declare found syscalls
      ansible.builtin.set_fact: syscalls_found="{{ find_command.results | selectattr('matched')
        | map(attribute='item') | list }}"

    - name: Declare missing syscalls
      ansible.builtin.set_fact: missing_syscalls="{{ syscalls | difference(syscalls_found)
        }}"

    - name: Replace the audit rule in {{ audit_file }}
      ansible.builtin.lineinfile:
        path: '{{ audit_file }}'
        regexp: (-a always,exit -F arch=b32)(?=.*(?:(?:-S |,)(?:{{ syscalls_per_file[audit_file]
          | join("|") }}))\b)((?:( -S |,)\w+)+)( -F auid>=1000 -F auid!=unset (?:-k
          |-F key=)\w+)
        line: \1\2\3{{ missing_syscalls | join("\3") }}\4
        backrefs: true
        state: present
        mode: g-rwx,o-rwx
      when: syscalls_found | length > 0 and missing_syscalls | length > 0

    - name: Add the audit rule to {{ audit_file }}
      ansible.builtin.lineinfile:
        path: '{{ audit_file }}'
        line: -a always,exit -F arch=b32 -S {{ syscalls | join(',') }} -F auid>=1000
          -F auid!=unset -F key=perm_mod
        create: true
        mode: g-rwx,o-rwx
        state: present
      when: syscalls_found | length == 0

    - name: Declare list of syscalls
      ansible.builtin.set_fact:
        syscalls:
        - chown
        syscall_grouping:
        - chown
        - fchown
        - fchownat
        - lchown

    - name: Check existence of chown in /etc/audit/audit.rules
      ansible.builtin.find:
        paths: /etc/audit
        contains: -a always,exit -F arch=b32(( -S |,)\w+)*(( -S |,){{ item }})+((
          -S |,)\w+)* -F auid>=1000 -F auid!=unset (-k\s+|-F\s+key=)\S+\s*$
        patterns: audit.rules
      register: find_command
      loop: '{{ (syscall_grouping + syscalls) | unique }}'

    - name: Set path to /etc/audit/audit.rules
      ansible.builtin.set_fact: audit_file="/etc/audit/audit.rules"

    - name: Declare found syscalls
      ansible.builtin.set_fact: syscalls_found="{{ find_command.results | selectattr('matched')
        | map(attribute='item') | list }}"

    - name: Declare missing syscalls
      ansible.builtin.set_fact: missing_syscalls="{{ syscalls | difference(syscalls_found)
        }}"

    - name: Replace the audit rule in {{ audit_file }}
      ansible.builtin.lineinfile:
        path: '{{ audit_file }}'
        regexp: (-a always,exit -F arch=b32)(?=.*(?:(?:-S |,)(?:{{ syscalls_found
          | join("|") }}))\b)((?:( -S |,)\w+)+)( -F auid>=1000 -F auid!=unset (?:-k
          |-F key=)\w+)
        line: \1\2\3{{ missing_syscalls | join("\3") }}\4
        backrefs: true
        state: present
        mode: g-rwx,o-rwx
      when: syscalls_found | length > 0 and missing_syscalls | length > 0

    - name: Add the audit rule to {{ audit_file }}
      ansible.builtin.lineinfile:
        path: '{{ audit_file }}'
        line: -a always,exit -F arch=b32 -S {{ syscalls | join(',') }} -F auid>=1000
          -F auid!=unset -F key=perm_mod
        create: true
        mode: g-rwx,o-rwx
        state: present
      when: syscalls_found | length == 0
    when:
    - '"audit" in ansible_facts.packages'
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - not ( ansible_architecture == "aarch64" )
    tags:
    - CJIS-5.4.1.1
    - DISA-STIG-OL09-00-000645
    - NIST-800-171-3.1.7
    - NIST-800-53-AU-12(c)
    - NIST-800-53-AU-2(d)
    - NIST-800-53-CM-6(a)
    - PCI-DSS-Req-10.5.5
    - PCI-DSSv4-10.3
    - PCI-DSSv4-10.3.4
    - audit_rules_dac_modification_chown
    - low_complexity
    - low_disruption
    - medium_severity
    - reboot_required
    - restrict_strategy

  - name: Perform remediation of Audit rules for chown for 64bit platform
    block:

    - name: Declare list of syscalls
      ansible.builtin.set_fact:
        syscalls:
        - chown
        syscall_grouping:
        - chown
        - fchown
        - fchownat
        - lchown

    - name: Check existence of chown in /etc/audit/rules.d/
      ansible.builtin.find:
        paths: /etc/audit/rules.d
        contains: -a always,exit -F arch=b64(( -S |,)\w+)*(( -S |,){{ item }})+((
          -S |,)\w+)* -F auid>=1000 -F auid!=unset (-k\s+|-F\s+key=)\S+\s*$
        patterns: '*.rules'
      register: find_command
      loop: '{{ (syscall_grouping + syscalls) | unique }}'

    - name: Reset syscalls found per file
      ansible.builtin.set_fact:
        syscalls_per_file: {}
        found_paths_dict: {}

    - name: Declare syscalls found per file
      ansible.builtin.set_fact: syscalls_per_file="{{ syscalls_per_file | combine(
        {item.files[0].path :[item.item] + syscalls_per_file.get(item.files[0].path,
        []) } ) }}"
      loop: '{{ find_command.results | selectattr(''matched'') | list }}'

    - name: Declare files where syscalls were found
      ansible.builtin.set_fact: found_paths="{{ find_command.results | map(attribute='files')
        | flatten | map(attribute='path') | list }}"

    - name: Count occurrences of syscalls in paths
      ansible.builtin.set_fact: found_paths_dict="{{ found_paths_dict | combine({
        item:1+found_paths_dict.get(item, 0) }) }}"
      loop: '{{ find_command.results | map(attribute=''files'') | flatten | map(attribute=''path'')
        | list }}'

    - name: Get path with most syscalls
      ansible.builtin.set_fact: audit_file="{{ (found_paths_dict | dict2items() |
        sort(attribute='value') | last).key }}"
      when: found_paths | length >= 1

    - name: No file with syscall found, set path to /etc/audit/rules.d/perm_mod.rules
      ansible.builtin.set_fact: audit_file="/etc/audit/rules.d/perm_mod.rules"
      when: found_paths | length == 0

    - name: Declare found syscalls
      ansible.builtin.set_fact: syscalls_found="{{ find_command.results | selectattr('matched')
        | map(attribute='item') | list }}"

    - name: Declare missing syscalls
      ansible.builtin.set_fact: missing_syscalls="{{ syscalls | difference(syscalls_found)
        }}"

    - name: Replace the audit rule in {{ audit_file }}
      ansible.builtin.lineinfile:
        path: '{{ audit_file }}'
        regexp: (-a always,exit -F arch=b64)(?=.*(?:(?:-S |,)(?:{{ syscalls_per_file[audit_file]
          | join("|") }}))\b)((?:( -S |,)\w+)+)( -F auid>=1000 -F auid!=unset (?:-k
          |-F key=)\w+)
        line: \1\2\3{{ missing_syscalls | join("\3") }}\4
        backrefs: true
        state: present
        mode: g-rwx,o-rwx
      when: syscalls_found | length > 0 and missing_syscalls | length > 0

    - name: Add the audit rule to {{ audit_file }}
      ansible.builtin.lineinfile:
        path: '{{ audit_file }}'
        line: -a always,exit -F arch=b64 -S {{ syscalls | join(',') }} -F auid>=1000
          -F auid!=unset -F key=perm_mod
        create: true
        mode: g-rwx,o-rwx
        state: present
      when: syscalls_found | length == 0

    - name: Declare list of syscalls
      ansible.builtin.set_fact:
        syscalls:
        - chown
        syscall_grouping:
        - chown
        - fchown
        - fchownat
        - lchown

    - name: Check existence of chown in /etc/audit/audit.rules
      ansible.builtin.find:
        paths: /etc/audit
        contains: -a always,exit -F arch=b64(( -S |,)\w+)*(( -S |,){{ item }})+((
          -S |,)\w+)* -F auid>=1000 -F auid!=unset (-k\s+|-F\s+key=)\S+\s*$
        patterns: audit.rules
      register: find_command
      loop: '{{ (syscall_grouping + syscalls) | unique }}'

    - name: Set path to /etc/audit/audit.rules
      ansible.builtin.set_fact: audit_file="/etc/audit/audit.rules"

    - name: Declare found syscalls
      ansible.builtin.set_fact: syscalls_found="{{ find_command.results | selectattr('matched')
        | map(attribute='item') | list }}"

    - name: Declare missing syscalls
      ansible.builtin.set_fact: missing_syscalls="{{ syscalls | difference(syscalls_found)
        }}"

    - name: Replace the audit rule in {{ audit_file }}
      ansible.builtin.lineinfile:
        path: '{{ audit_file }}'
        regexp: (-a always,exit -F arch=b64)(?=.*(?:(?:-S |,)(?:{{ syscalls_found
          | join("|") }}))\b)((?:( -S |,)\w+)+)( -F auid>=1000 -F auid!=unset (?:-k
          |-F key=)\w+)
        line: \1\2\3{{ missing_syscalls | join("\3") }}\4
        backrefs: true
        state: present
        mode: g-rwx,o-rwx
      when: syscalls_found | length > 0 and missing_syscalls | length > 0

    - name: Add the audit rule to {{ audit_file }}
      ansible.builtin.lineinfile:
        path: '{{ audit_file }}'
        line: -a always,exit -F arch=b64 -S {{ syscalls | join(',') }} -F auid>=1000
          -F auid!=unset -F key=perm_mod
        create: true
        mode: g-rwx,o-rwx
        state: present
      when: syscalls_found | length == 0
    when:
    - '"audit" in ansible_facts.packages'
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - not ( ansible_architecture == "aarch64" )
    - audit_arch == "b64"
    tags:
    - CJIS-5.4.1.1
    - DISA-STIG-OL09-00-000645
    - NIST-800-171-3.1.7
    - NIST-800-53-AU-12(c)
    - NIST-800-53-AU-2(d)
    - NIST-800-53-CM-6(a)
    - PCI-DSS-Req-10.5.5
    - PCI-DSSv4-10.3
    - PCI-DSSv4-10.3.4
    - audit_rules_dac_modification_chown
    - low_complexity
    - low_disruption
    - medium_severity
    - reboot_required
    - restrict_strategy

  - name: Set architecture for audit fchmod tasks
    ansible.builtin.set_fact:
      audit_arch: b64
    when:
    - '"audit" in ansible_facts.packages'
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - ansible_architecture == "aarch64" or ansible_architecture == "ppc64" or ansible_architecture
      == "ppc64le" or ansible_architecture == "s390x" or ansible_architecture == "x86_64"
    tags:
    - CJIS-5.4.1.1
    - DISA-STIG-OL09-00-000640
    - NIST-800-171-3.1.7
    - NIST-800-53-AU-12(c)
    - NIST-800-53-AU-2(d)
    - NIST-800-53-CM-6(a)
    - PCI-DSS-Req-10.5.5
    - PCI-DSSv4-10.3
    - PCI-DSSv4-10.3.4
    - audit_rules_dac_modification_fchmod
    - low_complexity
    - low_disruption
    - medium_severity
    - reboot_required
    - restrict_strategy

  - name: Perform remediation of Audit rules for fchmod for 32bit platform
    block:

    - name: Declare list of syscalls
      ansible.builtin.set_fact:
        syscalls:
        - fchmod
        syscall_grouping:
        - chmod
        - fchmod
        - fchmodat

    - name: Check existence of fchmod in /etc/audit/rules.d/
      ansible.builtin.find:
        paths: /etc/audit/rules.d
        contains: -a always,exit -F arch=b32(( -S |,)\w+)*(( -S |,){{ item }})+((
          -S |,)\w+)* -F auid>=1000 -F auid!=unset (-k\s+|-F\s+key=)\S+\s*$
        patterns: '*.rules'
      register: find_command
      loop: '{{ (syscall_grouping + syscalls) | unique }}'

    - name: Reset syscalls found per file
      ansible.builtin.set_fact:
        syscalls_per_file: {}
        found_paths_dict: {}

    - name: Declare syscalls found per file
      ansible.builtin.set_fact: syscalls_per_file="{{ syscalls_per_file | combine(
        {item.files[0].path :[item.item] + syscalls_per_file.get(item.files[0].path,
        []) } ) }}"
      loop: '{{ find_command.results | selectattr(''matched'') | list }}'

    - name: Declare files where syscalls were found
      ansible.builtin.set_fact: found_paths="{{ find_command.results | map(attribute='files')
        | flatten | map(attribute='path') | list }}"

    - name: Count occurrences of syscalls in paths
      ansible.builtin.set_fact: found_paths_dict="{{ found_paths_dict | combine({
        item:1+found_paths_dict.get(item, 0) }) }}"
      loop: '{{ find_command.results | map(attribute=''files'') | flatten | map(attribute=''path'')
        | list }}'

    - name: Get path with most syscalls
      ansible.builtin.set_fact: audit_file="{{ (found_paths_dict | dict2items() |
        sort(attribute='value') | last).key }}"
      when: found_paths | length >= 1

    - name: No file with syscall found, set path to /etc/audit/rules.d/perm_mod.rules
      ansible.builtin.set_fact: audit_file="/etc/audit/rules.d/perm_mod.rules"
      when: found_paths | length == 0

    - name: Declare found syscalls
      ansible.builtin.set_fact: syscalls_found="{{ find_command.results | selectattr('matched')
        | map(attribute='item') | list }}"

    - name: Declare missing syscalls
      ansible.builtin.set_fact: missing_syscalls="{{ syscalls | difference(syscalls_found)
        }}"

    - name: Replace the audit rule in {{ audit_file }}
      ansible.builtin.lineinfile:
        path: '{{ audit_file }}'
        regexp: (-a always,exit -F arch=b32)(?=.*(?:(?:-S |,)(?:{{ syscalls_per_file[audit_file]
          | join("|") }}))\b)((?:( -S |,)\w+)+)( -F auid>=1000 -F auid!=unset (?:-k
          |-F key=)\w+)
        line: \1\2\3{{ missing_syscalls | join("\3") }}\4
        backrefs: true
        state: present
        mode: g-rwx,o-rwx
      when: syscalls_found | length > 0 and missing_syscalls | length > 0

    - name: Add the audit rule to {{ audit_file }}
      ansible.builtin.lineinfile:
        path: '{{ audit_file }}'
        line: -a always,exit -F arch=b32 -S {{ syscalls | join(',') }} -F auid>=1000
          -F auid!=unset -F key=perm_mod
        create: true
        mode: g-rwx,o-rwx
        state: present
      when: syscalls_found | length == 0

    - name: Declare list of syscalls
      ansible.builtin.set_fact:
        syscalls:
        - fchmod
        syscall_grouping:
        - chmod
        - fchmod
        - fchmodat

    - name: Check existence of fchmod in /etc/audit/audit.rules
      ansible.builtin.find:
        paths: /etc/audit
        contains: -a always,exit -F arch=b32(( -S |,)\w+)*(( -S |,){{ item }})+((
          -S |,)\w+)* -F auid>=1000 -F auid!=unset (-k\s+|-F\s+key=)\S+\s*$
        patterns: audit.rules
      register: find_command
      loop: '{{ (syscall_grouping + syscalls) | unique }}'

    - name: Set path to /etc/audit/audit.rules
      ansible.builtin.set_fact: audit_file="/etc/audit/audit.rules"

    - name: Declare found syscalls
      ansible.builtin.set_fact: syscalls_found="{{ find_command.results | selectattr('matched')
        | map(attribute='item') | list }}"

    - name: Declare missing syscalls
      ansible.builtin.set_fact: missing_syscalls="{{ syscalls | difference(syscalls_found)
        }}"

    - name: Replace the audit rule in {{ audit_file }}
      ansible.builtin.lineinfile:
        path: '{{ audit_file }}'
        regexp: (-a always,exit -F arch=b32)(?=.*(?:(?:-S |,)(?:{{ syscalls_found
          | join("|") }}))\b)((?:( -S |,)\w+)+)( -F auid>=1000 -F auid!=unset (?:-k
          |-F key=)\w+)
        line: \1\2\3{{ missing_syscalls | join("\3") }}\4
        backrefs: true
        state: present
        mode: g-rwx,o-rwx
      when: syscalls_found | length > 0 and missing_syscalls | length > 0

    - name: Add the audit rule to {{ audit_file }}
      ansible.builtin.lineinfile:
        path: '{{ audit_file }}'
        line: -a always,exit -F arch=b32 -S {{ syscalls | join(',') }} -F auid>=1000
          -F auid!=unset -F key=perm_mod
        create: true
        mode: g-rwx,o-rwx
        state: present
      when: syscalls_found | length == 0
    when:
    - '"audit" in ansible_facts.packages'
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - CJIS-5.4.1.1
    - DISA-STIG-OL09-00-000640
    - NIST-800-171-3.1.7
    - NIST-800-53-AU-12(c)
    - NIST-800-53-AU-2(d)
    - NIST-800-53-CM-6(a)
    - PCI-DSS-Req-10.5.5
    - PCI-DSSv4-10.3
    - PCI-DSSv4-10.3.4
    - audit_rules_dac_modification_fchmod
    - low_complexity
    - low_disruption
    - medium_severity
    - reboot_required
    - restrict_strategy

  - name: Perform remediation of Audit rules for fchmod for 64bit platform
    block:

    - name: Declare list of syscalls
      ansible.builtin.set_fact:
        syscalls:
        - fchmod
        syscall_grouping:
        - chmod
        - fchmod
        - fchmodat

    - name: Check existence of fchmod in /etc/audit/rules.d/
      ansible.builtin.find:
        paths: /etc/audit/rules.d
        contains: -a always,exit -F arch=b64(( -S |,)\w+)*(( -S |,){{ item }})+((
          -S |,)\w+)* -F auid>=1000 -F auid!=unset (-k\s+|-F\s+key=)\S+\s*$
        patterns: '*.rules'
      register: find_command
      loop: '{{ (syscall_grouping + syscalls) | unique }}'

    - name: Reset syscalls found per file
      ansible.builtin.set_fact:
        syscalls_per_file: {}
        found_paths_dict: {}

    - name: Declare syscalls found per file
      ansible.builtin.set_fact: syscalls_per_file="{{ syscalls_per_file | combine(
        {item.files[0].path :[item.item] + syscalls_per_file.get(item.files[0].path,
        []) } ) }}"
      loop: '{{ find_command.results | selectattr(''matched'') | list }}'

    - name: Declare files where syscalls were found
      ansible.builtin.set_fact: found_paths="{{ find_command.results | map(attribute='files')
        | flatten | map(attribute='path') | list }}"

    - name: Count occurrences of syscalls in paths
      ansible.builtin.set_fact: found_paths_dict="{{ found_paths_dict | combine({
        item:1+found_paths_dict.get(item, 0) }) }}"
      loop: '{{ find_command.results | map(attribute=''files'') | flatten | map(attribute=''path'')
        | list }}'

    - name: Get path with most syscalls
      ansible.builtin.set_fact: audit_file="{{ (found_paths_dict | dict2items() |
        sort(attribute='value') | last).key }}"
      when: found_paths | length >= 1

    - name: No file with syscall found, set path to /etc/audit/rules.d/perm_mod.rules
      ansible.builtin.set_fact: audit_file="/etc/audit/rules.d/perm_mod.rules"
      when: found_paths | length == 0

    - name: Declare found syscalls
      ansible.builtin.set_fact: syscalls_found="{{ find_command.results | selectattr('matched')
        | map(attribute='item') | list }}"

    - name: Declare missing syscalls
      ansible.builtin.set_fact: missing_syscalls="{{ syscalls | difference(syscalls_found)
        }}"

    - name: Replace the audit rule in {{ audit_file }}
      ansible.builtin.lineinfile:
        path: '{{ audit_file }}'
        regexp: (-a always,exit -F arch=b64)(?=.*(?:(?:-S |,)(?:{{ syscalls_per_file[audit_file]
          | join("|") }}))\b)((?:( -S |,)\w+)+)( -F auid>=1000 -F auid!=unset (?:-k
          |-F key=)\w+)
        line: \1\2\3{{ missing_syscalls | join("\3") }}\4
        backrefs: true
        state: present
        mode: g-rwx,o-rwx
      when: syscalls_found | length > 0 and missing_syscalls | length > 0

    - name: Add the audit rule to {{ audit_file }}
      ansible.builtin.lineinfile:
        path: '{{ audit_file }}'
        line: -a always,exit -F arch=b64 -S {{ syscalls | join(',') }} -F auid>=1000
          -F auid!=unset -F key=perm_mod
        create: true
        mode: g-rwx,o-rwx
        state: present
      when: syscalls_found | length == 0

    - name: Declare list of syscalls
      ansible.builtin.set_fact:
        syscalls:
        - fchmod
        syscall_grouping:
        - chmod
        - fchmod
        - fchmodat

    - name: Check existence of fchmod in /etc/audit/audit.rules
      ansible.builtin.find:
        paths: /etc/audit
        contains: -a always,exit -F arch=b64(( -S |,)\w+)*(( -S |,){{ item }})+((
          -S |,)\w+)* -F auid>=1000 -F auid!=unset (-k\s+|-F\s+key=)\S+\s*$
        patterns: audit.rules
      register: find_command
      loop: '{{ (syscall_grouping + syscalls) | unique }}'

    - name: Set path to /etc/audit/audit.rules
      ansible.builtin.set_fact: audit_file="/etc/audit/audit.rules"

    - name: Declare found syscalls
      ansible.builtin.set_fact: syscalls_found="{{ find_command.results | selectattr('matched')
        | map(attribute='item') | list }}"

    - name: Declare missing syscalls
      ansible.builtin.set_fact: missing_syscalls="{{ syscalls | difference(syscalls_found)
        }}"

    - name: Replace the audit rule in {{ audit_file }}
      ansible.builtin.lineinfile:
        path: '{{ audit_file }}'
        regexp: (-a always,exit -F arch=b64)(?=.*(?:(?:-S |,)(?:{{ syscalls_found
          | join("|") }}))\b)((?:( -S |,)\w+)+)( -F auid>=1000 -F auid!=unset (?:-k
          |-F key=)\w+)
        line: \1\2\3{{ missing_syscalls | join("\3") }}\4
        backrefs: true
        state: present
        mode: g-rwx,o-rwx
      when: syscalls_found | length > 0 and missing_syscalls | length > 0

    - name: Add the audit rule to {{ audit_file }}
      ansible.builtin.lineinfile:
        path: '{{ audit_file }}'
        line: -a always,exit -F arch=b64 -S {{ syscalls | join(',') }} -F auid>=1000
          -F auid!=unset -F key=perm_mod
        create: true
        mode: g-rwx,o-rwx
        state: present
      when: syscalls_found | length == 0
    when:
    - '"audit" in ansible_facts.packages'
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - audit_arch == "b64"
    tags:
    - CJIS-5.4.1.1
    - DISA-STIG-OL09-00-000640
    - NIST-800-171-3.1.7
    - NIST-800-53-AU-12(c)
    - NIST-800-53-AU-2(d)
    - NIST-800-53-CM-6(a)
    - PCI-DSS-Req-10.5.5
    - PCI-DSSv4-10.3
    - PCI-DSSv4-10.3.4
    - audit_rules_dac_modification_fchmod
    - low_complexity
    - low_disruption
    - medium_severity
    - reboot_required
    - restrict_strategy

  - name: Set architecture for audit fchmodat tasks
    ansible.builtin.set_fact:
      audit_arch: b64
    when:
    - '"audit" in ansible_facts.packages'
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - ansible_architecture == "aarch64" or ansible_architecture == "ppc64" or ansible_architecture
      == "ppc64le" or ansible_architecture == "s390x" or ansible_architecture == "x86_64"
    tags:
    - CJIS-5.4.1.1
    - DISA-STIG-OL09-00-000640
    - NIST-800-171-3.1.7
    - NIST-800-53-AU-12(c)
    - NIST-800-53-AU-2(d)
    - NIST-800-53-CM-6(a)
    - PCI-DSS-Req-10.5.5
    - PCI-DSSv4-10.3
    - PCI-DSSv4-10.3.4
    - audit_rules_dac_modification_fchmodat
    - low_complexity
    - low_disruption
    - medium_severity
    - reboot_required
    - restrict_strategy

  - name: Perform remediation of Audit rules for fchmodat for 32bit platform
    block:

    - name: Declare list of syscalls
      ansible.builtin.set_fact:
        syscalls:
        - fchmodat
        syscall_grouping:
        - chmod
        - fchmod
        - fchmodat

    - name: Check existence of fchmodat in /etc/audit/rules.d/
      ansible.builtin.find:
        paths: /etc/audit/rules.d
        contains: -a always,exit -F arch=b32(( -S |,)\w+)*(( -S |,){{ item }})+((
          -S |,)\w+)* -F auid>=1000 -F auid!=unset (-k\s+|-F\s+key=)\S+\s*$
        patterns: '*.rules'
      register: find_command
      loop: '{{ (syscall_grouping + syscalls) | unique }}'

    - name: Reset syscalls found per file
      ansible.builtin.set_fact:
        syscalls_per_file: {}
        found_paths_dict: {}

    - name: Declare syscalls found per file
      ansible.builtin.set_fact: syscalls_per_file="{{ syscalls_per_file | combine(
        {item.files[0].path :[item.item] + syscalls_per_file.get(item.files[0].path,
        []) } ) }}"
      loop: '{{ find_command.results | selectattr(''matched'') | list }}'

    - name: Declare files where syscalls were found
      ansible.builtin.set_fact: found_paths="{{ find_command.results | map(attribute='files')
        | flatten | map(attribute='path') | list }}"

    - name: Count occurrences of syscalls in paths
      ansible.builtin.set_fact: found_paths_dict="{{ found_paths_dict | combine({
        item:1+found_paths_dict.get(item, 0) }) }}"
      loop: '{{ find_command.results | map(attribute=''files'') | flatten | map(attribute=''path'')
        | list }}'

    - name: Get path with most syscalls
      ansible.builtin.set_fact: audit_file="{{ (found_paths_dict | dict2items() |
        sort(attribute='value') | last).key }}"
      when: found_paths | length >= 1

    - name: No file with syscall found, set path to /etc/audit/rules.d/perm_mod.rules
      ansible.builtin.set_fact: audit_file="/etc/audit/rules.d/perm_mod.rules"
      when: found_paths | length == 0

    - name: Declare found syscalls
      ansible.builtin.set_fact: syscalls_found="{{ find_command.results | selectattr('matched')
        | map(attribute='item') | list }}"

    - name: Declare missing syscalls
      ansible.builtin.set_fact: missing_syscalls="{{ syscalls | difference(syscalls_found)
        }}"

    - name: Replace the audit rule in {{ audit_file }}
      ansible.builtin.lineinfile:
        path: '{{ audit_file }}'
        regexp: (-a always,exit -F arch=b32)(?=.*(?:(?:-S |,)(?:{{ syscalls_per_file[audit_file]
          | join("|") }}))\b)((?:( -S |,)\w+)+)( -F auid>=1000 -F auid!=unset (?:-k
          |-F key=)\w+)
        line: \1\2\3{{ missing_syscalls | join("\3") }}\4
        backrefs: true
        state: present
        mode: g-rwx,o-rwx
      when: syscalls_found | length > 0 and missing_syscalls | length > 0

    - name: Add the audit rule to {{ audit_file }}
      ansible.builtin.lineinfile:
        path: '{{ audit_file }}'
        line: -a always,exit -F arch=b32 -S {{ syscalls | join(',') }} -F auid>=1000
          -F auid!=unset -F key=perm_mod
        create: true
        mode: g-rwx,o-rwx
        state: present
      when: syscalls_found | length == 0

    - name: Declare list of syscalls
      ansible.builtin.set_fact:
        syscalls:
        - fchmodat
        syscall_grouping:
        - chmod
        - fchmod
        - fchmodat

    - name: Check existence of fchmodat in /etc/audit/audit.rules
      ansible.builtin.find:
        paths: /etc/audit
        contains: -a always,exit -F arch=b32(( -S |,)\w+)*(( -S |,){{ item }})+((
          -S |,)\w+)* -F auid>=1000 -F auid!=unset (-k\s+|-F\s+key=)\S+\s*$
        patterns: audit.rules
      register: find_command
      loop: '{{ (syscall_grouping + syscalls) | unique }}'

    - name: Set path to /etc/audit/audit.rules
      ansible.builtin.set_fact: audit_file="/etc/audit/audit.rules"

    - name: Declare found syscalls
      ansible.builtin.set_fact: syscalls_found="{{ find_command.results | selectattr('matched')
        | map(attribute='item') | list }}"

    - name: Declare missing syscalls
      ansible.builtin.set_fact: missing_syscalls="{{ syscalls | difference(syscalls_found)
        }}"

    - name: Replace the audit rule in {{ audit_file }}
      ansible.builtin.lineinfile:
        path: '{{ audit_file }}'
        regexp: (-a always,exit -F arch=b32)(?=.*(?:(?:-S |,)(?:{{ syscalls_found
          | join("|") }}))\b)((?:( -S |,)\w+)+)( -F auid>=1000 -F auid!=unset (?:-k
          |-F key=)\w+)
        line: \1\2\3{{ missing_syscalls | join("\3") }}\4
        backrefs: true
        state: present
        mode: g-rwx,o-rwx
      when: syscalls_found | length > 0 and missing_syscalls | length > 0

    - name: Add the audit rule to {{ audit_file }}
      ansible.builtin.lineinfile:
        path: '{{ audit_file }}'
        line: -a always,exit -F arch=b32 -S {{ syscalls | join(',') }} -F auid>=1000
          -F auid!=unset -F key=perm_mod
        create: true
        mode: g-rwx,o-rwx
        state: present
      when: syscalls_found | length == 0
    when:
    - '"audit" in ansible_facts.packages'
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - CJIS-5.4.1.1
    - DISA-STIG-OL09-00-000640
    - NIST-800-171-3.1.7
    - NIST-800-53-AU-12(c)
    - NIST-800-53-AU-2(d)
    - NIST-800-53-CM-6(a)
    - PCI-DSS-Req-10.5.5
    - PCI-DSSv4-10.3
    - PCI-DSSv4-10.3.4
    - audit_rules_dac_modification_fchmodat
    - low_complexity
    - low_disruption
    - medium_severity
    - reboot_required
    - restrict_strategy

  - name: Perform remediation of Audit rules for fchmodat for 64bit platform
    block:

    - name: Declare list of syscalls
      ansible.builtin.set_fact:
        syscalls:
        - fchmodat
        syscall_grouping:
        - chmod
        - fchmod
        - fchmodat

    - name: Check existence of fchmodat in /etc/audit/rules.d/
      ansible.builtin.find:
        paths: /etc/audit/rules.d
        contains: -a always,exit -F arch=b64(( -S |,)\w+)*(( -S |,){{ item }})+((
          -S |,)\w+)* -F auid>=1000 -F auid!=unset (-k\s+|-F\s+key=)\S+\s*$
        patterns: '*.rules'
      register: find_command
      loop: '{{ (syscall_grouping + syscalls) | unique }}'

    - name: Reset syscalls found per file
      ansible.builtin.set_fact:
        syscalls_per_file: {}
        found_paths_dict: {}

    - name: Declare syscalls found per file
      ansible.builtin.set_fact: syscalls_per_file="{{ syscalls_per_file | combine(
        {item.files[0].path :[item.item] + syscalls_per_file.get(item.files[0].path,
        []) } ) }}"
      loop: '{{ find_command.results | selectattr(''matched'') | list }}'

    - name: Declare files where syscalls were found
      ansible.builtin.set_fact: found_paths="{{ find_command.results | map(attribute='files')
        | flatten | map(attribute='path') | list }}"

    - name: Count occurrences of syscalls in paths
      ansible.builtin.set_fact: found_paths_dict="{{ found_paths_dict | combine({
        item:1+found_paths_dict.get(item, 0) }) }}"
      loop: '{{ find_command.results | map(attribute=''files'') | flatten | map(attribute=''path'')
        | list }}'

    - name: Get path with most syscalls
      ansible.builtin.set_fact: audit_file="{{ (found_paths_dict | dict2items() |
        sort(attribute='value') | last).key }}"
      when: found_paths | length >= 1

    - name: No file with syscall found, set path to /etc/audit/rules.d/perm_mod.rules
      ansible.builtin.set_fact: audit_file="/etc/audit/rules.d/perm_mod.rules"
      when: found_paths | length == 0

    - name: Declare found syscalls
      ansible.builtin.set_fact: syscalls_found="{{ find_command.results | selectattr('matched')
        | map(attribute='item') | list }}"

    - name: Declare missing syscalls
      ansible.builtin.set_fact: missing_syscalls="{{ syscalls | difference(syscalls_found)
        }}"

    - name: Replace the audit rule in {{ audit_file }}
      ansible.builtin.lineinfile:
        path: '{{ audit_file }}'
        regexp: (-a always,exit -F arch=b64)(?=.*(?:(?:-S |,)(?:{{ syscalls_per_file[audit_file]
          | join("|") }}))\b)((?:( -S |,)\w+)+)( -F auid>=1000 -F auid!=unset (?:-k
          |-F key=)\w+)
        line: \1\2\3{{ missing_syscalls | join("\3") }}\4
        backrefs: true
        state: present
        mode: g-rwx,o-rwx
      when: syscalls_found | length > 0 and missing_syscalls | length > 0

    - name: Add the audit rule to {{ audit_file }}
      ansible.builtin.lineinfile:
        path: '{{ audit_file }}'
        line: -a always,exit -F arch=b64 -S {{ syscalls | join(',') }} -F auid>=1000
          -F auid!=unset -F key=perm_mod
        create: true
        mode: g-rwx,o-rwx
        state: present
      when: syscalls_found | length == 0

    - name: Declare list of syscalls
      ansible.builtin.set_fact:
        syscalls:
        - fchmodat
        syscall_grouping:
        - chmod
        - fchmod
        - fchmodat

    - name: Check existence of fchmodat in /etc/audit/audit.rules
      ansible.builtin.find:
        paths: /etc/audit
        contains: -a always,exit -F arch=b64(( -S |,)\w+)*(( -S |,){{ item }})+((
          -S |,)\w+)* -F auid>=1000 -F auid!=unset (-k\s+|-F\s+key=)\S+\s*$
        patterns: audit.rules
      register: find_command
      loop: '{{ (syscall_grouping + syscalls) | unique }}'

    - name: Set path to /etc/audit/audit.rules
      ansible.builtin.set_fact: audit_file="/etc/audit/audit.rules"

    - name: Declare found syscalls
      ansible.builtin.set_fact: syscalls_found="{{ find_command.results | selectattr('matched')
        | map(attribute='item') | list }}"

    - name: Declare missing syscalls
      ansible.builtin.set_fact: missing_syscalls="{{ syscalls | difference(syscalls_found)
        }}"

    - name: Replace the audit rule in {{ audit_file }}
      ansible.builtin.lineinfile:
        path: '{{ audit_file }}'
        regexp: (-a always,exit -F arch=b64)(?=.*(?:(?:-S |,)(?:{{ syscalls_found
          | join("|") }}))\b)((?:( -S |,)\w+)+)( -F auid>=1000 -F auid!=unset (?:-k
          |-F key=)\w+)
        line: \1\2\3{{ missing_syscalls | join("\3") }}\4
        backrefs: true
        state: present
        mode: g-rwx,o-rwx
      when: syscalls_found | length > 0 and missing_syscalls | length > 0

    - name: Add the audit rule to {{ audit_file }}
      ansible.builtin.lineinfile:
        path: '{{ audit_file }}'
        line: -a always,exit -F arch=b64 -S {{ syscalls | join(',') }} -F auid>=1000
          -F auid!=unset -F key=perm_mod
        create: true
        mode: g-rwx,o-rwx
        state: present
      when: syscalls_found | length == 0
    when:
    - '"audit" in ansible_facts.packages'
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - audit_arch == "b64"
    tags:
    - CJIS-5.4.1.1
    - DISA-STIG-OL09-00-000640
    - NIST-800-171-3.1.7
    - NIST-800-53-AU-12(c)
    - NIST-800-53-AU-2(d)
    - NIST-800-53-CM-6(a)
    - PCI-DSS-Req-10.5.5
    - PCI-DSSv4-10.3
    - PCI-DSSv4-10.3.4
    - audit_rules_dac_modification_fchmodat
    - low_complexity
    - low_disruption
    - medium_severity
    - reboot_required
    - restrict_strategy

  - name: Set architecture for audit fchown tasks
    ansible.builtin.set_fact:
      audit_arch: b64
    when:
    - '"audit" in ansible_facts.packages'
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - ansible_architecture == "aarch64" or ansible_architecture == "ppc64" or ansible_architecture
      == "ppc64le" or ansible_architecture == "s390x" or ansible_architecture == "x86_64"
    tags:
    - CJIS-5.4.1.1
    - DISA-STIG-OL09-00-000645
    - NIST-800-171-3.1.7
    - NIST-800-53-AU-12(c)
    - NIST-800-53-AU-2(d)
    - NIST-800-53-CM-6(a)
    - PCI-DSS-Req-10.5.5
    - PCI-DSSv4-10.3
    - PCI-DSSv4-10.3.4
    - audit_rules_dac_modification_fchown
    - low_complexity
    - low_disruption
    - medium_severity
    - reboot_required
    - restrict_strategy

  - name: Perform remediation of Audit rules for fchown for 32bit platform
    block:

    - name: Declare list of syscalls
      ansible.builtin.set_fact:
        syscalls:
        - fchown
        syscall_grouping:
        - chown
        - fchown
        - fchownat
        - lchown

    - name: Check existence of fchown in /etc/audit/rules.d/
      ansible.builtin.find:
        paths: /etc/audit/rules.d
        contains: -a always,exit -F arch=b32(( -S |,)\w+)*(( -S |,){{ item }})+((
          -S |,)\w+)* -F auid>=1000 -F auid!=unset (-k\s+|-F\s+key=)\S+\s*$
        patterns: '*.rules'
      register: find_command
      loop: '{{ (syscall_grouping + syscalls) | unique }}'

    - name: Reset syscalls found per file
      ansible.builtin.set_fact:
        syscalls_per_file: {}
        found_paths_dict: {}

    - name: Declare syscalls found per file
      ansible.builtin.set_fact: syscalls_per_file="{{ syscalls_per_file | combine(
        {item.files[0].path :[item.item] + syscalls_per_file.get(item.files[0].path,
        []) } ) }}"
      loop: '{{ find_command.results | selectattr(''matched'') | list }}'

    - name: Declare files where syscalls were found
      ansible.builtin.set_fact: found_paths="{{ find_command.results | map(attribute='files')
        | flatten | map(attribute='path') | list }}"

    - name: Count occurrences of syscalls in paths
      ansible.builtin.set_fact: found_paths_dict="{{ found_paths_dict | combine({
        item:1+found_paths_dict.get(item, 0) }) }}"
      loop: '{{ find_command.results | map(attribute=''files'') | flatten | map(attribute=''path'')
        | list }}'

    - name: Get path with most syscalls
      ansible.builtin.set_fact: audit_file="{{ (found_paths_dict | dict2items() |
        sort(attribute='value') | last).key }}"
      when: found_paths | length >= 1

    - name: No file with syscall found, set path to /etc/audit/rules.d/perm_mod.rules
      ansible.builtin.set_fact: audit_file="/etc/audit/rules.d/perm_mod.rules"
      when: found_paths | length == 0

    - name: Declare found syscalls
      ansible.builtin.set_fact: syscalls_found="{{ find_command.results | selectattr('matched')
        | map(attribute='item') | list }}"

    - name: Declare missing syscalls
      ansible.builtin.set_fact: missing_syscalls="{{ syscalls | difference(syscalls_found)
        }}"

    - name: Replace the audit rule in {{ audit_file }}
      ansible.builtin.lineinfile:
        path: '{{ audit_file }}'
        regexp: (-a always,exit -F arch=b32)(?=.*(?:(?:-S |,)(?:{{ syscalls_per_file[audit_file]
          | join("|") }}))\b)((?:( -S |,)\w+)+)( -F auid>=1000 -F auid!=unset (?:-k
          |-F key=)\w+)
        line: \1\2\3{{ missing_syscalls | join("\3") }}\4
        backrefs: true
        state: present
        mode: g-rwx,o-rwx
      when: syscalls_found | length > 0 and missing_syscalls | length > 0

    - name: Add the audit rule to {{ audit_file }}
      ansible.builtin.lineinfile:
        path: '{{ audit_file }}'
        line: -a always,exit -F arch=b32 -S {{ syscalls | join(',') }} -F auid>=1000
          -F auid!=unset -F key=perm_mod
        create: true
        mode: g-rwx,o-rwx
        state: present
      when: syscalls_found | length == 0

    - name: Declare list of syscalls
      ansible.builtin.set_fact:
        syscalls:
        - fchown
        syscall_grouping:
        - chown
        - fchown
        - fchownat
        - lchown

    - name: Check existence of fchown in /etc/audit/audit.rules
      ansible.builtin.find:
        paths: /etc/audit
        contains: -a always,exit -F arch=b32(( -S |,)\w+)*(( -S |,){{ item }})+((
          -S |,)\w+)* -F auid>=1000 -F auid!=unset (-k\s+|-F\s+key=)\S+\s*$
        patterns: audit.rules
      register: find_command
      loop: '{{ (syscall_grouping + syscalls) | unique }}'

    - name: Set path to /etc/audit/audit.rules
      ansible.builtin.set_fact: audit_file="/etc/audit/audit.rules"

    - name: Declare found syscalls
      ansible.builtin.set_fact: syscalls_found="{{ find_command.results | selectattr('matched')
        | map(attribute='item') | list }}"

    - name: Declare missing syscalls
      ansible.builtin.set_fact: missing_syscalls="{{ syscalls | difference(syscalls_found)
        }}"

    - name: Replace the audit rule in {{ audit_file }}
      ansible.builtin.lineinfile:
        path: '{{ audit_file }}'
        regexp: (-a always,exit -F arch=b32)(?=.*(?:(?:-S |,)(?:{{ syscalls_found
          | join("|") }}))\b)((?:( -S |,)\w+)+)( -F auid>=1000 -F auid!=unset (?:-k
          |-F key=)\w+)
        line: \1\2\3{{ missing_syscalls | join("\3") }}\4
        backrefs: true
        state: present
        mode: g-rwx,o-rwx
      when: syscalls_found | length > 0 and missing_syscalls | length > 0

    - name: Add the audit rule to {{ audit_file }}
      ansible.builtin.lineinfile:
        path: '{{ audit_file }}'
        line: -a always,exit -F arch=b32 -S {{ syscalls | join(',') }} -F auid>=1000
          -F auid!=unset -F key=perm_mod
        create: true
        mode: g-rwx,o-rwx
        state: present
      when: syscalls_found | length == 0
    when:
    - '"audit" in ansible_facts.packages'
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - CJIS-5.4.1.1
    - DISA-STIG-OL09-00-000645
    - NIST-800-171-3.1.7
    - NIST-800-53-AU-12(c)
    - NIST-800-53-AU-2(d)
    - NIST-800-53-CM-6(a)
    - PCI-DSS-Req-10.5.5
    - PCI-DSSv4-10.3
    - PCI-DSSv4-10.3.4
    - audit_rules_dac_modification_fchown
    - low_complexity
    - low_disruption
    - medium_severity
    - reboot_required
    - restrict_strategy

  - name: Perform remediation of Audit rules for fchown for 64bit platform
    block:

    - name: Declare list of syscalls
      ansible.builtin.set_fact:
        syscalls:
        - fchown
        syscall_grouping:
        - chown
        - fchown
        - fchownat
        - lchown

    - name: Check existence of fchown in /etc/audit/rules.d/
      ansible.builtin.find:
        paths: /etc/audit/rules.d
        contains: -a always,exit -F arch=b64(( -S |,)\w+)*(( -S |,){{ item }})+((
          -S |,)\w+)* -F auid>=1000 -F auid!=unset (-k\s+|-F\s+key=)\S+\s*$
        patterns: '*.rules'
      register: find_command
      loop: '{{ (syscall_grouping + syscalls) | unique }}'

    - name: Reset syscalls found per file
      ansible.builtin.set_fact:
        syscalls_per_file: {}
        found_paths_dict: {}

    - name: Declare syscalls found per file
      ansible.builtin.set_fact: syscalls_per_file="{{ syscalls_per_file | combine(
        {item.files[0].path :[item.item] + syscalls_per_file.get(item.files[0].path,
        []) } ) }}"
      loop: '{{ find_command.results | selectattr(''matched'') | list }}'

    - name: Declare files where syscalls were found
      ansible.builtin.set_fact: found_paths="{{ find_command.results | map(attribute='files')
        | flatten | map(attribute='path') | list }}"

    - name: Count occurrences of syscalls in paths
      ansible.builtin.set_fact: found_paths_dict="{{ found_paths_dict | combine({
        item:1+found_paths_dict.get(item, 0) }) }}"
      loop: '{{ find_command.results | map(attribute=''files'') | flatten | map(attribute=''path'')
        | list }}'

    - name: Get path with most syscalls
      ansible.builtin.set_fact: audit_file="{{ (found_paths_dict | dict2items() |
        sort(attribute='value') | last).key }}"
      when: found_paths | length >= 1

    - name: No file with syscall found, set path to /etc/audit/rules.d/perm_mod.rules
      ansible.builtin.set_fact: audit_file="/etc/audit/rules.d/perm_mod.rules"
      when: found_paths | length == 0

    - name: Declare found syscalls
      ansible.builtin.set_fact: syscalls_found="{{ find_command.results | selectattr('matched')
        | map(attribute='item') | list }}"

    - name: Declare missing syscalls
      ansible.builtin.set_fact: missing_syscalls="{{ syscalls | difference(syscalls_found)
        }}"

    - name: Replace the audit rule in {{ audit_file }}
      ansible.builtin.lineinfile:
        path: '{{ audit_file }}'
        regexp: (-a always,exit -F arch=b64)(?=.*(?:(?:-S |,)(?:{{ syscalls_per_file[audit_file]
          | join("|") }}))\b)((?:( -S |,)\w+)+)( -F auid>=1000 -F auid!=unset (?:-k
          |-F key=)\w+)
        line: \1\2\3{{ missing_syscalls | join("\3") }}\4
        backrefs: true
        state: present
        mode: g-rwx,o-rwx
      when: syscalls_found | length > 0 and missing_syscalls | length > 0

    - name: Add the audit rule to {{ audit_file }}
      ansible.builtin.lineinfile:
        path: '{{ audit_file }}'
        line: -a always,exit -F arch=b64 -S {{ syscalls | join(',') }} -F auid>=1000
          -F auid!=unset -F key=perm_mod
        create: true
        mode: g-rwx,o-rwx
        state: present
      when: syscalls_found | length == 0

    - name: Declare list of syscalls
      ansible.builtin.set_fact:
        syscalls:
        - fchown
        syscall_grouping:
        - chown
        - fchown
        - fchownat
        - lchown

    - name: Check existence of fchown in /etc/audit/audit.rules
      ansible.builtin.find:
        paths: /etc/audit
        contains: -a always,exit -F arch=b64(( -S |,)\w+)*(( -S |,){{ item }})+((
          -S |,)\w+)* -F auid>=1000 -F auid!=unset (-k\s+|-F\s+key=)\S+\s*$
        patterns: audit.rules
      register: find_command
      loop: '{{ (syscall_grouping + syscalls) | unique }}'

    - name: Set path to /etc/audit/audit.rules
      ansible.builtin.set_fact: audit_file="/etc/audit/audit.rules"

    - name: Declare found syscalls
      ansible.builtin.set_fact: syscalls_found="{{ find_command.results | selectattr('matched')
        | map(attribute='item') | list }}"

    - name: Declare missing syscalls
      ansible.builtin.set_fact: missing_syscalls="{{ syscalls | difference(syscalls_found)
        }}"

    - name: Replace the audit rule in {{ audit_file }}
      ansible.builtin.lineinfile:
        path: '{{ audit_file }}'
        regexp: (-a always,exit -F arch=b64)(?=.*(?:(?:-S |,)(?:{{ syscalls_found
          | join("|") }}))\b)((?:( -S |,)\w+)+)( -F auid>=1000 -F auid!=unset (?:-k
          |-F key=)\w+)
        line: \1\2\3{{ missing_syscalls | join("\3") }}\4
        backrefs: true
        state: present
        mode: g-rwx,o-rwx
      when: syscalls_found | length > 0 and missing_syscalls | length > 0

    - name: Add the audit rule to {{ audit_file }}
      ansible.builtin.lineinfile:
        path: '{{ audit_file }}'
        line: -a always,exit -F arch=b64 -S {{ syscalls | join(',') }} -F auid>=1000
          -F auid!=unset -F key=perm_mod
        create: true
        mode: g-rwx,o-rwx
        state: present
      when: syscalls_found | length == 0
    when:
    - '"audit" in ansible_facts.packages'
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - audit_arch == "b64"
    tags:
    - CJIS-5.4.1.1
    - DISA-STIG-OL09-00-000645
    - NIST-800-171-3.1.7
    - NIST-800-53-AU-12(c)
    - NIST-800-53-AU-2(d)
    - NIST-800-53-CM-6(a)
    - PCI-DSS-Req-10.5.5
    - PCI-DSSv4-10.3
    - PCI-DSSv4-10.3.4
    - audit_rules_dac_modification_fchown
    - low_complexity
    - low_disruption
    - medium_severity
    - reboot_required
    - restrict_strategy

  - name: Set architecture for audit fchownat tasks
    ansible.builtin.set_fact:
      audit_arch: b64
    when:
    - '"audit" in ansible_facts.packages'
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - ansible_architecture == "aarch64" or ansible_architecture == "ppc64" or ansible_architecture
      == "ppc64le" or ansible_architecture == "s390x" or ansible_architecture == "x86_64"
    tags:
    - CJIS-5.4.1.1
    - DISA-STIG-OL09-00-000645
    - NIST-800-171-3.1.7
    - NIST-800-53-AU-12(c)
    - NIST-800-53-AU-2(d)
    - NIST-800-53-CM-6(a)
    - PCI-DSS-Req-10.5.5
    - PCI-DSSv4-10.3
    - PCI-DSSv4-10.3.4
    - audit_rules_dac_modification_fchownat
    - low_complexity
    - low_disruption
    - medium_severity
    - reboot_required
    - restrict_strategy

  - name: Perform remediation of Audit rules for fchownat for 32bit platform
    block:

    - name: Declare list of syscalls
      ansible.builtin.set_fact:
        syscalls:
        - fchownat
        syscall_grouping:
        - chown
        - fchown
        - fchownat
        - lchown

    - name: Check existence of fchownat in /etc/audit/rules.d/
      ansible.builtin.find:
        paths: /etc/audit/rules.d
        contains: -a always,exit -F arch=b32(( -S |,)\w+)*(( -S |,){{ item }})+((
          -S |,)\w+)* -F auid>=1000 -F auid!=unset (-k\s+|-F\s+key=)\S+\s*$
        patterns: '*.rules'
      register: find_command
      loop: '{{ (syscall_grouping + syscalls) | unique }}'

    - name: Reset syscalls found per file
      ansible.builtin.set_fact:
        syscalls_per_file: {}
        found_paths_dict: {}

    - name: Declare syscalls found per file
      ansible.builtin.set_fact: syscalls_per_file="{{ syscalls_per_file | combine(
        {item.files[0].path :[item.item] + syscalls_per_file.get(item.files[0].path,
        []) } ) }}"
      loop: '{{ find_command.results | selectattr(''matched'') | list }}'

    - name: Declare files where syscalls were found
      ansible.builtin.set_fact: found_paths="{{ find_command.results | map(attribute='files')
        | flatten | map(attribute='path') | list }}"

    - name: Count occurrences of syscalls in paths
      ansible.builtin.set_fact: found_paths_dict="{{ found_paths_dict | combine({
        item:1+found_paths_dict.get(item, 0) }) }}"
      loop: '{{ find_command.results | map(attribute=''files'') | flatten | map(attribute=''path'')
        | list }}'

    - name: Get path with most syscalls
      ansible.builtin.set_fact: audit_file="{{ (found_paths_dict | dict2items() |
        sort(attribute='value') | last).key }}"
      when: found_paths | length >= 1

    - name: No file with syscall found, set path to /etc/audit/rules.d/perm_mod.rules
      ansible.builtin.set_fact: audit_file="/etc/audit/rules.d/perm_mod.rules"
      when: found_paths | length == 0

    - name: Declare found syscalls
      ansible.builtin.set_fact: syscalls_found="{{ find_command.results | selectattr('matched')
        | map(attribute='item') | list }}"

    - name: Declare missing syscalls
      ansible.builtin.set_fact: missing_syscalls="{{ syscalls | difference(syscalls_found)
        }}"

    - name: Replace the audit rule in {{ audit_file }}
      ansible.builtin.lineinfile:
        path: '{{ audit_file }}'
        regexp: (-a always,exit -F arch=b32)(?=.*(?:(?:-S |,)(?:{{ syscalls_per_file[audit_file]
          | join("|") }}))\b)((?:( -S |,)\w+)+)( -F auid>=1000 -F auid!=unset (?:-k
          |-F key=)\w+)
        line: \1\2\3{{ missing_syscalls | join("\3") }}\4
        backrefs: true
        state: present
        mode: g-rwx,o-rwx
      when: syscalls_found | length > 0 and missing_syscalls | length > 0

    - name: Add the audit rule to {{ audit_file }}
      ansible.builtin.lineinfile:
        path: '{{ audit_file }}'
        line: -a always,exit -F arch=b32 -S {{ syscalls | join(',') }} -F auid>=1000
          -F auid!=unset -F key=perm_mod
        create: true
        mode: g-rwx,o-rwx
        state: present
      when: syscalls_found | length == 0

    - name: Declare list of syscalls
      ansible.builtin.set_fact:
        syscalls:
        - fchownat
        syscall_grouping:
        - chown
        - fchown
        - fchownat
        - lchown

    - name: Check existence of fchownat in /etc/audit/audit.rules
      ansible.builtin.find:
        paths: /etc/audit
        contains: -a always,exit -F arch=b32(( -S |,)\w+)*(( -S |,){{ item }})+((
          -S |,)\w+)* -F auid>=1000 -F auid!=unset (-k\s+|-F\s+key=)\S+\s*$
        patterns: audit.rules
      register: find_command
      loop: '{{ (syscall_grouping + syscalls) | unique }}'

    - name: Set path to /etc/audit/audit.rules
      ansible.builtin.set_fact: audit_file="/etc/audit/audit.rules"

    - name: Declare found syscalls
      ansible.builtin.set_fact: syscalls_found="{{ find_command.results | selectattr('matched')
        | map(attribute='item') | list }}"

    - name: Declare missing syscalls
      ansible.builtin.set_fact: missing_syscalls="{{ syscalls | difference(syscalls_found)
        }}"

    - name: Replace the audit rule in {{ audit_file }}
      ansible.builtin.lineinfile:
        path: '{{ audit_file }}'
        regexp: (-a always,exit -F arch=b32)(?=.*(?:(?:-S |,)(?:{{ syscalls_found
          | join("|") }}))\b)((?:( -S |,)\w+)+)( -F auid>=1000 -F auid!=unset (?:-k
          |-F key=)\w+)
        line: \1\2\3{{ missing_syscalls | join("\3") }}\4
        backrefs: true
        state: present
        mode: g-rwx,o-rwx
      when: syscalls_found | length > 0 and missing_syscalls | length > 0

    - name: Add the audit rule to {{ audit_file }}
      ansible.builtin.lineinfile:
        path: '{{ audit_file }}'
        line: -a always,exit -F arch=b32 -S {{ syscalls | join(',') }} -F auid>=1000
          -F auid!=unset -F key=perm_mod
        create: true
        mode: g-rwx,o-rwx
        state: present
      when: syscalls_found | length == 0
    when:
    - '"audit" in ansible_facts.packages'
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - CJIS-5.4.1.1
    - DISA-STIG-OL09-00-000645
    - NIST-800-171-3.1.7
    - NIST-800-53-AU-12(c)
    - NIST-800-53-AU-2(d)
    - NIST-800-53-CM-6(a)
    - PCI-DSS-Req-10.5.5
    - PCI-DSSv4-10.3
    - PCI-DSSv4-10.3.4
    - audit_rules_dac_modification_fchownat
    - low_complexity
    - low_disruption
    - medium_severity
    - reboot_required
    - restrict_strategy

  - name: Perform remediation of Audit rules for fchownat for 64bit platform
    block:

    - name: Declare list of syscalls
      ansible.builtin.set_fact:
        syscalls:
        - fchownat
        syscall_grouping:
        - chown
        - fchown
        - fchownat
        - lchown

    - name: Check existence of fchownat in /etc/audit/rules.d/
      ansible.builtin.find:
        paths: /etc/audit/rules.d
        contains: -a always,exit -F arch=b64(( -S |,)\w+)*(( -S |,){{ item }})+((
          -S |,)\w+)* -F auid>=1000 -F auid!=unset (-k\s+|-F\s+key=)\S+\s*$
        patterns: '*.rules'
      register: find_command
      loop: '{{ (syscall_grouping + syscalls) | unique }}'

    - name: Reset syscalls found per file
      ansible.builtin.set_fact:
        syscalls_per_file: {}
        found_paths_dict: {}

    - name: Declare syscalls found per file
      ansible.builtin.set_fact: syscalls_per_file="{{ syscalls_per_file | combine(
        {item.files[0].path :[item.item] + syscalls_per_file.get(item.files[0].path,
        []) } ) }}"
      loop: '{{ find_command.results | selectattr(''matched'') | list }}'

    - name: Declare files where syscalls were found
      ansible.builtin.set_fact: found_paths="{{ find_command.results | map(attribute='files')
        | flatten | map(attribute='path') | list }}"

    - name: Count occurrences of syscalls in paths
      ansible.builtin.set_fact: found_paths_dict="{{ found_paths_dict | combine({
        item:1+found_paths_dict.get(item, 0) }) }}"
      loop: '{{ find_command.results | map(attribute=''files'') | flatten | map(attribute=''path'')
        | list }}'

    - name: Get path with most syscalls
      ansible.builtin.set_fact: audit_file="{{ (found_paths_dict | dict2items() |
        sort(attribute='value') | last).key }}"
      when: found_paths | length >= 1

    - name: No file with syscall found, set path to /etc/audit/rules.d/perm_mod.rules
      ansible.builtin.set_fact: audit_file="/etc/audit/rules.d/perm_mod.rules"
      when: found_paths | length == 0

    - name: Declare found syscalls
      ansible.builtin.set_fact: syscalls_found="{{ find_command.results | selectattr('matched')
        | map(attribute='item') | list }}"

    - name: Declare missing syscalls
      ansible.builtin.set_fact: missing_syscalls="{{ syscalls | difference(syscalls_found)
        }}"

    - name: Replace the audit rule in {{ audit_file }}
      ansible.builtin.lineinfile:
        path: '{{ audit_file }}'
        regexp: (-a always,exit -F arch=b64)(?=.*(?:(?:-S |,)(?:{{ syscalls_per_file[audit_file]
          | join("|") }}))\b)((?:( -S |,)\w+)+)( -F auid>=1000 -F auid!=unset (?:-k
          |-F key=)\w+)
        line: \1\2\3{{ missing_syscalls | join("\3") }}\4
        backrefs: true
        state: present
        mode: g-rwx,o-rwx
      when: syscalls_found | length > 0 and missing_syscalls | length > 0

    - name: Add the audit rule to {{ audit_file }}
      ansible.builtin.lineinfile:
        path: '{{ audit_file }}'
        line: -a always,exit -F arch=b64 -S {{ syscalls | join(',') }} -F auid>=1000
          -F auid!=unset -F key=perm_mod
        create: true
        mode: g-rwx,o-rwx
        state: present
      when: syscalls_found | length == 0

    - name: Declare list of syscalls
      ansible.builtin.set_fact:
        syscalls:
        - fchownat
        syscall_grouping:
        - chown
        - fchown
        - fchownat
        - lchown

    - name: Check existence of fchownat in /etc/audit/audit.rules
      ansible.builtin.find:
        paths: /etc/audit
        contains: -a always,exit -F arch=b64(( -S |,)\w+)*(( -S |,){{ item }})+((
          -S |,)\w+)* -F auid>=1000 -F auid!=unset (-k\s+|-F\s+key=)\S+\s*$
        patterns: audit.rules
      register: find_command
      loop: '{{ (syscall_grouping + syscalls) | unique }}'

    - name: Set path to /etc/audit/audit.rules
      ansible.builtin.set_fact: audit_file="/etc/audit/audit.rules"

    - name: Declare found syscalls
      ansible.builtin.set_fact: syscalls_found="{{ find_command.results | selectattr('matched')
        | map(attribute='item') | list }}"

    - name: Declare missing syscalls
      ansible.builtin.set_fact: missing_syscalls="{{ syscalls | difference(syscalls_found)
        }}"

    - name: Replace the audit rule in {{ audit_file }}
      ansible.builtin.lineinfile:
        path: '{{ audit_file }}'
        regexp: (-a always,exit -F arch=b64)(?=.*(?:(?:-S |,)(?:{{ syscalls_found
          | join("|") }}))\b)((?:( -S |,)\w+)+)( -F auid>=1000 -F auid!=unset (?:-k
          |-F key=)\w+)
        line: \1\2\3{{ missing_syscalls | join("\3") }}\4
        backrefs: true
        state: present
        mode: g-rwx,o-rwx
      when: syscalls_found | length > 0 and missing_syscalls | length > 0

    - name: Add the audit rule to {{ audit_file }}
      ansible.builtin.lineinfile:
        path: '{{ audit_file }}'
        line: -a always,exit -F arch=b64 -S {{ syscalls | join(',') }} -F auid>=1000
          -F auid!=unset -F key=perm_mod
        create: true
        mode: g-rwx,o-rwx
        state: present
      when: syscalls_found | length == 0
    when:
    - '"audit" in ansible_facts.packages'
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - audit_arch == "b64"
    tags:
    - CJIS-5.4.1.1
    - DISA-STIG-OL09-00-000645
    - NIST-800-171-3.1.7
    - NIST-800-53-AU-12(c)
    - NIST-800-53-AU-2(d)
    - NIST-800-53-CM-6(a)
    - PCI-DSS-Req-10.5.5
    - PCI-DSSv4-10.3
    - PCI-DSSv4-10.3.4
    - audit_rules_dac_modification_fchownat
    - low_complexity
    - low_disruption
    - medium_severity
    - reboot_required
    - restrict_strategy

  - name: Set architecture for audit fremovexattr tasks
    ansible.builtin.set_fact:
      audit_arch: b64
    when:
    - '"audit" in ansible_facts.packages'
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - ansible_architecture == "aarch64" or ansible_architecture == "ppc64" or ansible_architecture
      == "ppc64le" or ansible_architecture == "s390x" or ansible_architecture == "x86_64"
    tags:
    - CJIS-5.4.1.1
    - DISA-STIG-OL09-00-000545
    - NIST-800-171-3.1.7
    - NIST-800-53-AU-12(c)
    - NIST-800-53-AU-2(d)
    - NIST-800-53-CM-6(a)
    - PCI-DSS-Req-10.5.5
    - PCI-DSSv4-10.3
    - PCI-DSSv4-10.3.4
    - audit_rules_dac_modification_fremovexattr
    - low_complexity
    - low_disruption
    - medium_severity
    - reboot_required
    - restrict_strategy

  - name: Perform remediation of Audit rules for fremovexattr for 32bit platform
    block:

    - name: Declare list of syscalls
      ansible.builtin.set_fact:
        syscalls:
        - fremovexattr
        syscall_grouping:
        - fremovexattr
        - lremovexattr
        - removexattr
        - fsetxattr
        - lsetxattr
        - setxattr

    - name: Check existence of fremovexattr in /etc/audit/rules.d/
      ansible.builtin.find:
        paths: /etc/audit/rules.d
        contains: -a always,exit -F arch=b32(( -S |,)\w+)*(( -S |,){{ item }})+((
          -S |,)\w+)* -F auid>=1000 -F auid!=unset (-k\s+|-F\s+key=)\S+\s*$
        patterns: '*.rules'
      register: find_command
      loop: '{{ (syscall_grouping + syscalls) | unique }}'

    - name: Reset syscalls found per file
      ansible.builtin.set_fact:
        syscalls_per_file: {}
        found_paths_dict: {}

    - name: Declare syscalls found per file
      ansible.builtin.set_fact: syscalls_per_file="{{ syscalls_per_file | combine(
        {item.files[0].path :[item.item] + syscalls_per_file.get(item.files[0].path,
        []) } ) }}"
      loop: '{{ find_command.results | selectattr(''matched'') | list }}'

    - name: Declare files where syscalls were found
      ansible.builtin.set_fact: found_paths="{{ find_command.results | map(attribute='files')
        | flatten | map(attribute='path') | list }}"

    - name: Count occurrences of syscalls in paths
      ansible.builtin.set_fact: found_paths_dict="{{ found_paths_dict | combine({
        item:1+found_paths_dict.get(item, 0) }) }}"
      loop: '{{ find_command.results | map(attribute=''files'') | flatten | map(attribute=''path'')
        | list }}'

    - name: Get path with most syscalls
      ansible.builtin.set_fact: audit_file="{{ (found_paths_dict | dict2items() |
        sort(attribute='value') | last).key }}"
      when: found_paths | length >= 1

    - name: No file with syscall found, set path to /etc/audit/rules.d/perm_mod.rules
      ansible.builtin.set_fact: audit_file="/etc/audit/rules.d/perm_mod.rules"
      when: found_paths | length == 0

    - name: Declare found syscalls
      ansible.builtin.set_fact: syscalls_found="{{ find_command.results | selectattr('matched')
        | map(attribute='item') | list }}"

    - name: Declare missing syscalls
      ansible.builtin.set_fact: missing_syscalls="{{ syscalls | difference(syscalls_found)
        }}"

    - name: Replace the audit rule in {{ audit_file }}
      ansible.builtin.lineinfile:
        path: '{{ audit_file }}'
        regexp: (-a always,exit -F arch=b32)(?=.*(?:(?:-S |,)(?:{{ syscalls_per_file[audit_file]
          | join("|") }}))\b)((?:( -S |,)\w+)+)( -F auid>=1000 -F auid!=unset (?:-k
          |-F key=)\w+)
        line: \1\2\3{{ missing_syscalls | join("\3") }}\4
        backrefs: true
        state: present
        mode: g-rwx,o-rwx
      when: syscalls_found | length > 0 and missing_syscalls | length > 0

    - name: Add the audit rule to {{ audit_file }}
      ansible.builtin.lineinfile:
        path: '{{ audit_file }}'
        line: -a always,exit -F arch=b32 -S {{ syscalls | join(',') }} -F auid>=1000
          -F auid!=unset -F key=perm_mod
        create: true
        mode: g-rwx,o-rwx
        state: present
      when: syscalls_found | length == 0

    - name: Declare list of syscalls
      ansible.builtin.set_fact:
        syscalls:
        - fremovexattr
        syscall_grouping:
        - fremovexattr
        - lremovexattr
        - removexattr
        - fsetxattr
        - lsetxattr
        - setxattr

    - name: Check existence of fremovexattr in /etc/audit/audit.rules
      ansible.builtin.find:
        paths: /etc/audit
        contains: -a always,exit -F arch=b32(( -S |,)\w+)*(( -S |,){{ item }})+((
          -S |,)\w+)* -F auid>=1000 -F auid!=unset (-k\s+|-F\s+key=)\S+\s*$
        patterns: audit.rules
      register: find_command
      loop: '{{ (syscall_grouping + syscalls) | unique }}'

    - name: Set path to /etc/audit/audit.rules
      ansible.builtin.set_fact: audit_file="/etc/audit/audit.rules"

    - name: Declare found syscalls
      ansible.builtin.set_fact: syscalls_found="{{ find_command.results | selectattr('matched')
        | map(attribute='item') | list }}"

    - name: Declare missing syscalls
      ansible.builtin.set_fact: missing_syscalls="{{ syscalls | difference(syscalls_found)
        }}"

    - name: Replace the audit rule in {{ audit_file }}
      ansible.builtin.lineinfile:
        path: '{{ audit_file }}'
        regexp: (-a always,exit -F arch=b32)(?=.*(?:(?:-S |,)(?:{{ syscalls_found
          | join("|") }}))\b)((?:( -S |,)\w+)+)( -F auid>=1000 -F auid!=unset (?:-k
          |-F key=)\w+)
        line: \1\2\3{{ missing_syscalls | join("\3") }}\4
        backrefs: true
        state: present
        mode: g-rwx,o-rwx
      when: syscalls_found | length > 0 and missing_syscalls | length > 0

    - name: Add the audit rule to {{ audit_file }}
      ansible.builtin.lineinfile:
        path: '{{ audit_file }}'
        line: -a always,exit -F arch=b32 -S {{ syscalls | join(',') }} -F auid>=1000
          -F auid!=unset -F key=perm_mod
        create: true
        mode: g-rwx,o-rwx
        state: present
      when: syscalls_found | length == 0

    - name: Declare list of syscalls
      ansible.builtin.set_fact:
        syscalls:
        - fremovexattr
        syscall_grouping:
        - fremovexattr
        - lremovexattr
        - removexattr
        - fsetxattr
        - lsetxattr
        - setxattr

    - name: Check existence of fremovexattr in /etc/audit/rules.d/
      ansible.builtin.find:
        paths: /etc/audit/rules.d
        contains: -a always,exit -F arch=b32(( -S |,)\w+)*(( -S |,){{ item }})+((
          -S |,)\w+)* -F auid=0 (-k\s+|-F\s+key=)\S+\s*$
        patterns: '*.rules'
      register: find_command
      loop: '{{ (syscall_grouping + syscalls) | unique }}'

    - name: Reset syscalls found per file
      ansible.builtin.set_fact:
        syscalls_per_file: {}
        found_paths_dict: {}

    - name: Declare syscalls found per file
      ansible.builtin.set_fact: syscalls_per_file="{{ syscalls_per_file | combine(
        {item.files[0].path :[item.item] + syscalls_per_file.get(item.files[0].path,
        []) } ) }}"
      loop: '{{ find_command.results | selectattr(''matched'') | list }}'

    - name: Declare files where syscalls were found
      ansible.builtin.set_fact: found_paths="{{ find_command.results | map(attribute='files')
        | flatten | map(attribute='path') | list }}"

    - name: Count occurrences of syscalls in paths
      ansible.builtin.set_fact: found_paths_dict="{{ found_paths_dict | combine({
        item:1+found_paths_dict.get(item, 0) }) }}"
      loop: '{{ find_command.results | map(attribute=''files'') | flatten | map(attribute=''path'')
        | list }}'

    - name: Get path with most syscalls
      ansible.builtin.set_fact: audit_file="{{ (found_paths_dict | dict2items() |
        sort(attribute='value') | last).key }}"
      when: found_paths | length >= 1

    - name: No file with syscall found, set path to /etc/audit/rules.d/perm_mod.rules
      ansible.builtin.set_fact: audit_file="/etc/audit/rules.d/perm_mod.rules"
      when: found_paths | length == 0

    - name: Declare found syscalls
      ansible.builtin.set_fact: syscalls_found="{{ find_command.results | selectattr('matched')
        | map(attribute='item') | list }}"

    - name: Declare missing syscalls
      ansible.builtin.set_fact: missing_syscalls="{{ syscalls | difference(syscalls_found)
        }}"

    - name: Replace the audit rule in {{ audit_file }}
      ansible.builtin.lineinfile:
        path: '{{ audit_file }}'
        regexp: (-a always,exit -F arch=b32)(?=.*(?:(?:-S |,)(?:{{ syscalls_per_file[audit_file]
          | join("|") }}))\b)((?:( -S |,)\w+)+)( -F auid=0 (?:-k |-F key=)\w+)
        line: \1\2\3{{ missing_syscalls | join("\3") }}\4
        backrefs: true
        state: present
        mode: g-rwx,o-rwx
      when: syscalls_found | length > 0 and missing_syscalls | length > 0

    - name: Add the audit rule to {{ audit_file }}
      ansible.builtin.lineinfile:
        path: '{{ audit_file }}'
        line: -a always,exit -F arch=b32 -S {{ syscalls | join(',') }} -F auid=0 -F
          key=perm_mod
        create: true
        mode: g-rwx,o-rwx
        state: present
      when: syscalls_found | length == 0

    - name: Declare list of syscalls
      ansible.builtin.set_fact:
        syscalls:
        - fremovexattr
        syscall_grouping:
        - fremovexattr
        - lremovexattr
        - removexattr
        - fsetxattr
        - lsetxattr
        - setxattr

    - name: Check existence of fremovexattr in /etc/audit/audit.rules
      ansible.builtin.find:
        paths: /etc/audit
        contains: -a always,exit -F arch=b32(( -S |,)\w+)*(( -S |,){{ item }})+((
          -S |,)\w+)* -F auid=0 (-k\s+|-F\s+key=)\S+\s*$
        patterns: audit.rules
      register: find_command
      loop: '{{ (syscall_grouping + syscalls) | unique }}'

    - name: Set path to /etc/audit/audit.rules
      ansible.builtin.set_fact: audit_file="/etc/audit/audit.rules"

    - name: Declare found syscalls
      ansible.builtin.set_fact: syscalls_found="{{ find_command.results | selectattr('matched')
        | map(attribute='item') | list }}"

    - name: Declare missing syscalls
      ansible.builtin.set_fact: missing_syscalls="{{ syscalls | difference(syscalls_found)
        }}"

    - name: Replace the audit rule in {{ audit_file }}
      ansible.builtin.lineinfile:
        path: '{{ audit_file }}'
        regexp: (-a always,exit -F arch=b32)(?=.*(?:(?:-S |,)(?:{{ syscalls_found
          | join("|") }}))\b)((?:( -S |,)\w+)+)( -F auid=0 (?:-k |-F key=)\w+)
        line: \1\2\3{{ missing_syscalls | join("\3") }}\4
        backrefs: true
        state: present
        mode: g-rwx,o-rwx
      when: syscalls_found | length > 0 and missing_syscalls | length > 0

    - name: Add the audit rule to {{ audit_file }}
      ansible.builtin.lineinfile:
        path: '{{ audit_file }}'
        line: -a always,exit -F arch=b32 -S {{ syscalls | join(',') }} -F auid=0 -F
          key=perm_mod
        create: true
        mode: g-rwx,o-rwx
        state: present
      when: syscalls_found | length == 0
    when:
    - '"audit" in ansible_facts.packages'
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - CJIS-5.4.1.1
    - DISA-STIG-OL09-00-000545
    - NIST-800-171-3.1.7
    - NIST-800-53-AU-12(c)
    - NIST-800-53-AU-2(d)
    - NIST-800-53-CM-6(a)
    - PCI-DSS-Req-10.5.5
    - PCI-DSSv4-10.3
    - PCI-DSSv4-10.3.4
    - audit_rules_dac_modification_fremovexattr
    - low_complexity
    - low_disruption
    - medium_severity
    - reboot_required
    - restrict_strategy

  - name: Perform remediation of Audit rules for fremovexattr for 64bit platform
    block:

    - name: Declare list of syscalls
      ansible.builtin.set_fact:
        syscalls:
        - fremovexattr
        syscall_grouping:
        - fremovexattr
        - lremovexattr
        - removexattr
        - fsetxattr
        - lsetxattr
        - setxattr

    - name: Check existence of fremovexattr in /etc/audit/rules.d/
      ansible.builtin.find:
        paths: /etc/audit/rules.d
        contains: -a always,exit -F arch=b64(( -S |,)\w+)*(( -S |,){{ item }})+((
          -S |,)\w+)* -F auid>=1000 -F auid!=unset (-k\s+|-F\s+key=)\S+\s*$
        patterns: '*.rules'
      register: find_command
      loop: '{{ (syscall_grouping + syscalls) | unique }}'

    - name: Reset syscalls found per file
      ansible.builtin.set_fact:
        syscalls_per_file: {}
        found_paths_dict: {}

    - name: Declare syscalls found per file
      ansible.builtin.set_fact: syscalls_per_file="{{ syscalls_per_file | combine(
        {item.files[0].path :[item.item] + syscalls_per_file.get(item.files[0].path,
        []) } ) }}"
      loop: '{{ find_command.results | selectattr(''matched'') | list }}'

    - name: Declare files where syscalls were found
      ansible.builtin.set_fact: found_paths="{{ find_command.results | map(attribute='files')
        | flatten | map(attribute='path') | list }}"

    - name: Count occurrences of syscalls in paths
      ansible.builtin.set_fact: found_paths_dict="{{ found_paths_dict | combine({
        item:1+found_paths_dict.get(item, 0) }) }}"
      loop: '{{ find_command.results | map(attribute=''files'') | flatten | map(attribute=''path'')
        | list }}'

    - name: Get path with most syscalls
      ansible.builtin.set_fact: audit_file="{{ (found_paths_dict | dict2items() |
        sort(attribute='value') | last).key }}"
      when: found_paths | length >= 1

    - name: No file with syscall found, set path to /etc/audit/rules.d/perm_mod.rules
      ansible.builtin.set_fact: audit_file="/etc/audit/rules.d/perm_mod.rules"
      when: found_paths | length == 0

    - name: Declare found syscalls
      ansible.builtin.set_fact: syscalls_found="{{ find_command.results | selectattr('matched')
        | map(attribute='item') | list }}"

    - name: Declare missing syscalls
      ansible.builtin.set_fact: missing_syscalls="{{ syscalls | difference(syscalls_found)
        }}"

    - name: Replace the audit rule in {{ audit_file }}
      ansible.builtin.lineinfile:
        path: '{{ audit_file }}'
        regexp: (-a always,exit -F arch=b64)(?=.*(?:(?:-S |,)(?:{{ syscalls_per_file[audit_file]
          | join("|") }}))\b)((?:( -S |,)\w+)+)( -F auid>=1000 -F auid!=unset (?:-k
          |-F key=)\w+)
        line: \1\2\3{{ missing_syscalls | join("\3") }}\4
        backrefs: true
        state: present
        mode: g-rwx,o-rwx
      when: syscalls_found | length > 0 and missing_syscalls | length > 0

    - name: Add the audit rule to {{ audit_file }}
      ansible.builtin.lineinfile:
        path: '{{ audit_file }}'
        line: -a always,exit -F arch=b64 -S {{ syscalls | join(',') }} -F auid>=1000
          -F auid!=unset -F key=perm_mod
        create: true
        mode: g-rwx,o-rwx
        state: present
      when: syscalls_found | length == 0

    - name: Declare list of syscalls
      ansible.builtin.set_fact:
        syscalls:
        - fremovexattr
        syscall_grouping:
        - fremovexattr
        - lremovexattr
        - removexattr
        - fsetxattr
        - lsetxattr
        - setxattr

    - name: Check existence of fremovexattr in /etc/audit/audit.rules
      ansible.builtin.find:
        paths: /etc/audit
        contains: -a always,exit -F arch=b64(( -S |,)\w+)*(( -S |,){{ item }})+((
          -S |,)\w+)* -F auid>=1000 -F auid!=unset (-k\s+|-F\s+key=)\S+\s*$
        patterns: audit.rules
      register: find_command
      loop: '{{ (syscall_grouping + syscalls) | unique }}'

    - name: Set path to /etc/audit/audit.rules
      ansible.builtin.set_fact: audit_file="/etc/audit/audit.rules"

    - name: Declare found syscalls
      ansible.builtin.set_fact: syscalls_found="{{ find_command.results | selectattr('matched')
        | map(attribute='item') | list }}"

    - name: Declare missing syscalls
      ansible.builtin.set_fact: missing_syscalls="{{ syscalls | difference(syscalls_found)
        }}"

    - name: Replace the audit rule in {{ audit_file }}
      ansible.builtin.lineinfile:
        path: '{{ audit_file }}'
        regexp: (-a always,exit -F arch=b64)(?=.*(?:(?:-S |,)(?:{{ syscalls_found
          | join("|") }}))\b)((?:( -S |,)\w+)+)( -F auid>=1000 -F auid!=unset (?:-k
          |-F key=)\w+)
        line: \1\2\3{{ missing_syscalls | join("\3") }}\4
        backrefs: true
        state: present
        mode: g-rwx,o-rwx
      when: syscalls_found | length > 0 and missing_syscalls | length > 0

    - name: Add the audit rule to {{ audit_file }}
      ansible.builtin.lineinfile:
        path: '{{ audit_file }}'
        line: -a always,exit -F arch=b64 -S {{ syscalls | join(',') }} -F auid>=1000
          -F auid!=unset -F key=perm_mod
        create: true
        mode: g-rwx,o-rwx
        state: present
      when: syscalls_found | length == 0

    - name: Declare list of syscalls
      ansible.builtin.set_fact:
        syscalls:
        - fremovexattr
        syscall_grouping:
        - fremovexattr
        - lremovexattr
        - removexattr
        - fsetxattr
        - lsetxattr
        - setxattr

    - name: Check existence of fremovexattr in /etc/audit/rules.d/
      ansible.builtin.find:
        paths: /etc/audit/rules.d
        contains: -a always,exit -F arch=b64(( -S |,)\w+)*(( -S |,){{ item }})+((
          -S |,)\w+)* -F auid=0 (-k\s+|-F\s+key=)\S+\s*$
        patterns: '*.rules'
      register: find_command
      loop: '{{ (syscall_grouping + syscalls) | unique }}'

    - name: Reset syscalls found per file
      ansible.builtin.set_fact:
        syscalls_per_file: {}
        found_paths_dict: {}

    - name: Declare syscalls found per file
      ansible.builtin.set_fact: syscalls_per_file="{{ syscalls_per_file | combine(
        {item.files[0].path :[item.item] + syscalls_per_file.get(item.files[0].path,
        []) } ) }}"
      loop: '{{ find_command.results | selectattr(''matched'') | list }}'

    - name: Declare files where syscalls were found
      ansible.builtin.set_fact: found_paths="{{ find_command.results | map(attribute='files')
        | flatten | map(attribute='path') | list }}"

    - name: Count occurrences of syscalls in paths
      ansible.builtin.set_fact: found_paths_dict="{{ found_paths_dict | combine({
        item:1+found_paths_dict.get(item, 0) }) }}"
      loop: '{{ find_command.results | map(attribute=''files'') | flatten | map(attribute=''path'')
        | list }}'

    - name: Get path with most syscalls
      ansible.builtin.set_fact: audit_file="{{ (found_paths_dict | dict2items() |
        sort(attribute='value') | last).key }}"
      when: found_paths | length >= 1

    - name: No file with syscall found, set path to /etc/audit/rules.d/perm_mod.rules
      ansible.builtin.set_fact: audit_file="/etc/audit/rules.d/perm_mod.rules"
      when: found_paths | length == 0

    - name: Declare found syscalls
      ansible.builtin.set_fact: syscalls_found="{{ find_command.results | selectattr('matched')
        | map(attribute='item') | list }}"

    - name: Declare missing syscalls
      ansible.builtin.set_fact: missing_syscalls="{{ syscalls | difference(syscalls_found)
        }}"

    - name: Replace the audit rule in {{ audit_file }}
      ansible.builtin.lineinfile:
        path: '{{ audit_file }}'
        regexp: (-a always,exit -F arch=b64)(?=.*(?:(?:-S |,)(?:{{ syscalls_per_file[audit_file]
          | join("|") }}))\b)((?:( -S |,)\w+)+)( -F auid=0 (?:-k |-F key=)\w+)
        line: \1\2\3{{ missing_syscalls | join("\3") }}\4
        backrefs: true
        state: present
        mode: g-rwx,o-rwx
      when: syscalls_found | length > 0 and missing_syscalls | length > 0

    - name: Add the audit rule to {{ audit_file }}
      ansible.builtin.lineinfile:
        path: '{{ audit_file }}'
        line: -a always,exit -F arch=b64 -S {{ syscalls | join(',') }} -F auid=0 -F
          key=perm_mod
        create: true
        mode: g-rwx,o-rwx
        state: present
      when: syscalls_found | length == 0

    - name: Declare list of syscalls
      ansible.builtin.set_fact:
        syscalls:
        - fremovexattr
        syscall_grouping:
        - fremovexattr
        - lremovexattr
        - removexattr
        - fsetxattr
        - lsetxattr
        - setxattr

    - name: Check existence of fremovexattr in /etc/audit/audit.rules
      ansible.builtin.find:
        paths: /etc/audit
        contains: -a always,exit -F arch=b64(( -S |,)\w+)*(( -S |,){{ item }})+((
          -S |,)\w+)* -F auid=0 (-k\s+|-F\s+key=)\S+\s*$
        patterns: audit.rules
      register: find_command
      loop: '{{ (syscall_grouping + syscalls) | unique }}'

    - name: Set path to /etc/audit/audit.rules
      ansible.builtin.set_fact: audit_file="/etc/audit/audit.rules"

    - name: Declare found syscalls
      ansible.builtin.set_fact: syscalls_found="{{ find_command.results | selectattr('matched')
        | map(attribute='item') | list }}"

    - name: Declare missing syscalls
      ansible.builtin.set_fact: missing_syscalls="{{ syscalls | difference(syscalls_found)
        }}"

    - name: Replace the audit rule in {{ audit_file }}
      ansible.builtin.lineinfile:
        path: '{{ audit_file }}'
        regexp: (-a always,exit -F arch=b64)(?=.*(?:(?:-S |,)(?:{{ syscalls_found
          | join("|") }}))\b)((?:( -S |,)\w+)+)( -F auid=0 (?:-k |-F key=)\w+)
        line: \1\2\3{{ missing_syscalls | join("\3") }}\4
        backrefs: true
        state: present
        mode: g-rwx,o-rwx
      when: syscalls_found | length > 0 and missing_syscalls | length > 0

    - name: Add the audit rule to {{ audit_file }}
      ansible.builtin.lineinfile:
        path: '{{ audit_file }}'
        line: -a always,exit -F arch=b64 -S {{ syscalls | join(',') }} -F auid=0 -F
          key=perm_mod
        create: true
        mode: g-rwx,o-rwx
        state: present
      when: syscalls_found | length == 0
    when:
    - '"audit" in ansible_facts.packages'
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - audit_arch == "b64"
    tags:
    - CJIS-5.4.1.1
    - DISA-STIG-OL09-00-000545
    - NIST-800-171-3.1.7
    - NIST-800-53-AU-12(c)
    - NIST-800-53-AU-2(d)
    - NIST-800-53-CM-6(a)
    - PCI-DSS-Req-10.5.5
    - PCI-DSSv4-10.3
    - PCI-DSSv4-10.3.4
    - audit_rules_dac_modification_fremovexattr
    - low_complexity
    - low_disruption
    - medium_severity
    - reboot_required
    - restrict_strategy

  - name: Set architecture for audit fsetxattr tasks
    ansible.builtin.set_fact:
      audit_arch: b64
    when:
    - '"audit" in ansible_facts.packages'
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - ansible_architecture == "aarch64" or ansible_architecture == "ppc64" or ansible_architecture
      == "ppc64le" or ansible_architecture == "s390x" or ansible_architecture == "x86_64"
    tags:
    - CJIS-5.4.1.1
    - DISA-STIG-OL09-00-000545
    - NIST-800-171-3.1.7
    - NIST-800-53-AU-12(c)
    - NIST-800-53-AU-2(d)
    - NIST-800-53-CM-6(a)
    - PCI-DSS-Req-10.5.5
    - PCI-DSSv4-10.3
    - PCI-DSSv4-10.3.4
    - audit_rules_dac_modification_fsetxattr
    - low_complexity
    - low_disruption
    - medium_severity
    - reboot_required
    - restrict_strategy

  - name: Perform remediation of Audit rules for fsetxattr for 32bit platform
    block:

    - name: Declare list of syscalls
      ansible.builtin.set_fact:
        syscalls:
        - fsetxattr
        syscall_grouping:
        - fremovexattr
        - lremovexattr
        - removexattr
        - fsetxattr
        - lsetxattr
        - setxattr

    - name: Check existence of fsetxattr in /etc/audit/rules.d/
      ansible.builtin.find:
        paths: /etc/audit/rules.d
        contains: -a always,exit -F arch=b32(( -S |,)\w+)*(( -S |,){{ item }})+((
          -S |,)\w+)* -F auid>=1000 -F auid!=unset (-k\s+|-F\s+key=)\S+\s*$
        patterns: '*.rules'
      register: find_command
      loop: '{{ (syscall_grouping + syscalls) | unique }}'

    - name: Reset syscalls found per file
      ansible.builtin.set_fact:
        syscalls_per_file: {}
        found_paths_dict: {}

    - name: Declare syscalls found per file
      ansible.builtin.set_fact: syscalls_per_file="{{ syscalls_per_file | combine(
        {item.files[0].path :[item.item] + syscalls_per_file.get(item.files[0].path,
        []) } ) }}"
      loop: '{{ find_command.results | selectattr(''matched'') | list }}'

    - name: Declare files where syscalls were found
      ansible.builtin.set_fact: found_paths="{{ find_command.results | map(attribute='files')
        | flatten | map(attribute='path') | list }}"

    - name: Count occurrences of syscalls in paths
      ansible.builtin.set_fact: found_paths_dict="{{ found_paths_dict | combine({
        item:1+found_paths_dict.get(item, 0) }) }}"
      loop: '{{ find_command.results | map(attribute=''files'') | flatten | map(attribute=''path'')
        | list }}'

    - name: Get path with most syscalls
      ansible.builtin.set_fact: audit_file="{{ (found_paths_dict | dict2items() |
        sort(attribute='value') | last).key }}"
      when: found_paths | length >= 1

    - name: No file with syscall found, set path to /etc/audit/rules.d/perm_mod.rules
      ansible.builtin.set_fact: audit_file="/etc/audit/rules.d/perm_mod.rules"
      when: found_paths | length == 0

    - name: Declare found syscalls
      ansible.builtin.set_fact: syscalls_found="{{ find_command.results | selectattr('matched')
        | map(attribute='item') | list }}"

    - name: Declare missing syscalls
      ansible.builtin.set_fact: missing_syscalls="{{ syscalls | difference(syscalls_found)
        }}"

    - name: Replace the audit rule in {{ audit_file }}
      ansible.builtin.lineinfile:
        path: '{{ audit_file }}'
        regexp: (-a always,exit -F arch=b32)(?=.*(?:(?:-S |,)(?:{{ syscalls_per_file[audit_file]
          | join("|") }}))\b)((?:( -S |,)\w+)+)( -F auid>=1000 -F auid!=unset (?:-k
          |-F key=)\w+)
        line: \1\2\3{{ missing_syscalls | join("\3") }}\4
        backrefs: true
        state: present
        mode: g-rwx,o-rwx
      when: syscalls_found | length > 0 and missing_syscalls | length > 0

    - name: Add the audit rule to {{ audit_file }}
      ansible.builtin.lineinfile:
        path: '{{ audit_file }}'
        line: -a always,exit -F arch=b32 -S {{ syscalls | join(',') }} -F auid>=1000
          -F auid!=unset -F key=perm_mod
        create: true
        mode: g-rwx,o-rwx
        state: present
      when: syscalls_found | length == 0

    - name: Declare list of syscalls
      ansible.builtin.set_fact:
        syscalls:
        - fsetxattr
        syscall_grouping:
        - fremovexattr
        - lremovexattr
        - removexattr
        - fsetxattr
        - lsetxattr
        - setxattr

    - name: Check existence of fsetxattr in /etc/audit/audit.rules
      ansible.builtin.find:
        paths: /etc/audit
        contains: -a always,exit -F arch=b32(( -S |,)\w+)*(( -S |,){{ item }})+((
          -S |,)\w+)* -F auid>=1000 -F auid!=unset (-k\s+|-F\s+key=)\S+\s*$
        patterns: audit.rules
      register: find_command
      loop: '{{ (syscall_grouping + syscalls) | unique }}'

    - name: Set path to /etc/audit/audit.rules
      ansible.builtin.set_fact: audit_file="/etc/audit/audit.rules"

    - name: Declare found syscalls
      ansible.builtin.set_fact: syscalls_found="{{ find_command.results | selectattr('matched')
        | map(attribute='item') | list }}"

    - name: Declare missing syscalls
      ansible.builtin.set_fact: missing_syscalls="{{ syscalls | difference(syscalls_found)
        }}"

    - name: Replace the audit rule in {{ audit_file }}
      ansible.builtin.lineinfile:
        path: '{{ audit_file }}'
        regexp: (-a always,exit -F arch=b32)(?=.*(?:(?:-S |,)(?:{{ syscalls_found
          | join("|") }}))\b)((?:( -S |,)\w+)+)( -F auid>=1000 -F auid!=unset (?:-k
          |-F key=)\w+)
        line: \1\2\3{{ missing_syscalls | join("\3") }}\4
        backrefs: true
        state: present
        mode: g-rwx,o-rwx
      when: syscalls_found | length > 0 and missing_syscalls | length > 0

    - name: Add the audit rule to {{ audit_file }}
      ansible.builtin.lineinfile:
        path: '{{ audit_file }}'
        line: -a always,exit -F arch=b32 -S {{ syscalls | join(',') }} -F auid>=1000
          -F auid!=unset -F key=perm_mod
        create: true
        mode: g-rwx,o-rwx
        state: present
      when: syscalls_found | length == 0

    - name: Declare list of syscalls
      ansible.builtin.set_fact:
        syscalls:
        - fsetxattr
        syscall_grouping:
        - fremovexattr
        - lremovexattr
        - removexattr
        - fsetxattr
        - lsetxattr
        - setxattr

    - name: Check existence of fsetxattr in /etc/audit/rules.d/
      ansible.builtin.find:
        paths: /etc/audit/rules.d
        contains: -a always,exit -F arch=b32(( -S |,)\w+)*(( -S |,){{ item }})+((
          -S |,)\w+)* -F auid=0 (-k\s+|-F\s+key=)\S+\s*$
        patterns: '*.rules'
      register: find_command
      loop: '{{ (syscall_grouping + syscalls) | unique }}'

    - name: Reset syscalls found per file
      ansible.builtin.set_fact:
        syscalls_per_file: {}
        found_paths_dict: {}

    - name: Declare syscalls found per file
      ansible.builtin.set_fact: syscalls_per_file="{{ syscalls_per_file | combine(
        {item.files[0].path :[item.item] + syscalls_per_file.get(item.files[0].path,
        []) } ) }}"
      loop: '{{ find_command.results | selectattr(''matched'') | list }}'

    - name: Declare files where syscalls were found
      ansible.builtin.set_fact: found_paths="{{ find_command.results | map(attribute='files')
        | flatten | map(attribute='path') | list }}"

    - name: Count occurrences of syscalls in paths
      ansible.builtin.set_fact: found_paths_dict="{{ found_paths_dict | combine({
        item:1+found_paths_dict.get(item, 0) }) }}"
      loop: '{{ find_command.results | map(attribute=''files'') | flatten | map(attribute=''path'')
        | list }}'

    - name: Get path with most syscalls
      ansible.builtin.set_fact: audit_file="{{ (found_paths_dict | dict2items() |
        sort(attribute='value') | last).key }}"
      when: found_paths | length >= 1

    - name: No file with syscall found, set path to /etc/audit/rules.d/perm_mod.rules
      ansible.builtin.set_fact: audit_file="/etc/audit/rules.d/perm_mod.rules"
      when: found_paths | length == 0

    - name: Declare found syscalls
      ansible.builtin.set_fact: syscalls_found="{{ find_command.results | selectattr('matched')
        | map(attribute='item') | list }}"

    - name: Declare missing syscalls
      ansible.builtin.set_fact: missing_syscalls="{{ syscalls | difference(syscalls_found)
        }}"

    - name: Replace the audit rule in {{ audit_file }}
      ansible.builtin.lineinfile:
        path: '{{ audit_file }}'
        regexp: (-a always,exit -F arch=b32)(?=.*(?:(?:-S |,)(?:{{ syscalls_per_file[audit_file]
          | join("|") }}))\b)((?:( -S |,)\w+)+)( -F auid=0 (?:-k |-F key=)\w+)
        line: \1\2\3{{ missing_syscalls | join("\3") }}\4
        backrefs: true
        state: present
        mode: g-rwx,o-rwx
      when: syscalls_found | length > 0 and missing_syscalls | length > 0

    - name: Add the audit rule to {{ audit_file }}
      ansible.builtin.lineinfile:
        path: '{{ audit_file }}'
        line: -a always,exit -F arch=b32 -S {{ syscalls | join(',') }} -F auid=0 -F
          key=perm_mod
        create: true
        mode: g-rwx,o-rwx
        state: present
      when: syscalls_found | length == 0

    - name: Declare list of syscalls
      ansible.builtin.set_fact:
        syscalls:
        - fsetxattr
        syscall_grouping:
        - fremovexattr
        - lremovexattr
        - removexattr
        - fsetxattr
        - lsetxattr
        - setxattr

    - name: Check existence of fsetxattr in /etc/audit/audit.rules
      ansible.builtin.find:
        paths: /etc/audit
        contains: -a always,exit -F arch=b32(( -S |,)\w+)*(( -S |,){{ item }})+((
          -S |,)\w+)* -F auid=0 (-k\s+|-F\s+key=)\S+\s*$
        patterns: audit.rules
      register: find_command
      loop: '{{ (syscall_grouping + syscalls) | unique }}'

    - name: Set path to /etc/audit/audit.rules
      ansible.builtin.set_fact: audit_file="/etc/audit/audit.rules"

    - name: Declare found syscalls
      ansible.builtin.set_fact: syscalls_found="{{ find_command.results | selectattr('matched')
        | map(attribute='item') | list }}"

    - name: Declare missing syscalls
      ansible.builtin.set_fact: missing_syscalls="{{ syscalls | difference(syscalls_found)
        }}"

    - name: Replace the audit rule in {{ audit_file }}
      ansible.builtin.lineinfile:
        path: '{{ audit_file }}'
        regexp: (-a always,exit -F arch=b32)(?=.*(?:(?:-S |,)(?:{{ syscalls_found
          | join("|") }}))\b)((?:( -S |,)\w+)+)( -F auid=0 (?:-k |-F key=)\w+)
        line: \1\2\3{{ missing_syscalls | join("\3") }}\4
        backrefs: true
        state: present
        mode: g-rwx,o-rwx
      when: syscalls_found | length > 0 and missing_syscalls | length > 0

    - name: Add the audit rule to {{ audit_file }}
      ansible.builtin.lineinfile:
        path: '{{ audit_file }}'
        line: -a always,exit -F arch=b32 -S {{ syscalls | join(',') }} -F auid=0 -F
          key=perm_mod
        create: true
        mode: g-rwx,o-rwx
        state: present
      when: syscalls_found | length == 0
    when:
    - '"audit" in ansible_facts.packages'
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - CJIS-5.4.1.1
    - DISA-STIG-OL09-00-000545
    - NIST-800-171-3.1.7
    - NIST-800-53-AU-12(c)
    - NIST-800-53-AU-2(d)
    - NIST-800-53-CM-6(a)
    - PCI-DSS-Req-10.5.5
    - PCI-DSSv4-10.3
    - PCI-DSSv4-10.3.4
    - audit_rules_dac_modification_fsetxattr
    - low_complexity
    - low_disruption
    - medium_severity
    - reboot_required
    - restrict_strategy

  - name: Perform remediation of Audit rules for fsetxattr for 64bit platform
    block:

    - name: Declare list of syscalls
      ansible.builtin.set_fact:
        syscalls:
        - fsetxattr
        syscall_grouping:
        - fremovexattr
        - lremovexattr
        - removexattr
        - fsetxattr
        - lsetxattr
        - setxattr

    - name: Check existence of fsetxattr in /etc/audit/rules.d/
      ansible.builtin.find:
        paths: /etc/audit/rules.d
        contains: -a always,exit -F arch=b64(( -S |,)\w+)*(( -S |,){{ item }})+((
          -S |,)\w+)* -F auid>=1000 -F auid!=unset (-k\s+|-F\s+key=)\S+\s*$
        patterns: '*.rules'
      register: find_command
      loop: '{{ (syscall_grouping + syscalls) | unique }}'

    - name: Reset syscalls found per file
      ansible.builtin.set_fact:
        syscalls_per_file: {}
        found_paths_dict: {}

    - name: Declare syscalls found per file
      ansible.builtin.set_fact: syscalls_per_file="{{ syscalls_per_file | combine(
        {item.files[0].path :[item.item] + syscalls_per_file.get(item.files[0].path,
        []) } ) }}"
      loop: '{{ find_command.results | selectattr(''matched'') | list }}'

    - name: Declare files where syscalls were found
      ansible.builtin.set_fact: found_paths="{{ find_command.results | map(attribute='files')
        | flatten | map(attribute='path') | list }}"

    - name: Count occurrences of syscalls in paths
      ansible.builtin.set_fact: found_paths_dict="{{ found_paths_dict | combine({
        item:1+found_paths_dict.get(item, 0) }) }}"
      loop: '{{ find_command.results | map(attribute=''files'') | flatten | map(attribute=''path'')
        | list }}'

    - name: Get path with most syscalls
      ansible.builtin.set_fact: audit_file="{{ (found_paths_dict | dict2items() |
        sort(attribute='value') | last).key }}"
      when: found_paths | length >= 1

    - name: No file with syscall found, set path to /etc/audit/rules.d/perm_mod.rules
      ansible.builtin.set_fact: audit_file="/etc/audit/rules.d/perm_mod.rules"
      when: found_paths | length == 0

    - name: Declare found syscalls
      ansible.builtin.set_fact: syscalls_found="{{ find_command.results | selectattr('matched')
        | map(attribute='item') | list }}"

    - name: Declare missing syscalls
      ansible.builtin.set_fact: missing_syscalls="{{ syscalls | difference(syscalls_found)
        }}"

    - name: Replace the audit rule in {{ audit_file }}
      ansible.builtin.lineinfile:
        path: '{{ audit_file }}'
        regexp: (-a always,exit -F arch=b64)(?=.*(?:(?:-S |,)(?:{{ syscalls_per_file[audit_file]
          | join("|") }}))\b)((?:( -S |,)\w+)+)( -F auid>=1000 -F auid!=unset (?:-k
          |-F key=)\w+)
        line: \1\2\3{{ missing_syscalls | join("\3") }}\4
        backrefs: true
        state: present
        mode: g-rwx,o-rwx
      when: syscalls_found | length > 0 and missing_syscalls | length > 0

    - name: Add the audit rule to {{ audit_file }}
      ansible.builtin.lineinfile:
        path: '{{ audit_file }}'
        line: -a always,exit -F arch=b64 -S {{ syscalls | join(',') }} -F auid>=1000
          -F auid!=unset -F key=perm_mod
        create: true
        mode: g-rwx,o-rwx
        state: present
      when: syscalls_found | length == 0

    - name: Declare list of syscalls
      ansible.builtin.set_fact:
        syscalls:
        - fsetxattr
        syscall_grouping:
        - fremovexattr
        - lremovexattr
        - removexattr
        - fsetxattr
        - lsetxattr
        - setxattr

    - name: Check existence of fsetxattr in /etc/audit/audit.rules
      ansible.builtin.find:
        paths: /etc/audit
        contains: -a always,exit -F arch=b64(( -S |,)\w+)*(( -S |,){{ item }})+((
          -S |,)\w+)* -F auid>=1000 -F auid!=unset (-k\s+|-F\s+key=)\S+\s*$
        patterns: audit.rules
      register: find_command
      loop: '{{ (syscall_grouping + syscalls) | unique }}'

    - name: Set path to /etc/audit/audit.rules
      ansible.builtin.set_fact: audit_file="/etc/audit/audit.rules"

    - name: Declare found syscalls
      ansible.builtin.set_fact: syscalls_found="{{ find_command.results | selectattr('matched')
        | map(attribute='item') | list }}"

    - name: Declare missing syscalls
      ansible.builtin.set_fact: missing_syscalls="{{ syscalls | difference(syscalls_found)
        }}"

    - name: Replace the audit rule in {{ audit_file }}
      ansible.builtin.lineinfile:
        path: '{{ audit_file }}'
        regexp: (-a always,exit -F arch=b64)(?=.*(?:(?:-S |,)(?:{{ syscalls_found
          | join("|") }}))\b)((?:( -S |,)\w+)+)( -F auid>=1000 -F auid!=unset (?:-k
          |-F key=)\w+)
        line: \1\2\3{{ missing_syscalls | join("\3") }}\4
        backrefs: true
        state: present
        mode: g-rwx,o-rwx
      when: syscalls_found | length > 0 and missing_syscalls | length > 0

    - name: Add the audit rule to {{ audit_file }}
      ansible.builtin.lineinfile:
        path: '{{ audit_file }}'
        line: -a always,exit -F arch=b64 -S {{ syscalls | join(',') }} -F auid>=1000
          -F auid!=unset -F key=perm_mod
        create: true
        mode: g-rwx,o-rwx
        state: present
      when: syscalls_found | length == 0

    - name: Declare list of syscalls
      ansible.builtin.set_fact:
        syscalls:
        - fsetxattr
        syscall_grouping:
        - fremovexattr
        - lremovexattr
        - removexattr
        - fsetxattr
        - lsetxattr
        - setxattr

    - name: Check existence of fsetxattr in /etc/audit/rules.d/
      ansible.builtin.find:
        paths: /etc/audit/rules.d
        contains: -a always,exit -F arch=b64(( -S |,)\w+)*(( -S |,){{ item }})+((
          -S |,)\w+)* -F auid=0 (-k\s+|-F\s+key=)\S+\s*$
        patterns: '*.rules'
      register: find_command
      loop: '{{ (syscall_grouping + syscalls) | unique }}'

    - name: Reset syscalls found per file
      ansible.builtin.set_fact:
        syscalls_per_file: {}
        found_paths_dict: {}

    - name: Declare syscalls found per file
      ansible.builtin.set_fact: syscalls_per_file="{{ syscalls_per_file | combine(
        {item.files[0].path :[item.item] + syscalls_per_file.get(item.files[0].path,
        []) } ) }}"
      loop: '{{ find_command.results | selectattr(''matched'') | list }}'

    - name: Declare files where syscalls were found
      ansible.builtin.set_fact: found_paths="{{ find_command.results | map(attribute='files')
        | flatten | map(attribute='path') | list }}"

    - name: Count occurrences of syscalls in paths
      ansible.builtin.set_fact: found_paths_dict="{{ found_paths_dict | combine({
        item:1+found_paths_dict.get(item, 0) }) }}"
      loop: '{{ find_command.results | map(attribute=''files'') | flatten | map(attribute=''path'')
        | list }}'

    - name: Get path with most syscalls
      ansible.builtin.set_fact: audit_file="{{ (found_paths_dict | dict2items() |
        sort(attribute='value') | last).key }}"
      when: found_paths | length >= 1

    - name: No file with syscall found, set path to /etc/audit/rules.d/perm_mod.rules
      ansible.builtin.set_fact: audit_file="/etc/audit/rules.d/perm_mod.rules"
      when: found_paths | length == 0

    - name: Declare found syscalls
      ansible.builtin.set_fact: syscalls_found="{{ find_command.results | selectattr('matched')
        | map(attribute='item') | list }}"

    - name: Declare missing syscalls
      ansible.builtin.set_fact: missing_syscalls="{{ syscalls | difference(syscalls_found)
        }}"

    - name: Replace the audit rule in {{ audit_file }}
      ansible.builtin.lineinfile:
        path: '{{ audit_file }}'
        regexp: (-a always,exit -F arch=b64)(?=.*(?:(?:-S |,)(?:{{ syscalls_per_file[audit_file]
          | join("|") }}))\b)((?:( -S |,)\w+)+)( -F auid=0 (?:-k |-F key=)\w+)
        line: \1\2\3{{ missing_syscalls | join("\3") }}\4
        backrefs: true
        state: present
        mode: g-rwx,o-rwx
      when: syscalls_found | length > 0 and missing_syscalls | length > 0

    - name: Add the audit rule to {{ audit_file }}
      ansible.builtin.lineinfile:
        path: '{{ audit_file }}'
        line: -a always,exit -F arch=b64 -S {{ syscalls | join(',') }} -F auid=0 -F
          key=perm_mod
        create: true
        mode: g-rwx,o-rwx
        state: present
      when: syscalls_found | length == 0

    - name: Declare list of syscalls
      ansible.builtin.set_fact:
        syscalls:
        - fsetxattr
        syscall_grouping:
        - fremovexattr
        - lremovexattr
        - removexattr
        - fsetxattr
        - lsetxattr
        - setxattr

    - name: Check existence of fsetxattr in /etc/audit/audit.rules
      ansible.builtin.find:
        paths: /etc/audit
        contains: -a always,exit -F arch=b64(( -S |,)\w+)*(( -S |,){{ item }})+((
          -S |,)\w+)* -F auid=0 (-k\s+|-F\s+key=)\S+\s*$
        patterns: audit.rules
      register: find_command
      loop: '{{ (syscall_grouping + syscalls) | unique }}'

    - name: Set path to /etc/audit/audit.rules
      ansible.builtin.set_fact: audit_file="/etc/audit/audit.rules"

    - name: Declare found syscalls
      ansible.builtin.set_fact: syscalls_found="{{ find_command.results | selectattr('matched')
        | map(attribute='item') | list }}"

    - name: Declare missing syscalls
      ansible.builtin.set_fact: missing_syscalls="{{ syscalls | difference(syscalls_found)
        }}"

    - name: Replace the audit rule in {{ audit_file }}
      ansible.builtin.lineinfile:
        path: '{{ audit_file }}'
        regexp: (-a always,exit -F arch=b64)(?=.*(?:(?:-S |,)(?:{{ syscalls_found
          | join("|") }}))\b)((?:( -S |,)\w+)+)( -F auid=0 (?:-k |-F key=)\w+)
        line: \1\2\3{{ missing_syscalls | join("\3") }}\4
        backrefs: true
        state: present
        mode: g-rwx,o-rwx
      when: syscalls_found | length > 0 and missing_syscalls | length > 0

    - name: Add the audit rule to {{ audit_file }}
      ansible.builtin.lineinfile:
        path: '{{ audit_file }}'
        line: -a always,exit -F arch=b64 -S {{ syscalls | join(',') }} -F auid=0 -F
          key=perm_mod
        create: true
        mode: g-rwx,o-rwx
        state: present
      when: syscalls_found | length == 0
    when:
    - '"audit" in ansible_facts.packages'
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - audit_arch == "b64"
    tags:
    - CJIS-5.4.1.1
    - DISA-STIG-OL09-00-000545
    - NIST-800-171-3.1.7
    - NIST-800-53-AU-12(c)
    - NIST-800-53-AU-2(d)
    - NIST-800-53-CM-6(a)
    - PCI-DSS-Req-10.5.5
    - PCI-DSSv4-10.3
    - PCI-DSSv4-10.3.4
    - audit_rules_dac_modification_fsetxattr
    - low_complexity
    - low_disruption
    - medium_severity
    - reboot_required
    - restrict_strategy

  - name: Set architecture for audit lchown tasks
    ansible.builtin.set_fact:
      audit_arch: b64
    when:
    - '"audit" in ansible_facts.packages'
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - not ( ansible_architecture == "aarch64" )
    - ansible_architecture == "aarch64" or ansible_architecture == "ppc64" or ansible_architecture
      == "ppc64le" or ansible_architecture == "s390x" or ansible_architecture == "x86_64"
    tags:
    - CJIS-5.4.1.1
    - DISA-STIG-OL09-00-000645
    - NIST-800-171-3.1.7
    - NIST-800-53-AU-12(c)
    - NIST-800-53-AU-2(d)
    - NIST-800-53-CM-6(a)
    - PCI-DSS-Req-10.5.5
    - PCI-DSSv4-10.3
    - PCI-DSSv4-10.3.4
    - audit_rules_dac_modification_lchown
    - low_complexity
    - low_disruption
    - medium_severity
    - reboot_required
    - restrict_strategy

  - name: Perform remediation of Audit rules for lchown for 32bit platform
    block:

    - name: Declare list of syscalls
      ansible.builtin.set_fact:
        syscalls:
        - lchown
        syscall_grouping:
        - chown
        - fchown
        - fchownat
        - lchown

    - name: Check existence of lchown in /etc/audit/rules.d/
      ansible.builtin.find:
        paths: /etc/audit/rules.d
        contains: -a always,exit -F arch=b32(( -S |,)\w+)*(( -S |,){{ item }})+((
          -S |,)\w+)* -F auid>=1000 -F auid!=unset (-k\s+|-F\s+key=)\S+\s*$
        patterns: '*.rules'
      register: find_command
      loop: '{{ (syscall_grouping + syscalls) | unique }}'

    - name: Reset syscalls found per file
      ansible.builtin.set_fact:
        syscalls_per_file: {}
        found_paths_dict: {}

    - name: Declare syscalls found per file
      ansible.builtin.set_fact: syscalls_per_file="{{ syscalls_per_file | combine(
        {item.files[0].path :[item.item] + syscalls_per_file.get(item.files[0].path,
        []) } ) }}"
      loop: '{{ find_command.results | selectattr(''matched'') | list }}'

    - name: Declare files where syscalls were found
      ansible.builtin.set_fact: found_paths="{{ find_command.results | map(attribute='files')
        | flatten | map(attribute='path') | list }}"

    - name: Count occurrences of syscalls in paths
      ansible.builtin.set_fact: found_paths_dict="{{ found_paths_dict | combine({
        item:1+found_paths_dict.get(item, 0) }) }}"
      loop: '{{ find_command.results | map(attribute=''files'') | flatten | map(attribute=''path'')
        | list }}'

    - name: Get path with most syscalls
      ansible.builtin.set_fact: audit_file="{{ (found_paths_dict | dict2items() |
        sort(attribute='value') | last).key }}"
      when: found_paths | length >= 1

    - name: No file with syscall found, set path to /etc/audit/rules.d/perm_mod.rules
      ansible.builtin.set_fact: audit_file="/etc/audit/rules.d/perm_mod.rules"
      when: found_paths | length == 0

    - name: Declare found syscalls
      ansible.builtin.set_fact: syscalls_found="{{ find_command.results | selectattr('matched')
        | map(attribute='item') | list }}"

    - name: Declare missing syscalls
      ansible.builtin.set_fact: missing_syscalls="{{ syscalls | difference(syscalls_found)
        }}"

    - name: Replace the audit rule in {{ audit_file }}
      ansible.builtin.lineinfile:
        path: '{{ audit_file }}'
        regexp: (-a always,exit -F arch=b32)(?=.*(?:(?:-S |,)(?:{{ syscalls_per_file[audit_file]
          | join("|") }}))\b)((?:( -S |,)\w+)+)( -F auid>=1000 -F auid!=unset (?:-k
          |-F key=)\w+)
        line: \1\2\3{{ missing_syscalls | join("\3") }}\4
        backrefs: true
        state: present
        mode: g-rwx,o-rwx
      when: syscalls_found | length > 0 and missing_syscalls | length > 0

    - name: Add the audit rule to {{ audit_file }}
      ansible.builtin.lineinfile:
        path: '{{ audit_file }}'
        line: -a always,exit -F arch=b32 -S {{ syscalls | join(',') }} -F auid>=1000
          -F auid!=unset -F key=perm_mod
        create: true
        mode: g-rwx,o-rwx
        state: present
      when: syscalls_found | length == 0

    - name: Declare list of syscalls
      ansible.builtin.set_fact:
        syscalls:
        - lchown
        syscall_grouping:
        - chown
        - fchown
        - fchownat
        - lchown

    - name: Check existence of lchown in /etc/audit/audit.rules
      ansible.builtin.find:
        paths: /etc/audit
        contains: -a always,exit -F arch=b32(( -S |,)\w+)*(( -S |,){{ item }})+((
          -S |,)\w+)* -F auid>=1000 -F auid!=unset (-k\s+|-F\s+key=)\S+\s*$
        patterns: audit.rules
      register: find_command
      loop: '{{ (syscall_grouping + syscalls) | unique }}'

    - name: Set path to /etc/audit/audit.rules
      ansible.builtin.set_fact: audit_file="/etc/audit/audit.rules"

    - name: Declare found syscalls
      ansible.builtin.set_fact: syscalls_found="{{ find_command.results | selectattr('matched')
        | map(attribute='item') | list }}"

    - name: Declare missing syscalls
      ansible.builtin.set_fact: missing_syscalls="{{ syscalls | difference(syscalls_found)
        }}"

    - name: Replace the audit rule in {{ audit_file }}
      ansible.builtin.lineinfile:
        path: '{{ audit_file }}'
        regexp: (-a always,exit -F arch=b32)(?=.*(?:(?:-S |,)(?:{{ syscalls_found
          | join("|") }}))\b)((?:( -S |,)\w+)+)( -F auid>=1000 -F auid!=unset (?:-k
          |-F key=)\w+)
        line: \1\2\3{{ missing_syscalls | join("\3") }}\4
        backrefs: true
        state: present
        mode: g-rwx,o-rwx
      when: syscalls_found | length > 0 and missing_syscalls | length > 0

    - name: Add the audit rule to {{ audit_file }}
      ansible.builtin.lineinfile:
        path: '{{ audit_file }}'
        line: -a always,exit -F arch=b32 -S {{ syscalls | join(',') }} -F auid>=1000
          -F auid!=unset -F key=perm_mod
        create: true
        mode: g-rwx,o-rwx
        state: present
      when: syscalls_found | length == 0
    when:
    - '"audit" in ansible_facts.packages'
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - not ( ansible_architecture == "aarch64" )
    tags:
    - CJIS-5.4.1.1
    - DISA-STIG-OL09-00-000645
    - NIST-800-171-3.1.7
    - NIST-800-53-AU-12(c)
    - NIST-800-53-AU-2(d)
    - NIST-800-53-CM-6(a)
    - PCI-DSS-Req-10.5.5
    - PCI-DSSv4-10.3
    - PCI-DSSv4-10.3.4
    - audit_rules_dac_modification_lchown
    - low_complexity
    - low_disruption
    - medium_severity
    - reboot_required
    - restrict_strategy

  - name: Perform remediation of Audit rules for lchown for 64bit platform
    block:

    - name: Declare list of syscalls
      ansible.builtin.set_fact:
        syscalls:
        - lchown
        syscall_grouping:
        - chown
        - fchown
        - fchownat
        - lchown

    - name: Check existence of lchown in /etc/audit/rules.d/
      ansible.builtin.find:
        paths: /etc/audit/rules.d
        contains: -a always,exit -F arch=b64(( -S |,)\w+)*(( -S |,){{ item }})+((
          -S |,)\w+)* -F auid>=1000 -F auid!=unset (-k\s+|-F\s+key=)\S+\s*$
        patterns: '*.rules'
      register: find_command
      loop: '{{ (syscall_grouping + syscalls) | unique }}'

    - name: Reset syscalls found per file
      ansible.builtin.set_fact:
        syscalls_per_file: {}
        found_paths_dict: {}

    - name: Declare syscalls found per file
      ansible.builtin.set_fact: syscalls_per_file="{{ syscalls_per_file | combine(
        {item.files[0].path :[item.item] + syscalls_per_file.get(item.files[0].path,
        []) } ) }}"
      loop: '{{ find_command.results | selectattr(''matched'') | list }}'

    - name: Declare files where syscalls were found
      ansible.builtin.set_fact: found_paths="{{ find_command.results | map(attribute='files')
        | flatten | map(attribute='path') | list }}"

    - name: Count occurrences of syscalls in paths
      ansible.builtin.set_fact: found_paths_dict="{{ found_paths_dict | combine({
        item:1+found_paths_dict.get(item, 0) }) }}"
      loop: '{{ find_command.results | map(attribute=''files'') | flatten | map(attribute=''path'')
        | list }}'

    - name: Get path with most syscalls
      ansible.builtin.set_fact: audit_file="{{ (found_paths_dict | dict2items() |
        sort(attribute='value') | last).key }}"
      when: found_paths | length >= 1

    - name: No file with syscall found, set path to /etc/audit/rules.d/perm_mod.rules
      ansible.builtin.set_fact: audit_file="/etc/audit/rules.d/perm_mod.rules"
      when: found_paths | length == 0

    - name: Declare found syscalls
      ansible.builtin.set_fact: syscalls_found="{{ find_command.results | selectattr('matched')
        | map(attribute='item') | list }}"

    - name: Declare missing syscalls
      ansible.builtin.set_fact: missing_syscalls="{{ syscalls | difference(syscalls_found)
        }}"

    - name: Replace the audit rule in {{ audit_file }}
      ansible.builtin.lineinfile:
        path: '{{ audit_file }}'
        regexp: (-a always,exit -F arch=b64)(?=.*(?:(?:-S |,)(?:{{ syscalls_per_file[audit_file]
          | join("|") }}))\b)((?:( -S |,)\w+)+)( -F auid>=1000 -F auid!=unset (?:-k
          |-F key=)\w+)
        line: \1\2\3{{ missing_syscalls | join("\3") }}\4
        backrefs: true
        state: present
        mode: g-rwx,o-rwx
      when: syscalls_found | length > 0 and missing_syscalls | length > 0

    - name: Add the audit rule to {{ audit_file }}
      ansible.builtin.lineinfile:
        path: '{{ audit_file }}'
        line: -a always,exit -F arch=b64 -S {{ syscalls | join(',') }} -F auid>=1000
          -F auid!=unset -F key=perm_mod
        create: true
        mode: g-rwx,o-rwx
        state: present
      when: syscalls_found | length == 0

    - name: Declare list of syscalls
      ansible.builtin.set_fact:
        syscalls:
        - lchown
        syscall_grouping:
        - chown
        - fchown
        - fchownat
        - lchown

    - name: Check existence of lchown in /etc/audit/audit.rules
      ansible.builtin.find:
        paths: /etc/audit
        contains: -a always,exit -F arch=b64(( -S |,)\w+)*(( -S |,){{ item }})+((
          -S |,)\w+)* -F auid>=1000 -F auid!=unset (-k\s+|-F\s+key=)\S+\s*$
        patterns: audit.rules
      register: find_command
      loop: '{{ (syscall_grouping + syscalls) | unique }}'

    - name: Set path to /etc/audit/audit.rules
      ansible.builtin.set_fact: audit_file="/etc/audit/audit.rules"

    - name: Declare found syscalls
      ansible.builtin.set_fact: syscalls_found="{{ find_command.results | selectattr('matched')
        | map(attribute='item') | list }}"

    - name: Declare missing syscalls
      ansible.builtin.set_fact: missing_syscalls="{{ syscalls | difference(syscalls_found)
        }}"

    - name: Replace the audit rule in {{ audit_file }}
      ansible.builtin.lineinfile:
        path: '{{ audit_file }}'
        regexp: (-a always,exit -F arch=b64)(?=.*(?:(?:-S |,)(?:{{ syscalls_found
          | join("|") }}))\b)((?:( -S |,)\w+)+)( -F auid>=1000 -F auid!=unset (?:-k
          |-F key=)\w+)
        line: \1\2\3{{ missing_syscalls | join("\3") }}\4
        backrefs: true
        state: present
        mode: g-rwx,o-rwx
      when: syscalls_found | length > 0 and missing_syscalls | length > 0

    - name: Add the audit rule to {{ audit_file }}
      ansible.builtin.lineinfile:
        path: '{{ audit_file }}'
        line: -a always,exit -F arch=b64 -S {{ syscalls | join(',') }} -F auid>=1000
          -F auid!=unset -F key=perm_mod
        create: true
        mode: g-rwx,o-rwx
        state: present
      when: syscalls_found | length == 0
    when:
    - '"audit" in ansible_facts.packages'
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - not ( ansible_architecture == "aarch64" )
    - audit_arch == "b64"
    tags:
    - CJIS-5.4.1.1
    - DISA-STIG-OL09-00-000645
    - NIST-800-171-3.1.7
    - NIST-800-53-AU-12(c)
    - NIST-800-53-AU-2(d)
    - NIST-800-53-CM-6(a)
    - PCI-DSS-Req-10.5.5
    - PCI-DSSv4-10.3
    - PCI-DSSv4-10.3.4
    - audit_rules_dac_modification_lchown
    - low_complexity
    - low_disruption
    - medium_severity
    - reboot_required
    - restrict_strategy

  - name: Set architecture for audit lremovexattr tasks
    ansible.builtin.set_fact:
      audit_arch: b64
    when:
    - '"audit" in ansible_facts.packages'
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - ansible_architecture == "aarch64" or ansible_architecture == "ppc64" or ansible_architecture
      == "ppc64le" or ansible_architecture == "s390x" or ansible_architecture == "x86_64"
    tags:
    - CJIS-5.4.1.1
    - DISA-STIG-OL09-00-000545
    - NIST-800-171-3.1.7
    - NIST-800-53-AU-12(c)
    - NIST-800-53-AU-2(d)
    - NIST-800-53-CM-6(a)
    - PCI-DSS-Req-10.5.5
    - PCI-DSSv4-10.3
    - PCI-DSSv4-10.3.4
    - audit_rules_dac_modification_lremovexattr
    - low_complexity
    - low_disruption
    - medium_severity
    - reboot_required
    - restrict_strategy

  - name: Perform remediation of Audit rules for lremovexattr for 32bit platform
    block:

    - name: Declare list of syscalls
      ansible.builtin.set_fact:
        syscalls:
        - lremovexattr
        syscall_grouping:
        - fremovexattr
        - lremovexattr
        - removexattr
        - fsetxattr
        - lsetxattr
        - setxattr

    - name: Check existence of lremovexattr in /etc/audit/rules.d/
      ansible.builtin.find:
        paths: /etc/audit/rules.d
        contains: -a always,exit -F arch=b32(( -S |,)\w+)*(( -S |,){{ item }})+((
          -S |,)\w+)* -F auid>=1000 -F auid!=unset (-k\s+|-F\s+key=)\S+\s*$
        patterns: '*.rules'
      register: find_command
      loop: '{{ (syscall_grouping + syscalls) | unique }}'

    - name: Reset syscalls found per file
      ansible.builtin.set_fact:
        syscalls_per_file: {}
        found_paths_dict: {}

    - name: Declare syscalls found per file
      ansible.builtin.set_fact: syscalls_per_file="{{ syscalls_per_file | combine(
        {item.files[0].path :[item.item] + syscalls_per_file.get(item.files[0].path,
        []) } ) }}"
      loop: '{{ find_command.results | selectattr(''matched'') | list }}'

    - name: Declare files where syscalls were found
      ansible.builtin.set_fact: found_paths="{{ find_command.results | map(attribute='files')
        | flatten | map(attribute='path') | list }}"

    - name: Count occurrences of syscalls in paths
      ansible.builtin.set_fact: found_paths_dict="{{ found_paths_dict | combine({
        item:1+found_paths_dict.get(item, 0) }) }}"
      loop: '{{ find_command.results | map(attribute=''files'') | flatten | map(attribute=''path'')
        | list }}'

    - name: Get path with most syscalls
      ansible.builtin.set_fact: audit_file="{{ (found_paths_dict | dict2items() |
        sort(attribute='value') | last).key }}"
      when: found_paths | length >= 1

    - name: No file with syscall found, set path to /etc/audit/rules.d/perm_mod.rules
      ansible.builtin.set_fact: audit_file="/etc/audit/rules.d/perm_mod.rules"
      when: found_paths | length == 0

    - name: Declare found syscalls
      ansible.builtin.set_fact: syscalls_found="{{ find_command.results | selectattr('matched')
        | map(attribute='item') | list }}"

    - name: Declare missing syscalls
      ansible.builtin.set_fact: missing_syscalls="{{ syscalls | difference(syscalls_found)
        }}"

    - name: Replace the audit rule in {{ audit_file }}
      ansible.builtin.lineinfile:
        path: '{{ audit_file }}'
        regexp: (-a always,exit -F arch=b32)(?=.*(?:(?:-S |,)(?:{{ syscalls_per_file[audit_file]
          | join("|") }}))\b)((?:( -S |,)\w+)+)( -F auid>=1000 -F auid!=unset (?:-k
          |-F key=)\w+)
        line: \1\2\3{{ missing_syscalls | join("\3") }}\4
        backrefs: true
        state: present
        mode: g-rwx,o-rwx
      when: syscalls_found | length > 0 and missing_syscalls | length > 0

    - name: Add the audit rule to {{ audit_file }}
      ansible.builtin.lineinfile:
        path: '{{ audit_file }}'
        line: -a always,exit -F arch=b32 -S {{ syscalls | join(',') }} -F auid>=1000
          -F auid!=unset -F key=perm_mod
        create: true
        mode: g-rwx,o-rwx
        state: present
      when: syscalls_found | length == 0

    - name: Declare list of syscalls
      ansible.builtin.set_fact:
        syscalls:
        - lremovexattr
        syscall_grouping:
        - fremovexattr
        - lremovexattr
        - removexattr
        - fsetxattr
        - lsetxattr
        - setxattr

    - name: Check existence of lremovexattr in /etc/audit/audit.rules
      ansible.builtin.find:
        paths: /etc/audit
        contains: -a always,exit -F arch=b32(( -S |,)\w+)*(( -S |,){{ item }})+((
          -S |,)\w+)* -F auid>=1000 -F auid!=unset (-k\s+|-F\s+key=)\S+\s*$
        patterns: audit.rules
      register: find_command
      loop: '{{ (syscall_grouping + syscalls) | unique }}'

    - name: Set path to /etc/audit/audit.rules
      ansible.builtin.set_fact: audit_file="/etc/audit/audit.rules"

    - name: Declare found syscalls
      ansible.builtin.set_fact: syscalls_found="{{ find_command.results | selectattr('matched')
        | map(attribute='item') | list }}"

    - name: Declare missing syscalls
      ansible.builtin.set_fact: missing_syscalls="{{ syscalls | difference(syscalls_found)
        }}"

    - name: Replace the audit rule in {{ audit_file }}
      ansible.builtin.lineinfile:
        path: '{{ audit_file }}'
        regexp: (-a always,exit -F arch=b32)(?=.*(?:(?:-S |,)(?:{{ syscalls_found
          | join("|") }}))\b)((?:( -S |,)\w+)+)( -F auid>=1000 -F auid!=unset (?:-k
          |-F key=)\w+)
        line: \1\2\3{{ missing_syscalls | join("\3") }}\4
        backrefs: true
        state: present
        mode: g-rwx,o-rwx
      when: syscalls_found | length > 0 and missing_syscalls | length > 0

    - name: Add the audit rule to {{ audit_file }}
      ansible.builtin.lineinfile:
        path: '{{ audit_file }}'
        line: -a always,exit -F arch=b32 -S {{ syscalls | join(',') }} -F auid>=1000
          -F auid!=unset -F key=perm_mod
        create: true
        mode: g-rwx,o-rwx
        state: present
      when: syscalls_found | length == 0

    - name: Declare list of syscalls
      ansible.builtin.set_fact:
        syscalls:
        - lremovexattr
        syscall_grouping:
        - fremovexattr
        - lremovexattr
        - removexattr
        - fsetxattr
        - lsetxattr
        - setxattr

    - name: Check existence of lremovexattr in /etc/audit/rules.d/
      ansible.builtin.find:
        paths: /etc/audit/rules.d
        contains: -a always,exit -F arch=b32(( -S |,)\w+)*(( -S |,){{ item }})+((
          -S |,)\w+)* -F auid=0 (-k\s+|-F\s+key=)\S+\s*$
        patterns: '*.rules'
      register: find_command
      loop: '{{ (syscall_grouping + syscalls) | unique }}'

    - name: Reset syscalls found per file
      ansible.builtin.set_fact:
        syscalls_per_file: {}
        found_paths_dict: {}

    - name: Declare syscalls found per file
      ansible.builtin.set_fact: syscalls_per_file="{{ syscalls_per_file | combine(
        {item.files[0].path :[item.item] + syscalls_per_file.get(item.files[0].path,
        []) } ) }}"
      loop: '{{ find_command.results | selectattr(''matched'') | list }}'

    - name: Declare files where syscalls were found
      ansible.builtin.set_fact: found_paths="{{ find_command.results | map(attribute='files')
        | flatten | map(attribute='path') | list }}"

    - name: Count occurrences of syscalls in paths
      ansible.builtin.set_fact: found_paths_dict="{{ found_paths_dict | combine({
        item:1+found_paths_dict.get(item, 0) }) }}"
      loop: '{{ find_command.results | map(attribute=''files'') | flatten | map(attribute=''path'')
        | list }}'

    - name: Get path with most syscalls
      ansible.builtin.set_fact: audit_file="{{ (found_paths_dict | dict2items() |
        sort(attribute='value') | last).key }}"
      when: found_paths | length >= 1

    - name: No file with syscall found, set path to /etc/audit/rules.d/perm_mod.rules
      ansible.builtin.set_fact: audit_file="/etc/audit/rules.d/perm_mod.rules"
      when: found_paths | length == 0

    - name: Declare found syscalls
      ansible.builtin.set_fact: syscalls_found="{{ find_command.results | selectattr('matched')
        | map(attribute='item') | list }}"

    - name: Declare missing syscalls
      ansible.builtin.set_fact: missing_syscalls="{{ syscalls | difference(syscalls_found)
        }}"

    - name: Replace the audit rule in {{ audit_file }}
      ansible.builtin.lineinfile:
        path: '{{ audit_file }}'
        regexp: (-a always,exit -F arch=b32)(?=.*(?:(?:-S |,)(?:{{ syscalls_per_file[audit_file]
          | join("|") }}))\b)((?:( -S |,)\w+)+)( -F auid=0 (?:-k |-F key=)\w+)
        line: \1\2\3{{ missing_syscalls | join("\3") }}\4
        backrefs: true
        state: present
        mode: g-rwx,o-rwx
      when: syscalls_found | length > 0 and missing_syscalls | length > 0

    - name: Add the audit rule to {{ audit_file }}
      ansible.builtin.lineinfile:
        path: '{{ audit_file }}'
        line: -a always,exit -F arch=b32 -S {{ syscalls | join(',') }} -F auid=0 -F
          key=perm_mod
        create: true
        mode: g-rwx,o-rwx
        state: present
      when: syscalls_found | length == 0

    - name: Declare list of syscalls
      ansible.builtin.set_fact:
        syscalls:
        - lremovexattr
        syscall_grouping:
        - fremovexattr
        - lremovexattr
        - removexattr
        - fsetxattr
        - lsetxattr
        - setxattr

    - name: Check existence of lremovexattr in /etc/audit/audit.rules
      ansible.builtin.find:
        paths: /etc/audit
        contains: -a always,exit -F arch=b32(( -S |,)\w+)*(( -S |,){{ item }})+((
          -S |,)\w+)* -F auid=0 (-k\s+|-F\s+key=)\S+\s*$
        patterns: audit.rules
      register: find_command
      loop: '{{ (syscall_grouping + syscalls) | unique }}'

    - name: Set path to /etc/audit/audit.rules
      ansible.builtin.set_fact: audit_file="/etc/audit/audit.rules"

    - name: Declare found syscalls
      ansible.builtin.set_fact: syscalls_found="{{ find_command.results | selectattr('matched')
        | map(attribute='item') | list }}"

    - name: Declare missing syscalls
      ansible.builtin.set_fact: missing_syscalls="{{ syscalls | difference(syscalls_found)
        }}"

    - name: Replace the audit rule in {{ audit_file }}
      ansible.builtin.lineinfile:
        path: '{{ audit_file }}'
        regexp: (-a always,exit -F arch=b32)(?=.*(?:(?:-S |,)(?:{{ syscalls_found
          | join("|") }}))\b)((?:( -S |,)\w+)+)( -F auid=0 (?:-k |-F key=)\w+)
        line: \1\2\3{{ missing_syscalls | join("\3") }}\4
        backrefs: true
        state: present
        mode: g-rwx,o-rwx
      when: syscalls_found | length > 0 and missing_syscalls | length > 0

    - name: Add the audit rule to {{ audit_file }}
      ansible.builtin.lineinfile:
        path: '{{ audit_file }}'
        line: -a always,exit -F arch=b32 -S {{ syscalls | join(',') }} -F auid=0 -F
          key=perm_mod
        create: true
        mode: g-rwx,o-rwx
        state: present
      when: syscalls_found | length == 0
    when:
    - '"audit" in ansible_facts.packages'
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - CJIS-5.4.1.1
    - DISA-STIG-OL09-00-000545
    - NIST-800-171-3.1.7
    - NIST-800-53-AU-12(c)
    - NIST-800-53-AU-2(d)
    - NIST-800-53-CM-6(a)
    - PCI-DSS-Req-10.5.5
    - PCI-DSSv4-10.3
    - PCI-DSSv4-10.3.4
    - audit_rules_dac_modification_lremovexattr
    - low_complexity
    - low_disruption
    - medium_severity
    - reboot_required
    - restrict_strategy

  - name: Perform remediation of Audit rules for lremovexattr for 64bit platform
    block:

    - name: Declare list of syscalls
      ansible.builtin.set_fact:
        syscalls:
        - lremovexattr
        syscall_grouping:
        - fremovexattr
        - lremovexattr
        - removexattr
        - fsetxattr
        - lsetxattr
        - setxattr

    - name: Check existence of lremovexattr in /etc/audit/rules.d/
      ansible.builtin.find:
        paths: /etc/audit/rules.d
        contains: -a always,exit -F arch=b64(( -S |,)\w+)*(( -S |,){{ item }})+((
          -S |,)\w+)* -F auid>=1000 -F auid!=unset (-k\s+|-F\s+key=)\S+\s*$
        patterns: '*.rules'
      register: find_command
      loop: '{{ (syscall_grouping + syscalls) | unique }}'

    - name: Reset syscalls found per file
      ansible.builtin.set_fact:
        syscalls_per_file: {}
        found_paths_dict: {}

    - name: Declare syscalls found per file
      ansible.builtin.set_fact: syscalls_per_file="{{ syscalls_per_file | combine(
        {item.files[0].path :[item.item] + syscalls_per_file.get(item.files[0].path,
        []) } ) }}"
      loop: '{{ find_command.results | selectattr(''matched'') | list }}'

    - name: Declare files where syscalls were found
      ansible.builtin.set_fact: found_paths="{{ find_command.results | map(attribute='files')
        | flatten | map(attribute='path') | list }}"

    - name: Count occurrences of syscalls in paths
      ansible.builtin.set_fact: found_paths_dict="{{ found_paths_dict | combine({
        item:1+found_paths_dict.get(item, 0) }) }}"
      loop: '{{ find_command.results | map(attribute=''files'') | flatten | map(attribute=''path'')
        | list }}'

    - name: Get path with most syscalls
      ansible.builtin.set_fact: audit_file="{{ (found_paths_dict | dict2items() |
        sort(attribute='value') | last).key }}"
      when: found_paths | length >= 1

    - name: No file with syscall found, set path to /etc/audit/rules.d/perm_mod.rules
      ansible.builtin.set_fact: audit_file="/etc/audit/rules.d/perm_mod.rules"
      when: found_paths | length == 0

    - name: Declare found syscalls
      ansible.builtin.set_fact: syscalls_found="{{ find_command.results | selectattr('matched')
        | map(attribute='item') | list }}"

    - name: Declare missing syscalls
      ansible.builtin.set_fact: missing_syscalls="{{ syscalls | difference(syscalls_found)
        }}"

    - name: Replace the audit rule in {{ audit_file }}
      ansible.builtin.lineinfile:
        path: '{{ audit_file }}'
        regexp: (-a always,exit -F arch=b64)(?=.*(?:(?:-S |,)(?:{{ syscalls_per_file[audit_file]
          | join("|") }}))\b)((?:( -S |,)\w+)+)( -F auid>=1000 -F auid!=unset (?:-k
          |-F key=)\w+)
        line: \1\2\3{{ missing_syscalls | join("\3") }}\4
        backrefs: true
        state: present
        mode: g-rwx,o-rwx
      when: syscalls_found | length > 0 and missing_syscalls | length > 0

    - name: Add the audit rule to {{ audit_file }}
      ansible.builtin.lineinfile:
        path: '{{ audit_file }}'
        line: -a always,exit -F arch=b64 -S {{ syscalls | join(',') }} -F auid>=1000
          -F auid!=unset -F key=perm_mod
        create: true
        mode: g-rwx,o-rwx
        state: present
      when: syscalls_found | length == 0

    - name: Declare list of syscalls
      ansible.builtin.set_fact:
        syscalls:
        - lremovexattr
        syscall_grouping:
        - fremovexattr
        - lremovexattr
        - removexattr
        - fsetxattr
        - lsetxattr
        - setxattr

    - name: Check existence of lremovexattr in /etc/audit/audit.rules
      ansible.builtin.find:
        paths: /etc/audit
        contains: -a always,exit -F arch=b64(( -S |,)\w+)*(( -S |,){{ item }})+((
          -S |,)\w+)* -F auid>=1000 -F auid!=unset (-k\s+|-F\s+key=)\S+\s*$
        patterns: audit.rules
      register: find_command
      loop: '{{ (syscall_grouping + syscalls) | unique }}'

    - name: Set path to /etc/audit/audit.rules
      ansible.builtin.set_fact: audit_file="/etc/audit/audit.rules"

    - name: Declare found syscalls
      ansible.builtin.set_fact: syscalls_found="{{ find_command.results | selectattr('matched')
        | map(attribute='item') | list }}"

    - name: Declare missing syscalls
      ansible.builtin.set_fact: missing_syscalls="{{ syscalls | difference(syscalls_found)
        }}"

    - name: Replace the audit rule in {{ audit_file }}
      ansible.builtin.lineinfile:
        path: '{{ audit_file }}'
        regexp: (-a always,exit -F arch=b64)(?=.*(?:(?:-S |,)(?:{{ syscalls_found
          | join("|") }}))\b)((?:( -S |,)\w+)+)( -F auid>=1000 -F auid!=unset (?:-k
          |-F key=)\w+)
        line: \1\2\3{{ missing_syscalls | join("\3") }}\4
        backrefs: true
        state: present
        mode: g-rwx,o-rwx
      when: syscalls_found | length > 0 and missing_syscalls | length > 0

    - name: Add the audit rule to {{ audit_file }}
      ansible.builtin.lineinfile:
        path: '{{ audit_file }}'
        line: -a always,exit -F arch=b64 -S {{ syscalls | join(',') }} -F auid>=1000
          -F auid!=unset -F key=perm_mod
        create: true
        mode: g-rwx,o-rwx
        state: present
      when: syscalls_found | length == 0

    - name: Declare list of syscalls
      ansible.builtin.set_fact:
        syscalls:
        - lremovexattr
        syscall_grouping:
        - fremovexattr
        - lremovexattr
        - removexattr
        - fsetxattr
        - lsetxattr
        - setxattr

    - name: Check existence of lremovexattr in /etc/audit/rules.d/
      ansible.builtin.find:
        paths: /etc/audit/rules.d
        contains: -a always,exit -F arch=b64(( -S |,)\w+)*(( -S |,){{ item }})+((
          -S |,)\w+)* -F auid=0 (-k\s+|-F\s+key=)\S+\s*$
        patterns: '*.rules'
      register: find_command
      loop: '{{ (syscall_grouping + syscalls) | unique }}'

    - name: Reset syscalls found per file
      ansible.builtin.set_fact:
        syscalls_per_file: {}
        found_paths_dict: {}

    - name: Declare syscalls found per file
      ansible.builtin.set_fact: syscalls_per_file="{{ syscalls_per_file | combine(
        {item.files[0].path :[item.item] + syscalls_per_file.get(item.files[0].path,
        []) } ) }}"
      loop: '{{ find_command.results | selectattr(''matched'') | list }}'

    - name: Declare files where syscalls were found
      ansible.builtin.set_fact: found_paths="{{ find_command.results | map(attribute='files')
        | flatten | map(attribute='path') | list }}"

    - name: Count occurrences of syscalls in paths
      ansible.builtin.set_fact: found_paths_dict="{{ found_paths_dict | combine({
        item:1+found_paths_dict.get(item, 0) }) }}"
      loop: '{{ find_command.results | map(attribute=''files'') | flatten | map(attribute=''path'')
        | list }}'

    - name: Get path with most syscalls
      ansible.builtin.set_fact: audit_file="{{ (found_paths_dict | dict2items() |
        sort(attribute='value') | last).key }}"
      when: found_paths | length >= 1

    - name: No file with syscall found, set path to /etc/audit/rules.d/perm_mod.rules
      ansible.builtin.set_fact: audit_file="/etc/audit/rules.d/perm_mod.rules"
      when: found_paths | length == 0

    - name: Declare found syscalls
      ansible.builtin.set_fact: syscalls_found="{{ find_command.results | selectattr('matched')
        | map(attribute='item') | list }}"

    - name: Declare missing syscalls
      ansible.builtin.set_fact: missing_syscalls="{{ syscalls | difference(syscalls_found)
        }}"

    - name: Replace the audit rule in {{ audit_file }}
      ansible.builtin.lineinfile:
        path: '{{ audit_file }}'
        regexp: (-a always,exit -F arch=b64)(?=.*(?:(?:-S |,)(?:{{ syscalls_per_file[audit_file]
          | join("|") }}))\b)((?:( -S |,)\w+)+)( -F auid=0 (?:-k |-F key=)\w+)
        line: \1\2\3{{ missing_syscalls | join("\3") }}\4
        backrefs: true
        state: present
        mode: g-rwx,o-rwx
      when: syscalls_found | length > 0 and missing_syscalls | length > 0

    - name: Add the audit rule to {{ audit_file }}
      ansible.builtin.lineinfile:
        path: '{{ audit_file }}'
        line: -a always,exit -F arch=b64 -S {{ syscalls | join(',') }} -F auid=0 -F
          key=perm_mod
        create: true
        mode: g-rwx,o-rwx
        state: present
      when: syscalls_found | length == 0

    - name: Declare list of syscalls
      ansible.builtin.set_fact:
        syscalls:
        - lremovexattr
        syscall_grouping:
        - fremovexattr
        - lremovexattr
        - removexattr
        - fsetxattr
        - lsetxattr
        - setxattr

    - name: Check existence of lremovexattr in /etc/audit/audit.rules
      ansible.builtin.find:
        paths: /etc/audit
        contains: -a always,exit -F arch=b64(( -S |,)\w+)*(( -S |,){{ item }})+((
          -S |,)\w+)* -F auid=0 (-k\s+|-F\s+key=)\S+\s*$
        patterns: audit.rules
      register: find_command
      loop: '{{ (syscall_grouping + syscalls) | unique }}'

    - name: Set path to /etc/audit/audit.rules
      ansible.builtin.set_fact: audit_file="/etc/audit/audit.rules"

    - name: Declare found syscalls
      ansible.builtin.set_fact: syscalls_found="{{ find_command.results | selectattr('matched')
        | map(attribute='item') | list }}"

    - name: Declare missing syscalls
      ansible.builtin.set_fact: missing_syscalls="{{ syscalls | difference(syscalls_found)
        }}"

    - name: Replace the audit rule in {{ audit_file }}
      ansible.builtin.lineinfile:
        path: '{{ audit_file }}'
        regexp: (-a always,exit -F arch=b64)(?=.*(?:(?:-S |,)(?:{{ syscalls_found
          | join("|") }}))\b)((?:( -S |,)\w+)+)( -F auid=0 (?:-k |-F key=)\w+)
        line: \1\2\3{{ missing_syscalls | join("\3") }}\4
        backrefs: true
        state: present
        mode: g-rwx,o-rwx
      when: syscalls_found | length > 0 and missing_syscalls | length > 0

    - name: Add the audit rule to {{ audit_file }}
      ansible.builtin.lineinfile:
        path: '{{ audit_file }}'
        line: -a always,exit -F arch=b64 -S {{ syscalls | join(',') }} -F auid=0 -F
          key=perm_mod
        create: true
        mode: g-rwx,o-rwx
        state: present
      when: syscalls_found | length == 0
    when:
    - '"audit" in ansible_facts.packages'
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - audit_arch == "b64"
    tags:
    - CJIS-5.4.1.1
    - DISA-STIG-OL09-00-000545
    - NIST-800-171-3.1.7
    - NIST-800-53-AU-12(c)
    - NIST-800-53-AU-2(d)
    - NIST-800-53-CM-6(a)
    - PCI-DSS-Req-10.5.5
    - PCI-DSSv4-10.3
    - PCI-DSSv4-10.3.4
    - audit_rules_dac_modification_lremovexattr
    - low_complexity
    - low_disruption
    - medium_severity
    - reboot_required
    - restrict_strategy

  - name: Set architecture for audit lsetxattr tasks
    ansible.builtin.set_fact:
      audit_arch: b64
    when:
    - '"audit" in ansible_facts.packages'
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - ansible_architecture == "aarch64" or ansible_architecture == "ppc64" or ansible_architecture
      == "ppc64le" or ansible_architecture == "s390x" or ansible_architecture == "x86_64"
    tags:
    - CJIS-5.4.1.1
    - DISA-STIG-OL09-00-000545
    - NIST-800-171-3.1.7
    - NIST-800-53-AU-12(c)
    - NIST-800-53-AU-2(d)
    - NIST-800-53-CM-6(a)
    - PCI-DSS-Req-10.5.5
    - PCI-DSSv4-10.3
    - PCI-DSSv4-10.3.4
    - audit_rules_dac_modification_lsetxattr
    - low_complexity
    - low_disruption
    - medium_severity
    - reboot_required
    - restrict_strategy

  - name: Perform remediation of Audit rules for lsetxattr for 32bit platform
    block:

    - name: Declare list of syscalls
      ansible.builtin.set_fact:
        syscalls:
        - lsetxattr
        syscall_grouping:
        - fremovexattr
        - lremovexattr
        - removexattr
        - fsetxattr
        - lsetxattr
        - setxattr

    - name: Check existence of lsetxattr in /etc/audit/rules.d/
      ansible.builtin.find:
        paths: /etc/audit/rules.d
        contains: -a always,exit -F arch=b32(( -S |,)\w+)*(( -S |,){{ item }})+((
          -S |,)\w+)* -F auid>=1000 -F auid!=unset (-k\s+|-F\s+key=)\S+\s*$
        patterns: '*.rules'
      register: find_command
      loop: '{{ (syscall_grouping + syscalls) | unique }}'

    - name: Reset syscalls found per file
      ansible.builtin.set_fact:
        syscalls_per_file: {}
        found_paths_dict: {}

    - name: Declare syscalls found per file
      ansible.builtin.set_fact: syscalls_per_file="{{ syscalls_per_file | combine(
        {item.files[0].path :[item.item] + syscalls_per_file.get(item.files[0].path,
        []) } ) }}"
      loop: '{{ find_command.results | selectattr(''matched'') | list }}'

    - name: Declare files where syscalls were found
      ansible.builtin.set_fact: found_paths="{{ find_command.results | map(attribute='files')
        | flatten | map(attribute='path') | list }}"

    - name: Count occurrences of syscalls in paths
      ansible.builtin.set_fact: found_paths_dict="{{ found_paths_dict | combine({
        item:1+found_paths_dict.get(item, 0) }) }}"
      loop: '{{ find_command.results | map(attribute=''files'') | flatten | map(attribute=''path'')
        | list }}'

    - name: Get path with most syscalls
      ansible.builtin.set_fact: audit_file="{{ (found_paths_dict | dict2items() |
        sort(attribute='value') | last).key }}"
      when: found_paths | length >= 1

    - name: No file with syscall found, set path to /etc/audit/rules.d/perm_mod.rules
      ansible.builtin.set_fact: audit_file="/etc/audit/rules.d/perm_mod.rules"
      when: found_paths | length == 0

    - name: Declare found syscalls
      ansible.builtin.set_fact: syscalls_found="{{ find_command.results | selectattr('matched')
        | map(attribute='item') | list }}"

    - name: Declare missing syscalls
      ansible.builtin.set_fact: missing_syscalls="{{ syscalls | difference(syscalls_found)
        }}"

    - name: Replace the audit rule in {{ audit_file }}
      ansible.builtin.lineinfile:
        path: '{{ audit_file }}'
        regexp: (-a always,exit -F arch=b32)(?=.*(?:(?:-S |,)(?:{{ syscalls_per_file[audit_file]
          | join("|") }}))\b)((?:( -S |,)\w+)+)( -F auid>=1000 -F auid!=unset (?:-k
          |-F key=)\w+)
        line: \1\2\3{{ missing_syscalls | join("\3") }}\4
        backrefs: true
        state: present
        mode: g-rwx,o-rwx
      when: syscalls_found | length > 0 and missing_syscalls | length > 0

    - name: Add the audit rule to {{ audit_file }}
      ansible.builtin.lineinfile:
        path: '{{ audit_file }}'
        line: -a always,exit -F arch=b32 -S {{ syscalls | join(',') }} -F auid>=1000
          -F auid!=unset -F key=perm_mod
        create: true
        mode: g-rwx,o-rwx
        state: present
      when: syscalls_found | length == 0

    - name: Declare list of syscalls
      ansible.builtin.set_fact:
        syscalls:
        - lsetxattr
        syscall_grouping:
        - fremovexattr
        - lremovexattr
        - removexattr
        - fsetxattr
        - lsetxattr
        - setxattr

    - name: Check existence of lsetxattr in /etc/audit/audit.rules
      ansible.builtin.find:
        paths: /etc/audit
        contains: -a always,exit -F arch=b32(( -S |,)\w+)*(( -S |,){{ item }})+((
          -S |,)\w+)* -F auid>=1000 -F auid!=unset (-k\s+|-F\s+key=)\S+\s*$
        patterns: audit.rules
      register: find_command
      loop: '{{ (syscall_grouping + syscalls) | unique }}'

    - name: Set path to /etc/audit/audit.rules
      ansible.builtin.set_fact: audit_file="/etc/audit/audit.rules"

    - name: Declare found syscalls
      ansible.builtin.set_fact: syscalls_found="{{ find_command.results | selectattr('matched')
        | map(attribute='item') | list }}"

    - name: Declare missing syscalls
      ansible.builtin.set_fact: missing_syscalls="{{ syscalls | difference(syscalls_found)
        }}"

    - name: Replace the audit rule in {{ audit_file }}
      ansible.builtin.lineinfile:
        path: '{{ audit_file }}'
        regexp: (-a always,exit -F arch=b32)(?=.*(?:(?:-S |,)(?:{{ syscalls_found
          | join("|") }}))\b)((?:( -S |,)\w+)+)( -F auid>=1000 -F auid!=unset (?:-k
          |-F key=)\w+)
        line: \1\2\3{{ missing_syscalls | join("\3") }}\4
        backrefs: true
        state: present
        mode: g-rwx,o-rwx
      when: syscalls_found | length > 0 and missing_syscalls | length > 0

    - name: Add the audit rule to {{ audit_file }}
      ansible.builtin.lineinfile:
        path: '{{ audit_file }}'
        line: -a always,exit -F arch=b32 -S {{ syscalls | join(',') }} -F auid>=1000
          -F auid!=unset -F key=perm_mod
        create: true
        mode: g-rwx,o-rwx
        state: present
      when: syscalls_found | length == 0

    - name: Declare list of syscalls
      ansible.builtin.set_fact:
        syscalls:
        - lsetxattr
        syscall_grouping:
        - fremovexattr
        - lremovexattr
        - removexattr
        - fsetxattr
        - lsetxattr
        - setxattr

    - name: Check existence of lsetxattr in /etc/audit/rules.d/
      ansible.builtin.find:
        paths: /etc/audit/rules.d
        contains: -a always,exit -F arch=b32(( -S |,)\w+)*(( -S |,){{ item }})+((
          -S |,)\w+)* -F auid=0 (-k\s+|-F\s+key=)\S+\s*$
        patterns: '*.rules'
      register: find_command
      loop: '{{ (syscall_grouping + syscalls) | unique }}'

    - name: Reset syscalls found per file
      ansible.builtin.set_fact:
        syscalls_per_file: {}
        found_paths_dict: {}

    - name: Declare syscalls found per file
      ansible.builtin.set_fact: syscalls_per_file="{{ syscalls_per_file | combine(
        {item.files[0].path :[item.item] + syscalls_per_file.get(item.files[0].path,
        []) } ) }}"
      loop: '{{ find_command.results | selectattr(''matched'') | list }}'

    - name: Declare files where syscalls were found
      ansible.builtin.set_fact: found_paths="{{ find_command.results | map(attribute='files')
        | flatten | map(attribute='path') | list }}"

    - name: Count occurrences of syscalls in paths
      ansible.builtin.set_fact: found_paths_dict="{{ found_paths_dict | combine({
        item:1+found_paths_dict.get(item, 0) }) }}"
      loop: '{{ find_command.results | map(attribute=''files'') | flatten | map(attribute=''path'')
        | list }}'

    - name: Get path with most syscalls
      ansible.builtin.set_fact: audit_file="{{ (found_paths_dict | dict2items() |
        sort(attribute='value') | last).key }}"
      when: found_paths | length >= 1

    - name: No file with syscall found, set path to /etc/audit/rules.d/perm_mod.rules
      ansible.builtin.set_fact: audit_file="/etc/audit/rules.d/perm_mod.rules"
      when: found_paths | length == 0

    - name: Declare found syscalls
      ansible.builtin.set_fact: syscalls_found="{{ find_command.results | selectattr('matched')
        | map(attribute='item') | list }}"

    - name: Declare missing syscalls
      ansible.builtin.set_fact: missing_syscalls="{{ syscalls | difference(syscalls_found)
        }}"

    - name: Replace the audit rule in {{ audit_file }}
      ansible.builtin.lineinfile:
        path: '{{ audit_file }}'
        regexp: (-a always,exit -F arch=b32)(?=.*(?:(?:-S |,)(?:{{ syscalls_per_file[audit_file]
          | join("|") }}))\b)((?:( -S |,)\w+)+)( -F auid=0 (?:-k |-F key=)\w+)
        line: \1\2\3{{ missing_syscalls | join("\3") }}\4
        backrefs: true
        state: present
        mode: g-rwx,o-rwx
      when: syscalls_found | length > 0 and missing_syscalls | length > 0

    - name: Add the audit rule to {{ audit_file }}
      ansible.builtin.lineinfile:
        path: '{{ audit_file }}'
        line: -a always,exit -F arch=b32 -S {{ syscalls | join(',') }} -F auid=0 -F
          key=perm_mod
        create: true
        mode: g-rwx,o-rwx
        state: present
      when: syscalls_found | length == 0

    - name: Declare list of syscalls
      ansible.builtin.set_fact:
        syscalls:
        - lsetxattr
        syscall_grouping:
        - fremovexattr
        - lremovexattr
        - removexattr
        - fsetxattr
        - lsetxattr
        - setxattr

    - name: Check existence of lsetxattr in /etc/audit/audit.rules
      ansible.builtin.find:
        paths: /etc/audit
        contains: -a always,exit -F arch=b32(( -S |,)\w+)*(( -S |,){{ item }})+((
          -S |,)\w+)* -F auid=0 (-k\s+|-F\s+key=)\S+\s*$
        patterns: audit.rules
      register: find_command
      loop: '{{ (syscall_grouping + syscalls) | unique }}'

    - name: Set path to /etc/audit/audit.rules
      ansible.builtin.set_fact: audit_file="/etc/audit/audit.rules"

    - name: Declare found syscalls
      ansible.builtin.set_fact: syscalls_found="{{ find_command.results | selectattr('matched')
        | map(attribute='item') | list }}"

    - name: Declare missing syscalls
      ansible.builtin.set_fact: missing_syscalls="{{ syscalls | difference(syscalls_found)
        }}"

    - name: Replace the audit rule in {{ audit_file }}
      ansible.builtin.lineinfile:
        path: '{{ audit_file }}'
        regexp: (-a always,exit -F arch=b32)(?=.*(?:(?:-S |,)(?:{{ syscalls_found
          | join("|") }}))\b)((?:( -S |,)\w+)+)( -F auid=0 (?:-k |-F key=)\w+)
        line: \1\2\3{{ missing_syscalls | join("\3") }}\4
        backrefs: true
        state: present
        mode: g-rwx,o-rwx
      when: syscalls_found | length > 0 and missing_syscalls | length > 0

    - name: Add the audit rule to {{ audit_file }}
      ansible.builtin.lineinfile:
        path: '{{ audit_file }}'
        line: -a always,exit -F arch=b32 -S {{ syscalls | join(',') }} -F auid=0 -F
          key=perm_mod
        create: true
        mode: g-rwx,o-rwx
        state: present
      when: syscalls_found | length == 0
    when:
    - '"audit" in ansible_facts.packages'
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - CJIS-5.4.1.1
    - DISA-STIG-OL09-00-000545
    - NIST-800-171-3.1.7
    - NIST-800-53-AU-12(c)
    - NIST-800-53-AU-2(d)
    - NIST-800-53-CM-6(a)
    - PCI-DSS-Req-10.5.5
    - PCI-DSSv4-10.3
    - PCI-DSSv4-10.3.4
    - audit_rules_dac_modification_lsetxattr
    - low_complexity
    - low_disruption
    - medium_severity
    - reboot_required
    - restrict_strategy

  - name: Perform remediation of Audit rules for lsetxattr for 64bit platform
    block:

    - name: Declare list of syscalls
      ansible.builtin.set_fact:
        syscalls:
        - lsetxattr
        syscall_grouping:
        - fremovexattr
        - lremovexattr
        - removexattr
        - fsetxattr
        - lsetxattr
        - setxattr

    - name: Check existence of lsetxattr in /etc/audit/rules.d/
      ansible.builtin.find:
        paths: /etc/audit/rules.d
        contains: -a always,exit -F arch=b64(( -S |,)\w+)*(( -S |,){{ item }})+((
          -S |,)\w+)* -F auid>=1000 -F auid!=unset (-k\s+|-F\s+key=)\S+\s*$
        patterns: '*.rules'
      register: find_command
      loop: '{{ (syscall_grouping + syscalls) | unique }}'

    - name: Reset syscalls found per file
      ansible.builtin.set_fact:
        syscalls_per_file: {}
        found_paths_dict: {}

    - name: Declare syscalls found per file
      ansible.builtin.set_fact: syscalls_per_file="{{ syscalls_per_file | combine(
        {item.files[0].path :[item.item] + syscalls_per_file.get(item.files[0].path,
        []) } ) }}"
      loop: '{{ find_command.results | selectattr(''matched'') | list }}'

    - name: Declare files where syscalls were found
      ansible.builtin.set_fact: found_paths="{{ find_command.results | map(attribute='files')
        | flatten | map(attribute='path') | list }}"

    - name: Count occurrences of syscalls in paths
      ansible.builtin.set_fact: found_paths_dict="{{ found_paths_dict | combine({
        item:1+found_paths_dict.get(item, 0) }) }}"
      loop: '{{ find_command.results | map(attribute=''files'') | flatten | map(attribute=''path'')
        | list }}'

    - name: Get path with most syscalls
      ansible.builtin.set_fact: audit_file="{{ (found_paths_dict | dict2items() |
        sort(attribute='value') | last).key }}"
      when: found_paths | length >= 1

    - name: No file with syscall found, set path to /etc/audit/rules.d/perm_mod.rules
      ansible.builtin.set_fact: audit_file="/etc/audit/rules.d/perm_mod.rules"
      when: found_paths | length == 0

    - name: Declare found syscalls
      ansible.builtin.set_fact: syscalls_found="{{ find_command.results | selectattr('matched')
        | map(attribute='item') | list }}"

    - name: Declare missing syscalls
      ansible.builtin.set_fact: missing_syscalls="{{ syscalls | difference(syscalls_found)
        }}"

    - name: Replace the audit rule in {{ audit_file }}
      ansible.builtin.lineinfile:
        path: '{{ audit_file }}'
        regexp: (-a always,exit -F arch=b64)(?=.*(?:(?:-S |,)(?:{{ syscalls_per_file[audit_file]
          | join("|") }}))\b)((?:( -S |,)\w+)+)( -F auid>=1000 -F auid!=unset (?:-k
          |-F key=)\w+)
        line: \1\2\3{{ missing_syscalls | join("\3") }}\4
        backrefs: true
        state: present
        mode: g-rwx,o-rwx
      when: syscalls_found | length > 0 and missing_syscalls | length > 0

    - name: Add the audit rule to {{ audit_file }}
      ansible.builtin.lineinfile:
        path: '{{ audit_file }}'
        line: -a always,exit -F arch=b64 -S {{ syscalls | join(',') }} -F auid>=1000
          -F auid!=unset -F key=perm_mod
        create: true
        mode: g-rwx,o-rwx
        state: present
      when: syscalls_found | length == 0

    - name: Declare list of syscalls
      ansible.builtin.set_fact:
        syscalls:
        - lsetxattr
        syscall_grouping:
        - fremovexattr
        - lremovexattr
        - removexattr
        - fsetxattr
        - lsetxattr
        - setxattr

    - name: Check existence of lsetxattr in /etc/audit/audit.rules
      ansible.builtin.find:
        paths: /etc/audit
        contains: -a always,exit -F arch=b64(( -S |,)\w+)*(( -S |,){{ item }})+((
          -S |,)\w+)* -F auid>=1000 -F auid!=unset (-k\s+|-F\s+key=)\S+\s*$
        patterns: audit.rules
      register: find_command
      loop: '{{ (syscall_grouping + syscalls) | unique }}'

    - name: Set path to /etc/audit/audit.rules
      ansible.builtin.set_fact: audit_file="/etc/audit/audit.rules"

    - name: Declare found syscalls
      ansible.builtin.set_fact: syscalls_found="{{ find_command.results | selectattr('matched')
        | map(attribute='item') | list }}"

    - name: Declare missing syscalls
      ansible.builtin.set_fact: missing_syscalls="{{ syscalls | difference(syscalls_found)
        }}"

    - name: Replace the audit rule in {{ audit_file }}
      ansible.builtin.lineinfile:
        path: '{{ audit_file }}'
        regexp: (-a always,exit -F arch=b64)(?=.*(?:(?:-S |,)(?:{{ syscalls_found
          | join("|") }}))\b)((?:( -S |,)\w+)+)( -F auid>=1000 -F auid!=unset (?:-k
          |-F key=)\w+)
        line: \1\2\3{{ missing_syscalls | join("\3") }}\4
        backrefs: true
        state: present
        mode: g-rwx,o-rwx
      when: syscalls_found | length > 0 and missing_syscalls | length > 0

    - name: Add the audit rule to {{ audit_file }}
      ansible.builtin.lineinfile:
        path: '{{ audit_file }}'
        line: -a always,exit -F arch=b64 -S {{ syscalls | join(',') }} -F auid>=1000
          -F auid!=unset -F key=perm_mod
        create: true
        mode: g-rwx,o-rwx
        state: present
      when: syscalls_found | length == 0

    - name: Declare list of syscalls
      ansible.builtin.set_fact:
        syscalls:
        - lsetxattr
        syscall_grouping:
        - fremovexattr
        - lremovexattr
        - removexattr
        - fsetxattr
        - lsetxattr
        - setxattr

    - name: Check existence of lsetxattr in /etc/audit/rules.d/
      ansible.builtin.find:
        paths: /etc/audit/rules.d
        contains: -a always,exit -F arch=b64(( -S |,)\w+)*(( -S |,){{ item }})+((
          -S |,)\w+)* -F auid=0 (-k\s+|-F\s+key=)\S+\s*$
        patterns: '*.rules'
      register: find_command
      loop: '{{ (syscall_grouping + syscalls) | unique }}'

    - name: Reset syscalls found per file
      ansible.builtin.set_fact:
        syscalls_per_file: {}
        found_paths_dict: {}

    - name: Declare syscalls found per file
      ansible.builtin.set_fact: syscalls_per_file="{{ syscalls_per_file | combine(
        {item.files[0].path :[item.item] + syscalls_per_file.get(item.files[0].path,
        []) } ) }}"
      loop: '{{ find_command.results | selectattr(''matched'') | list }}'

    - name: Declare files where syscalls were found
      ansible.builtin.set_fact: found_paths="{{ find_command.results | map(attribute='files')
        | flatten | map(attribute='path') | list }}"

    - name: Count occurrences of syscalls in paths
      ansible.builtin.set_fact: found_paths_dict="{{ found_paths_dict | combine({
        item:1+found_paths_dict.get(item, 0) }) }}"
      loop: '{{ find_command.results | map(attribute=''files'') | flatten | map(attribute=''path'')
        | list }}'

    - name: Get path with most syscalls
      ansible.builtin.set_fact: audit_file="{{ (found_paths_dict | dict2items() |
        sort(attribute='value') | last).key }}"
      when: found_paths | length >= 1

    - name: No file with syscall found, set path to /etc/audit/rules.d/perm_mod.rules
      ansible.builtin.set_fact: audit_file="/etc/audit/rules.d/perm_mod.rules"
      when: found_paths | length == 0

    - name: Declare found syscalls
      ansible.builtin.set_fact: syscalls_found="{{ find_command.results | selectattr('matched')
        | map(attribute='item') | list }}"

    - name: Declare missing syscalls
      ansible.builtin.set_fact: missing_syscalls="{{ syscalls | difference(syscalls_found)
        }}"

    - name: Replace the audit rule in {{ audit_file }}
      ansible.builtin.lineinfile:
        path: '{{ audit_file }}'
        regexp: (-a always,exit -F arch=b64)(?=.*(?:(?:-S |,)(?:{{ syscalls_per_file[audit_file]
          | join("|") }}))\b)((?:( -S |,)\w+)+)( -F auid=0 (?:-k |-F key=)\w+)
        line: \1\2\3{{ missing_syscalls | join("\3") }}\4
        backrefs: true
        state: present
        mode: g-rwx,o-rwx
      when: syscalls_found | length > 0 and missing_syscalls | length > 0

    - name: Add the audit rule to {{ audit_file }}
      ansible.builtin.lineinfile:
        path: '{{ audit_file }}'
        line: -a always,exit -F arch=b64 -S {{ syscalls | join(',') }} -F auid=0 -F
          key=perm_mod
        create: true
        mode: g-rwx,o-rwx
        state: present
      when: syscalls_found | length == 0

    - name: Declare list of syscalls
      ansible.builtin.set_fact:
        syscalls:
        - lsetxattr
        syscall_grouping:
        - fremovexattr
        - lremovexattr
        - removexattr
        - fsetxattr
        - lsetxattr
        - setxattr

    - name: Check existence of lsetxattr in /etc/audit/audit.rules
      ansible.builtin.find:
        paths: /etc/audit
        contains: -a always,exit -F arch=b64(( -S |,)\w+)*(( -S |,){{ item }})+((
          -S |,)\w+)* -F auid=0 (-k\s+|-F\s+key=)\S+\s*$
        patterns: audit.rules
      register: find_command
      loop: '{{ (syscall_grouping + syscalls) | unique }}'

    - name: Set path to /etc/audit/audit.rules
      ansible.builtin.set_fact: audit_file="/etc/audit/audit.rules"

    - name: Declare found syscalls
      ansible.builtin.set_fact: syscalls_found="{{ find_command.results | selectattr('matched')
        | map(attribute='item') | list }}"

    - name: Declare missing syscalls
      ansible.builtin.set_fact: missing_syscalls="{{ syscalls | difference(syscalls_found)
        }}"

    - name: Replace the audit rule in {{ audit_file }}
      ansible.builtin.lineinfile:
        path: '{{ audit_file }}'
        regexp: (-a always,exit -F arch=b64)(?=.*(?:(?:-S |,)(?:{{ syscalls_found
          | join("|") }}))\b)((?:( -S |,)\w+)+)( -F auid=0 (?:-k |-F key=)\w+)
        line: \1\2\3{{ missing_syscalls | join("\3") }}\4
        backrefs: true
        state: present
        mode: g-rwx,o-rwx
      when: syscalls_found | length > 0 and missing_syscalls | length > 0

    - name: Add the audit rule to {{ audit_file }}
      ansible.builtin.lineinfile:
        path: '{{ audit_file }}'
        line: -a always,exit -F arch=b64 -S {{ syscalls | join(',') }} -F auid=0 -F
          key=perm_mod
        create: true
        mode: g-rwx,o-rwx
        state: present
      when: syscalls_found | length == 0
    when:
    - '"audit" in ansible_facts.packages'
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - audit_arch == "b64"
    tags:
    - CJIS-5.4.1.1
    - DISA-STIG-OL09-00-000545
    - NIST-800-171-3.1.7
    - NIST-800-53-AU-12(c)
    - NIST-800-53-AU-2(d)
    - NIST-800-53-CM-6(a)
    - PCI-DSS-Req-10.5.5
    - PCI-DSSv4-10.3
    - PCI-DSSv4-10.3.4
    - audit_rules_dac_modification_lsetxattr
    - low_complexity
    - low_disruption
    - medium_severity
    - reboot_required
    - restrict_strategy

  - name: Set architecture for audit removexattr tasks
    ansible.builtin.set_fact:
      audit_arch: b64
    when:
    - '"audit" in ansible_facts.packages'
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - ansible_architecture == "aarch64" or ansible_architecture == "ppc64" or ansible_architecture
      == "ppc64le" or ansible_architecture == "s390x" or ansible_architecture == "x86_64"
    tags:
    - CJIS-5.4.1.1
    - DISA-STIG-OL09-00-000545
    - NIST-800-171-3.1.7
    - NIST-800-53-AU-12(c)
    - NIST-800-53-AU-2(d)
    - NIST-800-53-CM-6(a)
    - PCI-DSS-Req-10.5.5
    - PCI-DSSv4-10.3
    - PCI-DSSv4-10.3.4
    - audit_rules_dac_modification_removexattr
    - low_complexity
    - low_disruption
    - medium_severity
    - reboot_required
    - restrict_strategy

  - name: Perform remediation of Audit rules for removexattr for 32bit platform
    block:

    - name: Declare list of syscalls
      ansible.builtin.set_fact:
        syscalls:
        - removexattr
        syscall_grouping:
        - fremovexattr
        - lremovexattr
        - removexattr
        - fsetxattr
        - lsetxattr
        - setxattr

    - name: Check existence of removexattr in /etc/audit/rules.d/
      ansible.builtin.find:
        paths: /etc/audit/rules.d
        contains: -a always,exit -F arch=b32(( -S |,)\w+)*(( -S |,){{ item }})+((
          -S |,)\w+)* -F auid>=1000 -F auid!=unset (-k\s+|-F\s+key=)\S+\s*$
        patterns: '*.rules'
      register: find_command
      loop: '{{ (syscall_grouping + syscalls) | unique }}'

    - name: Reset syscalls found per file
      ansible.builtin.set_fact:
        syscalls_per_file: {}
        found_paths_dict: {}

    - name: Declare syscalls found per file
      ansible.builtin.set_fact: syscalls_per_file="{{ syscalls_per_file | combine(
        {item.files[0].path :[item.item] + syscalls_per_file.get(item.files[0].path,
        []) } ) }}"
      loop: '{{ find_command.results | selectattr(''matched'') | list }}'

    - name: Declare files where syscalls were found
      ansible.builtin.set_fact: found_paths="{{ find_command.results | map(attribute='files')
        | flatten | map(attribute='path') | list }}"

    - name: Count occurrences of syscalls in paths
      ansible.builtin.set_fact: found_paths_dict="{{ found_paths_dict | combine({
        item:1+found_paths_dict.get(item, 0) }) }}"
      loop: '{{ find_command.results | map(attribute=''files'') | flatten | map(attribute=''path'')
        | list }}'

    - name: Get path with most syscalls
      ansible.builtin.set_fact: audit_file="{{ (found_paths_dict | dict2items() |
        sort(attribute='value') | last).key }}"
      when: found_paths | length >= 1

    - name: No file with syscall found, set path to /etc/audit/rules.d/perm_mod.rules
      ansible.builtin.set_fact: audit_file="/etc/audit/rules.d/perm_mod.rules"
      when: found_paths | length == 0

    - name: Declare found syscalls
      ansible.builtin.set_fact: syscalls_found="{{ find_command.results | selectattr('matched')
        | map(attribute='item') | list }}"

    - name: Declare missing syscalls
      ansible.builtin.set_fact: missing_syscalls="{{ syscalls | difference(syscalls_found)
        }}"

    - name: Replace the audit rule in {{ audit_file }}
      ansible.builtin.lineinfile:
        path: '{{ audit_file }}'
        regexp: (-a always,exit -F arch=b32)(?=.*(?:(?:-S |,)(?:{{ syscalls_per_file[audit_file]
          | join("|") }}))\b)((?:( -S |,)\w+)+)( -F auid>=1000 -F auid!=unset (?:-k
          |-F key=)\w+)
        line: \1\2\3{{ missing_syscalls | join("\3") }}\4
        backrefs: true
        state: present
        mode: g-rwx,o-rwx
      when: syscalls_found | length > 0 and missing_syscalls | length > 0

    - name: Add the audit rule to {{ audit_file }}
      ansible.builtin.lineinfile:
        path: '{{ audit_file }}'
        line: -a always,exit -F arch=b32 -S {{ syscalls | join(',') }} -F auid>=1000
          -F auid!=unset -F key=perm_mod
        create: true
        mode: g-rwx,o-rwx
        state: present
      when: syscalls_found | length == 0

    - name: Declare list of syscalls
      ansible.builtin.set_fact:
        syscalls:
        - removexattr
        syscall_grouping:
        - fremovexattr
        - lremovexattr
        - removexattr
        - fsetxattr
        - lsetxattr
        - setxattr

    - name: Check existence of removexattr in /etc/audit/audit.rules
      ansible.builtin.find:
        paths: /etc/audit
        contains: -a always,exit -F arch=b32(( -S |,)\w+)*(( -S |,){{ item }})+((
          -S |,)\w+)* -F auid>=1000 -F auid!=unset (-k\s+|-F\s+key=)\S+\s*$
        patterns: audit.rules
      register: find_command
      loop: '{{ (syscall_grouping + syscalls) | unique }}'

    - name: Set path to /etc/audit/audit.rules
      ansible.builtin.set_fact: audit_file="/etc/audit/audit.rules"

    - name: Declare found syscalls
      ansible.builtin.set_fact: syscalls_found="{{ find_command.results | selectattr('matched')
        | map(attribute='item') | list }}"

    - name: Declare missing syscalls
      ansible.builtin.set_fact: missing_syscalls="{{ syscalls | difference(syscalls_found)
        }}"

    - name: Replace the audit rule in {{ audit_file }}
      ansible.builtin.lineinfile:
        path: '{{ audit_file }}'
        regexp: (-a always,exit -F arch=b32)(?=.*(?:(?:-S |,)(?:{{ syscalls_found
          | join("|") }}))\b)((?:( -S |,)\w+)+)( -F auid>=1000 -F auid!=unset (?:-k
          |-F key=)\w+)
        line: \1\2\3{{ missing_syscalls | join("\3") }}\4
        backrefs: true
        state: present
        mode: g-rwx,o-rwx
      when: syscalls_found | length > 0 and missing_syscalls | length > 0

    - name: Add the audit rule to {{ audit_file }}
      ansible.builtin.lineinfile:
        path: '{{ audit_file }}'
        line: -a always,exit -F arch=b32 -S {{ syscalls | join(',') }} -F auid>=1000
          -F auid!=unset -F key=perm_mod
        create: true
        mode: g-rwx,o-rwx
        state: present
      when: syscalls_found | length == 0

    - name: Declare list of syscalls
      ansible.builtin.set_fact:
        syscalls:
        - removexattr
        syscall_grouping:
        - fremovexattr
        - lremovexattr
        - removexattr
        - fsetxattr
        - lsetxattr
        - setxattr

    - name: Check existence of removexattr in /etc/audit/rules.d/
      ansible.builtin.find:
        paths: /etc/audit/rules.d
        contains: -a always,exit -F arch=b32(( -S |,)\w+)*(( -S |,){{ item }})+((
          -S |,)\w+)* -F auid=0 (-k\s+|-F\s+key=)\S+\s*$
        patterns: '*.rules'
      register: find_command
      loop: '{{ (syscall_grouping + syscalls) | unique }}'

    - name: Reset syscalls found per file
      ansible.builtin.set_fact:
        syscalls_per_file: {}
        found_paths_dict: {}

    - name: Declare syscalls found per file
      ansible.builtin.set_fact: syscalls_per_file="{{ syscalls_per_file | combine(
        {item.files[0].path :[item.item] + syscalls_per_file.get(item.files[0].path,
        []) } ) }}"
      loop: '{{ find_command.results | selectattr(''matched'') | list }}'

    - name: Declare files where syscalls were found
      ansible.builtin.set_fact: found_paths="{{ find_command.results | map(attribute='files')
        | flatten | map(attribute='path') | list }}"

    - name: Count occurrences of syscalls in paths
      ansible.builtin.set_fact: found_paths_dict="{{ found_paths_dict | combine({
        item:1+found_paths_dict.get(item, 0) }) }}"
      loop: '{{ find_command.results | map(attribute=''files'') | flatten | map(attribute=''path'')
        | list }}'

    - name: Get path with most syscalls
      ansible.builtin.set_fact: audit_file="{{ (found_paths_dict | dict2items() |
        sort(attribute='value') | last).key }}"
      when: found_paths | length >= 1

    - name: No file with syscall found, set path to /etc/audit/rules.d/perm_mod.rules
      ansible.builtin.set_fact: audit_file="/etc/audit/rules.d/perm_mod.rules"
      when: found_paths | length == 0

    - name: Declare found syscalls
      ansible.builtin.set_fact: syscalls_found="{{ find_command.results | selectattr('matched')
        | map(attribute='item') | list }}"

    - name: Declare missing syscalls
      ansible.builtin.set_fact: missing_syscalls="{{ syscalls | difference(syscalls_found)
        }}"

    - name: Replace the audit rule in {{ audit_file }}
      ansible.builtin.lineinfile:
        path: '{{ audit_file }}'
        regexp: (-a always,exit -F arch=b32)(?=.*(?:(?:-S |,)(?:{{ syscalls_per_file[audit_file]
          | join("|") }}))\b)((?:( -S |,)\w+)+)( -F auid=0 (?:-k |-F key=)\w+)
        line: \1\2\3{{ missing_syscalls | join("\3") }}\4
        backrefs: true
        state: present
        mode: g-rwx,o-rwx
      when: syscalls_found | length > 0 and missing_syscalls | length > 0

    - name: Add the audit rule to {{ audit_file }}
      ansible.builtin.lineinfile:
        path: '{{ audit_file }}'
        line: -a always,exit -F arch=b32 -S {{ syscalls | join(',') }} -F auid=0 -F
          key=perm_mod
        create: true
        mode: g-rwx,o-rwx
        state: present
      when: syscalls_found | length == 0

    - name: Declare list of syscalls
      ansible.builtin.set_fact:
        syscalls:
        - removexattr
        syscall_grouping:
        - fremovexattr
        - lremovexattr
        - removexattr
        - fsetxattr
        - lsetxattr
        - setxattr

    - name: Check existence of removexattr in /etc/audit/audit.rules
      ansible.builtin.find:
        paths: /etc/audit
        contains: -a always,exit -F arch=b32(( -S |,)\w+)*(( -S |,){{ item }})+((
          -S |,)\w+)* -F auid=0 (-k\s+|-F\s+key=)\S+\s*$
        patterns: audit.rules
      register: find_command
      loop: '{{ (syscall_grouping + syscalls) | unique }}'

    - name: Set path to /etc/audit/audit.rules
      ansible.builtin.set_fact: audit_file="/etc/audit/audit.rules"

    - name: Declare found syscalls
      ansible.builtin.set_fact: syscalls_found="{{ find_command.results | selectattr('matched')
        | map(attribute='item') | list }}"

    - name: Declare missing syscalls
      ansible.builtin.set_fact: missing_syscalls="{{ syscalls | difference(syscalls_found)
        }}"

    - name: Replace the audit rule in {{ audit_file }}
      ansible.builtin.lineinfile:
        path: '{{ audit_file }}'
        regexp: (-a always,exit -F arch=b32)(?=.*(?:(?:-S |,)(?:{{ syscalls_found
          | join("|") }}))\b)((?:( -S |,)\w+)+)( -F auid=0 (?:-k |-F key=)\w+)
        line: \1\2\3{{ missing_syscalls | join("\3") }}\4
        backrefs: true
        state: present
        mode: g-rwx,o-rwx
      when: syscalls_found | length > 0 and missing_syscalls | length > 0

    - name: Add the audit rule to {{ audit_file }}
      ansible.builtin.lineinfile:
        path: '{{ audit_file }}'
        line: -a always,exit -F arch=b32 -S {{ syscalls | join(',') }} -F auid=0 -F
          key=perm_mod
        create: true
        mode: g-rwx,o-rwx
        state: present
      when: syscalls_found | length == 0
    when:
    - '"audit" in ansible_facts.packages'
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - CJIS-5.4.1.1
    - DISA-STIG-OL09-00-000545
    - NIST-800-171-3.1.7
    - NIST-800-53-AU-12(c)
    - NIST-800-53-AU-2(d)
    - NIST-800-53-CM-6(a)
    - PCI-DSS-Req-10.5.5
    - PCI-DSSv4-10.3
    - PCI-DSSv4-10.3.4
    - audit_rules_dac_modification_removexattr
    - low_complexity
    - low_disruption
    - medium_severity
    - reboot_required
    - restrict_strategy

  - name: Perform remediation of Audit rules for removexattr for 64bit platform
    block:

    - name: Declare list of syscalls
      ansible.builtin.set_fact:
        syscalls:
        - removexattr
        syscall_grouping:
        - fremovexattr
        - lremovexattr
        - removexattr
        - fsetxattr
        - lsetxattr
        - setxattr

    - name: Check existence of removexattr in /etc/audit/rules.d/
      ansible.builtin.find:
        paths: /etc/audit/rules.d
        contains: -a always,exit -F arch=b64(( -S |,)\w+)*(( -S |,){{ item }})+((
          -S |,)\w+)* -F auid>=1000 -F auid!=unset (-k\s+|-F\s+key=)\S+\s*$
        patterns: '*.rules'
      register: find_command
      loop: '{{ (syscall_grouping + syscalls) | unique }}'

    - name: Reset syscalls found per file
      ansible.builtin.set_fact:
        syscalls_per_file: {}
        found_paths_dict: {}

    - name: Declare syscalls found per file
      ansible.builtin.set_fact: syscalls_per_file="{{ syscalls_per_file | combine(
        {item.files[0].path :[item.item] + syscalls_per_file.get(item.files[0].path,
        []) } ) }}"
      loop: '{{ find_command.results | selectattr(''matched'') | list }}'

    - name: Declare files where syscalls were found
      ansible.builtin.set_fact: found_paths="{{ find_command.results | map(attribute='files')
        | flatten | map(attribute='path') | list }}"

    - name: Count occurrences of syscalls in paths
      ansible.builtin.set_fact: found_paths_dict="{{ found_paths_dict | combine({
        item:1+found_paths_dict.get(item, 0) }) }}"
      loop: '{{ find_command.results | map(attribute=''files'') | flatten | map(attribute=''path'')
        | list }}'

    - name: Get path with most syscalls
      ansible.builtin.set_fact: audit_file="{{ (found_paths_dict | dict2items() |
        sort(attribute='value') | last).key }}"
      when: found_paths | length >= 1

    - name: No file with syscall found, set path to /etc/audit/rules.d/perm_mod.rules
      ansible.builtin.set_fact: audit_file="/etc/audit/rules.d/perm_mod.rules"
      when: found_paths | length == 0

    - name: Declare found syscalls
      ansible.builtin.set_fact: syscalls_found="{{ find_command.results | selectattr('matched')
        | map(attribute='item') | list }}"

    - name: Declare missing syscalls
      ansible.builtin.set_fact: missing_syscalls="{{ syscalls | difference(syscalls_found)
        }}"

    - name: Replace the audit rule in {{ audit_file }}
      ansible.builtin.lineinfile:
        path: '{{ audit_file }}'
        regexp: (-a always,exit -F arch=b64)(?=.*(?:(?:-S |,)(?:{{ syscalls_per_file[audit_file]
          | join("|") }}))\b)((?:( -S |,)\w+)+)( -F auid>=1000 -F auid!=unset (?:-k
          |-F key=)\w+)
        line: \1\2\3{{ missing_syscalls | join("\3") }}\4
        backrefs: true
        state: present
        mode: g-rwx,o-rwx
      when: syscalls_found | length > 0 and missing_syscalls | length > 0

    - name: Add the audit rule to {{ audit_file }}
      ansible.builtin.lineinfile:
        path: '{{ audit_file }}'
        line: -a always,exit -F arch=b64 -S {{ syscalls | join(',') }} -F auid>=1000
          -F auid!=unset -F key=perm_mod
        create: true
        mode: g-rwx,o-rwx
        state: present
      when: syscalls_found | length == 0

    - name: Declare list of syscalls
      ansible.builtin.set_fact:
        syscalls:
        - removexattr
        syscall_grouping:
        - fremovexattr
        - lremovexattr
        - removexattr
        - fsetxattr
        - lsetxattr
        - setxattr

    - name: Check existence of removexattr in /etc/audit/audit.rules
      ansible.builtin.find:
        paths: /etc/audit
        contains: -a always,exit -F arch=b64(( -S |,)\w+)*(( -S |,){{ item }})+((
          -S |,)\w+)* -F auid>=1000 -F auid!=unset (-k\s+|-F\s+key=)\S+\s*$
        patterns: audit.rules
      register: find_command
      loop: '{{ (syscall_grouping + syscalls) | unique }}'

    - name: Set path to /etc/audit/audit.rules
      ansible.builtin.set_fact: audit_file="/etc/audit/audit.rules"

    - name: Declare found syscalls
      ansible.builtin.set_fact: syscalls_found="{{ find_command.results | selectattr('matched')
        | map(attribute='item') | list }}"

    - name: Declare missing syscalls
      ansible.builtin.set_fact: missing_syscalls="{{ syscalls | difference(syscalls_found)
        }}"

    - name: Replace the audit rule in {{ audit_file }}
      ansible.builtin.lineinfile:
        path: '{{ audit_file }}'
        regexp: (-a always,exit -F arch=b64)(?=.*(?:(?:-S |,)(?:{{ syscalls_found
          | join("|") }}))\b)((?:( -S |,)\w+)+)( -F auid>=1000 -F auid!=unset (?:-k
          |-F key=)\w+)
        line: \1\2\3{{ missing_syscalls | join("\3") }}\4
        backrefs: true
        state: present
        mode: g-rwx,o-rwx
      when: syscalls_found | length > 0 and missing_syscalls | length > 0

    - name: Add the audit rule to {{ audit_file }}
      ansible.builtin.lineinfile:
        path: '{{ audit_file }}'
        line: -a always,exit -F arch=b64 -S {{ syscalls | join(',') }} -F auid>=1000
          -F auid!=unset -F key=perm_mod
        create: true
        mode: g-rwx,o-rwx
        state: present
      when: syscalls_found | length == 0

    - name: Declare list of syscalls
      ansible.builtin.set_fact:
        syscalls:
        - removexattr
        syscall_grouping:
        - fremovexattr
        - lremovexattr
        - removexattr
        - fsetxattr
        - lsetxattr
        - setxattr

    - name: Check existence of removexattr in /etc/audit/rules.d/
      ansible.builtin.find:
        paths: /etc/audit/rules.d
        contains: -a always,exit -F arch=b64(( -S |,)\w+)*(( -S |,){{ item }})+((
          -S |,)\w+)* -F auid=0 (-k\s+|-F\s+key=)\S+\s*$
        patterns: '*.rules'
      register: find_command
      loop: '{{ (syscall_grouping + syscalls) | unique }}'

    - name: Reset syscalls found per file
      ansible.builtin.set_fact:
        syscalls_per_file: {}
        found_paths_dict: {}

    - name: Declare syscalls found per file
      ansible.builtin.set_fact: syscalls_per_file="{{ syscalls_per_file | combine(
        {item.files[0].path :[item.item] + syscalls_per_file.get(item.files[0].path,
        []) } ) }}"
      loop: '{{ find_command.results | selectattr(''matched'') | list }}'

    - name: Declare files where syscalls were found
      ansible.builtin.set_fact: found_paths="{{ find_command.results | map(attribute='files')
        | flatten | map(attribute='path') | list }}"

    - name: Count occurrences of syscalls in paths
      ansible.builtin.set_fact: found_paths_dict="{{ found_paths_dict | combine({
        item:1+found_paths_dict.get(item, 0) }) }}"
      loop: '{{ find_command.results | map(attribute=''files'') | flatten | map(attribute=''path'')
        | list }}'

    - name: Get path with most syscalls
      ansible.builtin.set_fact: audit_file="{{ (found_paths_dict | dict2items() |
        sort(attribute='value') | last).key }}"
      when: found_paths | length >= 1

    - name: No file with syscall found, set path to /etc/audit/rules.d/perm_mod.rules
      ansible.builtin.set_fact: audit_file="/etc/audit/rules.d/perm_mod.rules"
      when: found_paths | length == 0

    - name: Declare found syscalls
      ansible.builtin.set_fact: syscalls_found="{{ find_command.results | selectattr('matched')
        | map(attribute='item') | list }}"

    - name: Declare missing syscalls
      ansible.builtin.set_fact: missing_syscalls="{{ syscalls | difference(syscalls_found)
        }}"

    - name: Replace the audit rule in {{ audit_file }}
      ansible.builtin.lineinfile:
        path: '{{ audit_file }}'
        regexp: (-a always,exit -F arch=b64)(?=.*(?:(?:-S |,)(?:{{ syscalls_per_file[audit_file]
          | join("|") }}))\b)((?:( -S |,)\w+)+)( -F auid=0 (?:-k |-F key=)\w+)
        line: \1\2\3{{ missing_syscalls | join("\3") }}\4
        backrefs: true
        state: present
        mode: g-rwx,o-rwx
      when: syscalls_found | length > 0 and missing_syscalls | length > 0

    - name: Add the audit rule to {{ audit_file }}
      ansible.builtin.lineinfile:
        path: '{{ audit_file }}'
        line: -a always,exit -F arch=b64 -S {{ syscalls | join(',') }} -F auid=0 -F
          key=perm_mod
        create: true
        mode: g-rwx,o-rwx
        state: present
      when: syscalls_found | length == 0

    - name: Declare list of syscalls
      ansible.builtin.set_fact:
        syscalls:
        - removexattr
        syscall_grouping:
        - fremovexattr
        - lremovexattr
        - removexattr
        - fsetxattr
        - lsetxattr
        - setxattr

    - name: Check existence of removexattr in /etc/audit/audit.rules
      ansible.builtin.find:
        paths: /etc/audit
        contains: -a always,exit -F arch=b64(( -S |,)\w+)*(( -S |,){{ item }})+((
          -S |,)\w+)* -F auid=0 (-k\s+|-F\s+key=)\S+\s*$
        patterns: audit.rules
      register: find_command
      loop: '{{ (syscall_grouping + syscalls) | unique }}'

    - name: Set path to /etc/audit/audit.rules
      ansible.builtin.set_fact: audit_file="/etc/audit/audit.rules"

    - name: Declare found syscalls
      ansible.builtin.set_fact: syscalls_found="{{ find_command.results | selectattr('matched')
        | map(attribute='item') | list }}"

    - name: Declare missing syscalls
      ansible.builtin.set_fact: missing_syscalls="{{ syscalls | difference(syscalls_found)
        }}"

    - name: Replace the audit rule in {{ audit_file }}
      ansible.builtin.lineinfile:
        path: '{{ audit_file }}'
        regexp: (-a always,exit -F arch=b64)(?=.*(?:(?:-S |,)(?:{{ syscalls_found
          | join("|") }}))\b)((?:( -S |,)\w+)+)( -F auid=0 (?:-k |-F key=)\w+)
        line: \1\2\3{{ missing_syscalls | join("\3") }}\4
        backrefs: true
        state: present
        mode: g-rwx,o-rwx
      when: syscalls_found | length > 0 and missing_syscalls | length > 0

    - name: Add the audit rule to {{ audit_file }}
      ansible.builtin.lineinfile:
        path: '{{ audit_file }}'
        line: -a always,exit -F arch=b64 -S {{ syscalls | join(',') }} -F auid=0 -F
          key=perm_mod
        create: true
        mode: g-rwx,o-rwx
        state: present
      when: syscalls_found | length == 0
    when:
    - '"audit" in ansible_facts.packages'
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - audit_arch == "b64"
    tags:
    - CJIS-5.4.1.1
    - DISA-STIG-OL09-00-000545
    - NIST-800-171-3.1.7
    - NIST-800-53-AU-12(c)
    - NIST-800-53-AU-2(d)
    - NIST-800-53-CM-6(a)
    - PCI-DSS-Req-10.5.5
    - PCI-DSSv4-10.3
    - PCI-DSSv4-10.3.4
    - audit_rules_dac_modification_removexattr
    - low_complexity
    - low_disruption
    - medium_severity
    - reboot_required
    - restrict_strategy

  - name: Set architecture for audit setxattr tasks
    ansible.builtin.set_fact:
      audit_arch: b64
    when:
    - '"audit" in ansible_facts.packages'
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - ansible_architecture == "aarch64" or ansible_architecture == "ppc64" or ansible_architecture
      == "ppc64le" or ansible_architecture == "s390x" or ansible_architecture == "x86_64"
    tags:
    - CJIS-5.4.1.1
    - DISA-STIG-OL09-00-000545
    - NIST-800-171-3.1.7
    - NIST-800-53-AU-12(c)
    - NIST-800-53-AU-2(d)
    - NIST-800-53-CM-6(a)
    - PCI-DSS-Req-10.5.5
    - PCI-DSSv4-10.3
    - PCI-DSSv4-10.3.4
    - audit_rules_dac_modification_setxattr
    - low_complexity
    - low_disruption
    - medium_severity
    - reboot_required
    - restrict_strategy

  - name: Perform remediation of Audit rules for setxattr for 32bit platform
    block:

    - name: Declare list of syscalls
      ansible.builtin.set_fact:
        syscalls:
        - setxattr
        syscall_grouping:
        - fremovexattr
        - lremovexattr
        - removexattr
        - fsetxattr
        - lsetxattr
        - setxattr

    - name: Check existence of setxattr in /etc/audit/rules.d/
      ansible.builtin.find:
        paths: /etc/audit/rules.d
        contains: -a always,exit -F arch=b32(( -S |,)\w+)*(( -S |,){{ item }})+((
          -S |,)\w+)* -F auid>=1000 -F auid!=unset (-k\s+|-F\s+key=)\S+\s*$
        patterns: '*.rules'
      register: find_command
      loop: '{{ (syscall_grouping + syscalls) | unique }}'

    - name: Reset syscalls found per file
      ansible.builtin.set_fact:
        syscalls_per_file: {}
        found_paths_dict: {}

    - name: Declare syscalls found per file
      ansible.builtin.set_fact: syscalls_per_file="{{ syscalls_per_file | combine(
        {item.files[0].path :[item.item] + syscalls_per_file.get(item.files[0].path,
        []) } ) }}"
      loop: '{{ find_command.results | selectattr(''matched'') | list }}'

    - name: Declare files where syscalls were found
      ansible.builtin.set_fact: found_paths="{{ find_command.results | map(attribute='files')
        | flatten | map(attribute='path') | list }}"

    - name: Count occurrences of syscalls in paths
      ansible.builtin.set_fact: found_paths_dict="{{ found_paths_dict | combine({
        item:1+found_paths_dict.get(item, 0) }) }}"
      loop: '{{ find_command.results | map(attribute=''files'') | flatten | map(attribute=''path'')
        | list }}'

    - name: Get path with most syscalls
      ansible.builtin.set_fact: audit_file="{{ (found_paths_dict | dict2items() |
        sort(attribute='value') | last).key }}"
      when: found_paths | length >= 1

    - name: No file with syscall found, set path to /etc/audit/rules.d/perm_mod.rules
      ansible.builtin.set_fact: audit_file="/etc/audit/rules.d/perm_mod.rules"
      when: found_paths | length == 0

    - name: Declare found syscalls
      ansible.builtin.set_fact: syscalls_found="{{ find_command.results | selectattr('matched')
        | map(attribute='item') | list }}"

    - name: Declare missing syscalls
      ansible.builtin.set_fact: missing_syscalls="{{ syscalls | difference(syscalls_found)
        }}"

    - name: Replace the audit rule in {{ audit_file }}
      ansible.builtin.lineinfile:
        path: '{{ audit_file }}'
        regexp: (-a always,exit -F arch=b32)(?=.*(?:(?:-S |,)(?:{{ syscalls_per_file[audit_file]
          | join("|") }}))\b)((?:( -S |,)\w+)+)( -F auid>=1000 -F auid!=unset (?:-k
          |-F key=)\w+)
        line: \1\2\3{{ missing_syscalls | join("\3") }}\4
        backrefs: true
        state: present
        mode: g-rwx,o-rwx
      when: syscalls_found | length > 0 and missing_syscalls | length > 0

    - name: Add the audit rule to {{ audit_file }}
      ansible.builtin.lineinfile:
        path: '{{ audit_file }}'
        line: -a always,exit -F arch=b32 -S {{ syscalls | join(',') }} -F auid>=1000
          -F auid!=unset -F key=perm_mod
        create: true
        mode: g-rwx,o-rwx
        state: present
      when: syscalls_found | length == 0

    - name: Declare list of syscalls
      ansible.builtin.set_fact:
        syscalls:
        - setxattr
        syscall_grouping:
        - fremovexattr
        - lremovexattr
        - removexattr
        - fsetxattr
        - lsetxattr
        - setxattr

    - name: Check existence of setxattr in /etc/audit/audit.rules
      ansible.builtin.find:
        paths: /etc/audit
        contains: -a always,exit -F arch=b32(( -S |,)\w+)*(( -S |,){{ item }})+((
          -S |,)\w+)* -F auid>=1000 -F auid!=unset (-k\s+|-F\s+key=)\S+\s*$
        patterns: audit.rules
      register: find_command
      loop: '{{ (syscall_grouping + syscalls) | unique }}'

    - name: Set path to /etc/audit/audit.rules
      ansible.builtin.set_fact: audit_file="/etc/audit/audit.rules"

    - name: Declare found syscalls
      ansible.builtin.set_fact: syscalls_found="{{ find_command.results | selectattr('matched')
        | map(attribute='item') | list }}"

    - name: Declare missing syscalls
      ansible.builtin.set_fact: missing_syscalls="{{ syscalls | difference(syscalls_found)
        }}"

    - name: Replace the audit rule in {{ audit_file }}
      ansible.builtin.lineinfile:
        path: '{{ audit_file }}'
        regexp: (-a always,exit -F arch=b32)(?=.*(?:(?:-S |,)(?:{{ syscalls_found
          | join("|") }}))\b)((?:( -S |,)\w+)+)( -F auid>=1000 -F auid!=unset (?:-k
          |-F key=)\w+)
        line: \1\2\3{{ missing_syscalls | join("\3") }}\4
        backrefs: true
        state: present
        mode: g-rwx,o-rwx
      when: syscalls_found | length > 0 and missing_syscalls | length > 0

    - name: Add the audit rule to {{ audit_file }}
      ansible.builtin.lineinfile:
        path: '{{ audit_file }}'
        line: -a always,exit -F arch=b32 -S {{ syscalls | join(',') }} -F auid>=1000
          -F auid!=unset -F key=perm_mod
        create: true
        mode: g-rwx,o-rwx
        state: present
      when: syscalls_found | length == 0

    - name: Declare list of syscalls
      ansible.builtin.set_fact:
        syscalls:
        - setxattr
        syscall_grouping:
        - fremovexattr
        - lremovexattr
        - removexattr
        - fsetxattr
        - lsetxattr
        - setxattr

    - name: Check existence of setxattr in /etc/audit/rules.d/
      ansible.builtin.find:
        paths: /etc/audit/rules.d
        contains: -a always,exit -F arch=b32(( -S |,)\w+)*(( -S |,){{ item }})+((
          -S |,)\w+)* -F auid=0 (-k\s+|-F\s+key=)\S+\s*$
        patterns: '*.rules'
      register: find_command
      loop: '{{ (syscall_grouping + syscalls) | unique }}'

    - name: Reset syscalls found per file
      ansible.builtin.set_fact:
        syscalls_per_file: {}
        found_paths_dict: {}

    - name: Declare syscalls found per file
      ansible.builtin.set_fact: syscalls_per_file="{{ syscalls_per_file | combine(
        {item.files[0].path :[item.item] + syscalls_per_file.get(item.files[0].path,
        []) } ) }}"
      loop: '{{ find_command.results | selectattr(''matched'') | list }}'

    - name: Declare files where syscalls were found
      ansible.builtin.set_fact: found_paths="{{ find_command.results | map(attribute='files')
        | flatten | map(attribute='path') | list }}"

    - name: Count occurrences of syscalls in paths
      ansible.builtin.set_fact: found_paths_dict="{{ found_paths_dict | combine({
        item:1+found_paths_dict.get(item, 0) }) }}"
      loop: '{{ find_command.results | map(attribute=''files'') | flatten | map(attribute=''path'')
        | list }}'

    - name: Get path with most syscalls
      ansible.builtin.set_fact: audit_file="{{ (found_paths_dict | dict2items() |
        sort(attribute='value') | last).key }}"
      when: found_paths | length >= 1

    - name: No file with syscall found, set path to /etc/audit/rules.d/perm_mod.rules
      ansible.builtin.set_fact: audit_file="/etc/audit/rules.d/perm_mod.rules"
      when: found_paths | length == 0

    - name: Declare found syscalls
      ansible.builtin.set_fact: syscalls_found="{{ find_command.results | selectattr('matched')
        | map(attribute='item') | list }}"

    - name: Declare missing syscalls
      ansible.builtin.set_fact: missing_syscalls="{{ syscalls | difference(syscalls_found)
        }}"

    - name: Replace the audit rule in {{ audit_file }}
      ansible.builtin.lineinfile:
        path: '{{ audit_file }}'
        regexp: (-a always,exit -F arch=b32)(?=.*(?:(?:-S |,)(?:{{ syscalls_per_file[audit_file]
          | join("|") }}))\b)((?:( -S |,)\w+)+)( -F auid=0 (?:-k |-F key=)\w+)
        line: \1\2\3{{ missing_syscalls | join("\3") }}\4
        backrefs: true
        state: present
        mode: g-rwx,o-rwx
      when: syscalls_found | length > 0 and missing_syscalls | length > 0

    - name: Add the audit rule to {{ audit_file }}
      ansible.builtin.lineinfile:
        path: '{{ audit_file }}'
        line: -a always,exit -F arch=b32 -S {{ syscalls | join(',') }} -F auid=0 -F
          key=perm_mod
        create: true
        mode: g-rwx,o-rwx
        state: present
      when: syscalls_found | length == 0

    - name: Declare list of syscalls
      ansible.builtin.set_fact:
        syscalls:
        - setxattr
        syscall_grouping:
        - fremovexattr
        - lremovexattr
        - removexattr
        - fsetxattr
        - lsetxattr
        - setxattr

    - name: Check existence of setxattr in /etc/audit/audit.rules
      ansible.builtin.find:
        paths: /etc/audit
        contains: -a always,exit -F arch=b32(( -S |,)\w+)*(( -S |,){{ item }})+((
          -S |,)\w+)* -F auid=0 (-k\s+|-F\s+key=)\S+\s*$
        patterns: audit.rules
      register: find_command
      loop: '{{ (syscall_grouping + syscalls) | unique }}'

    - name: Set path to /etc/audit/audit.rules
      ansible.builtin.set_fact: audit_file="/etc/audit/audit.rules"

    - name: Declare found syscalls
      ansible.builtin.set_fact: syscalls_found="{{ find_command.results | selectattr('matched')
        | map(attribute='item') | list }}"

    - name: Declare missing syscalls
      ansible.builtin.set_fact: missing_syscalls="{{ syscalls | difference(syscalls_found)
        }}"

    - name: Replace the audit rule in {{ audit_file }}
      ansible.builtin.lineinfile:
        path: '{{ audit_file }}'
        regexp: (-a always,exit -F arch=b32)(?=.*(?:(?:-S |,)(?:{{ syscalls_found
          | join("|") }}))\b)((?:( -S |,)\w+)+)( -F auid=0 (?:-k |-F key=)\w+)
        line: \1\2\3{{ missing_syscalls | join("\3") }}\4
        backrefs: true
        state: present
        mode: g-rwx,o-rwx
      when: syscalls_found | length > 0 and missing_syscalls | length > 0

    - name: Add the audit rule to {{ audit_file }}
      ansible.builtin.lineinfile:
        path: '{{ audit_file }}'
        line: -a always,exit -F arch=b32 -S {{ syscalls | join(',') }} -F auid=0 -F
          key=perm_mod
        create: true
        mode: g-rwx,o-rwx
        state: present
      when: syscalls_found | length == 0
    when:
    - '"audit" in ansible_facts.packages'
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - CJIS-5.4.1.1
    - DISA-STIG-OL09-00-000545
    - NIST-800-171-3.1.7
    - NIST-800-53-AU-12(c)
    - NIST-800-53-AU-2(d)
    - NIST-800-53-CM-6(a)
    - PCI-DSS-Req-10.5.5
    - PCI-DSSv4-10.3
    - PCI-DSSv4-10.3.4
    - audit_rules_dac_modification_setxattr
    - low_complexity
    - low_disruption
    - medium_severity
    - reboot_required
    - restrict_strategy

  - name: Perform remediation of Audit rules for setxattr for 64bit platform
    block:

    - name: Declare list of syscalls
      ansible.builtin.set_fact:
        syscalls:
        - setxattr
        syscall_grouping:
        - fremovexattr
        - lremovexattr
        - removexattr
        - fsetxattr
        - lsetxattr
        - setxattr

    - name: Check existence of setxattr in /etc/audit/rules.d/
      ansible.builtin.find:
        paths: /etc/audit/rules.d
        contains: -a always,exit -F arch=b64(( -S |,)\w+)*(( -S |,){{ item }})+((
          -S |,)\w+)* -F auid>=1000 -F auid!=unset (-k\s+|-F\s+key=)\S+\s*$
        patterns: '*.rules'
      register: find_command
      loop: '{{ (syscall_grouping + syscalls) | unique }}'

    - name: Reset syscalls found per file
      ansible.builtin.set_fact:
        syscalls_per_file: {}
        found_paths_dict: {}

    - name: Declare syscalls found per file
      ansible.builtin.set_fact: syscalls_per_file="{{ syscalls_per_file | combine(
        {item.files[0].path :[item.item] + syscalls_per_file.get(item.files[0].path,
        []) } ) }}"
      loop: '{{ find_command.results | selectattr(''matched'') | list }}'

    - name: Declare files where syscalls were found
      ansible.builtin.set_fact: found_paths="{{ find_command.results | map(attribute='files')
        | flatten | map(attribute='path') | list }}"

    - name: Count occurrences of syscalls in paths
      ansible.builtin.set_fact: found_paths_dict="{{ found_paths_dict | combine({
        item:1+found_paths_dict.get(item, 0) }) }}"
      loop: '{{ find_command.results | map(attribute=''files'') | flatten | map(attribute=''path'')
        | list }}'

    - name: Get path with most syscalls
      ansible.builtin.set_fact: audit_file="{{ (found_paths_dict | dict2items() |
        sort(attribute='value') | last).key }}"
      when: found_paths | length >= 1

    - name: No file with syscall found, set path to /etc/audit/rules.d/perm_mod.rules
      ansible.builtin.set_fact: audit_file="/etc/audit/rules.d/perm_mod.rules"
      when: found_paths | length == 0

    - name: Declare found syscalls
      ansible.builtin.set_fact: syscalls_found="{{ find_command.results | selectattr('matched')
        | map(attribute='item') | list }}"

    - name: Declare missing syscalls
      ansible.builtin.set_fact: missing_syscalls="{{ syscalls | difference(syscalls_found)
        }}"

    - name: Replace the audit rule in {{ audit_file }}
      ansible.builtin.lineinfile:
        path: '{{ audit_file }}'
        regexp: (-a always,exit -F arch=b64)(?=.*(?:(?:-S |,)(?:{{ syscalls_per_file[audit_file]
          | join("|") }}))\b)((?:( -S |,)\w+)+)( -F auid>=1000 -F auid!=unset (?:-k
          |-F key=)\w+)
        line: \1\2\3{{ missing_syscalls | join("\3") }}\4
        backrefs: true
        state: present
        mode: g-rwx,o-rwx
      when: syscalls_found | length > 0 and missing_syscalls | length > 0

    - name: Add the audit rule to {{ audit_file }}
      ansible.builtin.lineinfile:
        path: '{{ audit_file }}'
        line: -a always,exit -F arch=b64 -S {{ syscalls | join(',') }} -F auid>=1000
          -F auid!=unset -F key=perm_mod
        create: true
        mode: g-rwx,o-rwx
        state: present
      when: syscalls_found | length == 0

    - name: Declare list of syscalls
      ansible.builtin.set_fact:
        syscalls:
        - setxattr
        syscall_grouping:
        - fremovexattr
        - lremovexattr
        - removexattr
        - fsetxattr
        - lsetxattr
        - setxattr

    - name: Check existence of setxattr in /etc/audit/audit.rules
      ansible.builtin.find:
        paths: /etc/audit
        contains: -a always,exit -F arch=b64(( -S |,)\w+)*(( -S |,){{ item }})+((
          -S |,)\w+)* -F auid>=1000 -F auid!=unset (-k\s+|-F\s+key=)\S+\s*$
        patterns: audit.rules
      register: find_command
      loop: '{{ (syscall_grouping + syscalls) | unique }}'

    - name: Set path to /etc/audit/audit.rules
      ansible.builtin.set_fact: audit_file="/etc/audit/audit.rules"

    - name: Declare found syscalls
      ansible.builtin.set_fact: syscalls_found="{{ find_command.results | selectattr('matched')
        | map(attribute='item') | list }}"

    - name: Declare missing syscalls
      ansible.builtin.set_fact: missing_syscalls="{{ syscalls | difference(syscalls_found)
        }}"

    - name: Replace the audit rule in {{ audit_file }}
      ansible.builtin.lineinfile:
        path: '{{ audit_file }}'
        regexp: (-a always,exit -F arch=b64)(?=.*(?:(?:-S |,)(?:{{ syscalls_found
          | join("|") }}))\b)((?:( -S |,)\w+)+)( -F auid>=1000 -F auid!=unset (?:-k
          |-F key=)\w+)
        line: \1\2\3{{ missing_syscalls | join("\3") }}\4
        backrefs: true
        state: present
        mode: g-rwx,o-rwx
      when: syscalls_found | length > 0 and missing_syscalls | length > 0

    - name: Add the audit rule to {{ audit_file }}
      ansible.builtin.lineinfile:
        path: '{{ audit_file }}'
        line: -a always,exit -F arch=b64 -S {{ syscalls | join(',') }} -F auid>=1000
          -F auid!=unset -F key=perm_mod
        create: true
        mode: g-rwx,o-rwx
        state: present
      when: syscalls_found | length == 0

    - name: Declare list of syscalls
      ansible.builtin.set_fact:
        syscalls:
        - setxattr
        syscall_grouping:
        - fremovexattr
        - lremovexattr
        - removexattr
        - fsetxattr
        - lsetxattr
        - setxattr

    - name: Check existence of setxattr in /etc/audit/rules.d/
      ansible.builtin.find:
        paths: /etc/audit/rules.d
        contains: -a always,exit -F arch=b64(( -S |,)\w+)*(( -S |,){{ item }})+((
          -S |,)\w+)* -F auid=0 (-k\s+|-F\s+key=)\S+\s*$
        patterns: '*.rules'
      register: find_command
      loop: '{{ (syscall_grouping + syscalls) | unique }}'

    - name: Reset syscalls found per file
      ansible.builtin.set_fact:
        syscalls_per_file: {}
        found_paths_dict: {}

    - name: Declare syscalls found per file
      ansible.builtin.set_fact: syscalls_per_file="{{ syscalls_per_file | combine(
        {item.files[0].path :[item.item] + syscalls_per_file.get(item.files[0].path,
        []) } ) }}"
      loop: '{{ find_command.results | selectattr(''matched'') | list }}'

    - name: Declare files where syscalls were found
      ansible.builtin.set_fact: found_paths="{{ find_command.results | map(attribute='files')
        | flatten | map(attribute='path') | list }}"

    - name: Count occurrences of syscalls in paths
      ansible.builtin.set_fact: found_paths_dict="{{ found_paths_dict | combine({
        item:1+found_paths_dict.get(item, 0) }) }}"
      loop: '{{ find_command.results | map(attribute=''files'') | flatten | map(attribute=''path'')
        | list }}'

    - name: Get path with most syscalls
      ansible.builtin.set_fact: audit_file="{{ (found_paths_dict | dict2items() |
        sort(attribute='value') | last).key }}"
      when: found_paths | length >= 1

    - name: No file with syscall found, set path to /etc/audit/rules.d/perm_mod.rules
      ansible.builtin.set_fact: audit_file="/etc/audit/rules.d/perm_mod.rules"
      when: found_paths | length == 0

    - name: Declare found syscalls
      ansible.builtin.set_fact: syscalls_found="{{ find_command.results | selectattr('matched')
        | map(attribute='item') | list }}"

    - name: Declare missing syscalls
      ansible.builtin.set_fact: missing_syscalls="{{ syscalls | difference(syscalls_found)
        }}"

    - name: Replace the audit rule in {{ audit_file }}
      ansible.builtin.lineinfile:
        path: '{{ audit_file }}'
        regexp: (-a always,exit -F arch=b64)(?=.*(?:(?:-S |,)(?:{{ syscalls_per_file[audit_file]
          | join("|") }}))\b)((?:( -S |,)\w+)+)( -F auid=0 (?:-k |-F key=)\w+)
        line: \1\2\3{{ missing_syscalls | join("\3") }}\4
        backrefs: true
        state: present
        mode: g-rwx,o-rwx
      when: syscalls_found | length > 0 and missing_syscalls | length > 0

    - name: Add the audit rule to {{ audit_file }}
      ansible.builtin.lineinfile:
        path: '{{ audit_file }}'
        line: -a always,exit -F arch=b64 -S {{ syscalls | join(',') }} -F auid=0 -F
          key=perm_mod
        create: true
        mode: g-rwx,o-rwx
        state: present
      when: syscalls_found | length == 0

    - name: Declare list of syscalls
      ansible.builtin.set_fact:
        syscalls:
        - setxattr
        syscall_grouping:
        - fremovexattr
        - lremovexattr
        - removexattr
        - fsetxattr
        - lsetxattr
        - setxattr

    - name: Check existence of setxattr in /etc/audit/audit.rules
      ansible.builtin.find:
        paths: /etc/audit
        contains: -a always,exit -F arch=b64(( -S |,)\w+)*(( -S |,){{ item }})+((
          -S |,)\w+)* -F auid=0 (-k\s+|-F\s+key=)\S+\s*$
        patterns: audit.rules
      register: find_command
      loop: '{{ (syscall_grouping + syscalls) | unique }}'

    - name: Set path to /etc/audit/audit.rules
      ansible.builtin.set_fact: audit_file="/etc/audit/audit.rules"

    - name: Declare found syscalls
      ansible.builtin.set_fact: syscalls_found="{{ find_command.results | selectattr('matched')
        | map(attribute='item') | list }}"

    - name: Declare missing syscalls
      ansible.builtin.set_fact: missing_syscalls="{{ syscalls | difference(syscalls_found)
        }}"

    - name: Replace the audit rule in {{ audit_file }}
      ansible.builtin.lineinfile:
        path: '{{ audit_file }}'
        regexp: (-a always,exit -F arch=b64)(?=.*(?:(?:-S |,)(?:{{ syscalls_found
          | join("|") }}))\b)((?:( -S |,)\w+)+)( -F auid=0 (?:-k |-F key=)\w+)
        line: \1\2\3{{ missing_syscalls | join("\3") }}\4
        backrefs: true
        state: present
        mode: g-rwx,o-rwx
      when: syscalls_found | length > 0 and missing_syscalls | length > 0

    - name: Add the audit rule to {{ audit_file }}
      ansible.builtin.lineinfile:
        path: '{{ audit_file }}'
        line: -a always,exit -F arch=b64 -S {{ syscalls | join(',') }} -F auid=0 -F
          key=perm_mod
        create: true
        mode: g-rwx,o-rwx
        state: present
      when: syscalls_found | length == 0
    when:
    - '"audit" in ansible_facts.packages'
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - audit_arch == "b64"
    tags:
    - CJIS-5.4.1.1
    - DISA-STIG-OL09-00-000545
    - NIST-800-171-3.1.7
    - NIST-800-53-AU-12(c)
    - NIST-800-53-AU-2(d)
    - NIST-800-53-CM-6(a)
    - PCI-DSS-Req-10.5.5
    - PCI-DSSv4-10.3
    - PCI-DSSv4-10.3.4
    - audit_rules_dac_modification_setxattr
    - low_complexity
    - low_disruption
    - medium_severity
    - reboot_required
    - restrict_strategy

  - name: Perform remediation of Audit rules for umount for x86 platform
    block:

    - name: Declare list of syscalls
      ansible.builtin.set_fact:
        syscalls:
        - umount
        syscall_grouping: []

    - name: Check existence of umount in /etc/audit/rules.d/
      ansible.builtin.find:
        paths: /etc/audit/rules.d
        contains: -a always,exit -F arch=b32(( -S |,)\w+)*(( -S |,){{ item }})+((
          -S |,)\w+)* -F auid>=1000 -F auid!=unset (-k\s+|-F\s+key=)\S+\s*$
        patterns: '*.rules'
      register: find_command
      loop: '{{ (syscall_grouping + syscalls) | unique }}'

    - name: Reset syscalls found per file
      ansible.builtin.set_fact:
        syscalls_per_file: {}
        found_paths_dict: {}

    - name: Declare syscalls found per file
      ansible.builtin.set_fact: syscalls_per_file="{{ syscalls_per_file | combine(
        {item.files[0].path :[item.item] + syscalls_per_file.get(item.files[0].path,
        []) } ) }}"
      loop: '{{ find_command.results | selectattr(''matched'') | list }}'

    - name: Declare files where syscalls were found
      ansible.builtin.set_fact: found_paths="{{ find_command.results | map(attribute='files')
        | flatten | map(attribute='path') | list }}"

    - name: Count occurrences of syscalls in paths
      ansible.builtin.set_fact: found_paths_dict="{{ found_paths_dict | combine({
        item:1+found_paths_dict.get(item, 0) }) }}"
      loop: '{{ find_command.results | map(attribute=''files'') | flatten | map(attribute=''path'')
        | list }}'

    - name: Get path with most syscalls
      ansible.builtin.set_fact: audit_file="{{ (found_paths_dict | dict2items() |
        sort(attribute='value') | last).key }}"
      when: found_paths | length >= 1

    - name: No file with syscall found, set path to /etc/audit/rules.d/perm_mod.rules
      ansible.builtin.set_fact: audit_file="/etc/audit/rules.d/perm_mod.rules"
      when: found_paths | length == 0

    - name: Declare found syscalls
      ansible.builtin.set_fact: syscalls_found="{{ find_command.results | selectattr('matched')
        | map(attribute='item') | list }}"

    - name: Declare missing syscalls
      ansible.builtin.set_fact: missing_syscalls="{{ syscalls | difference(syscalls_found)
        }}"

    - name: Replace the audit rule in {{ audit_file }}
      ansible.builtin.lineinfile:
        path: '{{ audit_file }}'
        regexp: (-a always,exit -F arch=b32)(?=.*(?:(?:-S |,)(?:{{ syscalls_per_file[audit_file]
          | join("|") }}))\b)((?:( -S |,)\w+)+)( -F auid>=1000 -F auid!=unset (?:-k
          |-F key=)\w+)
        line: \1\2\3{{ missing_syscalls | join("\3") }}\4
        backrefs: true
        state: present
        mode: g-rwx,o-rwx
      when: syscalls_found | length > 0 and missing_syscalls | length > 0

    - name: Add the audit rule to {{ audit_file }}
      ansible.builtin.lineinfile:
        path: '{{ audit_file }}'
        line: -a always,exit -F arch=b32 -S {{ syscalls | join(',') }} -F auid>=1000
          -F auid!=unset -F key=perm_mod
        create: true
        mode: g-rwx,o-rwx
        state: present
      when: syscalls_found | length == 0

    - name: Declare list of syscalls
      ansible.builtin.set_fact:
        syscalls:
        - umount
        syscall_grouping: []

    - name: Check existence of umount in /etc/audit/audit.rules
      ansible.builtin.find:
        paths: /etc/audit
        contains: -a always,exit -F arch=b32(( -S |,)\w+)*(( -S |,){{ item }})+((
          -S |,)\w+)* -F auid>=1000 -F auid!=unset (-k\s+|-F\s+key=)\S+\s*$
        patterns: audit.rules
      register: find_command
      loop: '{{ (syscall_grouping + syscalls) | unique }}'

    - name: Set path to /etc/audit/audit.rules
      ansible.builtin.set_fact: audit_file="/etc/audit/audit.rules"

    - name: Declare found syscalls
      ansible.builtin.set_fact: syscalls_found="{{ find_command.results | selectattr('matched')
        | map(attribute='item') | list }}"

    - name: Declare missing syscalls
      ansible.builtin.set_fact: missing_syscalls="{{ syscalls | difference(syscalls_found)
        }}"

    - name: Replace the audit rule in {{ audit_file }}
      ansible.builtin.lineinfile:
        path: '{{ audit_file }}'
        regexp: (-a always,exit -F arch=b32)(?=.*(?:(?:-S |,)(?:{{ syscalls_found
          | join("|") }}))\b)((?:( -S |,)\w+)+)( -F auid>=1000 -F auid!=unset (?:-k
          |-F key=)\w+)
        line: \1\2\3{{ missing_syscalls | join("\3") }}\4
        backrefs: true
        state: present
        mode: g-rwx,o-rwx
      when: syscalls_found | length > 0 and missing_syscalls | length > 0

    - name: Add the audit rule to {{ audit_file }}
      ansible.builtin.lineinfile:
        path: '{{ audit_file }}'
        line: -a always,exit -F arch=b32 -S {{ syscalls | join(',') }} -F auid>=1000
          -F auid!=unset -F key=perm_mod
        create: true
        mode: g-rwx,o-rwx
        state: present
      when: syscalls_found | length == 0
    when:
    - '"audit" in ansible_facts.packages'
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - not ( ansible_architecture == "aarch64" )
    tags:
    - DISA-STIG-OL09-00-000840
    - audit_rules_dac_modification_umount
    - low_complexity
    - low_disruption
    - medium_severity
    - reboot_required
    - restrict_strategy

  - name: Set architecture for audit umount2 tasks
    ansible.builtin.set_fact:
      audit_arch: b64
    when:
    - '"audit" in ansible_facts.packages'
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - ansible_architecture == "aarch64" or ansible_architecture == "ppc64" or ansible_architecture
      == "ppc64le" or ansible_architecture == "s390x" or ansible_architecture == "x86_64"
    tags:
    - DISA-STIG-OL09-00-000845
    - audit_rules_dac_modification_umount2
    - low_complexity
    - low_disruption
    - medium_severity
    - reboot_required
    - restrict_strategy

  - name: Perform remediation of Audit rules for umount2 for 32bit platform
    block:

    - name: Declare list of syscalls
      ansible.builtin.set_fact:
        syscalls:
        - umount2
        syscall_grouping: []

    - name: Check existence of umount2 in /etc/audit/rules.d/
      ansible.builtin.find:
        paths: /etc/audit/rules.d
        contains: -a always,exit -F arch=b32(( -S |,)\w+)*(( -S |,){{ item }})+((
          -S |,)\w+)* -F auid>=1000 -F auid!=unset (-k\s+|-F\s+key=)\S+\s*$
        patterns: '*.rules'
      register: find_command
      loop: '{{ (syscall_grouping + syscalls) | unique }}'

    - name: Reset syscalls found per file
      ansible.builtin.set_fact:
        syscalls_per_file: {}
        found_paths_dict: {}

    - name: Declare syscalls found per file
      ansible.builtin.set_fact: syscalls_per_file="{{ syscalls_per_file | combine(
        {item.files[0].path :[item.item] + syscalls_per_file.get(item.files[0].path,
        []) } ) }}"
      loop: '{{ find_command.results | selectattr(''matched'') | list }}'

    - name: Declare files where syscalls were found
      ansible.builtin.set_fact: found_paths="{{ find_command.results | map(attribute='files')
        | flatten | map(attribute='path') | list }}"

    - name: Count occurrences of syscalls in paths
      ansible.builtin.set_fact: found_paths_dict="{{ found_paths_dict | combine({
        item:1+found_paths_dict.get(item, 0) }) }}"
      loop: '{{ find_command.results | map(attribute=''files'') | flatten | map(attribute=''path'')
        | list }}'

    - name: Get path with most syscalls
      ansible.builtin.set_fact: audit_file="{{ (found_paths_dict | dict2items() |
        sort(attribute='value') | last).key }}"
      when: found_paths | length >= 1

    - name: No file with syscall found, set path to /etc/audit/rules.d/perm_mod.rules
      ansible.builtin.set_fact: audit_file="/etc/audit/rules.d/perm_mod.rules"
      when: found_paths | length == 0

    - name: Declare found syscalls
      ansible.builtin.set_fact: syscalls_found="{{ find_command.results | selectattr('matched')
        | map(attribute='item') | list }}"

    - name: Declare missing syscalls
      ansible.builtin.set_fact: missing_syscalls="{{ syscalls | difference(syscalls_found)
        }}"

    - name: Replace the audit rule in {{ audit_file }}
      ansible.builtin.lineinfile:
        path: '{{ audit_file }}'
        regexp: (-a always,exit -F arch=b32)(?=.*(?:(?:-S |,)(?:{{ syscalls_per_file[audit_file]
          | join("|") }}))\b)((?:( -S |,)\w+)+)( -F auid>=1000 -F auid!=unset (?:-k
          |-F key=)\w+)
        line: \1\2\3{{ missing_syscalls | join("\3") }}\4
        backrefs: true
        state: present
        mode: g-rwx,o-rwx
      when: syscalls_found | length > 0 and missing_syscalls | length > 0

    - name: Add the audit rule to {{ audit_file }}
      ansible.builtin.lineinfile:
        path: '{{ audit_file }}'
        line: -a always,exit -F arch=b32 -S {{ syscalls | join(',') }} -F auid>=1000
          -F auid!=unset -F key=perm_mod
        create: true
        mode: g-rwx,o-rwx
        state: present
      when: syscalls_found | length == 0

    - name: Declare list of syscalls
      ansible.builtin.set_fact:
        syscalls:
        - umount2
        syscall_grouping: []

    - name: Check existence of umount2 in /etc/audit/audit.rules
      ansible.builtin.find:
        paths: /etc/audit
        contains: -a always,exit -F arch=b32(( -S |,)\w+)*(( -S |,){{ item }})+((
          -S |,)\w+)* -F auid>=1000 -F auid!=unset (-k\s+|-F\s+key=)\S+\s*$
        patterns: audit.rules
      register: find_command
      loop: '{{ (syscall_grouping + syscalls) | unique }}'

    - name: Set path to /etc/audit/audit.rules
      ansible.builtin.set_fact: audit_file="/etc/audit/audit.rules"

    - name: Declare found syscalls
      ansible.builtin.set_fact: syscalls_found="{{ find_command.results | selectattr('matched')
        | map(attribute='item') | list }}"

    - name: Declare missing syscalls
      ansible.builtin.set_fact: missing_syscalls="{{ syscalls | difference(syscalls_found)
        }}"

    - name: Replace the audit rule in {{ audit_file }}
      ansible.builtin.lineinfile:
        path: '{{ audit_file }}'
        regexp: (-a always,exit -F arch=b32)(?=.*(?:(?:-S |,)(?:{{ syscalls_found
          | join("|") }}))\b)((?:( -S |,)\w+)+)( -F auid>=1000 -F auid!=unset (?:-k
          |-F key=)\w+)
        line: \1\2\3{{ missing_syscalls | join("\3") }}\4
        backrefs: true
        state: present
        mode: g-rwx,o-rwx
      when: syscalls_found | length > 0 and missing_syscalls | length > 0

    - name: Add the audit rule to {{ audit_file }}
      ansible.builtin.lineinfile:
        path: '{{ audit_file }}'
        line: -a always,exit -F arch=b32 -S {{ syscalls | join(',') }} -F auid>=1000
          -F auid!=unset -F key=perm_mod
        create: true
        mode: g-rwx,o-rwx
        state: present
      when: syscalls_found | length == 0
    when:
    - '"audit" in ansible_facts.packages'
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-000845
    - audit_rules_dac_modification_umount2
    - low_complexity
    - low_disruption
    - medium_severity
    - reboot_required
    - restrict_strategy

  - name: Perform remediation of Audit rules for umount2 for 64bit platform
    block:

    - name: Declare list of syscalls
      ansible.builtin.set_fact:
        syscalls:
        - umount2
        syscall_grouping: []

    - name: Check existence of umount2 in /etc/audit/rules.d/
      ansible.builtin.find:
        paths: /etc/audit/rules.d
        contains: -a always,exit -F arch=b64(( -S |,)\w+)*(( -S |,){{ item }})+((
          -S |,)\w+)* -F auid>=1000 -F auid!=unset (-k\s+|-F\s+key=)\S+\s*$
        patterns: '*.rules'
      register: find_command
      loop: '{{ (syscall_grouping + syscalls) | unique }}'

    - name: Reset syscalls found per file
      ansible.builtin.set_fact:
        syscalls_per_file: {}
        found_paths_dict: {}

    - name: Declare syscalls found per file
      ansible.builtin.set_fact: syscalls_per_file="{{ syscalls_per_file | combine(
        {item.files[0].path :[item.item] + syscalls_per_file.get(item.files[0].path,
        []) } ) }}"
      loop: '{{ find_command.results | selectattr(''matched'') | list }}'

    - name: Declare files where syscalls were found
      ansible.builtin.set_fact: found_paths="{{ find_command.results | map(attribute='files')
        | flatten | map(attribute='path') | list }}"

    - name: Count occurrences of syscalls in paths
      ansible.builtin.set_fact: found_paths_dict="{{ found_paths_dict | combine({
        item:1+found_paths_dict.get(item, 0) }) }}"
      loop: '{{ find_command.results | map(attribute=''files'') | flatten | map(attribute=''path'')
        | list }}'

    - name: Get path with most syscalls
      ansible.builtin.set_fact: audit_file="{{ (found_paths_dict | dict2items() |
        sort(attribute='value') | last).key }}"
      when: found_paths | length >= 1

    - name: No file with syscall found, set path to /etc/audit/rules.d/perm_mod.rules
      ansible.builtin.set_fact: audit_file="/etc/audit/rules.d/perm_mod.rules"
      when: found_paths | length == 0

    - name: Declare found syscalls
      ansible.builtin.set_fact: syscalls_found="{{ find_command.results | selectattr('matched')
        | map(attribute='item') | list }}"

    - name: Declare missing syscalls
      ansible.builtin.set_fact: missing_syscalls="{{ syscalls | difference(syscalls_found)
        }}"

    - name: Replace the audit rule in {{ audit_file }}
      ansible.builtin.lineinfile:
        path: '{{ audit_file }}'
        regexp: (-a always,exit -F arch=b64)(?=.*(?:(?:-S |,)(?:{{ syscalls_per_file[audit_file]
          | join("|") }}))\b)((?:( -S |,)\w+)+)( -F auid>=1000 -F auid!=unset (?:-k
          |-F key=)\w+)
        line: \1\2\3{{ missing_syscalls | join("\3") }}\4
        backrefs: true
        state: present
        mode: g-rwx,o-rwx
      when: syscalls_found | length > 0 and missing_syscalls | length > 0

    - name: Add the audit rule to {{ audit_file }}
      ansible.builtin.lineinfile:
        path: '{{ audit_file }}'
        line: -a always,exit -F arch=b64 -S {{ syscalls | join(',') }} -F auid>=1000
          -F auid!=unset -F key=perm_mod
        create: true
        mode: g-rwx,o-rwx
        state: present
      when: syscalls_found | length == 0

    - name: Declare list of syscalls
      ansible.builtin.set_fact:
        syscalls:
        - umount2
        syscall_grouping: []

    - name: Check existence of umount2 in /etc/audit/audit.rules
      ansible.builtin.find:
        paths: /etc/audit
        contains: -a always,exit -F arch=b64(( -S |,)\w+)*(( -S |,){{ item }})+((
          -S |,)\w+)* -F auid>=1000 -F auid!=unset (-k\s+|-F\s+key=)\S+\s*$
        patterns: audit.rules
      register: find_command
      loop: '{{ (syscall_grouping + syscalls) | unique }}'

    - name: Set path to /etc/audit/audit.rules
      ansible.builtin.set_fact: audit_file="/etc/audit/audit.rules"

    - name: Declare found syscalls
      ansible.builtin.set_fact: syscalls_found="{{ find_command.results | selectattr('matched')
        | map(attribute='item') | list }}"

    - name: Declare missing syscalls
      ansible.builtin.set_fact: missing_syscalls="{{ syscalls | difference(syscalls_found)
        }}"

    - name: Replace the audit rule in {{ audit_file }}
      ansible.builtin.lineinfile:
        path: '{{ audit_file }}'
        regexp: (-a always,exit -F arch=b64)(?=.*(?:(?:-S |,)(?:{{ syscalls_found
          | join("|") }}))\b)((?:( -S |,)\w+)+)( -F auid>=1000 -F auid!=unset (?:-k
          |-F key=)\w+)
        line: \1\2\3{{ missing_syscalls | join("\3") }}\4
        backrefs: true
        state: present
        mode: g-rwx,o-rwx
      when: syscalls_found | length > 0 and missing_syscalls | length > 0

    - name: Add the audit rule to {{ audit_file }}
      ansible.builtin.lineinfile:
        path: '{{ audit_file }}'
        line: -a always,exit -F arch=b64 -S {{ syscalls | join(',') }} -F auid>=1000
          -F auid!=unset -F key=perm_mod
        create: true
        mode: g-rwx,o-rwx
        state: present
      when: syscalls_found | length == 0
    when:
    - '"audit" in ansible_facts.packages'
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - audit_arch == "b64"
    tags:
    - DISA-STIG-OL09-00-000845
    - audit_rules_dac_modification_umount2
    - low_complexity
    - low_disruption
    - medium_severity
    - reboot_required
    - restrict_strategy

  - name: Record Any Attempts to Run chacl - Perform remediation of Audit rules for
      /usr/bin/chacl
    block:

    - name: Declare list of syscalls
      ansible.builtin.set_fact:
        syscalls: []
        syscall_grouping: []

    - name: Check existence of  in /etc/audit/rules.d/
      ansible.builtin.find:
        paths: /etc/audit/rules.d
        contains: -a always,exit(( -S |,)\w+)*(( -S |,){{ item }})+(( -S |,)\w+)*
          -F path=/usr/bin/chacl -F perm=x -F auid>=1000 -F auid!=unset (-k\s+|-F\s+key=)\S+\s*$
        patterns: '*.rules'
      register: find_command
      loop: '{{ (syscall_grouping + syscalls) | unique }}'

    - name: Reset syscalls found per file
      ansible.builtin.set_fact:
        syscalls_per_file: {}
        found_paths_dict: {}

    - name: Declare syscalls found per file
      ansible.builtin.set_fact: syscalls_per_file="{{ syscalls_per_file | combine(
        {item.files[0].path :[item.item] + syscalls_per_file.get(item.files[0].path,
        []) } ) }}"
      loop: '{{ find_command.results | selectattr(''matched'') | list }}'

    - name: Declare files where syscalls were found
      ansible.builtin.set_fact: found_paths="{{ find_command.results | map(attribute='files')
        | flatten | map(attribute='path') | list }}"

    - name: Count occurrences of syscalls in paths
      ansible.builtin.set_fact: found_paths_dict="{{ found_paths_dict | combine({
        item:1+found_paths_dict.get(item, 0) }) }}"
      loop: '{{ find_command.results | map(attribute=''files'') | flatten | map(attribute=''path'')
        | list }}'

    - name: Get path with most syscalls
      ansible.builtin.set_fact: audit_file="{{ (found_paths_dict | dict2items() |
        sort(attribute='value') | last).key }}"
      when: found_paths | length >= 1

    - name: No file with syscall found, set path to /etc/audit/rules.d/privileged.rules
      ansible.builtin.set_fact: audit_file="/etc/audit/rules.d/privileged.rules"
      when: found_paths | length == 0

    - name: Declare found syscalls
      ansible.builtin.set_fact: syscalls_found="{{ find_command.results | selectattr('matched')
        | map(attribute='item') | list }}"

    - name: Declare missing syscalls
      ansible.builtin.set_fact: missing_syscalls="{{ syscalls | difference(syscalls_found)
        }}"

    - name: Replace the audit rule in {{ audit_file }}
      ansible.builtin.lineinfile:
        path: '{{ audit_file }}'
        regexp: (-a always,exit)(?=.*(?:(?:-S |,)(?:{{ syscalls_per_file[audit_file]
          | join("|") }}))\b)((?:( -S |,)\w+)+)( -F path=/usr/bin/chacl -F perm=x
          -F auid>=1000 -F auid!=unset (?:-k |-F key=)\w+)
        line: \1\2\3{{ missing_syscalls | join("\3") }}\4
        backrefs: true
        state: present
        mode: g-rwx,o-rwx
      when: syscalls_found | length > 0 and missing_syscalls | length > 0

    - name: Add the audit rule to {{ audit_file }}
      ansible.builtin.lineinfile:
        path: '{{ audit_file }}'
        line: -a always,exit{{ syscalls | join(',') }} -F path=/usr/bin/chacl -F perm=x
          -F auid>=1000 -F auid!=unset -F key=privileged
        create: true
        mode: g-rwx,o-rwx
        state: present
      when: syscalls_found | length == 0

    - name: Declare list of syscalls
      ansible.builtin.set_fact:
        syscalls: []
        syscall_grouping: []

    - name: Check existence of  in /etc/audit/audit.rules
      ansible.builtin.find:
        paths: /etc/audit
        contains: -a always,exit(( -S |,)\w+)*(( -S |,){{ item }})+(( -S |,)\w+)*
          -F path=/usr/bin/chacl -F perm=x -F auid>=1000 -F auid!=unset (-k\s+|-F\s+key=)\S+\s*$
        patterns: audit.rules
      register: find_command
      loop: '{{ (syscall_grouping + syscalls) | unique }}'

    - name: Set path to /etc/audit/audit.rules
      ansible.builtin.set_fact: audit_file="/etc/audit/audit.rules"

    - name: Declare found syscalls
      ansible.builtin.set_fact: syscalls_found="{{ find_command.results | selectattr('matched')
        | map(attribute='item') | list }}"

    - name: Declare missing syscalls
      ansible.builtin.set_fact: missing_syscalls="{{ syscalls | difference(syscalls_found)
        }}"

    - name: Replace the audit rule in {{ audit_file }}
      ansible.builtin.lineinfile:
        path: '{{ audit_file }}'
        regexp: (-a always,exit)(?=.*(?:(?:-S |,)(?:{{ syscalls_found | join("|")
          }}))\b)((?:( -S |,)\w+)+)( -F path=/usr/bin/chacl -F perm=x -F auid>=1000
          -F auid!=unset (?:-k |-F key=)\w+)
        line: \1\2\3{{ missing_syscalls | join("\3") }}\4
        backrefs: true
        state: present
        mode: g-rwx,o-rwx
      when: syscalls_found | length > 0 and missing_syscalls | length > 0

    - name: Add the audit rule to {{ audit_file }}
      ansible.builtin.lineinfile:
        path: '{{ audit_file }}'
        line: -a always,exit{{ syscalls | join(',') }} -F path=/usr/bin/chacl -F perm=x
          -F auid>=1000 -F auid!=unset -F key=privileged
        create: true
        mode: g-rwx,o-rwx
        state: present
      when: syscalls_found | length == 0
    when:
    - '"audit" in ansible_facts.packages'
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-000665
    - audit_rules_execution_chacl
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Record Any Attempts to Run setfacl - Perform remediation of Audit rules
      for /usr/bin/setfacl
    block:

    - name: Declare list of syscalls
      ansible.builtin.set_fact:
        syscalls: []
        syscall_grouping: []

    - name: Check existence of  in /etc/audit/rules.d/
      ansible.builtin.find:
        paths: /etc/audit/rules.d
        contains: -a always,exit(( -S |,)\w+)*(( -S |,){{ item }})+(( -S |,)\w+)*
          -F path=/usr/bin/setfacl -F perm=x -F auid>=1000 -F auid!=unset (-k\s+|-F\s+key=)\S+\s*$
        patterns: '*.rules'
      register: find_command
      loop: '{{ (syscall_grouping + syscalls) | unique }}'

    - name: Reset syscalls found per file
      ansible.builtin.set_fact:
        syscalls_per_file: {}
        found_paths_dict: {}

    - name: Declare syscalls found per file
      ansible.builtin.set_fact: syscalls_per_file="{{ syscalls_per_file | combine(
        {item.files[0].path :[item.item] + syscalls_per_file.get(item.files[0].path,
        []) } ) }}"
      loop: '{{ find_command.results | selectattr(''matched'') | list }}'

    - name: Declare files where syscalls were found
      ansible.builtin.set_fact: found_paths="{{ find_command.results | map(attribute='files')
        | flatten | map(attribute='path') | list }}"

    - name: Count occurrences of syscalls in paths
      ansible.builtin.set_fact: found_paths_dict="{{ found_paths_dict | combine({
        item:1+found_paths_dict.get(item, 0) }) }}"
      loop: '{{ find_command.results | map(attribute=''files'') | flatten | map(attribute=''path'')
        | list }}'

    - name: Get path with most syscalls
      ansible.builtin.set_fact: audit_file="{{ (found_paths_dict | dict2items() |
        sort(attribute='value') | last).key }}"
      when: found_paths | length >= 1

    - name: No file with syscall found, set path to /etc/audit/rules.d/privileged.rules
      ansible.builtin.set_fact: audit_file="/etc/audit/rules.d/privileged.rules"
      when: found_paths | length == 0

    - name: Declare found syscalls
      ansible.builtin.set_fact: syscalls_found="{{ find_command.results | selectattr('matched')
        | map(attribute='item') | list }}"

    - name: Declare missing syscalls
      ansible.builtin.set_fact: missing_syscalls="{{ syscalls | difference(syscalls_found)
        }}"

    - name: Replace the audit rule in {{ audit_file }}
      ansible.builtin.lineinfile:
        path: '{{ audit_file }}'
        regexp: (-a always,exit)(?=.*(?:(?:-S |,)(?:{{ syscalls_per_file[audit_file]
          | join("|") }}))\b)((?:( -S |,)\w+)+)( -F path=/usr/bin/setfacl -F perm=x
          -F auid>=1000 -F auid!=unset (?:-k |-F key=)\w+)
        line: \1\2\3{{ missing_syscalls | join("\3") }}\4
        backrefs: true
        state: present
        mode: g-rwx,o-rwx
      when: syscalls_found | length > 0 and missing_syscalls | length > 0

    - name: Add the audit rule to {{ audit_file }}
      ansible.builtin.lineinfile:
        path: '{{ audit_file }}'
        line: -a always,exit{{ syscalls | join(',') }} -F path=/usr/bin/setfacl -F
          perm=x -F auid>=1000 -F auid!=unset -F key=privileged
        create: true
        mode: g-rwx,o-rwx
        state: present
      when: syscalls_found | length == 0

    - name: Declare list of syscalls
      ansible.builtin.set_fact:
        syscalls: []
        syscall_grouping: []

    - name: Check existence of  in /etc/audit/audit.rules
      ansible.builtin.find:
        paths: /etc/audit
        contains: -a always,exit(( -S |,)\w+)*(( -S |,){{ item }})+(( -S |,)\w+)*
          -F path=/usr/bin/setfacl -F perm=x -F auid>=1000 -F auid!=unset (-k\s+|-F\s+key=)\S+\s*$
        patterns: audit.rules
      register: find_command
      loop: '{{ (syscall_grouping + syscalls) | unique }}'

    - name: Set path to /etc/audit/audit.rules
      ansible.builtin.set_fact: audit_file="/etc/audit/audit.rules"

    - name: Declare found syscalls
      ansible.builtin.set_fact: syscalls_found="{{ find_command.results | selectattr('matched')
        | map(attribute='item') | list }}"

    - name: Declare missing syscalls
      ansible.builtin.set_fact: missing_syscalls="{{ syscalls | difference(syscalls_found)
        }}"

    - name: Replace the audit rule in {{ audit_file }}
      ansible.builtin.lineinfile:
        path: '{{ audit_file }}'
        regexp: (-a always,exit)(?=.*(?:(?:-S |,)(?:{{ syscalls_found | join("|")
          }}))\b)((?:( -S |,)\w+)+)( -F path=/usr/bin/setfacl -F perm=x -F auid>=1000
          -F auid!=unset (?:-k |-F key=)\w+)
        line: \1\2\3{{ missing_syscalls | join("\3") }}\4
        backrefs: true
        state: present
        mode: g-rwx,o-rwx
      when: syscalls_found | length > 0 and missing_syscalls | length > 0

    - name: Add the audit rule to {{ audit_file }}
      ansible.builtin.lineinfile:
        path: '{{ audit_file }}'
        line: -a always,exit{{ syscalls | join(',') }} -F path=/usr/bin/setfacl -F
          perm=x -F auid>=1000 -F auid!=unset -F key=privileged
        create: true
        mode: g-rwx,o-rwx
        state: present
      when: syscalls_found | length == 0
    when:
    - '"audit" in ansible_facts.packages'
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-000560
    - audit_rules_execution_setfacl
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Record Any Attempts to Run chcon - Perform remediation of Audit rules for
      /usr/bin/chcon
    block:

    - name: Declare list of syscalls
      ansible.builtin.set_fact:
        syscalls: []
        syscall_grouping: []

    - name: Check existence of  in /etc/audit/rules.d/
      ansible.builtin.find:
        paths: /etc/audit/rules.d
        contains: -a always,exit(( -S |,)\w+)*(( -S |,){{ item }})+(( -S |,)\w+)*
          -F path=/usr/bin/chcon -F perm=x -F auid>=1000 -F auid!=unset (-k\s+|-F\s+key=)\S+\s*$
        patterns: '*.rules'
      register: find_command
      loop: '{{ (syscall_grouping + syscalls) | unique }}'

    - name: Reset syscalls found per file
      ansible.builtin.set_fact:
        syscalls_per_file: {}
        found_paths_dict: {}

    - name: Declare syscalls found per file
      ansible.builtin.set_fact: syscalls_per_file="{{ syscalls_per_file | combine(
        {item.files[0].path :[item.item] + syscalls_per_file.get(item.files[0].path,
        []) } ) }}"
      loop: '{{ find_command.results | selectattr(''matched'') | list }}'

    - name: Declare files where syscalls were found
      ansible.builtin.set_fact: found_paths="{{ find_command.results | map(attribute='files')
        | flatten | map(attribute='path') | list }}"

    - name: Count occurrences of syscalls in paths
      ansible.builtin.set_fact: found_paths_dict="{{ found_paths_dict | combine({
        item:1+found_paths_dict.get(item, 0) }) }}"
      loop: '{{ find_command.results | map(attribute=''files'') | flatten | map(attribute=''path'')
        | list }}'

    - name: Get path with most syscalls
      ansible.builtin.set_fact: audit_file="{{ (found_paths_dict | dict2items() |
        sort(attribute='value') | last).key }}"
      when: found_paths | length >= 1

    - name: No file with syscall found, set path to /etc/audit/rules.d/privileged.rules
      ansible.builtin.set_fact: audit_file="/etc/audit/rules.d/privileged.rules"
      when: found_paths | length == 0

    - name: Declare found syscalls
      ansible.builtin.set_fact: syscalls_found="{{ find_command.results | selectattr('matched')
        | map(attribute='item') | list }}"

    - name: Declare missing syscalls
      ansible.builtin.set_fact: missing_syscalls="{{ syscalls | difference(syscalls_found)
        }}"

    - name: Replace the audit rule in {{ audit_file }}
      ansible.builtin.lineinfile:
        path: '{{ audit_file }}'
        regexp: (-a always,exit)(?=.*(?:(?:-S |,)(?:{{ syscalls_per_file[audit_file]
          | join("|") }}))\b)((?:( -S |,)\w+)+)( -F path=/usr/bin/chcon -F perm=x
          -F auid>=1000 -F auid!=unset (?:-k |-F key=)\w+)
        line: \1\2\3{{ missing_syscalls | join("\3") }}\4
        backrefs: true
        state: present
        mode: g-rwx,o-rwx
      when: syscalls_found | length > 0 and missing_syscalls | length > 0

    - name: Add the audit rule to {{ audit_file }}
      ansible.builtin.lineinfile:
        path: '{{ audit_file }}'
        line: -a always,exit{{ syscalls | join(',') }} -F path=/usr/bin/chcon -F perm=x
          -F auid>=1000 -F auid!=unset -F key=privileged
        create: true
        mode: g-rwx,o-rwx
        state: present
      when: syscalls_found | length == 0

    - name: Declare list of syscalls
      ansible.builtin.set_fact:
        syscalls: []
        syscall_grouping: []

    - name: Check existence of  in /etc/audit/audit.rules
      ansible.builtin.find:
        paths: /etc/audit
        contains: -a always,exit(( -S |,)\w+)*(( -S |,){{ item }})+(( -S |,)\w+)*
          -F path=/usr/bin/chcon -F perm=x -F auid>=1000 -F auid!=unset (-k\s+|-F\s+key=)\S+\s*$
        patterns: audit.rules
      register: find_command
      loop: '{{ (syscall_grouping + syscalls) | unique }}'

    - name: Set path to /etc/audit/audit.rules
      ansible.builtin.set_fact: audit_file="/etc/audit/audit.rules"

    - name: Declare found syscalls
      ansible.builtin.set_fact: syscalls_found="{{ find_command.results | selectattr('matched')
        | map(attribute='item') | list }}"

    - name: Declare missing syscalls
      ansible.builtin.set_fact: missing_syscalls="{{ syscalls | difference(syscalls_found)
        }}"

    - name: Replace the audit rule in {{ audit_file }}
      ansible.builtin.lineinfile:
        path: '{{ audit_file }}'
        regexp: (-a always,exit)(?=.*(?:(?:-S |,)(?:{{ syscalls_found | join("|")
          }}))\b)((?:( -S |,)\w+)+)( -F path=/usr/bin/chcon -F perm=x -F auid>=1000
          -F auid!=unset (?:-k |-F key=)\w+)
        line: \1\2\3{{ missing_syscalls | join("\3") }}\4
        backrefs: true
        state: present
        mode: g-rwx,o-rwx
      when: syscalls_found | length > 0 and missing_syscalls | length > 0

    - name: Add the audit rule to {{ audit_file }}
      ansible.builtin.lineinfile:
        path: '{{ audit_file }}'
        line: -a always,exit{{ syscalls | join(',') }} -F path=/usr/bin/chcon -F perm=x
          -F auid>=1000 -F auid!=unset -F key=privileged
        create: true
        mode: g-rwx,o-rwx
        state: present
      when: syscalls_found | length == 0
    when:
    - '"audit" in ansible_facts.packages'
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-000555
    - NIST-800-171-3.1.7
    - NIST-800-53-AC-6(9)
    - NIST-800-53-AU-12(c)
    - NIST-800-53-AU-2(d)
    - NIST-800-53-CM-6(a)
    - audit_rules_execution_chcon
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Record Any Attempts to Run semanage - Perform remediation of Audit rules
      for /usr/sbin/semanage
    block:

    - name: Declare list of syscalls
      ansible.builtin.set_fact:
        syscalls: []
        syscall_grouping: []

    - name: Check existence of  in /etc/audit/rules.d/
      ansible.builtin.find:
        paths: /etc/audit/rules.d
        contains: -a always,exit(( -S |,)\w+)*(( -S |,){{ item }})+(( -S |,)\w+)*
          -F path=/usr/sbin/semanage -F perm=x -F auid>=1000 -F auid!=unset (-k\s+|-F\s+key=)\S+\s*$
        patterns: '*.rules'
      register: find_command
      loop: '{{ (syscall_grouping + syscalls) | unique }}'

    - name: Reset syscalls found per file
      ansible.builtin.set_fact:
        syscalls_per_file: {}
        found_paths_dict: {}

    - name: Declare syscalls found per file
      ansible.builtin.set_fact: syscalls_per_file="{{ syscalls_per_file | combine(
        {item.files[0].path :[item.item] + syscalls_per_file.get(item.files[0].path,
        []) } ) }}"
      loop: '{{ find_command.results | selectattr(''matched'') | list }}'

    - name: Declare files where syscalls were found
      ansible.builtin.set_fact: found_paths="{{ find_command.results | map(attribute='files')
        | flatten | map(attribute='path') | list }}"

    - name: Count occurrences of syscalls in paths
      ansible.builtin.set_fact: found_paths_dict="{{ found_paths_dict | combine({
        item:1+found_paths_dict.get(item, 0) }) }}"
      loop: '{{ find_command.results | map(attribute=''files'') | flatten | map(attribute=''path'')
        | list }}'

    - name: Get path with most syscalls
      ansible.builtin.set_fact: audit_file="{{ (found_paths_dict | dict2items() |
        sort(attribute='value') | last).key }}"
      when: found_paths | length >= 1

    - name: No file with syscall found, set path to /etc/audit/rules.d/privileged.rules
      ansible.builtin.set_fact: audit_file="/etc/audit/rules.d/privileged.rules"
      when: found_paths | length == 0

    - name: Declare found syscalls
      ansible.builtin.set_fact: syscalls_found="{{ find_command.results | selectattr('matched')
        | map(attribute='item') | list }}"

    - name: Declare missing syscalls
      ansible.builtin.set_fact: missing_syscalls="{{ syscalls | difference(syscalls_found)
        }}"

    - name: Replace the audit rule in {{ audit_file }}
      ansible.builtin.lineinfile:
        path: '{{ audit_file }}'
        regexp: (-a always,exit)(?=.*(?:(?:-S |,)(?:{{ syscalls_per_file[audit_file]
          | join("|") }}))\b)((?:( -S |,)\w+)+)( -F path=/usr/sbin/semanage -F perm=x
          -F auid>=1000 -F auid!=unset (?:-k |-F key=)\w+)
        line: \1\2\3{{ missing_syscalls | join("\3") }}\4
        backrefs: true
        state: present
        mode: g-rwx,o-rwx
      when: syscalls_found | length > 0 and missing_syscalls | length > 0

    - name: Add the audit rule to {{ audit_file }}
      ansible.builtin.lineinfile:
        path: '{{ audit_file }}'
        line: -a always,exit{{ syscalls | join(',') }} -F path=/usr/sbin/semanage
          -F perm=x -F auid>=1000 -F auid!=unset -F key=privileged
        create: true
        mode: g-rwx,o-rwx
        state: present
      when: syscalls_found | length == 0

    - name: Declare list of syscalls
      ansible.builtin.set_fact:
        syscalls: []
        syscall_grouping: []

    - name: Check existence of  in /etc/audit/audit.rules
      ansible.builtin.find:
        paths: /etc/audit
        contains: -a always,exit(( -S |,)\w+)*(( -S |,){{ item }})+(( -S |,)\w+)*
          -F path=/usr/sbin/semanage -F perm=x -F auid>=1000 -F auid!=unset (-k\s+|-F\s+key=)\S+\s*$
        patterns: audit.rules
      register: find_command
      loop: '{{ (syscall_grouping + syscalls) | unique }}'

    - name: Set path to /etc/audit/audit.rules
      ansible.builtin.set_fact: audit_file="/etc/audit/audit.rules"

    - name: Declare found syscalls
      ansible.builtin.set_fact: syscalls_found="{{ find_command.results | selectattr('matched')
        | map(attribute='item') | list }}"

    - name: Declare missing syscalls
      ansible.builtin.set_fact: missing_syscalls="{{ syscalls | difference(syscalls_found)
        }}"

    - name: Replace the audit rule in {{ audit_file }}
      ansible.builtin.lineinfile:
        path: '{{ audit_file }}'
        regexp: (-a always,exit)(?=.*(?:(?:-S |,)(?:{{ syscalls_found | join("|")
          }}))\b)((?:( -S |,)\w+)+)( -F path=/usr/sbin/semanage -F perm=x -F auid>=1000
          -F auid!=unset (?:-k |-F key=)\w+)
        line: \1\2\3{{ missing_syscalls | join("\3") }}\4
        backrefs: true
        state: present
        mode: g-rwx,o-rwx
      when: syscalls_found | length > 0 and missing_syscalls | length > 0

    - name: Add the audit rule to {{ audit_file }}
      ansible.builtin.lineinfile:
        path: '{{ audit_file }}'
        line: -a always,exit{{ syscalls | join(',') }} -F path=/usr/sbin/semanage
          -F perm=x -F auid>=1000 -F auid!=unset -F key=privileged
        create: true
        mode: g-rwx,o-rwx
        state: present
      when: syscalls_found | length == 0
    when:
    - '"audit" in ansible_facts.packages'
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-000650
    - NIST-800-171-3.1.7
    - NIST-800-53-AC-2(4)
    - NIST-800-53-AC-6(9)
    - NIST-800-53-AU-12(c)
    - NIST-800-53-AU-2(d)
    - NIST-800-53-CM-6(a)
    - audit_rules_execution_semanage
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Record Any Attempts to Run setfiles - Perform remediation of Audit rules
      for /usr/sbin/setfiles
    block:

    - name: Declare list of syscalls
      ansible.builtin.set_fact:
        syscalls: []
        syscall_grouping: []

    - name: Check existence of  in /etc/audit/rules.d/
      ansible.builtin.find:
        paths: /etc/audit/rules.d
        contains: -a always,exit(( -S |,)\w+)*(( -S |,){{ item }})+(( -S |,)\w+)*
          -F path=/usr/sbin/setfiles -F perm=x -F auid>=1000 -F auid!=unset (-k\s+|-F\s+key=)\S+\s*$
        patterns: '*.rules'
      register: find_command
      loop: '{{ (syscall_grouping + syscalls) | unique }}'

    - name: Reset syscalls found per file
      ansible.builtin.set_fact:
        syscalls_per_file: {}
        found_paths_dict: {}

    - name: Declare syscalls found per file
      ansible.builtin.set_fact: syscalls_per_file="{{ syscalls_per_file | combine(
        {item.files[0].path :[item.item] + syscalls_per_file.get(item.files[0].path,
        []) } ) }}"
      loop: '{{ find_command.results | selectattr(''matched'') | list }}'

    - name: Declare files where syscalls were found
      ansible.builtin.set_fact: found_paths="{{ find_command.results | map(attribute='files')
        | flatten | map(attribute='path') | list }}"

    - name: Count occurrences of syscalls in paths
      ansible.builtin.set_fact: found_paths_dict="{{ found_paths_dict | combine({
        item:1+found_paths_dict.get(item, 0) }) }}"
      loop: '{{ find_command.results | map(attribute=''files'') | flatten | map(attribute=''path'')
        | list }}'

    - name: Get path with most syscalls
      ansible.builtin.set_fact: audit_file="{{ (found_paths_dict | dict2items() |
        sort(attribute='value') | last).key }}"
      when: found_paths | length >= 1

    - name: No file with syscall found, set path to /etc/audit/rules.d/privileged.rules
      ansible.builtin.set_fact: audit_file="/etc/audit/rules.d/privileged.rules"
      when: found_paths | length == 0

    - name: Declare found syscalls
      ansible.builtin.set_fact: syscalls_found="{{ find_command.results | selectattr('matched')
        | map(attribute='item') | list }}"

    - name: Declare missing syscalls
      ansible.builtin.set_fact: missing_syscalls="{{ syscalls | difference(syscalls_found)
        }}"

    - name: Replace the audit rule in {{ audit_file }}
      ansible.builtin.lineinfile:
        path: '{{ audit_file }}'
        regexp: (-a always,exit)(?=.*(?:(?:-S |,)(?:{{ syscalls_per_file[audit_file]
          | join("|") }}))\b)((?:( -S |,)\w+)+)( -F path=/usr/sbin/setfiles -F perm=x
          -F auid>=1000 -F auid!=unset (?:-k |-F key=)\w+)
        line: \1\2\3{{ missing_syscalls | join("\3") }}\4
        backrefs: true
        state: present
        mode: g-rwx,o-rwx
      when: syscalls_found | length > 0 and missing_syscalls | length > 0

    - name: Add the audit rule to {{ audit_file }}
      ansible.builtin.lineinfile:
        path: '{{ audit_file }}'
        line: -a always,exit{{ syscalls | join(',') }} -F path=/usr/sbin/setfiles
          -F perm=x -F auid>=1000 -F auid!=unset -F key=privileged
        create: true
        mode: g-rwx,o-rwx
        state: present
      when: syscalls_found | length == 0

    - name: Declare list of syscalls
      ansible.builtin.set_fact:
        syscalls: []
        syscall_grouping: []

    - name: Check existence of  in /etc/audit/audit.rules
      ansible.builtin.find:
        paths: /etc/audit
        contains: -a always,exit(( -S |,)\w+)*(( -S |,){{ item }})+(( -S |,)\w+)*
          -F path=/usr/sbin/setfiles -F perm=x -F auid>=1000 -F auid!=unset (-k\s+|-F\s+key=)\S+\s*$
        patterns: audit.rules
      register: find_command
      loop: '{{ (syscall_grouping + syscalls) | unique }}'

    - name: Set path to /etc/audit/audit.rules
      ansible.builtin.set_fact: audit_file="/etc/audit/audit.rules"

    - name: Declare found syscalls
      ansible.builtin.set_fact: syscalls_found="{{ find_command.results | selectattr('matched')
        | map(attribute='item') | list }}"

    - name: Declare missing syscalls
      ansible.builtin.set_fact: missing_syscalls="{{ syscalls | difference(syscalls_found)
        }}"

    - name: Replace the audit rule in {{ audit_file }}
      ansible.builtin.lineinfile:
        path: '{{ audit_file }}'
        regexp: (-a always,exit)(?=.*(?:(?:-S |,)(?:{{ syscalls_found | join("|")
          }}))\b)((?:( -S |,)\w+)+)( -F path=/usr/sbin/setfiles -F perm=x -F auid>=1000
          -F auid!=unset (?:-k |-F key=)\w+)
        line: \1\2\3{{ missing_syscalls | join("\3") }}\4
        backrefs: true
        state: present
        mode: g-rwx,o-rwx
      when: syscalls_found | length > 0 and missing_syscalls | length > 0

    - name: Add the audit rule to {{ audit_file }}
      ansible.builtin.lineinfile:
        path: '{{ audit_file }}'
        line: -a always,exit{{ syscalls | join(',') }} -F path=/usr/sbin/setfiles
          -F perm=x -F auid>=1000 -F auid!=unset -F key=privileged
        create: true
        mode: g-rwx,o-rwx
        state: present
      when: syscalls_found | length == 0
    when:
    - '"audit" in ansible_facts.packages'
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-000655
    - NIST-800-53-AC-6(9)
    - NIST-800-53-AU-12(c)
    - NIST-800-53-AU-2(d)
    - NIST-800-53-CM-6(a)
    - audit_rules_execution_setfiles
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Record Any Attempts to Run setsebool - Perform remediation of Audit rules
      for /usr/sbin/setsebool
    block:

    - name: Declare list of syscalls
      ansible.builtin.set_fact:
        syscalls: []
        syscall_grouping: []

    - name: Check existence of  in /etc/audit/rules.d/
      ansible.builtin.find:
        paths: /etc/audit/rules.d
        contains: -a always,exit(( -S |,)\w+)*(( -S |,){{ item }})+(( -S |,)\w+)*
          -F path=/usr/sbin/setsebool -F perm=x -F auid>=1000 -F auid!=unset (-k\s+|-F\s+key=)\S+\s*$
        patterns: '*.rules'
      register: find_command
      loop: '{{ (syscall_grouping + syscalls) | unique }}'

    - name: Reset syscalls found per file
      ansible.builtin.set_fact:
        syscalls_per_file: {}
        found_paths_dict: {}

    - name: Declare syscalls found per file
      ansible.builtin.set_fact: syscalls_per_file="{{ syscalls_per_file | combine(
        {item.files[0].path :[item.item] + syscalls_per_file.get(item.files[0].path,
        []) } ) }}"
      loop: '{{ find_command.results | selectattr(''matched'') | list }}'

    - name: Declare files where syscalls were found
      ansible.builtin.set_fact: found_paths="{{ find_command.results | map(attribute='files')
        | flatten | map(attribute='path') | list }}"

    - name: Count occurrences of syscalls in paths
      ansible.builtin.set_fact: found_paths_dict="{{ found_paths_dict | combine({
        item:1+found_paths_dict.get(item, 0) }) }}"
      loop: '{{ find_command.results | map(attribute=''files'') | flatten | map(attribute=''path'')
        | list }}'

    - name: Get path with most syscalls
      ansible.builtin.set_fact: audit_file="{{ (found_paths_dict | dict2items() |
        sort(attribute='value') | last).key }}"
      when: found_paths | length >= 1

    - name: No file with syscall found, set path to /etc/audit/rules.d/privileged.rules
      ansible.builtin.set_fact: audit_file="/etc/audit/rules.d/privileged.rules"
      when: found_paths | length == 0

    - name: Declare found syscalls
      ansible.builtin.set_fact: syscalls_found="{{ find_command.results | selectattr('matched')
        | map(attribute='item') | list }}"

    - name: Declare missing syscalls
      ansible.builtin.set_fact: missing_syscalls="{{ syscalls | difference(syscalls_found)
        }}"

    - name: Replace the audit rule in {{ audit_file }}
      ansible.builtin.lineinfile:
        path: '{{ audit_file }}'
        regexp: (-a always,exit)(?=.*(?:(?:-S |,)(?:{{ syscalls_per_file[audit_file]
          | join("|") }}))\b)((?:( -S |,)\w+)+)( -F path=/usr/sbin/setsebool -F perm=x
          -F auid>=1000 -F auid!=unset (?:-k |-F key=)\w+)
        line: \1\2\3{{ missing_syscalls | join("\3") }}\4
        backrefs: true
        state: present
        mode: g-rwx,o-rwx
      when: syscalls_found | length > 0 and missing_syscalls | length > 0

    - name: Add the audit rule to {{ audit_file }}
      ansible.builtin.lineinfile:
        path: '{{ audit_file }}'
        line: -a always,exit{{ syscalls | join(',') }} -F path=/usr/sbin/setsebool
          -F perm=x -F auid>=1000 -F auid!=unset -F key=privileged
        create: true
        mode: g-rwx,o-rwx
        state: present
      when: syscalls_found | length == 0

    - name: Declare list of syscalls
      ansible.builtin.set_fact:
        syscalls: []
        syscall_grouping: []

    - name: Check existence of  in /etc/audit/audit.rules
      ansible.builtin.find:
        paths: /etc/audit
        contains: -a always,exit(( -S |,)\w+)*(( -S |,){{ item }})+(( -S |,)\w+)*
          -F path=/usr/sbin/setsebool -F perm=x -F auid>=1000 -F auid!=unset (-k\s+|-F\s+key=)\S+\s*$
        patterns: audit.rules
      register: find_command
      loop: '{{ (syscall_grouping + syscalls) | unique }}'

    - name: Set path to /etc/audit/audit.rules
      ansible.builtin.set_fact: audit_file="/etc/audit/audit.rules"

    - name: Declare found syscalls
      ansible.builtin.set_fact: syscalls_found="{{ find_command.results | selectattr('matched')
        | map(attribute='item') | list }}"

    - name: Declare missing syscalls
      ansible.builtin.set_fact: missing_syscalls="{{ syscalls | difference(syscalls_found)
        }}"

    - name: Replace the audit rule in {{ audit_file }}
      ansible.builtin.lineinfile:
        path: '{{ audit_file }}'
        regexp: (-a always,exit)(?=.*(?:(?:-S |,)(?:{{ syscalls_found | join("|")
          }}))\b)((?:( -S |,)\w+)+)( -F path=/usr/sbin/setsebool -F perm=x -F auid>=1000
          -F auid!=unset (?:-k |-F key=)\w+)
        line: \1\2\3{{ missing_syscalls | join("\3") }}\4
        backrefs: true
        state: present
        mode: g-rwx,o-rwx
      when: syscalls_found | length > 0 and missing_syscalls | length > 0

    - name: Add the audit rule to {{ audit_file }}
      ansible.builtin.lineinfile:
        path: '{{ audit_file }}'
        line: -a always,exit{{ syscalls | join(',') }} -F path=/usr/sbin/setsebool
          -F perm=x -F auid>=1000 -F auid!=unset -F key=privileged
        create: true
        mode: g-rwx,o-rwx
        state: present
      when: syscalls_found | length == 0
    when:
    - '"audit" in ansible_facts.packages'
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-000660
    - NIST-800-171-3.1.7
    - NIST-800-53-AC-6(9)
    - NIST-800-53-AU-12(c)
    - NIST-800-53-AU-2(d)
    - NIST-800-53-CM-6(a)
    - audit_rules_execution_setsebool
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Set architecture for audit rename tasks
    ansible.builtin.set_fact:
      audit_arch: b64
    when:
    - '"audit" in ansible_facts.packages'
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - not ( ansible_architecture == "aarch64" )
    - ansible_architecture == "aarch64" or ansible_architecture == "ppc64" or ansible_architecture
      == "ppc64le" or ansible_architecture == "s390x" or ansible_architecture == "x86_64"
    tags:
    - DISA-STIG-OL09-00-000680
    - NIST-800-171-3.1.7
    - NIST-800-53-AU-12(c)
    - NIST-800-53-AU-2(d)
    - NIST-800-53-CM-6(a)
    - PCI-DSS-Req-10.2.7
    - PCI-DSSv4-10.2
    - PCI-DSSv4-10.2.1
    - PCI-DSSv4-10.2.1.7
    - audit_rules_file_deletion_events_rename
    - low_complexity
    - low_disruption
    - medium_severity
    - reboot_required
    - restrict_strategy

  - name: Perform remediation of Audit rules for rename for 32bit platform
    block:

    - name: Declare list of syscalls
      ansible.builtin.set_fact:
        syscalls:
        - rename
        syscall_grouping:
        - unlink
        - unlinkat
        - rename
        - renameat
        - renameat2
        - rmdir

    - name: Check existence of rename in /etc/audit/rules.d/
      ansible.builtin.find:
        paths: /etc/audit/rules.d
        contains: -a always,exit -F arch=b32(( -S |,)\w+)*(( -S |,){{ item }})+((
          -S |,)\w+)* -F auid>=1000 -F auid!=unset (-k\s+|-F\s+key=)\S+\s*$
        patterns: '*.rules'
      register: find_command
      loop: '{{ (syscall_grouping + syscalls) | unique }}'

    - name: Reset syscalls found per file
      ansible.builtin.set_fact:
        syscalls_per_file: {}
        found_paths_dict: {}

    - name: Declare syscalls found per file
      ansible.builtin.set_fact: syscalls_per_file="{{ syscalls_per_file | combine(
        {item.files[0].path :[item.item] + syscalls_per_file.get(item.files[0].path,
        []) } ) }}"
      loop: '{{ find_command.results | selectattr(''matched'') | list }}'

    - name: Declare files where syscalls were found
      ansible.builtin.set_fact: found_paths="{{ find_command.results | map(attribute='files')
        | flatten | map(attribute='path') | list }}"

    - name: Count occurrences of syscalls in paths
      ansible.builtin.set_fact: found_paths_dict="{{ found_paths_dict | combine({
        item:1+found_paths_dict.get(item, 0) }) }}"
      loop: '{{ find_command.results | map(attribute=''files'') | flatten | map(attribute=''path'')
        | list }}'

    - name: Get path with most syscalls
      ansible.builtin.set_fact: audit_file="{{ (found_paths_dict | dict2items() |
        sort(attribute='value') | last).key }}"
      when: found_paths | length >= 1

    - name: No file with syscall found, set path to /etc/audit/rules.d/delete.rules
      ansible.builtin.set_fact: audit_file="/etc/audit/rules.d/delete.rules"
      when: found_paths | length == 0

    - name: Declare found syscalls
      ansible.builtin.set_fact: syscalls_found="{{ find_command.results | selectattr('matched')
        | map(attribute='item') | list }}"

    - name: Declare missing syscalls
      ansible.builtin.set_fact: missing_syscalls="{{ syscalls | difference(syscalls_found)
        }}"

    - name: Replace the audit rule in {{ audit_file }}
      ansible.builtin.lineinfile:
        path: '{{ audit_file }}'
        regexp: (-a always,exit -F arch=b32)(?=.*(?:(?:-S |,)(?:{{ syscalls_per_file[audit_file]
          | join("|") }}))\b)((?:( -S |,)\w+)+)( -F auid>=1000 -F auid!=unset (?:-k
          |-F key=)\w+)
        line: \1\2\3{{ missing_syscalls | join("\3") }}\4
        backrefs: true
        state: present
        mode: g-rwx,o-rwx
      when: syscalls_found | length > 0 and missing_syscalls | length > 0

    - name: Add the audit rule to {{ audit_file }}
      ansible.builtin.lineinfile:
        path: '{{ audit_file }}'
        line: -a always,exit -F arch=b32 -S {{ syscalls | join(',') }} -F auid>=1000
          -F auid!=unset -F key=delete
        create: true
        mode: g-rwx,o-rwx
        state: present
      when: syscalls_found | length == 0

    - name: Declare list of syscalls
      ansible.builtin.set_fact:
        syscalls:
        - rename
        syscall_grouping:
        - unlink
        - unlinkat
        - rename
        - renameat
        - renameat2
        - rmdir

    - name: Check existence of rename in /etc/audit/audit.rules
      ansible.builtin.find:
        paths: /etc/audit
        contains: -a always,exit -F arch=b32(( -S |,)\w+)*(( -S |,){{ item }})+((
          -S |,)\w+)* -F auid>=1000 -F auid!=unset (-k\s+|-F\s+key=)\S+\s*$
        patterns: audit.rules
      register: find_command
      loop: '{{ (syscall_grouping + syscalls) | unique }}'

    - name: Set path to /etc/audit/audit.rules
      ansible.builtin.set_fact: audit_file="/etc/audit/audit.rules"

    - name: Declare found syscalls
      ansible.builtin.set_fact: syscalls_found="{{ find_command.results | selectattr('matched')
        | map(attribute='item') | list }}"

    - name: Declare missing syscalls
      ansible.builtin.set_fact: missing_syscalls="{{ syscalls | difference(syscalls_found)
        }}"

    - name: Replace the audit rule in {{ audit_file }}
      ansible.builtin.lineinfile:
        path: '{{ audit_file }}'
        regexp: (-a always,exit -F arch=b32)(?=.*(?:(?:-S |,)(?:{{ syscalls_found
          | join("|") }}))\b)((?:( -S |,)\w+)+)( -F auid>=1000 -F auid!=unset (?:-k
          |-F key=)\w+)
        line: \1\2\3{{ missing_syscalls | join("\3") }}\4
        backrefs: true
        state: present
        mode: g-rwx,o-rwx
      when: syscalls_found | length > 0 and missing_syscalls | length > 0

    - name: Add the audit rule to {{ audit_file }}
      ansible.builtin.lineinfile:
        path: '{{ audit_file }}'
        line: -a always,exit -F arch=b32 -S {{ syscalls | join(',') }} -F auid>=1000
          -F auid!=unset -F key=delete
        create: true
        mode: g-rwx,o-rwx
        state: present
      when: syscalls_found | length == 0
    when:
    - '"audit" in ansible_facts.packages'
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - not ( ansible_architecture == "aarch64" )
    tags:
    - DISA-STIG-OL09-00-000680
    - NIST-800-171-3.1.7
    - NIST-800-53-AU-12(c)
    - NIST-800-53-AU-2(d)
    - NIST-800-53-CM-6(a)
    - PCI-DSS-Req-10.2.7
    - PCI-DSSv4-10.2
    - PCI-DSSv4-10.2.1
    - PCI-DSSv4-10.2.1.7
    - audit_rules_file_deletion_events_rename
    - low_complexity
    - low_disruption
    - medium_severity
    - reboot_required
    - restrict_strategy

  - name: Perform remediation of Audit rules for rename for 64bit platform
    block:

    - name: Declare list of syscalls
      ansible.builtin.set_fact:
        syscalls:
        - rename
        syscall_grouping:
        - unlink
        - unlinkat
        - rename
        - renameat
        - renameat2
        - rmdir

    - name: Check existence of rename in /etc/audit/rules.d/
      ansible.builtin.find:
        paths: /etc/audit/rules.d
        contains: -a always,exit -F arch=b64(( -S |,)\w+)*(( -S |,){{ item }})+((
          -S |,)\w+)* -F auid>=1000 -F auid!=unset (-k\s+|-F\s+key=)\S+\s*$
        patterns: '*.rules'
      register: find_command
      loop: '{{ (syscall_grouping + syscalls) | unique }}'

    - name: Reset syscalls found per file
      ansible.builtin.set_fact:
        syscalls_per_file: {}
        found_paths_dict: {}

    - name: Declare syscalls found per file
      ansible.builtin.set_fact: syscalls_per_file="{{ syscalls_per_file | combine(
        {item.files[0].path :[item.item] + syscalls_per_file.get(item.files[0].path,
        []) } ) }}"
      loop: '{{ find_command.results | selectattr(''matched'') | list }}'

    - name: Declare files where syscalls were found
      ansible.builtin.set_fact: found_paths="{{ find_command.results | map(attribute='files')
        | flatten | map(attribute='path') | list }}"

    - name: Count occurrences of syscalls in paths
      ansible.builtin.set_fact: found_paths_dict="{{ found_paths_dict | combine({
        item:1+found_paths_dict.get(item, 0) }) }}"
      loop: '{{ find_command.results | map(attribute=''files'') | flatten | map(attribute=''path'')
        | list }}'

    - name: Get path with most syscalls
      ansible.builtin.set_fact: audit_file="{{ (found_paths_dict | dict2items() |
        sort(attribute='value') | last).key }}"
      when: found_paths | length >= 1

    - name: No file with syscall found, set path to /etc/audit/rules.d/delete.rules
      ansible.builtin.set_fact: audit_file="/etc/audit/rules.d/delete.rules"
      when: found_paths | length == 0

    - name: Declare found syscalls
      ansible.builtin.set_fact: syscalls_found="{{ find_command.results | selectattr('matched')
        | map(attribute='item') | list }}"

    - name: Declare missing syscalls
      ansible.builtin.set_fact: missing_syscalls="{{ syscalls | difference(syscalls_found)
        }}"

    - name: Replace the audit rule in {{ audit_file }}
      ansible.builtin.lineinfile:
        path: '{{ audit_file }}'
        regexp: (-a always,exit -F arch=b64)(?=.*(?:(?:-S |,)(?:{{ syscalls_per_file[audit_file]
          | join("|") }}))\b)((?:( -S |,)\w+)+)( -F auid>=1000 -F auid!=unset (?:-k
          |-F key=)\w+)
        line: \1\2\3{{ missing_syscalls | join("\3") }}\4
        backrefs: true
        state: present
        mode: g-rwx,o-rwx
      when: syscalls_found | length > 0 and missing_syscalls | length > 0

    - name: Add the audit rule to {{ audit_file }}
      ansible.builtin.lineinfile:
        path: '{{ audit_file }}'
        line: -a always,exit -F arch=b64 -S {{ syscalls | join(',') }} -F auid>=1000
          -F auid!=unset -F key=delete
        create: true
        mode: g-rwx,o-rwx
        state: present
      when: syscalls_found | length == 0

    - name: Declare list of syscalls
      ansible.builtin.set_fact:
        syscalls:
        - rename
        syscall_grouping:
        - unlink
        - unlinkat
        - rename
        - renameat
        - renameat2
        - rmdir

    - name: Check existence of rename in /etc/audit/audit.rules
      ansible.builtin.find:
        paths: /etc/audit
        contains: -a always,exit -F arch=b64(( -S |,)\w+)*(( -S |,){{ item }})+((
          -S |,)\w+)* -F auid>=1000 -F auid!=unset (-k\s+|-F\s+key=)\S+\s*$
        patterns: audit.rules
      register: find_command
      loop: '{{ (syscall_grouping + syscalls) | unique }}'

    - name: Set path to /etc/audit/audit.rules
      ansible.builtin.set_fact: audit_file="/etc/audit/audit.rules"

    - name: Declare found syscalls
      ansible.builtin.set_fact: syscalls_found="{{ find_command.results | selectattr('matched')
        | map(attribute='item') | list }}"

    - name: Declare missing syscalls
      ansible.builtin.set_fact: missing_syscalls="{{ syscalls | difference(syscalls_found)
        }}"

    - name: Replace the audit rule in {{ audit_file }}
      ansible.builtin.lineinfile:
        path: '{{ audit_file }}'
        regexp: (-a always,exit -F arch=b64)(?=.*(?:(?:-S |,)(?:{{ syscalls_found
          | join("|") }}))\b)((?:( -S |,)\w+)+)( -F auid>=1000 -F auid!=unset (?:-k
          |-F key=)\w+)
        line: \1\2\3{{ missing_syscalls | join("\3") }}\4
        backrefs: true
        state: present
        mode: g-rwx,o-rwx
      when: syscalls_found | length > 0 and missing_syscalls | length > 0

    - name: Add the audit rule to {{ audit_file }}
      ansible.builtin.lineinfile:
        path: '{{ audit_file }}'
        line: -a always,exit -F arch=b64 -S {{ syscalls | join(',') }} -F auid>=1000
          -F auid!=unset -F key=delete
        create: true
        mode: g-rwx,o-rwx
        state: present
      when: syscalls_found | length == 0
    when:
    - '"audit" in ansible_facts.packages'
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - not ( ansible_architecture == "aarch64" )
    - audit_arch == "b64"
    tags:
    - DISA-STIG-OL09-00-000680
    - NIST-800-171-3.1.7
    - NIST-800-53-AU-12(c)
    - NIST-800-53-AU-2(d)
    - NIST-800-53-CM-6(a)
    - PCI-DSS-Req-10.2.7
    - PCI-DSSv4-10.2
    - PCI-DSSv4-10.2.1
    - PCI-DSSv4-10.2.1.7
    - audit_rules_file_deletion_events_rename
    - low_complexity
    - low_disruption
    - medium_severity
    - reboot_required
    - restrict_strategy

  - name: Set architecture for audit renameat tasks
    ansible.builtin.set_fact:
      audit_arch: b64
    when:
    - '"audit" in ansible_facts.packages'
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - ansible_architecture == "aarch64" or ansible_architecture == "ppc64" or ansible_architecture
      == "ppc64le" or ansible_architecture == "s390x" or ansible_architecture == "x86_64"
    tags:
    - DISA-STIG-OL09-00-000680
    - NIST-800-171-3.1.7
    - NIST-800-53-AU-12(c)
    - NIST-800-53-AU-2(d)
    - NIST-800-53-CM-6(a)
    - PCI-DSS-Req-10.2.7
    - PCI-DSSv4-10.2
    - PCI-DSSv4-10.2.1
    - PCI-DSSv4-10.2.1.7
    - audit_rules_file_deletion_events_renameat
    - low_complexity
    - low_disruption
    - medium_severity
    - reboot_required
    - restrict_strategy

  - name: Perform remediation of Audit rules for renameat for 32bit platform
    block:

    - name: Declare list of syscalls
      ansible.builtin.set_fact:
        syscalls:
        - renameat
        syscall_grouping:
        - unlink
        - unlinkat
        - rename
        - renameat
        - renameat2
        - rmdir

    - name: Check existence of renameat in /etc/audit/rules.d/
      ansible.builtin.find:
        paths: /etc/audit/rules.d
        contains: -a always,exit -F arch=b32(( -S |,)\w+)*(( -S |,){{ item }})+((
          -S |,)\w+)* -F auid>=1000 -F auid!=unset (-k\s+|-F\s+key=)\S+\s*$
        patterns: '*.rules'
      register: find_command
      loop: '{{ (syscall_grouping + syscalls) | unique }}'

    - name: Reset syscalls found per file
      ansible.builtin.set_fact:
        syscalls_per_file: {}
        found_paths_dict: {}

    - name: Declare syscalls found per file
      ansible.builtin.set_fact: syscalls_per_file="{{ syscalls_per_file | combine(
        {item.files[0].path :[item.item] + syscalls_per_file.get(item.files[0].path,
        []) } ) }}"
      loop: '{{ find_command.results | selectattr(''matched'') | list }}'

    - name: Declare files where syscalls were found
      ansible.builtin.set_fact: found_paths="{{ find_command.results | map(attribute='files')
        | flatten | map(attribute='path') | list }}"

    - name: Count occurrences of syscalls in paths
      ansible.builtin.set_fact: found_paths_dict="{{ found_paths_dict | combine({
        item:1+found_paths_dict.get(item, 0) }) }}"
      loop: '{{ find_command.results | map(attribute=''files'') | flatten | map(attribute=''path'')
        | list }}'

    - name: Get path with most syscalls
      ansible.builtin.set_fact: audit_file="{{ (found_paths_dict | dict2items() |
        sort(attribute='value') | last).key }}"
      when: found_paths | length >= 1

    - name: No file with syscall found, set path to /etc/audit/rules.d/delete.rules
      ansible.builtin.set_fact: audit_file="/etc/audit/rules.d/delete.rules"
      when: found_paths | length == 0

    - name: Declare found syscalls
      ansible.builtin.set_fact: syscalls_found="{{ find_command.results | selectattr('matched')
        | map(attribute='item') | list }}"

    - name: Declare missing syscalls
      ansible.builtin.set_fact: missing_syscalls="{{ syscalls | difference(syscalls_found)
        }}"

    - name: Replace the audit rule in {{ audit_file }}
      ansible.builtin.lineinfile:
        path: '{{ audit_file }}'
        regexp: (-a always,exit -F arch=b32)(?=.*(?:(?:-S |,)(?:{{ syscalls_per_file[audit_file]
          | join("|") }}))\b)((?:( -S |,)\w+)+)( -F auid>=1000 -F auid!=unset (?:-k
          |-F key=)\w+)
        line: \1\2\3{{ missing_syscalls | join("\3") }}\4
        backrefs: true
        state: present
        mode: g-rwx,o-rwx
      when: syscalls_found | length > 0 and missing_syscalls | length > 0

    - name: Add the audit rule to {{ audit_file }}
      ansible.builtin.lineinfile:
        path: '{{ audit_file }}'
        line: -a always,exit -F arch=b32 -S {{ syscalls | join(',') }} -F auid>=1000
          -F auid!=unset -F key=delete
        create: true
        mode: g-rwx,o-rwx
        state: present
      when: syscalls_found | length == 0

    - name: Declare list of syscalls
      ansible.builtin.set_fact:
        syscalls:
        - renameat
        syscall_grouping:
        - unlink
        - unlinkat
        - rename
        - renameat
        - renameat2
        - rmdir

    - name: Check existence of renameat in /etc/audit/audit.rules
      ansible.builtin.find:
        paths: /etc/audit
        contains: -a always,exit -F arch=b32(( -S |,)\w+)*(( -S |,){{ item }})+((
          -S |,)\w+)* -F auid>=1000 -F auid!=unset (-k\s+|-F\s+key=)\S+\s*$
        patterns: audit.rules
      register: find_command
      loop: '{{ (syscall_grouping + syscalls) | unique }}'

    - name: Set path to /etc/audit/audit.rules
      ansible.builtin.set_fact: audit_file="/etc/audit/audit.rules"

    - name: Declare found syscalls
      ansible.builtin.set_fact: syscalls_found="{{ find_command.results | selectattr('matched')
        | map(attribute='item') | list }}"

    - name: Declare missing syscalls
      ansible.builtin.set_fact: missing_syscalls="{{ syscalls | difference(syscalls_found)
        }}"

    - name: Replace the audit rule in {{ audit_file }}
      ansible.builtin.lineinfile:
        path: '{{ audit_file }}'
        regexp: (-a always,exit -F arch=b32)(?=.*(?:(?:-S |,)(?:{{ syscalls_found
          | join("|") }}))\b)((?:( -S |,)\w+)+)( -F auid>=1000 -F auid!=unset (?:-k
          |-F key=)\w+)
        line: \1\2\3{{ missing_syscalls | join("\3") }}\4
        backrefs: true
        state: present
        mode: g-rwx,o-rwx
      when: syscalls_found | length > 0 and missing_syscalls | length > 0

    - name: Add the audit rule to {{ audit_file }}
      ansible.builtin.lineinfile:
        path: '{{ audit_file }}'
        line: -a always,exit -F arch=b32 -S {{ syscalls | join(',') }} -F auid>=1000
          -F auid!=unset -F key=delete
        create: true
        mode: g-rwx,o-rwx
        state: present
      when: syscalls_found | length == 0
    when:
    - '"audit" in ansible_facts.packages'
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-000680
    - NIST-800-171-3.1.7
    - NIST-800-53-AU-12(c)
    - NIST-800-53-AU-2(d)
    - NIST-800-53-CM-6(a)
    - PCI-DSS-Req-10.2.7
    - PCI-DSSv4-10.2
    - PCI-DSSv4-10.2.1
    - PCI-DSSv4-10.2.1.7
    - audit_rules_file_deletion_events_renameat
    - low_complexity
    - low_disruption
    - medium_severity
    - reboot_required
    - restrict_strategy

  - name: Perform remediation of Audit rules for renameat for 64bit platform
    block:

    - name: Declare list of syscalls
      ansible.builtin.set_fact:
        syscalls:
        - renameat
        syscall_grouping:
        - unlink
        - unlinkat
        - rename
        - renameat
        - renameat2
        - rmdir

    - name: Check existence of renameat in /etc/audit/rules.d/
      ansible.builtin.find:
        paths: /etc/audit/rules.d
        contains: -a always,exit -F arch=b64(( -S |,)\w+)*(( -S |,){{ item }})+((
          -S |,)\w+)* -F auid>=1000 -F auid!=unset (-k\s+|-F\s+key=)\S+\s*$
        patterns: '*.rules'
      register: find_command
      loop: '{{ (syscall_grouping + syscalls) | unique }}'

    - name: Reset syscalls found per file
      ansible.builtin.set_fact:
        syscalls_per_file: {}
        found_paths_dict: {}

    - name: Declare syscalls found per file
      ansible.builtin.set_fact: syscalls_per_file="{{ syscalls_per_file | combine(
        {item.files[0].path :[item.item] + syscalls_per_file.get(item.files[0].path,
        []) } ) }}"
      loop: '{{ find_command.results | selectattr(''matched'') | list }}'

    - name: Declare files where syscalls were found
      ansible.builtin.set_fact: found_paths="{{ find_command.results | map(attribute='files')
        | flatten | map(attribute='path') | list }}"

    - name: Count occurrences of syscalls in paths
      ansible.builtin.set_fact: found_paths_dict="{{ found_paths_dict | combine({
        item:1+found_paths_dict.get(item, 0) }) }}"
      loop: '{{ find_command.results | map(attribute=''files'') | flatten | map(attribute=''path'')
        | list }}'

    - name: Get path with most syscalls
      ansible.builtin.set_fact: audit_file="{{ (found_paths_dict | dict2items() |
        sort(attribute='value') | last).key }}"
      when: found_paths | length >= 1

    - name: No file with syscall found, set path to /etc/audit/rules.d/delete.rules
      ansible.builtin.set_fact: audit_file="/etc/audit/rules.d/delete.rules"
      when: found_paths | length == 0

    - name: Declare found syscalls
      ansible.builtin.set_fact: syscalls_found="{{ find_command.results | selectattr('matched')
        | map(attribute='item') | list }}"

    - name: Declare missing syscalls
      ansible.builtin.set_fact: missing_syscalls="{{ syscalls | difference(syscalls_found)
        }}"

    - name: Replace the audit rule in {{ audit_file }}
      ansible.builtin.lineinfile:
        path: '{{ audit_file }}'
        regexp: (-a always,exit -F arch=b64)(?=.*(?:(?:-S |,)(?:{{ syscalls_per_file[audit_file]
          | join("|") }}))\b)((?:( -S |,)\w+)+)( -F auid>=1000 -F auid!=unset (?:-k
          |-F key=)\w+)
        line: \1\2\3{{ missing_syscalls | join("\3") }}\4
        backrefs: true
        state: present
        mode: g-rwx,o-rwx
      when: syscalls_found | length > 0 and missing_syscalls | length > 0

    - name: Add the audit rule to {{ audit_file }}
      ansible.builtin.lineinfile:
        path: '{{ audit_file }}'
        line: -a always,exit -F arch=b64 -S {{ syscalls | join(',') }} -F auid>=1000
          -F auid!=unset -F key=delete
        create: true
        mode: g-rwx,o-rwx
        state: present
      when: syscalls_found | length == 0

    - name: Declare list of syscalls
      ansible.builtin.set_fact:
        syscalls:
        - renameat
        syscall_grouping:
        - unlink
        - unlinkat
        - rename
        - renameat
        - renameat2
        - rmdir

    - name: Check existence of renameat in /etc/audit/audit.rules
      ansible.builtin.find:
        paths: /etc/audit
        contains: -a always,exit -F arch=b64(( -S |,)\w+)*(( -S |,){{ item }})+((
          -S |,)\w+)* -F auid>=1000 -F auid!=unset (-k\s+|-F\s+key=)\S+\s*$
        patterns: audit.rules
      register: find_command
      loop: '{{ (syscall_grouping + syscalls) | unique }}'

    - name: Set path to /etc/audit/audit.rules
      ansible.builtin.set_fact: audit_file="/etc/audit/audit.rules"

    - name: Declare found syscalls
      ansible.builtin.set_fact: syscalls_found="{{ find_command.results | selectattr('matched')
        | map(attribute='item') | list }}"

    - name: Declare missing syscalls
      ansible.builtin.set_fact: missing_syscalls="{{ syscalls | difference(syscalls_found)
        }}"

    - name: Replace the audit rule in {{ audit_file }}
      ansible.builtin.lineinfile:
        path: '{{ audit_file }}'
        regexp: (-a always,exit -F arch=b64)(?=.*(?:(?:-S |,)(?:{{ syscalls_found
          | join("|") }}))\b)((?:( -S |,)\w+)+)( -F auid>=1000 -F auid!=unset (?:-k
          |-F key=)\w+)
        line: \1\2\3{{ missing_syscalls | join("\3") }}\4
        backrefs: true
        state: present
        mode: g-rwx,o-rwx
      when: syscalls_found | length > 0 and missing_syscalls | length > 0

    - name: Add the audit rule to {{ audit_file }}
      ansible.builtin.lineinfile:
        path: '{{ audit_file }}'
        line: -a always,exit -F arch=b64 -S {{ syscalls | join(',') }} -F auid>=1000
          -F auid!=unset -F key=delete
        create: true
        mode: g-rwx,o-rwx
        state: present
      when: syscalls_found | length == 0
    when:
    - '"audit" in ansible_facts.packages'
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - audit_arch == "b64"
    tags:
    - DISA-STIG-OL09-00-000680
    - NIST-800-171-3.1.7
    - NIST-800-53-AU-12(c)
    - NIST-800-53-AU-2(d)
    - NIST-800-53-CM-6(a)
    - PCI-DSS-Req-10.2.7
    - PCI-DSSv4-10.2
    - PCI-DSSv4-10.2.1
    - PCI-DSSv4-10.2.1.7
    - audit_rules_file_deletion_events_renameat
    - low_complexity
    - low_disruption
    - medium_severity
    - reboot_required
    - restrict_strategy

  - name: Set architecture for audit rmdir tasks
    ansible.builtin.set_fact:
      audit_arch: b64
    when:
    - '"audit" in ansible_facts.packages'
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - not ( ansible_architecture == "aarch64" )
    - ansible_architecture == "aarch64" or ansible_architecture == "ppc64" or ansible_architecture
      == "ppc64le" or ansible_architecture == "s390x" or ansible_architecture == "x86_64"
    tags:
    - DISA-STIG-OL09-00-000680
    - NIST-800-171-3.1.7
    - NIST-800-53-AU-12(c)
    - NIST-800-53-AU-2(d)
    - NIST-800-53-CM-6(a)
    - PCI-DSS-Req-10.2.7
    - PCI-DSSv4-10.2
    - PCI-DSSv4-10.2.1
    - PCI-DSSv4-10.2.1.7
    - audit_rules_file_deletion_events_rmdir
    - low_complexity
    - low_disruption
    - medium_severity
    - reboot_required
    - restrict_strategy

  - name: Perform remediation of Audit rules for rmdir for 32bit platform
    block:

    - name: Declare list of syscalls
      ansible.builtin.set_fact:
        syscalls:
        - rmdir
        syscall_grouping:
        - unlink
        - unlinkat
        - rename
        - renameat
        - renameat2
        - rmdir

    - name: Check existence of rmdir in /etc/audit/rules.d/
      ansible.builtin.find:
        paths: /etc/audit/rules.d
        contains: -a always,exit -F arch=b32(( -S |,)\w+)*(( -S |,){{ item }})+((
          -S |,)\w+)* -F auid>=1000 -F auid!=unset (-k\s+|-F\s+key=)\S+\s*$
        patterns: '*.rules'
      register: find_command
      loop: '{{ (syscall_grouping + syscalls) | unique }}'

    - name: Reset syscalls found per file
      ansible.builtin.set_fact:
        syscalls_per_file: {}
        found_paths_dict: {}

    - name: Declare syscalls found per file
      ansible.builtin.set_fact: syscalls_per_file="{{ syscalls_per_file | combine(
        {item.files[0].path :[item.item] + syscalls_per_file.get(item.files[0].path,
        []) } ) }}"
      loop: '{{ find_command.results | selectattr(''matched'') | list }}'

    - name: Declare files where syscalls were found
      ansible.builtin.set_fact: found_paths="{{ find_command.results | map(attribute='files')
        | flatten | map(attribute='path') | list }}"

    - name: Count occurrences of syscalls in paths
      ansible.builtin.set_fact: found_paths_dict="{{ found_paths_dict | combine({
        item:1+found_paths_dict.get(item, 0) }) }}"
      loop: '{{ find_command.results | map(attribute=''files'') | flatten | map(attribute=''path'')
        | list }}'

    - name: Get path with most syscalls
      ansible.builtin.set_fact: audit_file="{{ (found_paths_dict | dict2items() |
        sort(attribute='value') | last).key }}"
      when: found_paths | length >= 1

    - name: No file with syscall found, set path to /etc/audit/rules.d/delete.rules
      ansible.builtin.set_fact: audit_file="/etc/audit/rules.d/delete.rules"
      when: found_paths | length == 0

    - name: Declare found syscalls
      ansible.builtin.set_fact: syscalls_found="{{ find_command.results | selectattr('matched')
        | map(attribute='item') | list }}"

    - name: Declare missing syscalls
      ansible.builtin.set_fact: missing_syscalls="{{ syscalls | difference(syscalls_found)
        }}"

    - name: Replace the audit rule in {{ audit_file }}
      ansible.builtin.lineinfile:
        path: '{{ audit_file }}'
        regexp: (-a always,exit -F arch=b32)(?=.*(?:(?:-S |,)(?:{{ syscalls_per_file[audit_file]
          | join("|") }}))\b)((?:( -S |,)\w+)+)( -F auid>=1000 -F auid!=unset (?:-k
          |-F key=)\w+)
        line: \1\2\3{{ missing_syscalls | join("\3") }}\4
        backrefs: true
        state: present
        mode: g-rwx,o-rwx
      when: syscalls_found | length > 0 and missing_syscalls | length > 0

    - name: Add the audit rule to {{ audit_file }}
      ansible.builtin.lineinfile:
        path: '{{ audit_file }}'
        line: -a always,exit -F arch=b32 -S {{ syscalls | join(',') }} -F auid>=1000
          -F auid!=unset -F key=delete
        create: true
        mode: g-rwx,o-rwx
        state: present
      when: syscalls_found | length == 0

    - name: Declare list of syscalls
      ansible.builtin.set_fact:
        syscalls:
        - rmdir
        syscall_grouping:
        - unlink
        - unlinkat
        - rename
        - renameat
        - renameat2
        - rmdir

    - name: Check existence of rmdir in /etc/audit/audit.rules
      ansible.builtin.find:
        paths: /etc/audit
        contains: -a always,exit -F arch=b32(( -S |,)\w+)*(( -S |,){{ item }})+((
          -S |,)\w+)* -F auid>=1000 -F auid!=unset (-k\s+|-F\s+key=)\S+\s*$
        patterns: audit.rules
      register: find_command
      loop: '{{ (syscall_grouping + syscalls) | unique }}'

    - name: Set path to /etc/audit/audit.rules
      ansible.builtin.set_fact: audit_file="/etc/audit/audit.rules"

    - name: Declare found syscalls
      ansible.builtin.set_fact: syscalls_found="{{ find_command.results | selectattr('matched')
        | map(attribute='item') | list }}"

    - name: Declare missing syscalls
      ansible.builtin.set_fact: missing_syscalls="{{ syscalls | difference(syscalls_found)
        }}"

    - name: Replace the audit rule in {{ audit_file }}
      ansible.builtin.lineinfile:
        path: '{{ audit_file }}'
        regexp: (-a always,exit -F arch=b32)(?=.*(?:(?:-S |,)(?:{{ syscalls_found
          | join("|") }}))\b)((?:( -S |,)\w+)+)( -F auid>=1000 -F auid!=unset (?:-k
          |-F key=)\w+)
        line: \1\2\3{{ missing_syscalls | join("\3") }}\4
        backrefs: true
        state: present
        mode: g-rwx,o-rwx
      when: syscalls_found | length > 0 and missing_syscalls | length > 0

    - name: Add the audit rule to {{ audit_file }}
      ansible.builtin.lineinfile:
        path: '{{ audit_file }}'
        line: -a always,exit -F arch=b32 -S {{ syscalls | join(',') }} -F auid>=1000
          -F auid!=unset -F key=delete
        create: true
        mode: g-rwx,o-rwx
        state: present
      when: syscalls_found | length == 0
    when:
    - '"audit" in ansible_facts.packages'
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - not ( ansible_architecture == "aarch64" )
    tags:
    - DISA-STIG-OL09-00-000680
    - NIST-800-171-3.1.7
    - NIST-800-53-AU-12(c)
    - NIST-800-53-AU-2(d)
    - NIST-800-53-CM-6(a)
    - PCI-DSS-Req-10.2.7
    - PCI-DSSv4-10.2
    - PCI-DSSv4-10.2.1
    - PCI-DSSv4-10.2.1.7
    - audit_rules_file_deletion_events_rmdir
    - low_complexity
    - low_disruption
    - medium_severity
    - reboot_required
    - restrict_strategy

  - name: Perform remediation of Audit rules for rmdir for 64bit platform
    block:

    - name: Declare list of syscalls
      ansible.builtin.set_fact:
        syscalls:
        - rmdir
        syscall_grouping:
        - unlink
        - unlinkat
        - rename
        - renameat
        - renameat2
        - rmdir

    - name: Check existence of rmdir in /etc/audit/rules.d/
      ansible.builtin.find:
        paths: /etc/audit/rules.d
        contains: -a always,exit -F arch=b64(( -S |,)\w+)*(( -S |,){{ item }})+((
          -S |,)\w+)* -F auid>=1000 -F auid!=unset (-k\s+|-F\s+key=)\S+\s*$
        patterns: '*.rules'
      register: find_command
      loop: '{{ (syscall_grouping + syscalls) | unique }}'

    - name: Reset syscalls found per file
      ansible.builtin.set_fact:
        syscalls_per_file: {}
        found_paths_dict: {}

    - name: Declare syscalls found per file
      ansible.builtin.set_fact: syscalls_per_file="{{ syscalls_per_file | combine(
        {item.files[0].path :[item.item] + syscalls_per_file.get(item.files[0].path,
        []) } ) }}"
      loop: '{{ find_command.results | selectattr(''matched'') | list }}'

    - name: Declare files where syscalls were found
      ansible.builtin.set_fact: found_paths="{{ find_command.results | map(attribute='files')
        | flatten | map(attribute='path') | list }}"

    - name: Count occurrences of syscalls in paths
      ansible.builtin.set_fact: found_paths_dict="{{ found_paths_dict | combine({
        item:1+found_paths_dict.get(item, 0) }) }}"
      loop: '{{ find_command.results | map(attribute=''files'') | flatten | map(attribute=''path'')
        | list }}'

    - name: Get path with most syscalls
      ansible.builtin.set_fact: audit_file="{{ (found_paths_dict | dict2items() |
        sort(attribute='value') | last).key }}"
      when: found_paths | length >= 1

    - name: No file with syscall found, set path to /etc/audit/rules.d/delete.rules
      ansible.builtin.set_fact: audit_file="/etc/audit/rules.d/delete.rules"
      when: found_paths | length == 0

    - name: Declare found syscalls
      ansible.builtin.set_fact: syscalls_found="{{ find_command.results | selectattr('matched')
        | map(attribute='item') | list }}"

    - name: Declare missing syscalls
      ansible.builtin.set_fact: missing_syscalls="{{ syscalls | difference(syscalls_found)
        }}"

    - name: Replace the audit rule in {{ audit_file }}
      ansible.builtin.lineinfile:
        path: '{{ audit_file }}'
        regexp: (-a always,exit -F arch=b64)(?=.*(?:(?:-S |,)(?:{{ syscalls_per_file[audit_file]
          | join("|") }}))\b)((?:( -S |,)\w+)+)( -F auid>=1000 -F auid!=unset (?:-k
          |-F key=)\w+)
        line: \1\2\3{{ missing_syscalls | join("\3") }}\4
        backrefs: true
        state: present
        mode: g-rwx,o-rwx
      when: syscalls_found | length > 0 and missing_syscalls | length > 0

    - name: Add the audit rule to {{ audit_file }}
      ansible.builtin.lineinfile:
        path: '{{ audit_file }}'
        line: -a always,exit -F arch=b64 -S {{ syscalls | join(',') }} -F auid>=1000
          -F auid!=unset -F key=delete
        create: true
        mode: g-rwx,o-rwx
        state: present
      when: syscalls_found | length == 0

    - name: Declare list of syscalls
      ansible.builtin.set_fact:
        syscalls:
        - rmdir
        syscall_grouping:
        - unlink
        - unlinkat
        - rename
        - renameat
        - renameat2
        - rmdir

    - name: Check existence of rmdir in /etc/audit/audit.rules
      ansible.builtin.find:
        paths: /etc/audit
        contains: -a always,exit -F arch=b64(( -S |,)\w+)*(( -S |,){{ item }})+((
          -S |,)\w+)* -F auid>=1000 -F auid!=unset (-k\s+|-F\s+key=)\S+\s*$
        patterns: audit.rules
      register: find_command
      loop: '{{ (syscall_grouping + syscalls) | unique }}'

    - name: Set path to /etc/audit/audit.rules
      ansible.builtin.set_fact: audit_file="/etc/audit/audit.rules"

    - name: Declare found syscalls
      ansible.builtin.set_fact: syscalls_found="{{ find_command.results | selectattr('matched')
        | map(attribute='item') | list }}"

    - name: Declare missing syscalls
      ansible.builtin.set_fact: missing_syscalls="{{ syscalls | difference(syscalls_found)
        }}"

    - name: Replace the audit rule in {{ audit_file }}
      ansible.builtin.lineinfile:
        path: '{{ audit_file }}'
        regexp: (-a always,exit -F arch=b64)(?=.*(?:(?:-S |,)(?:{{ syscalls_found
          | join("|") }}))\b)((?:( -S |,)\w+)+)( -F auid>=1000 -F auid!=unset (?:-k
          |-F key=)\w+)
        line: \1\2\3{{ missing_syscalls | join("\3") }}\4
        backrefs: true
        state: present
        mode: g-rwx,o-rwx
      when: syscalls_found | length > 0 and missing_syscalls | length > 0

    - name: Add the audit rule to {{ audit_file }}
      ansible.builtin.lineinfile:
        path: '{{ audit_file }}'
        line: -a always,exit -F arch=b64 -S {{ syscalls | join(',') }} -F auid>=1000
          -F auid!=unset -F key=delete
        create: true
        mode: g-rwx,o-rwx
        state: present
      when: syscalls_found | length == 0
    when:
    - '"audit" in ansible_facts.packages'
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - not ( ansible_architecture == "aarch64" )
    - audit_arch == "b64"
    tags:
    - DISA-STIG-OL09-00-000680
    - NIST-800-171-3.1.7
    - NIST-800-53-AU-12(c)
    - NIST-800-53-AU-2(d)
    - NIST-800-53-CM-6(a)
    - PCI-DSS-Req-10.2.7
    - PCI-DSSv4-10.2
    - PCI-DSSv4-10.2.1
    - PCI-DSSv4-10.2.1.7
    - audit_rules_file_deletion_events_rmdir
    - low_complexity
    - low_disruption
    - medium_severity
    - reboot_required
    - restrict_strategy

  - name: Set architecture for audit unlink tasks
    ansible.builtin.set_fact:
      audit_arch: b64
    when:
    - '"audit" in ansible_facts.packages'
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - not ( ansible_architecture == "aarch64" )
    - ansible_architecture == "aarch64" or ansible_architecture == "ppc64" or ansible_architecture
      == "ppc64le" or ansible_architecture == "s390x" or ansible_architecture == "x86_64"
    tags:
    - DISA-STIG-OL09-00-000680
    - NIST-800-171-3.1.7
    - NIST-800-53-AU-12(c)
    - NIST-800-53-AU-2(d)
    - NIST-800-53-CM-6(a)
    - PCI-DSS-Req-10.2.7
    - PCI-DSSv4-10.2
    - PCI-DSSv4-10.2.1
    - PCI-DSSv4-10.2.1.7
    - audit_rules_file_deletion_events_unlink
    - low_complexity
    - low_disruption
    - medium_severity
    - reboot_required
    - restrict_strategy

  - name: Perform remediation of Audit rules for unlink for 32bit platform
    block:

    - name: Declare list of syscalls
      ansible.builtin.set_fact:
        syscalls:
        - unlink
        syscall_grouping:
        - unlink
        - unlinkat
        - rename
        - renameat
        - renameat2
        - rmdir

    - name: Check existence of unlink in /etc/audit/rules.d/
      ansible.builtin.find:
        paths: /etc/audit/rules.d
        contains: -a always,exit -F arch=b32(( -S |,)\w+)*(( -S |,){{ item }})+((
          -S |,)\w+)* -F auid>=1000 -F auid!=unset (-k\s+|-F\s+key=)\S+\s*$
        patterns: '*.rules'
      register: find_command
      loop: '{{ (syscall_grouping + syscalls) | unique }}'

    - name: Reset syscalls found per file
      ansible.builtin.set_fact:
        syscalls_per_file: {}
        found_paths_dict: {}

    - name: Declare syscalls found per file
      ansible.builtin.set_fact: syscalls_per_file="{{ syscalls_per_file | combine(
        {item.files[0].path :[item.item] + syscalls_per_file.get(item.files[0].path,
        []) } ) }}"
      loop: '{{ find_command.results | selectattr(''matched'') | list }}'

    - name: Declare files where syscalls were found
      ansible.builtin.set_fact: found_paths="{{ find_command.results | map(attribute='files')
        | flatten | map(attribute='path') | list }}"

    - name: Count occurrences of syscalls in paths
      ansible.builtin.set_fact: found_paths_dict="{{ found_paths_dict | combine({
        item:1+found_paths_dict.get(item, 0) }) }}"
      loop: '{{ find_command.results | map(attribute=''files'') | flatten | map(attribute=''path'')
        | list }}'

    - name: Get path with most syscalls
      ansible.builtin.set_fact: audit_file="{{ (found_paths_dict | dict2items() |
        sort(attribute='value') | last).key }}"
      when: found_paths | length >= 1

    - name: No file with syscall found, set path to /etc/audit/rules.d/delete.rules
      ansible.builtin.set_fact: audit_file="/etc/audit/rules.d/delete.rules"
      when: found_paths | length == 0

    - name: Declare found syscalls
      ansible.builtin.set_fact: syscalls_found="{{ find_command.results | selectattr('matched')
        | map(attribute='item') | list }}"

    - name: Declare missing syscalls
      ansible.builtin.set_fact: missing_syscalls="{{ syscalls | difference(syscalls_found)
        }}"

    - name: Replace the audit rule in {{ audit_file }}
      ansible.builtin.lineinfile:
        path: '{{ audit_file }}'
        regexp: (-a always,exit -F arch=b32)(?=.*(?:(?:-S |,)(?:{{ syscalls_per_file[audit_file]
          | join("|") }}))\b)((?:( -S |,)\w+)+)( -F auid>=1000 -F auid!=unset (?:-k
          |-F key=)\w+)
        line: \1\2\3{{ missing_syscalls | join("\3") }}\4
        backrefs: true
        state: present
        mode: g-rwx,o-rwx
      when: syscalls_found | length > 0 and missing_syscalls | length > 0

    - name: Add the audit rule to {{ audit_file }}
      ansible.builtin.lineinfile:
        path: '{{ audit_file }}'
        line: -a always,exit -F arch=b32 -S {{ syscalls | join(',') }} -F auid>=1000
          -F auid!=unset -F key=delete
        create: true
        mode: g-rwx,o-rwx
        state: present
      when: syscalls_found | length == 0

    - name: Declare list of syscalls
      ansible.builtin.set_fact:
        syscalls:
        - unlink
        syscall_grouping:
        - unlink
        - unlinkat
        - rename
        - renameat
        - renameat2
        - rmdir

    - name: Check existence of unlink in /etc/audit/audit.rules
      ansible.builtin.find:
        paths: /etc/audit
        contains: -a always,exit -F arch=b32(( -S |,)\w+)*(( -S |,){{ item }})+((
          -S |,)\w+)* -F auid>=1000 -F auid!=unset (-k\s+|-F\s+key=)\S+\s*$
        patterns: audit.rules
      register: find_command
      loop: '{{ (syscall_grouping + syscalls) | unique }}'

    - name: Set path to /etc/audit/audit.rules
      ansible.builtin.set_fact: audit_file="/etc/audit/audit.rules"

    - name: Declare found syscalls
      ansible.builtin.set_fact: syscalls_found="{{ find_command.results | selectattr('matched')
        | map(attribute='item') | list }}"

    - name: Declare missing syscalls
      ansible.builtin.set_fact: missing_syscalls="{{ syscalls | difference(syscalls_found)
        }}"

    - name: Replace the audit rule in {{ audit_file }}
      ansible.builtin.lineinfile:
        path: '{{ audit_file }}'
        regexp: (-a always,exit -F arch=b32)(?=.*(?:(?:-S |,)(?:{{ syscalls_found
          | join("|") }}))\b)((?:( -S |,)\w+)+)( -F auid>=1000 -F auid!=unset (?:-k
          |-F key=)\w+)
        line: \1\2\3{{ missing_syscalls | join("\3") }}\4
        backrefs: true
        state: present
        mode: g-rwx,o-rwx
      when: syscalls_found | length > 0 and missing_syscalls | length > 0

    - name: Add the audit rule to {{ audit_file }}
      ansible.builtin.lineinfile:
        path: '{{ audit_file }}'
        line: -a always,exit -F arch=b32 -S {{ syscalls | join(',') }} -F auid>=1000
          -F auid!=unset -F key=delete
        create: true
        mode: g-rwx,o-rwx
        state: present
      when: syscalls_found | length == 0
    when:
    - '"audit" in ansible_facts.packages'
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - not ( ansible_architecture == "aarch64" )
    tags:
    - DISA-STIG-OL09-00-000680
    - NIST-800-171-3.1.7
    - NIST-800-53-AU-12(c)
    - NIST-800-53-AU-2(d)
    - NIST-800-53-CM-6(a)
    - PCI-DSS-Req-10.2.7
    - PCI-DSSv4-10.2
    - PCI-DSSv4-10.2.1
    - PCI-DSSv4-10.2.1.7
    - audit_rules_file_deletion_events_unlink
    - low_complexity
    - low_disruption
    - medium_severity
    - reboot_required
    - restrict_strategy

  - name: Perform remediation of Audit rules for unlink for 64bit platform
    block:

    - name: Declare list of syscalls
      ansible.builtin.set_fact:
        syscalls:
        - unlink
        syscall_grouping:
        - unlink
        - unlinkat
        - rename
        - renameat
        - renameat2
        - rmdir

    - name: Check existence of unlink in /etc/audit/rules.d/
      ansible.builtin.find:
        paths: /etc/audit/rules.d
        contains: -a always,exit -F arch=b64(( -S |,)\w+)*(( -S |,){{ item }})+((
          -S |,)\w+)* -F auid>=1000 -F auid!=unset (-k\s+|-F\s+key=)\S+\s*$
        patterns: '*.rules'
      register: find_command
      loop: '{{ (syscall_grouping + syscalls) | unique }}'

    - name: Reset syscalls found per file
      ansible.builtin.set_fact:
        syscalls_per_file: {}
        found_paths_dict: {}

    - name: Declare syscalls found per file
      ansible.builtin.set_fact: syscalls_per_file="{{ syscalls_per_file | combine(
        {item.files[0].path :[item.item] + syscalls_per_file.get(item.files[0].path,
        []) } ) }}"
      loop: '{{ find_command.results | selectattr(''matched'') | list }}'

    - name: Declare files where syscalls were found
      ansible.builtin.set_fact: found_paths="{{ find_command.results | map(attribute='files')
        | flatten | map(attribute='path') | list }}"

    - name: Count occurrences of syscalls in paths
      ansible.builtin.set_fact: found_paths_dict="{{ found_paths_dict | combine({
        item:1+found_paths_dict.get(item, 0) }) }}"
      loop: '{{ find_command.results | map(attribute=''files'') | flatten | map(attribute=''path'')
        | list }}'

    - name: Get path with most syscalls
      ansible.builtin.set_fact: audit_file="{{ (found_paths_dict | dict2items() |
        sort(attribute='value') | last).key }}"
      when: found_paths | length >= 1

    - name: No file with syscall found, set path to /etc/audit/rules.d/delete.rules
      ansible.builtin.set_fact: audit_file="/etc/audit/rules.d/delete.rules"
      when: found_paths | length == 0

    - name: Declare found syscalls
      ansible.builtin.set_fact: syscalls_found="{{ find_command.results | selectattr('matched')
        | map(attribute='item') | list }}"

    - name: Declare missing syscalls
      ansible.builtin.set_fact: missing_syscalls="{{ syscalls | difference(syscalls_found)
        }}"

    - name: Replace the audit rule in {{ audit_file }}
      ansible.builtin.lineinfile:
        path: '{{ audit_file }}'
        regexp: (-a always,exit -F arch=b64)(?=.*(?:(?:-S |,)(?:{{ syscalls_per_file[audit_file]
          | join("|") }}))\b)((?:( -S |,)\w+)+)( -F auid>=1000 -F auid!=unset (?:-k
          |-F key=)\w+)
        line: \1\2\3{{ missing_syscalls | join("\3") }}\4
        backrefs: true
        state: present
        mode: g-rwx,o-rwx
      when: syscalls_found | length > 0 and missing_syscalls | length > 0

    - name: Add the audit rule to {{ audit_file }}
      ansible.builtin.lineinfile:
        path: '{{ audit_file }}'
        line: -a always,exit -F arch=b64 -S {{ syscalls | join(',') }} -F auid>=1000
          -F auid!=unset -F key=delete
        create: true
        mode: g-rwx,o-rwx
        state: present
      when: syscalls_found | length == 0

    - name: Declare list of syscalls
      ansible.builtin.set_fact:
        syscalls:
        - unlink
        syscall_grouping:
        - unlink
        - unlinkat
        - rename
        - renameat
        - renameat2
        - rmdir

    - name: Check existence of unlink in /etc/audit/audit.rules
      ansible.builtin.find:
        paths: /etc/audit
        contains: -a always,exit -F arch=b64(( -S |,)\w+)*(( -S |,){{ item }})+((
          -S |,)\w+)* -F auid>=1000 -F auid!=unset (-k\s+|-F\s+key=)\S+\s*$
        patterns: audit.rules
      register: find_command
      loop: '{{ (syscall_grouping + syscalls) | unique }}'

    - name: Set path to /etc/audit/audit.rules
      ansible.builtin.set_fact: audit_file="/etc/audit/audit.rules"

    - name: Declare found syscalls
      ansible.builtin.set_fact: syscalls_found="{{ find_command.results | selectattr('matched')
        | map(attribute='item') | list }}"

    - name: Declare missing syscalls
      ansible.builtin.set_fact: missing_syscalls="{{ syscalls | difference(syscalls_found)
        }}"

    - name: Replace the audit rule in {{ audit_file }}
      ansible.builtin.lineinfile:
        path: '{{ audit_file }}'
        regexp: (-a always,exit -F arch=b64)(?=.*(?:(?:-S |,)(?:{{ syscalls_found
          | join("|") }}))\b)((?:( -S |,)\w+)+)( -F auid>=1000 -F auid!=unset (?:-k
          |-F key=)\w+)
        line: \1\2\3{{ missing_syscalls | join("\3") }}\4
        backrefs: true
        state: present
        mode: g-rwx,o-rwx
      when: syscalls_found | length > 0 and missing_syscalls | length > 0

    - name: Add the audit rule to {{ audit_file }}
      ansible.builtin.lineinfile:
        path: '{{ audit_file }}'
        line: -a always,exit -F arch=b64 -S {{ syscalls | join(',') }} -F auid>=1000
          -F auid!=unset -F key=delete
        create: true
        mode: g-rwx,o-rwx
        state: present
      when: syscalls_found | length == 0
    when:
    - '"audit" in ansible_facts.packages'
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - not ( ansible_architecture == "aarch64" )
    - audit_arch == "b64"
    tags:
    - DISA-STIG-OL09-00-000680
    - NIST-800-171-3.1.7
    - NIST-800-53-AU-12(c)
    - NIST-800-53-AU-2(d)
    - NIST-800-53-CM-6(a)
    - PCI-DSS-Req-10.2.7
    - PCI-DSSv4-10.2
    - PCI-DSSv4-10.2.1
    - PCI-DSSv4-10.2.1.7
    - audit_rules_file_deletion_events_unlink
    - low_complexity
    - low_disruption
    - medium_severity
    - reboot_required
    - restrict_strategy

  - name: Set architecture for audit unlinkat tasks
    ansible.builtin.set_fact:
      audit_arch: b64
    when:
    - '"audit" in ansible_facts.packages'
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - ansible_architecture == "aarch64" or ansible_architecture == "ppc64" or ansible_architecture
      == "ppc64le" or ansible_architecture == "s390x" or ansible_architecture == "x86_64"
    tags:
    - DISA-STIG-OL09-00-000680
    - NIST-800-171-3.1.7
    - NIST-800-53-AU-12(c)
    - NIST-800-53-AU-2(d)
    - NIST-800-53-CM-6(a)
    - PCI-DSS-Req-10.2.7
    - PCI-DSSv4-10.2
    - PCI-DSSv4-10.2.1
    - PCI-DSSv4-10.2.1.7
    - audit_rules_file_deletion_events_unlinkat
    - low_complexity
    - low_disruption
    - medium_severity
    - reboot_required
    - restrict_strategy

  - name: Perform remediation of Audit rules for unlinkat for 32bit platform
    block:

    - name: Declare list of syscalls
      ansible.builtin.set_fact:
        syscalls:
        - unlinkat
        syscall_grouping:
        - unlink
        - unlinkat
        - rename
        - renameat
        - renameat2
        - rmdir

    - name: Check existence of unlinkat in /etc/audit/rules.d/
      ansible.builtin.find:
        paths: /etc/audit/rules.d
        contains: -a always,exit -F arch=b32(( -S |,)\w+)*(( -S |,){{ item }})+((
          -S |,)\w+)* -F auid>=1000 -F auid!=unset (-k\s+|-F\s+key=)\S+\s*$
        patterns: '*.rules'
      register: find_command
      loop: '{{ (syscall_grouping + syscalls) | unique }}'

    - name: Reset syscalls found per file
      ansible.builtin.set_fact:
        syscalls_per_file: {}
        found_paths_dict: {}

    - name: Declare syscalls found per file
      ansible.builtin.set_fact: syscalls_per_file="{{ syscalls_per_file | combine(
        {item.files[0].path :[item.item] + syscalls_per_file.get(item.files[0].path,
        []) } ) }}"
      loop: '{{ find_command.results | selectattr(''matched'') | list }}'

    - name: Declare files where syscalls were found
      ansible.builtin.set_fact: found_paths="{{ find_command.results | map(attribute='files')
        | flatten | map(attribute='path') | list }}"

    - name: Count occurrences of syscalls in paths
      ansible.builtin.set_fact: found_paths_dict="{{ found_paths_dict | combine({
        item:1+found_paths_dict.get(item, 0) }) }}"
      loop: '{{ find_command.results | map(attribute=''files'') | flatten | map(attribute=''path'')
        | list }}'

    - name: Get path with most syscalls
      ansible.builtin.set_fact: audit_file="{{ (found_paths_dict | dict2items() |
        sort(attribute='value') | last).key }}"
      when: found_paths | length >= 1

    - name: No file with syscall found, set path to /etc/audit/rules.d/delete.rules
      ansible.builtin.set_fact: audit_file="/etc/audit/rules.d/delete.rules"
      when: found_paths | length == 0

    - name: Declare found syscalls
      ansible.builtin.set_fact: syscalls_found="{{ find_command.results | selectattr('matched')
        | map(attribute='item') | list }}"

    - name: Declare missing syscalls
      ansible.builtin.set_fact: missing_syscalls="{{ syscalls | difference(syscalls_found)
        }}"

    - name: Replace the audit rule in {{ audit_file }}
      ansible.builtin.lineinfile:
        path: '{{ audit_file }}'
        regexp: (-a always,exit -F arch=b32)(?=.*(?:(?:-S |,)(?:{{ syscalls_per_file[audit_file]
          | join("|") }}))\b)((?:( -S |,)\w+)+)( -F auid>=1000 -F auid!=unset (?:-k
          |-F key=)\w+)
        line: \1\2\3{{ missing_syscalls | join("\3") }}\4
        backrefs: true
        state: present
        mode: g-rwx,o-rwx
      when: syscalls_found | length > 0 and missing_syscalls | length > 0

    - name: Add the audit rule to {{ audit_file }}
      ansible.builtin.lineinfile:
        path: '{{ audit_file }}'
        line: -a always,exit -F arch=b32 -S {{ syscalls | join(',') }} -F auid>=1000
          -F auid!=unset -F key=delete
        create: true
        mode: g-rwx,o-rwx
        state: present
      when: syscalls_found | length == 0

    - name: Declare list of syscalls
      ansible.builtin.set_fact:
        syscalls:
        - unlinkat
        syscall_grouping:
        - unlink
        - unlinkat
        - rename
        - renameat
        - renameat2
        - rmdir

    - name: Check existence of unlinkat in /etc/audit/audit.rules
      ansible.builtin.find:
        paths: /etc/audit
        contains: -a always,exit -F arch=b32(( -S |,)\w+)*(( -S |,){{ item }})+((
          -S |,)\w+)* -F auid>=1000 -F auid!=unset (-k\s+|-F\s+key=)\S+\s*$
        patterns: audit.rules
      register: find_command
      loop: '{{ (syscall_grouping + syscalls) | unique }}'

    - name: Set path to /etc/audit/audit.rules
      ansible.builtin.set_fact: audit_file="/etc/audit/audit.rules"

    - name: Declare found syscalls
      ansible.builtin.set_fact: syscalls_found="{{ find_command.results | selectattr('matched')
        | map(attribute='item') | list }}"

    - name: Declare missing syscalls
      ansible.builtin.set_fact: missing_syscalls="{{ syscalls | difference(syscalls_found)
        }}"

    - name: Replace the audit rule in {{ audit_file }}
      ansible.builtin.lineinfile:
        path: '{{ audit_file }}'
        regexp: (-a always,exit -F arch=b32)(?=.*(?:(?:-S |,)(?:{{ syscalls_found
          | join("|") }}))\b)((?:( -S |,)\w+)+)( -F auid>=1000 -F auid!=unset (?:-k
          |-F key=)\w+)
        line: \1\2\3{{ missing_syscalls | join("\3") }}\4
        backrefs: true
        state: present
        mode: g-rwx,o-rwx
      when: syscalls_found | length > 0 and missing_syscalls | length > 0

    - name: Add the audit rule to {{ audit_file }}
      ansible.builtin.lineinfile:
        path: '{{ audit_file }}'
        line: -a always,exit -F arch=b32 -S {{ syscalls | join(',') }} -F auid>=1000
          -F auid!=unset -F key=delete
        create: true
        mode: g-rwx,o-rwx
        state: present
      when: syscalls_found | length == 0
    when:
    - '"audit" in ansible_facts.packages'
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-000680
    - NIST-800-171-3.1.7
    - NIST-800-53-AU-12(c)
    - NIST-800-53-AU-2(d)
    - NIST-800-53-CM-6(a)
    - PCI-DSS-Req-10.2.7
    - PCI-DSSv4-10.2
    - PCI-DSSv4-10.2.1
    - PCI-DSSv4-10.2.1.7
    - audit_rules_file_deletion_events_unlinkat
    - low_complexity
    - low_disruption
    - medium_severity
    - reboot_required
    - restrict_strategy

  - name: Perform remediation of Audit rules for unlinkat for 64bit platform
    block:

    - name: Declare list of syscalls
      ansible.builtin.set_fact:
        syscalls:
        - unlinkat
        syscall_grouping:
        - unlink
        - unlinkat
        - rename
        - renameat
        - renameat2
        - rmdir

    - name: Check existence of unlinkat in /etc/audit/rules.d/
      ansible.builtin.find:
        paths: /etc/audit/rules.d
        contains: -a always,exit -F arch=b64(( -S |,)\w+)*(( -S |,){{ item }})+((
          -S |,)\w+)* -F auid>=1000 -F auid!=unset (-k\s+|-F\s+key=)\S+\s*$
        patterns: '*.rules'
      register: find_command
      loop: '{{ (syscall_grouping + syscalls) | unique }}'

    - name: Reset syscalls found per file
      ansible.builtin.set_fact:
        syscalls_per_file: {}
        found_paths_dict: {}

    - name: Declare syscalls found per file
      ansible.builtin.set_fact: syscalls_per_file="{{ syscalls_per_file | combine(
        {item.files[0].path :[item.item] + syscalls_per_file.get(item.files[0].path,
        []) } ) }}"
      loop: '{{ find_command.results | selectattr(''matched'') | list }}'

    - name: Declare files where syscalls were found
      ansible.builtin.set_fact: found_paths="{{ find_command.results | map(attribute='files')
        | flatten | map(attribute='path') | list }}"

    - name: Count occurrences of syscalls in paths
      ansible.builtin.set_fact: found_paths_dict="{{ found_paths_dict | combine({
        item:1+found_paths_dict.get(item, 0) }) }}"
      loop: '{{ find_command.results | map(attribute=''files'') | flatten | map(attribute=''path'')
        | list }}'

    - name: Get path with most syscalls
      ansible.builtin.set_fact: audit_file="{{ (found_paths_dict | dict2items() |
        sort(attribute='value') | last).key }}"
      when: found_paths | length >= 1

    - name: No file with syscall found, set path to /etc/audit/rules.d/delete.rules
      ansible.builtin.set_fact: audit_file="/etc/audit/rules.d/delete.rules"
      when: found_paths | length == 0

    - name: Declare found syscalls
      ansible.builtin.set_fact: syscalls_found="{{ find_command.results | selectattr('matched')
        | map(attribute='item') | list }}"

    - name: Declare missing syscalls
      ansible.builtin.set_fact: missing_syscalls="{{ syscalls | difference(syscalls_found)
        }}"

    - name: Replace the audit rule in {{ audit_file }}
      ansible.builtin.lineinfile:
        path: '{{ audit_file }}'
        regexp: (-a always,exit -F arch=b64)(?=.*(?:(?:-S |,)(?:{{ syscalls_per_file[audit_file]
          | join("|") }}))\b)((?:( -S |,)\w+)+)( -F auid>=1000 -F auid!=unset (?:-k
          |-F key=)\w+)
        line: \1\2\3{{ missing_syscalls | join("\3") }}\4
        backrefs: true
        state: present
        mode: g-rwx,o-rwx
      when: syscalls_found | length > 0 and missing_syscalls | length > 0

    - name: Add the audit rule to {{ audit_file }}
      ansible.builtin.lineinfile:
        path: '{{ audit_file }}'
        line: -a always,exit -F arch=b64 -S {{ syscalls | join(',') }} -F auid>=1000
          -F auid!=unset -F key=delete
        create: true
        mode: g-rwx,o-rwx
        state: present
      when: syscalls_found | length == 0

    - name: Declare list of syscalls
      ansible.builtin.set_fact:
        syscalls:
        - unlinkat
        syscall_grouping:
        - unlink
        - unlinkat
        - rename
        - renameat
        - renameat2
        - rmdir

    - name: Check existence of unlinkat in /etc/audit/audit.rules
      ansible.builtin.find:
        paths: /etc/audit
        contains: -a always,exit -F arch=b64(( -S |,)\w+)*(( -S |,){{ item }})+((
          -S |,)\w+)* -F auid>=1000 -F auid!=unset (-k\s+|-F\s+key=)\S+\s*$
        patterns: audit.rules
      register: find_command
      loop: '{{ (syscall_grouping + syscalls) | unique }}'

    - name: Set path to /etc/audit/audit.rules
      ansible.builtin.set_fact: audit_file="/etc/audit/audit.rules"

    - name: Declare found syscalls
      ansible.builtin.set_fact: syscalls_found="{{ find_command.results | selectattr('matched')
        | map(attribute='item') | list }}"

    - name: Declare missing syscalls
      ansible.builtin.set_fact: missing_syscalls="{{ syscalls | difference(syscalls_found)
        }}"

    - name: Replace the audit rule in {{ audit_file }}
      ansible.builtin.lineinfile:
        path: '{{ audit_file }}'
        regexp: (-a always,exit -F arch=b64)(?=.*(?:(?:-S |,)(?:{{ syscalls_found
          | join("|") }}))\b)((?:( -S |,)\w+)+)( -F auid>=1000 -F auid!=unset (?:-k
          |-F key=)\w+)
        line: \1\2\3{{ missing_syscalls | join("\3") }}\4
        backrefs: true
        state: present
        mode: g-rwx,o-rwx
      when: syscalls_found | length > 0 and missing_syscalls | length > 0

    - name: Add the audit rule to {{ audit_file }}
      ansible.builtin.lineinfile:
        path: '{{ audit_file }}'
        line: -a always,exit -F arch=b64 -S {{ syscalls | join(',') }} -F auid>=1000
          -F auid!=unset -F key=delete
        create: true
        mode: g-rwx,o-rwx
        state: present
      when: syscalls_found | length == 0
    when:
    - '"audit" in ansible_facts.packages'
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - audit_arch == "b64"
    tags:
    - DISA-STIG-OL09-00-000680
    - NIST-800-171-3.1.7
    - NIST-800-53-AU-12(c)
    - NIST-800-53-AU-2(d)
    - NIST-800-53-CM-6(a)
    - PCI-DSS-Req-10.2.7
    - PCI-DSSv4-10.2
    - PCI-DSSv4-10.2.1
    - PCI-DSSv4-10.2.1.7
    - audit_rules_file_deletion_events_unlinkat
    - low_complexity
    - low_disruption
    - medium_severity
    - reboot_required
    - restrict_strategy

  - name: Set architecture for audit creat tasks
    ansible.builtin.set_fact:
      audit_arch: b64
    when:
    - '"audit" in ansible_facts.packages'
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - not ( ansible_architecture == "aarch64" )
    - ansible_architecture == "aarch64" or ansible_architecture == "ppc64" or ansible_architecture
      == "ppc64le" or ansible_architecture == "s390x" or ansible_architecture == "x86_64"
    tags:
    - DISA-STIG-OL09-00-000635
    - NIST-800-171-3.1.7
    - NIST-800-53-AU-12(c)
    - NIST-800-53-AU-2(d)
    - NIST-800-53-CM-6(a)
    - PCI-DSS-Req-10.2.1
    - PCI-DSS-Req-10.2.4
    - audit_rules_unsuccessful_file_modification_creat
    - low_complexity
    - low_disruption
    - medium_severity
    - reboot_required
    - restrict_strategy

  - name: Perform remediation of Audit rules for creat EACCES for 32bit platform
    block:

    - name: Declare list of syscalls
      ansible.builtin.set_fact:
        syscalls:
        - creat
        syscall_grouping:
        - creat
        - ftruncate
        - truncate
        - open
        - openat
        - open_by_handle_at

    - name: Check existence of creat in /etc/audit/rules.d/
      ansible.builtin.find:
        paths: /etc/audit/rules.d
        contains: -a always,exit -F arch=b32(( -S |,)\w+)*(( -S |,){{ item }})+((
          -S |,)\w+)* -F exit=-EACCES -F auid>=1000 -F auid!=unset (-k\s+|-F\s+key=)\S+\s*$
        patterns: '*.rules'
      register: find_command
      loop: '{{ (syscall_grouping + syscalls) | unique }}'

    - name: Reset syscalls found per file
      ansible.builtin.set_fact:
        syscalls_per_file: {}
        found_paths_dict: {}

    - name: Declare syscalls found per file
      ansible.builtin.set_fact: syscalls_per_file="{{ syscalls_per_file | combine(
        {item.files[0].path :[item.item] + syscalls_per_file.get(item.files[0].path,
        []) } ) }}"
      loop: '{{ find_command.results | selectattr(''matched'') | list }}'

    - name: Declare files where syscalls were found
      ansible.builtin.set_fact: found_paths="{{ find_command.results | map(attribute='files')
        | flatten | map(attribute='path') | list }}"

    - name: Count occurrences of syscalls in paths
      ansible.builtin.set_fact: found_paths_dict="{{ found_paths_dict | combine({
        item:1+found_paths_dict.get(item, 0) }) }}"
      loop: '{{ find_command.results | map(attribute=''files'') | flatten | map(attribute=''path'')
        | list }}'

    - name: Get path with most syscalls
      ansible.builtin.set_fact: audit_file="{{ (found_paths_dict | dict2items() |
        sort(attribute='value') | last).key }}"
      when: found_paths | length >= 1

    - name: No file with syscall found, set path to /etc/audit/rules.d/access.rules
      ansible.builtin.set_fact: audit_file="/etc/audit/rules.d/access.rules"
      when: found_paths | length == 0

    - name: Declare found syscalls
      ansible.builtin.set_fact: syscalls_found="{{ find_command.results | selectattr('matched')
        | map(attribute='item') | list }}"

    - name: Declare missing syscalls
      ansible.builtin.set_fact: missing_syscalls="{{ syscalls | difference(syscalls_found)
        }}"

    - name: Replace the audit rule in {{ audit_file }}
      ansible.builtin.lineinfile:
        path: '{{ audit_file }}'
        regexp: (-a always,exit -F arch=b32)(?=.*(?:(?:-S |,)(?:{{ syscalls_per_file[audit_file]
          | join("|") }}))\b)((?:( -S |,)\w+)+)( -F exit=-EACCES -F auid>=1000 -F
          auid!=unset (?:-k |-F key=)\w+)
        line: \1\2\3{{ missing_syscalls | join("\3") }}\4
        backrefs: true
        state: present
        mode: g-rwx,o-rwx
      when: syscalls_found | length > 0 and missing_syscalls | length > 0

    - name: Add the audit rule to {{ audit_file }}
      ansible.builtin.lineinfile:
        path: '{{ audit_file }}'
        line: -a always,exit -F arch=b32 -S {{ syscalls | join(',') }} -F exit=-EACCES
          -F auid>=1000 -F auid!=unset -F key=access
        create: true
        mode: g-rwx,o-rwx
        state: present
      when: syscalls_found | length == 0

    - name: Declare list of syscalls
      ansible.builtin.set_fact:
        syscalls:
        - creat
        syscall_grouping:
        - creat
        - ftruncate
        - truncate
        - open
        - openat
        - open_by_handle_at

    - name: Check existence of creat in /etc/audit/audit.rules
      ansible.builtin.find:
        paths: /etc/audit
        contains: -a always,exit -F arch=b32(( -S |,)\w+)*(( -S |,){{ item }})+((
          -S |,)\w+)* -F exit=-EACCES -F auid>=1000 -F auid!=unset (-k\s+|-F\s+key=)\S+\s*$
        patterns: audit.rules
      register: find_command
      loop: '{{ (syscall_grouping + syscalls) | unique }}'

    - name: Set path to /etc/audit/audit.rules
      ansible.builtin.set_fact: audit_file="/etc/audit/audit.rules"

    - name: Declare found syscalls
      ansible.builtin.set_fact: syscalls_found="{{ find_command.results | selectattr('matched')
        | map(attribute='item') | list }}"

    - name: Declare missing syscalls
      ansible.builtin.set_fact: missing_syscalls="{{ syscalls | difference(syscalls_found)
        }}"

    - name: Replace the audit rule in {{ audit_file }}
      ansible.builtin.lineinfile:
        path: '{{ audit_file }}'
        regexp: (-a always,exit -F arch=b32)(?=.*(?:(?:-S |,)(?:{{ syscalls_found
          | join("|") }}))\b)((?:( -S |,)\w+)+)( -F exit=-EACCES -F auid>=1000 -F
          auid!=unset (?:-k |-F key=)\w+)
        line: \1\2\3{{ missing_syscalls | join("\3") }}\4
        backrefs: true
        state: present
        mode: g-rwx,o-rwx
      when: syscalls_found | length > 0 and missing_syscalls | length > 0

    - name: Add the audit rule to {{ audit_file }}
      ansible.builtin.lineinfile:
        path: '{{ audit_file }}'
        line: -a always,exit -F arch=b32 -S {{ syscalls | join(',') }} -F exit=-EACCES
          -F auid>=1000 -F auid!=unset -F key=access
        create: true
        mode: g-rwx,o-rwx
        state: present
      when: syscalls_found | length == 0
    when:
    - '"audit" in ansible_facts.packages'
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - not ( ansible_architecture == "aarch64" )
    tags:
    - DISA-STIG-OL09-00-000635
    - NIST-800-171-3.1.7
    - NIST-800-53-AU-12(c)
    - NIST-800-53-AU-2(d)
    - NIST-800-53-CM-6(a)
    - PCI-DSS-Req-10.2.1
    - PCI-DSS-Req-10.2.4
    - audit_rules_unsuccessful_file_modification_creat
    - low_complexity
    - low_disruption
    - medium_severity
    - reboot_required
    - restrict_strategy

  - name: Perform remediation of Audit rules for creat EACCES for 64bit platform
    block:

    - name: Declare list of syscalls
      ansible.builtin.set_fact:
        syscalls:
        - creat
        syscall_grouping:
        - creat
        - ftruncate
        - truncate
        - open
        - openat
        - open_by_handle_at

    - name: Check existence of creat in /etc/audit/rules.d/
      ansible.builtin.find:
        paths: /etc/audit/rules.d
        contains: -a always,exit -F arch=b64(( -S |,)\w+)*(( -S |,){{ item }})+((
          -S |,)\w+)* -F exit=-EACCES -F auid>=1000 -F auid!=unset (-k\s+|-F\s+key=)\S+\s*$
        patterns: '*.rules'
      register: find_command
      loop: '{{ (syscall_grouping + syscalls) | unique }}'

    - name: Reset syscalls found per file
      ansible.builtin.set_fact:
        syscalls_per_file: {}
        found_paths_dict: {}

    - name: Declare syscalls found per file
      ansible.builtin.set_fact: syscalls_per_file="{{ syscalls_per_file | combine(
        {item.files[0].path :[item.item] + syscalls_per_file.get(item.files[0].path,
        []) } ) }}"
      loop: '{{ find_command.results | selectattr(''matched'') | list }}'

    - name: Declare files where syscalls were found
      ansible.builtin.set_fact: found_paths="{{ find_command.results | map(attribute='files')
        | flatten | map(attribute='path') | list }}"

    - name: Count occurrences of syscalls in paths
      ansible.builtin.set_fact: found_paths_dict="{{ found_paths_dict | combine({
        item:1+found_paths_dict.get(item, 0) }) }}"
      loop: '{{ find_command.results | map(attribute=''files'') | flatten | map(attribute=''path'')
        | list }}'

    - name: Get path with most syscalls
      ansible.builtin.set_fact: audit_file="{{ (found_paths_dict | dict2items() |
        sort(attribute='value') | last).key }}"
      when: found_paths | length >= 1

    - name: No file with syscall found, set path to /etc/audit/rules.d/access.rules
      ansible.builtin.set_fact: audit_file="/etc/audit/rules.d/access.rules"
      when: found_paths | length == 0

    - name: Declare found syscalls
      ansible.builtin.set_fact: syscalls_found="{{ find_command.results | selectattr('matched')
        | map(attribute='item') | list }}"

    - name: Declare missing syscalls
      ansible.builtin.set_fact: missing_syscalls="{{ syscalls | difference(syscalls_found)
        }}"

    - name: Replace the audit rule in {{ audit_file }}
      ansible.builtin.lineinfile:
        path: '{{ audit_file }}'
        regexp: (-a always,exit -F arch=b64)(?=.*(?:(?:-S |,)(?:{{ syscalls_per_file[audit_file]
          | join("|") }}))\b)((?:( -S |,)\w+)+)( -F exit=-EACCES -F auid>=1000 -F
          auid!=unset (?:-k |-F key=)\w+)
        line: \1\2\3{{ missing_syscalls | join("\3") }}\4
        backrefs: true
        state: present
        mode: g-rwx,o-rwx
      when: syscalls_found | length > 0 and missing_syscalls | length > 0

    - name: Add the audit rule to {{ audit_file }}
      ansible.builtin.lineinfile:
        path: '{{ audit_file }}'
        line: -a always,exit -F arch=b64 -S {{ syscalls | join(',') }} -F exit=-EACCES
          -F auid>=1000 -F auid!=unset -F key=access
        create: true
        mode: g-rwx,o-rwx
        state: present
      when: syscalls_found | length == 0

    - name: Declare list of syscalls
      ansible.builtin.set_fact:
        syscalls:
        - creat
        syscall_grouping:
        - creat
        - ftruncate
        - truncate
        - open
        - openat
        - open_by_handle_at

    - name: Check existence of creat in /etc/audit/audit.rules
      ansible.builtin.find:
        paths: /etc/audit
        contains: -a always,exit -F arch=b64(( -S |,)\w+)*(( -S |,){{ item }})+((
          -S |,)\w+)* -F exit=-EACCES -F auid>=1000 -F auid!=unset (-k\s+|-F\s+key=)\S+\s*$
        patterns: audit.rules
      register: find_command
      loop: '{{ (syscall_grouping + syscalls) | unique }}'

    - name: Set path to /etc/audit/audit.rules
      ansible.builtin.set_fact: audit_file="/etc/audit/audit.rules"

    - name: Declare found syscalls
      ansible.builtin.set_fact: syscalls_found="{{ find_command.results | selectattr('matched')
        | map(attribute='item') | list }}"

    - name: Declare missing syscalls
      ansible.builtin.set_fact: missing_syscalls="{{ syscalls | difference(syscalls_found)
        }}"

    - name: Replace the audit rule in {{ audit_file }}
      ansible.builtin.lineinfile:
        path: '{{ audit_file }}'
        regexp: (-a always,exit -F arch=b64)(?=.*(?:(?:-S |,)(?:{{ syscalls_found
          | join("|") }}))\b)((?:( -S |,)\w+)+)( -F exit=-EACCES -F auid>=1000 -F
          auid!=unset (?:-k |-F key=)\w+)
        line: \1\2\3{{ missing_syscalls | join("\3") }}\4
        backrefs: true
        state: present
        mode: g-rwx,o-rwx
      when: syscalls_found | length > 0 and missing_syscalls | length > 0

    - name: Add the audit rule to {{ audit_file }}
      ansible.builtin.lineinfile:
        path: '{{ audit_file }}'
        line: -a always,exit -F arch=b64 -S {{ syscalls | join(',') }} -F exit=-EACCES
          -F auid>=1000 -F auid!=unset -F key=access
        create: true
        mode: g-rwx,o-rwx
        state: present
      when: syscalls_found | length == 0
    when:
    - '"audit" in ansible_facts.packages'
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - not ( ansible_architecture == "aarch64" )
    - audit_arch == "b64"
    tags:
    - DISA-STIG-OL09-00-000635
    - NIST-800-171-3.1.7
    - NIST-800-53-AU-12(c)
    - NIST-800-53-AU-2(d)
    - NIST-800-53-CM-6(a)
    - PCI-DSS-Req-10.2.1
    - PCI-DSS-Req-10.2.4
    - audit_rules_unsuccessful_file_modification_creat
    - low_complexity
    - low_disruption
    - medium_severity
    - reboot_required
    - restrict_strategy

  - name: Perform remediation of Audit rules for creat EPERM for 32bit platform
    block:

    - name: Declare list of syscalls
      ansible.builtin.set_fact:
        syscalls:
        - creat
        syscall_grouping:
        - creat
        - ftruncate
        - truncate
        - open
        - openat
        - open_by_handle_at

    - name: Check existence of creat in /etc/audit/rules.d/
      ansible.builtin.find:
        paths: /etc/audit/rules.d
        contains: -a always,exit -F arch=b32(( -S |,)\w+)*(( -S |,){{ item }})+((
          -S |,)\w+)* -F exit=-EPERM -F auid>=1000 -F auid!=unset (-k\s+|-F\s+key=)\S+\s*$
        patterns: '*.rules'
      register: find_command
      loop: '{{ (syscall_grouping + syscalls) | unique }}'

    - name: Reset syscalls found per file
      ansible.builtin.set_fact:
        syscalls_per_file: {}
        found_paths_dict: {}

    - name: Declare syscalls found per file
      ansible.builtin.set_fact: syscalls_per_file="{{ syscalls_per_file | combine(
        {item.files[0].path :[item.item] + syscalls_per_file.get(item.files[0].path,
        []) } ) }}"
      loop: '{{ find_command.results | selectattr(''matched'') | list }}'

    - name: Declare files where syscalls were found
      ansible.builtin.set_fact: found_paths="{{ find_command.results | map(attribute='files')
        | flatten | map(attribute='path') | list }}"

    - name: Count occurrences of syscalls in paths
      ansible.builtin.set_fact: found_paths_dict="{{ found_paths_dict | combine({
        item:1+found_paths_dict.get(item, 0) }) }}"
      loop: '{{ find_command.results | map(attribute=''files'') | flatten | map(attribute=''path'')
        | list }}'

    - name: Get path with most syscalls
      ansible.builtin.set_fact: audit_file="{{ (found_paths_dict | dict2items() |
        sort(attribute='value') | last).key }}"
      when: found_paths | length >= 1

    - name: No file with syscall found, set path to /etc/audit/rules.d/access.rules
      ansible.builtin.set_fact: audit_file="/etc/audit/rules.d/access.rules"
      when: found_paths | length == 0

    - name: Declare found syscalls
      ansible.builtin.set_fact: syscalls_found="{{ find_command.results | selectattr('matched')
        | map(attribute='item') | list }}"

    - name: Declare missing syscalls
      ansible.builtin.set_fact: missing_syscalls="{{ syscalls | difference(syscalls_found)
        }}"

    - name: Replace the audit rule in {{ audit_file }}
      ansible.builtin.lineinfile:
        path: '{{ audit_file }}'
        regexp: (-a always,exit -F arch=b32)(?=.*(?:(?:-S |,)(?:{{ syscalls_per_file[audit_file]
          | join("|") }}))\b)((?:( -S |,)\w+)+)( -F exit=-EPERM -F auid>=1000 -F auid!=unset
          (?:-k |-F key=)\w+)
        line: \1\2\3{{ missing_syscalls | join("\3") }}\4
        backrefs: true
        state: present
        mode: g-rwx,o-rwx
      when: syscalls_found | length > 0 and missing_syscalls | length > 0

    - name: Add the audit rule to {{ audit_file }}
      ansible.builtin.lineinfile:
        path: '{{ audit_file }}'
        line: -a always,exit -F arch=b32 -S {{ syscalls | join(',') }} -F exit=-EPERM
          -F auid>=1000 -F auid!=unset -F key=access
        create: true
        mode: g-rwx,o-rwx
        state: present
      when: syscalls_found | length == 0

    - name: Declare list of syscalls
      ansible.builtin.set_fact:
        syscalls:
        - creat
        syscall_grouping:
        - creat
        - ftruncate
        - truncate
        - open
        - openat
        - open_by_handle_at

    - name: Check existence of creat in /etc/audit/audit.rules
      ansible.builtin.find:
        paths: /etc/audit
        contains: -a always,exit -F arch=b32(( -S |,)\w+)*(( -S |,){{ item }})+((
          -S |,)\w+)* -F exit=-EPERM -F auid>=1000 -F auid!=unset (-k\s+|-F\s+key=)\S+\s*$
        patterns: audit.rules
      register: find_command
      loop: '{{ (syscall_grouping + syscalls) | unique }}'

    - name: Set path to /etc/audit/audit.rules
      ansible.builtin.set_fact: audit_file="/etc/audit/audit.rules"

    - name: Declare found syscalls
      ansible.builtin.set_fact: syscalls_found="{{ find_command.results | selectattr('matched')
        | map(attribute='item') | list }}"

    - name: Declare missing syscalls
      ansible.builtin.set_fact: missing_syscalls="{{ syscalls | difference(syscalls_found)
        }}"

    - name: Replace the audit rule in {{ audit_file }}
      ansible.builtin.lineinfile:
        path: '{{ audit_file }}'
        regexp: (-a always,exit -F arch=b32)(?=.*(?:(?:-S |,)(?:{{ syscalls_found
          | join("|") }}))\b)((?:( -S |,)\w+)+)( -F exit=-EPERM -F auid>=1000 -F auid!=unset
          (?:-k |-F key=)\w+)
        line: \1\2\3{{ missing_syscalls | join("\3") }}\4
        backrefs: true
        state: present
        mode: g-rwx,o-rwx
      when: syscalls_found | length > 0 and missing_syscalls | length > 0

    - name: Add the audit rule to {{ audit_file }}
      ansible.builtin.lineinfile:
        path: '{{ audit_file }}'
        line: -a always,exit -F arch=b32 -S {{ syscalls | join(',') }} -F exit=-EPERM
          -F auid>=1000 -F auid!=unset -F key=access
        create: true
        mode: g-rwx,o-rwx
        state: present
      when: syscalls_found | length == 0
    when:
    - '"audit" in ansible_facts.packages'
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - not ( ansible_architecture == "aarch64" )
    tags:
    - DISA-STIG-OL09-00-000635
    - NIST-800-171-3.1.7
    - NIST-800-53-AU-12(c)
    - NIST-800-53-AU-2(d)
    - NIST-800-53-CM-6(a)
    - PCI-DSS-Req-10.2.1
    - PCI-DSS-Req-10.2.4
    - audit_rules_unsuccessful_file_modification_creat
    - low_complexity
    - low_disruption
    - medium_severity
    - reboot_required
    - restrict_strategy

  - name: Perform remediation of Audit rules for creat EPERM for 64bit platform
    block:

    - name: Declare list of syscalls
      ansible.builtin.set_fact:
        syscalls:
        - creat
        syscall_grouping:
        - creat
        - ftruncate
        - truncate
        - open
        - openat
        - open_by_handle_at

    - name: Check existence of creat in /etc/audit/rules.d/
      ansible.builtin.find:
        paths: /etc/audit/rules.d
        contains: -a always,exit -F arch=b64(( -S |,)\w+)*(( -S |,){{ item }})+((
          -S |,)\w+)* -F exit=-EPERM -F auid>=1000 -F auid!=unset (-k\s+|-F\s+key=)\S+\s*$
        patterns: '*.rules'
      register: find_command
      loop: '{{ (syscall_grouping + syscalls) | unique }}'

    - name: Reset syscalls found per file
      ansible.builtin.set_fact:
        syscalls_per_file: {}
        found_paths_dict: {}

    - name: Declare syscalls found per file
      ansible.builtin.set_fact: syscalls_per_file="{{ syscalls_per_file | combine(
        {item.files[0].path :[item.item] + syscalls_per_file.get(item.files[0].path,
        []) } ) }}"
      loop: '{{ find_command.results | selectattr(''matched'') | list }}'

    - name: Declare files where syscalls were found
      ansible.builtin.set_fact: found_paths="{{ find_command.results | map(attribute='files')
        | flatten | map(attribute='path') | list }}"

    - name: Count occurrences of syscalls in paths
      ansible.builtin.set_fact: found_paths_dict="{{ found_paths_dict | combine({
        item:1+found_paths_dict.get(item, 0) }) }}"
      loop: '{{ find_command.results | map(attribute=''files'') | flatten | map(attribute=''path'')
        | list }}'

    - name: Get path with most syscalls
      ansible.builtin.set_fact: audit_file="{{ (found_paths_dict | dict2items() |
        sort(attribute='value') | last).key }}"
      when: found_paths | length >= 1

    - name: No file with syscall found, set path to /etc/audit/rules.d/access.rules
      ansible.builtin.set_fact: audit_file="/etc/audit/rules.d/access.rules"
      when: found_paths | length == 0

    - name: Declare found syscalls
      ansible.builtin.set_fact: syscalls_found="{{ find_command.results | selectattr('matched')
        | map(attribute='item') | list }}"

    - name: Declare missing syscalls
      ansible.builtin.set_fact: missing_syscalls="{{ syscalls | difference(syscalls_found)
        }}"

    - name: Replace the audit rule in {{ audit_file }}
      ansible.builtin.lineinfile:
        path: '{{ audit_file }}'
        regexp: (-a always,exit -F arch=b64)(?=.*(?:(?:-S |,)(?:{{ syscalls_per_file[audit_file]
          | join("|") }}))\b)((?:( -S |,)\w+)+)( -F exit=-EPERM -F auid>=1000 -F auid!=unset
          (?:-k |-F key=)\w+)
        line: \1\2\3{{ missing_syscalls | join("\3") }}\4
        backrefs: true
        state: present
        mode: g-rwx,o-rwx
      when: syscalls_found | length > 0 and missing_syscalls | length > 0

    - name: Add the audit rule to {{ audit_file }}
      ansible.builtin.lineinfile:
        path: '{{ audit_file }}'
        line: -a always,exit -F arch=b64 -S {{ syscalls | join(',') }} -F exit=-EPERM
          -F auid>=1000 -F auid!=unset -F key=access
        create: true
        mode: g-rwx,o-rwx
        state: present
      when: syscalls_found | length == 0

    - name: Declare list of syscalls
      ansible.builtin.set_fact:
        syscalls:
        - creat
        syscall_grouping:
        - creat
        - ftruncate
        - truncate
        - open
        - openat
        - open_by_handle_at

    - name: Check existence of creat in /etc/audit/audit.rules
      ansible.builtin.find:
        paths: /etc/audit
        contains: -a always,exit -F arch=b64(( -S |,)\w+)*(( -S |,){{ item }})+((
          -S |,)\w+)* -F exit=-EPERM -F auid>=1000 -F auid!=unset (-k\s+|-F\s+key=)\S+\s*$
        patterns: audit.rules
      register: find_command
      loop: '{{ (syscall_grouping + syscalls) | unique }}'

    - name: Set path to /etc/audit/audit.rules
      ansible.builtin.set_fact: audit_file="/etc/audit/audit.rules"

    - name: Declare found syscalls
      ansible.builtin.set_fact: syscalls_found="{{ find_command.results | selectattr('matched')
        | map(attribute='item') | list }}"

    - name: Declare missing syscalls
      ansible.builtin.set_fact: missing_syscalls="{{ syscalls | difference(syscalls_found)
        }}"

    - name: Replace the audit rule in {{ audit_file }}
      ansible.builtin.lineinfile:
        path: '{{ audit_file }}'
        regexp: (-a always,exit -F arch=b64)(?=.*(?:(?:-S |,)(?:{{ syscalls_found
          | join("|") }}))\b)((?:( -S |,)\w+)+)( -F exit=-EPERM -F auid>=1000 -F auid!=unset
          (?:-k |-F key=)\w+)
        line: \1\2\3{{ missing_syscalls | join("\3") }}\4
        backrefs: true
        state: present
        mode: g-rwx,o-rwx
      when: syscalls_found | length > 0 and missing_syscalls | length > 0

    - name: Add the audit rule to {{ audit_file }}
      ansible.builtin.lineinfile:
        path: '{{ audit_file }}'
        line: -a always,exit -F arch=b64 -S {{ syscalls | join(',') }} -F exit=-EPERM
          -F auid>=1000 -F auid!=unset -F key=access
        create: true
        mode: g-rwx,o-rwx
        state: present
      when: syscalls_found | length == 0
    when:
    - '"audit" in ansible_facts.packages'
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - not ( ansible_architecture == "aarch64" )
    - audit_arch == "b64"
    tags:
    - DISA-STIG-OL09-00-000635
    - NIST-800-171-3.1.7
    - NIST-800-53-AU-12(c)
    - NIST-800-53-AU-2(d)
    - NIST-800-53-CM-6(a)
    - PCI-DSS-Req-10.2.1
    - PCI-DSS-Req-10.2.4
    - audit_rules_unsuccessful_file_modification_creat
    - low_complexity
    - low_disruption
    - medium_severity
    - reboot_required
    - restrict_strategy

  - name: Set architecture for audit ftruncate tasks
    ansible.builtin.set_fact:
      audit_arch: b64
    when:
    - '"audit" in ansible_facts.packages'
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - ansible_architecture == "aarch64" or ansible_architecture == "ppc64" or ansible_architecture
      == "ppc64le" or ansible_architecture == "s390x" or ansible_architecture == "x86_64"
    tags:
    - DISA-STIG-OL09-00-000635
    - NIST-800-171-3.1.7
    - NIST-800-53-AU-12(c)
    - NIST-800-53-AU-2(d)
    - NIST-800-53-CM-6(a)
    - PCI-DSS-Req-10.2.1
    - PCI-DSS-Req-10.2.4
    - audit_rules_unsuccessful_file_modification_ftruncate
    - low_complexity
    - low_disruption
    - medium_severity
    - reboot_required
    - restrict_strategy

  - name: Perform remediation of Audit rules for ftruncate EACCES for 32bit platform
    block:

    - name: Declare list of syscalls
      ansible.builtin.set_fact:
        syscalls:
        - ftruncate
        syscall_grouping:
        - creat
        - ftruncate
        - truncate
        - open
        - openat
        - open_by_handle_at

    - name: Check existence of ftruncate in /etc/audit/rules.d/
      ansible.builtin.find:
        paths: /etc/audit/rules.d
        contains: -a always,exit -F arch=b32(( -S |,)\w+)*(( -S |,){{ item }})+((
          -S |,)\w+)* -F exit=-EACCES -F auid>=1000 -F auid!=unset (-k\s+|-F\s+key=)\S+\s*$
        patterns: '*.rules'
      register: find_command
      loop: '{{ (syscall_grouping + syscalls) | unique }}'

    - name: Reset syscalls found per file
      ansible.builtin.set_fact:
        syscalls_per_file: {}
        found_paths_dict: {}

    - name: Declare syscalls found per file
      ansible.builtin.set_fact: syscalls_per_file="{{ syscalls_per_file | combine(
        {item.files[0].path :[item.item] + syscalls_per_file.get(item.files[0].path,
        []) } ) }}"
      loop: '{{ find_command.results | selectattr(''matched'') | list }}'

    - name: Declare files where syscalls were found
      ansible.builtin.set_fact: found_paths="{{ find_command.results | map(attribute='files')
        | flatten | map(attribute='path') | list }}"

    - name: Count occurrences of syscalls in paths
      ansible.builtin.set_fact: found_paths_dict="{{ found_paths_dict | combine({
        item:1+found_paths_dict.get(item, 0) }) }}"
      loop: '{{ find_command.results | map(attribute=''files'') | flatten | map(attribute=''path'')
        | list }}'

    - name: Get path with most syscalls
      ansible.builtin.set_fact: audit_file="{{ (found_paths_dict | dict2items() |
        sort(attribute='value') | last).key }}"
      when: found_paths | length >= 1

    - name: No file with syscall found, set path to /etc/audit/rules.d/access.rules
      ansible.builtin.set_fact: audit_file="/etc/audit/rules.d/access.rules"
      when: found_paths | length == 0

    - name: Declare found syscalls
      ansible.builtin.set_fact: syscalls_found="{{ find_command.results | selectattr('matched')
        | map(attribute='item') | list }}"

    - name: Declare missing syscalls
      ansible.builtin.set_fact: missing_syscalls="{{ syscalls | difference(syscalls_found)
        }}"

    - name: Replace the audit rule in {{ audit_file }}
      ansible.builtin.lineinfile:
        path: '{{ audit_file }}'
        regexp: (-a always,exit -F arch=b32)(?=.*(?:(?:-S |,)(?:{{ syscalls_per_file[audit_file]
          | join("|") }}))\b)((?:( -S |,)\w+)+)( -F exit=-EACCES -F auid>=1000 -F
          auid!=unset (?:-k |-F key=)\w+)
        line: \1\2\3{{ missing_syscalls | join("\3") }}\4
        backrefs: true
        state: present
        mode: g-rwx,o-rwx
      when: syscalls_found | length > 0 and missing_syscalls | length > 0

    - name: Add the audit rule to {{ audit_file }}
      ansible.builtin.lineinfile:
        path: '{{ audit_file }}'
        line: -a always,exit -F arch=b32 -S {{ syscalls | join(',') }} -F exit=-EACCES
          -F auid>=1000 -F auid!=unset -F key=access
        create: true
        mode: g-rwx,o-rwx
        state: present
      when: syscalls_found | length == 0

    - name: Declare list of syscalls
      ansible.builtin.set_fact:
        syscalls:
        - ftruncate
        syscall_grouping:
        - creat
        - ftruncate
        - truncate
        - open
        - openat
        - open_by_handle_at

    - name: Check existence of ftruncate in /etc/audit/audit.rules
      ansible.builtin.find:
        paths: /etc/audit
        contains: -a always,exit -F arch=b32(( -S |,)\w+)*(( -S |,){{ item }})+((
          -S |,)\w+)* -F exit=-EACCES -F auid>=1000 -F auid!=unset (-k\s+|-F\s+key=)\S+\s*$
        patterns: audit.rules
      register: find_command
      loop: '{{ (syscall_grouping + syscalls) | unique }}'

    - name: Set path to /etc/audit/audit.rules
      ansible.builtin.set_fact: audit_file="/etc/audit/audit.rules"

    - name: Declare found syscalls
      ansible.builtin.set_fact: syscalls_found="{{ find_command.results | selectattr('matched')
        | map(attribute='item') | list }}"

    - name: Declare missing syscalls
      ansible.builtin.set_fact: missing_syscalls="{{ syscalls | difference(syscalls_found)
        }}"

    - name: Replace the audit rule in {{ audit_file }}
      ansible.builtin.lineinfile:
        path: '{{ audit_file }}'
        regexp: (-a always,exit -F arch=b32)(?=.*(?:(?:-S |,)(?:{{ syscalls_found
          | join("|") }}))\b)((?:( -S |,)\w+)+)( -F exit=-EACCES -F auid>=1000 -F
          auid!=unset (?:-k |-F key=)\w+)
        line: \1\2\3{{ missing_syscalls | join("\3") }}\4
        backrefs: true
        state: present
        mode: g-rwx,o-rwx
      when: syscalls_found | length > 0 and missing_syscalls | length > 0

    - name: Add the audit rule to {{ audit_file }}
      ansible.builtin.lineinfile:
        path: '{{ audit_file }}'
        line: -a always,exit -F arch=b32 -S {{ syscalls | join(',') }} -F exit=-EACCES
          -F auid>=1000 -F auid!=unset -F key=access
        create: true
        mode: g-rwx,o-rwx
        state: present
      when: syscalls_found | length == 0
    when:
    - '"audit" in ansible_facts.packages'
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-000635
    - NIST-800-171-3.1.7
    - NIST-800-53-AU-12(c)
    - NIST-800-53-AU-2(d)
    - NIST-800-53-CM-6(a)
    - PCI-DSS-Req-10.2.1
    - PCI-DSS-Req-10.2.4
    - audit_rules_unsuccessful_file_modification_ftruncate
    - low_complexity
    - low_disruption
    - medium_severity
    - reboot_required
    - restrict_strategy

  - name: Perform remediation of Audit rules for ftruncate EACCES for 64bit platform
    block:

    - name: Declare list of syscalls
      ansible.builtin.set_fact:
        syscalls:
        - ftruncate
        syscall_grouping:
        - creat
        - ftruncate
        - truncate
        - open
        - openat
        - open_by_handle_at

    - name: Check existence of ftruncate in /etc/audit/rules.d/
      ansible.builtin.find:
        paths: /etc/audit/rules.d
        contains: -a always,exit -F arch=b64(( -S |,)\w+)*(( -S |,){{ item }})+((
          -S |,)\w+)* -F exit=-EACCES -F auid>=1000 -F auid!=unset (-k\s+|-F\s+key=)\S+\s*$
        patterns: '*.rules'
      register: find_command
      loop: '{{ (syscall_grouping + syscalls) | unique }}'

    - name: Reset syscalls found per file
      ansible.builtin.set_fact:
        syscalls_per_file: {}
        found_paths_dict: {}

    - name: Declare syscalls found per file
      ansible.builtin.set_fact: syscalls_per_file="{{ syscalls_per_file | combine(
        {item.files[0].path :[item.item] + syscalls_per_file.get(item.files[0].path,
        []) } ) }}"
      loop: '{{ find_command.results | selectattr(''matched'') | list }}'

    - name: Declare files where syscalls were found
      ansible.builtin.set_fact: found_paths="{{ find_command.results | map(attribute='files')
        | flatten | map(attribute='path') | list }}"

    - name: Count occurrences of syscalls in paths
      ansible.builtin.set_fact: found_paths_dict="{{ found_paths_dict | combine({
        item:1+found_paths_dict.get(item, 0) }) }}"
      loop: '{{ find_command.results | map(attribute=''files'') | flatten | map(attribute=''path'')
        | list }}'

    - name: Get path with most syscalls
      ansible.builtin.set_fact: audit_file="{{ (found_paths_dict | dict2items() |
        sort(attribute='value') | last).key }}"
      when: found_paths | length >= 1

    - name: No file with syscall found, set path to /etc/audit/rules.d/access.rules
      ansible.builtin.set_fact: audit_file="/etc/audit/rules.d/access.rules"
      when: found_paths | length == 0

    - name: Declare found syscalls
      ansible.builtin.set_fact: syscalls_found="{{ find_command.results | selectattr('matched')
        | map(attribute='item') | list }}"

    - name: Declare missing syscalls
      ansible.builtin.set_fact: missing_syscalls="{{ syscalls | difference(syscalls_found)
        }}"

    - name: Replace the audit rule in {{ audit_file }}
      ansible.builtin.lineinfile:
        path: '{{ audit_file }}'
        regexp: (-a always,exit -F arch=b64)(?=.*(?:(?:-S |,)(?:{{ syscalls_per_file[audit_file]
          | join("|") }}))\b)((?:( -S |,)\w+)+)( -F exit=-EACCES -F auid>=1000 -F
          auid!=unset (?:-k |-F key=)\w+)
        line: \1\2\3{{ missing_syscalls | join("\3") }}\4
        backrefs: true
        state: present
        mode: g-rwx,o-rwx
      when: syscalls_found | length > 0 and missing_syscalls | length > 0

    - name: Add the audit rule to {{ audit_file }}
      ansible.builtin.lineinfile:
        path: '{{ audit_file }}'
        line: -a always,exit -F arch=b64 -S {{ syscalls | join(',') }} -F exit=-EACCES
          -F auid>=1000 -F auid!=unset -F key=access
        create: true
        mode: g-rwx,o-rwx
        state: present
      when: syscalls_found | length == 0

    - name: Declare list of syscalls
      ansible.builtin.set_fact:
        syscalls:
        - ftruncate
        syscall_grouping:
        - creat
        - ftruncate
        - truncate
        - open
        - openat
        - open_by_handle_at

    - name: Check existence of ftruncate in /etc/audit/audit.rules
      ansible.builtin.find:
        paths: /etc/audit
        contains: -a always,exit -F arch=b64(( -S |,)\w+)*(( -S |,){{ item }})+((
          -S |,)\w+)* -F exit=-EACCES -F auid>=1000 -F auid!=unset (-k\s+|-F\s+key=)\S+\s*$
        patterns: audit.rules
      register: find_command
      loop: '{{ (syscall_grouping + syscalls) | unique }}'

    - name: Set path to /etc/audit/audit.rules
      ansible.builtin.set_fact: audit_file="/etc/audit/audit.rules"

    - name: Declare found syscalls
      ansible.builtin.set_fact: syscalls_found="{{ find_command.results | selectattr('matched')
        | map(attribute='item') | list }}"

    - name: Declare missing syscalls
      ansible.builtin.set_fact: missing_syscalls="{{ syscalls | difference(syscalls_found)
        }}"

    - name: Replace the audit rule in {{ audit_file }}
      ansible.builtin.lineinfile:
        path: '{{ audit_file }}'
        regexp: (-a always,exit -F arch=b64)(?=.*(?:(?:-S |,)(?:{{ syscalls_found
          | join("|") }}))\b)((?:( -S |,)\w+)+)( -F exit=-EACCES -F auid>=1000 -F
          auid!=unset (?:-k |-F key=)\w+)
        line: \1\2\3{{ missing_syscalls | join("\3") }}\4
        backrefs: true
        state: present
        mode: g-rwx,o-rwx
      when: syscalls_found | length > 0 and missing_syscalls | length > 0

    - name: Add the audit rule to {{ audit_file }}
      ansible.builtin.lineinfile:
        path: '{{ audit_file }}'
        line: -a always,exit -F arch=b64 -S {{ syscalls | join(',') }} -F exit=-EACCES
          -F auid>=1000 -F auid!=unset -F key=access
        create: true
        mode: g-rwx,o-rwx
        state: present
      when: syscalls_found | length == 0
    when:
    - '"audit" in ansible_facts.packages'
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - audit_arch == "b64"
    tags:
    - DISA-STIG-OL09-00-000635
    - NIST-800-171-3.1.7
    - NIST-800-53-AU-12(c)
    - NIST-800-53-AU-2(d)
    - NIST-800-53-CM-6(a)
    - PCI-DSS-Req-10.2.1
    - PCI-DSS-Req-10.2.4
    - audit_rules_unsuccessful_file_modification_ftruncate
    - low_complexity
    - low_disruption
    - medium_severity
    - reboot_required
    - restrict_strategy

  - name: Perform remediation of Audit rules for ftruncate EPERM for 32bit platform
    block:

    - name: Declare list of syscalls
      ansible.builtin.set_fact:
        syscalls:
        - ftruncate
        syscall_grouping:
        - creat
        - ftruncate
        - truncate
        - open
        - openat
        - open_by_handle_at

    - name: Check existence of ftruncate in /etc/audit/rules.d/
      ansible.builtin.find:
        paths: /etc/audit/rules.d
        contains: -a always,exit -F arch=b32(( -S |,)\w+)*(( -S |,){{ item }})+((
          -S |,)\w+)* -F exit=-EPERM -F auid>=1000 -F auid!=unset (-k\s+|-F\s+key=)\S+\s*$
        patterns: '*.rules'
      register: find_command
      loop: '{{ (syscall_grouping + syscalls) | unique }}'

    - name: Reset syscalls found per file
      ansible.builtin.set_fact:
        syscalls_per_file: {}
        found_paths_dict: {}

    - name: Declare syscalls found per file
      ansible.builtin.set_fact: syscalls_per_file="{{ syscalls_per_file | combine(
        {item.files[0].path :[item.item] + syscalls_per_file.get(item.files[0].path,
        []) } ) }}"
      loop: '{{ find_command.results | selectattr(''matched'') | list }}'

    - name: Declare files where syscalls were found
      ansible.builtin.set_fact: found_paths="{{ find_command.results | map(attribute='files')
        | flatten | map(attribute='path') | list }}"

    - name: Count occurrences of syscalls in paths
      ansible.builtin.set_fact: found_paths_dict="{{ found_paths_dict | combine({
        item:1+found_paths_dict.get(item, 0) }) }}"
      loop: '{{ find_command.results | map(attribute=''files'') | flatten | map(attribute=''path'')
        | list }}'

    - name: Get path with most syscalls
      ansible.builtin.set_fact: audit_file="{{ (found_paths_dict | dict2items() |
        sort(attribute='value') | last).key }}"
      when: found_paths | length >= 1

    - name: No file with syscall found, set path to /etc/audit/rules.d/access.rules
      ansible.builtin.set_fact: audit_file="/etc/audit/rules.d/access.rules"
      when: found_paths | length == 0

    - name: Declare found syscalls
      ansible.builtin.set_fact: syscalls_found="{{ find_command.results | selectattr('matched')
        | map(attribute='item') | list }}"

    - name: Declare missing syscalls
      ansible.builtin.set_fact: missing_syscalls="{{ syscalls | difference(syscalls_found)
        }}"

    - name: Replace the audit rule in {{ audit_file }}
      ansible.builtin.lineinfile:
        path: '{{ audit_file }}'
        regexp: (-a always,exit -F arch=b32)(?=.*(?:(?:-S |,)(?:{{ syscalls_per_file[audit_file]
          | join("|") }}))\b)((?:( -S |,)\w+)+)( -F exit=-EPERM -F auid>=1000 -F auid!=unset
          (?:-k |-F key=)\w+)
        line: \1\2\3{{ missing_syscalls | join("\3") }}\4
        backrefs: true
        state: present
        mode: g-rwx,o-rwx
      when: syscalls_found | length > 0 and missing_syscalls | length > 0

    - name: Add the audit rule to {{ audit_file }}
      ansible.builtin.lineinfile:
        path: '{{ audit_file }}'
        line: -a always,exit -F arch=b32 -S {{ syscalls | join(',') }} -F exit=-EPERM
          -F auid>=1000 -F auid!=unset -F key=access
        create: true
        mode: g-rwx,o-rwx
        state: present
      when: syscalls_found | length == 0

    - name: Declare list of syscalls
      ansible.builtin.set_fact:
        syscalls:
        - ftruncate
        syscall_grouping:
        - creat
        - ftruncate
        - truncate
        - open
        - openat
        - open_by_handle_at

    - name: Check existence of ftruncate in /etc/audit/audit.rules
      ansible.builtin.find:
        paths: /etc/audit
        contains: -a always,exit -F arch=b32(( -S |,)\w+)*(( -S |,){{ item }})+((
          -S |,)\w+)* -F exit=-EPERM -F auid>=1000 -F auid!=unset (-k\s+|-F\s+key=)\S+\s*$
        patterns: audit.rules
      register: find_command
      loop: '{{ (syscall_grouping + syscalls) | unique }}'

    - name: Set path to /etc/audit/audit.rules
      ansible.builtin.set_fact: audit_file="/etc/audit/audit.rules"

    - name: Declare found syscalls
      ansible.builtin.set_fact: syscalls_found="{{ find_command.results | selectattr('matched')
        | map(attribute='item') | list }}"

    - name: Declare missing syscalls
      ansible.builtin.set_fact: missing_syscalls="{{ syscalls | difference(syscalls_found)
        }}"

    - name: Replace the audit rule in {{ audit_file }}
      ansible.builtin.lineinfile:
        path: '{{ audit_file }}'
        regexp: (-a always,exit -F arch=b32)(?=.*(?:(?:-S |,)(?:{{ syscalls_found
          | join("|") }}))\b)((?:( -S |,)\w+)+)( -F exit=-EPERM -F auid>=1000 -F auid!=unset
          (?:-k |-F key=)\w+)
        line: \1\2\3{{ missing_syscalls | join("\3") }}\4
        backrefs: true
        state: present
        mode: g-rwx,o-rwx
      when: syscalls_found | length > 0 and missing_syscalls | length > 0

    - name: Add the audit rule to {{ audit_file }}
      ansible.builtin.lineinfile:
        path: '{{ audit_file }}'
        line: -a always,exit -F arch=b32 -S {{ syscalls | join(',') }} -F exit=-EPERM
          -F auid>=1000 -F auid!=unset -F key=access
        create: true
        mode: g-rwx,o-rwx
        state: present
      when: syscalls_found | length == 0
    when:
    - '"audit" in ansible_facts.packages'
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-000635
    - NIST-800-171-3.1.7
    - NIST-800-53-AU-12(c)
    - NIST-800-53-AU-2(d)
    - NIST-800-53-CM-6(a)
    - PCI-DSS-Req-10.2.1
    - PCI-DSS-Req-10.2.4
    - audit_rules_unsuccessful_file_modification_ftruncate
    - low_complexity
    - low_disruption
    - medium_severity
    - reboot_required
    - restrict_strategy

  - name: Perform remediation of Audit rules for ftruncate EPERM for 64bit platform
    block:

    - name: Declare list of syscalls
      ansible.builtin.set_fact:
        syscalls:
        - ftruncate
        syscall_grouping:
        - creat
        - ftruncate
        - truncate
        - open
        - openat
        - open_by_handle_at

    - name: Check existence of ftruncate in /etc/audit/rules.d/
      ansible.builtin.find:
        paths: /etc/audit/rules.d
        contains: -a always,exit -F arch=b64(( -S |,)\w+)*(( -S |,){{ item }})+((
          -S |,)\w+)* -F exit=-EPERM -F auid>=1000 -F auid!=unset (-k\s+|-F\s+key=)\S+\s*$
        patterns: '*.rules'
      register: find_command
      loop: '{{ (syscall_grouping + syscalls) | unique }}'

    - name: Reset syscalls found per file
      ansible.builtin.set_fact:
        syscalls_per_file: {}
        found_paths_dict: {}

    - name: Declare syscalls found per file
      ansible.builtin.set_fact: syscalls_per_file="{{ syscalls_per_file | combine(
        {item.files[0].path :[item.item] + syscalls_per_file.get(item.files[0].path,
        []) } ) }}"
      loop: '{{ find_command.results | selectattr(''matched'') | list }}'

    - name: Declare files where syscalls were found
      ansible.builtin.set_fact: found_paths="{{ find_command.results | map(attribute='files')
        | flatten | map(attribute='path') | list }}"

    - name: Count occurrences of syscalls in paths
      ansible.builtin.set_fact: found_paths_dict="{{ found_paths_dict | combine({
        item:1+found_paths_dict.get(item, 0) }) }}"
      loop: '{{ find_command.results | map(attribute=''files'') | flatten | map(attribute=''path'')
        | list }}'

    - name: Get path with most syscalls
      ansible.builtin.set_fact: audit_file="{{ (found_paths_dict | dict2items() |
        sort(attribute='value') | last).key }}"
      when: found_paths | length >= 1

    - name: No file with syscall found, set path to /etc/audit/rules.d/access.rules
      ansible.builtin.set_fact: audit_file="/etc/audit/rules.d/access.rules"
      when: found_paths | length == 0

    - name: Declare found syscalls
      ansible.builtin.set_fact: syscalls_found="{{ find_command.results | selectattr('matched')
        | map(attribute='item') | list }}"

    - name: Declare missing syscalls
      ansible.builtin.set_fact: missing_syscalls="{{ syscalls | difference(syscalls_found)
        }}"

    - name: Replace the audit rule in {{ audit_file }}
      ansible.builtin.lineinfile:
        path: '{{ audit_file }}'
        regexp: (-a always,exit -F arch=b64)(?=.*(?:(?:-S |,)(?:{{ syscalls_per_file[audit_file]
          | join("|") }}))\b)((?:( -S |,)\w+)+)( -F exit=-EPERM -F auid>=1000 -F auid!=unset
          (?:-k |-F key=)\w+)
        line: \1\2\3{{ missing_syscalls | join("\3") }}\4
        backrefs: true
        state: present
        mode: g-rwx,o-rwx
      when: syscalls_found | length > 0 and missing_syscalls | length > 0

    - name: Add the audit rule to {{ audit_file }}
      ansible.builtin.lineinfile:
        path: '{{ audit_file }}'
        line: -a always,exit -F arch=b64 -S {{ syscalls | join(',') }} -F exit=-EPERM
          -F auid>=1000 -F auid!=unset -F key=access
        create: true
        mode: g-rwx,o-rwx
        state: present
      when: syscalls_found | length == 0

    - name: Declare list of syscalls
      ansible.builtin.set_fact:
        syscalls:
        - ftruncate
        syscall_grouping:
        - creat
        - ftruncate
        - truncate
        - open
        - openat
        - open_by_handle_at

    - name: Check existence of ftruncate in /etc/audit/audit.rules
      ansible.builtin.find:
        paths: /etc/audit
        contains: -a always,exit -F arch=b64(( -S |,)\w+)*(( -S |,){{ item }})+((
          -S |,)\w+)* -F exit=-EPERM -F auid>=1000 -F auid!=unset (-k\s+|-F\s+key=)\S+\s*$
        patterns: audit.rules
      register: find_command
      loop: '{{ (syscall_grouping + syscalls) | unique }}'

    - name: Set path to /etc/audit/audit.rules
      ansible.builtin.set_fact: audit_file="/etc/audit/audit.rules"

    - name: Declare found syscalls
      ansible.builtin.set_fact: syscalls_found="{{ find_command.results | selectattr('matched')
        | map(attribute='item') | list }}"

    - name: Declare missing syscalls
      ansible.builtin.set_fact: missing_syscalls="{{ syscalls | difference(syscalls_found)
        }}"

    - name: Replace the audit rule in {{ audit_file }}
      ansible.builtin.lineinfile:
        path: '{{ audit_file }}'
        regexp: (-a always,exit -F arch=b64)(?=.*(?:(?:-S |,)(?:{{ syscalls_found
          | join("|") }}))\b)((?:( -S |,)\w+)+)( -F exit=-EPERM -F auid>=1000 -F auid!=unset
          (?:-k |-F key=)\w+)
        line: \1\2\3{{ missing_syscalls | join("\3") }}\4
        backrefs: true
        state: present
        mode: g-rwx,o-rwx
      when: syscalls_found | length > 0 and missing_syscalls | length > 0

    - name: Add the audit rule to {{ audit_file }}
      ansible.builtin.lineinfile:
        path: '{{ audit_file }}'
        line: -a always,exit -F arch=b64 -S {{ syscalls | join(',') }} -F exit=-EPERM
          -F auid>=1000 -F auid!=unset -F key=access
        create: true
        mode: g-rwx,o-rwx
        state: present
      when: syscalls_found | length == 0
    when:
    - '"audit" in ansible_facts.packages'
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - audit_arch == "b64"
    tags:
    - DISA-STIG-OL09-00-000635
    - NIST-800-171-3.1.7
    - NIST-800-53-AU-12(c)
    - NIST-800-53-AU-2(d)
    - NIST-800-53-CM-6(a)
    - PCI-DSS-Req-10.2.1
    - PCI-DSS-Req-10.2.4
    - audit_rules_unsuccessful_file_modification_ftruncate
    - low_complexity
    - low_disruption
    - medium_severity
    - reboot_required
    - restrict_strategy

  - name: Set architecture for audit open tasks
    ansible.builtin.set_fact:
      audit_arch: b64
    when:
    - '"audit" in ansible_facts.packages'
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - not ( ansible_architecture == "aarch64" )
    - ansible_architecture == "aarch64" or ansible_architecture == "ppc64" or ansible_architecture
      == "ppc64le" or ansible_architecture == "s390x" or ansible_architecture == "x86_64"
    tags:
    - DISA-STIG-OL09-00-000635
    - NIST-800-171-3.1.7
    - NIST-800-53-AU-12(c)
    - NIST-800-53-AU-2(d)
    - NIST-800-53-CM-6(a)
    - PCI-DSS-Req-10.2.1
    - PCI-DSS-Req-10.2.4
    - audit_rules_unsuccessful_file_modification_open
    - low_complexity
    - low_disruption
    - medium_severity
    - reboot_required
    - restrict_strategy

  - name: Perform remediation of Audit rules for open EACCES for 32bit platform
    block:

    - name: Declare list of syscalls
      ansible.builtin.set_fact:
        syscalls:
        - open
        syscall_grouping:
        - creat
        - ftruncate
        - truncate
        - open
        - openat
        - open_by_handle_at

    - name: Check existence of open in /etc/audit/rules.d/
      ansible.builtin.find:
        paths: /etc/audit/rules.d
        contains: -a always,exit -F arch=b32(( -S |,)\w+)*(( -S |,){{ item }})+((
          -S |,)\w+)* -F exit=-EACCES -F auid>=1000 -F auid!=unset (-k\s+|-F\s+key=)\S+\s*$
        patterns: '*.rules'
      register: find_command
      loop: '{{ (syscall_grouping + syscalls) | unique }}'

    - name: Reset syscalls found per file
      ansible.builtin.set_fact:
        syscalls_per_file: {}
        found_paths_dict: {}

    - name: Declare syscalls found per file
      ansible.builtin.set_fact: syscalls_per_file="{{ syscalls_per_file | combine(
        {item.files[0].path :[item.item] + syscalls_per_file.get(item.files[0].path,
        []) } ) }}"
      loop: '{{ find_command.results | selectattr(''matched'') | list }}'

    - name: Declare files where syscalls were found
      ansible.builtin.set_fact: found_paths="{{ find_command.results | map(attribute='files')
        | flatten | map(attribute='path') | list }}"

    - name: Count occurrences of syscalls in paths
      ansible.builtin.set_fact: found_paths_dict="{{ found_paths_dict | combine({
        item:1+found_paths_dict.get(item, 0) }) }}"
      loop: '{{ find_command.results | map(attribute=''files'') | flatten | map(attribute=''path'')
        | list }}'

    - name: Get path with most syscalls
      ansible.builtin.set_fact: audit_file="{{ (found_paths_dict | dict2items() |
        sort(attribute='value') | last).key }}"
      when: found_paths | length >= 1

    - name: No file with syscall found, set path to /etc/audit/rules.d/access.rules
      ansible.builtin.set_fact: audit_file="/etc/audit/rules.d/access.rules"
      when: found_paths | length == 0

    - name: Declare found syscalls
      ansible.builtin.set_fact: syscalls_found="{{ find_command.results | selectattr('matched')
        | map(attribute='item') | list }}"

    - name: Declare missing syscalls
      ansible.builtin.set_fact: missing_syscalls="{{ syscalls | difference(syscalls_found)
        }}"

    - name: Replace the audit rule in {{ audit_file }}
      ansible.builtin.lineinfile:
        path: '{{ audit_file }}'
        regexp: (-a always,exit -F arch=b32)(?=.*(?:(?:-S |,)(?:{{ syscalls_per_file[audit_file]
          | join("|") }}))\b)((?:( -S |,)\w+)+)( -F exit=-EACCES -F auid>=1000 -F
          auid!=unset (?:-k |-F key=)\w+)
        line: \1\2\3{{ missing_syscalls | join("\3") }}\4
        backrefs: true
        state: present
        mode: g-rwx,o-rwx
      when: syscalls_found | length > 0 and missing_syscalls | length > 0

    - name: Add the audit rule to {{ audit_file }}
      ansible.builtin.lineinfile:
        path: '{{ audit_file }}'
        line: -a always,exit -F arch=b32 -S {{ syscalls | join(',') }} -F exit=-EACCES
          -F auid>=1000 -F auid!=unset -F key=access
        create: true
        mode: g-rwx,o-rwx
        state: present
      when: syscalls_found | length == 0

    - name: Declare list of syscalls
      ansible.builtin.set_fact:
        syscalls:
        - open
        syscall_grouping:
        - creat
        - ftruncate
        - truncate
        - open
        - openat
        - open_by_handle_at

    - name: Check existence of open in /etc/audit/audit.rules
      ansible.builtin.find:
        paths: /etc/audit
        contains: -a always,exit -F arch=b32(( -S |,)\w+)*(( -S |,){{ item }})+((
          -S |,)\w+)* -F exit=-EACCES -F auid>=1000 -F auid!=unset (-k\s+|-F\s+key=)\S+\s*$
        patterns: audit.rules
      register: find_command
      loop: '{{ (syscall_grouping + syscalls) | unique }}'

    - name: Set path to /etc/audit/audit.rules
      ansible.builtin.set_fact: audit_file="/etc/audit/audit.rules"

    - name: Declare found syscalls
      ansible.builtin.set_fact: syscalls_found="{{ find_command.results | selectattr('matched')
        | map(attribute='item') | list }}"

    - name: Declare missing syscalls
      ansible.builtin.set_fact: missing_syscalls="{{ syscalls | difference(syscalls_found)
        }}"

    - name: Replace the audit rule in {{ audit_file }}
      ansible.builtin.lineinfile:
        path: '{{ audit_file }}'
        regexp: (-a always,exit -F arch=b32)(?=.*(?:(?:-S |,)(?:{{ syscalls_found
          | join("|") }}))\b)((?:( -S |,)\w+)+)( -F exit=-EACCES -F auid>=1000 -F
          auid!=unset (?:-k |-F key=)\w+)
        line: \1\2\3{{ missing_syscalls | join("\3") }}\4
        backrefs: true
        state: present
        mode: g-rwx,o-rwx
      when: syscalls_found | length > 0 and missing_syscalls | length > 0

    - name: Add the audit rule to {{ audit_file }}
      ansible.builtin.lineinfile:
        path: '{{ audit_file }}'
        line: -a always,exit -F arch=b32 -S {{ syscalls | join(',') }} -F exit=-EACCES
          -F auid>=1000 -F auid!=unset -F key=access
        create: true
        mode: g-rwx,o-rwx
        state: present
      when: syscalls_found | length == 0
    when:
    - '"audit" in ansible_facts.packages'
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - not ( ansible_architecture == "aarch64" )
    tags:
    - DISA-STIG-OL09-00-000635
    - NIST-800-171-3.1.7
    - NIST-800-53-AU-12(c)
    - NIST-800-53-AU-2(d)
    - NIST-800-53-CM-6(a)
    - PCI-DSS-Req-10.2.1
    - PCI-DSS-Req-10.2.4
    - audit_rules_unsuccessful_file_modification_open
    - low_complexity
    - low_disruption
    - medium_severity
    - reboot_required
    - restrict_strategy

  - name: Perform remediation of Audit rules for open EACCES for 64bit platform
    block:

    - name: Declare list of syscalls
      ansible.builtin.set_fact:
        syscalls:
        - open
        syscall_grouping:
        - creat
        - ftruncate
        - truncate
        - open
        - openat
        - open_by_handle_at

    - name: Check existence of open in /etc/audit/rules.d/
      ansible.builtin.find:
        paths: /etc/audit/rules.d
        contains: -a always,exit -F arch=b64(( -S |,)\w+)*(( -S |,){{ item }})+((
          -S |,)\w+)* -F exit=-EACCES -F auid>=1000 -F auid!=unset (-k\s+|-F\s+key=)\S+\s*$
        patterns: '*.rules'
      register: find_command
      loop: '{{ (syscall_grouping + syscalls) | unique }}'

    - name: Reset syscalls found per file
      ansible.builtin.set_fact:
        syscalls_per_file: {}
        found_paths_dict: {}

    - name: Declare syscalls found per file
      ansible.builtin.set_fact: syscalls_per_file="{{ syscalls_per_file | combine(
        {item.files[0].path :[item.item] + syscalls_per_file.get(item.files[0].path,
        []) } ) }}"
      loop: '{{ find_command.results | selectattr(''matched'') | list }}'

    - name: Declare files where syscalls were found
      ansible.builtin.set_fact: found_paths="{{ find_command.results | map(attribute='files')
        | flatten | map(attribute='path') | list }}"

    - name: Count occurrences of syscalls in paths
      ansible.builtin.set_fact: found_paths_dict="{{ found_paths_dict | combine({
        item:1+found_paths_dict.get(item, 0) }) }}"
      loop: '{{ find_command.results | map(attribute=''files'') | flatten | map(attribute=''path'')
        | list }}'

    - name: Get path with most syscalls
      ansible.builtin.set_fact: audit_file="{{ (found_paths_dict | dict2items() |
        sort(attribute='value') | last).key }}"
      when: found_paths | length >= 1

    - name: No file with syscall found, set path to /etc/audit/rules.d/access.rules
      ansible.builtin.set_fact: audit_file="/etc/audit/rules.d/access.rules"
      when: found_paths | length == 0

    - name: Declare found syscalls
      ansible.builtin.set_fact: syscalls_found="{{ find_command.results | selectattr('matched')
        | map(attribute='item') | list }}"

    - name: Declare missing syscalls
      ansible.builtin.set_fact: missing_syscalls="{{ syscalls | difference(syscalls_found)
        }}"

    - name: Replace the audit rule in {{ audit_file }}
      ansible.builtin.lineinfile:
        path: '{{ audit_file }}'
        regexp: (-a always,exit -F arch=b64)(?=.*(?:(?:-S |,)(?:{{ syscalls_per_file[audit_file]
          | join("|") }}))\b)((?:( -S |,)\w+)+)( -F exit=-EACCES -F auid>=1000 -F
          auid!=unset (?:-k |-F key=)\w+)
        line: \1\2\3{{ missing_syscalls | join("\3") }}\4
        backrefs: true
        state: present
        mode: g-rwx,o-rwx
      when: syscalls_found | length > 0 and missing_syscalls | length > 0

    - name: Add the audit rule to {{ audit_file }}
      ansible.builtin.lineinfile:
        path: '{{ audit_file }}'
        line: -a always,exit -F arch=b64 -S {{ syscalls | join(',') }} -F exit=-EACCES
          -F auid>=1000 -F auid!=unset -F key=access
        create: true
        mode: g-rwx,o-rwx
        state: present
      when: syscalls_found | length == 0

    - name: Declare list of syscalls
      ansible.builtin.set_fact:
        syscalls:
        - open
        syscall_grouping:
        - creat
        - ftruncate
        - truncate
        - open
        - openat
        - open_by_handle_at

    - name: Check existence of open in /etc/audit/audit.rules
      ansible.builtin.find:
        paths: /etc/audit
        contains: -a always,exit -F arch=b64(( -S |,)\w+)*(( -S |,){{ item }})+((
          -S |,)\w+)* -F exit=-EACCES -F auid>=1000 -F auid!=unset (-k\s+|-F\s+key=)\S+\s*$
        patterns: audit.rules
      register: find_command
      loop: '{{ (syscall_grouping + syscalls) | unique }}'

    - name: Set path to /etc/audit/audit.rules
      ansible.builtin.set_fact: audit_file="/etc/audit/audit.rules"

    - name: Declare found syscalls
      ansible.builtin.set_fact: syscalls_found="{{ find_command.results | selectattr('matched')
        | map(attribute='item') | list }}"

    - name: Declare missing syscalls
      ansible.builtin.set_fact: missing_syscalls="{{ syscalls | difference(syscalls_found)
        }}"

    - name: Replace the audit rule in {{ audit_file }}
      ansible.builtin.lineinfile:
        path: '{{ audit_file }}'
        regexp: (-a always,exit -F arch=b64)(?=.*(?:(?:-S |,)(?:{{ syscalls_found
          | join("|") }}))\b)((?:( -S |,)\w+)+)( -F exit=-EACCES -F auid>=1000 -F
          auid!=unset (?:-k |-F key=)\w+)
        line: \1\2\3{{ missing_syscalls | join("\3") }}\4
        backrefs: true
        state: present
        mode: g-rwx,o-rwx
      when: syscalls_found | length > 0 and missing_syscalls | length > 0

    - name: Add the audit rule to {{ audit_file }}
      ansible.builtin.lineinfile:
        path: '{{ audit_file }}'
        line: -a always,exit -F arch=b64 -S {{ syscalls | join(',') }} -F exit=-EACCES
          -F auid>=1000 -F auid!=unset -F key=access
        create: true
        mode: g-rwx,o-rwx
        state: present
      when: syscalls_found | length == 0
    when:
    - '"audit" in ansible_facts.packages'
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - not ( ansible_architecture == "aarch64" )
    - audit_arch == "b64"
    tags:
    - DISA-STIG-OL09-00-000635
    - NIST-800-171-3.1.7
    - NIST-800-53-AU-12(c)
    - NIST-800-53-AU-2(d)
    - NIST-800-53-CM-6(a)
    - PCI-DSS-Req-10.2.1
    - PCI-DSS-Req-10.2.4
    - audit_rules_unsuccessful_file_modification_open
    - low_complexity
    - low_disruption
    - medium_severity
    - reboot_required
    - restrict_strategy

  - name: Perform remediation of Audit rules for open EPERM for 32bit platform
    block:

    - name: Declare list of syscalls
      ansible.builtin.set_fact:
        syscalls:
        - open
        syscall_grouping:
        - creat
        - ftruncate
        - truncate
        - open
        - openat
        - open_by_handle_at

    - name: Check existence of open in /etc/audit/rules.d/
      ansible.builtin.find:
        paths: /etc/audit/rules.d
        contains: -a always,exit -F arch=b32(( -S |,)\w+)*(( -S |,){{ item }})+((
          -S |,)\w+)* -F exit=-EPERM -F auid>=1000 -F auid!=unset (-k\s+|-F\s+key=)\S+\s*$
        patterns: '*.rules'
      register: find_command
      loop: '{{ (syscall_grouping + syscalls) | unique }}'

    - name: Reset syscalls found per file
      ansible.builtin.set_fact:
        syscalls_per_file: {}
        found_paths_dict: {}

    - name: Declare syscalls found per file
      ansible.builtin.set_fact: syscalls_per_file="{{ syscalls_per_file | combine(
        {item.files[0].path :[item.item] + syscalls_per_file.get(item.files[0].path,
        []) } ) }}"
      loop: '{{ find_command.results | selectattr(''matched'') | list }}'

    - name: Declare files where syscalls were found
      ansible.builtin.set_fact: found_paths="{{ find_command.results | map(attribute='files')
        | flatten | map(attribute='path') | list }}"

    - name: Count occurrences of syscalls in paths
      ansible.builtin.set_fact: found_paths_dict="{{ found_paths_dict | combine({
        item:1+found_paths_dict.get(item, 0) }) }}"
      loop: '{{ find_command.results | map(attribute=''files'') | flatten | map(attribute=''path'')
        | list }}'

    - name: Get path with most syscalls
      ansible.builtin.set_fact: audit_file="{{ (found_paths_dict | dict2items() |
        sort(attribute='value') | last).key }}"
      when: found_paths | length >= 1

    - name: No file with syscall found, set path to /etc/audit/rules.d/access.rules
      ansible.builtin.set_fact: audit_file="/etc/audit/rules.d/access.rules"
      when: found_paths | length == 0

    - name: Declare found syscalls
      ansible.builtin.set_fact: syscalls_found="{{ find_command.results | selectattr('matched')
        | map(attribute='item') | list }}"

    - name: Declare missing syscalls
      ansible.builtin.set_fact: missing_syscalls="{{ syscalls | difference(syscalls_found)
        }}"

    - name: Replace the audit rule in {{ audit_file }}
      ansible.builtin.lineinfile:
        path: '{{ audit_file }}'
        regexp: (-a always,exit -F arch=b32)(?=.*(?:(?:-S |,)(?:{{ syscalls_per_file[audit_file]
          | join("|") }}))\b)((?:( -S |,)\w+)+)( -F exit=-EPERM -F auid>=1000 -F auid!=unset
          (?:-k |-F key=)\w+)
        line: \1\2\3{{ missing_syscalls | join("\3") }}\4
        backrefs: true
        state: present
        mode: g-rwx,o-rwx
      when: syscalls_found | length > 0 and missing_syscalls | length > 0

    - name: Add the audit rule to {{ audit_file }}
      ansible.builtin.lineinfile:
        path: '{{ audit_file }}'
        line: -a always,exit -F arch=b32 -S {{ syscalls | join(',') }} -F exit=-EPERM
          -F auid>=1000 -F auid!=unset -F key=access
        create: true
        mode: g-rwx,o-rwx
        state: present
      when: syscalls_found | length == 0

    - name: Declare list of syscalls
      ansible.builtin.set_fact:
        syscalls:
        - open
        syscall_grouping:
        - creat
        - ftruncate
        - truncate
        - open
        - openat
        - open_by_handle_at

    - name: Check existence of open in /etc/audit/audit.rules
      ansible.builtin.find:
        paths: /etc/audit
        contains: -a always,exit -F arch=b32(( -S |,)\w+)*(( -S |,){{ item }})+((
          -S |,)\w+)* -F exit=-EPERM -F auid>=1000 -F auid!=unset (-k\s+|-F\s+key=)\S+\s*$
        patterns: audit.rules
      register: find_command
      loop: '{{ (syscall_grouping + syscalls) | unique }}'

    - name: Set path to /etc/audit/audit.rules
      ansible.builtin.set_fact: audit_file="/etc/audit/audit.rules"

    - name: Declare found syscalls
      ansible.builtin.set_fact: syscalls_found="{{ find_command.results | selectattr('matched')
        | map(attribute='item') | list }}"

    - name: Declare missing syscalls
      ansible.builtin.set_fact: missing_syscalls="{{ syscalls | difference(syscalls_found)
        }}"

    - name: Replace the audit rule in {{ audit_file }}
      ansible.builtin.lineinfile:
        path: '{{ audit_file }}'
        regexp: (-a always,exit -F arch=b32)(?=.*(?:(?:-S |,)(?:{{ syscalls_found
          | join("|") }}))\b)((?:( -S |,)\w+)+)( -F exit=-EPERM -F auid>=1000 -F auid!=unset
          (?:-k |-F key=)\w+)
        line: \1\2\3{{ missing_syscalls | join("\3") }}\4
        backrefs: true
        state: present
        mode: g-rwx,o-rwx
      when: syscalls_found | length > 0 and missing_syscalls | length > 0

    - name: Add the audit rule to {{ audit_file }}
      ansible.builtin.lineinfile:
        path: '{{ audit_file }}'
        line: -a always,exit -F arch=b32 -S {{ syscalls | join(',') }} -F exit=-EPERM
          -F auid>=1000 -F auid!=unset -F key=access
        create: true
        mode: g-rwx,o-rwx
        state: present
      when: syscalls_found | length == 0
    when:
    - '"audit" in ansible_facts.packages'
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - not ( ansible_architecture == "aarch64" )
    tags:
    - DISA-STIG-OL09-00-000635
    - NIST-800-171-3.1.7
    - NIST-800-53-AU-12(c)
    - NIST-800-53-AU-2(d)
    - NIST-800-53-CM-6(a)
    - PCI-DSS-Req-10.2.1
    - PCI-DSS-Req-10.2.4
    - audit_rules_unsuccessful_file_modification_open
    - low_complexity
    - low_disruption
    - medium_severity
    - reboot_required
    - restrict_strategy

  - name: Perform remediation of Audit rules for open EPERM for 64bit platform
    block:

    - name: Declare list of syscalls
      ansible.builtin.set_fact:
        syscalls:
        - open
        syscall_grouping:
        - creat
        - ftruncate
        - truncate
        - open
        - openat
        - open_by_handle_at

    - name: Check existence of open in /etc/audit/rules.d/
      ansible.builtin.find:
        paths: /etc/audit/rules.d
        contains: -a always,exit -F arch=b64(( -S |,)\w+)*(( -S |,){{ item }})+((
          -S |,)\w+)* -F exit=-EPERM -F auid>=1000 -F auid!=unset (-k\s+|-F\s+key=)\S+\s*$
        patterns: '*.rules'
      register: find_command
      loop: '{{ (syscall_grouping + syscalls) | unique }}'

    - name: Reset syscalls found per file
      ansible.builtin.set_fact:
        syscalls_per_file: {}
        found_paths_dict: {}

    - name: Declare syscalls found per file
      ansible.builtin.set_fact: syscalls_per_file="{{ syscalls_per_file | combine(
        {item.files[0].path :[item.item] + syscalls_per_file.get(item.files[0].path,
        []) } ) }}"
      loop: '{{ find_command.results | selectattr(''matched'') | list }}'

    - name: Declare files where syscalls were found
      ansible.builtin.set_fact: found_paths="{{ find_command.results | map(attribute='files')
        | flatten | map(attribute='path') | list }}"

    - name: Count occurrences of syscalls in paths
      ansible.builtin.set_fact: found_paths_dict="{{ found_paths_dict | combine({
        item:1+found_paths_dict.get(item, 0) }) }}"
      loop: '{{ find_command.results | map(attribute=''files'') | flatten | map(attribute=''path'')
        | list }}'

    - name: Get path with most syscalls
      ansible.builtin.set_fact: audit_file="{{ (found_paths_dict | dict2items() |
        sort(attribute='value') | last).key }}"
      when: found_paths | length >= 1

    - name: No file with syscall found, set path to /etc/audit/rules.d/access.rules
      ansible.builtin.set_fact: audit_file="/etc/audit/rules.d/access.rules"
      when: found_paths | length == 0

    - name: Declare found syscalls
      ansible.builtin.set_fact: syscalls_found="{{ find_command.results | selectattr('matched')
        | map(attribute='item') | list }}"

    - name: Declare missing syscalls
      ansible.builtin.set_fact: missing_syscalls="{{ syscalls | difference(syscalls_found)
        }}"

    - name: Replace the audit rule in {{ audit_file }}
      ansible.builtin.lineinfile:
        path: '{{ audit_file }}'
        regexp: (-a always,exit -F arch=b64)(?=.*(?:(?:-S |,)(?:{{ syscalls_per_file[audit_file]
          | join("|") }}))\b)((?:( -S |,)\w+)+)( -F exit=-EPERM -F auid>=1000 -F auid!=unset
          (?:-k |-F key=)\w+)
        line: \1\2\3{{ missing_syscalls | join("\3") }}\4
        backrefs: true
        state: present
        mode: g-rwx,o-rwx
      when: syscalls_found | length > 0 and missing_syscalls | length > 0

    - name: Add the audit rule to {{ audit_file }}
      ansible.builtin.lineinfile:
        path: '{{ audit_file }}'
        line: -a always,exit -F arch=b64 -S {{ syscalls | join(',') }} -F exit=-EPERM
          -F auid>=1000 -F auid!=unset -F key=access
        create: true
        mode: g-rwx,o-rwx
        state: present
      when: syscalls_found | length == 0

    - name: Declare list of syscalls
      ansible.builtin.set_fact:
        syscalls:
        - open
        syscall_grouping:
        - creat
        - ftruncate
        - truncate
        - open
        - openat
        - open_by_handle_at

    - name: Check existence of open in /etc/audit/audit.rules
      ansible.builtin.find:
        paths: /etc/audit
        contains: -a always,exit -F arch=b64(( -S |,)\w+)*(( -S |,){{ item }})+((
          -S |,)\w+)* -F exit=-EPERM -F auid>=1000 -F auid!=unset (-k\s+|-F\s+key=)\S+\s*$
        patterns: audit.rules
      register: find_command
      loop: '{{ (syscall_grouping + syscalls) | unique }}'

    - name: Set path to /etc/audit/audit.rules
      ansible.builtin.set_fact: audit_file="/etc/audit/audit.rules"

    - name: Declare found syscalls
      ansible.builtin.set_fact: syscalls_found="{{ find_command.results | selectattr('matched')
        | map(attribute='item') | list }}"

    - name: Declare missing syscalls
      ansible.builtin.set_fact: missing_syscalls="{{ syscalls | difference(syscalls_found)
        }}"

    - name: Replace the audit rule in {{ audit_file }}
      ansible.builtin.lineinfile:
        path: '{{ audit_file }}'
        regexp: (-a always,exit -F arch=b64)(?=.*(?:(?:-S |,)(?:{{ syscalls_found
          | join("|") }}))\b)((?:( -S |,)\w+)+)( -F exit=-EPERM -F auid>=1000 -F auid!=unset
          (?:-k |-F key=)\w+)
        line: \1\2\3{{ missing_syscalls | join("\3") }}\4
        backrefs: true
        state: present
        mode: g-rwx,o-rwx
      when: syscalls_found | length > 0 and missing_syscalls | length > 0

    - name: Add the audit rule to {{ audit_file }}
      ansible.builtin.lineinfile:
        path: '{{ audit_file }}'
        line: -a always,exit -F arch=b64 -S {{ syscalls | join(',') }} -F exit=-EPERM
          -F auid>=1000 -F auid!=unset -F key=access
        create: true
        mode: g-rwx,o-rwx
        state: present
      when: syscalls_found | length == 0
    when:
    - '"audit" in ansible_facts.packages'
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - not ( ansible_architecture == "aarch64" )
    - audit_arch == "b64"
    tags:
    - DISA-STIG-OL09-00-000635
    - NIST-800-171-3.1.7
    - NIST-800-53-AU-12(c)
    - NIST-800-53-AU-2(d)
    - NIST-800-53-CM-6(a)
    - PCI-DSS-Req-10.2.1
    - PCI-DSS-Req-10.2.4
    - audit_rules_unsuccessful_file_modification_open
    - low_complexity
    - low_disruption
    - medium_severity
    - reboot_required
    - restrict_strategy

  - name: Set architecture for audit open_by_handle_at tasks
    ansible.builtin.set_fact:
      audit_arch: b64
    when:
    - '"audit" in ansible_facts.packages'
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - ansible_architecture == "aarch64" or ansible_architecture == "ppc64" or ansible_architecture
      == "ppc64le" or ansible_architecture == "s390x" or ansible_architecture == "x86_64"
    tags:
    - DISA-STIG-OL09-00-000635
    - NIST-800-171-3.1.7
    - NIST-800-53-AU-12(c)
    - NIST-800-53-AU-2(d)
    - NIST-800-53-CM-6(a)
    - PCI-DSS-Req-10.2.1
    - PCI-DSS-Req-10.2.4
    - audit_rules_unsuccessful_file_modification_open_by_handle_at
    - low_complexity
    - low_disruption
    - medium_severity
    - reboot_required
    - restrict_strategy

  - name: Perform remediation of Audit rules for open_by_handle_at EACCES for 32bit
      platform
    block:

    - name: Declare list of syscalls
      ansible.builtin.set_fact:
        syscalls:
        - open_by_handle_at
        syscall_grouping:
        - creat
        - ftruncate
        - truncate
        - open
        - openat
        - open_by_handle_at

    - name: Check existence of open_by_handle_at in /etc/audit/rules.d/
      ansible.builtin.find:
        paths: /etc/audit/rules.d
        contains: -a always,exit -F arch=b32(( -S |,)\w+)*(( -S |,){{ item }})+((
          -S |,)\w+)* -F exit=-EACCES -F auid>=1000 -F auid!=unset (-k\s+|-F\s+key=)\S+\s*$
        patterns: '*.rules'
      register: find_command
      loop: '{{ (syscall_grouping + syscalls) | unique }}'

    - name: Reset syscalls found per file
      ansible.builtin.set_fact:
        syscalls_per_file: {}
        found_paths_dict: {}

    - name: Declare syscalls found per file
      ansible.builtin.set_fact: syscalls_per_file="{{ syscalls_per_file | combine(
        {item.files[0].path :[item.item] + syscalls_per_file.get(item.files[0].path,
        []) } ) }}"
      loop: '{{ find_command.results | selectattr(''matched'') | list }}'

    - name: Declare files where syscalls were found
      ansible.builtin.set_fact: found_paths="{{ find_command.results | map(attribute='files')
        | flatten | map(attribute='path') | list }}"

    - name: Count occurrences of syscalls in paths
      ansible.builtin.set_fact: found_paths_dict="{{ found_paths_dict | combine({
        item:1+found_paths_dict.get(item, 0) }) }}"
      loop: '{{ find_command.results | map(attribute=''files'') | flatten | map(attribute=''path'')
        | list }}'

    - name: Get path with most syscalls
      ansible.builtin.set_fact: audit_file="{{ (found_paths_dict | dict2items() |
        sort(attribute='value') | last).key }}"
      when: found_paths | length >= 1

    - name: No file with syscall found, set path to /etc/audit/rules.d/access.rules
      ansible.builtin.set_fact: audit_file="/etc/audit/rules.d/access.rules"
      when: found_paths | length == 0

    - name: Declare found syscalls
      ansible.builtin.set_fact: syscalls_found="{{ find_command.results | selectattr('matched')
        | map(attribute='item') | list }}"

    - name: Declare missing syscalls
      ansible.builtin.set_fact: missing_syscalls="{{ syscalls | difference(syscalls_found)
        }}"

    - name: Replace the audit rule in {{ audit_file }}
      ansible.builtin.lineinfile:
        path: '{{ audit_file }}'
        regexp: (-a always,exit -F arch=b32)(?=.*(?:(?:-S |,)(?:{{ syscalls_per_file[audit_file]
          | join("|") }}))\b)((?:( -S |,)\w+)+)( -F exit=-EACCES -F auid>=1000 -F
          auid!=unset (?:-k |-F key=)\w+)
        line: \1\2\3{{ missing_syscalls | join("\3") }}\4
        backrefs: true
        state: present
        mode: g-rwx,o-rwx
      when: syscalls_found | length > 0 and missing_syscalls | length > 0

    - name: Add the audit rule to {{ audit_file }}
      ansible.builtin.lineinfile:
        path: '{{ audit_file }}'
        line: -a always,exit -F arch=b32 -S {{ syscalls | join(',') }} -F exit=-EACCES
          -F auid>=1000 -F auid!=unset -F key=access
        create: true
        mode: g-rwx,o-rwx
        state: present
      when: syscalls_found | length == 0

    - name: Declare list of syscalls
      ansible.builtin.set_fact:
        syscalls:
        - open_by_handle_at
        syscall_grouping:
        - creat
        - ftruncate
        - truncate
        - open
        - openat
        - open_by_handle_at

    - name: Check existence of open_by_handle_at in /etc/audit/audit.rules
      ansible.builtin.find:
        paths: /etc/audit
        contains: -a always,exit -F arch=b32(( -S |,)\w+)*(( -S |,){{ item }})+((
          -S |,)\w+)* -F exit=-EACCES -F auid>=1000 -F auid!=unset (-k\s+|-F\s+key=)\S+\s*$
        patterns: audit.rules
      register: find_command
      loop: '{{ (syscall_grouping + syscalls) | unique }}'

    - name: Set path to /etc/audit/audit.rules
      ansible.builtin.set_fact: audit_file="/etc/audit/audit.rules"

    - name: Declare found syscalls
      ansible.builtin.set_fact: syscalls_found="{{ find_command.results | selectattr('matched')
        | map(attribute='item') | list }}"

    - name: Declare missing syscalls
      ansible.builtin.set_fact: missing_syscalls="{{ syscalls | difference(syscalls_found)
        }}"

    - name: Replace the audit rule in {{ audit_file }}
      ansible.builtin.lineinfile:
        path: '{{ audit_file }}'
        regexp: (-a always,exit -F arch=b32)(?=.*(?:(?:-S |,)(?:{{ syscalls_found
          | join("|") }}))\b)((?:( -S |,)\w+)+)( -F exit=-EACCES -F auid>=1000 -F
          auid!=unset (?:-k |-F key=)\w+)
        line: \1\2\3{{ missing_syscalls | join("\3") }}\4
        backrefs: true
        state: present
        mode: g-rwx,o-rwx
      when: syscalls_found | length > 0 and missing_syscalls | length > 0

    - name: Add the audit rule to {{ audit_file }}
      ansible.builtin.lineinfile:
        path: '{{ audit_file }}'
        line: -a always,exit -F arch=b32 -S {{ syscalls | join(',') }} -F exit=-EACCES
          -F auid>=1000 -F auid!=unset -F key=access
        create: true
        mode: g-rwx,o-rwx
        state: present
      when: syscalls_found | length == 0
    when:
    - '"audit" in ansible_facts.packages'
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-000635
    - NIST-800-171-3.1.7
    - NIST-800-53-AU-12(c)
    - NIST-800-53-AU-2(d)
    - NIST-800-53-CM-6(a)
    - PCI-DSS-Req-10.2.1
    - PCI-DSS-Req-10.2.4
    - audit_rules_unsuccessful_file_modification_open_by_handle_at
    - low_complexity
    - low_disruption
    - medium_severity
    - reboot_required
    - restrict_strategy

  - name: Perform remediation of Audit rules for open_by_handle_at EACCES for 64bit
      platform
    block:

    - name: Declare list of syscalls
      ansible.builtin.set_fact:
        syscalls:
        - open_by_handle_at
        syscall_grouping:
        - creat
        - ftruncate
        - truncate
        - open
        - openat
        - open_by_handle_at

    - name: Check existence of open_by_handle_at in /etc/audit/rules.d/
      ansible.builtin.find:
        paths: /etc/audit/rules.d
        contains: -a always,exit -F arch=b64(( -S |,)\w+)*(( -S |,){{ item }})+((
          -S |,)\w+)* -F exit=-EACCES -F auid>=1000 -F auid!=unset (-k\s+|-F\s+key=)\S+\s*$
        patterns: '*.rules'
      register: find_command
      loop: '{{ (syscall_grouping + syscalls) | unique }}'

    - name: Reset syscalls found per file
      ansible.builtin.set_fact:
        syscalls_per_file: {}
        found_paths_dict: {}

    - name: Declare syscalls found per file
      ansible.builtin.set_fact: syscalls_per_file="{{ syscalls_per_file | combine(
        {item.files[0].path :[item.item] + syscalls_per_file.get(item.files[0].path,
        []) } ) }}"
      loop: '{{ find_command.results | selectattr(''matched'') | list }}'

    - name: Declare files where syscalls were found
      ansible.builtin.set_fact: found_paths="{{ find_command.results | map(attribute='files')
        | flatten | map(attribute='path') | list }}"

    - name: Count occurrences of syscalls in paths
      ansible.builtin.set_fact: found_paths_dict="{{ found_paths_dict | combine({
        item:1+found_paths_dict.get(item, 0) }) }}"
      loop: '{{ find_command.results | map(attribute=''files'') | flatten | map(attribute=''path'')
        | list }}'

    - name: Get path with most syscalls
      ansible.builtin.set_fact: audit_file="{{ (found_paths_dict | dict2items() |
        sort(attribute='value') | last).key }}"
      when: found_paths | length >= 1

    - name: No file with syscall found, set path to /etc/audit/rules.d/access.rules
      ansible.builtin.set_fact: audit_file="/etc/audit/rules.d/access.rules"
      when: found_paths | length == 0

    - name: Declare found syscalls
      ansible.builtin.set_fact: syscalls_found="{{ find_command.results | selectattr('matched')
        | map(attribute='item') | list }}"

    - name: Declare missing syscalls
      ansible.builtin.set_fact: missing_syscalls="{{ syscalls | difference(syscalls_found)
        }}"

    - name: Replace the audit rule in {{ audit_file }}
      ansible.builtin.lineinfile:
        path: '{{ audit_file }}'
        regexp: (-a always,exit -F arch=b64)(?=.*(?:(?:-S |,)(?:{{ syscalls_per_file[audit_file]
          | join("|") }}))\b)((?:( -S |,)\w+)+)( -F exit=-EACCES -F auid>=1000 -F
          auid!=unset (?:-k |-F key=)\w+)
        line: \1\2\3{{ missing_syscalls | join("\3") }}\4
        backrefs: true
        state: present
        mode: g-rwx,o-rwx
      when: syscalls_found | length > 0 and missing_syscalls | length > 0

    - name: Add the audit rule to {{ audit_file }}
      ansible.builtin.lineinfile:
        path: '{{ audit_file }}'
        line: -a always,exit -F arch=b64 -S {{ syscalls | join(',') }} -F exit=-EACCES
          -F auid>=1000 -F auid!=unset -F key=access
        create: true
        mode: g-rwx,o-rwx
        state: present
      when: syscalls_found | length == 0

    - name: Declare list of syscalls
      ansible.builtin.set_fact:
        syscalls:
        - open_by_handle_at
        syscall_grouping:
        - creat
        - ftruncate
        - truncate
        - open
        - openat
        - open_by_handle_at

    - name: Check existence of open_by_handle_at in /etc/audit/audit.rules
      ansible.builtin.find:
        paths: /etc/audit
        contains: -a always,exit -F arch=b64(( -S |,)\w+)*(( -S |,){{ item }})+((
          -S |,)\w+)* -F exit=-EACCES -F auid>=1000 -F auid!=unset (-k\s+|-F\s+key=)\S+\s*$
        patterns: audit.rules
      register: find_command
      loop: '{{ (syscall_grouping + syscalls) | unique }}'

    - name: Set path to /etc/audit/audit.rules
      ansible.builtin.set_fact: audit_file="/etc/audit/audit.rules"

    - name: Declare found syscalls
      ansible.builtin.set_fact: syscalls_found="{{ find_command.results | selectattr('matched')
        | map(attribute='item') | list }}"

    - name: Declare missing syscalls
      ansible.builtin.set_fact: missing_syscalls="{{ syscalls | difference(syscalls_found)
        }}"

    - name: Replace the audit rule in {{ audit_file }}
      ansible.builtin.lineinfile:
        path: '{{ audit_file }}'
        regexp: (-a always,exit -F arch=b64)(?=.*(?:(?:-S |,)(?:{{ syscalls_found
          | join("|") }}))\b)((?:( -S |,)\w+)+)( -F exit=-EACCES -F auid>=1000 -F
          auid!=unset (?:-k |-F key=)\w+)
        line: \1\2\3{{ missing_syscalls | join("\3") }}\4
        backrefs: true
        state: present
        mode: g-rwx,o-rwx
      when: syscalls_found | length > 0 and missing_syscalls | length > 0

    - name: Add the audit rule to {{ audit_file }}
      ansible.builtin.lineinfile:
        path: '{{ audit_file }}'
        line: -a always,exit -F arch=b64 -S {{ syscalls | join(',') }} -F exit=-EACCES
          -F auid>=1000 -F auid!=unset -F key=access
        create: true
        mode: g-rwx,o-rwx
        state: present
      when: syscalls_found | length == 0
    when:
    - '"audit" in ansible_facts.packages'
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - audit_arch == "b64"
    tags:
    - DISA-STIG-OL09-00-000635
    - NIST-800-171-3.1.7
    - NIST-800-53-AU-12(c)
    - NIST-800-53-AU-2(d)
    - NIST-800-53-CM-6(a)
    - PCI-DSS-Req-10.2.1
    - PCI-DSS-Req-10.2.4
    - audit_rules_unsuccessful_file_modification_open_by_handle_at
    - low_complexity
    - low_disruption
    - medium_severity
    - reboot_required
    - restrict_strategy

  - name: Perform remediation of Audit rules for open_by_handle_at EPERM for 32bit
      platform
    block:

    - name: Declare list of syscalls
      ansible.builtin.set_fact:
        syscalls:
        - open_by_handle_at
        syscall_grouping:
        - creat
        - ftruncate
        - truncate
        - open
        - openat
        - open_by_handle_at

    - name: Check existence of open_by_handle_at in /etc/audit/rules.d/
      ansible.builtin.find:
        paths: /etc/audit/rules.d
        contains: -a always,exit -F arch=b32(( -S |,)\w+)*(( -S |,){{ item }})+((
          -S |,)\w+)* -F exit=-EPERM -F auid>=1000 -F auid!=unset (-k\s+|-F\s+key=)\S+\s*$
        patterns: '*.rules'
      register: find_command
      loop: '{{ (syscall_grouping + syscalls) | unique }}'

    - name: Reset syscalls found per file
      ansible.builtin.set_fact:
        syscalls_per_file: {}
        found_paths_dict: {}

    - name: Declare syscalls found per file
      ansible.builtin.set_fact: syscalls_per_file="{{ syscalls_per_file | combine(
        {item.files[0].path :[item.item] + syscalls_per_file.get(item.files[0].path,
        []) } ) }}"
      loop: '{{ find_command.results | selectattr(''matched'') | list }}'

    - name: Declare files where syscalls were found
      ansible.builtin.set_fact: found_paths="{{ find_command.results | map(attribute='files')
        | flatten | map(attribute='path') | list }}"

    - name: Count occurrences of syscalls in paths
      ansible.builtin.set_fact: found_paths_dict="{{ found_paths_dict | combine({
        item:1+found_paths_dict.get(item, 0) }) }}"
      loop: '{{ find_command.results | map(attribute=''files'') | flatten | map(attribute=''path'')
        | list }}'

    - name: Get path with most syscalls
      ansible.builtin.set_fact: audit_file="{{ (found_paths_dict | dict2items() |
        sort(attribute='value') | last).key }}"
      when: found_paths | length >= 1

    - name: No file with syscall found, set path to /etc/audit/rules.d/access.rules
      ansible.builtin.set_fact: audit_file="/etc/audit/rules.d/access.rules"
      when: found_paths | length == 0

    - name: Declare found syscalls
      ansible.builtin.set_fact: syscalls_found="{{ find_command.results | selectattr('matched')
        | map(attribute='item') | list }}"

    - name: Declare missing syscalls
      ansible.builtin.set_fact: missing_syscalls="{{ syscalls | difference(syscalls_found)
        }}"

    - name: Replace the audit rule in {{ audit_file }}
      ansible.builtin.lineinfile:
        path: '{{ audit_file }}'
        regexp: (-a always,exit -F arch=b32)(?=.*(?:(?:-S |,)(?:{{ syscalls_per_file[audit_file]
          | join("|") }}))\b)((?:( -S |,)\w+)+)( -F exit=-EPERM -F auid>=1000 -F auid!=unset
          (?:-k |-F key=)\w+)
        line: \1\2\3{{ missing_syscalls | join("\3") }}\4
        backrefs: true
        state: present
        mode: g-rwx,o-rwx
      when: syscalls_found | length > 0 and missing_syscalls | length > 0

    - name: Add the audit rule to {{ audit_file }}
      ansible.builtin.lineinfile:
        path: '{{ audit_file }}'
        line: -a always,exit -F arch=b32 -S {{ syscalls | join(',') }} -F exit=-EPERM
          -F auid>=1000 -F auid!=unset -F key=access
        create: true
        mode: g-rwx,o-rwx
        state: present
      when: syscalls_found | length == 0

    - name: Declare list of syscalls
      ansible.builtin.set_fact:
        syscalls:
        - open_by_handle_at
        syscall_grouping:
        - creat
        - ftruncate
        - truncate
        - open
        - openat
        - open_by_handle_at

    - name: Check existence of open_by_handle_at in /etc/audit/audit.rules
      ansible.builtin.find:
        paths: /etc/audit
        contains: -a always,exit -F arch=b32(( -S |,)\w+)*(( -S |,){{ item }})+((
          -S |,)\w+)* -F exit=-EPERM -F auid>=1000 -F auid!=unset (-k\s+|-F\s+key=)\S+\s*$
        patterns: audit.rules
      register: find_command
      loop: '{{ (syscall_grouping + syscalls) | unique }}'

    - name: Set path to /etc/audit/audit.rules
      ansible.builtin.set_fact: audit_file="/etc/audit/audit.rules"

    - name: Declare found syscalls
      ansible.builtin.set_fact: syscalls_found="{{ find_command.results | selectattr('matched')
        | map(attribute='item') | list }}"

    - name: Declare missing syscalls
      ansible.builtin.set_fact: missing_syscalls="{{ syscalls | difference(syscalls_found)
        }}"

    - name: Replace the audit rule in {{ audit_file }}
      ansible.builtin.lineinfile:
        path: '{{ audit_file }}'
        regexp: (-a always,exit -F arch=b32)(?=.*(?:(?:-S |,)(?:{{ syscalls_found
          | join("|") }}))\b)((?:( -S |,)\w+)+)( -F exit=-EPERM -F auid>=1000 -F auid!=unset
          (?:-k |-F key=)\w+)
        line: \1\2\3{{ missing_syscalls | join("\3") }}\4
        backrefs: true
        state: present
        mode: g-rwx,o-rwx
      when: syscalls_found | length > 0 and missing_syscalls | length > 0

    - name: Add the audit rule to {{ audit_file }}
      ansible.builtin.lineinfile:
        path: '{{ audit_file }}'
        line: -a always,exit -F arch=b32 -S {{ syscalls | join(',') }} -F exit=-EPERM
          -F auid>=1000 -F auid!=unset -F key=access
        create: true
        mode: g-rwx,o-rwx
        state: present
      when: syscalls_found | length == 0
    when:
    - '"audit" in ansible_facts.packages'
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-000635
    - NIST-800-171-3.1.7
    - NIST-800-53-AU-12(c)
    - NIST-800-53-AU-2(d)
    - NIST-800-53-CM-6(a)
    - PCI-DSS-Req-10.2.1
    - PCI-DSS-Req-10.2.4
    - audit_rules_unsuccessful_file_modification_open_by_handle_at
    - low_complexity
    - low_disruption
    - medium_severity
    - reboot_required
    - restrict_strategy

  - name: Perform remediation of Audit rules for open_by_handle_at EPERM for 64bit
      platform
    block:

    - name: Declare list of syscalls
      ansible.builtin.set_fact:
        syscalls:
        - open_by_handle_at
        syscall_grouping:
        - creat
        - ftruncate
        - truncate
        - open
        - openat
        - open_by_handle_at

    - name: Check existence of open_by_handle_at in /etc/audit/rules.d/
      ansible.builtin.find:
        paths: /etc/audit/rules.d
        contains: -a always,exit -F arch=b64(( -S |,)\w+)*(( -S |,){{ item }})+((
          -S |,)\w+)* -F exit=-EPERM -F auid>=1000 -F auid!=unset (-k\s+|-F\s+key=)\S+\s*$
        patterns: '*.rules'
      register: find_command
      loop: '{{ (syscall_grouping + syscalls) | unique }}'

    - name: Reset syscalls found per file
      ansible.builtin.set_fact:
        syscalls_per_file: {}
        found_paths_dict: {}

    - name: Declare syscalls found per file
      ansible.builtin.set_fact: syscalls_per_file="{{ syscalls_per_file | combine(
        {item.files[0].path :[item.item] + syscalls_per_file.get(item.files[0].path,
        []) } ) }}"
      loop: '{{ find_command.results | selectattr(''matched'') | list }}'

    - name: Declare files where syscalls were found
      ansible.builtin.set_fact: found_paths="{{ find_command.results | map(attribute='files')
        | flatten | map(attribute='path') | list }}"

    - name: Count occurrences of syscalls in paths
      ansible.builtin.set_fact: found_paths_dict="{{ found_paths_dict | combine({
        item:1+found_paths_dict.get(item, 0) }) }}"
      loop: '{{ find_command.results | map(attribute=''files'') | flatten | map(attribute=''path'')
        | list }}'

    - name: Get path with most syscalls
      ansible.builtin.set_fact: audit_file="{{ (found_paths_dict | dict2items() |
        sort(attribute='value') | last).key }}"
      when: found_paths | length >= 1

    - name: No file with syscall found, set path to /etc/audit/rules.d/access.rules
      ansible.builtin.set_fact: audit_file="/etc/audit/rules.d/access.rules"
      when: found_paths | length == 0

    - name: Declare found syscalls
      ansible.builtin.set_fact: syscalls_found="{{ find_command.results | selectattr('matched')
        | map(attribute='item') | list }}"

    - name: Declare missing syscalls
      ansible.builtin.set_fact: missing_syscalls="{{ syscalls | difference(syscalls_found)
        }}"

    - name: Replace the audit rule in {{ audit_file }}
      ansible.builtin.lineinfile:
        path: '{{ audit_file }}'
        regexp: (-a always,exit -F arch=b64)(?=.*(?:(?:-S |,)(?:{{ syscalls_per_file[audit_file]
          | join("|") }}))\b)((?:( -S |,)\w+)+)( -F exit=-EPERM -F auid>=1000 -F auid!=unset
          (?:-k |-F key=)\w+)
        line: \1\2\3{{ missing_syscalls | join("\3") }}\4
        backrefs: true
        state: present
        mode: g-rwx,o-rwx
      when: syscalls_found | length > 0 and missing_syscalls | length > 0

    - name: Add the audit rule to {{ audit_file }}
      ansible.builtin.lineinfile:
        path: '{{ audit_file }}'
        line: -a always,exit -F arch=b64 -S {{ syscalls | join(',') }} -F exit=-EPERM
          -F auid>=1000 -F auid!=unset -F key=access
        create: true
        mode: g-rwx,o-rwx
        state: present
      when: syscalls_found | length == 0

    - name: Declare list of syscalls
      ansible.builtin.set_fact:
        syscalls:
        - open_by_handle_at
        syscall_grouping:
        - creat
        - ftruncate
        - truncate
        - open
        - openat
        - open_by_handle_at

    - name: Check existence of open_by_handle_at in /etc/audit/audit.rules
      ansible.builtin.find:
        paths: /etc/audit
        contains: -a always,exit -F arch=b64(( -S |,)\w+)*(( -S |,){{ item }})+((
          -S |,)\w+)* -F exit=-EPERM -F auid>=1000 -F auid!=unset (-k\s+|-F\s+key=)\S+\s*$
        patterns: audit.rules
      register: find_command
      loop: '{{ (syscall_grouping + syscalls) | unique }}'

    - name: Set path to /etc/audit/audit.rules
      ansible.builtin.set_fact: audit_file="/etc/audit/audit.rules"

    - name: Declare found syscalls
      ansible.builtin.set_fact: syscalls_found="{{ find_command.results | selectattr('matched')
        | map(attribute='item') | list }}"

    - name: Declare missing syscalls
      ansible.builtin.set_fact: missing_syscalls="{{ syscalls | difference(syscalls_found)
        }}"

    - name: Replace the audit rule in {{ audit_file }}
      ansible.builtin.lineinfile:
        path: '{{ audit_file }}'
        regexp: (-a always,exit -F arch=b64)(?=.*(?:(?:-S |,)(?:{{ syscalls_found
          | join("|") }}))\b)((?:( -S |,)\w+)+)( -F exit=-EPERM -F auid>=1000 -F auid!=unset
          (?:-k |-F key=)\w+)
        line: \1\2\3{{ missing_syscalls | join("\3") }}\4
        backrefs: true
        state: present
        mode: g-rwx,o-rwx
      when: syscalls_found | length > 0 and missing_syscalls | length > 0

    - name: Add the audit rule to {{ audit_file }}
      ansible.builtin.lineinfile:
        path: '{{ audit_file }}'
        line: -a always,exit -F arch=b64 -S {{ syscalls | join(',') }} -F exit=-EPERM
          -F auid>=1000 -F auid!=unset -F key=access
        create: true
        mode: g-rwx,o-rwx
        state: present
      when: syscalls_found | length == 0
    when:
    - '"audit" in ansible_facts.packages'
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - audit_arch == "b64"
    tags:
    - DISA-STIG-OL09-00-000635
    - NIST-800-171-3.1.7
    - NIST-800-53-AU-12(c)
    - NIST-800-53-AU-2(d)
    - NIST-800-53-CM-6(a)
    - PCI-DSS-Req-10.2.1
    - PCI-DSS-Req-10.2.4
    - audit_rules_unsuccessful_file_modification_open_by_handle_at
    - low_complexity
    - low_disruption
    - medium_severity
    - reboot_required
    - restrict_strategy

  - name: Set architecture for audit openat tasks
    ansible.builtin.set_fact:
      audit_arch: b64
    when:
    - '"audit" in ansible_facts.packages'
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - ansible_architecture == "aarch64" or ansible_architecture == "ppc64" or ansible_architecture
      == "ppc64le" or ansible_architecture == "s390x" or ansible_architecture == "x86_64"
    tags:
    - DISA-STIG-OL09-00-000635
    - NIST-800-171-3.1.7
    - NIST-800-53-AU-12(c)
    - NIST-800-53-AU-2(d)
    - NIST-800-53-CM-6(a)
    - PCI-DSS-Req-10.2.1
    - PCI-DSS-Req-10.2.4
    - audit_rules_unsuccessful_file_modification_openat
    - low_complexity
    - low_disruption
    - medium_severity
    - reboot_required
    - restrict_strategy

  - name: Perform remediation of Audit rules for openat EACCES for 32bit platform
    block:

    - name: Declare list of syscalls
      ansible.builtin.set_fact:
        syscalls:
        - openat
        syscall_grouping:
        - creat
        - ftruncate
        - truncate
        - open
        - openat
        - open_by_handle_at

    - name: Check existence of openat in /etc/audit/rules.d/
      ansible.builtin.find:
        paths: /etc/audit/rules.d
        contains: -a always,exit -F arch=b32(( -S |,)\w+)*(( -S |,){{ item }})+((
          -S |,)\w+)* -F exit=-EACCES -F auid>=1000 -F auid!=unset (-k\s+|-F\s+key=)\S+\s*$
        patterns: '*.rules'
      register: find_command
      loop: '{{ (syscall_grouping + syscalls) | unique }}'

    - name: Reset syscalls found per file
      ansible.builtin.set_fact:
        syscalls_per_file: {}
        found_paths_dict: {}

    - name: Declare syscalls found per file
      ansible.builtin.set_fact: syscalls_per_file="{{ syscalls_per_file | combine(
        {item.files[0].path :[item.item] + syscalls_per_file.get(item.files[0].path,
        []) } ) }}"
      loop: '{{ find_command.results | selectattr(''matched'') | list }}'

    - name: Declare files where syscalls were found
      ansible.builtin.set_fact: found_paths="{{ find_command.results | map(attribute='files')
        | flatten | map(attribute='path') | list }}"

    - name: Count occurrences of syscalls in paths
      ansible.builtin.set_fact: found_paths_dict="{{ found_paths_dict | combine({
        item:1+found_paths_dict.get(item, 0) }) }}"
      loop: '{{ find_command.results | map(attribute=''files'') | flatten | map(attribute=''path'')
        | list }}'

    - name: Get path with most syscalls
      ansible.builtin.set_fact: audit_file="{{ (found_paths_dict | dict2items() |
        sort(attribute='value') | last).key }}"
      when: found_paths | length >= 1

    - name: No file with syscall found, set path to /etc/audit/rules.d/access.rules
      ansible.builtin.set_fact: audit_file="/etc/audit/rules.d/access.rules"
      when: found_paths | length == 0

    - name: Declare found syscalls
      ansible.builtin.set_fact: syscalls_found="{{ find_command.results | selectattr('matched')
        | map(attribute='item') | list }}"

    - name: Declare missing syscalls
      ansible.builtin.set_fact: missing_syscalls="{{ syscalls | difference(syscalls_found)
        }}"

    - name: Replace the audit rule in {{ audit_file }}
      ansible.builtin.lineinfile:
        path: '{{ audit_file }}'
        regexp: (-a always,exit -F arch=b32)(?=.*(?:(?:-S |,)(?:{{ syscalls_per_file[audit_file]
          | join("|") }}))\b)((?:( -S |,)\w+)+)( -F exit=-EACCES -F auid>=1000 -F
          auid!=unset (?:-k |-F key=)\w+)
        line: \1\2\3{{ missing_syscalls | join("\3") }}\4
        backrefs: true
        state: present
        mode: g-rwx,o-rwx
      when: syscalls_found | length > 0 and missing_syscalls | length > 0

    - name: Add the audit rule to {{ audit_file }}
      ansible.builtin.lineinfile:
        path: '{{ audit_file }}'
        line: -a always,exit -F arch=b32 -S {{ syscalls | join(',') }} -F exit=-EACCES
          -F auid>=1000 -F auid!=unset -F key=access
        create: true
        mode: g-rwx,o-rwx
        state: present
      when: syscalls_found | length == 0

    - name: Declare list of syscalls
      ansible.builtin.set_fact:
        syscalls:
        - openat
        syscall_grouping:
        - creat
        - ftruncate
        - truncate
        - open
        - openat
        - open_by_handle_at

    - name: Check existence of openat in /etc/audit/audit.rules
      ansible.builtin.find:
        paths: /etc/audit
        contains: -a always,exit -F arch=b32(( -S |,)\w+)*(( -S |,){{ item }})+((
          -S |,)\w+)* -F exit=-EACCES -F auid>=1000 -F auid!=unset (-k\s+|-F\s+key=)\S+\s*$
        patterns: audit.rules
      register: find_command
      loop: '{{ (syscall_grouping + syscalls) | unique }}'

    - name: Set path to /etc/audit/audit.rules
      ansible.builtin.set_fact: audit_file="/etc/audit/audit.rules"

    - name: Declare found syscalls
      ansible.builtin.set_fact: syscalls_found="{{ find_command.results | selectattr('matched')
        | map(attribute='item') | list }}"

    - name: Declare missing syscalls
      ansible.builtin.set_fact: missing_syscalls="{{ syscalls | difference(syscalls_found)
        }}"

    - name: Replace the audit rule in {{ audit_file }}
      ansible.builtin.lineinfile:
        path: '{{ audit_file }}'
        regexp: (-a always,exit -F arch=b32)(?=.*(?:(?:-S |,)(?:{{ syscalls_found
          | join("|") }}))\b)((?:( -S |,)\w+)+)( -F exit=-EACCES -F auid>=1000 -F
          auid!=unset (?:-k |-F key=)\w+)
        line: \1\2\3{{ missing_syscalls | join("\3") }}\4
        backrefs: true
        state: present
        mode: g-rwx,o-rwx
      when: syscalls_found | length > 0 and missing_syscalls | length > 0

    - name: Add the audit rule to {{ audit_file }}
      ansible.builtin.lineinfile:
        path: '{{ audit_file }}'
        line: -a always,exit -F arch=b32 -S {{ syscalls | join(',') }} -F exit=-EACCES
          -F auid>=1000 -F auid!=unset -F key=access
        create: true
        mode: g-rwx,o-rwx
        state: present
      when: syscalls_found | length == 0
    when:
    - '"audit" in ansible_facts.packages'
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-000635
    - NIST-800-171-3.1.7
    - NIST-800-53-AU-12(c)
    - NIST-800-53-AU-2(d)
    - NIST-800-53-CM-6(a)
    - PCI-DSS-Req-10.2.1
    - PCI-DSS-Req-10.2.4
    - audit_rules_unsuccessful_file_modification_openat
    - low_complexity
    - low_disruption
    - medium_severity
    - reboot_required
    - restrict_strategy

  - name: Perform remediation of Audit rules for openat EACCES for 64bit platform
    block:

    - name: Declare list of syscalls
      ansible.builtin.set_fact:
        syscalls:
        - openat
        syscall_grouping:
        - creat
        - ftruncate
        - truncate
        - open
        - openat
        - open_by_handle_at

    - name: Check existence of openat in /etc/audit/rules.d/
      ansible.builtin.find:
        paths: /etc/audit/rules.d
        contains: -a always,exit -F arch=b64(( -S |,)\w+)*(( -S |,){{ item }})+((
          -S |,)\w+)* -F exit=-EACCES -F auid>=1000 -F auid!=unset (-k\s+|-F\s+key=)\S+\s*$
        patterns: '*.rules'
      register: find_command
      loop: '{{ (syscall_grouping + syscalls) | unique }}'

    - name: Reset syscalls found per file
      ansible.builtin.set_fact:
        syscalls_per_file: {}
        found_paths_dict: {}

    - name: Declare syscalls found per file
      ansible.builtin.set_fact: syscalls_per_file="{{ syscalls_per_file | combine(
        {item.files[0].path :[item.item] + syscalls_per_file.get(item.files[0].path,
        []) } ) }}"
      loop: '{{ find_command.results | selectattr(''matched'') | list }}'

    - name: Declare files where syscalls were found
      ansible.builtin.set_fact: found_paths="{{ find_command.results | map(attribute='files')
        | flatten | map(attribute='path') | list }}"

    - name: Count occurrences of syscalls in paths
      ansible.builtin.set_fact: found_paths_dict="{{ found_paths_dict | combine({
        item:1+found_paths_dict.get(item, 0) }) }}"
      loop: '{{ find_command.results | map(attribute=''files'') | flatten | map(attribute=''path'')
        | list }}'

    - name: Get path with most syscalls
      ansible.builtin.set_fact: audit_file="{{ (found_paths_dict | dict2items() |
        sort(attribute='value') | last).key }}"
      when: found_paths | length >= 1

    - name: No file with syscall found, set path to /etc/audit/rules.d/access.rules
      ansible.builtin.set_fact: audit_file="/etc/audit/rules.d/access.rules"
      when: found_paths | length == 0

    - name: Declare found syscalls
      ansible.builtin.set_fact: syscalls_found="{{ find_command.results | selectattr('matched')
        | map(attribute='item') | list }}"

    - name: Declare missing syscalls
      ansible.builtin.set_fact: missing_syscalls="{{ syscalls | difference(syscalls_found)
        }}"

    - name: Replace the audit rule in {{ audit_file }}
      ansible.builtin.lineinfile:
        path: '{{ audit_file }}'
        regexp: (-a always,exit -F arch=b64)(?=.*(?:(?:-S |,)(?:{{ syscalls_per_file[audit_file]
          | join("|") }}))\b)((?:( -S |,)\w+)+)( -F exit=-EACCES -F auid>=1000 -F
          auid!=unset (?:-k |-F key=)\w+)
        line: \1\2\3{{ missing_syscalls | join("\3") }}\4
        backrefs: true
        state: present
        mode: g-rwx,o-rwx
      when: syscalls_found | length > 0 and missing_syscalls | length > 0

    - name: Add the audit rule to {{ audit_file }}
      ansible.builtin.lineinfile:
        path: '{{ audit_file }}'
        line: -a always,exit -F arch=b64 -S {{ syscalls | join(',') }} -F exit=-EACCES
          -F auid>=1000 -F auid!=unset -F key=access
        create: true
        mode: g-rwx,o-rwx
        state: present
      when: syscalls_found | length == 0

    - name: Declare list of syscalls
      ansible.builtin.set_fact:
        syscalls:
        - openat
        syscall_grouping:
        - creat
        - ftruncate
        - truncate
        - open
        - openat
        - open_by_handle_at

    - name: Check existence of openat in /etc/audit/audit.rules
      ansible.builtin.find:
        paths: /etc/audit
        contains: -a always,exit -F arch=b64(( -S |,)\w+)*(( -S |,){{ item }})+((
          -S |,)\w+)* -F exit=-EACCES -F auid>=1000 -F auid!=unset (-k\s+|-F\s+key=)\S+\s*$
        patterns: audit.rules
      register: find_command
      loop: '{{ (syscall_grouping + syscalls) | unique }}'

    - name: Set path to /etc/audit/audit.rules
      ansible.builtin.set_fact: audit_file="/etc/audit/audit.rules"

    - name: Declare found syscalls
      ansible.builtin.set_fact: syscalls_found="{{ find_command.results | selectattr('matched')
        | map(attribute='item') | list }}"

    - name: Declare missing syscalls
      ansible.builtin.set_fact: missing_syscalls="{{ syscalls | difference(syscalls_found)
        }}"

    - name: Replace the audit rule in {{ audit_file }}
      ansible.builtin.lineinfile:
        path: '{{ audit_file }}'
        regexp: (-a always,exit -F arch=b64)(?=.*(?:(?:-S |,)(?:{{ syscalls_found
          | join("|") }}))\b)((?:( -S |,)\w+)+)( -F exit=-EACCES -F auid>=1000 -F
          auid!=unset (?:-k |-F key=)\w+)
        line: \1\2\3{{ missing_syscalls | join("\3") }}\4
        backrefs: true
        state: present
        mode: g-rwx,o-rwx
      when: syscalls_found | length > 0 and missing_syscalls | length > 0

    - name: Add the audit rule to {{ audit_file }}
      ansible.builtin.lineinfile:
        path: '{{ audit_file }}'
        line: -a always,exit -F arch=b64 -S {{ syscalls | join(',') }} -F exit=-EACCES
          -F auid>=1000 -F auid!=unset -F key=access
        create: true
        mode: g-rwx,o-rwx
        state: present
      when: syscalls_found | length == 0
    when:
    - '"audit" in ansible_facts.packages'
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - audit_arch == "b64"
    tags:
    - DISA-STIG-OL09-00-000635
    - NIST-800-171-3.1.7
    - NIST-800-53-AU-12(c)
    - NIST-800-53-AU-2(d)
    - NIST-800-53-CM-6(a)
    - PCI-DSS-Req-10.2.1
    - PCI-DSS-Req-10.2.4
    - audit_rules_unsuccessful_file_modification_openat
    - low_complexity
    - low_disruption
    - medium_severity
    - reboot_required
    - restrict_strategy

  - name: Perform remediation of Audit rules for openat EPERM for 32bit platform
    block:

    - name: Declare list of syscalls
      ansible.builtin.set_fact:
        syscalls:
        - openat
        syscall_grouping:
        - creat
        - ftruncate
        - truncate
        - open
        - openat
        - open_by_handle_at

    - name: Check existence of openat in /etc/audit/rules.d/
      ansible.builtin.find:
        paths: /etc/audit/rules.d
        contains: -a always,exit -F arch=b32(( -S |,)\w+)*(( -S |,){{ item }})+((
          -S |,)\w+)* -F exit=-EPERM -F auid>=1000 -F auid!=unset (-k\s+|-F\s+key=)\S+\s*$
        patterns: '*.rules'
      register: find_command
      loop: '{{ (syscall_grouping + syscalls) | unique }}'

    - name: Reset syscalls found per file
      ansible.builtin.set_fact:
        syscalls_per_file: {}
        found_paths_dict: {}

    - name: Declare syscalls found per file
      ansible.builtin.set_fact: syscalls_per_file="{{ syscalls_per_file | combine(
        {item.files[0].path :[item.item] + syscalls_per_file.get(item.files[0].path,
        []) } ) }}"
      loop: '{{ find_command.results | selectattr(''matched'') | list }}'

    - name: Declare files where syscalls were found
      ansible.builtin.set_fact: found_paths="{{ find_command.results | map(attribute='files')
        | flatten | map(attribute='path') | list }}"

    - name: Count occurrences of syscalls in paths
      ansible.builtin.set_fact: found_paths_dict="{{ found_paths_dict | combine({
        item:1+found_paths_dict.get(item, 0) }) }}"
      loop: '{{ find_command.results | map(attribute=''files'') | flatten | map(attribute=''path'')
        | list }}'

    - name: Get path with most syscalls
      ansible.builtin.set_fact: audit_file="{{ (found_paths_dict | dict2items() |
        sort(attribute='value') | last).key }}"
      when: found_paths | length >= 1

    - name: No file with syscall found, set path to /etc/audit/rules.d/access.rules
      ansible.builtin.set_fact: audit_file="/etc/audit/rules.d/access.rules"
      when: found_paths | length == 0

    - name: Declare found syscalls
      ansible.builtin.set_fact: syscalls_found="{{ find_command.results | selectattr('matched')
        | map(attribute='item') | list }}"

    - name: Declare missing syscalls
      ansible.builtin.set_fact: missing_syscalls="{{ syscalls | difference(syscalls_found)
        }}"

    - name: Replace the audit rule in {{ audit_file }}
      ansible.builtin.lineinfile:
        path: '{{ audit_file }}'
        regexp: (-a always,exit -F arch=b32)(?=.*(?:(?:-S |,)(?:{{ syscalls_per_file[audit_file]
          | join("|") }}))\b)((?:( -S |,)\w+)+)( -F exit=-EPERM -F auid>=1000 -F auid!=unset
          (?:-k |-F key=)\w+)
        line: \1\2\3{{ missing_syscalls | join("\3") }}\4
        backrefs: true
        state: present
        mode: g-rwx,o-rwx
      when: syscalls_found | length > 0 and missing_syscalls | length > 0

    - name: Add the audit rule to {{ audit_file }}
      ansible.builtin.lineinfile:
        path: '{{ audit_file }}'
        line: -a always,exit -F arch=b32 -S {{ syscalls | join(',') }} -F exit=-EPERM
          -F auid>=1000 -F auid!=unset -F key=access
        create: true
        mode: g-rwx,o-rwx
        state: present
      when: syscalls_found | length == 0

    - name: Declare list of syscalls
      ansible.builtin.set_fact:
        syscalls:
        - openat
        syscall_grouping:
        - creat
        - ftruncate
        - truncate
        - open
        - openat
        - open_by_handle_at

    - name: Check existence of openat in /etc/audit/audit.rules
      ansible.builtin.find:
        paths: /etc/audit
        contains: -a always,exit -F arch=b32(( -S |,)\w+)*(( -S |,){{ item }})+((
          -S |,)\w+)* -F exit=-EPERM -F auid>=1000 -F auid!=unset (-k\s+|-F\s+key=)\S+\s*$
        patterns: audit.rules
      register: find_command
      loop: '{{ (syscall_grouping + syscalls) | unique }}'

    - name: Set path to /etc/audit/audit.rules
      ansible.builtin.set_fact: audit_file="/etc/audit/audit.rules"

    - name: Declare found syscalls
      ansible.builtin.set_fact: syscalls_found="{{ find_command.results | selectattr('matched')
        | map(attribute='item') | list }}"

    - name: Declare missing syscalls
      ansible.builtin.set_fact: missing_syscalls="{{ syscalls | difference(syscalls_found)
        }}"

    - name: Replace the audit rule in {{ audit_file }}
      ansible.builtin.lineinfile:
        path: '{{ audit_file }}'
        regexp: (-a always,exit -F arch=b32)(?=.*(?:(?:-S |,)(?:{{ syscalls_found
          | join("|") }}))\b)((?:( -S |,)\w+)+)( -F exit=-EPERM -F auid>=1000 -F auid!=unset
          (?:-k |-F key=)\w+)
        line: \1\2\3{{ missing_syscalls | join("\3") }}\4
        backrefs: true
        state: present
        mode: g-rwx,o-rwx
      when: syscalls_found | length > 0 and missing_syscalls | length > 0

    - name: Add the audit rule to {{ audit_file }}
      ansible.builtin.lineinfile:
        path: '{{ audit_file }}'
        line: -a always,exit -F arch=b32 -S {{ syscalls | join(',') }} -F exit=-EPERM
          -F auid>=1000 -F auid!=unset -F key=access
        create: true
        mode: g-rwx,o-rwx
        state: present
      when: syscalls_found | length == 0
    when:
    - '"audit" in ansible_facts.packages'
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-000635
    - NIST-800-171-3.1.7
    - NIST-800-53-AU-12(c)
    - NIST-800-53-AU-2(d)
    - NIST-800-53-CM-6(a)
    - PCI-DSS-Req-10.2.1
    - PCI-DSS-Req-10.2.4
    - audit_rules_unsuccessful_file_modification_openat
    - low_complexity
    - low_disruption
    - medium_severity
    - reboot_required
    - restrict_strategy

  - name: Perform remediation of Audit rules for openat EPERM for 64bit platform
    block:

    - name: Declare list of syscalls
      ansible.builtin.set_fact:
        syscalls:
        - openat
        syscall_grouping:
        - creat
        - ftruncate
        - truncate
        - open
        - openat
        - open_by_handle_at

    - name: Check existence of openat in /etc/audit/rules.d/
      ansible.builtin.find:
        paths: /etc/audit/rules.d
        contains: -a always,exit -F arch=b64(( -S |,)\w+)*(( -S |,){{ item }})+((
          -S |,)\w+)* -F exit=-EPERM -F auid>=1000 -F auid!=unset (-k\s+|-F\s+key=)\S+\s*$
        patterns: '*.rules'
      register: find_command
      loop: '{{ (syscall_grouping + syscalls) | unique }}'

    - name: Reset syscalls found per file
      ansible.builtin.set_fact:
        syscalls_per_file: {}
        found_paths_dict: {}

    - name: Declare syscalls found per file
      ansible.builtin.set_fact: syscalls_per_file="{{ syscalls_per_file | combine(
        {item.files[0].path :[item.item] + syscalls_per_file.get(item.files[0].path,
        []) } ) }}"
      loop: '{{ find_command.results | selectattr(''matched'') | list }}'

    - name: Declare files where syscalls were found
      ansible.builtin.set_fact: found_paths="{{ find_command.results | map(attribute='files')
        | flatten | map(attribute='path') | list }}"

    - name: Count occurrences of syscalls in paths
      ansible.builtin.set_fact: found_paths_dict="{{ found_paths_dict | combine({
        item:1+found_paths_dict.get(item, 0) }) }}"
      loop: '{{ find_command.results | map(attribute=''files'') | flatten | map(attribute=''path'')
        | list }}'

    - name: Get path with most syscalls
      ansible.builtin.set_fact: audit_file="{{ (found_paths_dict | dict2items() |
        sort(attribute='value') | last).key }}"
      when: found_paths | length >= 1

    - name: No file with syscall found, set path to /etc/audit/rules.d/access.rules
      ansible.builtin.set_fact: audit_file="/etc/audit/rules.d/access.rules"
      when: found_paths | length == 0

    - name: Declare found syscalls
      ansible.builtin.set_fact: syscalls_found="{{ find_command.results | selectattr('matched')
        | map(attribute='item') | list }}"

    - name: Declare missing syscalls
      ansible.builtin.set_fact: missing_syscalls="{{ syscalls | difference(syscalls_found)
        }}"

    - name: Replace the audit rule in {{ audit_file }}
      ansible.builtin.lineinfile:
        path: '{{ audit_file }}'
        regexp: (-a always,exit -F arch=b64)(?=.*(?:(?:-S |,)(?:{{ syscalls_per_file[audit_file]
          | join("|") }}))\b)((?:( -S |,)\w+)+)( -F exit=-EPERM -F auid>=1000 -F auid!=unset
          (?:-k |-F key=)\w+)
        line: \1\2\3{{ missing_syscalls | join("\3") }}\4
        backrefs: true
        state: present
        mode: g-rwx,o-rwx
      when: syscalls_found | length > 0 and missing_syscalls | length > 0

    - name: Add the audit rule to {{ audit_file }}
      ansible.builtin.lineinfile:
        path: '{{ audit_file }}'
        line: -a always,exit -F arch=b64 -S {{ syscalls | join(',') }} -F exit=-EPERM
          -F auid>=1000 -F auid!=unset -F key=access
        create: true
        mode: g-rwx,o-rwx
        state: present
      when: syscalls_found | length == 0

    - name: Declare list of syscalls
      ansible.builtin.set_fact:
        syscalls:
        - openat
        syscall_grouping:
        - creat
        - ftruncate
        - truncate
        - open
        - openat
        - open_by_handle_at

    - name: Check existence of openat in /etc/audit/audit.rules
      ansible.builtin.find:
        paths: /etc/audit
        contains: -a always,exit -F arch=b64(( -S |,)\w+)*(( -S |,){{ item }})+((
          -S |,)\w+)* -F exit=-EPERM -F auid>=1000 -F auid!=unset (-k\s+|-F\s+key=)\S+\s*$
        patterns: audit.rules
      register: find_command
      loop: '{{ (syscall_grouping + syscalls) | unique }}'

    - name: Set path to /etc/audit/audit.rules
      ansible.builtin.set_fact: audit_file="/etc/audit/audit.rules"

    - name: Declare found syscalls
      ansible.builtin.set_fact: syscalls_found="{{ find_command.results | selectattr('matched')
        | map(attribute='item') | list }}"

    - name: Declare missing syscalls
      ansible.builtin.set_fact: missing_syscalls="{{ syscalls | difference(syscalls_found)
        }}"

    - name: Replace the audit rule in {{ audit_file }}
      ansible.builtin.lineinfile:
        path: '{{ audit_file }}'
        regexp: (-a always,exit -F arch=b64)(?=.*(?:(?:-S |,)(?:{{ syscalls_found
          | join("|") }}))\b)((?:( -S |,)\w+)+)( -F exit=-EPERM -F auid>=1000 -F auid!=unset
          (?:-k |-F key=)\w+)
        line: \1\2\3{{ missing_syscalls | join("\3") }}\4
        backrefs: true
        state: present
        mode: g-rwx,o-rwx
      when: syscalls_found | length > 0 and missing_syscalls | length > 0

    - name: Add the audit rule to {{ audit_file }}
      ansible.builtin.lineinfile:
        path: '{{ audit_file }}'
        line: -a always,exit -F arch=b64 -S {{ syscalls | join(',') }} -F exit=-EPERM
          -F auid>=1000 -F auid!=unset -F key=access
        create: true
        mode: g-rwx,o-rwx
        state: present
      when: syscalls_found | length == 0
    when:
    - '"audit" in ansible_facts.packages'
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - audit_arch == "b64"
    tags:
    - DISA-STIG-OL09-00-000635
    - NIST-800-171-3.1.7
    - NIST-800-53-AU-12(c)
    - NIST-800-53-AU-2(d)
    - NIST-800-53-CM-6(a)
    - PCI-DSS-Req-10.2.1
    - PCI-DSS-Req-10.2.4
    - audit_rules_unsuccessful_file_modification_openat
    - low_complexity
    - low_disruption
    - medium_severity
    - reboot_required
    - restrict_strategy

  - name: Set architecture for audit truncate tasks
    ansible.builtin.set_fact:
      audit_arch: b64
    when:
    - '"audit" in ansible_facts.packages'
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - ansible_architecture == "aarch64" or ansible_architecture == "ppc64" or ansible_architecture
      == "ppc64le" or ansible_architecture == "s390x" or ansible_architecture == "x86_64"
    tags:
    - DISA-STIG-OL09-00-000635
    - NIST-800-171-3.1.7
    - NIST-800-53-AU-12(c)
    - NIST-800-53-AU-2(d)
    - NIST-800-53-CM-6(a)
    - PCI-DSS-Req-10.2.1
    - PCI-DSS-Req-10.2.4
    - audit_rules_unsuccessful_file_modification_truncate
    - low_complexity
    - low_disruption
    - medium_severity
    - reboot_required
    - restrict_strategy

  - name: Perform remediation of Audit rules for truncate EACCES for 32bit platform
    block:

    - name: Declare list of syscalls
      ansible.builtin.set_fact:
        syscalls:
        - truncate
        syscall_grouping:
        - creat
        - ftruncate
        - truncate
        - open
        - openat
        - open_by_handle_at

    - name: Check existence of truncate in /etc/audit/rules.d/
      ansible.builtin.find:
        paths: /etc/audit/rules.d
        contains: -a always,exit -F arch=b32(( -S |,)\w+)*(( -S |,){{ item }})+((
          -S |,)\w+)* -F exit=-EACCES -F auid>=1000 -F auid!=unset (-k\s+|-F\s+key=)\S+\s*$
        patterns: '*.rules'
      register: find_command
      loop: '{{ (syscall_grouping + syscalls) | unique }}'

    - name: Reset syscalls found per file
      ansible.builtin.set_fact:
        syscalls_per_file: {}
        found_paths_dict: {}

    - name: Declare syscalls found per file
      ansible.builtin.set_fact: syscalls_per_file="{{ syscalls_per_file | combine(
        {item.files[0].path :[item.item] + syscalls_per_file.get(item.files[0].path,
        []) } ) }}"
      loop: '{{ find_command.results | selectattr(''matched'') | list }}'

    - name: Declare files where syscalls were found
      ansible.builtin.set_fact: found_paths="{{ find_command.results | map(attribute='files')
        | flatten | map(attribute='path') | list }}"

    - name: Count occurrences of syscalls in paths
      ansible.builtin.set_fact: found_paths_dict="{{ found_paths_dict | combine({
        item:1+found_paths_dict.get(item, 0) }) }}"
      loop: '{{ find_command.results | map(attribute=''files'') | flatten | map(attribute=''path'')
        | list }}'

    - name: Get path with most syscalls
      ansible.builtin.set_fact: audit_file="{{ (found_paths_dict | dict2items() |
        sort(attribute='value') | last).key }}"
      when: found_paths | length >= 1

    - name: No file with syscall found, set path to /etc/audit/rules.d/access.rules
      ansible.builtin.set_fact: audit_file="/etc/audit/rules.d/access.rules"
      when: found_paths | length == 0

    - name: Declare found syscalls
      ansible.builtin.set_fact: syscalls_found="{{ find_command.results | selectattr('matched')
        | map(attribute='item') | list }}"

    - name: Declare missing syscalls
      ansible.builtin.set_fact: missing_syscalls="{{ syscalls | difference(syscalls_found)
        }}"

    - name: Replace the audit rule in {{ audit_file }}
      ansible.builtin.lineinfile:
        path: '{{ audit_file }}'
        regexp: (-a always,exit -F arch=b32)(?=.*(?:(?:-S |,)(?:{{ syscalls_per_file[audit_file]
          | join("|") }}))\b)((?:( -S |,)\w+)+)( -F exit=-EACCES -F auid>=1000 -F
          auid!=unset (?:-k |-F key=)\w+)
        line: \1\2\3{{ missing_syscalls | join("\3") }}\4
        backrefs: true
        state: present
        mode: g-rwx,o-rwx
      when: syscalls_found | length > 0 and missing_syscalls | length > 0

    - name: Add the audit rule to {{ audit_file }}
      ansible.builtin.lineinfile:
        path: '{{ audit_file }}'
        line: -a always,exit -F arch=b32 -S {{ syscalls | join(',') }} -F exit=-EACCES
          -F auid>=1000 -F auid!=unset -F key=access
        create: true
        mode: g-rwx,o-rwx
        state: present
      when: syscalls_found | length == 0

    - name: Declare list of syscalls
      ansible.builtin.set_fact:
        syscalls:
        - truncate
        syscall_grouping:
        - creat
        - ftruncate
        - truncate
        - open
        - openat
        - open_by_handle_at

    - name: Check existence of truncate in /etc/audit/audit.rules
      ansible.builtin.find:
        paths: /etc/audit
        contains: -a always,exit -F arch=b32(( -S |,)\w+)*(( -S |,){{ item }})+((
          -S |,)\w+)* -F exit=-EACCES -F auid>=1000 -F auid!=unset (-k\s+|-F\s+key=)\S+\s*$
        patterns: audit.rules
      register: find_command
      loop: '{{ (syscall_grouping + syscalls) | unique }}'

    - name: Set path to /etc/audit/audit.rules
      ansible.builtin.set_fact: audit_file="/etc/audit/audit.rules"

    - name: Declare found syscalls
      ansible.builtin.set_fact: syscalls_found="{{ find_command.results | selectattr('matched')
        | map(attribute='item') | list }}"

    - name: Declare missing syscalls
      ansible.builtin.set_fact: missing_syscalls="{{ syscalls | difference(syscalls_found)
        }}"

    - name: Replace the audit rule in {{ audit_file }}
      ansible.builtin.lineinfile:
        path: '{{ audit_file }}'
        regexp: (-a always,exit -F arch=b32)(?=.*(?:(?:-S |,)(?:{{ syscalls_found
          | join("|") }}))\b)((?:( -S |,)\w+)+)( -F exit=-EACCES -F auid>=1000 -F
          auid!=unset (?:-k |-F key=)\w+)
        line: \1\2\3{{ missing_syscalls | join("\3") }}\4
        backrefs: true
        state: present
        mode: g-rwx,o-rwx
      when: syscalls_found | length > 0 and missing_syscalls | length > 0

    - name: Add the audit rule to {{ audit_file }}
      ansible.builtin.lineinfile:
        path: '{{ audit_file }}'
        line: -a always,exit -F arch=b32 -S {{ syscalls | join(',') }} -F exit=-EACCES
          -F auid>=1000 -F auid!=unset -F key=access
        create: true
        mode: g-rwx,o-rwx
        state: present
      when: syscalls_found | length == 0
    when:
    - '"audit" in ansible_facts.packages'
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-000635
    - NIST-800-171-3.1.7
    - NIST-800-53-AU-12(c)
    - NIST-800-53-AU-2(d)
    - NIST-800-53-CM-6(a)
    - PCI-DSS-Req-10.2.1
    - PCI-DSS-Req-10.2.4
    - audit_rules_unsuccessful_file_modification_truncate
    - low_complexity
    - low_disruption
    - medium_severity
    - reboot_required
    - restrict_strategy

  - name: Perform remediation of Audit rules for truncate EACCES for 64bit platform
    block:

    - name: Declare list of syscalls
      ansible.builtin.set_fact:
        syscalls:
        - truncate
        syscall_grouping:
        - creat
        - ftruncate
        - truncate
        - open
        - openat
        - open_by_handle_at

    - name: Check existence of truncate in /etc/audit/rules.d/
      ansible.builtin.find:
        paths: /etc/audit/rules.d
        contains: -a always,exit -F arch=b64(( -S |,)\w+)*(( -S |,){{ item }})+((
          -S |,)\w+)* -F exit=-EACCES -F auid>=1000 -F auid!=unset (-k\s+|-F\s+key=)\S+\s*$
        patterns: '*.rules'
      register: find_command
      loop: '{{ (syscall_grouping + syscalls) | unique }}'

    - name: Reset syscalls found per file
      ansible.builtin.set_fact:
        syscalls_per_file: {}
        found_paths_dict: {}

    - name: Declare syscalls found per file
      ansible.builtin.set_fact: syscalls_per_file="{{ syscalls_per_file | combine(
        {item.files[0].path :[item.item] + syscalls_per_file.get(item.files[0].path,
        []) } ) }}"
      loop: '{{ find_command.results | selectattr(''matched'') | list }}'

    - name: Declare files where syscalls were found
      ansible.builtin.set_fact: found_paths="{{ find_command.results | map(attribute='files')
        | flatten | map(attribute='path') | list }}"

    - name: Count occurrences of syscalls in paths
      ansible.builtin.set_fact: found_paths_dict="{{ found_paths_dict | combine({
        item:1+found_paths_dict.get(item, 0) }) }}"
      loop: '{{ find_command.results | map(attribute=''files'') | flatten | map(attribute=''path'')
        | list }}'

    - name: Get path with most syscalls
      ansible.builtin.set_fact: audit_file="{{ (found_paths_dict | dict2items() |
        sort(attribute='value') | last).key }}"
      when: found_paths | length >= 1

    - name: No file with syscall found, set path to /etc/audit/rules.d/access.rules
      ansible.builtin.set_fact: audit_file="/etc/audit/rules.d/access.rules"
      when: found_paths | length == 0

    - name: Declare found syscalls
      ansible.builtin.set_fact: syscalls_found="{{ find_command.results | selectattr('matched')
        | map(attribute='item') | list }}"

    - name: Declare missing syscalls
      ansible.builtin.set_fact: missing_syscalls="{{ syscalls | difference(syscalls_found)
        }}"

    - name: Replace the audit rule in {{ audit_file }}
      ansible.builtin.lineinfile:
        path: '{{ audit_file }}'
        regexp: (-a always,exit -F arch=b64)(?=.*(?:(?:-S |,)(?:{{ syscalls_per_file[audit_file]
          | join("|") }}))\b)((?:( -S |,)\w+)+)( -F exit=-EACCES -F auid>=1000 -F
          auid!=unset (?:-k |-F key=)\w+)
        line: \1\2\3{{ missing_syscalls | join("\3") }}\4
        backrefs: true
        state: present
        mode: g-rwx,o-rwx
      when: syscalls_found | length > 0 and missing_syscalls | length > 0

    - name: Add the audit rule to {{ audit_file }}
      ansible.builtin.lineinfile:
        path: '{{ audit_file }}'
        line: -a always,exit -F arch=b64 -S {{ syscalls | join(',') }} -F exit=-EACCES
          -F auid>=1000 -F auid!=unset -F key=access
        create: true
        mode: g-rwx,o-rwx
        state: present
      when: syscalls_found | length == 0

    - name: Declare list of syscalls
      ansible.builtin.set_fact:
        syscalls:
        - truncate
        syscall_grouping:
        - creat
        - ftruncate
        - truncate
        - open
        - openat
        - open_by_handle_at

    - name: Check existence of truncate in /etc/audit/audit.rules
      ansible.builtin.find:
        paths: /etc/audit
        contains: -a always,exit -F arch=b64(( -S |,)\w+)*(( -S |,){{ item }})+((
          -S |,)\w+)* -F exit=-EACCES -F auid>=1000 -F auid!=unset (-k\s+|-F\s+key=)\S+\s*$
        patterns: audit.rules
      register: find_command
      loop: '{{ (syscall_grouping + syscalls) | unique }}'

    - name: Set path to /etc/audit/audit.rules
      ansible.builtin.set_fact: audit_file="/etc/audit/audit.rules"

    - name: Declare found syscalls
      ansible.builtin.set_fact: syscalls_found="{{ find_command.results | selectattr('matched')
        | map(attribute='item') | list }}"

    - name: Declare missing syscalls
      ansible.builtin.set_fact: missing_syscalls="{{ syscalls | difference(syscalls_found)
        }}"

    - name: Replace the audit rule in {{ audit_file }}
      ansible.builtin.lineinfile:
        path: '{{ audit_file }}'
        regexp: (-a always,exit -F arch=b64)(?=.*(?:(?:-S |,)(?:{{ syscalls_found
          | join("|") }}))\b)((?:( -S |,)\w+)+)( -F exit=-EACCES -F auid>=1000 -F
          auid!=unset (?:-k |-F key=)\w+)
        line: \1\2\3{{ missing_syscalls | join("\3") }}\4
        backrefs: true
        state: present
        mode: g-rwx,o-rwx
      when: syscalls_found | length > 0 and missing_syscalls | length > 0

    - name: Add the audit rule to {{ audit_file }}
      ansible.builtin.lineinfile:
        path: '{{ audit_file }}'
        line: -a always,exit -F arch=b64 -S {{ syscalls | join(',') }} -F exit=-EACCES
          -F auid>=1000 -F auid!=unset -F key=access
        create: true
        mode: g-rwx,o-rwx
        state: present
      when: syscalls_found | length == 0
    when:
    - '"audit" in ansible_facts.packages'
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - audit_arch == "b64"
    tags:
    - DISA-STIG-OL09-00-000635
    - NIST-800-171-3.1.7
    - NIST-800-53-AU-12(c)
    - NIST-800-53-AU-2(d)
    - NIST-800-53-CM-6(a)
    - PCI-DSS-Req-10.2.1
    - PCI-DSS-Req-10.2.4
    - audit_rules_unsuccessful_file_modification_truncate
    - low_complexity
    - low_disruption
    - medium_severity
    - reboot_required
    - restrict_strategy

  - name: Perform remediation of Audit rules for truncate EPERM for 32bit platform
    block:

    - name: Declare list of syscalls
      ansible.builtin.set_fact:
        syscalls:
        - truncate
        syscall_grouping:
        - creat
        - ftruncate
        - truncate
        - open
        - openat
        - open_by_handle_at

    - name: Check existence of truncate in /etc/audit/rules.d/
      ansible.builtin.find:
        paths: /etc/audit/rules.d
        contains: -a always,exit -F arch=b32(( -S |,)\w+)*(( -S |,){{ item }})+((
          -S |,)\w+)* -F exit=-EPERM -F auid>=1000 -F auid!=unset (-k\s+|-F\s+key=)\S+\s*$
        patterns: '*.rules'
      register: find_command
      loop: '{{ (syscall_grouping + syscalls) | unique }}'

    - name: Reset syscalls found per file
      ansible.builtin.set_fact:
        syscalls_per_file: {}
        found_paths_dict: {}

    - name: Declare syscalls found per file
      ansible.builtin.set_fact: syscalls_per_file="{{ syscalls_per_file | combine(
        {item.files[0].path :[item.item] + syscalls_per_file.get(item.files[0].path,
        []) } ) }}"
      loop: '{{ find_command.results | selectattr(''matched'') | list }}'

    - name: Declare files where syscalls were found
      ansible.builtin.set_fact: found_paths="{{ find_command.results | map(attribute='files')
        | flatten | map(attribute='path') | list }}"

    - name: Count occurrences of syscalls in paths
      ansible.builtin.set_fact: found_paths_dict="{{ found_paths_dict | combine({
        item:1+found_paths_dict.get(item, 0) }) }}"
      loop: '{{ find_command.results | map(attribute=''files'') | flatten | map(attribute=''path'')
        | list }}'

    - name: Get path with most syscalls
      ansible.builtin.set_fact: audit_file="{{ (found_paths_dict | dict2items() |
        sort(attribute='value') | last).key }}"
      when: found_paths | length >= 1

    - name: No file with syscall found, set path to /etc/audit/rules.d/access.rules
      ansible.builtin.set_fact: audit_file="/etc/audit/rules.d/access.rules"
      when: found_paths | length == 0

    - name: Declare found syscalls
      ansible.builtin.set_fact: syscalls_found="{{ find_command.results | selectattr('matched')
        | map(attribute='item') | list }}"

    - name: Declare missing syscalls
      ansible.builtin.set_fact: missing_syscalls="{{ syscalls | difference(syscalls_found)
        }}"

    - name: Replace the audit rule in {{ audit_file }}
      ansible.builtin.lineinfile:
        path: '{{ audit_file }}'
        regexp: (-a always,exit -F arch=b32)(?=.*(?:(?:-S |,)(?:{{ syscalls_per_file[audit_file]
          | join("|") }}))\b)((?:( -S |,)\w+)+)( -F exit=-EPERM -F auid>=1000 -F auid!=unset
          (?:-k |-F key=)\w+)
        line: \1\2\3{{ missing_syscalls | join("\3") }}\4
        backrefs: true
        state: present
        mode: g-rwx,o-rwx
      when: syscalls_found | length > 0 and missing_syscalls | length > 0

    - name: Add the audit rule to {{ audit_file }}
      ansible.builtin.lineinfile:
        path: '{{ audit_file }}'
        line: -a always,exit -F arch=b32 -S {{ syscalls | join(',') }} -F exit=-EPERM
          -F auid>=1000 -F auid!=unset -F key=access
        create: true
        mode: g-rwx,o-rwx
        state: present
      when: syscalls_found | length == 0

    - name: Declare list of syscalls
      ansible.builtin.set_fact:
        syscalls:
        - truncate
        syscall_grouping:
        - creat
        - ftruncate
        - truncate
        - open
        - openat
        - open_by_handle_at

    - name: Check existence of truncate in /etc/audit/audit.rules
      ansible.builtin.find:
        paths: /etc/audit
        contains: -a always,exit -F arch=b32(( -S |,)\w+)*(( -S |,){{ item }})+((
          -S |,)\w+)* -F exit=-EPERM -F auid>=1000 -F auid!=unset (-k\s+|-F\s+key=)\S+\s*$
        patterns: audit.rules
      register: find_command
      loop: '{{ (syscall_grouping + syscalls) | unique }}'

    - name: Set path to /etc/audit/audit.rules
      ansible.builtin.set_fact: audit_file="/etc/audit/audit.rules"

    - name: Declare found syscalls
      ansible.builtin.set_fact: syscalls_found="{{ find_command.results | selectattr('matched')
        | map(attribute='item') | list }}"

    - name: Declare missing syscalls
      ansible.builtin.set_fact: missing_syscalls="{{ syscalls | difference(syscalls_found)
        }}"

    - name: Replace the audit rule in {{ audit_file }}
      ansible.builtin.lineinfile:
        path: '{{ audit_file }}'
        regexp: (-a always,exit -F arch=b32)(?=.*(?:(?:-S |,)(?:{{ syscalls_found
          | join("|") }}))\b)((?:( -S |,)\w+)+)( -F exit=-EPERM -F auid>=1000 -F auid!=unset
          (?:-k |-F key=)\w+)
        line: \1\2\3{{ missing_syscalls | join("\3") }}\4
        backrefs: true
        state: present
        mode: g-rwx,o-rwx
      when: syscalls_found | length > 0 and missing_syscalls | length > 0

    - name: Add the audit rule to {{ audit_file }}
      ansible.builtin.lineinfile:
        path: '{{ audit_file }}'
        line: -a always,exit -F arch=b32 -S {{ syscalls | join(',') }} -F exit=-EPERM
          -F auid>=1000 -F auid!=unset -F key=access
        create: true
        mode: g-rwx,o-rwx
        state: present
      when: syscalls_found | length == 0
    when:
    - '"audit" in ansible_facts.packages'
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-000635
    - NIST-800-171-3.1.7
    - NIST-800-53-AU-12(c)
    - NIST-800-53-AU-2(d)
    - NIST-800-53-CM-6(a)
    - PCI-DSS-Req-10.2.1
    - PCI-DSS-Req-10.2.4
    - audit_rules_unsuccessful_file_modification_truncate
    - low_complexity
    - low_disruption
    - medium_severity
    - reboot_required
    - restrict_strategy

  - name: Perform remediation of Audit rules for truncate EPERM for 64bit platform
    block:

    - name: Declare list of syscalls
      ansible.builtin.set_fact:
        syscalls:
        - truncate
        syscall_grouping:
        - creat
        - ftruncate
        - truncate
        - open
        - openat
        - open_by_handle_at

    - name: Check existence of truncate in /etc/audit/rules.d/
      ansible.builtin.find:
        paths: /etc/audit/rules.d
        contains: -a always,exit -F arch=b64(( -S |,)\w+)*(( -S |,){{ item }})+((
          -S |,)\w+)* -F exit=-EPERM -F auid>=1000 -F auid!=unset (-k\s+|-F\s+key=)\S+\s*$
        patterns: '*.rules'
      register: find_command
      loop: '{{ (syscall_grouping + syscalls) | unique }}'

    - name: Reset syscalls found per file
      ansible.builtin.set_fact:
        syscalls_per_file: {}
        found_paths_dict: {}

    - name: Declare syscalls found per file
      ansible.builtin.set_fact: syscalls_per_file="{{ syscalls_per_file | combine(
        {item.files[0].path :[item.item] + syscalls_per_file.get(item.files[0].path,
        []) } ) }}"
      loop: '{{ find_command.results | selectattr(''matched'') | list }}'

    - name: Declare files where syscalls were found
      ansible.builtin.set_fact: found_paths="{{ find_command.results | map(attribute='files')
        | flatten | map(attribute='path') | list }}"

    - name: Count occurrences of syscalls in paths
      ansible.builtin.set_fact: found_paths_dict="{{ found_paths_dict | combine({
        item:1+found_paths_dict.get(item, 0) }) }}"
      loop: '{{ find_command.results | map(attribute=''files'') | flatten | map(attribute=''path'')
        | list }}'

    - name: Get path with most syscalls
      ansible.builtin.set_fact: audit_file="{{ (found_paths_dict | dict2items() |
        sort(attribute='value') | last).key }}"
      when: found_paths | length >= 1

    - name: No file with syscall found, set path to /etc/audit/rules.d/access.rules
      ansible.builtin.set_fact: audit_file="/etc/audit/rules.d/access.rules"
      when: found_paths | length == 0

    - name: Declare found syscalls
      ansible.builtin.set_fact: syscalls_found="{{ find_command.results | selectattr('matched')
        | map(attribute='item') | list }}"

    - name: Declare missing syscalls
      ansible.builtin.set_fact: missing_syscalls="{{ syscalls | difference(syscalls_found)
        }}"

    - name: Replace the audit rule in {{ audit_file }}
      ansible.builtin.lineinfile:
        path: '{{ audit_file }}'
        regexp: (-a always,exit -F arch=b64)(?=.*(?:(?:-S |,)(?:{{ syscalls_per_file[audit_file]
          | join("|") }}))\b)((?:( -S |,)\w+)+)( -F exit=-EPERM -F auid>=1000 -F auid!=unset
          (?:-k |-F key=)\w+)
        line: \1\2\3{{ missing_syscalls | join("\3") }}\4
        backrefs: true
        state: present
        mode: g-rwx,o-rwx
      when: syscalls_found | length > 0 and missing_syscalls | length > 0

    - name: Add the audit rule to {{ audit_file }}
      ansible.builtin.lineinfile:
        path: '{{ audit_file }}'
        line: -a always,exit -F arch=b64 -S {{ syscalls | join(',') }} -F exit=-EPERM
          -F auid>=1000 -F auid!=unset -F key=access
        create: true
        mode: g-rwx,o-rwx
        state: present
      when: syscalls_found | length == 0

    - name: Declare list of syscalls
      ansible.builtin.set_fact:
        syscalls:
        - truncate
        syscall_grouping:
        - creat
        - ftruncate
        - truncate
        - open
        - openat
        - open_by_handle_at

    - name: Check existence of truncate in /etc/audit/audit.rules
      ansible.builtin.find:
        paths: /etc/audit
        contains: -a always,exit -F arch=b64(( -S |,)\w+)*(( -S |,){{ item }})+((
          -S |,)\w+)* -F exit=-EPERM -F auid>=1000 -F auid!=unset (-k\s+|-F\s+key=)\S+\s*$
        patterns: audit.rules
      register: find_command
      loop: '{{ (syscall_grouping + syscalls) | unique }}'

    - name: Set path to /etc/audit/audit.rules
      ansible.builtin.set_fact: audit_file="/etc/audit/audit.rules"

    - name: Declare found syscalls
      ansible.builtin.set_fact: syscalls_found="{{ find_command.results | selectattr('matched')
        | map(attribute='item') | list }}"

    - name: Declare missing syscalls
      ansible.builtin.set_fact: missing_syscalls="{{ syscalls | difference(syscalls_found)
        }}"

    - name: Replace the audit rule in {{ audit_file }}
      ansible.builtin.lineinfile:
        path: '{{ audit_file }}'
        regexp: (-a always,exit -F arch=b64)(?=.*(?:(?:-S |,)(?:{{ syscalls_found
          | join("|") }}))\b)((?:( -S |,)\w+)+)( -F exit=-EPERM -F auid>=1000 -F auid!=unset
          (?:-k |-F key=)\w+)
        line: \1\2\3{{ missing_syscalls | join("\3") }}\4
        backrefs: true
        state: present
        mode: g-rwx,o-rwx
      when: syscalls_found | length > 0 and missing_syscalls | length > 0

    - name: Add the audit rule to {{ audit_file }}
      ansible.builtin.lineinfile:
        path: '{{ audit_file }}'
        line: -a always,exit -F arch=b64 -S {{ syscalls | join(',') }} -F exit=-EPERM
          -F auid>=1000 -F auid!=unset -F key=access
        create: true
        mode: g-rwx,o-rwx
        state: present
      when: syscalls_found | length == 0
    when:
    - '"audit" in ansible_facts.packages'
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - audit_arch == "b64"
    tags:
    - DISA-STIG-OL09-00-000635
    - NIST-800-171-3.1.7
    - NIST-800-53-AU-12(c)
    - NIST-800-53-AU-2(d)
    - NIST-800-53-CM-6(a)
    - PCI-DSS-Req-10.2.1
    - PCI-DSS-Req-10.2.4
    - audit_rules_unsuccessful_file_modification_truncate
    - low_complexity
    - low_disruption
    - medium_severity
    - reboot_required
    - restrict_strategy

  - name: Ensure auditd Collects Information on Kernel Module Unloading - delete_module
      - Set architecture for audit ['delete_module'] tasks
    ansible.builtin.set_fact:
      audit_arch: b64
    when:
    - '"audit" in ansible_facts.packages'
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - ansible_architecture == "aarch64" or ansible_architecture == "ppc64" or ansible_architecture
      == "ppc64le" or ansible_architecture == "s390x" or ansible_architecture == "x86_64"
    tags:
    - DISA-STIG-OL09-00-000685
    - NIST-800-171-3.1.7
    - NIST-800-53-AC-6(9)
    - NIST-800-53-AU-12(c)
    - NIST-800-53-AU-2(d)
    - NIST-800-53-CM-6(a)
    - PCI-DSS-Req-10.2.7
    - audit_rules_kernel_module_loading_delete
    - configure_strategy
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

  - name: Ensure auditd Collects Information on Kernel Module Unloading - delete_module
      - Perform remediation of Audit rules for ['delete_module'] for 32bit platform
    block:

    - name: Declare list of syscalls
      ansible.builtin.set_fact:
        syscalls:
        - delete_module
        syscall_grouping:
        - create_module
        - delete_module
        - finit_module
        - init_module
        - query_module

    - name: Check existence of delete_module in /etc/audit/rules.d/
      ansible.builtin.find:
        paths: /etc/audit/rules.d
        contains: -a always,exit -F arch=b32(( -S |,)\w+)*(( -S |,){{ item }})+((
          -S |,)\w+)* -F auid>=1000 -F auid!=unset (-k\s+|-F\s+key=)\S+\s*$
        patterns: '*.rules'
      register: find_command
      loop: '{{ (syscall_grouping + syscalls) | unique }}'

    - name: Reset syscalls found per file
      ansible.builtin.set_fact:
        syscalls_per_file: {}
        found_paths_dict: {}

    - name: Declare syscalls found per file
      ansible.builtin.set_fact: syscalls_per_file="{{ syscalls_per_file | combine(
        {item.files[0].path :[item.item] + syscalls_per_file.get(item.files[0].path,
        []) } ) }}"
      loop: '{{ find_command.results | selectattr(''matched'') | list }}'

    - name: Declare files where syscalls were found
      ansible.builtin.set_fact: found_paths="{{ find_command.results | map(attribute='files')
        | flatten | map(attribute='path') | list }}"

    - name: Count occurrences of syscalls in paths
      ansible.builtin.set_fact: found_paths_dict="{{ found_paths_dict | combine({
        item:1+found_paths_dict.get(item, 0) }) }}"
      loop: '{{ find_command.results | map(attribute=''files'') | flatten | map(attribute=''path'')
        | list }}'

    - name: Get path with most syscalls
      ansible.builtin.set_fact: audit_file="{{ (found_paths_dict | dict2items() |
        sort(attribute='value') | last).key }}"
      when: found_paths | length >= 1

    - name: No file with syscall found, set path to /etc/audit/rules.d/modules.rules
      ansible.builtin.set_fact: audit_file="/etc/audit/rules.d/modules.rules"
      when: found_paths | length == 0

    - name: Declare found syscalls
      ansible.builtin.set_fact: syscalls_found="{{ find_command.results | selectattr('matched')
        | map(attribute='item') | list }}"

    - name: Declare missing syscalls
      ansible.builtin.set_fact: missing_syscalls="{{ syscalls | difference(syscalls_found)
        }}"

    - name: Replace the audit rule in {{ audit_file }}
      ansible.builtin.lineinfile:
        path: '{{ audit_file }}'
        regexp: (-a always,exit -F arch=b32)(?=.*(?:(?:-S |,)(?:{{ syscalls_per_file[audit_file]
          | join("|") }}))\b)((?:( -S |,)\w+)+)( -F auid>=1000 -F auid!=unset (?:-k
          |-F key=)\w+)
        line: \1\2\3{{ missing_syscalls | join("\3") }}\4
        backrefs: true
        state: present
        mode: g-rwx,o-rwx
      when: syscalls_found | length > 0 and missing_syscalls | length > 0

    - name: Add the audit rule to {{ audit_file }}
      ansible.builtin.lineinfile:
        path: '{{ audit_file }}'
        line: -a always,exit -F arch=b32 -S {{ syscalls | join(',') }} -F auid>=1000
          -F auid!=unset -F key=modules
        create: true
        mode: g-rwx,o-rwx
        state: present
      when: syscalls_found | length == 0

    - name: Declare list of syscalls
      ansible.builtin.set_fact:
        syscalls:
        - delete_module
        syscall_grouping:
        - create_module
        - delete_module
        - finit_module
        - init_module
        - query_module

    - name: Check existence of delete_module in /etc/audit/audit.rules
      ansible.builtin.find:
        paths: /etc/audit
        contains: -a always,exit -F arch=b32(( -S |,)\w+)*(( -S |,){{ item }})+((
          -S |,)\w+)* -F auid>=1000 -F auid!=unset (-k\s+|-F\s+key=)\S+\s*$
        patterns: audit.rules
      register: find_command
      loop: '{{ (syscall_grouping + syscalls) | unique }}'

    - name: Set path to /etc/audit/audit.rules
      ansible.builtin.set_fact: audit_file="/etc/audit/audit.rules"

    - name: Declare found syscalls
      ansible.builtin.set_fact: syscalls_found="{{ find_command.results | selectattr('matched')
        | map(attribute='item') | list }}"

    - name: Declare missing syscalls
      ansible.builtin.set_fact: missing_syscalls="{{ syscalls | difference(syscalls_found)
        }}"

    - name: Replace the audit rule in {{ audit_file }}
      ansible.builtin.lineinfile:
        path: '{{ audit_file }}'
        regexp: (-a always,exit -F arch=b32)(?=.*(?:(?:-S |,)(?:{{ syscalls_found
          | join("|") }}))\b)((?:( -S |,)\w+)+)( -F auid>=1000 -F auid!=unset (?:-k
          |-F key=)\w+)
        line: \1\2\3{{ missing_syscalls | join("\3") }}\4
        backrefs: true
        state: present
        mode: g-rwx,o-rwx
      when: syscalls_found | length > 0 and missing_syscalls | length > 0

    - name: Add the audit rule to {{ audit_file }}
      ansible.builtin.lineinfile:
        path: '{{ audit_file }}'
        line: -a always,exit -F arch=b32 -S {{ syscalls | join(',') }} -F auid>=1000
          -F auid!=unset -F key=modules
        create: true
        mode: g-rwx,o-rwx
        state: present
      when: syscalls_found | length == 0
    when:
    - '"audit" in ansible_facts.packages'
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-000685
    - NIST-800-171-3.1.7
    - NIST-800-53-AC-6(9)
    - NIST-800-53-AU-12(c)
    - NIST-800-53-AU-2(d)
    - NIST-800-53-CM-6(a)
    - PCI-DSS-Req-10.2.7
    - audit_rules_kernel_module_loading_delete
    - configure_strategy
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

  - name: Ensure auditd Collects Information on Kernel Module Unloading - delete_module
      - Perform remediation of Audit rules for ['delete_module'] for 64bit platform
    block:

    - name: Declare list of syscalls
      ansible.builtin.set_fact:
        syscalls:
        - delete_module
        syscall_grouping:
        - create_module
        - delete_module
        - finit_module
        - init_module
        - query_module

    - name: Check existence of delete_module in /etc/audit/rules.d/
      ansible.builtin.find:
        paths: /etc/audit/rules.d
        contains: -a always,exit -F arch=b64(( -S |,)\w+)*(( -S |,){{ item }})+((
          -S |,)\w+)* -F auid>=1000 -F auid!=unset (-k\s+|-F\s+key=)\S+\s*$
        patterns: '*.rules'
      register: find_command
      loop: '{{ (syscall_grouping + syscalls) | unique }}'

    - name: Reset syscalls found per file
      ansible.builtin.set_fact:
        syscalls_per_file: {}
        found_paths_dict: {}

    - name: Declare syscalls found per file
      ansible.builtin.set_fact: syscalls_per_file="{{ syscalls_per_file | combine(
        {item.files[0].path :[item.item] + syscalls_per_file.get(item.files[0].path,
        []) } ) }}"
      loop: '{{ find_command.results | selectattr(''matched'') | list }}'

    - name: Declare files where syscalls were found
      ansible.builtin.set_fact: found_paths="{{ find_command.results | map(attribute='files')
        | flatten | map(attribute='path') | list }}"

    - name: Count occurrences of syscalls in paths
      ansible.builtin.set_fact: found_paths_dict="{{ found_paths_dict | combine({
        item:1+found_paths_dict.get(item, 0) }) }}"
      loop: '{{ find_command.results | map(attribute=''files'') | flatten | map(attribute=''path'')
        | list }}'

    - name: Get path with most syscalls
      ansible.builtin.set_fact: audit_file="{{ (found_paths_dict | dict2items() |
        sort(attribute='value') | last).key }}"
      when: found_paths | length >= 1

    - name: No file with syscall found, set path to /etc/audit/rules.d/modules.rules
      ansible.builtin.set_fact: audit_file="/etc/audit/rules.d/modules.rules"
      when: found_paths | length == 0

    - name: Declare found syscalls
      ansible.builtin.set_fact: syscalls_found="{{ find_command.results | selectattr('matched')
        | map(attribute='item') | list }}"

    - name: Declare missing syscalls
      ansible.builtin.set_fact: missing_syscalls="{{ syscalls | difference(syscalls_found)
        }}"

    - name: Replace the audit rule in {{ audit_file }}
      ansible.builtin.lineinfile:
        path: '{{ audit_file }}'
        regexp: (-a always,exit -F arch=b64)(?=.*(?:(?:-S |,)(?:{{ syscalls_per_file[audit_file]
          | join("|") }}))\b)((?:( -S |,)\w+)+)( -F auid>=1000 -F auid!=unset (?:-k
          |-F key=)\w+)
        line: \1\2\3{{ missing_syscalls | join("\3") }}\4
        backrefs: true
        state: present
        mode: g-rwx,o-rwx
      when: syscalls_found | length > 0 and missing_syscalls | length > 0

    - name: Add the audit rule to {{ audit_file }}
      ansible.builtin.lineinfile:
        path: '{{ audit_file }}'
        line: -a always,exit -F arch=b64 -S {{ syscalls | join(',') }} -F auid>=1000
          -F auid!=unset -F key=modules
        create: true
        mode: g-rwx,o-rwx
        state: present
      when: syscalls_found | length == 0

    - name: Declare list of syscalls
      ansible.builtin.set_fact:
        syscalls:
        - delete_module
        syscall_grouping:
        - create_module
        - delete_module
        - finit_module
        - init_module
        - query_module

    - name: Check existence of delete_module in /etc/audit/audit.rules
      ansible.builtin.find:
        paths: /etc/audit
        contains: -a always,exit -F arch=b64(( -S |,)\w+)*(( -S |,){{ item }})+((
          -S |,)\w+)* -F auid>=1000 -F auid!=unset (-k\s+|-F\s+key=)\S+\s*$
        patterns: audit.rules
      register: find_command
      loop: '{{ (syscall_grouping + syscalls) | unique }}'

    - name: Set path to /etc/audit/audit.rules
      ansible.builtin.set_fact: audit_file="/etc/audit/audit.rules"

    - name: Declare found syscalls
      ansible.builtin.set_fact: syscalls_found="{{ find_command.results | selectattr('matched')
        | map(attribute='item') | list }}"

    - name: Declare missing syscalls
      ansible.builtin.set_fact: missing_syscalls="{{ syscalls | difference(syscalls_found)
        }}"

    - name: Replace the audit rule in {{ audit_file }}
      ansible.builtin.lineinfile:
        path: '{{ audit_file }}'
        regexp: (-a always,exit -F arch=b64)(?=.*(?:(?:-S |,)(?:{{ syscalls_found
          | join("|") }}))\b)((?:( -S |,)\w+)+)( -F auid>=1000 -F auid!=unset (?:-k
          |-F key=)\w+)
        line: \1\2\3{{ missing_syscalls | join("\3") }}\4
        backrefs: true
        state: present
        mode: g-rwx,o-rwx
      when: syscalls_found | length > 0 and missing_syscalls | length > 0

    - name: Add the audit rule to {{ audit_file }}
      ansible.builtin.lineinfile:
        path: '{{ audit_file }}'
        line: -a always,exit -F arch=b64 -S {{ syscalls | join(',') }} -F auid>=1000
          -F auid!=unset -F key=modules
        create: true
        mode: g-rwx,o-rwx
        state: present
      when: syscalls_found | length == 0
    when:
    - '"audit" in ansible_facts.packages'
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - audit_arch == "b64"
    tags:
    - DISA-STIG-OL09-00-000685
    - NIST-800-171-3.1.7
    - NIST-800-53-AC-6(9)
    - NIST-800-53-AU-12(c)
    - NIST-800-53-AU-2(d)
    - NIST-800-53-CM-6(a)
    - PCI-DSS-Req-10.2.7
    - audit_rules_kernel_module_loading_delete
    - configure_strategy
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

  - name: Ensure auditd Collects Information on Kernel Module Loading and Unloading
      - finit_module - Set architecture for audit ['finit_module'] tasks
    ansible.builtin.set_fact:
      audit_arch: b64
    when:
    - '"audit" in ansible_facts.packages'
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - ansible_architecture == "aarch64" or ansible_architecture == "ppc64" or ansible_architecture
      == "ppc64le" or ansible_architecture == "s390x" or ansible_architecture == "x86_64"
    tags:
    - DISA-STIG-OL09-00-000690
    - NIST-800-171-3.1.7
    - NIST-800-53-AC-6(9)
    - NIST-800-53-AU-12(c)
    - NIST-800-53-AU-2(d)
    - NIST-800-53-CM-6(a)
    - PCI-DSS-Req-10.2.7
    - audit_rules_kernel_module_loading_finit
    - configure_strategy
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

  - name: Ensure auditd Collects Information on Kernel Module Loading and Unloading
      - finit_module - Perform remediation of Audit rules for ['finit_module'] for
      32bit platform
    block:

    - name: Declare list of syscalls
      ansible.builtin.set_fact:
        syscalls:
        - finit_module
        syscall_grouping:
        - create_module
        - delete_module
        - finit_module
        - init_module
        - query_module

    - name: Check existence of finit_module in /etc/audit/rules.d/
      ansible.builtin.find:
        paths: /etc/audit/rules.d
        contains: -a always,exit -F arch=b32(( -S |,)\w+)*(( -S |,){{ item }})+((
          -S |,)\w+)* -F auid>=1000 -F auid!=unset (-k\s+|-F\s+key=)\S+\s*$
        patterns: '*.rules'
      register: find_command
      loop: '{{ (syscall_grouping + syscalls) | unique }}'

    - name: Reset syscalls found per file
      ansible.builtin.set_fact:
        syscalls_per_file: {}
        found_paths_dict: {}

    - name: Declare syscalls found per file
      ansible.builtin.set_fact: syscalls_per_file="{{ syscalls_per_file | combine(
        {item.files[0].path :[item.item] + syscalls_per_file.get(item.files[0].path,
        []) } ) }}"
      loop: '{{ find_command.results | selectattr(''matched'') | list }}'

    - name: Declare files where syscalls were found
      ansible.builtin.set_fact: found_paths="{{ find_command.results | map(attribute='files')
        | flatten | map(attribute='path') | list }}"

    - name: Count occurrences of syscalls in paths
      ansible.builtin.set_fact: found_paths_dict="{{ found_paths_dict | combine({
        item:1+found_paths_dict.get(item, 0) }) }}"
      loop: '{{ find_command.results | map(attribute=''files'') | flatten | map(attribute=''path'')
        | list }}'

    - name: Get path with most syscalls
      ansible.builtin.set_fact: audit_file="{{ (found_paths_dict | dict2items() |
        sort(attribute='value') | last).key }}"
      when: found_paths | length >= 1

    - name: No file with syscall found, set path to /etc/audit/rules.d/modules.rules
      ansible.builtin.set_fact: audit_file="/etc/audit/rules.d/modules.rules"
      when: found_paths | length == 0

    - name: Declare found syscalls
      ansible.builtin.set_fact: syscalls_found="{{ find_command.results | selectattr('matched')
        | map(attribute='item') | list }}"

    - name: Declare missing syscalls
      ansible.builtin.set_fact: missing_syscalls="{{ syscalls | difference(syscalls_found)
        }}"

    - name: Replace the audit rule in {{ audit_file }}
      ansible.builtin.lineinfile:
        path: '{{ audit_file }}'
        regexp: (-a always,exit -F arch=b32)(?=.*(?:(?:-S |,)(?:{{ syscalls_per_file[audit_file]
          | join("|") }}))\b)((?:( -S |,)\w+)+)( -F auid>=1000 -F auid!=unset (?:-k
          |-F key=)\w+)
        line: \1\2\3{{ missing_syscalls | join("\3") }}\4
        backrefs: true
        state: present
        mode: g-rwx,o-rwx
      when: syscalls_found | length > 0 and missing_syscalls | length > 0

    - name: Add the audit rule to {{ audit_file }}
      ansible.builtin.lineinfile:
        path: '{{ audit_file }}'
        line: -a always,exit -F arch=b32 -S {{ syscalls | join(',') }} -F auid>=1000
          -F auid!=unset -F key=modules
        create: true
        mode: g-rwx,o-rwx
        state: present
      when: syscalls_found | length == 0

    - name: Declare list of syscalls
      ansible.builtin.set_fact:
        syscalls:
        - finit_module
        syscall_grouping:
        - create_module
        - delete_module
        - finit_module
        - init_module
        - query_module

    - name: Check existence of finit_module in /etc/audit/audit.rules
      ansible.builtin.find:
        paths: /etc/audit
        contains: -a always,exit -F arch=b32(( -S |,)\w+)*(( -S |,){{ item }})+((
          -S |,)\w+)* -F auid>=1000 -F auid!=unset (-k\s+|-F\s+key=)\S+\s*$
        patterns: audit.rules
      register: find_command
      loop: '{{ (syscall_grouping + syscalls) | unique }}'

    - name: Set path to /etc/audit/audit.rules
      ansible.builtin.set_fact: audit_file="/etc/audit/audit.rules"

    - name: Declare found syscalls
      ansible.builtin.set_fact: syscalls_found="{{ find_command.results | selectattr('matched')
        | map(attribute='item') | list }}"

    - name: Declare missing syscalls
      ansible.builtin.set_fact: missing_syscalls="{{ syscalls | difference(syscalls_found)
        }}"

    - name: Replace the audit rule in {{ audit_file }}
      ansible.builtin.lineinfile:
        path: '{{ audit_file }}'
        regexp: (-a always,exit -F arch=b32)(?=.*(?:(?:-S |,)(?:{{ syscalls_found
          | join("|") }}))\b)((?:( -S |,)\w+)+)( -F auid>=1000 -F auid!=unset (?:-k
          |-F key=)\w+)
        line: \1\2\3{{ missing_syscalls | join("\3") }}\4
        backrefs: true
        state: present
        mode: g-rwx,o-rwx
      when: syscalls_found | length > 0 and missing_syscalls | length > 0

    - name: Add the audit rule to {{ audit_file }}
      ansible.builtin.lineinfile:
        path: '{{ audit_file }}'
        line: -a always,exit -F arch=b32 -S {{ syscalls | join(',') }} -F auid>=1000
          -F auid!=unset -F key=modules
        create: true
        mode: g-rwx,o-rwx
        state: present
      when: syscalls_found | length == 0
    when:
    - '"audit" in ansible_facts.packages'
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-000690
    - NIST-800-171-3.1.7
    - NIST-800-53-AC-6(9)
    - NIST-800-53-AU-12(c)
    - NIST-800-53-AU-2(d)
    - NIST-800-53-CM-6(a)
    - PCI-DSS-Req-10.2.7
    - audit_rules_kernel_module_loading_finit
    - configure_strategy
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

  - name: Ensure auditd Collects Information on Kernel Module Loading and Unloading
      - finit_module - Perform remediation of Audit rules for ['finit_module'] for
      64bit platform
    block:

    - name: Declare list of syscalls
      ansible.builtin.set_fact:
        syscalls:
        - finit_module
        syscall_grouping:
        - create_module
        - delete_module
        - finit_module
        - init_module
        - query_module

    - name: Check existence of finit_module in /etc/audit/rules.d/
      ansible.builtin.find:
        paths: /etc/audit/rules.d
        contains: -a always,exit -F arch=b64(( -S |,)\w+)*(( -S |,){{ item }})+((
          -S |,)\w+)* -F auid>=1000 -F auid!=unset (-k\s+|-F\s+key=)\S+\s*$
        patterns: '*.rules'
      register: find_command
      loop: '{{ (syscall_grouping + syscalls) | unique }}'

    - name: Reset syscalls found per file
      ansible.builtin.set_fact:
        syscalls_per_file: {}
        found_paths_dict: {}

    - name: Declare syscalls found per file
      ansible.builtin.set_fact: syscalls_per_file="{{ syscalls_per_file | combine(
        {item.files[0].path :[item.item] + syscalls_per_file.get(item.files[0].path,
        []) } ) }}"
      loop: '{{ find_command.results | selectattr(''matched'') | list }}'

    - name: Declare files where syscalls were found
      ansible.builtin.set_fact: found_paths="{{ find_command.results | map(attribute='files')
        | flatten | map(attribute='path') | list }}"

    - name: Count occurrences of syscalls in paths
      ansible.builtin.set_fact: found_paths_dict="{{ found_paths_dict | combine({
        item:1+found_paths_dict.get(item, 0) }) }}"
      loop: '{{ find_command.results | map(attribute=''files'') | flatten | map(attribute=''path'')
        | list }}'

    - name: Get path with most syscalls
      ansible.builtin.set_fact: audit_file="{{ (found_paths_dict | dict2items() |
        sort(attribute='value') | last).key }}"
      when: found_paths | length >= 1

    - name: No file with syscall found, set path to /etc/audit/rules.d/modules.rules
      ansible.builtin.set_fact: audit_file="/etc/audit/rules.d/modules.rules"
      when: found_paths | length == 0

    - name: Declare found syscalls
      ansible.builtin.set_fact: syscalls_found="{{ find_command.results | selectattr('matched')
        | map(attribute='item') | list }}"

    - name: Declare missing syscalls
      ansible.builtin.set_fact: missing_syscalls="{{ syscalls | difference(syscalls_found)
        }}"

    - name: Replace the audit rule in {{ audit_file }}
      ansible.builtin.lineinfile:
        path: '{{ audit_file }}'
        regexp: (-a always,exit -F arch=b64)(?=.*(?:(?:-S |,)(?:{{ syscalls_per_file[audit_file]
          | join("|") }}))\b)((?:( -S |,)\w+)+)( -F auid>=1000 -F auid!=unset (?:-k
          |-F key=)\w+)
        line: \1\2\3{{ missing_syscalls | join("\3") }}\4
        backrefs: true
        state: present
        mode: g-rwx,o-rwx
      when: syscalls_found | length > 0 and missing_syscalls | length > 0

    - name: Add the audit rule to {{ audit_file }}
      ansible.builtin.lineinfile:
        path: '{{ audit_file }}'
        line: -a always,exit -F arch=b64 -S {{ syscalls | join(',') }} -F auid>=1000
          -F auid!=unset -F key=modules
        create: true
        mode: g-rwx,o-rwx
        state: present
      when: syscalls_found | length == 0

    - name: Declare list of syscalls
      ansible.builtin.set_fact:
        syscalls:
        - finit_module
        syscall_grouping:
        - create_module
        - delete_module
        - finit_module
        - init_module
        - query_module

    - name: Check existence of finit_module in /etc/audit/audit.rules
      ansible.builtin.find:
        paths: /etc/audit
        contains: -a always,exit -F arch=b64(( -S |,)\w+)*(( -S |,){{ item }})+((
          -S |,)\w+)* -F auid>=1000 -F auid!=unset (-k\s+|-F\s+key=)\S+\s*$
        patterns: audit.rules
      register: find_command
      loop: '{{ (syscall_grouping + syscalls) | unique }}'

    - name: Set path to /etc/audit/audit.rules
      ansible.builtin.set_fact: audit_file="/etc/audit/audit.rules"

    - name: Declare found syscalls
      ansible.builtin.set_fact: syscalls_found="{{ find_command.results | selectattr('matched')
        | map(attribute='item') | list }}"

    - name: Declare missing syscalls
      ansible.builtin.set_fact: missing_syscalls="{{ syscalls | difference(syscalls_found)
        }}"

    - name: Replace the audit rule in {{ audit_file }}
      ansible.builtin.lineinfile:
        path: '{{ audit_file }}'
        regexp: (-a always,exit -F arch=b64)(?=.*(?:(?:-S |,)(?:{{ syscalls_found
          | join("|") }}))\b)((?:( -S |,)\w+)+)( -F auid>=1000 -F auid!=unset (?:-k
          |-F key=)\w+)
        line: \1\2\3{{ missing_syscalls | join("\3") }}\4
        backrefs: true
        state: present
        mode: g-rwx,o-rwx
      when: syscalls_found | length > 0 and missing_syscalls | length > 0

    - name: Add the audit rule to {{ audit_file }}
      ansible.builtin.lineinfile:
        path: '{{ audit_file }}'
        line: -a always,exit -F arch=b64 -S {{ syscalls | join(',') }} -F auid>=1000
          -F auid!=unset -F key=modules
        create: true
        mode: g-rwx,o-rwx
        state: present
      when: syscalls_found | length == 0
    when:
    - '"audit" in ansible_facts.packages'
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - audit_arch == "b64"
    tags:
    - DISA-STIG-OL09-00-000690
    - NIST-800-171-3.1.7
    - NIST-800-53-AC-6(9)
    - NIST-800-53-AU-12(c)
    - NIST-800-53-AU-2(d)
    - NIST-800-53-CM-6(a)
    - PCI-DSS-Req-10.2.7
    - audit_rules_kernel_module_loading_finit
    - configure_strategy
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

  - name: Ensure auditd Collects Information on Kernel Module Loading - init_module
      - Set architecture for audit ['init_module'] tasks
    ansible.builtin.set_fact:
      audit_arch: b64
    when:
    - '"audit" in ansible_facts.packages'
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - ansible_architecture == "aarch64" or ansible_architecture == "ppc64" or ansible_architecture
      == "ppc64le" or ansible_architecture == "s390x" or ansible_architecture == "x86_64"
    tags:
    - DISA-STIG-OL09-00-000690
    - NIST-800-171-3.1.7
    - NIST-800-53-AC-6(9)
    - NIST-800-53-AU-12(c)
    - NIST-800-53-AU-2(d)
    - NIST-800-53-CM-6(a)
    - PCI-DSS-Req-10.2.7
    - audit_rules_kernel_module_loading_init
    - configure_strategy
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

  - name: Ensure auditd Collects Information on Kernel Module Loading - init_module
      - Perform remediation of Audit rules for ['init_module'] for 32bit platform
    block:

    - name: Declare list of syscalls
      ansible.builtin.set_fact:
        syscalls:
        - init_module
        syscall_grouping:
        - create_module
        - delete_module
        - finit_module
        - init_module
        - query_module

    - name: Check existence of init_module in /etc/audit/rules.d/
      ansible.builtin.find:
        paths: /etc/audit/rules.d
        contains: -a always,exit -F arch=b32(( -S |,)\w+)*(( -S |,){{ item }})+((
          -S |,)\w+)* -F auid>=1000 -F auid!=unset (-k\s+|-F\s+key=)\S+\s*$
        patterns: '*.rules'
      register: find_command
      loop: '{{ (syscall_grouping + syscalls) | unique }}'

    - name: Reset syscalls found per file
      ansible.builtin.set_fact:
        syscalls_per_file: {}
        found_paths_dict: {}

    - name: Declare syscalls found per file
      ansible.builtin.set_fact: syscalls_per_file="{{ syscalls_per_file | combine(
        {item.files[0].path :[item.item] + syscalls_per_file.get(item.files[0].path,
        []) } ) }}"
      loop: '{{ find_command.results | selectattr(''matched'') | list }}'

    - name: Declare files where syscalls were found
      ansible.builtin.set_fact: found_paths="{{ find_command.results | map(attribute='files')
        | flatten | map(attribute='path') | list }}"

    - name: Count occurrences of syscalls in paths
      ansible.builtin.set_fact: found_paths_dict="{{ found_paths_dict | combine({
        item:1+found_paths_dict.get(item, 0) }) }}"
      loop: '{{ find_command.results | map(attribute=''files'') | flatten | map(attribute=''path'')
        | list }}'

    - name: Get path with most syscalls
      ansible.builtin.set_fact: audit_file="{{ (found_paths_dict | dict2items() |
        sort(attribute='value') | last).key }}"
      when: found_paths | length >= 1

    - name: No file with syscall found, set path to /etc/audit/rules.d/modules.rules
      ansible.builtin.set_fact: audit_file="/etc/audit/rules.d/modules.rules"
      when: found_paths | length == 0

    - name: Declare found syscalls
      ansible.builtin.set_fact: syscalls_found="{{ find_command.results | selectattr('matched')
        | map(attribute='item') | list }}"

    - name: Declare missing syscalls
      ansible.builtin.set_fact: missing_syscalls="{{ syscalls | difference(syscalls_found)
        }}"

    - name: Replace the audit rule in {{ audit_file }}
      ansible.builtin.lineinfile:
        path: '{{ audit_file }}'
        regexp: (-a always,exit -F arch=b32)(?=.*(?:(?:-S |,)(?:{{ syscalls_per_file[audit_file]
          | join("|") }}))\b)((?:( -S |,)\w+)+)( -F auid>=1000 -F auid!=unset (?:-k
          |-F key=)\w+)
        line: \1\2\3{{ missing_syscalls | join("\3") }}\4
        backrefs: true
        state: present
        mode: g-rwx,o-rwx
      when: syscalls_found | length > 0 and missing_syscalls | length > 0

    - name: Add the audit rule to {{ audit_file }}
      ansible.builtin.lineinfile:
        path: '{{ audit_file }}'
        line: -a always,exit -F arch=b32 -S {{ syscalls | join(',') }} -F auid>=1000
          -F auid!=unset -F key=modules
        create: true
        mode: g-rwx,o-rwx
        state: present
      when: syscalls_found | length == 0

    - name: Declare list of syscalls
      ansible.builtin.set_fact:
        syscalls:
        - init_module
        syscall_grouping:
        - create_module
        - delete_module
        - finit_module
        - init_module
        - query_module

    - name: Check existence of init_module in /etc/audit/audit.rules
      ansible.builtin.find:
        paths: /etc/audit
        contains: -a always,exit -F arch=b32(( -S |,)\w+)*(( -S |,){{ item }})+((
          -S |,)\w+)* -F auid>=1000 -F auid!=unset (-k\s+|-F\s+key=)\S+\s*$
        patterns: audit.rules
      register: find_command
      loop: '{{ (syscall_grouping + syscalls) | unique }}'

    - name: Set path to /etc/audit/audit.rules
      ansible.builtin.set_fact: audit_file="/etc/audit/audit.rules"

    - name: Declare found syscalls
      ansible.builtin.set_fact: syscalls_found="{{ find_command.results | selectattr('matched')
        | map(attribute='item') | list }}"

    - name: Declare missing syscalls
      ansible.builtin.set_fact: missing_syscalls="{{ syscalls | difference(syscalls_found)
        }}"

    - name: Replace the audit rule in {{ audit_file }}
      ansible.builtin.lineinfile:
        path: '{{ audit_file }}'
        regexp: (-a always,exit -F arch=b32)(?=.*(?:(?:-S |,)(?:{{ syscalls_found
          | join("|") }}))\b)((?:( -S |,)\w+)+)( -F auid>=1000 -F auid!=unset (?:-k
          |-F key=)\w+)
        line: \1\2\3{{ missing_syscalls | join("\3") }}\4
        backrefs: true
        state: present
        mode: g-rwx,o-rwx
      when: syscalls_found | length > 0 and missing_syscalls | length > 0

    - name: Add the audit rule to {{ audit_file }}
      ansible.builtin.lineinfile:
        path: '{{ audit_file }}'
        line: -a always,exit -F arch=b32 -S {{ syscalls | join(',') }} -F auid>=1000
          -F auid!=unset -F key=modules
        create: true
        mode: g-rwx,o-rwx
        state: present
      when: syscalls_found | length == 0
    when:
    - '"audit" in ansible_facts.packages'
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-000690
    - NIST-800-171-3.1.7
    - NIST-800-53-AC-6(9)
    - NIST-800-53-AU-12(c)
    - NIST-800-53-AU-2(d)
    - NIST-800-53-CM-6(a)
    - PCI-DSS-Req-10.2.7
    - audit_rules_kernel_module_loading_init
    - configure_strategy
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

  - name: Ensure auditd Collects Information on Kernel Module Loading - init_module
      - Perform remediation of Audit rules for ['init_module'] for 64bit platform
    block:

    - name: Declare list of syscalls
      ansible.builtin.set_fact:
        syscalls:
        - init_module
        syscall_grouping:
        - create_module
        - delete_module
        - finit_module
        - init_module
        - query_module

    - name: Check existence of init_module in /etc/audit/rules.d/
      ansible.builtin.find:
        paths: /etc/audit/rules.d
        contains: -a always,exit -F arch=b64(( -S |,)\w+)*(( -S |,){{ item }})+((
          -S |,)\w+)* -F auid>=1000 -F auid!=unset (-k\s+|-F\s+key=)\S+\s*$
        patterns: '*.rules'
      register: find_command
      loop: '{{ (syscall_grouping + syscalls) | unique }}'

    - name: Reset syscalls found per file
      ansible.builtin.set_fact:
        syscalls_per_file: {}
        found_paths_dict: {}

    - name: Declare syscalls found per file
      ansible.builtin.set_fact: syscalls_per_file="{{ syscalls_per_file | combine(
        {item.files[0].path :[item.item] + syscalls_per_file.get(item.files[0].path,
        []) } ) }}"
      loop: '{{ find_command.results | selectattr(''matched'') | list }}'

    - name: Declare files where syscalls were found
      ansible.builtin.set_fact: found_paths="{{ find_command.results | map(attribute='files')
        | flatten | map(attribute='path') | list }}"

    - name: Count occurrences of syscalls in paths
      ansible.builtin.set_fact: found_paths_dict="{{ found_paths_dict | combine({
        item:1+found_paths_dict.get(item, 0) }) }}"
      loop: '{{ find_command.results | map(attribute=''files'') | flatten | map(attribute=''path'')
        | list }}'

    - name: Get path with most syscalls
      ansible.builtin.set_fact: audit_file="{{ (found_paths_dict | dict2items() |
        sort(attribute='value') | last).key }}"
      when: found_paths | length >= 1

    - name: No file with syscall found, set path to /etc/audit/rules.d/modules.rules
      ansible.builtin.set_fact: audit_file="/etc/audit/rules.d/modules.rules"
      when: found_paths | length == 0

    - name: Declare found syscalls
      ansible.builtin.set_fact: syscalls_found="{{ find_command.results | selectattr('matched')
        | map(attribute='item') | list }}"

    - name: Declare missing syscalls
      ansible.builtin.set_fact: missing_syscalls="{{ syscalls | difference(syscalls_found)
        }}"

    - name: Replace the audit rule in {{ audit_file }}
      ansible.builtin.lineinfile:
        path: '{{ audit_file }}'
        regexp: (-a always,exit -F arch=b64)(?=.*(?:(?:-S |,)(?:{{ syscalls_per_file[audit_file]
          | join("|") }}))\b)((?:( -S |,)\w+)+)( -F auid>=1000 -F auid!=unset (?:-k
          |-F key=)\w+)
        line: \1\2\3{{ missing_syscalls | join("\3") }}\4
        backrefs: true
        state: present
        mode: g-rwx,o-rwx
      when: syscalls_found | length > 0 and missing_syscalls | length > 0

    - name: Add the audit rule to {{ audit_file }}
      ansible.builtin.lineinfile:
        path: '{{ audit_file }}'
        line: -a always,exit -F arch=b64 -S {{ syscalls | join(',') }} -F auid>=1000
          -F auid!=unset -F key=modules
        create: true
        mode: g-rwx,o-rwx
        state: present
      when: syscalls_found | length == 0

    - name: Declare list of syscalls
      ansible.builtin.set_fact:
        syscalls:
        - init_module
        syscall_grouping:
        - create_module
        - delete_module
        - finit_module
        - init_module
        - query_module

    - name: Check existence of init_module in /etc/audit/audit.rules
      ansible.builtin.find:
        paths: /etc/audit
        contains: -a always,exit -F arch=b64(( -S |,)\w+)*(( -S |,){{ item }})+((
          -S |,)\w+)* -F auid>=1000 -F auid!=unset (-k\s+|-F\s+key=)\S+\s*$
        patterns: audit.rules
      register: find_command
      loop: '{{ (syscall_grouping + syscalls) | unique }}'

    - name: Set path to /etc/audit/audit.rules
      ansible.builtin.set_fact: audit_file="/etc/audit/audit.rules"

    - name: Declare found syscalls
      ansible.builtin.set_fact: syscalls_found="{{ find_command.results | selectattr('matched')
        | map(attribute='item') | list }}"

    - name: Declare missing syscalls
      ansible.builtin.set_fact: missing_syscalls="{{ syscalls | difference(syscalls_found)
        }}"

    - name: Replace the audit rule in {{ audit_file }}
      ansible.builtin.lineinfile:
        path: '{{ audit_file }}'
        regexp: (-a always,exit -F arch=b64)(?=.*(?:(?:-S |,)(?:{{ syscalls_found
          | join("|") }}))\b)((?:( -S |,)\w+)+)( -F auid>=1000 -F auid!=unset (?:-k
          |-F key=)\w+)
        line: \1\2\3{{ missing_syscalls | join("\3") }}\4
        backrefs: true
        state: present
        mode: g-rwx,o-rwx
      when: syscalls_found | length > 0 and missing_syscalls | length > 0

    - name: Add the audit rule to {{ audit_file }}
      ansible.builtin.lineinfile:
        path: '{{ audit_file }}'
        line: -a always,exit -F arch=b64 -S {{ syscalls | join(',') }} -F auid>=1000
          -F auid!=unset -F key=modules
        create: true
        mode: g-rwx,o-rwx
        state: present
      when: syscalls_found | length == 0
    when:
    - '"audit" in ansible_facts.packages'
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - audit_arch == "b64"
    tags:
    - DISA-STIG-OL09-00-000690
    - NIST-800-171-3.1.7
    - NIST-800-53-AC-6(9)
    - NIST-800-53-AU-12(c)
    - NIST-800-53-AU-2(d)
    - NIST-800-53-CM-6(a)
    - PCI-DSS-Req-10.2.7
    - audit_rules_kernel_module_loading_init
    - configure_strategy
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

  - name: Record Attempts to Alter Logon and Logout Events - faillock - Check if watch
      rule for {{ var_accounts_passwords_pam_faillock_dir }} already exists in /etc/audit/rules.d/
    ansible.builtin.find:
      paths: /etc/audit/rules.d
      contains: ^\s*-w\s+{{ var_accounts_passwords_pam_faillock_dir }}\s+-p\s+wa(\s|$)+
      patterns: '*.rules'
    register: find_existing_watch_rules_d
    when:
    - '"audit" in ansible_facts.packages'
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-000720
    - NIST-800-171-3.1.7
    - NIST-800-53-AC-6(9)
    - NIST-800-53-AU-12(c)
    - NIST-800-53-AU-2(d)
    - NIST-800-53-CM-6(a)
    - PCI-DSS-Req-10.2.3
    - PCI-DSSv4-10.2
    - PCI-DSSv4-10.2.1
    - PCI-DSSv4-10.2.1.3
    - audit_rules_login_events_faillock
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Record Attempts to Alter Logon and Logout Events - faillock - Search /etc/audit/rules.d
      for other rules with specified key logins
    ansible.builtin.find:
      paths: /etc/audit/rules.d
      contains: ^.*(?:-F key=|-k\s+)logins$
      patterns: '*.rules'
    register: find_watch_key
    when:
    - '"audit" in ansible_facts.packages'
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - find_existing_watch_rules_d.matched is defined and find_existing_watch_rules_d.matched
      == 0
    tags:
    - DISA-STIG-OL09-00-000720
    - NIST-800-171-3.1.7
    - NIST-800-53-AC-6(9)
    - NIST-800-53-AU-12(c)
    - NIST-800-53-AU-2(d)
    - NIST-800-53-CM-6(a)
    - PCI-DSS-Req-10.2.3
    - PCI-DSSv4-10.2
    - PCI-DSSv4-10.2.1
    - PCI-DSSv4-10.2.1.3
    - audit_rules_login_events_faillock
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Record Attempts to Alter Logon and Logout Events - faillock - Use /etc/audit/rules.d/logins.rules
      as the recipient for the rule
    ansible.builtin.set_fact:
      all_files:
      - /etc/audit/rules.d/logins.rules
    when:
    - '"audit" in ansible_facts.packages'
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - find_watch_key.matched is defined and find_watch_key.matched == 0 and find_existing_watch_rules_d.matched
      is defined and find_existing_watch_rules_d.matched == 0
    tags:
    - DISA-STIG-OL09-00-000720
    - NIST-800-171-3.1.7
    - NIST-800-53-AC-6(9)
    - NIST-800-53-AU-12(c)
    - NIST-800-53-AU-2(d)
    - NIST-800-53-CM-6(a)
    - PCI-DSS-Req-10.2.3
    - PCI-DSSv4-10.2
    - PCI-DSSv4-10.2.1
    - PCI-DSSv4-10.2.1.3
    - audit_rules_login_events_faillock
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Record Attempts to Alter Logon and Logout Events - faillock - Use matched
      file as the recipient for the rule
    ansible.builtin.set_fact:
      all_files:
      - '{{ find_watch_key.files | map(attribute=''path'') | list | first }}'
    when:
    - '"audit" in ansible_facts.packages'
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - find_watch_key.matched is defined and find_watch_key.matched > 0 and find_existing_watch_rules_d.matched
      is defined and find_existing_watch_rules_d.matched == 0
    tags:
    - DISA-STIG-OL09-00-000720
    - NIST-800-171-3.1.7
    - NIST-800-53-AC-6(9)
    - NIST-800-53-AU-12(c)
    - NIST-800-53-AU-2(d)
    - NIST-800-53-CM-6(a)
    - PCI-DSS-Req-10.2.3
    - PCI-DSSv4-10.2
    - PCI-DSSv4-10.2.1
    - PCI-DSSv4-10.2.1.3
    - audit_rules_login_events_faillock
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Record Attempts to Alter Logon and Logout Events - faillock - Add watch
      rule for {{ var_accounts_passwords_pam_faillock_dir }} in /etc/audit/rules.d/
    ansible.builtin.lineinfile:
      path: '{{ all_files[0] }}'
      line: -w {{ var_accounts_passwords_pam_faillock_dir }} -p wa -k logins
      create: true
      mode: '0600'
    when:
    - '"audit" in ansible_facts.packages'
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - find_existing_watch_rules_d.matched is defined and find_existing_watch_rules_d.matched
      == 0
    tags:
    - DISA-STIG-OL09-00-000720
    - NIST-800-171-3.1.7
    - NIST-800-53-AC-6(9)
    - NIST-800-53-AU-12(c)
    - NIST-800-53-AU-2(d)
    - NIST-800-53-CM-6(a)
    - PCI-DSS-Req-10.2.3
    - PCI-DSSv4-10.2
    - PCI-DSSv4-10.2.1
    - PCI-DSSv4-10.2.1.3
    - audit_rules_login_events_faillock
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Record Attempts to Alter Logon and Logout Events - faillock - Check if watch
      rule for {{ var_accounts_passwords_pam_faillock_dir }} already exists in /etc/audit/audit.rules
    ansible.builtin.find:
      paths: /etc/audit/
      contains: ^\s*-w\s+{{ var_accounts_passwords_pam_faillock_dir }}\s+-p\s+wa(\s|$)+
      patterns: audit.rules
    register: find_existing_watch_audit_rules
    when:
    - '"audit" in ansible_facts.packages'
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-000720
    - NIST-800-171-3.1.7
    - NIST-800-53-AC-6(9)
    - NIST-800-53-AU-12(c)
    - NIST-800-53-AU-2(d)
    - NIST-800-53-CM-6(a)
    - PCI-DSS-Req-10.2.3
    - PCI-DSSv4-10.2
    - PCI-DSSv4-10.2.1
    - PCI-DSSv4-10.2.1.3
    - audit_rules_login_events_faillock
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Record Attempts to Alter Logon and Logout Events - faillock - Add watch
      rule for {{ var_accounts_passwords_pam_faillock_dir }} in /etc/audit/audit.rules
    ansible.builtin.lineinfile:
      line: -w {{ var_accounts_passwords_pam_faillock_dir }} -p wa -k logins
      state: present
      dest: /etc/audit/audit.rules
      create: true
      mode: '0600'
    when:
    - '"audit" in ansible_facts.packages'
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - find_existing_watch_audit_rules.matched is defined and find_existing_watch_audit_rules.matched
      == 0
    tags:
    - DISA-STIG-OL09-00-000720
    - NIST-800-171-3.1.7
    - NIST-800-53-AC-6(9)
    - NIST-800-53-AU-12(c)
    - NIST-800-53-AU-2(d)
    - NIST-800-53-CM-6(a)
    - PCI-DSS-Req-10.2.3
    - PCI-DSSv4-10.2
    - PCI-DSSv4-10.2.1
    - PCI-DSSv4-10.2.1.3
    - audit_rules_login_events_faillock
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Record Attempts to Alter Logon and Logout Events - lastlog - Check if watch
      rule for /var/log/lastlog already exists in /etc/audit/rules.d/
    ansible.builtin.find:
      paths: /etc/audit/rules.d
      contains: ^\s*-w\s+/var/log/lastlog\s+-p\s+wa(\s|$)+
      patterns: '*.rules'
    register: find_existing_watch_rules_d
    when:
    - '"audit" in ansible_facts.packages'
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-000700
    - NIST-800-171-3.1.7
    - NIST-800-53-AC-6(9)
    - NIST-800-53-AU-12(c)
    - NIST-800-53-AU-2(d)
    - NIST-800-53-CM-6(a)
    - PCI-DSS-Req-10.2.3
    - PCI-DSSv4-10.2
    - PCI-DSSv4-10.2.1
    - PCI-DSSv4-10.2.1.3
    - audit_rules_login_events_lastlog
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Record Attempts to Alter Logon and Logout Events - lastlog - Search /etc/audit/rules.d
      for other rules with specified key logins
    ansible.builtin.find:
      paths: /etc/audit/rules.d
      contains: ^.*(?:-F key=|-k\s+)logins$
      patterns: '*.rules'
    register: find_watch_key
    when:
    - '"audit" in ansible_facts.packages'
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - find_existing_watch_rules_d.matched is defined and find_existing_watch_rules_d.matched
      == 0
    tags:
    - DISA-STIG-OL09-00-000700
    - NIST-800-171-3.1.7
    - NIST-800-53-AC-6(9)
    - NIST-800-53-AU-12(c)
    - NIST-800-53-AU-2(d)
    - NIST-800-53-CM-6(a)
    - PCI-DSS-Req-10.2.3
    - PCI-DSSv4-10.2
    - PCI-DSSv4-10.2.1
    - PCI-DSSv4-10.2.1.3
    - audit_rules_login_events_lastlog
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Record Attempts to Alter Logon and Logout Events - lastlog - Use /etc/audit/rules.d/logins.rules
      as the recipient for the rule
    ansible.builtin.set_fact:
      all_files:
      - /etc/audit/rules.d/logins.rules
    when:
    - '"audit" in ansible_facts.packages'
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - find_watch_key.matched is defined and find_watch_key.matched == 0 and find_existing_watch_rules_d.matched
      is defined and find_existing_watch_rules_d.matched == 0
    tags:
    - DISA-STIG-OL09-00-000700
    - NIST-800-171-3.1.7
    - NIST-800-53-AC-6(9)
    - NIST-800-53-AU-12(c)
    - NIST-800-53-AU-2(d)
    - NIST-800-53-CM-6(a)
    - PCI-DSS-Req-10.2.3
    - PCI-DSSv4-10.2
    - PCI-DSSv4-10.2.1
    - PCI-DSSv4-10.2.1.3
    - audit_rules_login_events_lastlog
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Record Attempts to Alter Logon and Logout Events - lastlog - Use matched
      file as the recipient for the rule
    ansible.builtin.set_fact:
      all_files:
      - '{{ find_watch_key.files | map(attribute=''path'') | list | first }}'
    when:
    - '"audit" in ansible_facts.packages'
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - find_watch_key.matched is defined and find_watch_key.matched > 0 and find_existing_watch_rules_d.matched
      is defined and find_existing_watch_rules_d.matched == 0
    tags:
    - DISA-STIG-OL09-00-000700
    - NIST-800-171-3.1.7
    - NIST-800-53-AC-6(9)
    - NIST-800-53-AU-12(c)
    - NIST-800-53-AU-2(d)
    - NIST-800-53-CM-6(a)
    - PCI-DSS-Req-10.2.3
    - PCI-DSSv4-10.2
    - PCI-DSSv4-10.2.1
    - PCI-DSSv4-10.2.1.3
    - audit_rules_login_events_lastlog
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Record Attempts to Alter Logon and Logout Events - lastlog - Add watch rule
      for /var/log/lastlog in /etc/audit/rules.d/
    ansible.builtin.lineinfile:
      path: '{{ all_files[0] }}'
      line: -w /var/log/lastlog -p wa -k logins
      create: true
      mode: '0600'
    when:
    - '"audit" in ansible_facts.packages'
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - find_existing_watch_rules_d.matched is defined and find_existing_watch_rules_d.matched
      == 0
    tags:
    - DISA-STIG-OL09-00-000700
    - NIST-800-171-3.1.7
    - NIST-800-53-AC-6(9)
    - NIST-800-53-AU-12(c)
    - NIST-800-53-AU-2(d)
    - NIST-800-53-CM-6(a)
    - PCI-DSS-Req-10.2.3
    - PCI-DSSv4-10.2
    - PCI-DSSv4-10.2.1
    - PCI-DSSv4-10.2.1.3
    - audit_rules_login_events_lastlog
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Record Attempts to Alter Logon and Logout Events - lastlog - Check if watch
      rule for /var/log/lastlog already exists in /etc/audit/audit.rules
    ansible.builtin.find:
      paths: /etc/audit/
      contains: ^\s*-w\s+/var/log/lastlog\s+-p\s+wa(\s|$)+
      patterns: audit.rules
    register: find_existing_watch_audit_rules
    when:
    - '"audit" in ansible_facts.packages'
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-000700
    - NIST-800-171-3.1.7
    - NIST-800-53-AC-6(9)
    - NIST-800-53-AU-12(c)
    - NIST-800-53-AU-2(d)
    - NIST-800-53-CM-6(a)
    - PCI-DSS-Req-10.2.3
    - PCI-DSSv4-10.2
    - PCI-DSSv4-10.2.1
    - PCI-DSSv4-10.2.1.3
    - audit_rules_login_events_lastlog
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Record Attempts to Alter Logon and Logout Events - lastlog - Add watch rule
      for /var/log/lastlog in /etc/audit/audit.rules
    ansible.builtin.lineinfile:
      line: -w /var/log/lastlog -p wa -k logins
      state: present
      dest: /etc/audit/audit.rules
      create: true
      mode: '0600'
    when:
    - '"audit" in ansible_facts.packages'
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - find_existing_watch_audit_rules.matched is defined and find_existing_watch_audit_rules.matched
      == 0
    tags:
    - DISA-STIG-OL09-00-000700
    - NIST-800-171-3.1.7
    - NIST-800-53-AC-6(9)
    - NIST-800-53-AU-12(c)
    - NIST-800-53-AU-2(d)
    - NIST-800-53-CM-6(a)
    - PCI-DSS-Req-10.2.3
    - PCI-DSSv4-10.2
    - PCI-DSSv4-10.2.1
    - PCI-DSSv4-10.2.1.3
    - audit_rules_login_events_lastlog
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Record Attempts to Alter Logon and Logout Events - tallylog - Check if watch
      rule for /var/log/tallylog already exists in /etc/audit/rules.d/
    ansible.builtin.find:
      paths: /etc/audit/rules.d
      contains: ^\s*-w\s+/var/log/tallylog\s+-p\s+wa(\s|$)+
      patterns: '*.rules'
    register: find_existing_watch_rules_d
    when:
    - '"audit" in ansible_facts.packages'
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-000725
    - NIST-800-171-3.1.7
    - NIST-800-53-AC-6(9)
    - NIST-800-53-AU-12(c)
    - NIST-800-53-AU-2(d)
    - NIST-800-53-CM-6(a)
    - PCI-DSS-Req-10.2.3
    - PCI-DSSv4-10.2
    - PCI-DSSv4-10.2.1
    - PCI-DSSv4-10.2.1.3
    - audit_rules_login_events_tallylog
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Record Attempts to Alter Logon and Logout Events - tallylog - Search /etc/audit/rules.d
      for other rules with specified key logins
    ansible.builtin.find:
      paths: /etc/audit/rules.d
      contains: ^.*(?:-F key=|-k\s+)logins$
      patterns: '*.rules'
    register: find_watch_key
    when:
    - '"audit" in ansible_facts.packages'
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - find_existing_watch_rules_d.matched is defined and find_existing_watch_rules_d.matched
      == 0
    tags:
    - DISA-STIG-OL09-00-000725
    - NIST-800-171-3.1.7
    - NIST-800-53-AC-6(9)
    - NIST-800-53-AU-12(c)
    - NIST-800-53-AU-2(d)
    - NIST-800-53-CM-6(a)
    - PCI-DSS-Req-10.2.3
    - PCI-DSSv4-10.2
    - PCI-DSSv4-10.2.1
    - PCI-DSSv4-10.2.1.3
    - audit_rules_login_events_tallylog
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Record Attempts to Alter Logon and Logout Events - tallylog - Use /etc/audit/rules.d/logins.rules
      as the recipient for the rule
    ansible.builtin.set_fact:
      all_files:
      - /etc/audit/rules.d/logins.rules
    when:
    - '"audit" in ansible_facts.packages'
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - find_watch_key.matched is defined and find_watch_key.matched == 0 and find_existing_watch_rules_d.matched
      is defined and find_existing_watch_rules_d.matched == 0
    tags:
    - DISA-STIG-OL09-00-000725
    - NIST-800-171-3.1.7
    - NIST-800-53-AC-6(9)
    - NIST-800-53-AU-12(c)
    - NIST-800-53-AU-2(d)
    - NIST-800-53-CM-6(a)
    - PCI-DSS-Req-10.2.3
    - PCI-DSSv4-10.2
    - PCI-DSSv4-10.2.1
    - PCI-DSSv4-10.2.1.3
    - audit_rules_login_events_tallylog
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Record Attempts to Alter Logon and Logout Events - tallylog - Use matched
      file as the recipient for the rule
    ansible.builtin.set_fact:
      all_files:
      - '{{ find_watch_key.files | map(attribute=''path'') | list | first }}'
    when:
    - '"audit" in ansible_facts.packages'
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - find_watch_key.matched is defined and find_watch_key.matched > 0 and find_existing_watch_rules_d.matched
      is defined and find_existing_watch_rules_d.matched == 0
    tags:
    - DISA-STIG-OL09-00-000725
    - NIST-800-171-3.1.7
    - NIST-800-53-AC-6(9)
    - NIST-800-53-AU-12(c)
    - NIST-800-53-AU-2(d)
    - NIST-800-53-CM-6(a)
    - PCI-DSS-Req-10.2.3
    - PCI-DSSv4-10.2
    - PCI-DSSv4-10.2.1
    - PCI-DSSv4-10.2.1.3
    - audit_rules_login_events_tallylog
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Record Attempts to Alter Logon and Logout Events - tallylog - Add watch
      rule for /var/log/tallylog in /etc/audit/rules.d/
    ansible.builtin.lineinfile:
      path: '{{ all_files[0] }}'
      line: -w /var/log/tallylog -p wa -k logins
      create: true
      mode: '0600'
    when:
    - '"audit" in ansible_facts.packages'
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - find_existing_watch_rules_d.matched is defined and find_existing_watch_rules_d.matched
      == 0
    tags:
    - DISA-STIG-OL09-00-000725
    - NIST-800-171-3.1.7
    - NIST-800-53-AC-6(9)
    - NIST-800-53-AU-12(c)
    - NIST-800-53-AU-2(d)
    - NIST-800-53-CM-6(a)
    - PCI-DSS-Req-10.2.3
    - PCI-DSSv4-10.2
    - PCI-DSSv4-10.2.1
    - PCI-DSSv4-10.2.1.3
    - audit_rules_login_events_tallylog
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Record Attempts to Alter Logon and Logout Events - tallylog - Check if watch
      rule for /var/log/tallylog already exists in /etc/audit/audit.rules
    ansible.builtin.find:
      paths: /etc/audit/
      contains: ^\s*-w\s+/var/log/tallylog\s+-p\s+wa(\s|$)+
      patterns: audit.rules
    register: find_existing_watch_audit_rules
    when:
    - '"audit" in ansible_facts.packages'
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-000725
    - NIST-800-171-3.1.7
    - NIST-800-53-AC-6(9)
    - NIST-800-53-AU-12(c)
    - NIST-800-53-AU-2(d)
    - NIST-800-53-CM-6(a)
    - PCI-DSS-Req-10.2.3
    - PCI-DSSv4-10.2
    - PCI-DSSv4-10.2.1
    - PCI-DSSv4-10.2.1.3
    - audit_rules_login_events_tallylog
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Record Attempts to Alter Logon and Logout Events - tallylog - Add watch
      rule for /var/log/tallylog in /etc/audit/audit.rules
    ansible.builtin.lineinfile:
      line: -w /var/log/tallylog -p wa -k logins
      state: present
      dest: /etc/audit/audit.rules
      create: true
      mode: '0600'
    when:
    - '"audit" in ansible_facts.packages'
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - find_existing_watch_audit_rules.matched is defined and find_existing_watch_audit_rules.matched
      == 0
    tags:
    - DISA-STIG-OL09-00-000725
    - NIST-800-171-3.1.7
    - NIST-800-53-AC-6(9)
    - NIST-800-53-AU-12(c)
    - NIST-800-53-AU-2(d)
    - NIST-800-53-CM-6(a)
    - PCI-DSS-Req-10.2.3
    - PCI-DSSv4-10.2
    - PCI-DSSv4-10.2.1
    - PCI-DSSv4-10.2.1.3
    - audit_rules_login_events_tallylog
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Ensure auditd Collects Information on the Use of Privileged Commands - init
      - Perform remediation of Audit rules for /usr/sbin/init
    block:

    - name: Declare list of syscalls
      ansible.builtin.set_fact:
        syscalls: []
        syscall_grouping: []

    - name: Check existence of  in /etc/audit/rules.d/
      ansible.builtin.find:
        paths: /etc/audit/rules.d
        contains: -a always,exit(( -S |,)\w+)*(( -S |,){{ item }})+(( -S |,)\w+)*
          -F path=/usr/sbin/init -F perm=x -F auid>=1000 -F auid!=unset (-k\s+|-F\s+key=)\S+\s*$
        patterns: '*.rules'
      register: find_command
      loop: '{{ (syscall_grouping + syscalls) | unique }}'

    - name: Reset syscalls found per file
      ansible.builtin.set_fact:
        syscalls_per_file: {}
        found_paths_dict: {}

    - name: Declare syscalls found per file
      ansible.builtin.set_fact: syscalls_per_file="{{ syscalls_per_file | combine(
        {item.files[0].path :[item.item] + syscalls_per_file.get(item.files[0].path,
        []) } ) }}"
      loop: '{{ find_command.results | selectattr(''matched'') | list }}'

    - name: Declare files where syscalls were found
      ansible.builtin.set_fact: found_paths="{{ find_command.results | map(attribute='files')
        | flatten | map(attribute='path') | list }}"

    - name: Count occurrences of syscalls in paths
      ansible.builtin.set_fact: found_paths_dict="{{ found_paths_dict | combine({
        item:1+found_paths_dict.get(item, 0) }) }}"
      loop: '{{ find_command.results | map(attribute=''files'') | flatten | map(attribute=''path'')
        | list }}'

    - name: Get path with most syscalls
      ansible.builtin.set_fact: audit_file="{{ (found_paths_dict | dict2items() |
        sort(attribute='value') | last).key }}"
      when: found_paths | length >= 1

    - name: No file with syscall found, set path to /etc/audit/rules.d/privileged.rules
      ansible.builtin.set_fact: audit_file="/etc/audit/rules.d/privileged.rules"
      when: found_paths | length == 0

    - name: Declare found syscalls
      ansible.builtin.set_fact: syscalls_found="{{ find_command.results | selectattr('matched')
        | map(attribute='item') | list }}"

    - name: Declare missing syscalls
      ansible.builtin.set_fact: missing_syscalls="{{ syscalls | difference(syscalls_found)
        }}"

    - name: Replace the audit rule in {{ audit_file }}
      ansible.builtin.lineinfile:
        path: '{{ audit_file }}'
        regexp: (-a always,exit)(?=.*(?:(?:-S |,)(?:{{ syscalls_per_file[audit_file]
          | join("|") }}))\b)((?:( -S |,)\w+)+)( -F path=/usr/sbin/init -F perm=x
          -F auid>=1000 -F auid!=unset (?:-k |-F key=)\w+)
        line: \1\2\3{{ missing_syscalls | join("\3") }}\4
        backrefs: true
        state: present
        mode: g-rwx,o-rwx
      when: syscalls_found | length > 0 and missing_syscalls | length > 0

    - name: Add the audit rule to {{ audit_file }}
      ansible.builtin.lineinfile:
        path: '{{ audit_file }}'
        line: -a always,exit{{ syscalls | join(',') }} -F path=/usr/sbin/init -F perm=x
          -F auid>=1000 -F auid!=unset -F key=privileged
        create: true
        mode: g-rwx,o-rwx
        state: present
      when: syscalls_found | length == 0

    - name: Declare list of syscalls
      ansible.builtin.set_fact:
        syscalls: []
        syscall_grouping: []

    - name: Check existence of  in /etc/audit/audit.rules
      ansible.builtin.find:
        paths: /etc/audit
        contains: -a always,exit(( -S |,)\w+)*(( -S |,){{ item }})+(( -S |,)\w+)*
          -F path=/usr/sbin/init -F perm=x -F auid>=1000 -F auid!=unset (-k\s+|-F\s+key=)\S+\s*$
        patterns: audit.rules
      register: find_command
      loop: '{{ (syscall_grouping + syscalls) | unique }}'

    - name: Set path to /etc/audit/audit.rules
      ansible.builtin.set_fact: audit_file="/etc/audit/audit.rules"

    - name: Declare found syscalls
      ansible.builtin.set_fact: syscalls_found="{{ find_command.results | selectattr('matched')
        | map(attribute='item') | list }}"

    - name: Declare missing syscalls
      ansible.builtin.set_fact: missing_syscalls="{{ syscalls | difference(syscalls_found)
        }}"

    - name: Replace the audit rule in {{ audit_file }}
      ansible.builtin.lineinfile:
        path: '{{ audit_file }}'
        regexp: (-a always,exit)(?=.*(?:(?:-S |,)(?:{{ syscalls_found | join("|")
          }}))\b)((?:( -S |,)\w+)+)( -F path=/usr/sbin/init -F perm=x -F auid>=1000
          -F auid!=unset (?:-k |-F key=)\w+)
        line: \1\2\3{{ missing_syscalls | join("\3") }}\4
        backrefs: true
        state: present
        mode: g-rwx,o-rwx
      when: syscalls_found | length > 0 and missing_syscalls | length > 0

    - name: Add the audit rule to {{ audit_file }}
      ansible.builtin.lineinfile:
        path: '{{ audit_file }}'
        line: -a always,exit{{ syscalls | join(',') }} -F path=/usr/sbin/init -F perm=x
          -F auid>=1000 -F auid!=unset -F key=privileged
        create: true
        mode: g-rwx,o-rwx
        state: present
      when: syscalls_found | length == 0
    when:
    - '"audit" in ansible_facts.packages'
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-000730
    - NIST-800-53-AU-12(c)
    - audit_privileged_commands_init
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Ensure auditd Collects Information on the Use of Privileged Commands - poweroff
      - Perform remediation of Audit rules for /usr/sbin/poweroff
    block:

    - name: Declare list of syscalls
      ansible.builtin.set_fact:
        syscalls: []
        syscall_grouping: []

    - name: Check existence of  in /etc/audit/rules.d/
      ansible.builtin.find:
        paths: /etc/audit/rules.d
        contains: -a always,exit(( -S |,)\w+)*(( -S |,){{ item }})+(( -S |,)\w+)*
          -F path=/usr/sbin/poweroff -F perm=x -F auid>=1000 -F auid!=unset (-k\s+|-F\s+key=)\S+\s*$
        patterns: '*.rules'
      register: find_command
      loop: '{{ (syscall_grouping + syscalls) | unique }}'

    - name: Reset syscalls found per file
      ansible.builtin.set_fact:
        syscalls_per_file: {}
        found_paths_dict: {}

    - name: Declare syscalls found per file
      ansible.builtin.set_fact: syscalls_per_file="{{ syscalls_per_file | combine(
        {item.files[0].path :[item.item] + syscalls_per_file.get(item.files[0].path,
        []) } ) }}"
      loop: '{{ find_command.results | selectattr(''matched'') | list }}'

    - name: Declare files where syscalls were found
      ansible.builtin.set_fact: found_paths="{{ find_command.results | map(attribute='files')
        | flatten | map(attribute='path') | list }}"

    - name: Count occurrences of syscalls in paths
      ansible.builtin.set_fact: found_paths_dict="{{ found_paths_dict | combine({
        item:1+found_paths_dict.get(item, 0) }) }}"
      loop: '{{ find_command.results | map(attribute=''files'') | flatten | map(attribute=''path'')
        | list }}'

    - name: Get path with most syscalls
      ansible.builtin.set_fact: audit_file="{{ (found_paths_dict | dict2items() |
        sort(attribute='value') | last).key }}"
      when: found_paths | length >= 1

    - name: No file with syscall found, set path to /etc/audit/rules.d/privileged.rules
      ansible.builtin.set_fact: audit_file="/etc/audit/rules.d/privileged.rules"
      when: found_paths | length == 0

    - name: Declare found syscalls
      ansible.builtin.set_fact: syscalls_found="{{ find_command.results | selectattr('matched')
        | map(attribute='item') | list }}"

    - name: Declare missing syscalls
      ansible.builtin.set_fact: missing_syscalls="{{ syscalls | difference(syscalls_found)
        }}"

    - name: Replace the audit rule in {{ audit_file }}
      ansible.builtin.lineinfile:
        path: '{{ audit_file }}'
        regexp: (-a always,exit)(?=.*(?:(?:-S |,)(?:{{ syscalls_per_file[audit_file]
          | join("|") }}))\b)((?:( -S |,)\w+)+)( -F path=/usr/sbin/poweroff -F perm=x
          -F auid>=1000 -F auid!=unset (?:-k |-F key=)\w+)
        line: \1\2\3{{ missing_syscalls | join("\3") }}\4
        backrefs: true
        state: present
        mode: g-rwx,o-rwx
      when: syscalls_found | length > 0 and missing_syscalls | length > 0

    - name: Add the audit rule to {{ audit_file }}
      ansible.builtin.lineinfile:
        path: '{{ audit_file }}'
        line: -a always,exit{{ syscalls | join(',') }} -F path=/usr/sbin/poweroff
          -F perm=x -F auid>=1000 -F auid!=unset -F key=privileged
        create: true
        mode: g-rwx,o-rwx
        state: present
      when: syscalls_found | length == 0

    - name: Declare list of syscalls
      ansible.builtin.set_fact:
        syscalls: []
        syscall_grouping: []

    - name: Check existence of  in /etc/audit/audit.rules
      ansible.builtin.find:
        paths: /etc/audit
        contains: -a always,exit(( -S |,)\w+)*(( -S |,){{ item }})+(( -S |,)\w+)*
          -F path=/usr/sbin/poweroff -F perm=x -F auid>=1000 -F auid!=unset (-k\s+|-F\s+key=)\S+\s*$
        patterns: audit.rules
      register: find_command
      loop: '{{ (syscall_grouping + syscalls) | unique }}'

    - name: Set path to /etc/audit/audit.rules
      ansible.builtin.set_fact: audit_file="/etc/audit/audit.rules"

    - name: Declare found syscalls
      ansible.builtin.set_fact: syscalls_found="{{ find_command.results | selectattr('matched')
        | map(attribute='item') | list }}"

    - name: Declare missing syscalls
      ansible.builtin.set_fact: missing_syscalls="{{ syscalls | difference(syscalls_found)
        }}"

    - name: Replace the audit rule in {{ audit_file }}
      ansible.builtin.lineinfile:
        path: '{{ audit_file }}'
        regexp: (-a always,exit)(?=.*(?:(?:-S |,)(?:{{ syscalls_found | join("|")
          }}))\b)((?:( -S |,)\w+)+)( -F path=/usr/sbin/poweroff -F perm=x -F auid>=1000
          -F auid!=unset (?:-k |-F key=)\w+)
        line: \1\2\3{{ missing_syscalls | join("\3") }}\4
        backrefs: true
        state: present
        mode: g-rwx,o-rwx
      when: syscalls_found | length > 0 and missing_syscalls | length > 0

    - name: Add the audit rule to {{ audit_file }}
      ansible.builtin.lineinfile:
        path: '{{ audit_file }}'
        line: -a always,exit{{ syscalls | join(',') }} -F path=/usr/sbin/poweroff
          -F perm=x -F auid>=1000 -F auid!=unset -F key=privileged
        create: true
        mode: g-rwx,o-rwx
        state: present
      when: syscalls_found | length == 0
    when:
    - '"audit" in ansible_facts.packages'
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-000735
    - NIST-800-53-AU-12(c)
    - audit_privileged_commands_poweroff
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Ensure auditd Collects Information on the Use of Privileged Commands - reboot
      - Perform remediation of Audit rules for /usr/sbin/reboot
    block:

    - name: Declare list of syscalls
      ansible.builtin.set_fact:
        syscalls: []
        syscall_grouping: []

    - name: Check existence of  in /etc/audit/rules.d/
      ansible.builtin.find:
        paths: /etc/audit/rules.d
        contains: -a always,exit(( -S |,)\w+)*(( -S |,){{ item }})+(( -S |,)\w+)*
          -F path=/usr/sbin/reboot -F perm=x -F auid>=1000 -F auid!=unset (-k\s+|-F\s+key=)\S+\s*$
        patterns: '*.rules'
      register: find_command
      loop: '{{ (syscall_grouping + syscalls) | unique }}'

    - name: Reset syscalls found per file
      ansible.builtin.set_fact:
        syscalls_per_file: {}
        found_paths_dict: {}

    - name: Declare syscalls found per file
      ansible.builtin.set_fact: syscalls_per_file="{{ syscalls_per_file | combine(
        {item.files[0].path :[item.item] + syscalls_per_file.get(item.files[0].path,
        []) } ) }}"
      loop: '{{ find_command.results | selectattr(''matched'') | list }}'

    - name: Declare files where syscalls were found
      ansible.builtin.set_fact: found_paths="{{ find_command.results | map(attribute='files')
        | flatten | map(attribute='path') | list }}"

    - name: Count occurrences of syscalls in paths
      ansible.builtin.set_fact: found_paths_dict="{{ found_paths_dict | combine({
        item:1+found_paths_dict.get(item, 0) }) }}"
      loop: '{{ find_command.results | map(attribute=''files'') | flatten | map(attribute=''path'')
        | list }}'

    - name: Get path with most syscalls
      ansible.builtin.set_fact: audit_file="{{ (found_paths_dict | dict2items() |
        sort(attribute='value') | last).key }}"
      when: found_paths | length >= 1

    - name: No file with syscall found, set path to /etc/audit/rules.d/privileged.rules
      ansible.builtin.set_fact: audit_file="/etc/audit/rules.d/privileged.rules"
      when: found_paths | length == 0

    - name: Declare found syscalls
      ansible.builtin.set_fact: syscalls_found="{{ find_command.results | selectattr('matched')
        | map(attribute='item') | list }}"

    - name: Declare missing syscalls
      ansible.builtin.set_fact: missing_syscalls="{{ syscalls | difference(syscalls_found)
        }}"

    - name: Replace the audit rule in {{ audit_file }}
      ansible.builtin.lineinfile:
        path: '{{ audit_file }}'
        regexp: (-a always,exit)(?=.*(?:(?:-S |,)(?:{{ syscalls_per_file[audit_file]
          | join("|") }}))\b)((?:( -S |,)\w+)+)( -F path=/usr/sbin/reboot -F perm=x
          -F auid>=1000 -F auid!=unset (?:-k |-F key=)\w+)
        line: \1\2\3{{ missing_syscalls | join("\3") }}\4
        backrefs: true
        state: present
        mode: g-rwx,o-rwx
      when: syscalls_found | length > 0 and missing_syscalls | length > 0

    - name: Add the audit rule to {{ audit_file }}
      ansible.builtin.lineinfile:
        path: '{{ audit_file }}'
        line: -a always,exit{{ syscalls | join(',') }} -F path=/usr/sbin/reboot -F
          perm=x -F auid>=1000 -F auid!=unset -F key=privileged
        create: true
        mode: g-rwx,o-rwx
        state: present
      when: syscalls_found | length == 0

    - name: Declare list of syscalls
      ansible.builtin.set_fact:
        syscalls: []
        syscall_grouping: []

    - name: Check existence of  in /etc/audit/audit.rules
      ansible.builtin.find:
        paths: /etc/audit
        contains: -a always,exit(( -S |,)\w+)*(( -S |,){{ item }})+(( -S |,)\w+)*
          -F path=/usr/sbin/reboot -F perm=x -F auid>=1000 -F auid!=unset (-k\s+|-F\s+key=)\S+\s*$
        patterns: audit.rules
      register: find_command
      loop: '{{ (syscall_grouping + syscalls) | unique }}'

    - name: Set path to /etc/audit/audit.rules
      ansible.builtin.set_fact: audit_file="/etc/audit/audit.rules"

    - name: Declare found syscalls
      ansible.builtin.set_fact: syscalls_found="{{ find_command.results | selectattr('matched')
        | map(attribute='item') | list }}"

    - name: Declare missing syscalls
      ansible.builtin.set_fact: missing_syscalls="{{ syscalls | difference(syscalls_found)
        }}"

    - name: Replace the audit rule in {{ audit_file }}
      ansible.builtin.lineinfile:
        path: '{{ audit_file }}'
        regexp: (-a always,exit)(?=.*(?:(?:-S |,)(?:{{ syscalls_found | join("|")
          }}))\b)((?:( -S |,)\w+)+)( -F path=/usr/sbin/reboot -F perm=x -F auid>=1000
          -F auid!=unset (?:-k |-F key=)\w+)
        line: \1\2\3{{ missing_syscalls | join("\3") }}\4
        backrefs: true
        state: present
        mode: g-rwx,o-rwx
      when: syscalls_found | length > 0 and missing_syscalls | length > 0

    - name: Add the audit rule to {{ audit_file }}
      ansible.builtin.lineinfile:
        path: '{{ audit_file }}'
        line: -a always,exit{{ syscalls | join(',') }} -F path=/usr/sbin/reboot -F
          perm=x -F auid>=1000 -F auid!=unset -F key=privileged
        create: true
        mode: g-rwx,o-rwx
        state: present
      when: syscalls_found | length == 0
    when:
    - '"audit" in ansible_facts.packages'
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-000740
    - NIST-800-53-AU-12(c)
    - audit_privileged_commands_reboot
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Ensure auditd Collects Information on the Use of Privileged Commands - shutdown
      - Perform remediation of Audit rules for /usr/sbin/shutdown
    block:

    - name: Declare list of syscalls
      ansible.builtin.set_fact:
        syscalls: []
        syscall_grouping: []

    - name: Check existence of  in /etc/audit/rules.d/
      ansible.builtin.find:
        paths: /etc/audit/rules.d
        contains: -a always,exit(( -S |,)\w+)*(( -S |,){{ item }})+(( -S |,)\w+)*
          -F path=/usr/sbin/shutdown -F perm=x -F auid>=1000 -F auid!=unset (-k\s+|-F\s+key=)\S+\s*$
        patterns: '*.rules'
      register: find_command
      loop: '{{ (syscall_grouping + syscalls) | unique }}'

    - name: Reset syscalls found per file
      ansible.builtin.set_fact:
        syscalls_per_file: {}
        found_paths_dict: {}

    - name: Declare syscalls found per file
      ansible.builtin.set_fact: syscalls_per_file="{{ syscalls_per_file | combine(
        {item.files[0].path :[item.item] + syscalls_per_file.get(item.files[0].path,
        []) } ) }}"
      loop: '{{ find_command.results | selectattr(''matched'') | list }}'

    - name: Declare files where syscalls were found
      ansible.builtin.set_fact: found_paths="{{ find_command.results | map(attribute='files')
        | flatten | map(attribute='path') | list }}"

    - name: Count occurrences of syscalls in paths
      ansible.builtin.set_fact: found_paths_dict="{{ found_paths_dict | combine({
        item:1+found_paths_dict.get(item, 0) }) }}"
      loop: '{{ find_command.results | map(attribute=''files'') | flatten | map(attribute=''path'')
        | list }}'

    - name: Get path with most syscalls
      ansible.builtin.set_fact: audit_file="{{ (found_paths_dict | dict2items() |
        sort(attribute='value') | last).key }}"
      when: found_paths | length >= 1

    - name: No file with syscall found, set path to /etc/audit/rules.d/privileged.rules
      ansible.builtin.set_fact: audit_file="/etc/audit/rules.d/privileged.rules"
      when: found_paths | length == 0

    - name: Declare found syscalls
      ansible.builtin.set_fact: syscalls_found="{{ find_command.results | selectattr('matched')
        | map(attribute='item') | list }}"

    - name: Declare missing syscalls
      ansible.builtin.set_fact: missing_syscalls="{{ syscalls | difference(syscalls_found)
        }}"

    - name: Replace the audit rule in {{ audit_file }}
      ansible.builtin.lineinfile:
        path: '{{ audit_file }}'
        regexp: (-a always,exit)(?=.*(?:(?:-S |,)(?:{{ syscalls_per_file[audit_file]
          | join("|") }}))\b)((?:( -S |,)\w+)+)( -F path=/usr/sbin/shutdown -F perm=x
          -F auid>=1000 -F auid!=unset (?:-k |-F key=)\w+)
        line: \1\2\3{{ missing_syscalls | join("\3") }}\4
        backrefs: true
        state: present
        mode: g-rwx,o-rwx
      when: syscalls_found | length > 0 and missing_syscalls | length > 0

    - name: Add the audit rule to {{ audit_file }}
      ansible.builtin.lineinfile:
        path: '{{ audit_file }}'
        line: -a always,exit{{ syscalls | join(',') }} -F path=/usr/sbin/shutdown
          -F perm=x -F auid>=1000 -F auid!=unset -F key=privileged
        create: true
        mode: g-rwx,o-rwx
        state: present
      when: syscalls_found | length == 0

    - name: Declare list of syscalls
      ansible.builtin.set_fact:
        syscalls: []
        syscall_grouping: []

    - name: Check existence of  in /etc/audit/audit.rules
      ansible.builtin.find:
        paths: /etc/audit
        contains: -a always,exit(( -S |,)\w+)*(( -S |,){{ item }})+(( -S |,)\w+)*
          -F path=/usr/sbin/shutdown -F perm=x -F auid>=1000 -F auid!=unset (-k\s+|-F\s+key=)\S+\s*$
        patterns: audit.rules
      register: find_command
      loop: '{{ (syscall_grouping + syscalls) | unique }}'

    - name: Set path to /etc/audit/audit.rules
      ansible.builtin.set_fact: audit_file="/etc/audit/audit.rules"

    - name: Declare found syscalls
      ansible.builtin.set_fact: syscalls_found="{{ find_command.results | selectattr('matched')
        | map(attribute='item') | list }}"

    - name: Declare missing syscalls
      ansible.builtin.set_fact: missing_syscalls="{{ syscalls | difference(syscalls_found)
        }}"

    - name: Replace the audit rule in {{ audit_file }}
      ansible.builtin.lineinfile:
        path: '{{ audit_file }}'
        regexp: (-a always,exit)(?=.*(?:(?:-S |,)(?:{{ syscalls_found | join("|")
          }}))\b)((?:( -S |,)\w+)+)( -F path=/usr/sbin/shutdown -F perm=x -F auid>=1000
          -F auid!=unset (?:-k |-F key=)\w+)
        line: \1\2\3{{ missing_syscalls | join("\3") }}\4
        backrefs: true
        state: present
        mode: g-rwx,o-rwx
      when: syscalls_found | length > 0 and missing_syscalls | length > 0

    - name: Add the audit rule to {{ audit_file }}
      ansible.builtin.lineinfile:
        path: '{{ audit_file }}'
        line: -a always,exit{{ syscalls | join(',') }} -F path=/usr/sbin/shutdown
          -F perm=x -F auid>=1000 -F auid!=unset -F key=privileged
        create: true
        mode: g-rwx,o-rwx
        state: present
      when: syscalls_found | length == 0
    when:
    - '"audit" in ansible_facts.packages'
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-000745
    - NIST-800-53-AU-12(c)
    - audit_privileged_commands_shutdown
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Ensure auditd Collects Information on the Use of Privileged Commands - chage
      - Perform remediation of Audit rules for /usr/bin/chage
    block:

    - name: Declare list of syscalls
      ansible.builtin.set_fact:
        syscalls: []
        syscall_grouping: []

    - name: Check existence of  in /etc/audit/rules.d/
      ansible.builtin.find:
        paths: /etc/audit/rules.d
        contains: -a always,exit(( -S |,)\w+)*(( -S |,){{ item }})+(( -S |,)\w+)*
          -F path=/usr/bin/chage -F perm=x -F auid>=1000 -F auid!=unset (-k\s+|-F\s+key=)\S+\s*$
        patterns: '*.rules'
      register: find_command
      loop: '{{ (syscall_grouping + syscalls) | unique }}'

    - name: Reset syscalls found per file
      ansible.builtin.set_fact:
        syscalls_per_file: {}
        found_paths_dict: {}

    - name: Declare syscalls found per file
      ansible.builtin.set_fact: syscalls_per_file="{{ syscalls_per_file | combine(
        {item.files[0].path :[item.item] + syscalls_per_file.get(item.files[0].path,
        []) } ) }}"
      loop: '{{ find_command.results | selectattr(''matched'') | list }}'

    - name: Declare files where syscalls were found
      ansible.builtin.set_fact: found_paths="{{ find_command.results | map(attribute='files')
        | flatten | map(attribute='path') | list }}"

    - name: Count occurrences of syscalls in paths
      ansible.builtin.set_fact: found_paths_dict="{{ found_paths_dict | combine({
        item:1+found_paths_dict.get(item, 0) }) }}"
      loop: '{{ find_command.results | map(attribute=''files'') | flatten | map(attribute=''path'')
        | list }}'

    - name: Get path with most syscalls
      ansible.builtin.set_fact: audit_file="{{ (found_paths_dict | dict2items() |
        sort(attribute='value') | last).key }}"
      when: found_paths | length >= 1

    - name: No file with syscall found, set path to /etc/audit/rules.d/privileged.rules
      ansible.builtin.set_fact: audit_file="/etc/audit/rules.d/privileged.rules"
      when: found_paths | length == 0

    - name: Declare found syscalls
      ansible.builtin.set_fact: syscalls_found="{{ find_command.results | selectattr('matched')
        | map(attribute='item') | list }}"

    - name: Declare missing syscalls
      ansible.builtin.set_fact: missing_syscalls="{{ syscalls | difference(syscalls_found)
        }}"

    - name: Replace the audit rule in {{ audit_file }}
      ansible.builtin.lineinfile:
        path: '{{ audit_file }}'
        regexp: (-a always,exit)(?=.*(?:(?:-S |,)(?:{{ syscalls_per_file[audit_file]
          | join("|") }}))\b)((?:( -S |,)\w+)+)( -F path=/usr/bin/chage -F perm=x
          -F auid>=1000 -F auid!=unset (?:-k |-F key=)\w+)
        line: \1\2\3{{ missing_syscalls | join("\3") }}\4
        backrefs: true
        state: present
        mode: g-rwx,o-rwx
      when: syscalls_found | length > 0 and missing_syscalls | length > 0

    - name: Add the audit rule to {{ audit_file }}
      ansible.builtin.lineinfile:
        path: '{{ audit_file }}'
        line: -a always,exit{{ syscalls | join(',') }} -F path=/usr/bin/chage -F perm=x
          -F auid>=1000 -F auid!=unset -F key=privileged
        create: true
        mode: g-rwx,o-rwx
        state: present
      when: syscalls_found | length == 0

    - name: Declare list of syscalls
      ansible.builtin.set_fact:
        syscalls: []
        syscall_grouping: []

    - name: Check existence of  in /etc/audit/audit.rules
      ansible.builtin.find:
        paths: /etc/audit
        contains: -a always,exit(( -S |,)\w+)*(( -S |,){{ item }})+(( -S |,)\w+)*
          -F path=/usr/bin/chage -F perm=x -F auid>=1000 -F auid!=unset (-k\s+|-F\s+key=)\S+\s*$
        patterns: audit.rules
      register: find_command
      loop: '{{ (syscall_grouping + syscalls) | unique }}'

    - name: Set path to /etc/audit/audit.rules
      ansible.builtin.set_fact: audit_file="/etc/audit/audit.rules"

    - name: Declare found syscalls
      ansible.builtin.set_fact: syscalls_found="{{ find_command.results | selectattr('matched')
        | map(attribute='item') | list }}"

    - name: Declare missing syscalls
      ansible.builtin.set_fact: missing_syscalls="{{ syscalls | difference(syscalls_found)
        }}"

    - name: Replace the audit rule in {{ audit_file }}
      ansible.builtin.lineinfile:
        path: '{{ audit_file }}'
        regexp: (-a always,exit)(?=.*(?:(?:-S |,)(?:{{ syscalls_found | join("|")
          }}))\b)((?:( -S |,)\w+)+)( -F path=/usr/bin/chage -F perm=x -F auid>=1000
          -F auid!=unset (?:-k |-F key=)\w+)
        line: \1\2\3{{ missing_syscalls | join("\3") }}\4
        backrefs: true
        state: present
        mode: g-rwx,o-rwx
      when: syscalls_found | length > 0 and missing_syscalls | length > 0

    - name: Add the audit rule to {{ audit_file }}
      ansible.builtin.lineinfile:
        path: '{{ audit_file }}'
        line: -a always,exit{{ syscalls | join(',') }} -F path=/usr/bin/chage -F perm=x
          -F auid>=1000 -F auid!=unset -F key=privileged
        create: true
        mode: g-rwx,o-rwx
        state: present
      when: syscalls_found | length == 0
    when:
    - '"audit" in ansible_facts.packages'
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-000550
    - NIST-800-171-3.1.7
    - NIST-800-53-AC-2(4)
    - NIST-800-53-AC-6(9)
    - NIST-800-53-AU-12(c)
    - NIST-800-53-AU-2(d)
    - NIST-800-53-CM-6(a)
    - audit_rules_privileged_commands_chage
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Ensure auditd Collects Information on the Use of Privileged Commands - chsh
      - Perform remediation of Audit rules for /usr/bin/chsh
    block:

    - name: Declare list of syscalls
      ansible.builtin.set_fact:
        syscalls: []
        syscall_grouping: []

    - name: Check existence of  in /etc/audit/rules.d/
      ansible.builtin.find:
        paths: /etc/audit/rules.d
        contains: -a always,exit(( -S |,)\w+)*(( -S |,){{ item }})+(( -S |,)\w+)*
          -F path=/usr/bin/chsh -F perm=x -F auid>=1000 -F auid!=unset (-k\s+|-F\s+key=)\S+\s*$
        patterns: '*.rules'
      register: find_command
      loop: '{{ (syscall_grouping + syscalls) | unique }}'

    - name: Reset syscalls found per file
      ansible.builtin.set_fact:
        syscalls_per_file: {}
        found_paths_dict: {}

    - name: Declare syscalls found per file
      ansible.builtin.set_fact: syscalls_per_file="{{ syscalls_per_file | combine(
        {item.files[0].path :[item.item] + syscalls_per_file.get(item.files[0].path,
        []) } ) }}"
      loop: '{{ find_command.results | selectattr(''matched'') | list }}'

    - name: Declare files where syscalls were found
      ansible.builtin.set_fact: found_paths="{{ find_command.results | map(attribute='files')
        | flatten | map(attribute='path') | list }}"

    - name: Count occurrences of syscalls in paths
      ansible.builtin.set_fact: found_paths_dict="{{ found_paths_dict | combine({
        item:1+found_paths_dict.get(item, 0) }) }}"
      loop: '{{ find_command.results | map(attribute=''files'') | flatten | map(attribute=''path'')
        | list }}'

    - name: Get path with most syscalls
      ansible.builtin.set_fact: audit_file="{{ (found_paths_dict | dict2items() |
        sort(attribute='value') | last).key }}"
      when: found_paths | length >= 1

    - name: No file with syscall found, set path to /etc/audit/rules.d/privileged.rules
      ansible.builtin.set_fact: audit_file="/etc/audit/rules.d/privileged.rules"
      when: found_paths | length == 0

    - name: Declare found syscalls
      ansible.builtin.set_fact: syscalls_found="{{ find_command.results | selectattr('matched')
        | map(attribute='item') | list }}"

    - name: Declare missing syscalls
      ansible.builtin.set_fact: missing_syscalls="{{ syscalls | difference(syscalls_found)
        }}"

    - name: Replace the audit rule in {{ audit_file }}
      ansible.builtin.lineinfile:
        path: '{{ audit_file }}'
        regexp: (-a always,exit)(?=.*(?:(?:-S |,)(?:{{ syscalls_per_file[audit_file]
          | join("|") }}))\b)((?:( -S |,)\w+)+)( -F path=/usr/bin/chsh -F perm=x -F
          auid>=1000 -F auid!=unset (?:-k |-F key=)\w+)
        line: \1\2\3{{ missing_syscalls | join("\3") }}\4
        backrefs: true
        state: present
        mode: g-rwx,o-rwx
      when: syscalls_found | length > 0 and missing_syscalls | length > 0

    - name: Add the audit rule to {{ audit_file }}
      ansible.builtin.lineinfile:
        path: '{{ audit_file }}'
        line: -a always,exit{{ syscalls | join(',') }} -F path=/usr/bin/chsh -F perm=x
          -F auid>=1000 -F auid!=unset -F key=privileged
        create: true
        mode: g-rwx,o-rwx
        state: present
      when: syscalls_found | length == 0

    - name: Declare list of syscalls
      ansible.builtin.set_fact:
        syscalls: []
        syscall_grouping: []

    - name: Check existence of  in /etc/audit/audit.rules
      ansible.builtin.find:
        paths: /etc/audit
        contains: -a always,exit(( -S |,)\w+)*(( -S |,){{ item }})+(( -S |,)\w+)*
          -F path=/usr/bin/chsh -F perm=x -F auid>=1000 -F auid!=unset (-k\s+|-F\s+key=)\S+\s*$
        patterns: audit.rules
      register: find_command
      loop: '{{ (syscall_grouping + syscalls) | unique }}'

    - name: Set path to /etc/audit/audit.rules
      ansible.builtin.set_fact: audit_file="/etc/audit/audit.rules"

    - name: Declare found syscalls
      ansible.builtin.set_fact: syscalls_found="{{ find_command.results | selectattr('matched')
        | map(attribute='item') | list }}"

    - name: Declare missing syscalls
      ansible.builtin.set_fact: missing_syscalls="{{ syscalls | difference(syscalls_found)
        }}"

    - name: Replace the audit rule in {{ audit_file }}
      ansible.builtin.lineinfile:
        path: '{{ audit_file }}'
        regexp: (-a always,exit)(?=.*(?:(?:-S |,)(?:{{ syscalls_found | join("|")
          }}))\b)((?:( -S |,)\w+)+)( -F path=/usr/bin/chsh -F perm=x -F auid>=1000
          -F auid!=unset (?:-k |-F key=)\w+)
        line: \1\2\3{{ missing_syscalls | join("\3") }}\4
        backrefs: true
        state: present
        mode: g-rwx,o-rwx
      when: syscalls_found | length > 0 and missing_syscalls | length > 0

    - name: Add the audit rule to {{ audit_file }}
      ansible.builtin.lineinfile:
        path: '{{ audit_file }}'
        line: -a always,exit{{ syscalls | join(',') }} -F path=/usr/bin/chsh -F perm=x
          -F auid>=1000 -F auid!=unset -F key=privileged
        create: true
        mode: g-rwx,o-rwx
        state: present
      when: syscalls_found | length == 0
    when:
    - '"audit" in ansible_facts.packages'
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-000565
    - NIST-800-171-3.1.7
    - NIST-800-53-AC-2(4)
    - NIST-800-53-AC-6(9)
    - NIST-800-53-AU-12(c)
    - NIST-800-53-AU-2(d)
    - NIST-800-53-CM-6(a)
    - audit_rules_privileged_commands_chsh
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Ensure auditd Collects Information on the Use of Privileged Commands - crontab
      - Perform remediation of Audit rules for /usr/bin/crontab
    block:

    - name: Declare list of syscalls
      ansible.builtin.set_fact:
        syscalls: []
        syscall_grouping: []

    - name: Check existence of  in /etc/audit/rules.d/
      ansible.builtin.find:
        paths: /etc/audit/rules.d
        contains: -a always,exit(( -S |,)\w+)*(( -S |,){{ item }})+(( -S |,)\w+)*
          -F path=/usr/bin/crontab -F perm=x -F auid>=1000 -F auid!=unset (-k\s+|-F\s+key=)\S+\s*$
        patterns: '*.rules'
      register: find_command
      loop: '{{ (syscall_grouping + syscalls) | unique }}'

    - name: Reset syscalls found per file
      ansible.builtin.set_fact:
        syscalls_per_file: {}
        found_paths_dict: {}

    - name: Declare syscalls found per file
      ansible.builtin.set_fact: syscalls_per_file="{{ syscalls_per_file | combine(
        {item.files[0].path :[item.item] + syscalls_per_file.get(item.files[0].path,
        []) } ) }}"
      loop: '{{ find_command.results | selectattr(''matched'') | list }}'

    - name: Declare files where syscalls were found
      ansible.builtin.set_fact: found_paths="{{ find_command.results | map(attribute='files')
        | flatten | map(attribute='path') | list }}"

    - name: Count occurrences of syscalls in paths
      ansible.builtin.set_fact: found_paths_dict="{{ found_paths_dict | combine({
        item:1+found_paths_dict.get(item, 0) }) }}"
      loop: '{{ find_command.results | map(attribute=''files'') | flatten | map(attribute=''path'')
        | list }}'

    - name: Get path with most syscalls
      ansible.builtin.set_fact: audit_file="{{ (found_paths_dict | dict2items() |
        sort(attribute='value') | last).key }}"
      when: found_paths | length >= 1

    - name: No file with syscall found, set path to /etc/audit/rules.d/privileged.rules
      ansible.builtin.set_fact: audit_file="/etc/audit/rules.d/privileged.rules"
      when: found_paths | length == 0

    - name: Declare found syscalls
      ansible.builtin.set_fact: syscalls_found="{{ find_command.results | selectattr('matched')
        | map(attribute='item') | list }}"

    - name: Declare missing syscalls
      ansible.builtin.set_fact: missing_syscalls="{{ syscalls | difference(syscalls_found)
        }}"

    - name: Replace the audit rule in {{ audit_file }}
      ansible.builtin.lineinfile:
        path: '{{ audit_file }}'
        regexp: (-a always,exit)(?=.*(?:(?:-S |,)(?:{{ syscalls_per_file[audit_file]
          | join("|") }}))\b)((?:( -S |,)\w+)+)( -F path=/usr/bin/crontab -F perm=x
          -F auid>=1000 -F auid!=unset (?:-k |-F key=)\w+)
        line: \1\2\3{{ missing_syscalls | join("\3") }}\4
        backrefs: true
        state: present
        mode: g-rwx,o-rwx
      when: syscalls_found | length > 0 and missing_syscalls | length > 0

    - name: Add the audit rule to {{ audit_file }}
      ansible.builtin.lineinfile:
        path: '{{ audit_file }}'
        line: -a always,exit{{ syscalls | join(',') }} -F path=/usr/bin/crontab -F
          perm=x -F auid>=1000 -F auid!=unset -F key=privileged
        create: true
        mode: g-rwx,o-rwx
        state: present
      when: syscalls_found | length == 0

    - name: Declare list of syscalls
      ansible.builtin.set_fact:
        syscalls: []
        syscall_grouping: []

    - name: Check existence of  in /etc/audit/audit.rules
      ansible.builtin.find:
        paths: /etc/audit
        contains: -a always,exit(( -S |,)\w+)*(( -S |,){{ item }})+(( -S |,)\w+)*
          -F path=/usr/bin/crontab -F perm=x -F auid>=1000 -F auid!=unset (-k\s+|-F\s+key=)\S+\s*$
        patterns: audit.rules
      register: find_command
      loop: '{{ (syscall_grouping + syscalls) | unique }}'

    - name: Set path to /etc/audit/audit.rules
      ansible.builtin.set_fact: audit_file="/etc/audit/audit.rules"

    - name: Declare found syscalls
      ansible.builtin.set_fact: syscalls_found="{{ find_command.results | selectattr('matched')
        | map(attribute='item') | list }}"

    - name: Declare missing syscalls
      ansible.builtin.set_fact: missing_syscalls="{{ syscalls | difference(syscalls_found)
        }}"

    - name: Replace the audit rule in {{ audit_file }}
      ansible.builtin.lineinfile:
        path: '{{ audit_file }}'
        regexp: (-a always,exit)(?=.*(?:(?:-S |,)(?:{{ syscalls_found | join("|")
          }}))\b)((?:( -S |,)\w+)+)( -F path=/usr/bin/crontab -F perm=x -F auid>=1000
          -F auid!=unset (?:-k |-F key=)\w+)
        line: \1\2\3{{ missing_syscalls | join("\3") }}\4
        backrefs: true
        state: present
        mode: g-rwx,o-rwx
      when: syscalls_found | length > 0 and missing_syscalls | length > 0

    - name: Add the audit rule to {{ audit_file }}
      ansible.builtin.lineinfile:
        path: '{{ audit_file }}'
        line: -a always,exit{{ syscalls | join(',') }} -F path=/usr/bin/crontab -F
          perm=x -F auid>=1000 -F auid!=unset -F key=privileged
        create: true
        mode: g-rwx,o-rwx
        state: present
      when: syscalls_found | length == 0
    when:
    - '"audit" in ansible_facts.packages'
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-000570
    - NIST-800-171-3.1.7
    - NIST-800-53-AC-6(9)
    - NIST-800-53-AU-12(c)
    - NIST-800-53-AU-2(d)
    - NIST-800-53-CM-6(a)
    - audit_rules_privileged_commands_crontab
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Ensure auditd Collects Information on the Use of Privileged Commands - gpasswd
      - Perform remediation of Audit rules for /usr/bin/gpasswd
    block:

    - name: Declare list of syscalls
      ansible.builtin.set_fact:
        syscalls: []
        syscall_grouping: []

    - name: Check existence of  in /etc/audit/rules.d/
      ansible.builtin.find:
        paths: /etc/audit/rules.d
        contains: -a always,exit(( -S |,)\w+)*(( -S |,){{ item }})+(( -S |,)\w+)*
          -F path=/usr/bin/gpasswd -F perm=x -F auid>=1000 -F auid!=unset (-k\s+|-F\s+key=)\S+\s*$
        patterns: '*.rules'
      register: find_command
      loop: '{{ (syscall_grouping + syscalls) | unique }}'

    - name: Reset syscalls found per file
      ansible.builtin.set_fact:
        syscalls_per_file: {}
        found_paths_dict: {}

    - name: Declare syscalls found per file
      ansible.builtin.set_fact: syscalls_per_file="{{ syscalls_per_file | combine(
        {item.files[0].path :[item.item] + syscalls_per_file.get(item.files[0].path,
        []) } ) }}"
      loop: '{{ find_command.results | selectattr(''matched'') | list }}'

    - name: Declare files where syscalls were found
      ansible.builtin.set_fact: found_paths="{{ find_command.results | map(attribute='files')
        | flatten | map(attribute='path') | list }}"

    - name: Count occurrences of syscalls in paths
      ansible.builtin.set_fact: found_paths_dict="{{ found_paths_dict | combine({
        item:1+found_paths_dict.get(item, 0) }) }}"
      loop: '{{ find_command.results | map(attribute=''files'') | flatten | map(attribute=''path'')
        | list }}'

    - name: Get path with most syscalls
      ansible.builtin.set_fact: audit_file="{{ (found_paths_dict | dict2items() |
        sort(attribute='value') | last).key }}"
      when: found_paths | length >= 1

    - name: No file with syscall found, set path to /etc/audit/rules.d/privileged.rules
      ansible.builtin.set_fact: audit_file="/etc/audit/rules.d/privileged.rules"
      when: found_paths | length == 0

    - name: Declare found syscalls
      ansible.builtin.set_fact: syscalls_found="{{ find_command.results | selectattr('matched')
        | map(attribute='item') | list }}"

    - name: Declare missing syscalls
      ansible.builtin.set_fact: missing_syscalls="{{ syscalls | difference(syscalls_found)
        }}"

    - name: Replace the audit rule in {{ audit_file }}
      ansible.builtin.lineinfile:
        path: '{{ audit_file }}'
        regexp: (-a always,exit)(?=.*(?:(?:-S |,)(?:{{ syscalls_per_file[audit_file]
          | join("|") }}))\b)((?:( -S |,)\w+)+)( -F path=/usr/bin/gpasswd -F perm=x
          -F auid>=1000 -F auid!=unset (?:-k |-F key=)\w+)
        line: \1\2\3{{ missing_syscalls | join("\3") }}\4
        backrefs: true
        state: present
        mode: g-rwx,o-rwx
      when: syscalls_found | length > 0 and missing_syscalls | length > 0

    - name: Add the audit rule to {{ audit_file }}
      ansible.builtin.lineinfile:
        path: '{{ audit_file }}'
        line: -a always,exit{{ syscalls | join(',') }} -F path=/usr/bin/gpasswd -F
          perm=x -F auid>=1000 -F auid!=unset -F key=privileged
        create: true
        mode: g-rwx,o-rwx
        state: present
      when: syscalls_found | length == 0

    - name: Declare list of syscalls
      ansible.builtin.set_fact:
        syscalls: []
        syscall_grouping: []

    - name: Check existence of  in /etc/audit/audit.rules
      ansible.builtin.find:
        paths: /etc/audit
        contains: -a always,exit(( -S |,)\w+)*(( -S |,){{ item }})+(( -S |,)\w+)*
          -F path=/usr/bin/gpasswd -F perm=x -F auid>=1000 -F auid!=unset (-k\s+|-F\s+key=)\S+\s*$
        patterns: audit.rules
      register: find_command
      loop: '{{ (syscall_grouping + syscalls) | unique }}'

    - name: Set path to /etc/audit/audit.rules
      ansible.builtin.set_fact: audit_file="/etc/audit/audit.rules"

    - name: Declare found syscalls
      ansible.builtin.set_fact: syscalls_found="{{ find_command.results | selectattr('matched')
        | map(attribute='item') | list }}"

    - name: Declare missing syscalls
      ansible.builtin.set_fact: missing_syscalls="{{ syscalls | difference(syscalls_found)
        }}"

    - name: Replace the audit rule in {{ audit_file }}
      ansible.builtin.lineinfile:
        path: '{{ audit_file }}'
        regexp: (-a always,exit)(?=.*(?:(?:-S |,)(?:{{ syscalls_found | join("|")
          }}))\b)((?:( -S |,)\w+)+)( -F path=/usr/bin/gpasswd -F perm=x -F auid>=1000
          -F auid!=unset (?:-k |-F key=)\w+)
        line: \1\2\3{{ missing_syscalls | join("\3") }}\4
        backrefs: true
        state: present
        mode: g-rwx,o-rwx
      when: syscalls_found | length > 0 and missing_syscalls | length > 0

    - name: Add the audit rule to {{ audit_file }}
      ansible.builtin.lineinfile:
        path: '{{ audit_file }}'
        line: -a always,exit{{ syscalls | join(',') }} -F path=/usr/bin/gpasswd -F
          perm=x -F auid>=1000 -F auid!=unset -F key=privileged
        create: true
        mode: g-rwx,o-rwx
        state: present
      when: syscalls_found | length == 0
    when:
    - '"audit" in ansible_facts.packages'
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-000575
    - NIST-800-171-3.1.7
    - NIST-800-53-AC-2(4)
    - NIST-800-53-AC-6(9)
    - NIST-800-53-AU-12(c)
    - NIST-800-53-AU-2(d)
    - NIST-800-53-CM-6(a)
    - audit_rules_privileged_commands_gpasswd
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Ensure auditd Collects Information on the Use of Privileged Commands - kmod
      - Perform remediation of Audit rules for /usr/bin/kmod
    block:

    - name: Declare list of syscalls
      ansible.builtin.set_fact:
        syscalls: []
        syscall_grouping: []

    - name: Check existence of  in /etc/audit/rules.d/
      ansible.builtin.find:
        paths: /etc/audit/rules.d
        contains: -a always,exit(( -S |,)\w+)*(( -S |,){{ item }})+(( -S |,)\w+)*
          -F path=/usr/bin/kmod -F perm=x -F auid>=1000 -F auid!=unset (-k\s+|-F\s+key=)\S+\s*$
        patterns: '*.rules'
      register: find_command
      loop: '{{ (syscall_grouping + syscalls) | unique }}'

    - name: Reset syscalls found per file
      ansible.builtin.set_fact:
        syscalls_per_file: {}
        found_paths_dict: {}

    - name: Declare syscalls found per file
      ansible.builtin.set_fact: syscalls_per_file="{{ syscalls_per_file | combine(
        {item.files[0].path :[item.item] + syscalls_per_file.get(item.files[0].path,
        []) } ) }}"
      loop: '{{ find_command.results | selectattr(''matched'') | list }}'

    - name: Declare files where syscalls were found
      ansible.builtin.set_fact: found_paths="{{ find_command.results | map(attribute='files')
        | flatten | map(attribute='path') | list }}"

    - name: Count occurrences of syscalls in paths
      ansible.builtin.set_fact: found_paths_dict="{{ found_paths_dict | combine({
        item:1+found_paths_dict.get(item, 0) }) }}"
      loop: '{{ find_command.results | map(attribute=''files'') | flatten | map(attribute=''path'')
        | list }}'

    - name: Get path with most syscalls
      ansible.builtin.set_fact: audit_file="{{ (found_paths_dict | dict2items() |
        sort(attribute='value') | last).key }}"
      when: found_paths | length >= 1

    - name: No file with syscall found, set path to /etc/audit/rules.d/privileged.rules
      ansible.builtin.set_fact: audit_file="/etc/audit/rules.d/privileged.rules"
      when: found_paths | length == 0

    - name: Declare found syscalls
      ansible.builtin.set_fact: syscalls_found="{{ find_command.results | selectattr('matched')
        | map(attribute='item') | list }}"

    - name: Declare missing syscalls
      ansible.builtin.set_fact: missing_syscalls="{{ syscalls | difference(syscalls_found)
        }}"

    - name: Replace the audit rule in {{ audit_file }}
      ansible.builtin.lineinfile:
        path: '{{ audit_file }}'
        regexp: (-a always,exit)(?=.*(?:(?:-S |,)(?:{{ syscalls_per_file[audit_file]
          | join("|") }}))\b)((?:( -S |,)\w+)+)( -F path=/usr/bin/kmod -F perm=x -F
          auid>=1000 -F auid!=unset (?:-k |-F key=)\w+)
        line: \1\2\3{{ missing_syscalls | join("\3") }}\4
        backrefs: true
        state: present
        mode: g-rwx,o-rwx
      when: syscalls_found | length > 0 and missing_syscalls | length > 0

    - name: Add the audit rule to {{ audit_file }}
      ansible.builtin.lineinfile:
        path: '{{ audit_file }}'
        line: -a always,exit{{ syscalls | join(',') }} -F path=/usr/bin/kmod -F perm=x
          -F auid>=1000 -F auid!=unset -F key=privileged
        create: true
        mode: g-rwx,o-rwx
        state: present
      when: syscalls_found | length == 0

    - name: Declare list of syscalls
      ansible.builtin.set_fact:
        syscalls: []
        syscall_grouping: []

    - name: Check existence of  in /etc/audit/audit.rules
      ansible.builtin.find:
        paths: /etc/audit
        contains: -a always,exit(( -S |,)\w+)*(( -S |,){{ item }})+(( -S |,)\w+)*
          -F path=/usr/bin/kmod -F perm=x -F auid>=1000 -F auid!=unset (-k\s+|-F\s+key=)\S+\s*$
        patterns: audit.rules
      register: find_command
      loop: '{{ (syscall_grouping + syscalls) | unique }}'

    - name: Set path to /etc/audit/audit.rules
      ansible.builtin.set_fact: audit_file="/etc/audit/audit.rules"

    - name: Declare found syscalls
      ansible.builtin.set_fact: syscalls_found="{{ find_command.results | selectattr('matched')
        | map(attribute='item') | list }}"

    - name: Declare missing syscalls
      ansible.builtin.set_fact: missing_syscalls="{{ syscalls | difference(syscalls_found)
        }}"

    - name: Replace the audit rule in {{ audit_file }}
      ansible.builtin.lineinfile:
        path: '{{ audit_file }}'
        regexp: (-a always,exit)(?=.*(?:(?:-S |,)(?:{{ syscalls_found | join("|")
          }}))\b)((?:( -S |,)\w+)+)( -F path=/usr/bin/kmod -F perm=x -F auid>=1000
          -F auid!=unset (?:-k |-F key=)\w+)
        line: \1\2\3{{ missing_syscalls | join("\3") }}\4
        backrefs: true
        state: present
        mode: g-rwx,o-rwx
      when: syscalls_found | length > 0 and missing_syscalls | length > 0

    - name: Add the audit rule to {{ audit_file }}
      ansible.builtin.lineinfile:
        path: '{{ audit_file }}'
        line: -a always,exit{{ syscalls | join(',') }} -F path=/usr/bin/kmod -F perm=x
          -F auid>=1000 -F auid!=unset -F key=privileged
        create: true
        mode: g-rwx,o-rwx
        state: present
      when: syscalls_found | length == 0
    when:
    - '"audit" in ansible_facts.packages'
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-000695
    - NIST-800-53-AU-12(a)
    - NIST-800-53-AU-12.1(ii)
    - NIST-800-53-AU-12.1(iv)AU-12(c)
    - NIST-800-53-AU-3
    - NIST-800-53-AU-3.1
    - NIST-800-53-MA-4(1)(a)
    - audit_rules_privileged_commands_kmod
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Ensure auditd Collects Information on the Use of Privileged Commands - mount
      - Perform remediation of Audit rules for /usr/bin/mount
    block:

    - name: Declare list of syscalls
      ansible.builtin.set_fact:
        syscalls: []
        syscall_grouping: []

    - name: Check existence of  in /etc/audit/rules.d/
      ansible.builtin.find:
        paths: /etc/audit/rules.d
        contains: -a always,exit(( -S |,)\w+)*(( -S |,){{ item }})+(( -S |,)\w+)*
          -F path=/usr/bin/mount -F perm=x -F auid>=1000 -F auid!=unset (-k\s+|-F\s+key=)\S+\s*$
        patterns: '*.rules'
      register: find_command
      loop: '{{ (syscall_grouping + syscalls) | unique }}'

    - name: Reset syscalls found per file
      ansible.builtin.set_fact:
        syscalls_per_file: {}
        found_paths_dict: {}

    - name: Declare syscalls found per file
      ansible.builtin.set_fact: syscalls_per_file="{{ syscalls_per_file | combine(
        {item.files[0].path :[item.item] + syscalls_per_file.get(item.files[0].path,
        []) } ) }}"
      loop: '{{ find_command.results | selectattr(''matched'') | list }}'

    - name: Declare files where syscalls were found
      ansible.builtin.set_fact: found_paths="{{ find_command.results | map(attribute='files')
        | flatten | map(attribute='path') | list }}"

    - name: Count occurrences of syscalls in paths
      ansible.builtin.set_fact: found_paths_dict="{{ found_paths_dict | combine({
        item:1+found_paths_dict.get(item, 0) }) }}"
      loop: '{{ find_command.results | map(attribute=''files'') | flatten | map(attribute=''path'')
        | list }}'

    - name: Get path with most syscalls
      ansible.builtin.set_fact: audit_file="{{ (found_paths_dict | dict2items() |
        sort(attribute='value') | last).key }}"
      when: found_paths | length >= 1

    - name: No file with syscall found, set path to /etc/audit/rules.d/privileged.rules
      ansible.builtin.set_fact: audit_file="/etc/audit/rules.d/privileged.rules"
      when: found_paths | length == 0

    - name: Declare found syscalls
      ansible.builtin.set_fact: syscalls_found="{{ find_command.results | selectattr('matched')
        | map(attribute='item') | list }}"

    - name: Declare missing syscalls
      ansible.builtin.set_fact: missing_syscalls="{{ syscalls | difference(syscalls_found)
        }}"

    - name: Replace the audit rule in {{ audit_file }}
      ansible.builtin.lineinfile:
        path: '{{ audit_file }}'
        regexp: (-a always,exit)(?=.*(?:(?:-S |,)(?:{{ syscalls_per_file[audit_file]
          | join("|") }}))\b)((?:( -S |,)\w+)+)( -F path=/usr/bin/mount -F perm=x
          -F auid>=1000 -F auid!=unset (?:-k |-F key=)\w+)
        line: \1\2\3{{ missing_syscalls | join("\3") }}\4
        backrefs: true
        state: present
        mode: g-rwx,o-rwx
      when: syscalls_found | length > 0 and missing_syscalls | length > 0

    - name: Add the audit rule to {{ audit_file }}
      ansible.builtin.lineinfile:
        path: '{{ audit_file }}'
        line: -a always,exit{{ syscalls | join(',') }} -F path=/usr/bin/mount -F perm=x
          -F auid>=1000 -F auid!=unset -F key=privileged
        create: true
        mode: g-rwx,o-rwx
        state: present
      when: syscalls_found | length == 0

    - name: Declare list of syscalls
      ansible.builtin.set_fact:
        syscalls: []
        syscall_grouping: []

    - name: Check existence of  in /etc/audit/audit.rules
      ansible.builtin.find:
        paths: /etc/audit
        contains: -a always,exit(( -S |,)\w+)*(( -S |,){{ item }})+(( -S |,)\w+)*
          -F path=/usr/bin/mount -F perm=x -F auid>=1000 -F auid!=unset (-k\s+|-F\s+key=)\S+\s*$
        patterns: audit.rules
      register: find_command
      loop: '{{ (syscall_grouping + syscalls) | unique }}'

    - name: Set path to /etc/audit/audit.rules
      ansible.builtin.set_fact: audit_file="/etc/audit/audit.rules"

    - name: Declare found syscalls
      ansible.builtin.set_fact: syscalls_found="{{ find_command.results | selectattr('matched')
        | map(attribute='item') | list }}"

    - name: Declare missing syscalls
      ansible.builtin.set_fact: missing_syscalls="{{ syscalls | difference(syscalls_found)
        }}"

    - name: Replace the audit rule in {{ audit_file }}
      ansible.builtin.lineinfile:
        path: '{{ audit_file }}'
        regexp: (-a always,exit)(?=.*(?:(?:-S |,)(?:{{ syscalls_found | join("|")
          }}))\b)((?:( -S |,)\w+)+)( -F path=/usr/bin/mount -F perm=x -F auid>=1000
          -F auid!=unset (?:-k |-F key=)\w+)
        line: \1\2\3{{ missing_syscalls | join("\3") }}\4
        backrefs: true
        state: present
        mode: g-rwx,o-rwx
      when: syscalls_found | length > 0 and missing_syscalls | length > 0

    - name: Add the audit rule to {{ audit_file }}
      ansible.builtin.lineinfile:
        path: '{{ audit_file }}'
        line: -a always,exit{{ syscalls | join(',') }} -F path=/usr/bin/mount -F perm=x
          -F auid>=1000 -F auid!=unset -F key=privileged
        create: true
        mode: g-rwx,o-rwx
        state: present
      when: syscalls_found | length == 0
    when:
    - '"audit" in ansible_facts.packages'
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-000630
    - NIST-800-53-AC-6(9)
    - NIST-800-53-AU-12(c)
    - NIST-800-53-AU-2(d)
    - NIST-800-53-CM-6(a)
    - audit_rules_privileged_commands_mount
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Ensure auditd Collects Information on the Use of Privileged Commands - newgrp
      - Perform remediation of Audit rules for /usr/bin/newgrp
    block:

    - name: Declare list of syscalls
      ansible.builtin.set_fact:
        syscalls: []
        syscall_grouping: []

    - name: Check existence of  in /etc/audit/rules.d/
      ansible.builtin.find:
        paths: /etc/audit/rules.d
        contains: -a always,exit(( -S |,)\w+)*(( -S |,){{ item }})+(( -S |,)\w+)*
          -F path=/usr/bin/newgrp -F perm=x -F auid>=1000 -F auid!=unset (-k\s+|-F\s+key=)\S+\s*$
        patterns: '*.rules'
      register: find_command
      loop: '{{ (syscall_grouping + syscalls) | unique }}'

    - name: Reset syscalls found per file
      ansible.builtin.set_fact:
        syscalls_per_file: {}
        found_paths_dict: {}

    - name: Declare syscalls found per file
      ansible.builtin.set_fact: syscalls_per_file="{{ syscalls_per_file | combine(
        {item.files[0].path :[item.item] + syscalls_per_file.get(item.files[0].path,
        []) } ) }}"
      loop: '{{ find_command.results | selectattr(''matched'') | list }}'

    - name: Declare files where syscalls were found
      ansible.builtin.set_fact: found_paths="{{ find_command.results | map(attribute='files')
        | flatten | map(attribute='path') | list }}"

    - name: Count occurrences of syscalls in paths
      ansible.builtin.set_fact: found_paths_dict="{{ found_paths_dict | combine({
        item:1+found_paths_dict.get(item, 0) }) }}"
      loop: '{{ find_command.results | map(attribute=''files'') | flatten | map(attribute=''path'')
        | list }}'

    - name: Get path with most syscalls
      ansible.builtin.set_fact: audit_file="{{ (found_paths_dict | dict2items() |
        sort(attribute='value') | last).key }}"
      when: found_paths | length >= 1

    - name: No file with syscall found, set path to /etc/audit/rules.d/privileged.rules
      ansible.builtin.set_fact: audit_file="/etc/audit/rules.d/privileged.rules"
      when: found_paths | length == 0

    - name: Declare found syscalls
      ansible.builtin.set_fact: syscalls_found="{{ find_command.results | selectattr('matched')
        | map(attribute='item') | list }}"

    - name: Declare missing syscalls
      ansible.builtin.set_fact: missing_syscalls="{{ syscalls | difference(syscalls_found)
        }}"

    - name: Replace the audit rule in {{ audit_file }}
      ansible.builtin.lineinfile:
        path: '{{ audit_file }}'
        regexp: (-a always,exit)(?=.*(?:(?:-S |,)(?:{{ syscalls_per_file[audit_file]
          | join("|") }}))\b)((?:( -S |,)\w+)+)( -F path=/usr/bin/newgrp -F perm=x
          -F auid>=1000 -F auid!=unset (?:-k |-F key=)\w+)
        line: \1\2\3{{ missing_syscalls | join("\3") }}\4
        backrefs: true
        state: present
        mode: g-rwx,o-rwx
      when: syscalls_found | length > 0 and missing_syscalls | length > 0

    - name: Add the audit rule to {{ audit_file }}
      ansible.builtin.lineinfile:
        path: '{{ audit_file }}'
        line: -a always,exit{{ syscalls | join(',') }} -F path=/usr/bin/newgrp -F
          perm=x -F auid>=1000 -F auid!=unset -F key=privileged
        create: true
        mode: g-rwx,o-rwx
        state: present
      when: syscalls_found | length == 0

    - name: Declare list of syscalls
      ansible.builtin.set_fact:
        syscalls: []
        syscall_grouping: []

    - name: Check existence of  in /etc/audit/audit.rules
      ansible.builtin.find:
        paths: /etc/audit
        contains: -a always,exit(( -S |,)\w+)*(( -S |,){{ item }})+(( -S |,)\w+)*
          -F path=/usr/bin/newgrp -F perm=x -F auid>=1000 -F auid!=unset (-k\s+|-F\s+key=)\S+\s*$
        patterns: audit.rules
      register: find_command
      loop: '{{ (syscall_grouping + syscalls) | unique }}'

    - name: Set path to /etc/audit/audit.rules
      ansible.builtin.set_fact: audit_file="/etc/audit/audit.rules"

    - name: Declare found syscalls
      ansible.builtin.set_fact: syscalls_found="{{ find_command.results | selectattr('matched')
        | map(attribute='item') | list }}"

    - name: Declare missing syscalls
      ansible.builtin.set_fact: missing_syscalls="{{ syscalls | difference(syscalls_found)
        }}"

    - name: Replace the audit rule in {{ audit_file }}
      ansible.builtin.lineinfile:
        path: '{{ audit_file }}'
        regexp: (-a always,exit)(?=.*(?:(?:-S |,)(?:{{ syscalls_found | join("|")
          }}))\b)((?:( -S |,)\w+)+)( -F path=/usr/bin/newgrp -F perm=x -F auid>=1000
          -F auid!=unset (?:-k |-F key=)\w+)
        line: \1\2\3{{ missing_syscalls | join("\3") }}\4
        backrefs: true
        state: present
        mode: g-rwx,o-rwx
      when: syscalls_found | length > 0 and missing_syscalls | length > 0

    - name: Add the audit rule to {{ audit_file }}
      ansible.builtin.lineinfile:
        path: '{{ audit_file }}'
        line: -a always,exit{{ syscalls | join(',') }} -F path=/usr/bin/newgrp -F
          perm=x -F auid>=1000 -F auid!=unset -F key=privileged
        create: true
        mode: g-rwx,o-rwx
        state: present
      when: syscalls_found | length == 0
    when:
    - '"audit" in ansible_facts.packages'
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-000580
    - NIST-800-171-3.1.7
    - NIST-800-53-AC-2(4)
    - NIST-800-53-AC-6(9)
    - NIST-800-53-AU-12(c)
    - NIST-800-53-AU-2(d)
    - NIST-800-53-CM-6(a)
    - audit_rules_privileged_commands_newgrp
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Ensure auditd Collects Information on the Use of Privileged Commands - pam_timestamp_check
      - Perform remediation of Audit rules for /usr/sbin/pam_timestamp_check
    block:

    - name: Declare list of syscalls
      ansible.builtin.set_fact:
        syscalls: []
        syscall_grouping: []

    - name: Check existence of  in /etc/audit/rules.d/
      ansible.builtin.find:
        paths: /etc/audit/rules.d
        contains: -a always,exit(( -S |,)\w+)*(( -S |,){{ item }})+(( -S |,)\w+)*
          -F path=/usr/sbin/pam_timestamp_check -F perm=x -F auid>=1000 -F auid!=unset
          (-k\s+|-F\s+key=)\S+\s*$
        patterns: '*.rules'
      register: find_command
      loop: '{{ (syscall_grouping + syscalls) | unique }}'

    - name: Reset syscalls found per file
      ansible.builtin.set_fact:
        syscalls_per_file: {}
        found_paths_dict: {}

    - name: Declare syscalls found per file
      ansible.builtin.set_fact: syscalls_per_file="{{ syscalls_per_file | combine(
        {item.files[0].path :[item.item] + syscalls_per_file.get(item.files[0].path,
        []) } ) }}"
      loop: '{{ find_command.results | selectattr(''matched'') | list }}'

    - name: Declare files where syscalls were found
      ansible.builtin.set_fact: found_paths="{{ find_command.results | map(attribute='files')
        | flatten | map(attribute='path') | list }}"

    - name: Count occurrences of syscalls in paths
      ansible.builtin.set_fact: found_paths_dict="{{ found_paths_dict | combine({
        item:1+found_paths_dict.get(item, 0) }) }}"
      loop: '{{ find_command.results | map(attribute=''files'') | flatten | map(attribute=''path'')
        | list }}'

    - name: Get path with most syscalls
      ansible.builtin.set_fact: audit_file="{{ (found_paths_dict | dict2items() |
        sort(attribute='value') | last).key }}"
      when: found_paths | length >= 1

    - name: No file with syscall found, set path to /etc/audit/rules.d/privileged.rules
      ansible.builtin.set_fact: audit_file="/etc/audit/rules.d/privileged.rules"
      when: found_paths | length == 0

    - name: Declare found syscalls
      ansible.builtin.set_fact: syscalls_found="{{ find_command.results | selectattr('matched')
        | map(attribute='item') | list }}"

    - name: Declare missing syscalls
      ansible.builtin.set_fact: missing_syscalls="{{ syscalls | difference(syscalls_found)
        }}"

    - name: Replace the audit rule in {{ audit_file }}
      ansible.builtin.lineinfile:
        path: '{{ audit_file }}'
        regexp: (-a always,exit)(?=.*(?:(?:-S |,)(?:{{ syscalls_per_file[audit_file]
          | join("|") }}))\b)((?:( -S |,)\w+)+)( -F path=/usr/sbin/pam_timestamp_check
          -F perm=x -F auid>=1000 -F auid!=unset (?:-k |-F key=)\w+)
        line: \1\2\3{{ missing_syscalls | join("\3") }}\4
        backrefs: true
        state: present
        mode: g-rwx,o-rwx
      when: syscalls_found | length > 0 and missing_syscalls | length > 0

    - name: Add the audit rule to {{ audit_file }}
      ansible.builtin.lineinfile:
        path: '{{ audit_file }}'
        line: -a always,exit{{ syscalls | join(',') }} -F path=/usr/sbin/pam_timestamp_check
          -F perm=x -F auid>=1000 -F auid!=unset -F key=privileged
        create: true
        mode: g-rwx,o-rwx
        state: present
      when: syscalls_found | length == 0

    - name: Declare list of syscalls
      ansible.builtin.set_fact:
        syscalls: []
        syscall_grouping: []

    - name: Check existence of  in /etc/audit/audit.rules
      ansible.builtin.find:
        paths: /etc/audit
        contains: -a always,exit(( -S |,)\w+)*(( -S |,){{ item }})+(( -S |,)\w+)*
          -F path=/usr/sbin/pam_timestamp_check -F perm=x -F auid>=1000 -F auid!=unset
          (-k\s+|-F\s+key=)\S+\s*$
        patterns: audit.rules
      register: find_command
      loop: '{{ (syscall_grouping + syscalls) | unique }}'

    - name: Set path to /etc/audit/audit.rules
      ansible.builtin.set_fact: audit_file="/etc/audit/audit.rules"

    - name: Declare found syscalls
      ansible.builtin.set_fact: syscalls_found="{{ find_command.results | selectattr('matched')
        | map(attribute='item') | list }}"

    - name: Declare missing syscalls
      ansible.builtin.set_fact: missing_syscalls="{{ syscalls | difference(syscalls_found)
        }}"

    - name: Replace the audit rule in {{ audit_file }}
      ansible.builtin.lineinfile:
        path: '{{ audit_file }}'
        regexp: (-a always,exit)(?=.*(?:(?:-S |,)(?:{{ syscalls_found | join("|")
          }}))\b)((?:( -S |,)\w+)+)( -F path=/usr/sbin/pam_timestamp_check -F perm=x
          -F auid>=1000 -F auid!=unset (?:-k |-F key=)\w+)
        line: \1\2\3{{ missing_syscalls | join("\3") }}\4
        backrefs: true
        state: present
        mode: g-rwx,o-rwx
      when: syscalls_found | length > 0 and missing_syscalls | length > 0

    - name: Add the audit rule to {{ audit_file }}
      ansible.builtin.lineinfile:
        path: '{{ audit_file }}'
        line: -a always,exit{{ syscalls | join(',') }} -F path=/usr/sbin/pam_timestamp_check
          -F perm=x -F auid>=1000 -F auid!=unset -F key=privileged
        create: true
        mode: g-rwx,o-rwx
        state: present
      when: syscalls_found | length == 0
    when:
    - '"audit" in ansible_facts.packages'
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-000585
    - NIST-800-171-3.1.7
    - NIST-800-53-AC-6(9)
    - NIST-800-53-AU-12(c)
    - NIST-800-53-AU-2(d)
    - NIST-800-53-CM-6(a)
    - audit_rules_privileged_commands_pam_timestamp_check
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Ensure auditd Collects Information on the Use of Privileged Commands - passwd
      - Perform remediation of Audit rules for /usr/bin/passwd
    block:

    - name: Declare list of syscalls
      ansible.builtin.set_fact:
        syscalls: []
        syscall_grouping: []

    - name: Check existence of  in /etc/audit/rules.d/
      ansible.builtin.find:
        paths: /etc/audit/rules.d
        contains: -a always,exit(( -S |,)\w+)*(( -S |,){{ item }})+(( -S |,)\w+)*
          -F path=/usr/bin/passwd -F perm=x -F auid>=1000 -F auid!=unset (-k\s+|-F\s+key=)\S+\s*$
        patterns: '*.rules'
      register: find_command
      loop: '{{ (syscall_grouping + syscalls) | unique }}'

    - name: Reset syscalls found per file
      ansible.builtin.set_fact:
        syscalls_per_file: {}
        found_paths_dict: {}

    - name: Declare syscalls found per file
      ansible.builtin.set_fact: syscalls_per_file="{{ syscalls_per_file | combine(
        {item.files[0].path :[item.item] + syscalls_per_file.get(item.files[0].path,
        []) } ) }}"
      loop: '{{ find_command.results | selectattr(''matched'') | list }}'

    - name: Declare files where syscalls were found
      ansible.builtin.set_fact: found_paths="{{ find_command.results | map(attribute='files')
        | flatten | map(attribute='path') | list }}"

    - name: Count occurrences of syscalls in paths
      ansible.builtin.set_fact: found_paths_dict="{{ found_paths_dict | combine({
        item:1+found_paths_dict.get(item, 0) }) }}"
      loop: '{{ find_command.results | map(attribute=''files'') | flatten | map(attribute=''path'')
        | list }}'

    - name: Get path with most syscalls
      ansible.builtin.set_fact: audit_file="{{ (found_paths_dict | dict2items() |
        sort(attribute='value') | last).key }}"
      when: found_paths | length >= 1

    - name: No file with syscall found, set path to /etc/audit/rules.d/privileged.rules
      ansible.builtin.set_fact: audit_file="/etc/audit/rules.d/privileged.rules"
      when: found_paths | length == 0

    - name: Declare found syscalls
      ansible.builtin.set_fact: syscalls_found="{{ find_command.results | selectattr('matched')
        | map(attribute='item') | list }}"

    - name: Declare missing syscalls
      ansible.builtin.set_fact: missing_syscalls="{{ syscalls | difference(syscalls_found)
        }}"

    - name: Replace the audit rule in {{ audit_file }}
      ansible.builtin.lineinfile:
        path: '{{ audit_file }}'
        regexp: (-a always,exit)(?=.*(?:(?:-S |,)(?:{{ syscalls_per_file[audit_file]
          | join("|") }}))\b)((?:( -S |,)\w+)+)( -F path=/usr/bin/passwd -F perm=x
          -F auid>=1000 -F auid!=unset (?:-k |-F key=)\w+)
        line: \1\2\3{{ missing_syscalls | join("\3") }}\4
        backrefs: true
        state: present
        mode: g-rwx,o-rwx
      when: syscalls_found | length > 0 and missing_syscalls | length > 0

    - name: Add the audit rule to {{ audit_file }}
      ansible.builtin.lineinfile:
        path: '{{ audit_file }}'
        line: -a always,exit{{ syscalls | join(',') }} -F path=/usr/bin/passwd -F
          perm=x -F auid>=1000 -F auid!=unset -F key=privileged
        create: true
        mode: g-rwx,o-rwx
        state: present
      when: syscalls_found | length == 0

    - name: Declare list of syscalls
      ansible.builtin.set_fact:
        syscalls: []
        syscall_grouping: []

    - name: Check existence of  in /etc/audit/audit.rules
      ansible.builtin.find:
        paths: /etc/audit
        contains: -a always,exit(( -S |,)\w+)*(( -S |,){{ item }})+(( -S |,)\w+)*
          -F path=/usr/bin/passwd -F perm=x -F auid>=1000 -F auid!=unset (-k\s+|-F\s+key=)\S+\s*$
        patterns: audit.rules
      register: find_command
      loop: '{{ (syscall_grouping + syscalls) | unique }}'

    - name: Set path to /etc/audit/audit.rules
      ansible.builtin.set_fact: audit_file="/etc/audit/audit.rules"

    - name: Declare found syscalls
      ansible.builtin.set_fact: syscalls_found="{{ find_command.results | selectattr('matched')
        | map(attribute='item') | list }}"

    - name: Declare missing syscalls
      ansible.builtin.set_fact: missing_syscalls="{{ syscalls | difference(syscalls_found)
        }}"

    - name: Replace the audit rule in {{ audit_file }}
      ansible.builtin.lineinfile:
        path: '{{ audit_file }}'
        regexp: (-a always,exit)(?=.*(?:(?:-S |,)(?:{{ syscalls_found | join("|")
          }}))\b)((?:( -S |,)\w+)+)( -F path=/usr/bin/passwd -F perm=x -F auid>=1000
          -F auid!=unset (?:-k |-F key=)\w+)
        line: \1\2\3{{ missing_syscalls | join("\3") }}\4
        backrefs: true
        state: present
        mode: g-rwx,o-rwx
      when: syscalls_found | length > 0 and missing_syscalls | length > 0

    - name: Add the audit rule to {{ audit_file }}
      ansible.builtin.lineinfile:
        path: '{{ audit_file }}'
        line: -a always,exit{{ syscalls | join(',') }} -F path=/usr/bin/passwd -F
          perm=x -F auid>=1000 -F auid!=unset -F key=privileged
        create: true
        mode: g-rwx,o-rwx
        state: present
      when: syscalls_found | length == 0
    when:
    - '"audit" in ansible_facts.packages'
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-000590
    - NIST-800-171-3.1.7
    - NIST-800-53-AC-2(4)
    - NIST-800-53-AC-6(9)
    - NIST-800-53-AU-12(c)
    - NIST-800-53-AU-2(d)
    - NIST-800-53-CM-6(a)
    - audit_rules_privileged_commands_passwd
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Ensure auditd Collects Information on the Use of Privileged Commands - postdrop
      - Perform remediation of Audit rules for /usr/sbin/postdrop
    block:

    - name: Declare list of syscalls
      ansible.builtin.set_fact:
        syscalls: []
        syscall_grouping: []

    - name: Check existence of  in /etc/audit/rules.d/
      ansible.builtin.find:
        paths: /etc/audit/rules.d
        contains: -a always,exit(( -S |,)\w+)*(( -S |,){{ item }})+(( -S |,)\w+)*
          -F path=/usr/sbin/postdrop -F perm=x -F auid>=1000 -F auid!=unset (-k\s+|-F\s+key=)\S+\s*$
        patterns: '*.rules'
      register: find_command
      loop: '{{ (syscall_grouping + syscalls) | unique }}'

    - name: Reset syscalls found per file
      ansible.builtin.set_fact:
        syscalls_per_file: {}
        found_paths_dict: {}

    - name: Declare syscalls found per file
      ansible.builtin.set_fact: syscalls_per_file="{{ syscalls_per_file | combine(
        {item.files[0].path :[item.item] + syscalls_per_file.get(item.files[0].path,
        []) } ) }}"
      loop: '{{ find_command.results | selectattr(''matched'') | list }}'

    - name: Declare files where syscalls were found
      ansible.builtin.set_fact: found_paths="{{ find_command.results | map(attribute='files')
        | flatten | map(attribute='path') | list }}"

    - name: Count occurrences of syscalls in paths
      ansible.builtin.set_fact: found_paths_dict="{{ found_paths_dict | combine({
        item:1+found_paths_dict.get(item, 0) }) }}"
      loop: '{{ find_command.results | map(attribute=''files'') | flatten | map(attribute=''path'')
        | list }}'

    - name: Get path with most syscalls
      ansible.builtin.set_fact: audit_file="{{ (found_paths_dict | dict2items() |
        sort(attribute='value') | last).key }}"
      when: found_paths | length >= 1

    - name: No file with syscall found, set path to /etc/audit/rules.d/privileged.rules
      ansible.builtin.set_fact: audit_file="/etc/audit/rules.d/privileged.rules"
      when: found_paths | length == 0

    - name: Declare found syscalls
      ansible.builtin.set_fact: syscalls_found="{{ find_command.results | selectattr('matched')
        | map(attribute='item') | list }}"

    - name: Declare missing syscalls
      ansible.builtin.set_fact: missing_syscalls="{{ syscalls | difference(syscalls_found)
        }}"

    - name: Replace the audit rule in {{ audit_file }}
      ansible.builtin.lineinfile:
        path: '{{ audit_file }}'
        regexp: (-a always,exit)(?=.*(?:(?:-S |,)(?:{{ syscalls_per_file[audit_file]
          | join("|") }}))\b)((?:( -S |,)\w+)+)( -F path=/usr/sbin/postdrop -F perm=x
          -F auid>=1000 -F auid!=unset (?:-k |-F key=)\w+)
        line: \1\2\3{{ missing_syscalls | join("\3") }}\4
        backrefs: true
        state: present
        mode: g-rwx,o-rwx
      when: syscalls_found | length > 0 and missing_syscalls | length > 0

    - name: Add the audit rule to {{ audit_file }}
      ansible.builtin.lineinfile:
        path: '{{ audit_file }}'
        line: -a always,exit{{ syscalls | join(',') }} -F path=/usr/sbin/postdrop
          -F perm=x -F auid>=1000 -F auid!=unset -F key=privileged
        create: true
        mode: g-rwx,o-rwx
        state: present
      when: syscalls_found | length == 0

    - name: Declare list of syscalls
      ansible.builtin.set_fact:
        syscalls: []
        syscall_grouping: []

    - name: Check existence of  in /etc/audit/audit.rules
      ansible.builtin.find:
        paths: /etc/audit
        contains: -a always,exit(( -S |,)\w+)*(( -S |,){{ item }})+(( -S |,)\w+)*
          -F path=/usr/sbin/postdrop -F perm=x -F auid>=1000 -F auid!=unset (-k\s+|-F\s+key=)\S+\s*$
        patterns: audit.rules
      register: find_command
      loop: '{{ (syscall_grouping + syscalls) | unique }}'

    - name: Set path to /etc/audit/audit.rules
      ansible.builtin.set_fact: audit_file="/etc/audit/audit.rules"

    - name: Declare found syscalls
      ansible.builtin.set_fact: syscalls_found="{{ find_command.results | selectattr('matched')
        | map(attribute='item') | list }}"

    - name: Declare missing syscalls
      ansible.builtin.set_fact: missing_syscalls="{{ syscalls | difference(syscalls_found)
        }}"

    - name: Replace the audit rule in {{ audit_file }}
      ansible.builtin.lineinfile:
        path: '{{ audit_file }}'
        regexp: (-a always,exit)(?=.*(?:(?:-S |,)(?:{{ syscalls_found | join("|")
          }}))\b)((?:( -S |,)\w+)+)( -F path=/usr/sbin/postdrop -F perm=x -F auid>=1000
          -F auid!=unset (?:-k |-F key=)\w+)
        line: \1\2\3{{ missing_syscalls | join("\3") }}\4
        backrefs: true
        state: present
        mode: g-rwx,o-rwx
      when: syscalls_found | length > 0 and missing_syscalls | length > 0

    - name: Add the audit rule to {{ audit_file }}
      ansible.builtin.lineinfile:
        path: '{{ audit_file }}'
        line: -a always,exit{{ syscalls | join(',') }} -F path=/usr/sbin/postdrop
          -F perm=x -F auid>=1000 -F auid!=unset -F key=privileged
        create: true
        mode: g-rwx,o-rwx
        state: present
      when: syscalls_found | length == 0
    when:
    - '"audit" in ansible_facts.packages'
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-000595
    - NIST-800-171-3.1.7
    - NIST-800-53-AC-6(9)
    - NIST-800-53-AU-12(c)
    - NIST-800-53-AU-2(d)
    - NIST-800-53-CM-6(a)
    - audit_rules_privileged_commands_postdrop
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Ensure auditd Collects Information on the Use of Privileged Commands - postqueue
      - Perform remediation of Audit rules for /usr/sbin/postqueue
    block:

    - name: Declare list of syscalls
      ansible.builtin.set_fact:
        syscalls: []
        syscall_grouping: []

    - name: Check existence of  in /etc/audit/rules.d/
      ansible.builtin.find:
        paths: /etc/audit/rules.d
        contains: -a always,exit(( -S |,)\w+)*(( -S |,){{ item }})+(( -S |,)\w+)*
          -F path=/usr/sbin/postqueue -F perm=x -F auid>=1000 -F auid!=unset (-k\s+|-F\s+key=)\S+\s*$
        patterns: '*.rules'
      register: find_command
      loop: '{{ (syscall_grouping + syscalls) | unique }}'

    - name: Reset syscalls found per file
      ansible.builtin.set_fact:
        syscalls_per_file: {}
        found_paths_dict: {}

    - name: Declare syscalls found per file
      ansible.builtin.set_fact: syscalls_per_file="{{ syscalls_per_file | combine(
        {item.files[0].path :[item.item] + syscalls_per_file.get(item.files[0].path,
        []) } ) }}"
      loop: '{{ find_command.results | selectattr(''matched'') | list }}'

    - name: Declare files where syscalls were found
      ansible.builtin.set_fact: found_paths="{{ find_command.results | map(attribute='files')
        | flatten | map(attribute='path') | list }}"

    - name: Count occurrences of syscalls in paths
      ansible.builtin.set_fact: found_paths_dict="{{ found_paths_dict | combine({
        item:1+found_paths_dict.get(item, 0) }) }}"
      loop: '{{ find_command.results | map(attribute=''files'') | flatten | map(attribute=''path'')
        | list }}'

    - name: Get path with most syscalls
      ansible.builtin.set_fact: audit_file="{{ (found_paths_dict | dict2items() |
        sort(attribute='value') | last).key }}"
      when: found_paths | length >= 1

    - name: No file with syscall found, set path to /etc/audit/rules.d/privileged.rules
      ansible.builtin.set_fact: audit_file="/etc/audit/rules.d/privileged.rules"
      when: found_paths | length == 0

    - name: Declare found syscalls
      ansible.builtin.set_fact: syscalls_found="{{ find_command.results | selectattr('matched')
        | map(attribute='item') | list }}"

    - name: Declare missing syscalls
      ansible.builtin.set_fact: missing_syscalls="{{ syscalls | difference(syscalls_found)
        }}"

    - name: Replace the audit rule in {{ audit_file }}
      ansible.builtin.lineinfile:
        path: '{{ audit_file }}'
        regexp: (-a always,exit)(?=.*(?:(?:-S |,)(?:{{ syscalls_per_file[audit_file]
          | join("|") }}))\b)((?:( -S |,)\w+)+)( -F path=/usr/sbin/postqueue -F perm=x
          -F auid>=1000 -F auid!=unset (?:-k |-F key=)\w+)
        line: \1\2\3{{ missing_syscalls | join("\3") }}\4
        backrefs: true
        state: present
        mode: g-rwx,o-rwx
      when: syscalls_found | length > 0 and missing_syscalls | length > 0

    - name: Add the audit rule to {{ audit_file }}
      ansible.builtin.lineinfile:
        path: '{{ audit_file }}'
        line: -a always,exit{{ syscalls | join(',') }} -F path=/usr/sbin/postqueue
          -F perm=x -F auid>=1000 -F auid!=unset -F key=privileged
        create: true
        mode: g-rwx,o-rwx
        state: present
      when: syscalls_found | length == 0

    - name: Declare list of syscalls
      ansible.builtin.set_fact:
        syscalls: []
        syscall_grouping: []

    - name: Check existence of  in /etc/audit/audit.rules
      ansible.builtin.find:
        paths: /etc/audit
        contains: -a always,exit(( -S |,)\w+)*(( -S |,){{ item }})+(( -S |,)\w+)*
          -F path=/usr/sbin/postqueue -F perm=x -F auid>=1000 -F auid!=unset (-k\s+|-F\s+key=)\S+\s*$
        patterns: audit.rules
      register: find_command
      loop: '{{ (syscall_grouping + syscalls) | unique }}'

    - name: Set path to /etc/audit/audit.rules
      ansible.builtin.set_fact: audit_file="/etc/audit/audit.rules"

    - name: Declare found syscalls
      ansible.builtin.set_fact: syscalls_found="{{ find_command.results | selectattr('matched')
        | map(attribute='item') | list }}"

    - name: Declare missing syscalls
      ansible.builtin.set_fact: missing_syscalls="{{ syscalls | difference(syscalls_found)
        }}"

    - name: Replace the audit rule in {{ audit_file }}
      ansible.builtin.lineinfile:
        path: '{{ audit_file }}'
        regexp: (-a always,exit)(?=.*(?:(?:-S |,)(?:{{ syscalls_found | join("|")
          }}))\b)((?:( -S |,)\w+)+)( -F path=/usr/sbin/postqueue -F perm=x -F auid>=1000
          -F auid!=unset (?:-k |-F key=)\w+)
        line: \1\2\3{{ missing_syscalls | join("\3") }}\4
        backrefs: true
        state: present
        mode: g-rwx,o-rwx
      when: syscalls_found | length > 0 and missing_syscalls | length > 0

    - name: Add the audit rule to {{ audit_file }}
      ansible.builtin.lineinfile:
        path: '{{ audit_file }}'
        line: -a always,exit{{ syscalls | join(',') }} -F path=/usr/sbin/postqueue
          -F perm=x -F auid>=1000 -F auid!=unset -F key=privileged
        create: true
        mode: g-rwx,o-rwx
        state: present
      when: syscalls_found | length == 0
    when:
    - '"audit" in ansible_facts.packages'
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-000600
    - NIST-800-171-3.1.7
    - NIST-800-53-AC-6(9)
    - NIST-800-53-AU-12(c)
    - NIST-800-53-AU-2(d)
    - NIST-800-53-CM-6(a)
    - audit_rules_privileged_commands_postqueue
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Record Any Attempts to Run ssh-agent - Perform remediation of Audit rules
      for /usr/bin/ssh-agent
    block:

    - name: Declare list of syscalls
      ansible.builtin.set_fact:
        syscalls: []
        syscall_grouping: []

    - name: Check existence of  in /etc/audit/rules.d/
      ansible.builtin.find:
        paths: /etc/audit/rules.d
        contains: -a always,exit(( -S |,)\w+)*(( -S |,){{ item }})+(( -S |,)\w+)*
          -F path=/usr/bin/ssh-agent -F perm=x -F auid>=1000 -F auid!=unset (-k\s+|-F\s+key=)\S+\s*$
        patterns: '*.rules'
      register: find_command
      loop: '{{ (syscall_grouping + syscalls) | unique }}'

    - name: Reset syscalls found per file
      ansible.builtin.set_fact:
        syscalls_per_file: {}
        found_paths_dict: {}

    - name: Declare syscalls found per file
      ansible.builtin.set_fact: syscalls_per_file="{{ syscalls_per_file | combine(
        {item.files[0].path :[item.item] + syscalls_per_file.get(item.files[0].path,
        []) } ) }}"
      loop: '{{ find_command.results | selectattr(''matched'') | list }}'

    - name: Declare files where syscalls were found
      ansible.builtin.set_fact: found_paths="{{ find_command.results | map(attribute='files')
        | flatten | map(attribute='path') | list }}"

    - name: Count occurrences of syscalls in paths
      ansible.builtin.set_fact: found_paths_dict="{{ found_paths_dict | combine({
        item:1+found_paths_dict.get(item, 0) }) }}"
      loop: '{{ find_command.results | map(attribute=''files'') | flatten | map(attribute=''path'')
        | list }}'

    - name: Get path with most syscalls
      ansible.builtin.set_fact: audit_file="{{ (found_paths_dict | dict2items() |
        sort(attribute='value') | last).key }}"
      when: found_paths | length >= 1

    - name: No file with syscall found, set path to /etc/audit/rules.d/privileged.rules
      ansible.builtin.set_fact: audit_file="/etc/audit/rules.d/privileged.rules"
      when: found_paths | length == 0

    - name: Declare found syscalls
      ansible.builtin.set_fact: syscalls_found="{{ find_command.results | selectattr('matched')
        | map(attribute='item') | list }}"

    - name: Declare missing syscalls
      ansible.builtin.set_fact: missing_syscalls="{{ syscalls | difference(syscalls_found)
        }}"

    - name: Replace the audit rule in {{ audit_file }}
      ansible.builtin.lineinfile:
        path: '{{ audit_file }}'
        regexp: (-a always,exit)(?=.*(?:(?:-S |,)(?:{{ syscalls_per_file[audit_file]
          | join("|") }}))\b)((?:( -S |,)\w+)+)( -F path=/usr/bin/ssh-agent -F perm=x
          -F auid>=1000 -F auid!=unset (?:-k |-F key=)\w+)
        line: \1\2\3{{ missing_syscalls | join("\3") }}\4
        backrefs: true
        state: present
        mode: g-rwx,o-rwx
      when: syscalls_found | length > 0 and missing_syscalls | length > 0

    - name: Add the audit rule to {{ audit_file }}
      ansible.builtin.lineinfile:
        path: '{{ audit_file }}'
        line: -a always,exit{{ syscalls | join(',') }} -F path=/usr/bin/ssh-agent
          -F perm=x -F auid>=1000 -F auid!=unset -F key=privileged
        create: true
        mode: g-rwx,o-rwx
        state: present
      when: syscalls_found | length == 0

    - name: Declare list of syscalls
      ansible.builtin.set_fact:
        syscalls: []
        syscall_grouping: []

    - name: Check existence of  in /etc/audit/audit.rules
      ansible.builtin.find:
        paths: /etc/audit
        contains: -a always,exit(( -S |,)\w+)*(( -S |,){{ item }})+(( -S |,)\w+)*
          -F path=/usr/bin/ssh-agent -F perm=x -F auid>=1000 -F auid!=unset (-k\s+|-F\s+key=)\S+\s*$
        patterns: audit.rules
      register: find_command
      loop: '{{ (syscall_grouping + syscalls) | unique }}'

    - name: Set path to /etc/audit/audit.rules
      ansible.builtin.set_fact: audit_file="/etc/audit/audit.rules"

    - name: Declare found syscalls
      ansible.builtin.set_fact: syscalls_found="{{ find_command.results | selectattr('matched')
        | map(attribute='item') | list }}"

    - name: Declare missing syscalls
      ansible.builtin.set_fact: missing_syscalls="{{ syscalls | difference(syscalls_found)
        }}"

    - name: Replace the audit rule in {{ audit_file }}
      ansible.builtin.lineinfile:
        path: '{{ audit_file }}'
        regexp: (-a always,exit)(?=.*(?:(?:-S |,)(?:{{ syscalls_found | join("|")
          }}))\b)((?:( -S |,)\w+)+)( -F path=/usr/bin/ssh-agent -F perm=x -F auid>=1000
          -F auid!=unset (?:-k |-F key=)\w+)
        line: \1\2\3{{ missing_syscalls | join("\3") }}\4
        backrefs: true
        state: present
        mode: g-rwx,o-rwx
      when: syscalls_found | length > 0 and missing_syscalls | length > 0

    - name: Add the audit rule to {{ audit_file }}
      ansible.builtin.lineinfile:
        path: '{{ audit_file }}'
        line: -a always,exit{{ syscalls | join(',') }} -F path=/usr/bin/ssh-agent
          -F perm=x -F auid>=1000 -F auid!=unset -F key=privileged
        create: true
        mode: g-rwx,o-rwx
        state: present
      when: syscalls_found | length == 0
    when:
    - '"audit" in ansible_facts.packages'
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-000605
    - audit_rules_privileged_commands_ssh_agent
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Ensure auditd Collects Information on the Use of Privileged Commands - ssh-keysign
      - Perform remediation of Audit rules for /usr/libexec/openssh/ssh-keysign
    block:

    - name: Declare list of syscalls
      ansible.builtin.set_fact:
        syscalls: []
        syscall_grouping: []

    - name: Check existence of  in /etc/audit/rules.d/
      ansible.builtin.find:
        paths: /etc/audit/rules.d
        contains: -a always,exit(( -S |,)\w+)*(( -S |,){{ item }})+(( -S |,)\w+)*
          -F path=/usr/libexec/openssh/ssh-keysign -F perm=x -F auid>=1000 -F auid!=unset
          (-k\s+|-F\s+key=)\S+\s*$
        patterns: '*.rules'
      register: find_command
      loop: '{{ (syscall_grouping + syscalls) | unique }}'

    - name: Reset syscalls found per file
      ansible.builtin.set_fact:
        syscalls_per_file: {}
        found_paths_dict: {}

    - name: Declare syscalls found per file
      ansible.builtin.set_fact: syscalls_per_file="{{ syscalls_per_file | combine(
        {item.files[0].path :[item.item] + syscalls_per_file.get(item.files[0].path,
        []) } ) }}"
      loop: '{{ find_command.results | selectattr(''matched'') | list }}'

    - name: Declare files where syscalls were found
      ansible.builtin.set_fact: found_paths="{{ find_command.results | map(attribute='files')
        | flatten | map(attribute='path') | list }}"

    - name: Count occurrences of syscalls in paths
      ansible.builtin.set_fact: found_paths_dict="{{ found_paths_dict | combine({
        item:1+found_paths_dict.get(item, 0) }) }}"
      loop: '{{ find_command.results | map(attribute=''files'') | flatten | map(attribute=''path'')
        | list }}'

    - name: Get path with most syscalls
      ansible.builtin.set_fact: audit_file="{{ (found_paths_dict | dict2items() |
        sort(attribute='value') | last).key }}"
      when: found_paths | length >= 1

    - name: No file with syscall found, set path to /etc/audit/rules.d/privileged.rules
      ansible.builtin.set_fact: audit_file="/etc/audit/rules.d/privileged.rules"
      when: found_paths | length == 0

    - name: Declare found syscalls
      ansible.builtin.set_fact: syscalls_found="{{ find_command.results | selectattr('matched')
        | map(attribute='item') | list }}"

    - name: Declare missing syscalls
      ansible.builtin.set_fact: missing_syscalls="{{ syscalls | difference(syscalls_found)
        }}"

    - name: Replace the audit rule in {{ audit_file }}
      ansible.builtin.lineinfile:
        path: '{{ audit_file }}'
        regexp: (-a always,exit)(?=.*(?:(?:-S |,)(?:{{ syscalls_per_file[audit_file]
          | join("|") }}))\b)((?:( -S |,)\w+)+)( -F path=/usr/libexec/openssh/ssh-keysign
          -F perm=x -F auid>=1000 -F auid!=unset (?:-k |-F key=)\w+)
        line: \1\2\3{{ missing_syscalls | join("\3") }}\4
        backrefs: true
        state: present
        mode: g-rwx,o-rwx
      when: syscalls_found | length > 0 and missing_syscalls | length > 0

    - name: Add the audit rule to {{ audit_file }}
      ansible.builtin.lineinfile:
        path: '{{ audit_file }}'
        line: -a always,exit{{ syscalls | join(',') }} -F path=/usr/libexec/openssh/ssh-keysign
          -F perm=x -F auid>=1000 -F auid!=unset -F key=privileged
        create: true
        mode: g-rwx,o-rwx
        state: present
      when: syscalls_found | length == 0

    - name: Declare list of syscalls
      ansible.builtin.set_fact:
        syscalls: []
        syscall_grouping: []

    - name: Check existence of  in /etc/audit/audit.rules
      ansible.builtin.find:
        paths: /etc/audit
        contains: -a always,exit(( -S |,)\w+)*(( -S |,){{ item }})+(( -S |,)\w+)*
          -F path=/usr/libexec/openssh/ssh-keysign -F perm=x -F auid>=1000 -F auid!=unset
          (-k\s+|-F\s+key=)\S+\s*$
        patterns: audit.rules
      register: find_command
      loop: '{{ (syscall_grouping + syscalls) | unique }}'

    - name: Set path to /etc/audit/audit.rules
      ansible.builtin.set_fact: audit_file="/etc/audit/audit.rules"

    - name: Declare found syscalls
      ansible.builtin.set_fact: syscalls_found="{{ find_command.results | selectattr('matched')
        | map(attribute='item') | list }}"

    - name: Declare missing syscalls
      ansible.builtin.set_fact: missing_syscalls="{{ syscalls | difference(syscalls_found)
        }}"

    - name: Replace the audit rule in {{ audit_file }}
      ansible.builtin.lineinfile:
        path: '{{ audit_file }}'
        regexp: (-a always,exit)(?=.*(?:(?:-S |,)(?:{{ syscalls_found | join("|")
          }}))\b)((?:( -S |,)\w+)+)( -F path=/usr/libexec/openssh/ssh-keysign -F perm=x
          -F auid>=1000 -F auid!=unset (?:-k |-F key=)\w+)
        line: \1\2\3{{ missing_syscalls | join("\3") }}\4
        backrefs: true
        state: present
        mode: g-rwx,o-rwx
      when: syscalls_found | length > 0 and missing_syscalls | length > 0

    - name: Add the audit rule to {{ audit_file }}
      ansible.builtin.lineinfile:
        path: '{{ audit_file }}'
        line: -a always,exit{{ syscalls | join(',') }} -F path=/usr/libexec/openssh/ssh-keysign
          -F perm=x -F auid>=1000 -F auid!=unset -F key=privileged
        create: true
        mode: g-rwx,o-rwx
        state: present
      when: syscalls_found | length == 0
    when:
    - '"audit" in ansible_facts.packages'
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-000610
    - NIST-800-171-3.1.7
    - NIST-800-53-AC-6(9)
    - NIST-800-53-AU-12(c)
    - NIST-800-53-AU-2(d)
    - NIST-800-53-CM-6(a)
    - audit_rules_privileged_commands_ssh_keysign
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Ensure auditd Collects Information on the Use of Privileged Commands - su
      - Perform remediation of Audit rules for /usr/bin/su
    block:

    - name: Declare list of syscalls
      ansible.builtin.set_fact:
        syscalls: []
        syscall_grouping: []

    - name: Check existence of  in /etc/audit/rules.d/
      ansible.builtin.find:
        paths: /etc/audit/rules.d
        contains: -a always,exit(( -S |,)\w+)*(( -S |,){{ item }})+(( -S |,)\w+)*
          -F path=/usr/bin/su -F perm=x -F auid>=1000 -F auid!=unset (-k\s+|-F\s+key=)\S+\s*$
        patterns: '*.rules'
      register: find_command
      loop: '{{ (syscall_grouping + syscalls) | unique }}'

    - name: Reset syscalls found per file
      ansible.builtin.set_fact:
        syscalls_per_file: {}
        found_paths_dict: {}

    - name: Declare syscalls found per file
      ansible.builtin.set_fact: syscalls_per_file="{{ syscalls_per_file | combine(
        {item.files[0].path :[item.item] + syscalls_per_file.get(item.files[0].path,
        []) } ) }}"
      loop: '{{ find_command.results | selectattr(''matched'') | list }}'

    - name: Declare files where syscalls were found
      ansible.builtin.set_fact: found_paths="{{ find_command.results | map(attribute='files')
        | flatten | map(attribute='path') | list }}"

    - name: Count occurrences of syscalls in paths
      ansible.builtin.set_fact: found_paths_dict="{{ found_paths_dict | combine({
        item:1+found_paths_dict.get(item, 0) }) }}"
      loop: '{{ find_command.results | map(attribute=''files'') | flatten | map(attribute=''path'')
        | list }}'

    - name: Get path with most syscalls
      ansible.builtin.set_fact: audit_file="{{ (found_paths_dict | dict2items() |
        sort(attribute='value') | last).key }}"
      when: found_paths | length >= 1

    - name: No file with syscall found, set path to /etc/audit/rules.d/privileged.rules
      ansible.builtin.set_fact: audit_file="/etc/audit/rules.d/privileged.rules"
      when: found_paths | length == 0

    - name: Declare found syscalls
      ansible.builtin.set_fact: syscalls_found="{{ find_command.results | selectattr('matched')
        | map(attribute='item') | list }}"

    - name: Declare missing syscalls
      ansible.builtin.set_fact: missing_syscalls="{{ syscalls | difference(syscalls_found)
        }}"

    - name: Replace the audit rule in {{ audit_file }}
      ansible.builtin.lineinfile:
        path: '{{ audit_file }}'
        regexp: (-a always,exit)(?=.*(?:(?:-S |,)(?:{{ syscalls_per_file[audit_file]
          | join("|") }}))\b)((?:( -S |,)\w+)+)( -F path=/usr/bin/su -F perm=x -F
          auid>=1000 -F auid!=unset (?:-k |-F key=)\w+)
        line: \1\2\3{{ missing_syscalls | join("\3") }}\4
        backrefs: true
        state: present
        mode: g-rwx,o-rwx
      when: syscalls_found | length > 0 and missing_syscalls | length > 0

    - name: Add the audit rule to {{ audit_file }}
      ansible.builtin.lineinfile:
        path: '{{ audit_file }}'
        line: -a always,exit{{ syscalls | join(',') }} -F path=/usr/bin/su -F perm=x
          -F auid>=1000 -F auid!=unset -F key=privileged
        create: true
        mode: g-rwx,o-rwx
        state: present
      when: syscalls_found | length == 0

    - name: Declare list of syscalls
      ansible.builtin.set_fact:
        syscalls: []
        syscall_grouping: []

    - name: Check existence of  in /etc/audit/audit.rules
      ansible.builtin.find:
        paths: /etc/audit
        contains: -a always,exit(( -S |,)\w+)*(( -S |,){{ item }})+(( -S |,)\w+)*
          -F path=/usr/bin/su -F perm=x -F auid>=1000 -F auid!=unset (-k\s+|-F\s+key=)\S+\s*$
        patterns: audit.rules
      register: find_command
      loop: '{{ (syscall_grouping + syscalls) | unique }}'

    - name: Set path to /etc/audit/audit.rules
      ansible.builtin.set_fact: audit_file="/etc/audit/audit.rules"

    - name: Declare found syscalls
      ansible.builtin.set_fact: syscalls_found="{{ find_command.results | selectattr('matched')
        | map(attribute='item') | list }}"

    - name: Declare missing syscalls
      ansible.builtin.set_fact: missing_syscalls="{{ syscalls | difference(syscalls_found)
        }}"

    - name: Replace the audit rule in {{ audit_file }}
      ansible.builtin.lineinfile:
        path: '{{ audit_file }}'
        regexp: (-a always,exit)(?=.*(?:(?:-S |,)(?:{{ syscalls_found | join("|")
          }}))\b)((?:( -S |,)\w+)+)( -F path=/usr/bin/su -F perm=x -F auid>=1000 -F
          auid!=unset (?:-k |-F key=)\w+)
        line: \1\2\3{{ missing_syscalls | join("\3") }}\4
        backrefs: true
        state: present
        mode: g-rwx,o-rwx
      when: syscalls_found | length > 0 and missing_syscalls | length > 0

    - name: Add the audit rule to {{ audit_file }}
      ansible.builtin.lineinfile:
        path: '{{ audit_file }}'
        line: -a always,exit{{ syscalls | join(',') }} -F path=/usr/bin/su -F perm=x
          -F auid>=1000 -F auid!=unset -F key=privileged
        create: true
        mode: g-rwx,o-rwx
        state: present
      when: syscalls_found | length == 0
    when:
    - '"audit" in ansible_facts.packages'
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-000540
    - NIST-800-171-3.1.7
    - NIST-800-53-AC-6(9)
    - NIST-800-53-AU-12(c)
    - NIST-800-53-AU-2(d)
    - NIST-800-53-CM-6(a)
    - audit_rules_privileged_commands_su
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Ensure auditd Collects Information on the Use of Privileged Commands - sudo
      - Perform remediation of Audit rules for /usr/bin/sudo
    block:

    - name: Declare list of syscalls
      ansible.builtin.set_fact:
        syscalls: []
        syscall_grouping: []

    - name: Check existence of  in /etc/audit/rules.d/
      ansible.builtin.find:
        paths: /etc/audit/rules.d
        contains: -a always,exit(( -S |,)\w+)*(( -S |,){{ item }})+(( -S |,)\w+)*
          -F path=/usr/bin/sudo -F perm=x -F auid>=1000 -F auid!=unset (-k\s+|-F\s+key=)\S+\s*$
        patterns: '*.rules'
      register: find_command
      loop: '{{ (syscall_grouping + syscalls) | unique }}'

    - name: Reset syscalls found per file
      ansible.builtin.set_fact:
        syscalls_per_file: {}
        found_paths_dict: {}

    - name: Declare syscalls found per file
      ansible.builtin.set_fact: syscalls_per_file="{{ syscalls_per_file | combine(
        {item.files[0].path :[item.item] + syscalls_per_file.get(item.files[0].path,
        []) } ) }}"
      loop: '{{ find_command.results | selectattr(''matched'') | list }}'

    - name: Declare files where syscalls were found
      ansible.builtin.set_fact: found_paths="{{ find_command.results | map(attribute='files')
        | flatten | map(attribute='path') | list }}"

    - name: Count occurrences of syscalls in paths
      ansible.builtin.set_fact: found_paths_dict="{{ found_paths_dict | combine({
        item:1+found_paths_dict.get(item, 0) }) }}"
      loop: '{{ find_command.results | map(attribute=''files'') | flatten | map(attribute=''path'')
        | list }}'

    - name: Get path with most syscalls
      ansible.builtin.set_fact: audit_file="{{ (found_paths_dict | dict2items() |
        sort(attribute='value') | last).key }}"
      when: found_paths | length >= 1

    - name: No file with syscall found, set path to /etc/audit/rules.d/privileged.rules
      ansible.builtin.set_fact: audit_file="/etc/audit/rules.d/privileged.rules"
      when: found_paths | length == 0

    - name: Declare found syscalls
      ansible.builtin.set_fact: syscalls_found="{{ find_command.results | selectattr('matched')
        | map(attribute='item') | list }}"

    - name: Declare missing syscalls
      ansible.builtin.set_fact: missing_syscalls="{{ syscalls | difference(syscalls_found)
        }}"

    - name: Replace the audit rule in {{ audit_file }}
      ansible.builtin.lineinfile:
        path: '{{ audit_file }}'
        regexp: (-a always,exit)(?=.*(?:(?:-S |,)(?:{{ syscalls_per_file[audit_file]
          | join("|") }}))\b)((?:( -S |,)\w+)+)( -F path=/usr/bin/sudo -F perm=x -F
          auid>=1000 -F auid!=unset (?:-k |-F key=)\w+)
        line: \1\2\3{{ missing_syscalls | join("\3") }}\4
        backrefs: true
        state: present
        mode: g-rwx,o-rwx
      when: syscalls_found | length > 0 and missing_syscalls | length > 0

    - name: Add the audit rule to {{ audit_file }}
      ansible.builtin.lineinfile:
        path: '{{ audit_file }}'
        line: -a always,exit{{ syscalls | join(',') }} -F path=/usr/bin/sudo -F perm=x
          -F auid>=1000 -F auid!=unset -F key=privileged
        create: true
        mode: g-rwx,o-rwx
        state: present
      when: syscalls_found | length == 0

    - name: Declare list of syscalls
      ansible.builtin.set_fact:
        syscalls: []
        syscall_grouping: []

    - name: Check existence of  in /etc/audit/audit.rules
      ansible.builtin.find:
        paths: /etc/audit
        contains: -a always,exit(( -S |,)\w+)*(( -S |,){{ item }})+(( -S |,)\w+)*
          -F path=/usr/bin/sudo -F perm=x -F auid>=1000 -F auid!=unset (-k\s+|-F\s+key=)\S+\s*$
        patterns: audit.rules
      register: find_command
      loop: '{{ (syscall_grouping + syscalls) | unique }}'

    - name: Set path to /etc/audit/audit.rules
      ansible.builtin.set_fact: audit_file="/etc/audit/audit.rules"

    - name: Declare found syscalls
      ansible.builtin.set_fact: syscalls_found="{{ find_command.results | selectattr('matched')
        | map(attribute='item') | list }}"

    - name: Declare missing syscalls
      ansible.builtin.set_fact: missing_syscalls="{{ syscalls | difference(syscalls_found)
        }}"

    - name: Replace the audit rule in {{ audit_file }}
      ansible.builtin.lineinfile:
        path: '{{ audit_file }}'
        regexp: (-a always,exit)(?=.*(?:(?:-S |,)(?:{{ syscalls_found | join("|")
          }}))\b)((?:( -S |,)\w+)+)( -F path=/usr/bin/sudo -F perm=x -F auid>=1000
          -F auid!=unset (?:-k |-F key=)\w+)
        line: \1\2\3{{ missing_syscalls | join("\3") }}\4
        backrefs: true
        state: present
        mode: g-rwx,o-rwx
      when: syscalls_found | length > 0 and missing_syscalls | length > 0

    - name: Add the audit rule to {{ audit_file }}
      ansible.builtin.lineinfile:
        path: '{{ audit_file }}'
        line: -a always,exit{{ syscalls | join(',') }} -F path=/usr/bin/sudo -F perm=x
          -F auid>=1000 -F auid!=unset -F key=privileged
        create: true
        mode: g-rwx,o-rwx
        state: present
      when: syscalls_found | length == 0
    when:
    - '"audit" in ansible_facts.packages'
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-000670
    - NIST-800-171-3.1.7
    - NIST-800-53-AC-6(9)
    - NIST-800-53-AU-12(c)
    - NIST-800-53-AU-2(d)
    - NIST-800-53-CM-6(a)
    - audit_rules_privileged_commands_sudo
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Ensure auditd Collects Information on the Use of Privileged Commands - sudoedit
      - Perform remediation of Audit rules for /usr/bin/sudoedit
    block:

    - name: Declare list of syscalls
      ansible.builtin.set_fact:
        syscalls: []
        syscall_grouping: []

    - name: Check existence of  in /etc/audit/rules.d/
      ansible.builtin.find:
        paths: /etc/audit/rules.d
        contains: -a always,exit(( -S |,)\w+)*(( -S |,){{ item }})+(( -S |,)\w+)*
          -F path=/usr/bin/sudoedit -F perm=x -F auid>=1000 -F auid!=unset (-k\s+|-F\s+key=)\S+\s*$
        patterns: '*.rules'
      register: find_command
      loop: '{{ (syscall_grouping + syscalls) | unique }}'

    - name: Reset syscalls found per file
      ansible.builtin.set_fact:
        syscalls_per_file: {}
        found_paths_dict: {}

    - name: Declare syscalls found per file
      ansible.builtin.set_fact: syscalls_per_file="{{ syscalls_per_file | combine(
        {item.files[0].path :[item.item] + syscalls_per_file.get(item.files[0].path,
        []) } ) }}"
      loop: '{{ find_command.results | selectattr(''matched'') | list }}'

    - name: Declare files where syscalls were found
      ansible.builtin.set_fact: found_paths="{{ find_command.results | map(attribute='files')
        | flatten | map(attribute='path') | list }}"

    - name: Count occurrences of syscalls in paths
      ansible.builtin.set_fact: found_paths_dict="{{ found_paths_dict | combine({
        item:1+found_paths_dict.get(item, 0) }) }}"
      loop: '{{ find_command.results | map(attribute=''files'') | flatten | map(attribute=''path'')
        | list }}'

    - name: Get path with most syscalls
      ansible.builtin.set_fact: audit_file="{{ (found_paths_dict | dict2items() |
        sort(attribute='value') | last).key }}"
      when: found_paths | length >= 1

    - name: No file with syscall found, set path to /etc/audit/rules.d/privileged.rules
      ansible.builtin.set_fact: audit_file="/etc/audit/rules.d/privileged.rules"
      when: found_paths | length == 0

    - name: Declare found syscalls
      ansible.builtin.set_fact: syscalls_found="{{ find_command.results | selectattr('matched')
        | map(attribute='item') | list }}"

    - name: Declare missing syscalls
      ansible.builtin.set_fact: missing_syscalls="{{ syscalls | difference(syscalls_found)
        }}"

    - name: Replace the audit rule in {{ audit_file }}
      ansible.builtin.lineinfile:
        path: '{{ audit_file }}'
        regexp: (-a always,exit)(?=.*(?:(?:-S |,)(?:{{ syscalls_per_file[audit_file]
          | join("|") }}))\b)((?:( -S |,)\w+)+)( -F path=/usr/bin/sudoedit -F perm=x
          -F auid>=1000 -F auid!=unset (?:-k |-F key=)\w+)
        line: \1\2\3{{ missing_syscalls | join("\3") }}\4
        backrefs: true
        state: present
        mode: g-rwx,o-rwx
      when: syscalls_found | length > 0 and missing_syscalls | length > 0

    - name: Add the audit rule to {{ audit_file }}
      ansible.builtin.lineinfile:
        path: '{{ audit_file }}'
        line: -a always,exit{{ syscalls | join(',') }} -F path=/usr/bin/sudoedit -F
          perm=x -F auid>=1000 -F auid!=unset -F key=privileged
        create: true
        mode: g-rwx,o-rwx
        state: present
      when: syscalls_found | length == 0

    - name: Declare list of syscalls
      ansible.builtin.set_fact:
        syscalls: []
        syscall_grouping: []

    - name: Check existence of  in /etc/audit/audit.rules
      ansible.builtin.find:
        paths: /etc/audit
        contains: -a always,exit(( -S |,)\w+)*(( -S |,){{ item }})+(( -S |,)\w+)*
          -F path=/usr/bin/sudoedit -F perm=x -F auid>=1000 -F auid!=unset (-k\s+|-F\s+key=)\S+\s*$
        patterns: audit.rules
      register: find_command
      loop: '{{ (syscall_grouping + syscalls) | unique }}'

    - name: Set path to /etc/audit/audit.rules
      ansible.builtin.set_fact: audit_file="/etc/audit/audit.rules"

    - name: Declare found syscalls
      ansible.builtin.set_fact: syscalls_found="{{ find_command.results | selectattr('matched')
        | map(attribute='item') | list }}"

    - name: Declare missing syscalls
      ansible.builtin.set_fact: missing_syscalls="{{ syscalls | difference(syscalls_found)
        }}"

    - name: Replace the audit rule in {{ audit_file }}
      ansible.builtin.lineinfile:
        path: '{{ audit_file }}'
        regexp: (-a always,exit)(?=.*(?:(?:-S |,)(?:{{ syscalls_found | join("|")
          }}))\b)((?:( -S |,)\w+)+)( -F path=/usr/bin/sudoedit -F perm=x -F auid>=1000
          -F auid!=unset (?:-k |-F key=)\w+)
        line: \1\2\3{{ missing_syscalls | join("\3") }}\4
        backrefs: true
        state: present
        mode: g-rwx,o-rwx
      when: syscalls_found | length > 0 and missing_syscalls | length > 0

    - name: Add the audit rule to {{ audit_file }}
      ansible.builtin.lineinfile:
        path: '{{ audit_file }}'
        line: -a always,exit{{ syscalls | join(',') }} -F path=/usr/bin/sudoedit -F
          perm=x -F auid>=1000 -F auid!=unset -F key=privileged
        create: true
        mode: g-rwx,o-rwx
        state: present
      when: syscalls_found | length == 0
    when:
    - '"audit" in ansible_facts.packages'
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-000615
    - NIST-800-171-3.1.7
    - NIST-800-53-AC-6(9)
    - NIST-800-53-AU-12(c)
    - NIST-800-53-AU-2(d)
    - NIST-800-53-CM-6(a)
    - audit_rules_privileged_commands_sudoedit
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Ensure auditd Collects Information on the Use of Privileged Commands - umount
      - Perform remediation of Audit rules for /usr/bin/umount
    block:

    - name: Declare list of syscalls
      ansible.builtin.set_fact:
        syscalls: []
        syscall_grouping: []

    - name: Check existence of  in /etc/audit/rules.d/
      ansible.builtin.find:
        paths: /etc/audit/rules.d
        contains: -a always,exit(( -S |,)\w+)*(( -S |,){{ item }})+(( -S |,)\w+)*
          -F path=/usr/bin/umount -F perm=x -F auid>=1000 -F auid!=unset (-k\s+|-F\s+key=)\S+\s*$
        patterns: '*.rules'
      register: find_command
      loop: '{{ (syscall_grouping + syscalls) | unique }}'

    - name: Reset syscalls found per file
      ansible.builtin.set_fact:
        syscalls_per_file: {}
        found_paths_dict: {}

    - name: Declare syscalls found per file
      ansible.builtin.set_fact: syscalls_per_file="{{ syscalls_per_file | combine(
        {item.files[0].path :[item.item] + syscalls_per_file.get(item.files[0].path,
        []) } ) }}"
      loop: '{{ find_command.results | selectattr(''matched'') | list }}'

    - name: Declare files where syscalls were found
      ansible.builtin.set_fact: found_paths="{{ find_command.results | map(attribute='files')
        | flatten | map(attribute='path') | list }}"

    - name: Count occurrences of syscalls in paths
      ansible.builtin.set_fact: found_paths_dict="{{ found_paths_dict | combine({
        item:1+found_paths_dict.get(item, 0) }) }}"
      loop: '{{ find_command.results | map(attribute=''files'') | flatten | map(attribute=''path'')
        | list }}'

    - name: Get path with most syscalls
      ansible.builtin.set_fact: audit_file="{{ (found_paths_dict | dict2items() |
        sort(attribute='value') | last).key }}"
      when: found_paths | length >= 1

    - name: No file with syscall found, set path to /etc/audit/rules.d/privileged.rules
      ansible.builtin.set_fact: audit_file="/etc/audit/rules.d/privileged.rules"
      when: found_paths | length == 0

    - name: Declare found syscalls
      ansible.builtin.set_fact: syscalls_found="{{ find_command.results | selectattr('matched')
        | map(attribute='item') | list }}"

    - name: Declare missing syscalls
      ansible.builtin.set_fact: missing_syscalls="{{ syscalls | difference(syscalls_found)
        }}"

    - name: Replace the audit rule in {{ audit_file }}
      ansible.builtin.lineinfile:
        path: '{{ audit_file }}'
        regexp: (-a always,exit)(?=.*(?:(?:-S |,)(?:{{ syscalls_per_file[audit_file]
          | join("|") }}))\b)((?:( -S |,)\w+)+)( -F path=/usr/bin/umount -F perm=x
          -F auid>=1000 -F auid!=unset (?:-k |-F key=)\w+)
        line: \1\2\3{{ missing_syscalls | join("\3") }}\4
        backrefs: true
        state: present
        mode: g-rwx,o-rwx
      when: syscalls_found | length > 0 and missing_syscalls | length > 0

    - name: Add the audit rule to {{ audit_file }}
      ansible.builtin.lineinfile:
        path: '{{ audit_file }}'
        line: -a always,exit{{ syscalls | join(',') }} -F path=/usr/bin/umount -F
          perm=x -F auid>=1000 -F auid!=unset -F key=privileged
        create: true
        mode: g-rwx,o-rwx
        state: present
      when: syscalls_found | length == 0

    - name: Declare list of syscalls
      ansible.builtin.set_fact:
        syscalls: []
        syscall_grouping: []

    - name: Check existence of  in /etc/audit/audit.rules
      ansible.builtin.find:
        paths: /etc/audit
        contains: -a always,exit(( -S |,)\w+)*(( -S |,){{ item }})+(( -S |,)\w+)*
          -F path=/usr/bin/umount -F perm=x -F auid>=1000 -F auid!=unset (-k\s+|-F\s+key=)\S+\s*$
        patterns: audit.rules
      register: find_command
      loop: '{{ (syscall_grouping + syscalls) | unique }}'

    - name: Set path to /etc/audit/audit.rules
      ansible.builtin.set_fact: audit_file="/etc/audit/audit.rules"

    - name: Declare found syscalls
      ansible.builtin.set_fact: syscalls_found="{{ find_command.results | selectattr('matched')
        | map(attribute='item') | list }}"

    - name: Declare missing syscalls
      ansible.builtin.set_fact: missing_syscalls="{{ syscalls | difference(syscalls_found)
        }}"

    - name: Replace the audit rule in {{ audit_file }}
      ansible.builtin.lineinfile:
        path: '{{ audit_file }}'
        regexp: (-a always,exit)(?=.*(?:(?:-S |,)(?:{{ syscalls_found | join("|")
          }}))\b)((?:( -S |,)\w+)+)( -F path=/usr/bin/umount -F perm=x -F auid>=1000
          -F auid!=unset (?:-k |-F key=)\w+)
        line: \1\2\3{{ missing_syscalls | join("\3") }}\4
        backrefs: true
        state: present
        mode: g-rwx,o-rwx
      when: syscalls_found | length > 0 and missing_syscalls | length > 0

    - name: Add the audit rule to {{ audit_file }}
      ansible.builtin.lineinfile:
        path: '{{ audit_file }}'
        line: -a always,exit{{ syscalls | join(',') }} -F path=/usr/bin/umount -F
          perm=x -F auid>=1000 -F auid!=unset -F key=privileged
        create: true
        mode: g-rwx,o-rwx
        state: present
      when: syscalls_found | length == 0
    when:
    - '"audit" in ansible_facts.packages'
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-000705
    - NIST-800-171-3.1.7
    - NIST-800-53-AC-6(9)
    - NIST-800-53-AU-12(c)
    - NIST-800-53-AU-2(d)
    - NIST-800-53-CM-6(a)
    - audit_rules_privileged_commands_umount
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Ensure auditd Collects Information on the Use of Privileged Commands - unix_chkpwd
      - Perform remediation of Audit rules for /usr/sbin/unix_chkpwd
    block:

    - name: Declare list of syscalls
      ansible.builtin.set_fact:
        syscalls: []
        syscall_grouping: []

    - name: Check existence of  in /etc/audit/rules.d/
      ansible.builtin.find:
        paths: /etc/audit/rules.d
        contains: -a always,exit(( -S |,)\w+)*(( -S |,){{ item }})+(( -S |,)\w+)*
          -F path=/usr/sbin/unix_chkpwd -F perm=x -F auid>=1000 -F auid!=unset (-k\s+|-F\s+key=)\S+\s*$
        patterns: '*.rules'
      register: find_command
      loop: '{{ (syscall_grouping + syscalls) | unique }}'

    - name: Reset syscalls found per file
      ansible.builtin.set_fact:
        syscalls_per_file: {}
        found_paths_dict: {}

    - name: Declare syscalls found per file
      ansible.builtin.set_fact: syscalls_per_file="{{ syscalls_per_file | combine(
        {item.files[0].path :[item.item] + syscalls_per_file.get(item.files[0].path,
        []) } ) }}"
      loop: '{{ find_command.results | selectattr(''matched'') | list }}'

    - name: Declare files where syscalls were found
      ansible.builtin.set_fact: found_paths="{{ find_command.results | map(attribute='files')
        | flatten | map(attribute='path') | list }}"

    - name: Count occurrences of syscalls in paths
      ansible.builtin.set_fact: found_paths_dict="{{ found_paths_dict | combine({
        item:1+found_paths_dict.get(item, 0) }) }}"
      loop: '{{ find_command.results | map(attribute=''files'') | flatten | map(attribute=''path'')
        | list }}'

    - name: Get path with most syscalls
      ansible.builtin.set_fact: audit_file="{{ (found_paths_dict | dict2items() |
        sort(attribute='value') | last).key }}"
      when: found_paths | length >= 1

    - name: No file with syscall found, set path to /etc/audit/rules.d/privileged.rules
      ansible.builtin.set_fact: audit_file="/etc/audit/rules.d/privileged.rules"
      when: found_paths | length == 0

    - name: Declare found syscalls
      ansible.builtin.set_fact: syscalls_found="{{ find_command.results | selectattr('matched')
        | map(attribute='item') | list }}"

    - name: Declare missing syscalls
      ansible.builtin.set_fact: missing_syscalls="{{ syscalls | difference(syscalls_found)
        }}"

    - name: Replace the audit rule in {{ audit_file }}
      ansible.builtin.lineinfile:
        path: '{{ audit_file }}'
        regexp: (-a always,exit)(?=.*(?:(?:-S |,)(?:{{ syscalls_per_file[audit_file]
          | join("|") }}))\b)((?:( -S |,)\w+)+)( -F path=/usr/sbin/unix_chkpwd -F
          perm=x -F auid>=1000 -F auid!=unset (?:-k |-F key=)\w+)
        line: \1\2\3{{ missing_syscalls | join("\3") }}\4
        backrefs: true
        state: present
        mode: g-rwx,o-rwx
      when: syscalls_found | length > 0 and missing_syscalls | length > 0

    - name: Add the audit rule to {{ audit_file }}
      ansible.builtin.lineinfile:
        path: '{{ audit_file }}'
        line: -a always,exit{{ syscalls | join(',') }} -F path=/usr/sbin/unix_chkpwd
          -F perm=x -F auid>=1000 -F auid!=unset -F key=privileged
        create: true
        mode: g-rwx,o-rwx
        state: present
      when: syscalls_found | length == 0

    - name: Declare list of syscalls
      ansible.builtin.set_fact:
        syscalls: []
        syscall_grouping: []

    - name: Check existence of  in /etc/audit/audit.rules
      ansible.builtin.find:
        paths: /etc/audit
        contains: -a always,exit(( -S |,)\w+)*(( -S |,){{ item }})+(( -S |,)\w+)*
          -F path=/usr/sbin/unix_chkpwd -F perm=x -F auid>=1000 -F auid!=unset (-k\s+|-F\s+key=)\S+\s*$
        patterns: audit.rules
      register: find_command
      loop: '{{ (syscall_grouping + syscalls) | unique }}'

    - name: Set path to /etc/audit/audit.rules
      ansible.builtin.set_fact: audit_file="/etc/audit/audit.rules"

    - name: Declare found syscalls
      ansible.builtin.set_fact: syscalls_found="{{ find_command.results | selectattr('matched')
        | map(attribute='item') | list }}"

    - name: Declare missing syscalls
      ansible.builtin.set_fact: missing_syscalls="{{ syscalls | difference(syscalls_found)
        }}"

    - name: Replace the audit rule in {{ audit_file }}
      ansible.builtin.lineinfile:
        path: '{{ audit_file }}'
        regexp: (-a always,exit)(?=.*(?:(?:-S |,)(?:{{ syscalls_found | join("|")
          }}))\b)((?:( -S |,)\w+)+)( -F path=/usr/sbin/unix_chkpwd -F perm=x -F auid>=1000
          -F auid!=unset (?:-k |-F key=)\w+)
        line: \1\2\3{{ missing_syscalls | join("\3") }}\4
        backrefs: true
        state: present
        mode: g-rwx,o-rwx
      when: syscalls_found | length > 0 and missing_syscalls | length > 0

    - name: Add the audit rule to {{ audit_file }}
      ansible.builtin.lineinfile:
        path: '{{ audit_file }}'
        line: -a always,exit{{ syscalls | join(',') }} -F path=/usr/sbin/unix_chkpwd
          -F perm=x -F auid>=1000 -F auid!=unset -F key=privileged
        create: true
        mode: g-rwx,o-rwx
        state: present
      when: syscalls_found | length == 0
    when:
    - '"audit" in ansible_facts.packages'
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-000620
    - NIST-800-171-3.1.7
    - NIST-800-53-AC-2(4)
    - NIST-800-53-AC-6(9)
    - NIST-800-53-AU-12(a)
    - NIST-800-53-AU-12(c)
    - NIST-800-53-AU-12.1(ii)
    - NIST-800-53-AU-12.1(iv)
    - NIST-800-53-AU-2(d)
    - NIST-800-53-AU-3
    - NIST-800-53-AU-3.1
    - NIST-800-53-CM-6(a)
    - NIST-800-53-MA-4(1)(a)
    - audit_rules_privileged_commands_unix_chkpwd
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Ensure auditd Collects Information on the Use of Privileged Commands - unix_update
      - Perform remediation of Audit rules for /usr/sbin/unix_update
    block:

    - name: Declare list of syscalls
      ansible.builtin.set_fact:
        syscalls: []
        syscall_grouping: []

    - name: Check existence of  in /etc/audit/rules.d/
      ansible.builtin.find:
        paths: /etc/audit/rules.d
        contains: -a always,exit(( -S |,)\w+)*(( -S |,){{ item }})+(( -S |,)\w+)*
          -F path=/usr/sbin/unix_update -F perm=x -F auid>=1000 -F auid!=unset (-k\s+|-F\s+key=)\S+\s*$
        patterns: '*.rules'
      register: find_command
      loop: '{{ (syscall_grouping + syscalls) | unique }}'

    - name: Reset syscalls found per file
      ansible.builtin.set_fact:
        syscalls_per_file: {}
        found_paths_dict: {}

    - name: Declare syscalls found per file
      ansible.builtin.set_fact: syscalls_per_file="{{ syscalls_per_file | combine(
        {item.files[0].path :[item.item] + syscalls_per_file.get(item.files[0].path,
        []) } ) }}"
      loop: '{{ find_command.results | selectattr(''matched'') | list }}'

    - name: Declare files where syscalls were found
      ansible.builtin.set_fact: found_paths="{{ find_command.results | map(attribute='files')
        | flatten | map(attribute='path') | list }}"

    - name: Count occurrences of syscalls in paths
      ansible.builtin.set_fact: found_paths_dict="{{ found_paths_dict | combine({
        item:1+found_paths_dict.get(item, 0) }) }}"
      loop: '{{ find_command.results | map(attribute=''files'') | flatten | map(attribute=''path'')
        | list }}'

    - name: Get path with most syscalls
      ansible.builtin.set_fact: audit_file="{{ (found_paths_dict | dict2items() |
        sort(attribute='value') | last).key }}"
      when: found_paths | length >= 1

    - name: No file with syscall found, set path to /etc/audit/rules.d/privileged.rules
      ansible.builtin.set_fact: audit_file="/etc/audit/rules.d/privileged.rules"
      when: found_paths | length == 0

    - name: Declare found syscalls
      ansible.builtin.set_fact: syscalls_found="{{ find_command.results | selectattr('matched')
        | map(attribute='item') | list }}"

    - name: Declare missing syscalls
      ansible.builtin.set_fact: missing_syscalls="{{ syscalls | difference(syscalls_found)
        }}"

    - name: Replace the audit rule in {{ audit_file }}
      ansible.builtin.lineinfile:
        path: '{{ audit_file }}'
        regexp: (-a always,exit)(?=.*(?:(?:-S |,)(?:{{ syscalls_per_file[audit_file]
          | join("|") }}))\b)((?:( -S |,)\w+)+)( -F path=/usr/sbin/unix_update -F
          perm=x -F auid>=1000 -F auid!=unset (?:-k |-F key=)\w+)
        line: \1\2\3{{ missing_syscalls | join("\3") }}\4
        backrefs: true
        state: present
        mode: g-rwx,o-rwx
      when: syscalls_found | length > 0 and missing_syscalls | length > 0

    - name: Add the audit rule to {{ audit_file }}
      ansible.builtin.lineinfile:
        path: '{{ audit_file }}'
        line: -a always,exit{{ syscalls | join(',') }} -F path=/usr/sbin/unix_update
          -F perm=x -F auid>=1000 -F auid!=unset -F key=privileged
        create: true
        mode: g-rwx,o-rwx
        state: present
      when: syscalls_found | length == 0

    - name: Declare list of syscalls
      ansible.builtin.set_fact:
        syscalls: []
        syscall_grouping: []

    - name: Check existence of  in /etc/audit/audit.rules
      ansible.builtin.find:
        paths: /etc/audit
        contains: -a always,exit(( -S |,)\w+)*(( -S |,){{ item }})+(( -S |,)\w+)*
          -F path=/usr/sbin/unix_update -F perm=x -F auid>=1000 -F auid!=unset (-k\s+|-F\s+key=)\S+\s*$
        patterns: audit.rules
      register: find_command
      loop: '{{ (syscall_grouping + syscalls) | unique }}'

    - name: Set path to /etc/audit/audit.rules
      ansible.builtin.set_fact: audit_file="/etc/audit/audit.rules"

    - name: Declare found syscalls
      ansible.builtin.set_fact: syscalls_found="{{ find_command.results | selectattr('matched')
        | map(attribute='item') | list }}"

    - name: Declare missing syscalls
      ansible.builtin.set_fact: missing_syscalls="{{ syscalls | difference(syscalls_found)
        }}"

    - name: Replace the audit rule in {{ audit_file }}
      ansible.builtin.lineinfile:
        path: '{{ audit_file }}'
        regexp: (-a always,exit)(?=.*(?:(?:-S |,)(?:{{ syscalls_found | join("|")
          }}))\b)((?:( -S |,)\w+)+)( -F path=/usr/sbin/unix_update -F perm=x -F auid>=1000
          -F auid!=unset (?:-k |-F key=)\w+)
        line: \1\2\3{{ missing_syscalls | join("\3") }}\4
        backrefs: true
        state: present
        mode: g-rwx,o-rwx
      when: syscalls_found | length > 0 and missing_syscalls | length > 0

    - name: Add the audit rule to {{ audit_file }}
      ansible.builtin.lineinfile:
        path: '{{ audit_file }}'
        line: -a always,exit{{ syscalls | join(',') }} -F path=/usr/sbin/unix_update
          -F perm=x -F auid>=1000 -F auid!=unset -F key=privileged
        create: true
        mode: g-rwx,o-rwx
        state: present
      when: syscalls_found | length == 0
    when:
    - '"audit" in ansible_facts.packages'
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-000535
    - audit_rules_privileged_commands_unix_update
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Ensure auditd Collects Information on the Use of Privileged Commands - userhelper
      - Perform remediation of Audit rules for /usr/sbin/userhelper
    block:

    - name: Declare list of syscalls
      ansible.builtin.set_fact:
        syscalls: []
        syscall_grouping: []

    - name: Check existence of  in /etc/audit/rules.d/
      ansible.builtin.find:
        paths: /etc/audit/rules.d
        contains: -a always,exit(( -S |,)\w+)*(( -S |,){{ item }})+(( -S |,)\w+)*
          -F path=/usr/sbin/userhelper -F perm=x -F auid>=1000 -F auid!=unset (-k\s+|-F\s+key=)\S+\s*$
        patterns: '*.rules'
      register: find_command
      loop: '{{ (syscall_grouping + syscalls) | unique }}'

    - name: Reset syscalls found per file
      ansible.builtin.set_fact:
        syscalls_per_file: {}
        found_paths_dict: {}

    - name: Declare syscalls found per file
      ansible.builtin.set_fact: syscalls_per_file="{{ syscalls_per_file | combine(
        {item.files[0].path :[item.item] + syscalls_per_file.get(item.files[0].path,
        []) } ) }}"
      loop: '{{ find_command.results | selectattr(''matched'') | list }}'

    - name: Declare files where syscalls were found
      ansible.builtin.set_fact: found_paths="{{ find_command.results | map(attribute='files')
        | flatten | map(attribute='path') | list }}"

    - name: Count occurrences of syscalls in paths
      ansible.builtin.set_fact: found_paths_dict="{{ found_paths_dict | combine({
        item:1+found_paths_dict.get(item, 0) }) }}"
      loop: '{{ find_command.results | map(attribute=''files'') | flatten | map(attribute=''path'')
        | list }}'

    - name: Get path with most syscalls
      ansible.builtin.set_fact: audit_file="{{ (found_paths_dict | dict2items() |
        sort(attribute='value') | last).key }}"
      when: found_paths | length >= 1

    - name: No file with syscall found, set path to /etc/audit/rules.d/privileged.rules
      ansible.builtin.set_fact: audit_file="/etc/audit/rules.d/privileged.rules"
      when: found_paths | length == 0

    - name: Declare found syscalls
      ansible.builtin.set_fact: syscalls_found="{{ find_command.results | selectattr('matched')
        | map(attribute='item') | list }}"

    - name: Declare missing syscalls
      ansible.builtin.set_fact: missing_syscalls="{{ syscalls | difference(syscalls_found)
        }}"

    - name: Replace the audit rule in {{ audit_file }}
      ansible.builtin.lineinfile:
        path: '{{ audit_file }}'
        regexp: (-a always,exit)(?=.*(?:(?:-S |,)(?:{{ syscalls_per_file[audit_file]
          | join("|") }}))\b)((?:( -S |,)\w+)+)( -F path=/usr/sbin/userhelper -F perm=x
          -F auid>=1000 -F auid!=unset (?:-k |-F key=)\w+)
        line: \1\2\3{{ missing_syscalls | join("\3") }}\4
        backrefs: true
        state: present
        mode: g-rwx,o-rwx
      when: syscalls_found | length > 0 and missing_syscalls | length > 0

    - name: Add the audit rule to {{ audit_file }}
      ansible.builtin.lineinfile:
        path: '{{ audit_file }}'
        line: -a always,exit{{ syscalls | join(',') }} -F path=/usr/sbin/userhelper
          -F perm=x -F auid>=1000 -F auid!=unset -F key=privileged
        create: true
        mode: g-rwx,o-rwx
        state: present
      when: syscalls_found | length == 0

    - name: Declare list of syscalls
      ansible.builtin.set_fact:
        syscalls: []
        syscall_grouping: []

    - name: Check existence of  in /etc/audit/audit.rules
      ansible.builtin.find:
        paths: /etc/audit
        contains: -a always,exit(( -S |,)\w+)*(( -S |,){{ item }})+(( -S |,)\w+)*
          -F path=/usr/sbin/userhelper -F perm=x -F auid>=1000 -F auid!=unset (-k\s+|-F\s+key=)\S+\s*$
        patterns: audit.rules
      register: find_command
      loop: '{{ (syscall_grouping + syscalls) | unique }}'

    - name: Set path to /etc/audit/audit.rules
      ansible.builtin.set_fact: audit_file="/etc/audit/audit.rules"

    - name: Declare found syscalls
      ansible.builtin.set_fact: syscalls_found="{{ find_command.results | selectattr('matched')
        | map(attribute='item') | list }}"

    - name: Declare missing syscalls
      ansible.builtin.set_fact: missing_syscalls="{{ syscalls | difference(syscalls_found)
        }}"

    - name: Replace the audit rule in {{ audit_file }}
      ansible.builtin.lineinfile:
        path: '{{ audit_file }}'
        regexp: (-a always,exit)(?=.*(?:(?:-S |,)(?:{{ syscalls_found | join("|")
          }}))\b)((?:( -S |,)\w+)+)( -F path=/usr/sbin/userhelper -F perm=x -F auid>=1000
          -F auid!=unset (?:-k |-F key=)\w+)
        line: \1\2\3{{ missing_syscalls | join("\3") }}\4
        backrefs: true
        state: present
        mode: g-rwx,o-rwx
      when: syscalls_found | length > 0 and missing_syscalls | length > 0

    - name: Add the audit rule to {{ audit_file }}
      ansible.builtin.lineinfile:
        path: '{{ audit_file }}'
        line: -a always,exit{{ syscalls | join(',') }} -F path=/usr/sbin/userhelper
          -F perm=x -F auid>=1000 -F auid!=unset -F key=privileged
        create: true
        mode: g-rwx,o-rwx
        state: present
      when: syscalls_found | length == 0
    when:
    - '"audit" in ansible_facts.packages'
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-000625
    - NIST-800-171-3.1.7
    - NIST-800-53-AC-6(9)
    - NIST-800-53-AU-12(c)
    - NIST-800-53-AU-2(d)
    - NIST-800-53-CM-6(a)
    - audit_rules_privileged_commands_userhelper
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Ensure auditd Collects Information on the Use of Privileged Commands - usermod
      - Perform remediation of Audit rules for /usr/sbin/usermod
    block:

    - name: Declare list of syscalls
      ansible.builtin.set_fact:
        syscalls: []
        syscall_grouping: []

    - name: Check existence of  in /etc/audit/rules.d/
      ansible.builtin.find:
        paths: /etc/audit/rules.d
        contains: -a always,exit(( -S |,)\w+)*(( -S |,){{ item }})+(( -S |,)\w+)*
          -F path=/usr/sbin/usermod -F perm=x -F auid>=1000 -F auid!=unset (-k\s+|-F\s+key=)\S+\s*$
        patterns: '*.rules'
      register: find_command
      loop: '{{ (syscall_grouping + syscalls) | unique }}'

    - name: Reset syscalls found per file
      ansible.builtin.set_fact:
        syscalls_per_file: {}
        found_paths_dict: {}

    - name: Declare syscalls found per file
      ansible.builtin.set_fact: syscalls_per_file="{{ syscalls_per_file | combine(
        {item.files[0].path :[item.item] + syscalls_per_file.get(item.files[0].path,
        []) } ) }}"
      loop: '{{ find_command.results | selectattr(''matched'') | list }}'

    - name: Declare files where syscalls were found
      ansible.builtin.set_fact: found_paths="{{ find_command.results | map(attribute='files')
        | flatten | map(attribute='path') | list }}"

    - name: Count occurrences of syscalls in paths
      ansible.builtin.set_fact: found_paths_dict="{{ found_paths_dict | combine({
        item:1+found_paths_dict.get(item, 0) }) }}"
      loop: '{{ find_command.results | map(attribute=''files'') | flatten | map(attribute=''path'')
        | list }}'

    - name: Get path with most syscalls
      ansible.builtin.set_fact: audit_file="{{ (found_paths_dict | dict2items() |
        sort(attribute='value') | last).key }}"
      when: found_paths | length >= 1

    - name: No file with syscall found, set path to /etc/audit/rules.d/privileged.rules
      ansible.builtin.set_fact: audit_file="/etc/audit/rules.d/privileged.rules"
      when: found_paths | length == 0

    - name: Declare found syscalls
      ansible.builtin.set_fact: syscalls_found="{{ find_command.results | selectattr('matched')
        | map(attribute='item') | list }}"

    - name: Declare missing syscalls
      ansible.builtin.set_fact: missing_syscalls="{{ syscalls | difference(syscalls_found)
        }}"

    - name: Replace the audit rule in {{ audit_file }}
      ansible.builtin.lineinfile:
        path: '{{ audit_file }}'
        regexp: (-a always,exit)(?=.*(?:(?:-S |,)(?:{{ syscalls_per_file[audit_file]
          | join("|") }}))\b)((?:( -S |,)\w+)+)( -F path=/usr/sbin/usermod -F perm=x
          -F auid>=1000 -F auid!=unset (?:-k |-F key=)\w+)
        line: \1\2\3{{ missing_syscalls | join("\3") }}\4
        backrefs: true
        state: present
        mode: g-rwx,o-rwx
      when: syscalls_found | length > 0 and missing_syscalls | length > 0

    - name: Add the audit rule to {{ audit_file }}
      ansible.builtin.lineinfile:
        path: '{{ audit_file }}'
        line: -a always,exit{{ syscalls | join(',') }} -F path=/usr/sbin/usermod -F
          perm=x -F auid>=1000 -F auid!=unset -F key=privileged
        create: true
        mode: g-rwx,o-rwx
        state: present
      when: syscalls_found | length == 0

    - name: Declare list of syscalls
      ansible.builtin.set_fact:
        syscalls: []
        syscall_grouping: []

    - name: Check existence of  in /etc/audit/audit.rules
      ansible.builtin.find:
        paths: /etc/audit
        contains: -a always,exit(( -S |,)\w+)*(( -S |,){{ item }})+(( -S |,)\w+)*
          -F path=/usr/sbin/usermod -F perm=x -F auid>=1000 -F auid!=unset (-k\s+|-F\s+key=)\S+\s*$
        patterns: audit.rules
      register: find_command
      loop: '{{ (syscall_grouping + syscalls) | unique }}'

    - name: Set path to /etc/audit/audit.rules
      ansible.builtin.set_fact: audit_file="/etc/audit/audit.rules"

    - name: Declare found syscalls
      ansible.builtin.set_fact: syscalls_found="{{ find_command.results | selectattr('matched')
        | map(attribute='item') | list }}"

    - name: Declare missing syscalls
      ansible.builtin.set_fact: missing_syscalls="{{ syscalls | difference(syscalls_found)
        }}"

    - name: Replace the audit rule in {{ audit_file }}
      ansible.builtin.lineinfile:
        path: '{{ audit_file }}'
        regexp: (-a always,exit)(?=.*(?:(?:-S |,)(?:{{ syscalls_found | join("|")
          }}))\b)((?:( -S |,)\w+)+)( -F path=/usr/sbin/usermod -F perm=x -F auid>=1000
          -F auid!=unset (?:-k |-F key=)\w+)
        line: \1\2\3{{ missing_syscalls | join("\3") }}\4
        backrefs: true
        state: present
        mode: g-rwx,o-rwx
      when: syscalls_found | length > 0 and missing_syscalls | length > 0

    - name: Add the audit rule to {{ audit_file }}
      ansible.builtin.lineinfile:
        path: '{{ audit_file }}'
        line: -a always,exit{{ syscalls | join(',') }} -F path=/usr/sbin/usermod -F
          perm=x -F auid>=1000 -F auid!=unset -F key=privileged
        create: true
        mode: g-rwx,o-rwx
        state: present
      when: syscalls_found | length == 0
    when:
    - '"audit" in ansible_facts.packages'
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-000675
    - audit_rules_privileged_commands_usermod
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Enable syslog plugin
    ansible.builtin.lineinfile:
      dest: /etc/audit/plugins.d/syslog.conf
      regexp: ^active
      line: active = yes
      create: true
    when:
    - '"audit" in ansible_facts.packages'
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - CJIS-5.4.1.1
    - DISA-STIG-OL09-00-000855
    - NIST-800-171-3.3.1
    - NIST-800-53-AU-4(1)
    - NIST-800-53-CM-6(a)
    - PCI-DSS-Req-10.5.3
    - PCI-DSSv4-10.3
    - PCI-DSSv4-10.3.3
    - auditd_audispd_syslog_plugin_activated
    - configure_strategy
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

  - name: Configure auditd Disk Error Action on Disk Error
    ansible.builtin.lineinfile:
      dest: /etc/audit/auditd.conf
      line: disk_error_action = {{ var_auditd_disk_error_action }}
      regexp: ^\s*disk_error_action\s*=\s*.*$
      state: present
      create: true
    when:
    - '"audit" in ansible_facts.packages'
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-000760
    - NIST-800-53-AU-5(1)
    - NIST-800-53-AU-5(2)
    - NIST-800-53-AU-5(4)
    - NIST-800-53-AU-5(b)
    - NIST-800-53-CM-6(a)
    - auditd_data_disk_error_action_stig
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Configure auditd Disk Full Action when Disk Space Is Full
    ansible.builtin.lineinfile:
      dest: /etc/audit/auditd.conf
      line: disk_full_action = {{ var_auditd_disk_full_action }}
      regexp: ^\s*disk_full_action\s*=\s*.*$
      state: present
      create: true
    when:
    - '"audit" in ansible_facts.packages'
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-000765
    - NIST-800-53-AU-5(1)
    - NIST-800-53-AU-5(2)
    - NIST-800-53-AU-5(4)
    - NIST-800-53-AU-5(b)
    - NIST-800-53-CM-6(a)
    - auditd_data_disk_full_action_stig
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Configure auditd mail_acct Action on Low Disk Space - Configure auditd mail_acct
      Action on Low Disk Space
    ansible.builtin.lineinfile:
      dest: /etc/audit/auditd.conf
      regexp: ^action_mail_acct
      line: action_mail_acct = {{ var_auditd_action_mail_acct }}
      state: present
      create: true
    when:
    - '"audit" in ansible_facts.packages'
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - CJIS-5.4.1.1
    - DISA-STIG-OL09-00-000825
    - NIST-800-171-3.3.1
    - NIST-800-53-AU-5(2)
    - NIST-800-53-AU-5(a)
    - NIST-800-53-CM-6(a)
    - NIST-800-53-IA-5(1)
    - PCI-DSS-Req-10.7.a
    - auditd_data_retention_action_mail_acct
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Configure auditd admin_space_left Action on Low Disk Space
    ansible.builtin.lineinfile:
      dest: /etc/audit/auditd.conf
      line: admin_space_left_action = {{ var_auditd_admin_space_left_action .split('|')[0]
        }}
      regexp: ^\s*admin_space_left_action\s*=\s*.*$
      state: present
      create: true
    when:
    - '"audit" in ansible_facts.packages'
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - CJIS-5.4.1.1
    - DISA-STIG-OL09-00-000885
    - NIST-800-171-3.3.1
    - NIST-800-53-AU-5(1)
    - NIST-800-53-AU-5(2)
    - NIST-800-53-AU-5(4)
    - NIST-800-53-AU-5(b)
    - NIST-800-53-CM-6(a)
    - PCI-DSS-Req-10.7
    - PCI-DSSv4-10.5
    - PCI-DSSv4-10.5.1
    - auditd_data_retention_admin_space_left_action
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Configure auditd admin_space_left on Low Disk Space
    ansible.builtin.lineinfile:
      dest: /etc/audit/auditd.conf
      line: admin_space_left = {{ var_auditd_admin_space_left_percentage }}%
      regexp: ^\s*admin_space_left\s*=\s*.*$
      state: present
      create: true
    when:
    - '"audit" in ansible_facts.packages'
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-000875
    - NIST-800-53-AU-5(1)
    - NIST-800-53-AU-5(2)
    - NIST-800-53-AU-5(4)
    - NIST-800-53-AU-5(b)
    - NIST-800-53-CM-6(a)
    - PCI-DSS-Req-10.7
    - auditd_data_retention_admin_space_left_percentage
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Configure auditd max_log_file_action Upon Reaching Maximum Log Size
    ansible.builtin.lineinfile:
      dest: /etc/audit/auditd.conf
      line: max_log_file_action = {{ var_auditd_max_log_file_action }}
      regexp: ^\s*max_log_file_action\s*=\s*.*$
      state: present
      create: true
    when:
    - '"audit" in ansible_facts.packages'
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-000770
    - NIST-800-53-AU-5(1)
    - NIST-800-53-AU-5(2)
    - NIST-800-53-AU-5(4)
    - NIST-800-53-AU-5(b)
    - NIST-800-53-CM-6(a)
    - PCI-DSS-Req-10.7
    - auditd_data_retention_max_log_file_action_stig
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Configure auditd space_left Action on Low Disk Space
    ansible.builtin.lineinfile:
      dest: /etc/audit/auditd.conf
      line: space_left_action = {{ var_auditd_space_left_action.split('|')[0] }}
      regexp: ^\s*space_left_action\s*=\s*.*$
      state: present
      create: true
    when:
    - '"audit" in ansible_facts.packages'
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - CJIS-5.4.1.1
    - DISA-STIG-OL09-00-000870
    - NIST-800-171-3.3.1
    - NIST-800-53-AU-5(1)
    - NIST-800-53-AU-5(2)
    - NIST-800-53-AU-5(4)
    - NIST-800-53-AU-5(b)
    - NIST-800-53-CM-6(a)
    - PCI-DSS-Req-10.7
    - PCI-DSSv4-10.5
    - PCI-DSSv4-10.5.1
    - auditd_data_retention_space_left_action
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Configure auditd space_left on Low Disk Space
    ansible.builtin.lineinfile:
      dest: /etc/audit/auditd.conf
      line: space_left = {{ var_auditd_space_left_percentage }}%
      regexp: ^\s*space_left\s*=\s*.*$
      state: present
      create: true
    when:
    - '"audit" in ansible_facts.packages'
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-000865
    - NIST-800-53-AU-5(1)
    - NIST-800-53-AU-5(2)
    - NIST-800-53-AU-5(4)
    - NIST-800-53-AU-5(b)
    - NIST-800-53-CM-6(a)
    - PCI-DSS-Req-10.7
    - auditd_data_retention_space_left_percentage
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Set number of records to cause an explicit flush to audit logs
    block:

    - name: Check for duplicate values
      ansible.builtin.lineinfile:
        path: /etc/audit/auditd.conf
        create: true
        regexp: (?i)(?i)^\s*freq\s*=\s*
        state: absent
      check_mode: true
      changed_when: false
      register: dupes

    - name: Deduplicate values from /etc/audit/auditd.conf
      ansible.builtin.lineinfile:
        path: /etc/audit/auditd.conf
        create: true
        regexp: (?i)(?i)^\s*freq\s*=\s*
        state: absent
      when: dupes.found is defined and dupes.found > 1

    - name: Insert correct line to /etc/audit/auditd.conf
      ansible.builtin.lineinfile:
        path: /etc/audit/auditd.conf
        create: true
        regexp: (?i)(?i)^\s*freq\s*=\s*
        line: freq = {{ var_auditd_freq }}
        state: present
    when:
    - '"audit" in ansible_facts.packages'
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-000775
    - NIST-800-53-CM-6
    - auditd_freq
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Include Local Events in Audit Logs
    block:

    - name: Check for duplicate values
      ansible.builtin.lineinfile:
        path: /etc/audit/auditd.conf
        create: true
        regexp: (?i)(?i)^\s*local_events\s*=\s*
        state: absent
      check_mode: true
      changed_when: false
      register: dupes

    - name: Deduplicate values from /etc/audit/auditd.conf
      ansible.builtin.lineinfile:
        path: /etc/audit/auditd.conf
        create: true
        regexp: (?i)(?i)^\s*local_events\s*=\s*
        state: absent
      when: dupes.found is defined and dupes.found > 1

    - name: Insert correct line to /etc/audit/auditd.conf
      ansible.builtin.lineinfile:
        path: /etc/audit/auditd.conf
        create: true
        regexp: (?i)(?i)^\s*local_events\s*=\s*
        line: local_events = yes
        state: present
    when:
    - '"audit" in ansible_facts.packages'
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-000800
    - NIST-800-53-CM-6
    - auditd_local_events
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Resolve information before writing to audit logs
    block:

    - name: Check for duplicate values
      ansible.builtin.lineinfile:
        path: /etc/audit/auditd.conf
        create: true
        regexp: (?i)(?i)^\s*log_format\s*=\s*
        state: absent
      check_mode: true
      changed_when: false
      register: dupes

    - name: Deduplicate values from /etc/audit/auditd.conf
      ansible.builtin.lineinfile:
        path: /etc/audit/auditd.conf
        create: true
        regexp: (?i)(?i)^\s*log_format\s*=\s*
        state: absent
      when: dupes.found is defined and dupes.found > 1

    - name: Insert correct line to /etc/audit/auditd.conf
      ansible.builtin.lineinfile:
        path: /etc/audit/auditd.conf
        create: true
        regexp: (?i)(?i)^\s*log_format\s*=\s*
        line: log_format = ENRICHED
        state: present
    when:
    - '"audit" in ansible_facts.packages'
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-000835
    - NIST-800-53-AU-3
    - NIST-800-53-CM-6
    - auditd_log_format
    - low_complexity
    - low_disruption
    - low_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Set type of computer node name logging in audit logs - Define Value to Be
      Used in the Remediation
    ansible.builtin.set_fact: auditd_name_format_split="{{ var_auditd_name_format.split('|')[0]
      }}"
    when:
    - '"audit" in ansible_facts.packages'
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-000755
    - NIST-800-53-AU-3
    - NIST-800-53-CM-6
    - PCI-DSSv4-10.2
    - PCI-DSSv4-10.2.2
    - auditd_name_format
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Set type of computer node name logging in audit logs
    block:

    - name: Check for duplicate values
      ansible.builtin.lineinfile:
        path: /etc/audit/auditd.conf
        create: true
        regexp: (?i)(?i)^\s*name_format\s*=\s*
        state: absent
      check_mode: true
      changed_when: false
      register: dupes

    - name: Deduplicate values from /etc/audit/auditd.conf
      ansible.builtin.lineinfile:
        path: /etc/audit/auditd.conf
        create: true
        regexp: (?i)(?i)^\s*name_format\s*=\s*
        state: absent
      when: dupes.found is defined and dupes.found > 1

    - name: Insert correct line to /etc/audit/auditd.conf
      ansible.builtin.lineinfile:
        path: /etc/audit/auditd.conf
        create: true
        regexp: (?i)(?i)^\s*name_format\s*=\s*
        line: name_format = {{ auditd_name_format_split }}
        state: present
    when:
    - '"audit" in ansible_facts.packages'
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-000755
    - NIST-800-53-AU-3
    - NIST-800-53-CM-6
    - PCI-DSSv4-10.2
    - PCI-DSSv4-10.2.2
    - auditd_name_format
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Appropriate Action Must be Setup When the Internal Audit Event Queue is
      Full
    block:

    - name: Check for duplicate values
      ansible.builtin.lineinfile:
        path: /etc/audit/auditd.conf
        create: true
        regexp: (?i)(?i)^\s*overflow_action\s*=\s*
        state: absent
      check_mode: true
      changed_when: false
      register: dupes

    - name: Deduplicate values from /etc/audit/auditd.conf
      ansible.builtin.lineinfile:
        path: /etc/audit/auditd.conf
        create: true
        regexp: (?i)(?i)^\s*overflow_action\s*=\s*
        state: absent
      when: dupes.found is defined and dupes.found > 1

    - name: Insert correct line to /etc/audit/auditd.conf
      ansible.builtin.lineinfile:
        path: /etc/audit/auditd.conf
        create: true
        regexp: (?i)(?i)^\s*overflow_action\s*=\s*
        line: overflow_action = syslog
        state: present
    when:
    - '"audit" in ansible_facts.packages'
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-000860
    - NIST-800-53-AU-4(1)
    - auditd_overflow_action
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Write Audit Logs to the Disk
    block:

    - name: Check for duplicate values
      ansible.builtin.lineinfile:
        path: /etc/audit/auditd.conf
        create: true
        regexp: (?i)(?i)^\s*write_logs\s*=\s*
        state: absent
      check_mode: true
      changed_when: false
      register: dupes

    - name: Deduplicate values from /etc/audit/auditd.conf
      ansible.builtin.lineinfile:
        path: /etc/audit/auditd.conf
        create: true
        regexp: (?i)(?i)^\s*write_logs\s*=\s*
        state: absent
      when: dupes.found is defined and dupes.found > 1

    - name: Insert correct line to /etc/audit/auditd.conf
      ansible.builtin.lineinfile:
        path: /etc/audit/auditd.conf
        create: true
        regexp: (?i)(?i)^\s*write_logs\s*=\s*
        line: write_logs = yes
        state: present
    when:
    - '"audit" in ansible_facts.packages'
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-000880
    - NIST-800-53-CM-6
    - auditd_write_logs
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Test for existence /etc/audit/auditd.conf
    ansible.builtin.stat:
      path: /etc/audit/auditd.conf
    register: file_exists
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-000810
    - NIST-800-53-AU-12(b)
    - configure_strategy
    - file_permissions_etc_audit_auditd
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

  - name: Ensure permission u-xs,g-xws,o-xwrt on /etc/audit/auditd.conf
    ansible.builtin.file:
      path: /etc/audit/auditd.conf
      mode: u-xs,g-xws,o-xwrt
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - file_exists.stat is defined and file_exists.stat.exists
    tags:
    - DISA-STIG-OL09-00-000810
    - NIST-800-53-AU-12(b)
    - configure_strategy
    - file_permissions_etc_audit_auditd
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

Youez - 2016 - github.com/yon3zu
LinuXploit