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-pci-dss.yml
---
###############################################################################
#
# Ansible Playbook for PCI-DSS v4.0 Control Baseline for Oracle Linux 9
#
# Profile Description:
# Payment Card Industry - Data Security Standard (PCI-DSS) is a set of
# security standards designed to ensure the secure handling of payment card
# data, with the goal of preventing data breaches and protecting sensitive
# financial information.
# This profile ensures Oracle Linux 9 is configured in alignment
# with PCI-DSS v4.0 requirements.
#
# Profile ID:  xccdf_org.ssgproject.content_profile_pci-dss
# 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_pci-dss --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_pci-dss
  hosts: all
  vars:
    var_system_crypto_policy: DEFAULT
    inactivity_timeout_value: '900'
    var_screensaver_lock_delay: '10'
    var_sudo_logfile: /var/log/sudo.log
    var_sudo_timestamp_timeout: '5'
    var_authselect_profile: sssd
    var_password_pam_remember: '4'
    var_password_pam_remember_control_flag: requisite,required
    var_password_pam_unix_remember: '4'
    var_accounts_passwords_pam_faillock_deny: '10'
    var_accounts_passwords_pam_faillock_unlock_time: '1800'
    var_password_pam_dcredit: '-1'
    var_password_pam_lcredit: '-1'
    var_password_pam_minlen: '12'
    var_password_hashing_algorithm_pam: sha512
    var_password_hashing_algorithm: SHA512
    var_account_disable_post_pw_expiration: '90'
    var_accounts_maximum_age_login_defs: '90'
    var_accounts_password_warn_age_login_defs: '7'
    var_accounts_tmout: '600'
    sysctl_net_ipv6_conf_default_accept_source_route_value: '0'
    sysctl_net_ipv4_conf_all_rp_filter_value: '1'
    sysctl_net_ipv4_conf_all_secure_redirects_value: '0'
    sysctl_net_ipv4_conf_default_accept_redirects_value: '0'
    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_selinux_policy_name: targeted
    var_selinux_state: enforcing
    var_postfix_inet_interfaces: loopback-only
    var_multiple_time_servers: 0.pool.ntp.org,1.pool.ntp.org,2.pool.ntp.org,3.pool.ntp.org
    var_sshd_set_keepalive: '1'
    sshd_idle_timeout_value: '900'
    var_sshd_set_login_grace_time: '60'
    sshd_max_auth_tries_value: '4'
    var_sshd_max_sessions: '10'
    var_sshd_set_maxstartups: 10:30:100
    var_audit_backlog_limit: '8192'
    var_accounts_passwords_pam_faillock_dir: /var/log/faillock
    var_auditd_admin_space_left_action: single
    var_auditd_space_left: '100'
    var_auditd_space_left_action: email
    var_auditd_name_format: fqd
  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 Periodic Execution of AIDE - 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
    - NIST-800-53-CM-6(a)
    - NIST-800-53-SI-7
    - NIST-800-53-SI-7(1)
    - PCI-DSS-Req-11.5
    - PCI-DSSv4-11.5.2
    - aide_periodic_cron_checking
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Configure Periodic Execution of AIDE - Install cron
    ansible.builtin.package:
      name: cronie
      state: present
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - CJIS-5.10.1.3
    - NIST-800-53-CM-6(a)
    - NIST-800-53-SI-7
    - NIST-800-53-SI-7(1)
    - PCI-DSS-Req-11.5
    - PCI-DSSv4-11.5.2
    - aide_periodic_cron_checking
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - 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: 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: Ensure logrotate is installed
    ansible.builtin.package:
      name: logrotate
      state: present
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - NIST-800-53-CM-6(a)
    - PCI-DSS-Req-10.7
    - PCI-DSSv4-10.5
    - PCI-DSSv4-10.5.1
    - enable_strategy
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - package_logrotate_installed

  - name: Prevent non-Privileged Users from Modifying Network Interfaces using nmcli
      - Ensure polkit-pkla-compat is installed
    ansible.builtin.package:
      name: polkit-pkla-compat
      state: present
    when: '"polkit" in ansible_facts.packages'
    tags:
    - NIST-800-171-3.1.16
    - NIST-800-53-AC-18(4)
    - NIST-800-53-CM-6(a)
    - PCI-DSSv4-1.2
    - PCI-DSSv4-1.2.8
    - low_complexity
    - low_disruption
    - medium_severity
    - network_nmcli_permissions
    - no_reboot_needed
    - restrict_strategy

  - 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: Configure Firewalld to Restrict Loopback Traffic - Ensure firewalld Package
      is Installed
    ansible.builtin.package:
      name: '{{ item }}'
      state: present
    with_items:
    - firewalld
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - PCI-DSSv4-1.4
    - PCI-DSSv4-1.4.1
    - configure_strategy
    - firewalld_loopback_traffic_restricted
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

  - name: Configure Firewalld to Trust Loopback Traffic - Ensure firewalld Package
      is Installed
    ansible.builtin.package:
      name: '{{ item }}'
      state: present
    with_items:
    - firewalld
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - PCI-DSSv4-1.4
    - PCI-DSSv4-1.4.1
    - configure_strategy
    - firewalld_loopback_traffic_trusted
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

  - name: Ensure nftables is installed
    ansible.builtin.package:
      name: nftables
      state: present
    when: ( ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
      )
    tags:
    - PCI-DSSv4-1.2
    - PCI-DSSv4-1.2.1
    - enable_strategy
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - package_nftables_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 libselinux is installed
    ansible.builtin.package:
      name: libselinux
      state: present
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - PCI-DSSv4-1.2
    - PCI-DSSv4-1.2.6
    - enable_strategy
    - high_severity
    - low_complexity
    - low_disruption
    - no_reboot_needed
    - package_libselinux_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: 'Uninstall DHCP Server Package: Ensure dhcp is removed'
    ansible.builtin.package:
      name: dhcp
      state: absent
    tags:
    - 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
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - package_dhcp_removed

  - name: 'Remove ftp Package: Ensure ftp is removed'
    ansible.builtin.package:
      name: ftp
      state: absent
    tags:
    - PCI-DSSv4-2.2
    - PCI-DSSv4-2.2.4
    - disable_strategy
    - low_complexity
    - low_disruption
    - low_severity
    - no_reboot_needed
    - package_ftp_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: 'Remove telnet Clients: Ensure telnet is removed'
    ansible.builtin.package:
      name: telnet
      state: absent
    tags:
    - NIST-800-171-3.1.13
    - PCI-DSSv4-2.2
    - PCI-DSSv4-2.2.4
    - disable_strategy
    - low_complexity
    - low_disruption
    - low_severity
    - no_reboot_needed
    - package_telnet_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: 'Remove tftp Daemon: Ensure tftp is removed'
    ansible.builtin.package:
      name: tftp
      state: absent
    tags:
    - PCI-DSSv4-2.2
    - PCI-DSSv4-2.2.4
    - disable_strategy
    - low_complexity
    - low_disruption
    - low_severity
    - no_reboot_needed
    - package_tftp_removed

  - name: 'Uninstall net-snmp Package: Ensure net-snmp is removed'
    ansible.builtin.package:
      name: net-snmp
      state: absent
    tags:
    - PCI-DSSv4-2.2
    - PCI-DSSv4-2.2.4
    - disable_strategy
    - low_complexity
    - low_disruption
    - no_reboot_needed
    - package_net-snmp_removed
    - unknown_severity

  - 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: 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: Verify nftables Service is Disabled - Disable service nftables
    block:

    - name: Verify nftables Service is Disabled - 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: Verify nftables Service is Disabled - Ensure nftables.service is Masked
      ansible.builtin.systemd:
        name: nftables.service
        state: stopped
        enabled: false
        masked: true
      when: service_exists.stdout_lines is search("nftables.service", multiline=True)

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

    - name: Verify nftables Service is Disabled - Disable Socket nftables
      ansible.builtin.systemd:
        name: nftables.socket
        enabled: false
        state: stopped
        masked: true
      when: socket_file_exists.stdout_lines is search("nftables.socket", multiline=True)
    tags:
    - PCI-DSSv4-1.2
    - PCI-DSSv4-1.2.1
    - disable_strategy
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - service_nftables_disabled
    - special_service_block
    when: ( "firewalld" in ansible_facts.packages and "nftables" in ansible_facts.packages
      and ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
      )

  - name: Disable Avahi Server Software - Disable service avahi-daemon
    block:

    - name: Disable Avahi Server Software - 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 Avahi Server Software - Ensure avahi-daemon.service is Masked
      ansible.builtin.systemd:
        name: avahi-daemon.service
        state: stopped
        enabled: false
        masked: true
      when: service_exists.stdout_lines is search("avahi-daemon.service", multiline=True)

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

    - name: Disable Avahi Server Software - Disable Socket avahi-daemon
      ansible.builtin.systemd:
        name: avahi-daemon.socket
        enabled: false
        state: stopped
        masked: true
      when: socket_file_exists.stdout_lines is search("avahi-daemon.socket", multiline=True)
    tags:
    - 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
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - service_avahi-daemon_disabled
    - special_service_block
    when: ( "avahi" in ansible_facts.packages and ("kernel" in ansible_facts.packages
      or "kernel-uek" in ansible_facts.packages) )

  - name: Ensure rsyncd service is disabled - Disable service rsyncd
    block:

    - name: Ensure rsyncd service is disabled - 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: Ensure rsyncd service is disabled - Ensure rsyncd.service is Masked
      ansible.builtin.systemd:
        name: rsyncd.service
        state: stopped
        enabled: false
        masked: true
      when: service_exists.stdout_lines is search("rsyncd.service", multiline=True)

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

    - name: Ensure rsyncd service is disabled - Disable Socket rsyncd
      ansible.builtin.systemd:
        name: rsyncd.socket
        enabled: false
        state: stopped
        masked: true
      when: socket_file_exists.stdout_lines is search("rsyncd.socket", multiline=True)
    tags:
    - PCI-DSSv4-2.2
    - PCI-DSSv4-2.2.4
    - disable_strategy
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - service_rsyncd_disabled
    - special_service_block
    when: ("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: '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: Read list of files with incorrect ownership
    ansible.builtin.command: rpm -Va --nodeps --nosignature --nofiledigest --nosize
      --nomtime --nordev --nocaps --nolinkto --nomode
    register: files_with_incorrect_ownership
    failed_when: files_with_incorrect_ownership.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 )
    tags:
    - CJIS-5.10.4.1
    - 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_ownership

  - name: Create list of packages
    ansible.builtin.command: rpm -qf "{{ item }}"
    with_items: '{{ files_with_incorrect_ownership.stdout_lines | map(''regex_findall'',
      ''^[.]+[U|G]+.* (\/.*)'', ''\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_ownership.stdout_lines | length > 0)
    tags:
    - CJIS-5.10.4.1
    - 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_ownership

  - name: Correct file ownership with RPM
    ansible.builtin.command: rpm --restore '{{ 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_ownership.stdout_lines | length > 0)
    tags:
    - CJIS-5.10.4.1
    - 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_ownership

  - 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: Configure Periodic Execution of AIDE - Setup Cron Tab
    ansible.builtin.cron:
      name: run AIDE check
      minute: 5
      hour: 4
      user: root
      job: /usr/sbin/aide --check
    register: crontab_check
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - '''cronie'' in ansible_facts.packages'
    tags:
    - CJIS-5.10.1.3
    - NIST-800-53-CM-6(a)
    - NIST-800-53-SI-7
    - NIST-800-53-SI-7(1)
    - PCI-DSS-Req-11.5
    - PCI-DSSv4-11.5.2
    - aide_periodic_cron_checking
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - 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: 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 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
    community.general.ini_file:
      dest: /etc/dconf/db/local.d/00-security-settings
      section: org/gnome/desktop/media-handling
      option: automount
      value: 'false'
      create: true
      no_extra_spaces: true
    register: result_ini
    when: '"gdm" in ansible_facts.packages'
    tags:
    - 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
    - low_complexity
    - medium_disruption
    - medium_severity
    - no_reboot_needed
    - unknown_strategy

  - name: Prevent user modification of GNOME3 Automounting - automount
    ansible.builtin.lineinfile:
      path: /etc/dconf/db/local.d/locks/00-security-settings-lock
      regexp: ^/org/gnome/desktop/media-handling/automount$
      line: /org/gnome/desktop/media-handling/automount
      create: true
    register: result_lineinfile
    when: '"gdm" in ansible_facts.packages'
    tags:
    - 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
    - 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:
    - 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
    - low_complexity
    - medium_disruption
    - medium_severity
    - 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: Enable GNOME3 Screensaver Idle Activation
    community.general.ini_file:
      dest: /etc/dconf/db/local.d/00-security-settings
      section: org/gnome/desktop/screensaver
      option: idle-activation-enabled
      value: 'true'
      create: true
      no_extra_spaces: true
    register: result_ini
    when: '"gdm" in ansible_facts.packages'
    tags:
    - CJIS-5.5.5
    - 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_activation_enabled
    - low_complexity
    - medium_disruption
    - medium_severity
    - no_reboot_needed
    - unknown_strategy

  - name: Prevent user modification of GNOME idle-activation-enabled
    ansible.builtin.lineinfile:
      path: /etc/dconf/db/local.d/locks/00-security-settings-lock
      regexp: ^/org/gnome/desktop/screensaver/idle-activation-enabled$
      line: /org/gnome/desktop/screensaver/idle-activation-enabled
      create: true
    register: result_lineinfile
    when: '"gdm" in ansible_facts.packages'
    tags:
    - CJIS-5.5.5
    - 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_activation_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:
    - CJIS-5.5.5
    - 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_activation_enabled
    - low_complexity
    - medium_disruption
    - medium_severity
    - 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 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: Ensure use_pty is enabled in /etc/sudoers
    ansible.builtin.lineinfile:
      path: /etc/sudoers
      regexp: ^[\s]*Defaults.*\buse_pty\b.*$
      line: Defaults use_pty
      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:
    - PCI-DSS-Req-10.2.5
    - PCI-DSSv4-2.2
    - PCI-DSSv4-2.2.6
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy
    - sudo_add_use_pty

  - name: Ensure logfile is enabled with the appropriate value in /etc/sudoers
    ansible.builtin.lineinfile:
      path: /etc/sudoers
      regexp: ^[\s]*Defaults\s(.*)\blogfile=[-]?.+\b(.*)$
      line: Defaults \1logfile={{ var_sudo_logfile }}\2
      validate: /usr/sbin/visudo -cf %s
      backrefs: true
    register: edit_sudoers_logfile_option
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - '"sudo" in ansible_facts.packages'
    tags:
    - PCI-DSS-Req-10.2.5
    - PCI-DSSv4-2.2
    - PCI-DSSv4-2.2.6
    - low_complexity
    - low_disruption
    - low_severity
    - no_reboot_needed
    - restrict_strategy
    - sudo_custom_logfile

  - name: Enable logfile option with appropriate value in /etc/sudoers
    ansible.builtin.lineinfile:
      path: /etc/sudoers
      line: Defaults logfile={{ var_sudo_logfile }}
      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_logfile_option is defined and not edit_sudoers_logfile_option.changed
    tags:
    - PCI-DSS-Req-10.2.5
    - PCI-DSSv4-2.2
    - PCI-DSSv4-2.2.6
    - low_complexity
    - low_disruption
    - low_severity
    - no_reboot_needed
    - restrict_strategy
    - sudo_custom_logfile

  - 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:
    - NIST-800-53-CM-6(a)
    - 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_authentication

  - 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:
    - NIST-800-53-CM-6(a)
    - 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_authentication

  - 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:
    - NIST-800-53-CM-6(a)
    - 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_authentication

  - 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:
    - NIST-800-53-CM-6(a)
    - 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_authentication

  - 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: 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: 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: Set the file_groupowner_etc_issue_net_newgroup variable if represented by
      gid
    ansible.builtin.set_fact:
      file_groupowner_etc_issue_net_newgroup: '0'
    tags:
    - PCI-DSSv4-1.2
    - PCI-DSSv4-1.2.8
    - configure_strategy
    - file_groupowner_etc_issue_net
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

  - name: Test for existence /etc/issue.net
    ansible.builtin.stat:
      path: /etc/issue.net
    register: file_exists
    tags:
    - PCI-DSSv4-1.2
    - PCI-DSSv4-1.2.8
    - configure_strategy
    - file_groupowner_etc_issue_net
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

  - name: Ensure group owner on /etc/issue.net
    ansible.builtin.file:
      path: /etc/issue.net
      follow: false
      group: '{{ file_groupowner_etc_issue_net_newgroup }}'
    when: file_exists.stat is defined and file_exists.stat.exists
    tags:
    - PCI-DSSv4-1.2
    - PCI-DSSv4-1.2.8
    - configure_strategy
    - file_groupowner_etc_issue_net
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

  - name: Set the file_owner_etc_issue_net_newown variable if represented by uid
    ansible.builtin.set_fact:
      file_owner_etc_issue_net_newown: '0'
    tags:
    - PCI-DSSv4-1.2
    - PCI-DSSv4-1.2.8
    - configure_strategy
    - file_owner_etc_issue_net
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

  - name: Test for existence /etc/issue.net
    ansible.builtin.stat:
      path: /etc/issue.net
    register: file_exists
    tags:
    - PCI-DSSv4-1.2
    - PCI-DSSv4-1.2.8
    - configure_strategy
    - file_owner_etc_issue_net
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

  - name: Ensure owner on /etc/issue.net
    ansible.builtin.file:
      path: /etc/issue.net
      follow: false
      owner: '{{ file_owner_etc_issue_net_newown }}'
    when: file_exists.stat is defined and file_exists.stat.exists
    tags:
    - PCI-DSSv4-1.2
    - PCI-DSSv4-1.2.8
    - configure_strategy
    - file_owner_etc_issue_net
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

  - name: Test for existence /etc/issue.net
    ansible.builtin.stat:
      path: /etc/issue.net
    register: file_exists
    tags:
    - PCI-DSSv4-1.2
    - PCI-DSSv4-1.2.8
    - configure_strategy
    - file_permissions_etc_issue_net
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

  - name: Ensure permission u-xs,g-xws,o-xwt on /etc/issue.net
    ansible.builtin.file:
      path: /etc/issue.net
      mode: u-xs,g-xws,o-xwt
    when: file_exists.stat is defined and file_exists.stat.exists
    tags:
    - PCI-DSSv4-1.2
    - PCI-DSSv4-1.2.8
    - configure_strategy
    - file_permissions_etc_issue_net
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

  - name: Ensure PAM Displays Last Logon/Access Notification - Check if system relies
      on authselect tool
    ansible.builtin.stat:
      path: /usr/bin/authselect
    register: result_authselect_present
    when: ( "pam" in ansible_facts.packages and ("kernel" in ansible_facts.packages
      or "kernel-uek" in ansible_facts.packages) )
    tags:
    - CJIS-5.5.2
    - NIST-800-53-AC-9
    - NIST-800-53-AC-9(1)
    - PCI-DSS-Req-10.2.4
    - PCI-DSSv4-10.2
    - PCI-DSSv4-10.2.1
    - PCI-DSSv4-10.2.1.4
    - configure_strategy
    - display_login_attempts
    - low_complexity
    - low_disruption
    - low_severity
    - no_reboot_needed

  - name: Ensure PAM Displays Last Logon/Access Notification - Collect the Available
      authselect Features
    ansible.builtin.command:
      cmd: authselect list-features sssd
    register: result_authselect_available_features
    changed_when: false
    check_mode: false
    when:
    - ( "pam" in ansible_facts.packages and ("kernel" in ansible_facts.packages or
      "kernel-uek" in ansible_facts.packages) )
    - result_authselect_present.stat.exists
    tags:
    - CJIS-5.5.2
    - NIST-800-53-AC-9
    - NIST-800-53-AC-9(1)
    - PCI-DSS-Req-10.2.4
    - PCI-DSSv4-10.2
    - PCI-DSSv4-10.2.1
    - PCI-DSSv4-10.2.1.4
    - configure_strategy
    - display_login_attempts
    - low_complexity
    - low_disruption
    - low_severity
    - no_reboot_needed

  - name: Ensure PAM Displays Last Logon/Access Notification - Configure pam_lastlog.so
      Using authselect Feature
    block:

    - name: Ensure PAM Displays Last Logon/Access Notification - 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 Displays Last Logon/Access Notification - 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 Displays Last Logon/Access Notification - Get authselect Features
        Currently Enabled
      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: Ensure PAM Displays Last Logon/Access Notification - Ensure "with-silent-lastlog"
        Feature is Disabled Using authselect Tool
      ansible.builtin.command:
        cmd: authselect disable-feature with-silent-lastlog
      register: result_authselect_disable_feature_cmd
      when:
      - result_authselect_check_cmd is success
      - result_authselect_features.stdout is search("with-silent-lastlog")

    - name: Ensure PAM Displays Last Logon/Access Notification - Ensure authselect
        changes are applied
      ansible.builtin.command:
        cmd: authselect apply-changes -b
      when:
      - result_authselect_disable_feature_cmd is not skipped
      - result_authselect_disable_feature_cmd is success
    when:
    - ( "pam" in ansible_facts.packages and ("kernel" in ansible_facts.packages or
      "kernel-uek" in ansible_facts.packages) )
    - result_authselect_present.stat.exists
    - result_authselect_available_features.stdout is search("with-silent-lastlog")
    tags:
    - CJIS-5.5.2
    - NIST-800-53-AC-9
    - NIST-800-53-AC-9(1)
    - PCI-DSS-Req-10.2.4
    - PCI-DSSv4-10.2
    - PCI-DSSv4-10.2.1
    - PCI-DSSv4-10.2.1.4
    - configure_strategy
    - display_login_attempts
    - low_complexity
    - low_disruption
    - low_severity
    - no_reboot_needed

  - name: Ensure PAM Displays Last Logon/Access Notification - Configure pam_lastlog.so
      in appropriate PAM files
    block:

    - name: Ensure PAM Displays Last Logon/Access Notification - Define the PAM file
        to be edited as a local fact
      ansible.builtin.set_fact:
        pam_file_path: /etc/pam.d/postlogin

    - name: Ensure PAM Displays Last Logon/Access Notification - Check if system relies
        on authselect tool
      ansible.builtin.stat:
        path: /usr/bin/authselect
      register: result_authselect_present

    - name: Ensure PAM Displays Last Logon/Access Notification - Ensure authselect
        custom profile is used if authselect is present
      block:

      - name: Ensure PAM Displays Last Logon/Access Notification - 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 Displays Last Logon/Access Notification - 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 Displays Last Logon/Access Notification - 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 Displays Last Logon/Access Notification - 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 Displays Last Logon/Access Notification - 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 Displays Last Logon/Access Notification - 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 Displays Last Logon/Access Notification - 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 Displays Last Logon/Access Notification - 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 Displays Last Logon/Access Notification - 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 Displays Last Logon/Access Notification - 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 Displays Last Logon/Access Notification - 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 Displays Last Logon/Access Notification - 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 Displays Last Logon/Access Notification - 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 Displays Last Logon/Access Notification - 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 Displays Last Logon/Access Notification - Define a fact for
        control already filtered in case filters are used
      ansible.builtin.set_fact:
        pam_module_control: required

    - name: Ensure PAM Displays Last Logon/Access Notification - Check if expected
        PAM module line is present in {{ pam_file_path }}
      ansible.builtin.lineinfile:
        path: '{{ pam_file_path }}'
        regexp: ^\s*session\s+{{ pam_module_control | regex_escape() }}\s+pam_lastlog.so\s*.*
        state: absent
      check_mode: true
      changed_when: false
      register: result_pam_line_present

    - name: Ensure PAM Displays Last Logon/Access Notification - Include or update
        the PAM module line in {{ pam_file_path }}
      block:

      - name: Ensure PAM Displays Last Logon/Access Notification - Check if required
          PAM module line is present in {{ pam_file_path }} with different control
        ansible.builtin.lineinfile:
          path: '{{ pam_file_path }}'
          regexp: ^\s*session\s+.*\s+pam_lastlog.so\s*
          state: absent
        check_mode: true
        changed_when: false
        register: result_pam_line_other_control_present

      - name: Ensure PAM Displays Last Logon/Access Notification - Ensure the correct
          control for the required PAM module line in {{ pam_file_path }}
        ansible.builtin.replace:
          dest: '{{ pam_file_path }}'
          regexp: ^(\s*session\s+).*(\bpam_lastlog.so.*)
          replace: \1{{ pam_module_control }} \2
        register: result_pam_module_edit
        when:
        - result_pam_line_other_control_present.found == 1

      - name: Ensure PAM Displays Last Logon/Access Notification - Ensure the required
          PAM module line is included in {{ pam_file_path }}
        ansible.builtin.lineinfile:
          dest: '{{ pam_file_path }}'
          insertafter: ^\s*session\s+.*pam_succeed_if\.so.*
          line: session    {{ pam_module_control }}    pam_lastlog.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 Displays Last Logon/Access Notification - 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 Displays Last Logon/Access Notification - Define a fact for
        control already filtered in case filters are used
      ansible.builtin.set_fact:
        pam_module_control: required

    - name: Ensure PAM Displays Last Logon/Access Notification - Check if the required
        PAM module option is present in {{ pam_file_path }}
      ansible.builtin.lineinfile:
        path: '{{ pam_file_path }}'
        regexp: ^\s*session\s+{{ pam_module_control | regex_escape() }}\s+pam_lastlog.so\s*.*\sshowfailed\b
        state: absent
      check_mode: true
      changed_when: false
      register: result_pam_module_display_login_attempts_option_present

    - name: Ensure PAM Displays Last Logon/Access Notification - Ensure the "showfailed"
        PAM option for "pam_lastlog.so" is included in {{ pam_file_path }}
      ansible.builtin.lineinfile:
        path: '{{ pam_file_path }}'
        backrefs: true
        regexp: ^(\s*session\s+{{ pam_module_control | regex_escape() }}\s+pam_lastlog.so.*)
        line: \1 showfailed
        state: present
      register: result_pam_display_login_attempts_add
      when:
      - result_pam_module_display_login_attempts_option_present.found is defined
      - result_pam_module_display_login_attempts_option_present.found == 0

    - name: Ensure PAM Displays Last Logon/Access Notification - Define a fact for
        control already filtered in case filters are used
      ansible.builtin.set_fact:
        pam_module_control: required

    - name: Ensure PAM Displays Last Logon/Access Notification - Check if {{ pam_file_path
        }} file is present
      ansible.builtin.stat:
        path: '{{ pam_file_path }}'
      register: result_pam_file_present

    - name: Ensure PAM Displays Last Logon/Access Notification - Ensure the "silent"
        option from "pam_lastlog.so" is not present in {{ pam_file_path }}
      ansible.builtin.replace:
        dest: '{{ pam_file_path }}'
        regexp: (.*session.*{{ pam_module_control | regex_escape() }}.*pam_lastlog.so.*)\bsilent\b=?[0-9a-zA-Z]*(.*)
        replace: \1\2
      register: result_pam_option_removal
      when:
      - result_pam_file_present.stat.exists
    when: ( "pam" in ansible_facts.packages and ("kernel" in ansible_facts.packages
      or "kernel-uek" in ansible_facts.packages) )
    tags:
    - CJIS-5.5.2
    - NIST-800-53-AC-9
    - NIST-800-53-AC-9(1)
    - PCI-DSS-Req-10.2.4
    - PCI-DSSv4-10.2
    - PCI-DSSv4-10.2.1
    - PCI-DSSv4-10.2.1.4
    - configure_strategy
    - display_login_attempts
    - low_complexity
    - low_disruption
    - low_severity
    - no_reboot_needed

  - name: 'Limit Password Reuse: password-auth - 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.6.2.1.1
    - NIST-800-171-3.5.8
    - NIST-800-53-IA-5(1)(e)
    - NIST-800-53-IA-5(f)
    - PCI-DSS-Req-8.2.5
    - PCI-DSSv4-8.3
    - PCI-DSSv4-8.3.7
    - accounts_password_pam_pwhistory_remember_password_auth
    - configure_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - no_reboot_needed

  - name: 'Limit Password Reuse: password-auth - Collect the available authselect
      features'
    ansible.builtin.command:
      cmd: authselect list-features sssd
    register: result_authselect_available_features
    changed_when: false
    check_mode: false
    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.6.2.1.1
    - NIST-800-171-3.5.8
    - NIST-800-53-IA-5(1)(e)
    - NIST-800-53-IA-5(f)
    - PCI-DSS-Req-8.2.5
    - PCI-DSSv4-8.3
    - PCI-DSSv4-8.3.7
    - accounts_password_pam_pwhistory_remember_password_auth
    - configure_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - no_reboot_needed

  - name: 'Limit Password Reuse: password-auth - Enable pam_pwhistory.so using authselect
      feature'
    block:

    - name: 'Limit Password Reuse: 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: 'Limit Password Reuse: 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: 'Limit Password Reuse: password-auth - 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: 'Limit Password Reuse: password-auth - Ensure "with-pwhistory" feature
        is enabled using authselect tool'
      ansible.builtin.command:
        cmd: authselect enable-feature with-pwhistory
      register: result_authselect_enable_feature_cmd
      when:
      - result_authselect_check_cmd is success
      - result_authselect_features.stdout is not search("with-pwhistory")

    - name: 'Limit Password Reuse: password-auth - 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
    - result_authselect_available_features.stdout is search("with-pwhistory")
    tags:
    - CJIS-5.6.2.1.1
    - NIST-800-171-3.5.8
    - NIST-800-53-IA-5(1)(e)
    - NIST-800-53-IA-5(f)
    - PCI-DSS-Req-8.2.5
    - PCI-DSSv4-8.3
    - PCI-DSSv4-8.3.7
    - accounts_password_pam_pwhistory_remember_password_auth
    - configure_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - no_reboot_needed

  - name: 'Limit Password Reuse: password-auth - Enable pam_pwhistory.so in appropriate
      PAM files'
    block:

    - name: 'Limit Password Reuse: 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: 'Limit Password Reuse: password-auth - Check if system relies on authselect
        tool'
      ansible.builtin.stat:
        path: /usr/bin/authselect
      register: result_authselect_present

    - name: 'Limit Password Reuse: password-auth - Ensure authselect custom profile
        is used if authselect is present'
      block:

      - name: 'Limit Password Reuse: 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: 'Limit Password Reuse: 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: 'Limit Password Reuse: 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: 'Limit Password Reuse: 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: 'Limit Password Reuse: 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: 'Limit Password Reuse: 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: 'Limit Password Reuse: 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: 'Limit Password Reuse: 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: 'Limit Password Reuse: 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: 'Limit Password Reuse: 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: 'Limit Password Reuse: 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: 'Limit Password Reuse: 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: 'Limit Password Reuse: 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: 'Limit Password Reuse: 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: 'Limit Password Reuse: password-auth - Define a fact for control already
        filtered in case filters are used'
      ansible.builtin.set_fact:
        pam_module_control: '{{ var_password_pam_remember_control_flag.split(",")[0]
          }}'

    - name: 'Limit Password Reuse: 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_pwhistory.so\s*.*
        state: absent
      check_mode: true
      changed_when: false
      register: result_pam_line_present

    - name: 'Limit Password Reuse: password-auth - Include or update the PAM module
        line in {{ pam_file_path }}'
      block:

      - name: 'Limit Password Reuse: 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_pwhistory.so\s*
          state: absent
        check_mode: true
        changed_when: false
        register: result_pam_line_other_control_present

      - name: 'Limit Password Reuse: 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_pwhistory.so.*)
          replace: \1{{ pam_module_control }} \2
        register: result_pam_module_edit
        when:
        - result_pam_line_other_control_present.found == 1

      - name: 'Limit Password Reuse: password-auth - Ensure the required PAM module
          line is included in {{ pam_file_path }}'
        ansible.builtin.lineinfile:
          dest: '{{ pam_file_path }}'
          insertafter: ^password.*requisite.*pam_pwquality\.so
          line: password    {{ pam_module_control }}    pam_pwhistory.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: 'Limit Password Reuse: 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
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - '"pam" in ansible_facts.packages'
    - |
      (result_authselect_available_features.stdout is defined and result_authselect_available_features.stdout is not search("with-pwhistory")) or result_authselect_available_features is not defined
    tags:
    - CJIS-5.6.2.1.1
    - NIST-800-171-3.5.8
    - NIST-800-53-IA-5(1)(e)
    - NIST-800-53-IA-5(f)
    - PCI-DSS-Req-8.2.5
    - PCI-DSSv4-8.3
    - PCI-DSSv4-8.3.7
    - accounts_password_pam_pwhistory_remember_password_auth
    - configure_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - no_reboot_needed

  - name: 'Limit Password Reuse: password-auth - Check the presence of /etc/security/pwhistory.conf
      file'
    ansible.builtin.stat:
      path: /etc/security/pwhistory.conf
    register: result_pwhistory_conf_check
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - '"pam" in ansible_facts.packages'
    tags:
    - CJIS-5.6.2.1.1
    - NIST-800-171-3.5.8
    - NIST-800-53-IA-5(1)(e)
    - NIST-800-53-IA-5(f)
    - PCI-DSS-Req-8.2.5
    - PCI-DSSv4-8.3
    - PCI-DSSv4-8.3.7
    - accounts_password_pam_pwhistory_remember_password_auth
    - configure_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - no_reboot_needed

  - name: 'Limit Password Reuse: password-auth - pam_pwhistory.so parameters are configured
      in /etc/security/pwhistory.conf file'
    block:

    - name: 'Limit Password Reuse: password-auth - Ensure the pam_pwhistory.so remember
        parameter in /etc/security/pwhistory.conf'
      ansible.builtin.lineinfile:
        path: /etc/security/pwhistory.conf
        regexp: ^\s*remember\s*=
        line: remember = {{ var_password_pam_remember }}
        state: present

    - name: 'Limit Password Reuse: password-auth - Ensure the pam_pwhistory.so remember
        parameter is removed from PAM files'
      block:

      - name: 'Limit Password Reuse: 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

      - name: 'Limit Password Reuse: password-auth - Check the proper remediation
          for the system'
        block:

        - name: 'Limit Password Reuse: 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: 'Limit Password Reuse: password-auth - Check if system relies on authselect
            tool'
          ansible.builtin.stat:
            path: /usr/bin/authselect
          register: result_authselect_present

        - name: 'Limit Password Reuse: password-auth - Ensure authselect custom profile
            is used if authselect is present'
          block:

          - name: 'Limit Password Reuse: 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: 'Limit Password Reuse: 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: 'Limit Password Reuse: 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: 'Limit Password Reuse: 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: 'Limit Password Reuse: 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: 'Limit Password Reuse: 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: 'Limit Password Reuse: 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: 'Limit Password Reuse: 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: 'Limit Password Reuse: 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: 'Limit Password Reuse: 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: 'Limit Password Reuse: 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: 'Limit Password Reuse: 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: 'Limit Password Reuse: 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: 'Limit Password Reuse: 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: 'Limit Password Reuse: password-auth - Define a fact for control already
            filtered in case filters are used'
          ansible.builtin.set_fact:
            pam_module_control: ''

        - name: 'Limit Password Reuse: password-auth - Check if {{ pam_file_path }}
            file is present'
          ansible.builtin.stat:
            path: '{{ pam_file_path }}'
          register: result_pam_file_present

        - name: 'Limit Password Reuse: password-auth - Ensure the "remember" option
            from "pam_pwhistory.so" is not present in {{ pam_file_path }}'
          ansible.builtin.replace:
            dest: '{{ pam_file_path }}'
            regexp: (.*password.*pam_pwhistory.so.*)\bremember\b=?[0-9a-zA-Z]*(.*)
            replace: \1\2
          register: result_pam_option_removal
          when:
          - result_pam_file_present.stat.exists

        - name: 'Limit Password Reuse: password-auth - 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_pwhistory_conf_check.stat.exists
    tags:
    - CJIS-5.6.2.1.1
    - NIST-800-171-3.5.8
    - NIST-800-53-IA-5(1)(e)
    - NIST-800-53-IA-5(f)
    - PCI-DSS-Req-8.2.5
    - PCI-DSSv4-8.3
    - PCI-DSSv4-8.3.7
    - accounts_password_pam_pwhistory_remember_password_auth
    - configure_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - no_reboot_needed

  - name: 'Limit Password Reuse: password-auth - pam_pwhistory.so parameters are configured
      in PAM files'
    block:

    - name: 'Limit Password Reuse: 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: 'Limit Password Reuse: password-auth - Check if system relies on authselect
        tool'
      ansible.builtin.stat:
        path: /usr/bin/authselect
      register: result_authselect_present

    - name: 'Limit Password Reuse: password-auth - Ensure authselect custom profile
        is used if authselect is present'
      block:

      - name: 'Limit Password Reuse: 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: 'Limit Password Reuse: 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: 'Limit Password Reuse: 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: 'Limit Password Reuse: 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: 'Limit Password Reuse: 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: 'Limit Password Reuse: 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: 'Limit Password Reuse: 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: 'Limit Password Reuse: 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: 'Limit Password Reuse: 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: 'Limit Password Reuse: 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: 'Limit Password Reuse: 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: 'Limit Password Reuse: 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: 'Limit Password Reuse: 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: 'Limit Password Reuse: 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: 'Limit Password Reuse: password-auth - Define a fact for control already
        filtered in case filters are used'
      ansible.builtin.set_fact:
        pam_module_control: requisite

    - name: 'Limit Password Reuse: 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_pwhistory.so\s*.*
        state: absent
      check_mode: true
      changed_when: false
      register: result_pam_line_present

    - name: 'Limit Password Reuse: password-auth - Include or update the PAM module
        line in {{ pam_file_path }}'
      block:

      - name: 'Limit Password Reuse: 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_pwhistory.so\s*
          state: absent
        check_mode: true
        changed_when: false
        register: result_pam_line_other_control_present

      - name: 'Limit Password Reuse: 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_pwhistory.so.*)
          replace: \1{{ pam_module_control }} \2
        register: result_pam_module_edit
        when:
        - result_pam_line_other_control_present.found == 1

      - name: 'Limit Password Reuse: 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_pwhistory.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: 'Limit Password Reuse: 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: 'Limit Password Reuse: password-auth - Define a fact for control already
        filtered in case filters are used'
      ansible.builtin.set_fact:
        pam_module_control: requisite

    - name: 'Limit Password Reuse: 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_pwhistory.so\s*.*\sremember\b
        state: absent
      check_mode: true
      changed_when: false
      register: result_pam_module_accounts_password_pam_pwhistory_remember_password_auth_option_present

    - name: 'Limit Password Reuse: password-auth - Ensure the "remember" PAM option
        for "pam_pwhistory.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_pwhistory.so.*)
        line: \1 remember={{ var_password_pam_remember }}
        state: present
      register: result_pam_accounts_password_pam_pwhistory_remember_password_auth_add
      when:
      - result_pam_module_accounts_password_pam_pwhistory_remember_password_auth_option_present.found
        is defined
      - result_pam_module_accounts_password_pam_pwhistory_remember_password_auth_option_present.found
        == 0

    - name: 'Limit Password Reuse: password-auth - Ensure the required value for "remember"
        PAM option from "pam_pwhistory.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_pwhistory.so\s+.*)(remember)=[0-9a-zA-Z]*\s*(.*)
        line: \1\2={{ var_password_pam_remember }} \3
      register: result_pam_accounts_password_pam_pwhistory_remember_password_auth_edit
      when:
      - result_pam_module_accounts_password_pam_pwhistory_remember_password_auth_option_present.found
        > 0

    - name: 'Limit Password Reuse: password-auth - Ensure authselect changes are applied'
      ansible.builtin.command:
        cmd: authselect apply-changes -b
      when:
      - result_authselect_present.stat.exists
      - (result_pam_remember_add is defined and result_pam_remember_add.changed) or
        (result_pam_remember_edit is defined and result_pam_remember_edit.changed)
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - '"pam" in ansible_facts.packages'
    - not result_pwhistory_conf_check.stat.exists
    tags:
    - CJIS-5.6.2.1.1
    - NIST-800-171-3.5.8
    - NIST-800-53-IA-5(1)(e)
    - NIST-800-53-IA-5(f)
    - PCI-DSS-Req-8.2.5
    - PCI-DSSv4-8.3
    - PCI-DSSv4-8.3.7
    - accounts_password_pam_pwhistory_remember_password_auth
    - configure_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - no_reboot_needed

  - name: 'Limit Password Reuse: system-auth - 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.6.2.1.1
    - NIST-800-171-3.5.8
    - NIST-800-53-IA-5(1)(e)
    - NIST-800-53-IA-5(f)
    - PCI-DSS-Req-8.2.5
    - PCI-DSSv4-8.3
    - PCI-DSSv4-8.3.7
    - accounts_password_pam_pwhistory_remember_system_auth
    - configure_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - no_reboot_needed

  - name: 'Limit Password Reuse: system-auth - Collect the available authselect features'
    ansible.builtin.command:
      cmd: authselect list-features sssd
    register: result_authselect_available_features
    changed_when: false
    check_mode: false
    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.6.2.1.1
    - NIST-800-171-3.5.8
    - NIST-800-53-IA-5(1)(e)
    - NIST-800-53-IA-5(f)
    - PCI-DSS-Req-8.2.5
    - PCI-DSSv4-8.3
    - PCI-DSSv4-8.3.7
    - accounts_password_pam_pwhistory_remember_system_auth
    - configure_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - no_reboot_needed

  - name: 'Limit Password Reuse: system-auth - Enable pam_pwhistory.so using authselect
      feature'
    block:

    - name: 'Limit Password Reuse: 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: 'Limit Password Reuse: 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: 'Limit Password Reuse: system-auth - 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: 'Limit Password Reuse: system-auth - Ensure "with-pwhistory" feature is
        enabled using authselect tool'
      ansible.builtin.command:
        cmd: authselect enable-feature with-pwhistory
      register: result_authselect_enable_feature_cmd
      when:
      - result_authselect_check_cmd is success
      - result_authselect_features.stdout is not search("with-pwhistory")

    - name: 'Limit Password Reuse: system-auth - 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
    - result_authselect_available_features.stdout is search("with-pwhistory")
    tags:
    - CJIS-5.6.2.1.1
    - NIST-800-171-3.5.8
    - NIST-800-53-IA-5(1)(e)
    - NIST-800-53-IA-5(f)
    - PCI-DSS-Req-8.2.5
    - PCI-DSSv4-8.3
    - PCI-DSSv4-8.3.7
    - accounts_password_pam_pwhistory_remember_system_auth
    - configure_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - no_reboot_needed

  - name: 'Limit Password Reuse: system-auth - Enable pam_pwhistory.so in appropriate
      PAM files'
    block:

    - name: 'Limit Password Reuse: 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: 'Limit Password Reuse: system-auth - Check if system relies on authselect
        tool'
      ansible.builtin.stat:
        path: /usr/bin/authselect
      register: result_authselect_present

    - name: 'Limit Password Reuse: system-auth - Ensure authselect custom profile
        is used if authselect is present'
      block:

      - name: 'Limit Password Reuse: 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: 'Limit Password Reuse: 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: 'Limit Password Reuse: 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: 'Limit Password Reuse: 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: 'Limit Password Reuse: 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: 'Limit Password Reuse: 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: 'Limit Password Reuse: 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: 'Limit Password Reuse: 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: 'Limit Password Reuse: 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: 'Limit Password Reuse: 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: 'Limit Password Reuse: 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: 'Limit Password Reuse: 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: 'Limit Password Reuse: 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: 'Limit Password Reuse: 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: 'Limit Password Reuse: system-auth - Define a fact for control already
        filtered in case filters are used'
      ansible.builtin.set_fact:
        pam_module_control: '{{ var_password_pam_remember_control_flag.split(",")[0]
          }}'

    - name: 'Limit Password Reuse: 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_pwhistory.so\s*.*
        state: absent
      check_mode: true
      changed_when: false
      register: result_pam_line_present

    - name: 'Limit Password Reuse: system-auth - Include or update the PAM module
        line in {{ pam_file_path }}'
      block:

      - name: 'Limit Password Reuse: 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_pwhistory.so\s*
          state: absent
        check_mode: true
        changed_when: false
        register: result_pam_line_other_control_present

      - name: 'Limit Password Reuse: 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_pwhistory.so.*)
          replace: \1{{ pam_module_control }} \2
        register: result_pam_module_edit
        when:
        - result_pam_line_other_control_present.found == 1

      - name: 'Limit Password Reuse: system-auth - Ensure the required PAM module
          line is included in {{ pam_file_path }}'
        ansible.builtin.lineinfile:
          dest: '{{ pam_file_path }}'
          insertafter: ^password.*requisite.*pam_pwquality\.so
          line: password    {{ pam_module_control }}    pam_pwhistory.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: 'Limit Password Reuse: 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
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - '"pam" in ansible_facts.packages'
    - |
      (result_authselect_available_features.stdout is defined and result_authselect_available_features.stdout is not search("with-pwhistory")) or result_authselect_available_features is not defined
    tags:
    - CJIS-5.6.2.1.1
    - NIST-800-171-3.5.8
    - NIST-800-53-IA-5(1)(e)
    - NIST-800-53-IA-5(f)
    - PCI-DSS-Req-8.2.5
    - PCI-DSSv4-8.3
    - PCI-DSSv4-8.3.7
    - accounts_password_pam_pwhistory_remember_system_auth
    - configure_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - no_reboot_needed

  - name: 'Limit Password Reuse: system-auth - Check the presence of /etc/security/pwhistory.conf
      file'
    ansible.builtin.stat:
      path: /etc/security/pwhistory.conf
    register: result_pwhistory_conf_check
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - '"pam" in ansible_facts.packages'
    tags:
    - CJIS-5.6.2.1.1
    - NIST-800-171-3.5.8
    - NIST-800-53-IA-5(1)(e)
    - NIST-800-53-IA-5(f)
    - PCI-DSS-Req-8.2.5
    - PCI-DSSv4-8.3
    - PCI-DSSv4-8.3.7
    - accounts_password_pam_pwhistory_remember_system_auth
    - configure_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - no_reboot_needed

  - name: 'Limit Password Reuse: system-auth - pam_pwhistory.so parameters are configured
      in /etc/security/pwhistory.conf file'
    block:

    - name: 'Limit Password Reuse: system-auth - Ensure the pam_pwhistory.so remember
        parameter in /etc/security/pwhistory.conf'
      ansible.builtin.lineinfile:
        path: /etc/security/pwhistory.conf
        regexp: ^\s*remember\s*=
        line: remember = {{ var_password_pam_remember }}
        state: present

    - name: 'Limit Password Reuse: system-auth - Ensure the pam_pwhistory.so remember
        parameter is removed from PAM files'
      block:

      - name: 'Limit Password Reuse: 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

      - name: 'Limit Password Reuse: system-auth - Check the proper remediation for
          the system'
        block:

        - name: 'Limit Password Reuse: 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: 'Limit Password Reuse: system-auth - Check if system relies on authselect
            tool'
          ansible.builtin.stat:
            path: /usr/bin/authselect
          register: result_authselect_present

        - name: 'Limit Password Reuse: system-auth - Ensure authselect custom profile
            is used if authselect is present'
          block:

          - name: 'Limit Password Reuse: 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: 'Limit Password Reuse: 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: 'Limit Password Reuse: 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: 'Limit Password Reuse: 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: 'Limit Password Reuse: 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: 'Limit Password Reuse: 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: 'Limit Password Reuse: 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: 'Limit Password Reuse: 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: 'Limit Password Reuse: 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: 'Limit Password Reuse: 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: 'Limit Password Reuse: 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: 'Limit Password Reuse: 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: 'Limit Password Reuse: 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: 'Limit Password Reuse: 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: 'Limit Password Reuse: system-auth - Define a fact for control already
            filtered in case filters are used'
          ansible.builtin.set_fact:
            pam_module_control: ''

        - name: 'Limit Password Reuse: system-auth - Check if {{ pam_file_path }}
            file is present'
          ansible.builtin.stat:
            path: '{{ pam_file_path }}'
          register: result_pam_file_present

        - name: 'Limit Password Reuse: system-auth - Ensure the "remember" option
            from "pam_pwhistory.so" is not present in {{ pam_file_path }}'
          ansible.builtin.replace:
            dest: '{{ pam_file_path }}'
            regexp: (.*password.*pam_pwhistory.so.*)\bremember\b=?[0-9a-zA-Z]*(.*)
            replace: \1\2
          register: result_pam_option_removal
          when:
          - result_pam_file_present.stat.exists

        - name: 'Limit Password Reuse: system-auth - 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
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - '"pam" in ansible_facts.packages'
    - result_pwhistory_conf_check.stat.exists
    tags:
    - CJIS-5.6.2.1.1
    - NIST-800-171-3.5.8
    - NIST-800-53-IA-5(1)(e)
    - NIST-800-53-IA-5(f)
    - PCI-DSS-Req-8.2.5
    - PCI-DSSv4-8.3
    - PCI-DSSv4-8.3.7
    - accounts_password_pam_pwhistory_remember_system_auth
    - configure_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - no_reboot_needed

  - name: 'Limit Password Reuse: system-auth - pam_pwhistory.so parameters are configured
      in PAM files'
    block:

    - name: 'Limit Password Reuse: 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: 'Limit Password Reuse: system-auth - Check if system relies on authselect
        tool'
      ansible.builtin.stat:
        path: /usr/bin/authselect
      register: result_authselect_present

    - name: 'Limit Password Reuse: system-auth - Ensure authselect custom profile
        is used if authselect is present'
      block:

      - name: 'Limit Password Reuse: 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: 'Limit Password Reuse: 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: 'Limit Password Reuse: 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: 'Limit Password Reuse: 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: 'Limit Password Reuse: 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: 'Limit Password Reuse: 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: 'Limit Password Reuse: 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: 'Limit Password Reuse: 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: 'Limit Password Reuse: 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: 'Limit Password Reuse: 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: 'Limit Password Reuse: 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: 'Limit Password Reuse: 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: 'Limit Password Reuse: 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: 'Limit Password Reuse: 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: 'Limit Password Reuse: system-auth - Define a fact for control already
        filtered in case filters are used'
      ansible.builtin.set_fact:
        pam_module_control: requisite

    - name: 'Limit Password Reuse: 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_pwhistory.so\s*.*
        state: absent
      check_mode: true
      changed_when: false
      register: result_pam_line_present

    - name: 'Limit Password Reuse: system-auth - Include or update the PAM module
        line in {{ pam_file_path }}'
      block:

      - name: 'Limit Password Reuse: 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_pwhistory.so\s*
          state: absent
        check_mode: true
        changed_when: false
        register: result_pam_line_other_control_present

      - name: 'Limit Password Reuse: 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_pwhistory.so.*)
          replace: \1{{ pam_module_control }} \2
        register: result_pam_module_edit
        when:
        - result_pam_line_other_control_present.found == 1

      - name: 'Limit Password Reuse: 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_pwhistory.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: 'Limit Password Reuse: 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: 'Limit Password Reuse: system-auth - Define a fact for control already
        filtered in case filters are used'
      ansible.builtin.set_fact:
        pam_module_control: requisite

    - name: 'Limit Password Reuse: 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_pwhistory.so\s*.*\sremember\b
        state: absent
      check_mode: true
      changed_when: false
      register: result_pam_module_accounts_password_pam_pwhistory_remember_system_auth_option_present

    - name: 'Limit Password Reuse: system-auth - Ensure the "remember" PAM option
        for "pam_pwhistory.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_pwhistory.so.*)
        line: \1 remember={{ var_password_pam_remember }}
        state: present
      register: result_pam_accounts_password_pam_pwhistory_remember_system_auth_add
      when:
      - result_pam_module_accounts_password_pam_pwhistory_remember_system_auth_option_present.found
        is defined
      - result_pam_module_accounts_password_pam_pwhistory_remember_system_auth_option_present.found
        == 0

    - name: 'Limit Password Reuse: system-auth - Ensure the required value for "remember"
        PAM option from "pam_pwhistory.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_pwhistory.so\s+.*)(remember)=[0-9a-zA-Z]*\s*(.*)
        line: \1\2={{ var_password_pam_remember }} \3
      register: result_pam_accounts_password_pam_pwhistory_remember_system_auth_edit
      when:
      - result_pam_module_accounts_password_pam_pwhistory_remember_system_auth_option_present.found
        > 0

    - name: 'Limit Password Reuse: system-auth - Ensure authselect changes are applied'
      ansible.builtin.command:
        cmd: authselect apply-changes -b
      when:
      - result_authselect_present.stat.exists
      - (result_pam_remember_add is defined and result_pam_remember_add.changed) or
        (result_pam_remember_edit is defined and result_pam_remember_edit.changed)
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - '"pam" in ansible_facts.packages'
    - not result_pwhistory_conf_check.stat.exists
    tags:
    - CJIS-5.6.2.1.1
    - NIST-800-171-3.5.8
    - NIST-800-53-IA-5(1)(e)
    - NIST-800-53-IA-5(f)
    - PCI-DSS-Req-8.2.5
    - PCI-DSSv4-8.3
    - PCI-DSSv4-8.3.7
    - accounts_password_pam_pwhistory_remember_system_auth
    - configure_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - no_reboot_needed

  - name: Limit Password Reuse - 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)
    - '"libpwquality" in ansible_facts.packages'
    tags:
    - CJIS-5.6.2.1.1
    - NIST-800-171-3.5.8
    - NIST-800-53-IA-5(1)(e)
    - NIST-800-53-IA-5(f)
    - PCI-DSS-Req-8.2.5
    - PCI-DSSv4-8.3
    - PCI-DSSv4-8.3.7
    - accounts_password_pam_unix_remember
    - configure_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - no_reboot_needed

  - name: Limit Password Reuse - Collect the available authselect features
    ansible.builtin.command:
      cmd: authselect list-features sssd
    register: result_authselect_available_features
    changed_when: false
    check_mode: false
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - '"libpwquality" in ansible_facts.packages'
    - result_authselect_present.stat.exists
    tags:
    - CJIS-5.6.2.1.1
    - NIST-800-171-3.5.8
    - NIST-800-53-IA-5(1)(e)
    - NIST-800-53-IA-5(f)
    - PCI-DSS-Req-8.2.5
    - PCI-DSSv4-8.3
    - PCI-DSSv4-8.3.7
    - accounts_password_pam_unix_remember
    - configure_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - no_reboot_needed

  - name: Limit Password Reuse - Enable pam_pwhistory.so using authselect feature
    block:

    - name: Limit Password Reuse - 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: Limit Password Reuse - 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: Limit Password Reuse - 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: Limit Password Reuse - Ensure "with-pwhistory" feature is enabled using
        authselect tool
      ansible.builtin.command:
        cmd: authselect enable-feature with-pwhistory
      register: result_authselect_enable_feature_cmd
      when:
      - result_authselect_check_cmd is success
      - result_authselect_features.stdout is not search("with-pwhistory")

    - name: Limit Password Reuse - 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)
    - '"libpwquality" in ansible_facts.packages'
    - result_authselect_present.stat.exists
    - result_authselect_available_features.stdout is search("with-pwhistory")
    tags:
    - CJIS-5.6.2.1.1
    - NIST-800-171-3.5.8
    - NIST-800-53-IA-5(1)(e)
    - NIST-800-53-IA-5(f)
    - PCI-DSS-Req-8.2.5
    - PCI-DSSv4-8.3
    - PCI-DSSv4-8.3.7
    - accounts_password_pam_unix_remember
    - configure_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - no_reboot_needed

  - name: Limit Password Reuse - Enable pam_pwhistory.so in appropriate PAM files
    block:

    - name: Limit Password Reuse - Define the PAM file to be edited as a local fact
      ansible.builtin.set_fact:
        pam_file_path: /etc/pam.d/system-auth

    - name: Limit Password Reuse - Check if system relies on authselect tool
      ansible.builtin.stat:
        path: /usr/bin/authselect
      register: result_authselect_present

    - name: Limit Password Reuse - Ensure authselect custom profile is used if authselect
        is present
      block:

      - name: Limit Password Reuse - 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: Limit Password Reuse - 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: Limit Password Reuse - 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: Limit Password Reuse - 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: Limit Password Reuse - 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: Limit Password Reuse - 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: Limit Password Reuse - 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: Limit Password Reuse - 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: Limit Password Reuse - 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: Limit Password Reuse - 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: Limit Password Reuse - 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: Limit Password Reuse - 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: Limit Password Reuse - 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: Limit Password Reuse - 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: Limit Password Reuse - Define a fact for control already filtered in case
        filters are used
      ansible.builtin.set_fact:
        pam_module_control: requisite

    - name: Limit Password Reuse - 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_pwhistory.so\s*.*
        state: absent
      check_mode: true
      changed_when: false
      register: result_pam_line_present

    - name: Limit Password Reuse - Include or update the PAM module line in {{ pam_file_path
        }}
      block:

      - name: Limit Password Reuse - 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_pwhistory.so\s*
          state: absent
        check_mode: true
        changed_when: false
        register: result_pam_line_other_control_present

      - name: Limit Password Reuse - 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_pwhistory.so.*)
          replace: \1{{ pam_module_control }} \2
        register: result_pam_module_edit
        when:
        - result_pam_line_other_control_present.found == 1

      - name: Limit Password Reuse - Ensure the required PAM module line is included
          in {{ pam_file_path }}
        ansible.builtin.lineinfile:
          dest: '{{ pam_file_path }}'
          insertafter: ^password.*requisite.*pam_pwquality\.so
          line: password    {{ pam_module_control }}    pam_pwhistory.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: Limit Password Reuse - 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
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - '"libpwquality" in ansible_facts.packages'
    - |
      (result_authselect_available_features.stdout is defined and result_authselect_available_features.stdout is not search("with-pwhistory")) or result_authselect_available_features is not defined
    tags:
    - CJIS-5.6.2.1.1
    - NIST-800-171-3.5.8
    - NIST-800-53-IA-5(1)(e)
    - NIST-800-53-IA-5(f)
    - PCI-DSS-Req-8.2.5
    - PCI-DSSv4-8.3
    - PCI-DSSv4-8.3.7
    - accounts_password_pam_unix_remember
    - configure_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - no_reboot_needed

  - name: Limit Password Reuse - Check the presence of /etc/security/pwhistory.conf
      file
    ansible.builtin.stat:
      path: /etc/security/pwhistory.conf
    register: result_pwhistory_conf_check
    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
    - NIST-800-171-3.5.8
    - NIST-800-53-IA-5(1)(e)
    - NIST-800-53-IA-5(f)
    - PCI-DSS-Req-8.2.5
    - PCI-DSSv4-8.3
    - PCI-DSSv4-8.3.7
    - accounts_password_pam_unix_remember
    - configure_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - no_reboot_needed

  - name: Limit Password Reuse - pam_pwhistory.so parameters are configured in /etc/security/pwhistory.conf
      file
    block:

    - name: Limit Password Reuse - Ensure the pam_pwhistory.so remember parameter
        in /etc/security/pwhistory.conf
      ansible.builtin.lineinfile:
        path: /etc/security/pwhistory.conf
        regexp: ^\s*remember\s*=
        line: remember = {{ var_password_pam_unix_remember }}
        state: present

    - name: Limit Password Reuse - Ensure the pam_pwhistory.so remember parameter
        is removed from PAM files
      block:

      - name: Limit Password Reuse - 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: Limit Password Reuse - Check the proper remediation for the system
        block:

        - name: Limit Password Reuse - Define the PAM file to be edited as a local
            fact
          ansible.builtin.set_fact:
            pam_file_path: /etc/pam.d/system-auth

        - name: Limit Password Reuse - Check if system relies on authselect tool
          ansible.builtin.stat:
            path: /usr/bin/authselect
          register: result_authselect_present

        - name: Limit Password Reuse - Ensure authselect custom profile is used if
            authselect is present
          block:

          - name: Limit Password Reuse - 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: Limit Password Reuse - 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: Limit Password Reuse - 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: Limit Password Reuse - 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: Limit Password Reuse - 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: Limit Password Reuse - 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: Limit Password Reuse - 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: Limit Password Reuse - 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: Limit Password Reuse - 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: Limit Password Reuse - 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: Limit Password Reuse - 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: Limit Password Reuse - 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: Limit Password Reuse - 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: Limit Password Reuse - 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: Limit Password Reuse - Define a fact for control already filtered
            in case filters are used
          ansible.builtin.set_fact:
            pam_module_control: ''

        - name: Limit Password Reuse - Check if {{ pam_file_path }} file is present
          ansible.builtin.stat:
            path: '{{ pam_file_path }}'
          register: result_pam_file_present

        - name: Limit Password Reuse - Ensure the "remember" option from "pam_pwhistory.so"
            is not present in {{ pam_file_path }}
          ansible.builtin.replace:
            dest: '{{ pam_file_path }}'
            regexp: (.*password.*pam_pwhistory.so.*)\bremember\b=?[0-9a-zA-Z]*(.*)
            replace: \1\2
          register: result_pam_option_removal
          when:
          - result_pam_file_present.stat.exists

        - name: Limit Password Reuse - 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
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - '"libpwquality" in ansible_facts.packages'
    - result_pwhistory_conf_check.stat.exists
    tags:
    - CJIS-5.6.2.1.1
    - NIST-800-171-3.5.8
    - NIST-800-53-IA-5(1)(e)
    - NIST-800-53-IA-5(f)
    - PCI-DSS-Req-8.2.5
    - PCI-DSSv4-8.3
    - PCI-DSSv4-8.3.7
    - accounts_password_pam_unix_remember
    - configure_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - no_reboot_needed

  - name: Limit Password Reuse - pam_pwhistory.so parameters are configured in PAM
      files
    block:

    - name: Limit Password Reuse - Define the PAM file to be edited as a local fact
      ansible.builtin.set_fact:
        pam_file_path: /etc/pam.d/system-auth

    - name: Limit Password Reuse - Check if system relies on authselect tool
      ansible.builtin.stat:
        path: /usr/bin/authselect
      register: result_authselect_present

    - name: Limit Password Reuse - Ensure authselect custom profile is used if authselect
        is present
      block:

      - name: Limit Password Reuse - 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: Limit Password Reuse - 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: Limit Password Reuse - 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: Limit Password Reuse - 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: Limit Password Reuse - 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: Limit Password Reuse - 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: Limit Password Reuse - 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: Limit Password Reuse - 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: Limit Password Reuse - 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: Limit Password Reuse - 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: Limit Password Reuse - 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: Limit Password Reuse - 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: Limit Password Reuse - 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: Limit Password Reuse - 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: Limit Password Reuse - Define a fact for control already filtered in case
        filters are used
      ansible.builtin.set_fact:
        pam_module_control: requisite

    - name: Limit Password Reuse - 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_pwhistory.so\s*.*
        state: absent
      check_mode: true
      changed_when: false
      register: result_pam_line_present

    - name: Limit Password Reuse - Include or update the PAM module line in {{ pam_file_path
        }}
      block:

      - name: Limit Password Reuse - 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_pwhistory.so\s*
          state: absent
        check_mode: true
        changed_when: false
        register: result_pam_line_other_control_present

      - name: Limit Password Reuse - 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_pwhistory.so.*)
          replace: \1{{ pam_module_control }} \2
        register: result_pam_module_edit
        when:
        - result_pam_line_other_control_present.found == 1

      - name: Limit Password Reuse - 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_pwhistory.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: Limit Password Reuse - 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: Limit Password Reuse - Define a fact for control already filtered in case
        filters are used
      ansible.builtin.set_fact:
        pam_module_control: requisite

    - name: Limit Password Reuse - 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_pwhistory.so\s*.*\sremember\b
        state: absent
      check_mode: true
      changed_when: false
      register: result_pam_module_accounts_password_pam_unix_remember_option_present

    - name: Limit Password Reuse - Ensure the "remember" PAM option for "pam_pwhistory.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_pwhistory.so.*)
        line: \1 remember={{ var_password_pam_unix_remember }}
        state: present
      register: result_pam_accounts_password_pam_unix_remember_add
      when:
      - result_pam_module_accounts_password_pam_unix_remember_option_present.found
        is defined
      - result_pam_module_accounts_password_pam_unix_remember_option_present.found
        == 0

    - name: Limit Password Reuse - Ensure the required value for "remember" PAM option
        from "pam_pwhistory.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_pwhistory.so\s+.*)(remember)=[0-9a-zA-Z]*\s*(.*)
        line: \1\2={{ var_password_pam_unix_remember }} \3
      register: result_pam_accounts_password_pam_unix_remember_edit
      when:
      - result_pam_module_accounts_password_pam_unix_remember_option_present.found
        > 0

    - name: Limit Password Reuse - Ensure authselect changes are applied
      ansible.builtin.command:
        cmd: authselect apply-changes -b
      when:
      - result_authselect_present.stat.exists
      - (result_pam_remember_add is defined and result_pam_remember_add.changed) or
        (result_pam_remember_edit is defined and result_pam_remember_edit.changed)
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - '"libpwquality" in ansible_facts.packages'
    - not result_pwhistory_conf_check.stat.exists
    tags:
    - CJIS-5.6.2.1.1
    - NIST-800-171-3.5.8
    - NIST-800-53-IA-5(1)(e)
    - NIST-800-53-IA-5(f)
    - PCI-DSS-Req-8.2.5
    - PCI-DSSv4-8.3
    - PCI-DSSv4-8.3.7
    - accounts_password_pam_unix_remember
    - configure_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - no_reboot_needed

  - 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: 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 - 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 - 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: 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 - 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)
    - '"pam" in ansible_facts.packages'
    tags:
    - CJIS-5.6.2.2
    - 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
    - configure_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - no_reboot_needed
    - set_password_hashing_algorithm_systemauth

  - name: Set PAM Password Hashing Algorithm - system-auth - Check the proper remediation
      for the system
    block:

    - name: Set PAM Password Hashing Algorithm - 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 PAM Password Hashing Algorithm - system-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 - system-auth - Ensure authselect custom
        profile is used if authselect is present
      block:

      - name: Set PAM Password Hashing Algorithm - 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 PAM Password Hashing Algorithm - 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 PAM Password Hashing Algorithm - 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 PAM Password Hashing Algorithm - 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 PAM Password Hashing Algorithm - 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 PAM Password Hashing Algorithm - 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 PAM Password Hashing Algorithm - 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 PAM Password Hashing Algorithm - 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 PAM Password Hashing Algorithm - 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 PAM Password Hashing Algorithm - 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 PAM Password Hashing Algorithm - 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 PAM Password Hashing Algorithm - 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 PAM Password Hashing Algorithm - 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 PAM Password Hashing Algorithm - 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 PAM Password Hashing Algorithm - system-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 - 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 PAM Password Hashing Algorithm - system-auth - Include or update the
        PAM module line in {{ pam_file_path }}
      block:

      - name: Set PAM Password Hashing Algorithm - 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 PAM Password Hashing Algorithm - 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 PAM Password Hashing Algorithm - 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 PAM Password Hashing Algorithm - 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 PAM Password Hashing Algorithm - system-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 - 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*.*\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_systemauth_option_present

    - name: Set PAM Password Hashing Algorithm - system-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_systemauth_add
      when:
      - result_pam_module_set_password_hashing_algorithm_systemauth_option_present.found
        is defined
      - result_pam_module_set_password_hashing_algorithm_systemauth_option_present.found
        == 0

    - name: Set PAM Password Hashing Algorithm - system-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_systemauth_add is defined and result_pam_set_password_hashing_algorithm_systemauth_add.changed)
         or (result_pam_set_password_hashing_algorithm_systemauth_edit is defined and result_pam_set_password_hashing_algorithm_systemauth_edit.changed)
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - '"pam" in ansible_facts.packages'
    - result_pam_auth_file_present.stat.exists
    tags:
    - CJIS-5.6.2.2
    - 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
    - configure_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - no_reboot_needed
    - set_password_hashing_algorithm_systemauth

  - name: Set PAM Password Hashing Algorithm - 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)
    - '"pam" in ansible_facts.packages'
    tags:
    - CJIS-5.6.2.2
    - 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
    - configure_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - no_reboot_needed
    - set_password_hashing_algorithm_systemauth

  - name: Set PAM Password Hashing Algorithm - system-auth - Check The Proper Remediation
      For The System
    block:

    - name: Set PAM Password Hashing Algorithm - 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 PAM Password Hashing Algorithm - system-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 - system-auth - Ensure authselect custom
        profile is used if authselect is present
      block:

      - name: Set PAM Password Hashing Algorithm - 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 PAM Password Hashing Algorithm - 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 PAM Password Hashing Algorithm - 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 PAM Password Hashing Algorithm - 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 PAM Password Hashing Algorithm - 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 PAM Password Hashing Algorithm - 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 PAM Password Hashing Algorithm - 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 PAM Password Hashing Algorithm - 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 PAM Password Hashing Algorithm - 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 PAM Password Hashing Algorithm - 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 PAM Password Hashing Algorithm - 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 PAM Password Hashing Algorithm - 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 PAM Password Hashing Algorithm - 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 PAM Password Hashing Algorithm - 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 PAM Password Hashing Algorithm - system-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 - system-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 - system-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_auth_file_present.stat.exists
    tags:
    - CJIS-5.6.2.2
    - 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
    - configure_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - no_reboot_needed
    - set_password_hashing_algorithm_systemauth

  - 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: 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: Set Existing Passwords Warning Age - Collect Users With Incorrect Number
      of Days of Warning Before Password Expires
    ansible.builtin.command:
      cmd: awk -F':' '(($6 < {{ var_accounts_password_warn_age_login_defs }} || $6
        == "") && $2 ~ /^\$/) {print $1}' /etc/shadow
    register: result_pass_warn_age_user_names
    changed_when: false
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - 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_warn_age_existing
    - configure_strategy
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

  - name: Set Existing Passwords Warning Age - Ensure the Number of Days of Warning
      Before Password Expires
    ansible.builtin.command:
      cmd: chage --warndays {{ var_accounts_password_warn_age_login_defs }} {{ item
        }}
    with_items: '{{ result_pass_warn_age_user_names.stdout_lines }}'
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - result_pass_warn_age_user_names is not skipped and result_pass_warn_age_user_names.stdout_lines
      | length > 0
    tags:
    - 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_warn_age_existing
    - configure_strategy
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

  - name: Set Password Warning Age
    ansible.builtin.lineinfile:
      dest: /etc/login.defs
      regexp: ^PASS_WARN_AGE *[0-9]*
      state: present
      line: PASS_WARN_AGE        {{ var_accounts_password_warn_age_login_defs }}
      create: true
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - '"shadow-utils" in ansible_facts.packages'
    tags:
    - 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)
    - PCI-DSS-Req-8.2.4
    - PCI-DSSv4-8.3
    - PCI-DSSv4-8.3.9
    - accounts_password_warn_age_login_defs
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Collect users with not correct INACTIVE parameter set
    ansible.builtin.command:
      cmd: awk -F':' '(($7 > {{ var_account_disable_post_pw_expiration }} || $7 ==
        "") && $2 ~ /^\$/) {print $1}' /etc/shadow
    register: user_names
    changed_when: false
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - 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
    - accounts_set_post_pw_existing
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Change the period of inactivity
    ansible.builtin.command:
      cmd: chage --inactive {{ var_account_disable_post_pw_expiration }} {{ item }}
    with_items: '{{ user_names.stdout_lines }}'
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - user_names is not skipped and user_names.stdout_lines | length > 0
    tags:
    - 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
    - accounts_set_post_pw_existing
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - 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: Direct root Logins Not Allowed
    ansible.builtin.copy:
      dest: /etc/securetty
      content: ''
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - NIST-800-171-3.1.1
    - NIST-800-171-3.1.6
    - NIST-800-53-CM-6(a)
    - NIST-800-53-IA-2
    - PCI-DSSv4-8.6
    - PCI-DSSv4-8.6.1
    - low_complexity
    - low_disruption
    - medium_severity
    - no_direct_root_logins
    - no_reboot_needed
    - restrict_strategy

  - name: Ensure that System Accounts Are Locked - 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:
    - NIST-800-53-AC-6
    - NIST-800-53-CM-6(a)
    - PCI-DSSv4-8.2
    - PCI-DSSv4-8.2.2
    - low_complexity
    - medium_disruption
    - medium_severity
    - no_password_auth_for_systemaccounts
    - no_reboot_needed
    - restrict_strategy

  - name: Ensure that System Accounts Are Locked - 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:
    - NIST-800-53-AC-6
    - NIST-800-53-CM-6(a)
    - PCI-DSSv4-8.2
    - PCI-DSSv4-8.2.2
    - low_complexity
    - medium_disruption
    - medium_severity
    - no_password_auth_for_systemaccounts
    - no_reboot_needed
    - restrict_strategy

  - name: Ensure that System Accounts Are Locked - Lock System Accounts
    ansible.builtin.user:
      name: '{{ item.key }}'
      password_lock: true
    loop: '{{ local_users }}'
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - item.value[1]|int < 1000
    - item.key not in ['root', 'halt', 'sync', 'shutdown', 'nfsnobody']
    tags:
    - NIST-800-53-AC-6
    - NIST-800-53-CM-6(a)
    - PCI-DSSv4-8.2
    - PCI-DSSv4-8.2.2
    - low_complexity
    - medium_disruption
    - medium_severity
    - no_password_auth_for_systemaccounts
    - 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 Virtual Console Root Logins
    ansible.builtin.lineinfile:
      dest: /etc/securetty
      regexp: ^vc/[0-9]
      state: absent
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - NIST-800-171-3.1.1
    - NIST-800-171-3.1.5
    - NIST-800-53-AC-6
    - NIST-800-53-CM-6(a)
    - PCI-DSSv4-8.6
    - PCI-DSSv4-8.6.1
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy
    - securetty_root_login_console_only

  - 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: 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_groupowner_user_cfg_newgroup variable if represented by gid
    ansible.builtin.set_fact:
      file_groupowner_user_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
    - 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_user_cfg
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

  - name: Test for existence /boot/grub2/user.cfg
    ansible.builtin.stat:
      path: /boot/grub2/user.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
    - 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_user_cfg
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

  - name: Ensure group owner on /boot/grub2/user.cfg
    ansible.builtin.file:
      path: /boot/grub2/user.cfg
      follow: false
      group: '{{ file_groupowner_user_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
    - 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_user_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: Set the file_owner_user_cfg_newown variable if represented by uid
    ansible.builtin.set_fact:
      file_owner_user_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
    - 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_user_cfg
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

  - name: Test for existence /boot/grub2/user.cfg
    ansible.builtin.stat:
      path: /boot/grub2/user.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
    - 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_user_cfg
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

  - name: Ensure owner on /boot/grub2/user.cfg
    ansible.builtin.file:
      path: /boot/grub2/user.cfg
      follow: false
      owner: '{{ file_owner_user_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
    - 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_user_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:
    - NIST-800-171-3.4.5
    - 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_grub2_cfg
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

  - name: Ensure permission u-xs,g-xwrs,o-xwrt on /boot/grub2/grub.cfg
    ansible.builtin.file:
      path: /boot/grub2/grub.cfg
      mode: u-xs,g-xwrs,o-xwrt
    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:
    - NIST-800-171-3.4.5
    - 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_grub2_cfg
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

  - name: Test for existence /boot/grub2/user.cfg
    ansible.builtin.stat:
      path: /boot/grub2/user.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:
    - NIST-800-171-3.4.5
    - 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_user_cfg
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

  - name: Ensure permission u-xs,g-xwrs,o-xwrt on /boot/grub2/user.cfg
    ansible.builtin.file:
      path: /boot/grub2/user.cfg
      mode: u-xs,g-xwrs,o-xwrt
    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:
    - NIST-800-171-3.4.5
    - 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_user_cfg
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

  - name: Ensure Log Files Are Owned By Appropriate Group - Set rsyslog logfile configuration
      facts
    ansible.builtin.set_fact:
      rsyslog_etc_config: /etc/rsyslog.conf
    when:
    - '"rsyslog" in ansible_facts.packages'
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - NIST-800-53-AC-6(1)
    - NIST-800-53-CM-6(a)
    - PCI-DSS-Req-10.5.1
    - PCI-DSS-Req-10.5.2
    - PCI-DSSv4-10.3
    - PCI-DSSv4-10.3.2
    - configure_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - no_reboot_needed
    - rsyslog_files_groupownership

  - name: Ensure Log Files Are Owned By Appropriate Group - Get IncludeConfig directive
    ansible.builtin.shell: |
      set -o pipefail
      grep -e '$IncludeConfig' {{ rsyslog_etc_config }} | cut -d ' ' -f 2 || true
    register: rsyslog_old_inc
    changed_when: false
    when:
    - '"rsyslog" in ansible_facts.packages'
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - NIST-800-53-AC-6(1)
    - NIST-800-53-CM-6(a)
    - PCI-DSS-Req-10.5.1
    - PCI-DSS-Req-10.5.2
    - PCI-DSSv4-10.3
    - PCI-DSSv4-10.3.2
    - configure_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - no_reboot_needed
    - rsyslog_files_groupownership

  - name: Ensure Log Files Are Owned By Appropriate Group - Get include files directives
    ansible.builtin.shell: |
      set -o pipefail
      awk '/)/{f=0} /include\(/{f=1} f{ nf=gensub("^(include\\(|\\s*)file=\"(\\S+)\".*","\\2",1); if($0!=nf){ print nf }}' {{ rsyslog_etc_config }} || true
    register: rsyslog_new_inc
    changed_when: false
    when:
    - '"rsyslog" in ansible_facts.packages'
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - NIST-800-53-AC-6(1)
    - NIST-800-53-CM-6(a)
    - PCI-DSS-Req-10.5.1
    - PCI-DSS-Req-10.5.2
    - PCI-DSSv4-10.3
    - PCI-DSSv4-10.3.2
    - configure_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - no_reboot_needed
    - rsyslog_files_groupownership

  - name: Ensure Log Files Are Owned By Appropriate Group - Aggregate rsyslog includes
    ansible.builtin.set_fact:
      include_config_output: '{{ rsyslog_old_inc.stdout_lines + rsyslog_new_inc.stdout_lines
        }}'
    when:
    - '"rsyslog" in ansible_facts.packages'
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - rsyslog_old_inc is not skipped and rsyslog_new_inc is not skipped
    tags:
    - NIST-800-53-AC-6(1)
    - NIST-800-53-CM-6(a)
    - PCI-DSS-Req-10.5.1
    - PCI-DSS-Req-10.5.2
    - PCI-DSSv4-10.3
    - PCI-DSSv4-10.3.2
    - configure_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - no_reboot_needed
    - rsyslog_files_groupownership

  - name: Ensure Log Files Are Owned By Appropriate Group - List all config files
    ansible.builtin.find:
      paths: '{{ item | dirname }}'
      patterns: '{{ item | basename }}'
      hidden: false
      follow: true
    loop: '{{ include_config_output | list + [rsyslog_etc_config] }}'
    when:
    - '"rsyslog" in ansible_facts.packages'
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - include_config_output is defined
    register: rsyslog_config_files
    failed_when: false
    changed_when: false
    tags:
    - NIST-800-53-AC-6(1)
    - NIST-800-53-CM-6(a)
    - PCI-DSS-Req-10.5.1
    - PCI-DSS-Req-10.5.2
    - PCI-DSSv4-10.3
    - PCI-DSSv4-10.3.2
    - configure_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - no_reboot_needed
    - rsyslog_files_groupownership

  - name: Ensure Log Files Are Owned By Appropriate Group - Extract log files old
      format
    ansible.builtin.shell: |
      set -o pipefail
      grep -oP '^[^(\s|#|\$)]+[\s]*.*[\s]+-?(/+[^:;\s]+);*\.*$' {{ item.1.path }} | \
      awk '{print $NF}' | \
      sed -e 's/^-//' || true
    loop: '{{ rsyslog_config_files.results | default([]) | subelements(''files'')
      }}'
    register: log_files_old
    changed_when: false
    when:
    - '"rsyslog" in ansible_facts.packages'
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - rsyslog_config_files is not skipped
    tags:
    - NIST-800-53-AC-6(1)
    - NIST-800-53-CM-6(a)
    - PCI-DSS-Req-10.5.1
    - PCI-DSS-Req-10.5.2
    - PCI-DSSv4-10.3
    - PCI-DSSv4-10.3.2
    - configure_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - no_reboot_needed
    - rsyslog_files_groupownership

  - name: Ensure Log Files Are Owned By Appropriate Group - Extract log files new
      format
    ansible.builtin.shell: |
      set -o pipefail
      grep -iozP "action\s*\(\s*type\s*=\s*\"omfile\"[^\)]*\)" {{ item.1.path }} | \
      grep -iaoP "\bFile\s*=\s*\"([/[:alnum:][:punct:]]*)\"\s*\)" | \
      grep -oE "\"([/[:alnum:][:punct:]]*)\"" | \
      tr -d "\"" | \
      grep -v '^/dev/' || true
    loop: '{{ rsyslog_config_files.results | default([]) | subelements(''files'')
      }}'
    register: log_files_new
    changed_when: false
    when:
    - '"rsyslog" in ansible_facts.packages'
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - rsyslog_config_files is not skipped
    tags:
    - NIST-800-53-AC-6(1)
    - NIST-800-53-CM-6(a)
    - PCI-DSS-Req-10.5.1
    - PCI-DSS-Req-10.5.2
    - PCI-DSSv4-10.3
    - PCI-DSSv4-10.3.2
    - configure_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - no_reboot_needed
    - rsyslog_files_groupownership

  - name: Ensure Log Files Are Owned By Appropriate Group - Sum all log files found
    ansible.builtin.set_fact:
      log_files: '{{ log_files_new.results | map(attribute=''stdout_lines'') | list
        | flatten | unique + log_files_old.results | map(attribute=''stdout_lines'')
        | list | flatten | unique }}'
    when:
    - '"rsyslog" in ansible_facts.packages'
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - NIST-800-53-AC-6(1)
    - NIST-800-53-CM-6(a)
    - PCI-DSS-Req-10.5.1
    - PCI-DSS-Req-10.5.2
    - PCI-DSSv4-10.3
    - PCI-DSSv4-10.3.2
    - configure_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - no_reboot_needed
    - rsyslog_files_groupownership

  - name: Ensure Log Files Are Owned By Appropriate Group -Setup log files attribute
    ansible.builtin.file:
      path: '{{ item }}'
      group: root
      state: file
    loop: '{{ log_files | list | flatten | unique }}'
    failed_when: false
    when:
    - '"rsyslog" in ansible_facts.packages'
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - NIST-800-53-AC-6(1)
    - NIST-800-53-CM-6(a)
    - PCI-DSS-Req-10.5.1
    - PCI-DSS-Req-10.5.2
    - PCI-DSSv4-10.3
    - PCI-DSSv4-10.3.2
    - configure_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - no_reboot_needed
    - rsyslog_files_groupownership

  - name: Ensure Log Files Are Owned By Appropriate User - Set rsyslog logfile configuration
      facts
    ansible.builtin.set_fact:
      rsyslog_etc_config: /etc/rsyslog.conf
    when:
    - '"rsyslog" in ansible_facts.packages'
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - NIST-800-53-AC-6(1)
    - NIST-800-53-CM-6(a)
    - PCI-DSS-Req-10.5.1
    - PCI-DSS-Req-10.5.2
    - PCI-DSSv4-10.3
    - PCI-DSSv4-10.3.2
    - configure_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - no_reboot_needed
    - rsyslog_files_ownership

  - name: Ensure Log Files Are Owned By Appropriate User - Get IncludeConfig directive
    ansible.builtin.shell: |
      set -o pipefail
      grep -e '$IncludeConfig' {{ rsyslog_etc_config }} | cut -d ' ' -f 2 || true
    register: rsyslog_old_inc
    changed_when: false
    when:
    - '"rsyslog" in ansible_facts.packages'
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - NIST-800-53-AC-6(1)
    - NIST-800-53-CM-6(a)
    - PCI-DSS-Req-10.5.1
    - PCI-DSS-Req-10.5.2
    - PCI-DSSv4-10.3
    - PCI-DSSv4-10.3.2
    - configure_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - no_reboot_needed
    - rsyslog_files_ownership

  - name: Ensure Log Files Are Owned By Appropriate User - Get include files directives
    ansible.builtin.shell: |
      set -o pipefail
      awk '/)/{f=0} /include\(/{f=1} f{ nf=gensub("^(include\\(|\\s*)file=\"(\\S+)\".*","\\2",1); if($0!=nf){ print nf }}' {{ rsyslog_etc_config }} || true
    register: rsyslog_new_inc
    changed_when: false
    when:
    - '"rsyslog" in ansible_facts.packages'
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - NIST-800-53-AC-6(1)
    - NIST-800-53-CM-6(a)
    - PCI-DSS-Req-10.5.1
    - PCI-DSS-Req-10.5.2
    - PCI-DSSv4-10.3
    - PCI-DSSv4-10.3.2
    - configure_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - no_reboot_needed
    - rsyslog_files_ownership

  - name: Ensure Log Files Are Owned By Appropriate User - Aggregate rsyslog includes
    ansible.builtin.set_fact:
      include_config_output: '{{ rsyslog_old_inc.stdout_lines + rsyslog_new_inc.stdout_lines
        }}'
    when:
    - '"rsyslog" in ansible_facts.packages'
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - rsyslog_old_inc is not skipped and rsyslog_new_inc is not skipped
    tags:
    - NIST-800-53-AC-6(1)
    - NIST-800-53-CM-6(a)
    - PCI-DSS-Req-10.5.1
    - PCI-DSS-Req-10.5.2
    - PCI-DSSv4-10.3
    - PCI-DSSv4-10.3.2
    - configure_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - no_reboot_needed
    - rsyslog_files_ownership

  - name: Ensure Log Files Are Owned By Appropriate User - List all config files
    ansible.builtin.find:
      paths: '{{ item | dirname }}'
      patterns: '{{ item | basename }}'
      hidden: false
      follow: true
    loop: '{{ include_config_output | list + [rsyslog_etc_config] }}'
    when:
    - '"rsyslog" in ansible_facts.packages'
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - include_config_output is defined
    register: rsyslog_config_files
    failed_when: false
    changed_when: false
    tags:
    - NIST-800-53-AC-6(1)
    - NIST-800-53-CM-6(a)
    - PCI-DSS-Req-10.5.1
    - PCI-DSS-Req-10.5.2
    - PCI-DSSv4-10.3
    - PCI-DSSv4-10.3.2
    - configure_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - no_reboot_needed
    - rsyslog_files_ownership

  - name: Ensure Log Files Are Owned By Appropriate User - Extract log files old format
    ansible.builtin.shell: |
      set -o pipefail
      grep -oP '^[^(\s|#|\$)]+[\s]*.*[\s]+-?(/+[^:;\s]+);*\.*$' {{ item.1.path }} | \
      awk '{print $NF}' | \
      sed -e 's/^-//' || true
    loop: '{{ rsyslog_config_files.results | default([]) | subelements(''files'')
      }}'
    register: log_files_old
    changed_when: false
    when:
    - '"rsyslog" in ansible_facts.packages'
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - rsyslog_config_files is not skipped
    tags:
    - NIST-800-53-AC-6(1)
    - NIST-800-53-CM-6(a)
    - PCI-DSS-Req-10.5.1
    - PCI-DSS-Req-10.5.2
    - PCI-DSSv4-10.3
    - PCI-DSSv4-10.3.2
    - configure_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - no_reboot_needed
    - rsyslog_files_ownership

  - name: Ensure Log Files Are Owned By Appropriate User - Extract log files new format
    ansible.builtin.shell: |
      set -o pipefail
      grep -iozP "action\s*\(\s*type\s*=\s*\"omfile\"[^\)]*\)" {{ item.1.path }} | \
      grep -iaoP "\bFile\s*=\s*\"([/[:alnum:][:punct:]]*)\"\s*\)" | \
      grep -oE "\"([/[:alnum:][:punct:]]*)\"" | \
      tr -d "\"" | \
      grep -v '^/dev/' || true
    loop: '{{ rsyslog_config_files.results | default([]) | subelements(''files'')
      }}'
    register: log_files_new
    changed_when: false
    when:
    - '"rsyslog" in ansible_facts.packages'
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - rsyslog_config_files is not skipped
    tags:
    - NIST-800-53-AC-6(1)
    - NIST-800-53-CM-6(a)
    - PCI-DSS-Req-10.5.1
    - PCI-DSS-Req-10.5.2
    - PCI-DSSv4-10.3
    - PCI-DSSv4-10.3.2
    - configure_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - no_reboot_needed
    - rsyslog_files_ownership

  - name: Ensure Log Files Are Owned By Appropriate User - Sum all log files found
    ansible.builtin.set_fact:
      log_files: '{{ log_files_new.results | map(attribute=''stdout_lines'') | list
        | flatten | unique + log_files_old.results | map(attribute=''stdout_lines'')
        | list | flatten | unique }}'
    when:
    - '"rsyslog" in ansible_facts.packages'
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - NIST-800-53-AC-6(1)
    - NIST-800-53-CM-6(a)
    - PCI-DSS-Req-10.5.1
    - PCI-DSS-Req-10.5.2
    - PCI-DSSv4-10.3
    - PCI-DSSv4-10.3.2
    - configure_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - no_reboot_needed
    - rsyslog_files_ownership

  - name: Ensure Log Files Are Owned By Appropriate User -Setup log files attribute
    ansible.builtin.file:
      path: '{{ item }}'
      owner: root
      state: file
    loop: '{{ log_files | list | flatten | unique }}'
    failed_when: false
    when:
    - '"rsyslog" in ansible_facts.packages'
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - NIST-800-53-AC-6(1)
    - NIST-800-53-CM-6(a)
    - PCI-DSS-Req-10.5.1
    - PCI-DSS-Req-10.5.2
    - PCI-DSSv4-10.3
    - PCI-DSSv4-10.3.2
    - configure_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - no_reboot_needed
    - rsyslog_files_ownership

  - name: Ensure System Log Files Have Correct Permissions - Set rsyslog logfile configuration
      facts
    ansible.builtin.set_fact:
      rsyslog_etc_config: /etc/rsyslog.conf
    when:
    - '"rsyslog" in ansible_facts.packages'
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - NIST-800-53-AC-6(1)
    - NIST-800-53-CM-6(a)
    - PCI-DSS-Req-10.5.1
    - PCI-DSS-Req-10.5.2
    - PCI-DSSv4-10.3
    - PCI-DSSv4-10.3.1
    - configure_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - no_reboot_needed
    - rsyslog_files_permissions

  - name: Ensure System Log Files Have Correct Permissions - Get IncludeConfig directive
    ansible.builtin.shell: |
      set -o pipefail
      grep -e '$IncludeConfig' {{ rsyslog_etc_config }} | cut -d ' ' -f 2 || true
    register: rsyslog_old_inc
    changed_when: false
    when:
    - '"rsyslog" in ansible_facts.packages'
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - NIST-800-53-AC-6(1)
    - NIST-800-53-CM-6(a)
    - PCI-DSS-Req-10.5.1
    - PCI-DSS-Req-10.5.2
    - PCI-DSSv4-10.3
    - PCI-DSSv4-10.3.1
    - configure_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - no_reboot_needed
    - rsyslog_files_permissions

  - name: Ensure System Log Files Have Correct Permissions - Get include files directives
    ansible.builtin.shell: |
      set -o pipefail
      awk '/)/{f=0} /include\(/{f=1} f{ nf=gensub("^(include\\(|\\s*)file=\"(\\S+)\".*","\\2",1); if($0!=nf){ print nf }}' {{ rsyslog_etc_config }} || true
    register: rsyslog_new_inc
    changed_when: false
    when:
    - '"rsyslog" in ansible_facts.packages'
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - NIST-800-53-AC-6(1)
    - NIST-800-53-CM-6(a)
    - PCI-DSS-Req-10.5.1
    - PCI-DSS-Req-10.5.2
    - PCI-DSSv4-10.3
    - PCI-DSSv4-10.3.1
    - configure_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - no_reboot_needed
    - rsyslog_files_permissions

  - name: Ensure System Log Files Have Correct Permissions - Aggregate rsyslog includes
    ansible.builtin.set_fact:
      include_config_output: '{{ rsyslog_old_inc.stdout_lines + rsyslog_new_inc.stdout_lines
        }}'
    when:
    - '"rsyslog" in ansible_facts.packages'
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - rsyslog_old_inc is not skipped and rsyslog_new_inc is not skipped
    tags:
    - NIST-800-53-AC-6(1)
    - NIST-800-53-CM-6(a)
    - PCI-DSS-Req-10.5.1
    - PCI-DSS-Req-10.5.2
    - PCI-DSSv4-10.3
    - PCI-DSSv4-10.3.1
    - configure_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - no_reboot_needed
    - rsyslog_files_permissions

  - name: Ensure System Log Files Have Correct Permissions - List all config files
    ansible.builtin.find:
      paths: '{{ item | dirname }}'
      patterns: '{{ item | basename }}'
      hidden: false
      follow: true
    loop: '{{ include_config_output | list + [rsyslog_etc_config] }}'
    when:
    - '"rsyslog" in ansible_facts.packages'
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - include_config_output is defined
    register: rsyslog_config_files
    failed_when: false
    changed_when: false
    tags:
    - NIST-800-53-AC-6(1)
    - NIST-800-53-CM-6(a)
    - PCI-DSS-Req-10.5.1
    - PCI-DSS-Req-10.5.2
    - PCI-DSSv4-10.3
    - PCI-DSSv4-10.3.1
    - configure_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - no_reboot_needed
    - rsyslog_files_permissions

  - name: Ensure System Log Files Have Correct Permissions - Extract log files old
      format
    ansible.builtin.shell: |
      set -o pipefail
      grep -oP '^[^(\s|#|\$)]+[\s]*.*[\s]+-?(/+[^:;\s]+);*\.*$' {{ item.1.path }} | \
      awk '{print $NF}' | \
      sed -e 's/^-//' || true
    loop: '{{ rsyslog_config_files.results | default([]) | subelements(''files'')
      }}'
    register: log_files_old
    changed_when: false
    when:
    - '"rsyslog" in ansible_facts.packages'
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - rsyslog_config_files is not skipped
    tags:
    - NIST-800-53-AC-6(1)
    - NIST-800-53-CM-6(a)
    - PCI-DSS-Req-10.5.1
    - PCI-DSS-Req-10.5.2
    - PCI-DSSv4-10.3
    - PCI-DSSv4-10.3.1
    - configure_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - no_reboot_needed
    - rsyslog_files_permissions

  - name: Ensure System Log Files Have Correct Permissions - Extract log files new
      format
    ansible.builtin.shell: |
      set -o pipefail
      grep -iozP "action\s*\(\s*type\s*=\s*\"omfile\"[^\)]*\)" {{ item.1.path }} | \
      grep -iaoP "\bFile\s*=\s*\"([/[:alnum:][:punct:]]*)\"\s*\)" | \
      grep -oE "\"([/[:alnum:][:punct:]]*)\"" | \
      tr -d "\"" | \
      grep -v '^/dev/' || true
    loop: '{{ rsyslog_config_files.results | default([]) | subelements(''files'')
      }}'
    register: log_files_new
    changed_when: false
    when:
    - '"rsyslog" in ansible_facts.packages'
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - rsyslog_config_files is not skipped
    tags:
    - NIST-800-53-AC-6(1)
    - NIST-800-53-CM-6(a)
    - PCI-DSS-Req-10.5.1
    - PCI-DSS-Req-10.5.2
    - PCI-DSSv4-10.3
    - PCI-DSSv4-10.3.1
    - configure_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - no_reboot_needed
    - rsyslog_files_permissions

  - name: Ensure System Log Files Have Correct Permissions - Sum all log files found
    ansible.builtin.set_fact:
      log_files: '{{ log_files_new.results | map(attribute=''stdout_lines'') | list
        | flatten | unique + log_files_old.results | map(attribute=''stdout_lines'')
        | list | flatten | unique }}'
    when:
    - '"rsyslog" in ansible_facts.packages'
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - NIST-800-53-AC-6(1)
    - NIST-800-53-CM-6(a)
    - PCI-DSS-Req-10.5.1
    - PCI-DSS-Req-10.5.2
    - PCI-DSSv4-10.3
    - PCI-DSSv4-10.3.1
    - configure_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - no_reboot_needed
    - rsyslog_files_permissions

  - name: Ensure System Log Files Have Correct Permissions -Setup log files attribute
    ansible.builtin.file:
      path: '{{ item }}'
      mode: '0640'
      state: file
    loop: '{{ log_files | list | flatten | unique }}'
    failed_when: false
    when:
    - '"rsyslog" in ansible_facts.packages'
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - NIST-800-53-AC-6(1)
    - NIST-800-53-CM-6(a)
    - PCI-DSS-Req-10.5.1
    - PCI-DSS-Req-10.5.2
    - PCI-DSSv4-10.3
    - PCI-DSSv4-10.3.1
    - configure_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - no_reboot_needed
    - rsyslog_files_permissions

  - name: Enable timer logrotate
    block:

    - name: Enable timer logrotate
      ansible.builtin.systemd:
        name: logrotate.timer
        enabled: 'yes'
        state: started
      when:
      - '"logrotate" in ansible_facts.packages'
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - ( ansible_distribution == 'OracleLinux' and ansible_distribution_version is
      version('9', '>=') and "logrotate" in ansible_facts.packages )
    tags:
    - NIST-800-53-CM-6(a)
    - PCI-DSS-Req-10.7
    - PCI-DSSv4-10.5
    - PCI-DSSv4-10.5.1
    - enable_strategy
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - timer_logrotate_enabled

  - name: Prevent non-Privileged Users from Modifying Network Interfaces using nmcli
      - Ensure non-privileged users do not have access to nmcli
    community.general.ini_file:
      path: /etc/polkit-1/localauthority/20-org.d/10-nm-harden-access.pkla
      section: Disable General User Access to NetworkManager
      option: '{{ item.option }}'
      value: '{{ item.value }}'
      no_extra_spaces: true
      create: true
    loop:
    - option: Identity
      value: default
    - option: Action
      value: org.freedesktop.NetworkManager.*
    - option: ResultAny
      value: 'no'
    - option: ResultInactive
      value: 'no'
    - option: ResultActive
      value: auth_admin
    when: '"polkit" in ansible_facts.packages'
    tags:
    - NIST-800-171-3.1.16
    - NIST-800-53-AC-18(4)
    - NIST-800-53-CM-6(a)
    - PCI-DSSv4-1.2
    - PCI-DSSv4-1.2.8
    - low_complexity
    - low_disruption
    - medium_severity
    - network_nmcli_permissions
    - no_reboot_needed
    - restrict_strategy

  - 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: Configure Firewalld to Restrict Loopback Traffic - Remediation is Applicable
      if firewalld Service is Running
    block:

    - name: Configure Firewalld to Restrict Loopback Traffic - Ensure firewalld trusted
        Zone Restricts IPv4 Loopback Traffic
      ansible.builtin.command:
        cmd: firewall-cmd --permanent --zone=trusted --add-rich-rule='rule family=ipv4
          source address="127.0.0.1" destination not address="127.0.0.1" drop'
      register: result_trusted_ipv4_restriction
      changed_when:
      - '''ALREADY_ENABLED'' not in result_trusted_ipv4_restriction.stderr'

    - name: Configure Firewalld to Restrict Loopback Traffic - Ensure firewalld trusted
        Zone Restricts IPv6 Loopback Traffic
      ansible.builtin.command:
        cmd: firewall-cmd --permanent --zone=trusted --add-rich-rule='rule family=ipv6
          source address="::1" destination not address="::1" drop'
      register: result_trusted_ipv6_restriction
      changed_when:
      - '''ALREADY_ENABLED'' not in result_trusted_ipv6_restriction.stderr'

    - name: Configure Firewalld to Restrict Loopback Traffic - Ensure firewalld Changes
        are Applied
      ansible.builtin.service:
        name: firewalld
        state: reloaded
      when:
      - result_trusted_ipv4_restriction is changed or result_trusted_ipv6_restriction
        is changed
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - ansible_facts.services['firewalld.service'].state == 'running'
    tags:
    - PCI-DSSv4-1.4
    - PCI-DSSv4-1.4.1
    - configure_strategy
    - firewalld_loopback_traffic_restricted
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

  - name: Configure Firewalld to Restrict Loopback Traffic - Informative Message Based
      on Service State
    ansible.builtin.assert:
      that:
      - ansible_check_mode or ansible_facts.services['firewalld.service'].state ==
        'running'
      fail_msg:
      - firewalld service is not active. Remediation aborted!
      - This remediation could not be applied because it depends on firewalld service
        running.
      - The service is not started by this remediation in order to prevent connection
        issues.
      success_msg:
      - Configure Firewalld to Restrict Loopback Traffic remediation successfully
        executed
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - PCI-DSSv4-1.4
    - PCI-DSSv4-1.4.1
    - configure_strategy
    - firewalld_loopback_traffic_restricted
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

  - name: Configure Firewalld to Trust Loopback Traffic - Remediation is Applicable
      if firewalld Service is Running
    block:

    - name: Configure Firewalld to Trust Loopback Traffic - Ensure firewalld trusted
        Zone Includes lo Interface
      ansible.builtin.command:
        cmd: firewall-cmd --permanent --zone=trusted --add-interface=lo
      register: result_lo_interface_assignment
      changed_when:
      - '''ALREADY_ENABLED'' not in result_lo_interface_assignment.stderr'

    - name: Configure Firewalld to Trust Loopback Traffic - Ensure firewalld Changes
        are Applied
      ansible.builtin.service:
        name: firewalld
        state: reloaded
      when:
      - result_lo_interface_assignment is changed
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - ansible_facts.services['firewalld.service'].state == 'running'
    tags:
    - PCI-DSSv4-1.4
    - PCI-DSSv4-1.4.1
    - configure_strategy
    - firewalld_loopback_traffic_trusted
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

  - name: Configure Firewalld to Trust Loopback Traffic - Informative Message Based
      on Service State
    ansible.builtin.assert:
      that:
      - ansible_check_mode or ansible_facts.services['firewalld.service'].state ==
        'running'
      fail_msg:
      - firewalld service is not active. Remediation aborted!
      - This remediation could not be applied because it depends on firewalld service
        running.
      - The service is not started by this remediation in order to prevent connection
        issues.
      success_msg:
      - Configure Firewalld to Trust Loopback Traffic remediation successfully executed
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - PCI-DSSv4-1.4
    - PCI-DSSv4-1.4.1
    - configure_strategy
    - firewalld_loopback_traffic_trusted
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

  - 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: 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 Secure 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:
    - 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_secure_redirects

  - name: Disable Kernel Parameter for Accepting Secure ICMP Redirects on all IPv4
      Interfaces - Find all files that contain net.ipv4.conf.all.secure_redirects
    ansible.builtin.shell:
      cmd: find -L {{ sysctl_paths | join(" ") }} -type f -name '*.conf' | xargs grep
        -HP '^\s*net.ipv4.conf.all.secure_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:
    - 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_secure_redirects

  - name: Disable Kernel Parameter for Accepting Secure ICMP Redirects on all IPv4
      Interfaces - Find all files that set net.ipv4.conf.all.secure_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.secure_redirects\s*=\s*{{ sysctl_net_ipv4_conf_all_secure_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:
    - 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_secure_redirects

  - name: Disable Kernel Parameter for Accepting Secure ICMP Redirects on all IPv4
      Interfaces - Comment out any occurrences of net.ipv4.conf.all.secure_redirects
      from config files
    ansible.builtin.replace:
      path: '{{ item | split(":") | first }}'
      regexp: ^[\s]*net.ipv4.conf.all.secure_redirects
      replace: '#net.ipv4.conf.all.secure_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:
    - 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_secure_redirects

  - name: Disable Kernel Parameter for Accepting Secure ICMP Redirects on all IPv4
      Interfaces - Comment out any occurrences of net.ipv4.conf.all.secure_redirects
      from /etc/sysctl.conf
    ansible.builtin.replace:
      path: '{{ item }}'
      regexp: ^[\s]*net.ipv4.conf.all.secure_redirects
      replace: '#net.ipv4.conf.all.secure_redirects'
    with_fileglob:
    - /etc/sysctl.conf
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - 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_secure_redirects

  - name: Disable Kernel Parameter for Accepting Secure ICMP Redirects on all IPv4
      Interfaces - Ensure sysctl net.ipv4.conf.all.secure_redirects is set
    ansible.posix.sysctl:
      name: net.ipv4.conf.all.secure_redirects
      value: '{{ sysctl_net_ipv4_conf_all_secure_redirects_value }}'
      sysctl_file: /etc/sysctl.d/net_ipv4_conf_all_secure_redirects.conf
      state: present
      reload: true
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - 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_secure_redirects

  - 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: 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: Disable Kernel Parameter for IP Forwarding 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:
    - 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-DSS-Req-1.3.1
    - PCI-DSS-Req-1.3.2
    - PCI-DSSv4-1.4
    - PCI-DSSv4-1.4.3
    - disable_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - reboot_required
    - sysctl_net_ipv4_ip_forward

  - name: Disable Kernel Parameter for IP Forwarding on IPv4 Interfaces - Find all
      files that contain net.ipv4.ip_forward
    ansible.builtin.shell:
      cmd: find -L {{ sysctl_paths | join(" ") }} -type f -name '*.conf' | xargs grep
        -HP '^\s*net.ipv4.ip_forward\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:
    - 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-DSS-Req-1.3.1
    - PCI-DSS-Req-1.3.2
    - PCI-DSSv4-1.4
    - PCI-DSSv4-1.4.3
    - disable_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - reboot_required
    - sysctl_net_ipv4_ip_forward

  - name: Disable Kernel Parameter for IP Forwarding on IPv4 Interfaces - Find all
      files that set net.ipv4.ip_forward to correct value
    ansible.builtin.shell:
      cmd: find -L {{ sysctl_paths | join(" ") }} -type f -name '*.conf' | xargs grep
        -HP '^\s*net.ipv4.ip_forward\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:
    - 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-DSS-Req-1.3.1
    - PCI-DSS-Req-1.3.2
    - PCI-DSSv4-1.4
    - PCI-DSSv4-1.4.3
    - disable_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - reboot_required
    - sysctl_net_ipv4_ip_forward

  - name: Disable Kernel Parameter for IP Forwarding on IPv4 Interfaces - Comment
      out any occurrences of net.ipv4.ip_forward from config files
    ansible.builtin.replace:
      path: '{{ item | split(":") | first }}'
      regexp: ^[\s]*net.ipv4.ip_forward
      replace: '#net.ipv4.ip_forward'
    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:
    - 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-DSS-Req-1.3.1
    - PCI-DSS-Req-1.3.2
    - PCI-DSSv4-1.4
    - PCI-DSSv4-1.4.3
    - disable_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - reboot_required
    - sysctl_net_ipv4_ip_forward

  - name: Disable Kernel Parameter for IP Forwarding on IPv4 Interfaces - Comment
      out any occurrences of net.ipv4.ip_forward from /etc/sysctl.conf
    ansible.builtin.replace:
      path: '{{ item }}'
      regexp: ^[\s]*net.ipv4.ip_forward
      replace: '#net.ipv4.ip_forward'
    with_fileglob:
    - /etc/sysctl.conf
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - 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-DSS-Req-1.3.1
    - PCI-DSS-Req-1.3.2
    - PCI-DSSv4-1.4
    - PCI-DSSv4-1.4.3
    - disable_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - reboot_required
    - sysctl_net_ipv4_ip_forward

  - name: Disable Kernel Parameter for IP Forwarding on IPv4 Interfaces - Ensure sysctl
      net.ipv4.ip_forward is set to 0
    ansible.posix.sysctl:
      name: net.ipv4.ip_forward
      value: '0'
      sysctl_file: /etc/sysctl.d/net_ipv4_ip_forward.conf
      state: present
      reload: true
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - 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-DSS-Req-1.3.1
    - PCI-DSS-Req-1.3.2
    - PCI-DSSv4-1.4
    - PCI-DSSv4-1.4.3
    - disable_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - reboot_required
    - sysctl_net_ipv4_ip_forward

  - name: Ensure kernel module 'dccp' is disabled
    ansible.builtin.lineinfile:
      create: true
      dest: /etc/modprobe.d/dccp.conf
      regexp: install\s+dccp
      line: install dccp /bin/false
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - CJIS-5.10.1
    - 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_dccp_disabled
    - low_complexity
    - medium_disruption
    - medium_severity
    - reboot_required

  - name: Ensure kernel module 'dccp' is blacklisted
    ansible.builtin.lineinfile:
      create: true
      dest: /etc/modprobe.d/dccp.conf
      regexp: ^blacklist dccp$
      line: blacklist dccp
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - CJIS-5.10.1
    - 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_dccp_disabled
    - low_complexity
    - medium_disruption
    - medium_severity
    - 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: 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: 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: 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_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_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_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_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/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/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: 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: 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: 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: Disable Core Dumps for SUID programs - 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:
    - NIST-800-53-SI-11(a)
    - NIST-800-53-SI-11(b)
    - 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_fs_suid_dumpable

  - name: Disable Core Dumps for SUID programs - Find all files that contain fs.suid_dumpable
    ansible.builtin.shell:
      cmd: find -L {{ sysctl_paths | join(" ") }} -type f -name '*.conf' | xargs grep
        -HP '^\s*fs.suid_dumpable\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:
    - NIST-800-53-SI-11(a)
    - NIST-800-53-SI-11(b)
    - 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_fs_suid_dumpable

  - name: Disable Core Dumps for SUID programs - Find all files that set fs.suid_dumpable
      to correct value
    ansible.builtin.shell:
      cmd: find -L {{ sysctl_paths | join(" ") }} -type f -name '*.conf' | xargs grep
        -HP '^\s*fs.suid_dumpable\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:
    - NIST-800-53-SI-11(a)
    - NIST-800-53-SI-11(b)
    - 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_fs_suid_dumpable

  - name: Disable Core Dumps for SUID programs - Comment out any occurrences of fs.suid_dumpable
      from config files
    ansible.builtin.replace:
      path: '{{ item | split(":") | first }}'
      regexp: ^[\s]*fs.suid_dumpable
      replace: '#fs.suid_dumpable'
    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:
    - NIST-800-53-SI-11(a)
    - NIST-800-53-SI-11(b)
    - 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_fs_suid_dumpable

  - name: Disable Core Dumps for SUID programs - Comment out any occurrences of fs.suid_dumpable
      from /etc/sysctl.conf
    ansible.builtin.replace:
      path: '{{ item }}'
      regexp: ^[\s]*fs.suid_dumpable
      replace: '#fs.suid_dumpable'
    with_fileglob:
    - /etc/sysctl.conf
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - NIST-800-53-SI-11(a)
    - NIST-800-53-SI-11(b)
    - 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_fs_suid_dumpable

  - name: Disable Core Dumps for SUID programs - Ensure sysctl fs.suid_dumpable is
      set to 0
    ansible.posix.sysctl:
      name: fs.suid_dumpable
      value: '0'
      sysctl_file: /etc/sysctl.d/fs_suid_dumpable.conf
      state: present
      reload: true
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - NIST-800-53-SI-11(a)
    - NIST-800-53-SI-11(b)
    - 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_fs_suid_dumpable

  - 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: Ensure SELinux Not Disabled in /etc/default/grub - Find /etc/grub.d/ files
    ansible.builtin.find:
      paths:
      - /etc/grub.d/
      follow: true
    register: result_grub_d
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - '"grub2-common" in ansible_facts.packages'
    tags:
    - NIST-800-171-3.1.2
    - NIST-800-171-3.7.2
    - NIST-800-53-AC-3
    - NIST-800-53-AC-3(3)(a)
    - PCI-DSSv4-1.2
    - PCI-DSSv4-1.2.6
    - grub2_enable_selinux
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Ensure SELinux Not Disabled in /etc/default/grub - Ensure SELinux Not Disabled
      in /etc/grub.d/ files
    ansible.builtin.replace:
      dest: '{{ item.path }}'
      regexp: (selinux|enforcing)=0
    with_items:
    - '{{ result_grub_d.files }}'
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - '"grub2-common" in ansible_facts.packages'
    tags:
    - NIST-800-171-3.1.2
    - NIST-800-171-3.7.2
    - NIST-800-53-AC-3
    - NIST-800-53-AC-3(3)(a)
    - PCI-DSSv4-1.2
    - PCI-DSSv4-1.2.6
    - grub2_enable_selinux
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Ensure SELinux Not Disabled in /etc/default/grub - Check if /etc/grub2.cfg
      exists
    ansible.builtin.stat:
      path: /etc/grub2.cfg
    register: result_grub2_cfg_present
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - '"grub2-common" in ansible_facts.packages'
    tags:
    - NIST-800-171-3.1.2
    - NIST-800-171-3.7.2
    - NIST-800-53-AC-3
    - NIST-800-53-AC-3(3)(a)
    - PCI-DSSv4-1.2
    - PCI-DSSv4-1.2.6
    - grub2_enable_selinux
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Ensure SELinux Not Disabled in /etc/default/grub - Check if /etc/default/grub
      exists
    ansible.builtin.stat:
      path: /etc/default/grub
    register: result_default_grub_present
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - '"grub2-common" in ansible_facts.packages'
    tags:
    - NIST-800-171-3.1.2
    - NIST-800-171-3.7.2
    - NIST-800-53-AC-3
    - NIST-800-53-AC-3(3)(a)
    - PCI-DSSv4-1.2
    - PCI-DSSv4-1.2.6
    - grub2_enable_selinux
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Ensure SELinux Not Disabled in /etc/default/grub - Ensure SELinux Not Disabled
      in /etc/grub2.cfg
    ansible.builtin.replace:
      dest: /etc/grub2.cfg
      regexp: (selinux|enforcing)=0
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - '"grub2-common" in ansible_facts.packages'
    - result_grub2_cfg_present.stat.exists
    tags:
    - NIST-800-171-3.1.2
    - NIST-800-171-3.7.2
    - NIST-800-53-AC-3
    - NIST-800-53-AC-3(3)(a)
    - PCI-DSSv4-1.2
    - PCI-DSSv4-1.2.6
    - grub2_enable_selinux
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Ensure SELinux Not Disabled in /etc/default/grub - Ensure SELinux Not Disabled
      in /etc/default/grub
    ansible.builtin.replace:
      dest: /etc/default/grub
      regexp: (selinux|enforcing)=0
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - '"grub2-common" in ansible_facts.packages'
    - result_default_grub_present.stat.exists
    tags:
    - NIST-800-171-3.1.2
    - NIST-800-171-3.7.2
    - NIST-800-53-AC-3
    - NIST-800-53-AC-3(3)(a)
    - PCI-DSSv4-1.2
    - PCI-DSSv4-1.2.6
    - grub2_enable_selinux
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - 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_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_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: Ensure that /etc/at.deny does not exist - Remove /etc/at.deny
    ansible.builtin.file:
      path: /etc/at.deny
      state: absent
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - PCI-DSSv4-2.2
    - PCI-DSSv4-2.2.6
    - disable_strategy
    - file_at_deny_not_exist
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

  - name: Ensure that /etc/cron.deny does not exist - Remove /etc/cron.deny
    ansible.builtin.file:
      path: /etc/cron.deny
      state: absent
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - PCI-DSSv4-2.2
    - PCI-DSSv4-2.2.6
    - disable_strategy
    - file_cron_deny_not_exist
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

  - name: Set the file_groupowner_at_allow_newgroup variable if represented by gid
    ansible.builtin.set_fact:
      file_groupowner_at_allow_newgroup: '0'
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - PCI-DSSv4-2.2
    - PCI-DSSv4-2.2.6
    - configure_strategy
    - file_groupowner_at_allow
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

  - name: Test for existence /etc/at.allow
    ansible.builtin.stat:
      path: /etc/at.allow
    register: file_exists
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - PCI-DSSv4-2.2
    - PCI-DSSv4-2.2.6
    - configure_strategy
    - file_groupowner_at_allow
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

  - name: Ensure group owner on /etc/at.allow
    ansible.builtin.file:
      path: /etc/at.allow
      follow: false
      group: '{{ file_groupowner_at_allow_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:
    - PCI-DSSv4-2.2
    - PCI-DSSv4-2.2.6
    - configure_strategy
    - file_groupowner_at_allow
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

  - name: Set the file_groupowner_cron_allow_newgroup variable if represented by gid
    ansible.builtin.set_fact:
      file_groupowner_cron_allow_newgroup: '0'
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - 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_allow
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

  - name: Test for existence /etc/cron.allow
    ansible.builtin.stat:
      path: /etc/cron.allow
    register: file_exists
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - 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_allow
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

  - name: Ensure group owner on /etc/cron.allow
    ansible.builtin.file:
      path: /etc/cron.allow
      follow: false
      group: '{{ file_groupowner_cron_allow_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:
    - 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_allow
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

  - name: Set the file_owner_cron_allow_newown variable if represented by uid
    ansible.builtin.set_fact:
      file_owner_cron_allow_newown: '0'
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - 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_allow
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

  - name: Test for existence /etc/cron.allow
    ansible.builtin.stat:
      path: /etc/cron.allow
    register: file_exists
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - 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_allow
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

  - name: Ensure owner on /etc/cron.allow
    ansible.builtin.file:
      path: /etc/cron.allow
      follow: false
      owner: '{{ file_owner_cron_allow_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:
    - 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_allow
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

  - name: Test for existence /etc/at.allow
    ansible.builtin.stat:
      path: /etc/at.allow
    register: file_exists
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - PCI-DSSv4-2.2
    - PCI-DSSv4-2.2.6
    - configure_strategy
    - file_permissions_at_allow
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

  - name: Ensure permission u-xs,g-xws,o-xwrt on /etc/at.allow
    ansible.builtin.file:
      path: /etc/at.allow
      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:
    - PCI-DSSv4-2.2
    - PCI-DSSv4-2.2.6
    - configure_strategy
    - file_permissions_at_allow
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

  - name: Test for existence /etc/cron.allow
    ansible.builtin.stat:
      path: /etc/cron.allow
    register: file_exists
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - PCI-DSSv4-2.2
    - PCI-DSSv4-2.2.6
    - configure_strategy
    - file_permissions_cron_allow
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

  - name: Ensure permission u-xs,g-xws,o-xwrt on /etc/cron.allow
    ansible.builtin.file:
      path: /etc/cron.allow
      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:
    - PCI-DSSv4-2.2
    - PCI-DSSv4-2.2.6
    - configure_strategy
    - file_permissions_cron_allow
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

  - name: Make changes to Postfix configuration file
    ansible.builtin.lineinfile:
      path: /etc/postfix/main.cf
      create: false
      regexp: (?i)^inet_interfaces\s*=\s.*
      line: inet_interfaces = {{ var_postfix_inet_interfaces }}
      state: present
      insertafter: ^inet_interfaces\s*=\s.*
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - '"postfix" in ansible_facts.packages'
    - '"postfix" in ansible_facts.packages'
    tags:
    - NIST-800-53-CM-6(a)
    - NIST-800-53-CM-7(a)
    - NIST-800-53-CM-7(b)
    - PCI-DSSv4-1.4
    - PCI-DSSv4-1.4.2
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - postfix_network_listening_disabled
    - restrict_strategy

  - name: Check if chrony main config has active server/pool entries
    ansible.builtin.command:
      cmd: grep -q '^[[:space:]]*\(server\|pool\)[[:space:]]\+[[:graph:]]\+' /etc/chrony.conf
    register: chrony_conf_has_servers
    changed_when: false
    failed_when: false
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - '"chrony" in ansible_facts.packages'
    tags:
    - NIST-800-53-AU-8(1)(a)
    - NIST-800-53-CM-6(a)
    - PCI-DSS-Req-10.4.3
    - PCI-DSSv4-10.6
    - PCI-DSSv4-10.6.2
    - chronyd_specify_remote_server
    - configure_strategy
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

  - name: Extract sourcedir paths from chrony configuration
    ansible.builtin.shell:
      cmd: grep '^[[:space:]]*sourcedir[[:space:]]\+' /etc/chrony.conf | awk '{print
        $2}'
    register: chrony_sourcedir_paths
    changed_when: false
    failed_when: false
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - '"chrony" in ansible_facts.packages'
    - chrony_conf_has_servers.rc != 0
    tags:
    - NIST-800-53-AU-8(1)(a)
    - NIST-800-53-CM-6(a)
    - PCI-DSS-Req-10.4.3
    - PCI-DSSv4-10.6
    - PCI-DSSv4-10.6.2
    - chronyd_specify_remote_server
    - configure_strategy
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

  - name: Check for server/pool entries in sourcedir .sources files
    ansible.builtin.shell:
      cmd: |
        for dir in {{ chrony_sourcedir_paths.stdout_lines | join(' ') }}; do
          if [ -d "$dir" ]; then
            grep -q '^[[:space:]]*\(server\|pool\)[[:space:]]\+[[:graph:]]\+' "$dir"/*.sources 2>/dev/null && exit 0
          fi
        done
        exit 1
    register: chrony_sourcedir_has_servers
    changed_when: false
    failed_when: false
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - '"chrony" in ansible_facts.packages'
    - chrony_conf_has_servers.rc != 0
    - chrony_sourcedir_paths.stdout_lines | length > 0
    tags:
    - NIST-800-53-AU-8(1)(a)
    - NIST-800-53-CM-6(a)
    - PCI-DSS-Req-10.4.3
    - PCI-DSSv4-10.6
    - PCI-DSSv4-10.6.2
    - chronyd_specify_remote_server
    - configure_strategy
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

  - name: Extract confdir paths from chrony configuration
    ansible.builtin.shell:
      cmd: grep '^[[:space:]]*confdir[[:space:]]\+' /etc/chrony.conf | awk '{print
        $2}'
    register: chrony_confdir_paths
    changed_when: false
    failed_when: false
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - '"chrony" in ansible_facts.packages'
    - chrony_conf_has_servers.rc != 0
    - (chrony_sourcedir_paths.stdout_lines | default([]) | length == 0 or chrony_sourcedir_has_servers.rc
      != 0)
    tags:
    - NIST-800-53-AU-8(1)(a)
    - NIST-800-53-CM-6(a)
    - PCI-DSS-Req-10.4.3
    - PCI-DSSv4-10.6
    - PCI-DSSv4-10.6.2
    - chronyd_specify_remote_server
    - configure_strategy
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

  - name: Check for server/pool entries in confdir .conf files
    ansible.builtin.shell:
      cmd: |
        for dir in {{ chrony_confdir_paths.stdout_lines | join(' ') }}; do
          if [ -d "$dir" ]; then
            grep -q '^[[:space:]]*\(server\|pool\)[[:space:]]\+[[:graph:]]\+' "$dir"/*.conf 2>/dev/null && exit 0
          fi
        done
        exit 1
    register: chrony_confdir_has_servers
    changed_when: false
    failed_when: false
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - '"chrony" in ansible_facts.packages'
    - chrony_conf_has_servers.rc != 0
    - chrony_confdir_paths.stdout_lines | default([]) | length > 0
    - (chrony_sourcedir_paths.stdout_lines | default([]) | length == 0 or chrony_sourcedir_has_servers.rc
      != 0)
    tags:
    - NIST-800-53-AU-8(1)(a)
    - NIST-800-53-CM-6(a)
    - PCI-DSS-Req-10.4.3
    - PCI-DSSv4-10.6
    - PCI-DSSv4-10.6.2
    - chronyd_specify_remote_server
    - configure_strategy
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

  - name: Create sourcedir directory if needed
    ansible.builtin.file:
      path: '{{ chrony_sourcedir_paths.stdout_lines[0] }}'
      state: directory
      mode: '0755'
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - '"chrony" in ansible_facts.packages'
    - chrony_conf_has_servers.rc != 0
    - chrony_sourcedir_paths.stdout_lines | default([]) | length > 0
    - chrony_sourcedir_has_servers.rc != 0
    tags:
    - NIST-800-53-AU-8(1)(a)
    - NIST-800-53-CM-6(a)
    - PCI-DSS-Req-10.4.3
    - PCI-DSSv4-10.6
    - PCI-DSSv4-10.6.2
    - chronyd_specify_remote_server
    - configure_strategy
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

  - name: Add remote time servers to sourcedir .sources file
    ansible.builtin.lineinfile:
      path: '{{ chrony_sourcedir_paths.stdout_lines[0] }}/ntp-servers.sources'
      line: server {{ item }}
      state: present
      create: true
      mode: '0644'
    loop: '{{ var_multiple_time_servers.split(",") }}'
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - '"chrony" in ansible_facts.packages'
    - chrony_conf_has_servers.rc != 0
    - chrony_sourcedir_paths.stdout_lines | default([]) | length > 0
    - chrony_sourcedir_has_servers.rc != 0
    tags:
    - NIST-800-53-AU-8(1)(a)
    - NIST-800-53-CM-6(a)
    - PCI-DSS-Req-10.4.3
    - PCI-DSSv4-10.6
    - PCI-DSSv4-10.6.2
    - chronyd_specify_remote_server
    - configure_strategy
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

  - name: Create confdir directory if needed
    ansible.builtin.file:
      path: '{{ chrony_confdir_paths.stdout_lines[0] }}'
      state: directory
      mode: '0755'
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - '"chrony" in ansible_facts.packages'
    - chrony_conf_has_servers.rc != 0
    - (chrony_sourcedir_paths.stdout_lines | default([]) | length == 0 or chrony_sourcedir_has_servers.rc
      != 0)
    - chrony_confdir_paths.stdout_lines | default([]) | length > 0
    - chrony_confdir_has_servers.rc != 0
    tags:
    - NIST-800-53-AU-8(1)(a)
    - NIST-800-53-CM-6(a)
    - PCI-DSS-Req-10.4.3
    - PCI-DSSv4-10.6
    - PCI-DSSv4-10.6.2
    - chronyd_specify_remote_server
    - configure_strategy
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

  - name: Add remote time servers to confdir .conf file
    ansible.builtin.lineinfile:
      path: '{{ chrony_confdir_paths.stdout_lines[0] }}/ntp-servers.conf'
      line: server {{ item }}
      state: present
      create: true
      mode: '0644'
    loop: '{{ var_multiple_time_servers.split(",") }}'
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - '"chrony" in ansible_facts.packages'
    - chrony_conf_has_servers.rc != 0
    - (chrony_sourcedir_paths.stdout_lines | default([]) | length == 0 or chrony_sourcedir_has_servers.rc
      != 0)
    - chrony_confdir_paths.stdout_lines | default([]) | length > 0
    - chrony_confdir_has_servers.rc != 0
    tags:
    - NIST-800-53-AU-8(1)(a)
    - NIST-800-53-CM-6(a)
    - PCI-DSS-Req-10.4.3
    - PCI-DSSv4-10.6
    - PCI-DSSv4-10.6.2
    - chronyd_specify_remote_server
    - configure_strategy
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

  - name: Add remote time servers to main chrony configuration
    ansible.builtin.lineinfile:
      path: /etc/chrony.conf
      line: server {{ item }}
      state: present
      create: true
    loop: '{{ var_multiple_time_servers.split(",") }}'
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - '"chrony" in ansible_facts.packages'
    - chrony_conf_has_servers.rc != 0
    - (chrony_sourcedir_paths.stdout_lines | default([]) | length == 0 or chrony_sourcedir_has_servers.rc
      != 0)
    - (chrony_confdir_paths.stdout_lines | default([]) | length == 0 or chrony_confdir_has_servers.rc
      != 0)
    tags:
    - NIST-800-53-AU-8(1)(a)
    - NIST-800-53-CM-6(a)
    - PCI-DSS-Req-10.4.3
    - PCI-DSSv4-10.6
    - PCI-DSSv4-10.6.2
    - chronyd_specify_remote_server
    - configure_strategy
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

  - name: Detect if file /etc/sysconfig/chronyd is not empty or missing
    ansible.builtin.find:
      path: /etc/sysconfig/
      patterns: chronyd
      contains: ^([\s]*OPTIONS=["]?[^"]*)("?)
    register: chronyd_file
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - '"chrony" in ansible_facts.packages'
    tags:
    - PCI-DSSv4-10.6
    - PCI-DSSv4-10.6.3
    - chronyd_run_as_chrony_user
    - configure_strategy
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

  - name: Remove any previous configuration of user used to run chronyd process
    ansible.builtin.replace:
      path: /etc/sysconfig/chronyd
      regexp: \s*-u\s*\w+\s*
      replace: ' '
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - '"chrony" in ansible_facts.packages'
    - chronyd_file is defined and chronyd_file.matched > 0
    tags:
    - PCI-DSSv4-10.6
    - PCI-DSSv4-10.6.3
    - chronyd_run_as_chrony_user
    - configure_strategy
    - 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 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:
    - 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:
    - 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:
    - PCI-DSSv4-2.2
    - PCI-DSSv4-2.2.6
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy
    - sshd_disable_tcp_forwarding

  - name: Comment conf from included files
    ansible.builtin.replace:
      path: '{{ item }}'
      regexp: ^(\s*AllowTcpForwarding.*)$
      replace: '# \1'
    loop: '{{ sshd_config_included_files.stdout_lines }}'
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - PCI-DSSv4-2.2
    - PCI-DSSv4-2.2.6
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy
    - sshd_disable_tcp_forwarding

  - name: Disable SSH TCP Forwarding - Check if the parameter AllowTcpForwarding is
      configured
    ansible.builtin.find:
      paths:
      - /etc/ssh/sshd_config
      - /etc/ssh/sshd_config.d
      contains: (?i)^\s*{{ "AllowTcpForwarding"| regex_escape }}\s+
    register: _sshd_config_has_parameter
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - PCI-DSSv4-2.2
    - PCI-DSSv4-2.2.6
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy
    - sshd_disable_tcp_forwarding

  - name: Disable SSH TCP Forwarding - Check if the parameter AllowTcpForwarding is
      configured correctly
    ansible.builtin.find:
      paths:
      - /etc/ssh/sshd_config
      - /etc/ssh/sshd_config.d
      contains: (?i)^\s*{{ "AllowTcpForwarding"| regex_escape }}\s+no$
    register: _sshd_config_correctly
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - PCI-DSSv4-2.2
    - PCI-DSSv4-2.2.6
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy
    - sshd_disable_tcp_forwarding

  - name: Disable SSH TCP Forwarding
    block:

    - name: Deduplicate values from /etc/ssh/sshd_config
      ansible.builtin.lineinfile:
        path: /etc/ssh/sshd_config
        create: false
        regexp: (?i)(?i)^\s*{{ "AllowTcpForwarding"| 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 AllowTcpForwarding is present in /etc/ssh/sshd_config.d
      ansible.builtin.find:
        paths: /etc/ssh/sshd_config.d
        recurse: 'yes'
        follow: 'no'
        contains: (?i)^\s*{{ "AllowTcpForwarding"| 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*{{ "AllowTcpForwarding"| 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*{{ "AllowTcpForwarding"| regex_escape }}\s+
        line: AllowTcpForwarding 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:
    - PCI-DSSv4-2.2
    - PCI-DSSv4-2.2.6
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy
    - sshd_disable_tcp_forwarding

  - name: Disable SSH TCP Forwarding - 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:
    - PCI-DSSv4-2.2
    - PCI-DSSv4-2.2.6
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy
    - sshd_disable_tcp_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:
    - 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:
    - PCI-DSSv4-2.2
    - PCI-DSSv4-2.2.6
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy
    - sshd_set_login_grace_time

  - name: Comment conf from included files
    ansible.builtin.replace:
      path: '{{ item }}'
      regexp: ^(\s*LoginGraceTime.*)$
      replace: '# \1'
    loop: '{{ sshd_config_included_files.stdout_lines }}'
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - PCI-DSSv4-2.2
    - PCI-DSSv4-2.2.6
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy
    - sshd_set_login_grace_time

  - name: Ensure SSH LoginGraceTime is configured - Check if the parameter LoginGraceTime
      is configured
    ansible.builtin.find:
      paths:
      - /etc/ssh/sshd_config
      - /etc/ssh/sshd_config.d
      contains: (?i)^\s*{{ "LoginGraceTime"| regex_escape }}\s+
    register: _sshd_config_has_parameter
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - PCI-DSSv4-2.2
    - PCI-DSSv4-2.2.6
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy
    - sshd_set_login_grace_time

  - name: Ensure SSH LoginGraceTime is configured - Check if the parameter LoginGraceTime
      is configured correctly
    ansible.builtin.find:
      paths:
      - /etc/ssh/sshd_config
      - /etc/ssh/sshd_config.d
      contains: (?i)^\s*{{ "LoginGraceTime"| regex_escape }}\s+{{ var_sshd_set_login_grace_time
        }}$
    register: _sshd_config_correctly
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - PCI-DSSv4-2.2
    - PCI-DSSv4-2.2.6
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy
    - sshd_set_login_grace_time

  - name: Ensure SSH LoginGraceTime is configured
    block:

    - name: Deduplicate values from /etc/ssh/sshd_config
      ansible.builtin.lineinfile:
        path: /etc/ssh/sshd_config
        create: false
        regexp: (?i)(?i)^\s*{{ "LoginGraceTime"| 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 LoginGraceTime is present in /etc/ssh/sshd_config.d
      ansible.builtin.find:
        paths: /etc/ssh/sshd_config.d
        recurse: 'yes'
        follow: 'no'
        contains: (?i)^\s*{{ "LoginGraceTime"| 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*{{ "LoginGraceTime"| 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*{{ "LoginGraceTime"| regex_escape }}\s+
        line: LoginGraceTime {{ var_sshd_set_login_grace_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:
    - PCI-DSSv4-2.2
    - PCI-DSSv4-2.2.6
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy
    - sshd_set_login_grace_time

  - name: Ensure SSH LoginGraceTime is configured - 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:
    - PCI-DSSv4-2.2
    - PCI-DSSv4-2.2.6
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy
    - sshd_set_login_grace_time

  - 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:
    - PCI-DSSv4-2.2
    - PCI-DSSv4-2.2.6
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy
    - sshd_set_max_auth_tries

  - name: Comment conf from included files
    ansible.builtin.replace:
      path: '{{ item }}'
      regexp: ^(\s*MaxAuthTries.*)$
      replace: '# \1'
    loop: '{{ sshd_config_included_files.stdout_lines }}'
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - PCI-DSSv4-2.2
    - PCI-DSSv4-2.2.6
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy
    - sshd_set_max_auth_tries

  - name: Set SSH authentication attempt limit - Check if the parameter MaxAuthTries
      is configured
    ansible.builtin.find:
      paths:
      - /etc/ssh/sshd_config
      - /etc/ssh/sshd_config.d
      contains: (?i)^\s*{{ "MaxAuthTries"| regex_escape }}\s+
    register: _sshd_config_has_parameter
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - PCI-DSSv4-2.2
    - PCI-DSSv4-2.2.6
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy
    - sshd_set_max_auth_tries

  - name: Set SSH authentication attempt limit - Check if the parameter MaxAuthTries
      is configured correctly
    ansible.builtin.find:
      paths:
      - /etc/ssh/sshd_config
      - /etc/ssh/sshd_config.d
      contains: (?i)^\s*{{ "MaxAuthTries"| regex_escape }}\s+{{ sshd_max_auth_tries_value
        }}$
    register: _sshd_config_correctly
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - PCI-DSSv4-2.2
    - PCI-DSSv4-2.2.6
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy
    - sshd_set_max_auth_tries

  - name: Set SSH authentication attempt limit
    block:

    - name: Deduplicate values from /etc/ssh/sshd_config
      ansible.builtin.lineinfile:
        path: /etc/ssh/sshd_config
        create: false
        regexp: (?i)(?i)^\s*{{ "MaxAuthTries"| 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 MaxAuthTries is present in /etc/ssh/sshd_config.d
      ansible.builtin.find:
        paths: /etc/ssh/sshd_config.d
        recurse: 'yes'
        follow: 'no'
        contains: (?i)^\s*{{ "MaxAuthTries"| 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*{{ "MaxAuthTries"| 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*{{ "MaxAuthTries"| regex_escape }}\s+
        line: MaxAuthTries {{ sshd_max_auth_tries_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:
    - PCI-DSSv4-2.2
    - PCI-DSSv4-2.2.6
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy
    - sshd_set_max_auth_tries

  - name: Set SSH authentication attempt limit - 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:
    - PCI-DSSv4-2.2
    - PCI-DSSv4-2.2.6
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy
    - sshd_set_max_auth_tries

  - 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:
    - PCI-DSSv4-2.2
    - PCI-DSSv4-2.2.6
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy
    - sshd_set_max_sessions

  - name: Comment conf from included files
    ansible.builtin.replace:
      path: '{{ item }}'
      regexp: ^(\s*MaxSessions.*)$
      replace: '# \1'
    loop: '{{ sshd_config_included_files.stdout_lines }}'
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - PCI-DSSv4-2.2
    - PCI-DSSv4-2.2.6
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy
    - sshd_set_max_sessions

  - name: Set SSH MaxSessions limit - Check if the parameter MaxSessions is configured
    ansible.builtin.find:
      paths:
      - /etc/ssh/sshd_config
      - /etc/ssh/sshd_config.d
      contains: (?i)^\s*{{ "MaxSessions"| regex_escape }}\s+
    register: _sshd_config_has_parameter
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - PCI-DSSv4-2.2
    - PCI-DSSv4-2.2.6
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy
    - sshd_set_max_sessions

  - name: Set SSH MaxSessions limit - Check if the parameter MaxSessions is configured
      correctly
    ansible.builtin.find:
      paths:
      - /etc/ssh/sshd_config
      - /etc/ssh/sshd_config.d
      contains: (?i)^\s*{{ "MaxSessions"| regex_escape }}\s+{{ var_sshd_max_sessions
        }}$
    register: _sshd_config_correctly
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - PCI-DSSv4-2.2
    - PCI-DSSv4-2.2.6
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy
    - sshd_set_max_sessions

  - name: Set SSH MaxSessions limit
    block:

    - name: Deduplicate values from /etc/ssh/sshd_config
      ansible.builtin.lineinfile:
        path: /etc/ssh/sshd_config
        create: false
        regexp: (?i)(?i)^\s*{{ "MaxSessions"| 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 MaxSessions is present in /etc/ssh/sshd_config.d
      ansible.builtin.find:
        paths: /etc/ssh/sshd_config.d
        recurse: 'yes'
        follow: 'no'
        contains: (?i)^\s*{{ "MaxSessions"| 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*{{ "MaxSessions"| 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*{{ "MaxSessions"| regex_escape }}\s+
        line: MaxSessions {{ var_sshd_max_sessions }}
        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:
    - PCI-DSSv4-2.2
    - PCI-DSSv4-2.2.6
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy
    - sshd_set_max_sessions

  - name: Set SSH MaxSessions limit - 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:
    - PCI-DSSv4-2.2
    - PCI-DSSv4-2.2.6
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy
    - sshd_set_max_sessions

  - 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:
    - PCI-DSSv4-2.2
    - PCI-DSSv4-2.2.6
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy
    - sshd_set_maxstartups

  - name: Comment conf from included files
    ansible.builtin.replace:
      path: '{{ item }}'
      regexp: ^(\s*MaxStartups.*)$
      replace: '# \1'
    loop: '{{ sshd_config_included_files.stdout_lines }}'
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - PCI-DSSv4-2.2
    - PCI-DSSv4-2.2.6
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy
    - sshd_set_maxstartups

  - name: Ensure SSH MaxStartups is configured - Check if the parameter MaxStartups
      is configured
    ansible.builtin.find:
      paths:
      - /etc/ssh/sshd_config
      - /etc/ssh/sshd_config.d
      contains: (?i)^\s*{{ "MaxStartups"| regex_escape }}\s+
    register: _sshd_config_has_parameter
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - PCI-DSSv4-2.2
    - PCI-DSSv4-2.2.6
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy
    - sshd_set_maxstartups

  - name: Ensure SSH MaxStartups is configured - Check if the parameter MaxStartups
      is configured correctly
    ansible.builtin.find:
      paths:
      - /etc/ssh/sshd_config
      - /etc/ssh/sshd_config.d
      contains: (?i)^\s*{{ "MaxStartups"| regex_escape }}\s+{{ var_sshd_set_maxstartups
        }}$
    register: _sshd_config_correctly
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - PCI-DSSv4-2.2
    - PCI-DSSv4-2.2.6
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy
    - sshd_set_maxstartups

  - name: Ensure SSH MaxStartups is configured
    block:

    - name: Deduplicate values from /etc/ssh/sshd_config
      ansible.builtin.lineinfile:
        path: /etc/ssh/sshd_config
        create: false
        regexp: (?i)(?i)^\s*{{ "MaxStartups"| 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 MaxStartups is present in /etc/ssh/sshd_config.d
      ansible.builtin.find:
        paths: /etc/ssh/sshd_config.d
        recurse: 'yes'
        follow: 'no'
        contains: (?i)^\s*{{ "MaxStartups"| 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*{{ "MaxStartups"| 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*{{ "MaxStartups"| regex_escape }}\s+
        line: MaxStartups {{ var_sshd_set_maxstartups }}
        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:
    - PCI-DSSv4-2.2
    - PCI-DSSv4-2.2.6
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy
    - sshd_set_maxstartups

  - name: Ensure SSH MaxStartups is configured - 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:
    - PCI-DSSv4-2.2
    - PCI-DSSv4-2.2.6
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy
    - sshd_set_maxstartups

  - 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: 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: Record Events that Modify the System's Mandatory Access Controls - Check
      if watch rule for /etc/selinux/ already exists in /etc/audit/rules.d/
    ansible.builtin.find:
      paths: /etc/audit/rules.d
      contains: ^\s*-w\s+/etc/selinux/\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
    - NIST-800-171-3.1.8
    - 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_mac_modification
    - low_complexity
    - low_disruption
    - medium_severity
    - reboot_required
    - restrict_strategy

  - name: Record Events that Modify the System's Mandatory Access Controls - Search
      /etc/audit/rules.d for other rules with specified key MAC-policy
    ansible.builtin.find:
      paths: /etc/audit/rules.d
      contains: ^.*(?:-F key=|-k\s+)MAC-policy$
      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
    - NIST-800-171-3.1.8
    - 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_mac_modification
    - low_complexity
    - low_disruption
    - medium_severity
    - reboot_required
    - restrict_strategy

  - name: Record Events that Modify the System's Mandatory Access Controls - Use /etc/audit/rules.d/MAC-policy.rules
      as the recipient for the rule
    ansible.builtin.set_fact:
      all_files:
      - /etc/audit/rules.d/MAC-policy.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
    - NIST-800-171-3.1.8
    - 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_mac_modification
    - low_complexity
    - low_disruption
    - medium_severity
    - reboot_required
    - restrict_strategy

  - name: Record Events that Modify the System's Mandatory Access Controls - 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
    - NIST-800-171-3.1.8
    - 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_mac_modification
    - low_complexity
    - low_disruption
    - medium_severity
    - reboot_required
    - restrict_strategy

  - name: Record Events that Modify the System's Mandatory Access Controls - Add watch
      rule for /etc/selinux/ in /etc/audit/rules.d/
    ansible.builtin.lineinfile:
      path: '{{ all_files[0] }}'
      line: -w /etc/selinux/ -p wa -k MAC-policy
      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
    - NIST-800-171-3.1.8
    - 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_mac_modification
    - low_complexity
    - low_disruption
    - medium_severity
    - reboot_required
    - restrict_strategy

  - name: Record Events that Modify the System's Mandatory Access Controls - Check
      if watch rule for /etc/selinux/ already exists in /etc/audit/audit.rules
    ansible.builtin.find:
      paths: /etc/audit/
      contains: ^\s*-w\s+/etc/selinux/\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
    - NIST-800-171-3.1.8
    - 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_mac_modification
    - low_complexity
    - low_disruption
    - medium_severity
    - reboot_required
    - restrict_strategy

  - name: Record Events that Modify the System's Mandatory Access Controls - Add watch
      rule for /etc/selinux/ in /etc/audit/audit.rules
    ansible.builtin.lineinfile:
      line: -w /etc/selinux/ -p wa -k MAC-policy
      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
    - NIST-800-171-3.1.8
    - 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_mac_modification
    - low_complexity
    - low_disruption
    - medium_severity
    - reboot_required
    - restrict_strategy

  - name: Record Events that Modify the System's Mandatory Access Controls (/etc/selinux)
      - Check if watch rule for /etc/selinux/ already exists in /etc/audit/rules.d/
    ansible.builtin.find:
      paths: /etc/audit/rules.d
      contains: ^\s*-w\s+/etc/selinux/\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:
    - PCI-DSS-Req-10.5.5
    - PCI-DSSv4-10.3
    - PCI-DSSv4-10.3.4
    - audit_rules_mac_modification_etc_selinux
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Record Events that Modify the System's Mandatory Access Controls (/etc/selinux)
      - Search /etc/audit/rules.d for other rules with specified key MAC-policy
    ansible.builtin.find:
      paths: /etc/audit/rules.d
      contains: ^.*(?:-F key=|-k\s+)MAC-policy$
      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:
    - PCI-DSS-Req-10.5.5
    - PCI-DSSv4-10.3
    - PCI-DSSv4-10.3.4
    - audit_rules_mac_modification_etc_selinux
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Record Events that Modify the System's Mandatory Access Controls (/etc/selinux)
      - Use /etc/audit/rules.d/MAC-policy.rules as the recipient for the rule
    ansible.builtin.set_fact:
      all_files:
      - /etc/audit/rules.d/MAC-policy.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:
    - PCI-DSS-Req-10.5.5
    - PCI-DSSv4-10.3
    - PCI-DSSv4-10.3.4
    - audit_rules_mac_modification_etc_selinux
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Record Events that Modify the System's Mandatory Access Controls (/etc/selinux)
      - 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:
    - PCI-DSS-Req-10.5.5
    - PCI-DSSv4-10.3
    - PCI-DSSv4-10.3.4
    - audit_rules_mac_modification_etc_selinux
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Record Events that Modify the System's Mandatory Access Controls (/etc/selinux)
      - Add watch rule for /etc/selinux/ in /etc/audit/rules.d/
    ansible.builtin.lineinfile:
      path: '{{ all_files[0] }}'
      line: -w /etc/selinux/ -p wa -k MAC-policy
      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:
    - PCI-DSS-Req-10.5.5
    - PCI-DSSv4-10.3
    - PCI-DSSv4-10.3.4
    - audit_rules_mac_modification_etc_selinux
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Record Events that Modify the System's Mandatory Access Controls (/etc/selinux)
      - Check if watch rule for /etc/selinux/ already exists in /etc/audit/audit.rules
    ansible.builtin.find:
      paths: /etc/audit/
      contains: ^\s*-w\s+/etc/selinux/\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:
    - PCI-DSS-Req-10.5.5
    - PCI-DSSv4-10.3
    - PCI-DSSv4-10.3.4
    - audit_rules_mac_modification_etc_selinux
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Record Events that Modify the System's Mandatory Access Controls (/etc/selinux)
      - Add watch rule for /etc/selinux/ in /etc/audit/audit.rules
    ansible.builtin.lineinfile:
      line: -w /etc/selinux/ -p wa -k MAC-policy
      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:
    - PCI-DSS-Req-10.5.5
    - PCI-DSSv4-10.3
    - PCI-DSSv4-10.3.4
    - audit_rules_mac_modification_etc_selinux
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Set architecture for audit mount 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
    - 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
    - PCI-DSSv4-10.2
    - PCI-DSSv4-10.2.1
    - PCI-DSSv4-10.2.1.7
    - audit_rules_media_export
    - low_complexity
    - low_disruption
    - medium_severity
    - reboot_required
    - restrict_strategy

  - name: Perform remediation of Audit rules for mount for 32bit platform
    block:

    - name: Declare list of syscalls
      ansible.builtin.set_fact:
        syscalls:
        - mount
        syscall_grouping: []

    - name: Check existence of mount 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/export.rules
      ansible.builtin.set_fact: audit_file="/etc/audit/rules.d/export.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=export
        create: true
        mode: g-rwx,o-rwx
        state: present
      when: syscalls_found | length == 0

    - name: Declare list of syscalls
      ansible.builtin.set_fact:
        syscalls:
        - mount
        syscall_grouping: []

    - name: Check existence of mount 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=export
        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
    - 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
    - PCI-DSSv4-10.2
    - PCI-DSSv4-10.2.1
    - PCI-DSSv4-10.2.1.7
    - audit_rules_media_export
    - low_complexity
    - low_disruption
    - medium_severity
    - reboot_required
    - restrict_strategy

  - name: Perform remediation of Audit rules for mount for 64bit platform
    block:

    - name: Declare list of syscalls
      ansible.builtin.set_fact:
        syscalls:
        - mount
        syscall_grouping: []

    - name: Check existence of mount 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/export.rules
      ansible.builtin.set_fact: audit_file="/etc/audit/rules.d/export.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=export
        create: true
        mode: g-rwx,o-rwx
        state: present
      when: syscalls_found | length == 0

    - name: Declare list of syscalls
      ansible.builtin.set_fact:
        syscalls:
        - mount
        syscall_grouping: []

    - name: Check existence of mount 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=export
        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
    - 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
    - PCI-DSSv4-10.2
    - PCI-DSSv4-10.2.1
    - PCI-DSSv4-10.2.1.7
    - audit_rules_media_export
    - low_complexity
    - low_disruption
    - medium_severity
    - reboot_required
    - restrict_strategy

  - name: Set architecture for audit 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
    - 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.5.5
    - PCI-DSSv4-10.3
    - PCI-DSSv4-10.3.4
    - audit_rules_networkconfig_modification
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Remediate audit rules for network configuration for 32bit platform
    block:

    - name: Declare list of syscalls
      ansible.builtin.set_fact:
        syscalls:
        - sethostname
        - setdomainname
        syscall_grouping:
        - sethostname
        - setdomainname

    - name: Check existence of sethostname, setdomainname 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+)* (-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/audit_rules_networkconfig_modification.rules
      ansible.builtin.set_fact: audit_file="/etc/audit/rules.d/audit_rules_networkconfig_modification.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+)+)( (?:-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 key=audit_rules_networkconfig_modification
        create: true
        mode: g-rwx,o-rwx
        state: present
      when: syscalls_found | length == 0

    - name: Declare list of syscalls
      ansible.builtin.set_fact:
        syscalls:
        - sethostname
        - setdomainname
        syscall_grouping:
        - sethostname
        - setdomainname

    - name: Check existence of sethostname, setdomainname in /etc/audit/audit.rules
      ansible.builtin.find:
        paths: /etc/audit
        contains: -a always,exit -F arch=b32(( -S |,)\w+)*(( -S |,){{ item }})+((
          -S |,)\w+)* (-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+)+)( (?:-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 key=audit_rules_networkconfig_modification
        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
    - 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.5.5
    - PCI-DSSv4-10.3
    - PCI-DSSv4-10.3.4
    - audit_rules_networkconfig_modification
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Remediate audit rules for network configuration for 64bit platform
    block:

    - name: Declare list of syscalls
      ansible.builtin.set_fact:
        syscalls:
        - sethostname
        - setdomainname
        syscall_grouping:
        - sethostname
        - setdomainname

    - name: Check existence of sethostname, setdomainname 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+)* (-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/audit_rules_networkconfig_modification.rules
      ansible.builtin.set_fact: audit_file="/etc/audit/rules.d/audit_rules_networkconfig_modification.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+)+)( (?:-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 key=audit_rules_networkconfig_modification
        create: true
        mode: g-rwx,o-rwx
        state: present
      when: syscalls_found | length == 0

    - name: Declare list of syscalls
      ansible.builtin.set_fact:
        syscalls:
        - sethostname
        - setdomainname
        syscall_grouping:
        - sethostname
        - setdomainname

    - name: Check existence of sethostname, setdomainname in /etc/audit/audit.rules
      ansible.builtin.find:
        paths: /etc/audit
        contains: -a always,exit -F arch=b64(( -S |,)\w+)*(( -S |,){{ item }})+((
          -S |,)\w+)* (-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+)+)( (?:-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 key=audit_rules_networkconfig_modification
        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
    - 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.5.5
    - PCI-DSSv4-10.3
    - PCI-DSSv4-10.3.4
    - audit_rules_networkconfig_modification
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Record Events that Modify the System's Network Environment - Check if watch
      rule for /etc/issue already exists in /etc/audit/rules.d/
    ansible.builtin.find:
      paths: /etc/audit/rules.d
      contains: ^\s*-w\s+/etc/issue\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
    - 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.5.5
    - PCI-DSSv4-10.3
    - PCI-DSSv4-10.3.4
    - audit_rules_networkconfig_modification
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Record Events that Modify the System's Network Environment - Search /etc/audit/rules.d
      for other rules with specified key audit_rules_networkconfig_modification
    ansible.builtin.find:
      paths: /etc/audit/rules.d
      contains: ^.*(?:-F key=|-k\s+)audit_rules_networkconfig_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
    - 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.5.5
    - PCI-DSSv4-10.3
    - PCI-DSSv4-10.3.4
    - audit_rules_networkconfig_modification
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Record Events that Modify the System's Network Environment - Use /etc/audit/rules.d/audit_rules_networkconfig_modification.rules
      as the recipient for the rule
    ansible.builtin.set_fact:
      all_files:
      - /etc/audit/rules.d/audit_rules_networkconfig_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
    - 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.5.5
    - PCI-DSSv4-10.3
    - PCI-DSSv4-10.3.4
    - audit_rules_networkconfig_modification
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Record Events that Modify the System's Network Environment - 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
    - 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.5.5
    - PCI-DSSv4-10.3
    - PCI-DSSv4-10.3.4
    - audit_rules_networkconfig_modification
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Record Events that Modify the System's Network Environment - Add watch rule
      for /etc/issue in /etc/audit/rules.d/
    ansible.builtin.lineinfile:
      path: '{{ all_files[0] }}'
      line: -w /etc/issue -p wa -k audit_rules_networkconfig_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
    - 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.5.5
    - PCI-DSSv4-10.3
    - PCI-DSSv4-10.3.4
    - audit_rules_networkconfig_modification
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Record Events that Modify the System's Network Environment - Check if watch
      rule for /etc/issue already exists in /etc/audit/audit.rules
    ansible.builtin.find:
      paths: /etc/audit/
      contains: ^\s*-w\s+/etc/issue\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
    - 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.5.5
    - PCI-DSSv4-10.3
    - PCI-DSSv4-10.3.4
    - audit_rules_networkconfig_modification
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Record Events that Modify the System's Network Environment - Add watch rule
      for /etc/issue in /etc/audit/audit.rules
    ansible.builtin.lineinfile:
      line: -w /etc/issue -p wa -k audit_rules_networkconfig_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
    - 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.5.5
    - PCI-DSSv4-10.3
    - PCI-DSSv4-10.3.4
    - audit_rules_networkconfig_modification
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Record Events that Modify the System's Network Environment - Check if watch
      rule for /etc/issue.net already exists in /etc/audit/rules.d/
    ansible.builtin.find:
      paths: /etc/audit/rules.d
      contains: ^\s*-w\s+/etc/issue.net\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
    - 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.5.5
    - PCI-DSSv4-10.3
    - PCI-DSSv4-10.3.4
    - audit_rules_networkconfig_modification
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Record Events that Modify the System's Network Environment - Search /etc/audit/rules.d
      for other rules with specified key audit_rules_networkconfig_modification
    ansible.builtin.find:
      paths: /etc/audit/rules.d
      contains: ^.*(?:-F key=|-k\s+)audit_rules_networkconfig_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
    - 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.5.5
    - PCI-DSSv4-10.3
    - PCI-DSSv4-10.3.4
    - audit_rules_networkconfig_modification
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Record Events that Modify the System's Network Environment - Use /etc/audit/rules.d/audit_rules_networkconfig_modification.rules
      as the recipient for the rule
    ansible.builtin.set_fact:
      all_files:
      - /etc/audit/rules.d/audit_rules_networkconfig_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
    - 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.5.5
    - PCI-DSSv4-10.3
    - PCI-DSSv4-10.3.4
    - audit_rules_networkconfig_modification
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Record Events that Modify the System's Network Environment - 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
    - 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.5.5
    - PCI-DSSv4-10.3
    - PCI-DSSv4-10.3.4
    - audit_rules_networkconfig_modification
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Record Events that Modify the System's Network Environment - Add watch rule
      for /etc/issue.net in /etc/audit/rules.d/
    ansible.builtin.lineinfile:
      path: '{{ all_files[0] }}'
      line: -w /etc/issue.net -p wa -k audit_rules_networkconfig_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
    - 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.5.5
    - PCI-DSSv4-10.3
    - PCI-DSSv4-10.3.4
    - audit_rules_networkconfig_modification
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Record Events that Modify the System's Network Environment - Check if watch
      rule for /etc/issue.net already exists in /etc/audit/audit.rules
    ansible.builtin.find:
      paths: /etc/audit/
      contains: ^\s*-w\s+/etc/issue.net\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
    - 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.5.5
    - PCI-DSSv4-10.3
    - PCI-DSSv4-10.3.4
    - audit_rules_networkconfig_modification
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Record Events that Modify the System's Network Environment - Add watch rule
      for /etc/issue.net in /etc/audit/audit.rules
    ansible.builtin.lineinfile:
      line: -w /etc/issue.net -p wa -k audit_rules_networkconfig_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
    - 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.5.5
    - PCI-DSSv4-10.3
    - PCI-DSSv4-10.3.4
    - audit_rules_networkconfig_modification
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Record Events that Modify the System's Network Environment - Check if watch
      rule for /etc/hosts already exists in /etc/audit/rules.d/
    ansible.builtin.find:
      paths: /etc/audit/rules.d
      contains: ^\s*-w\s+/etc/hosts\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
    - 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.5.5
    - PCI-DSSv4-10.3
    - PCI-DSSv4-10.3.4
    - audit_rules_networkconfig_modification
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Record Events that Modify the System's Network Environment - Search /etc/audit/rules.d
      for other rules with specified key audit_rules_networkconfig_modification
    ansible.builtin.find:
      paths: /etc/audit/rules.d
      contains: ^.*(?:-F key=|-k\s+)audit_rules_networkconfig_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
    - 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.5.5
    - PCI-DSSv4-10.3
    - PCI-DSSv4-10.3.4
    - audit_rules_networkconfig_modification
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Record Events that Modify the System's Network Environment - Use /etc/audit/rules.d/audit_rules_networkconfig_modification.rules
      as the recipient for the rule
    ansible.builtin.set_fact:
      all_files:
      - /etc/audit/rules.d/audit_rules_networkconfig_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
    - 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.5.5
    - PCI-DSSv4-10.3
    - PCI-DSSv4-10.3.4
    - audit_rules_networkconfig_modification
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Record Events that Modify the System's Network Environment - 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
    - 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.5.5
    - PCI-DSSv4-10.3
    - PCI-DSSv4-10.3.4
    - audit_rules_networkconfig_modification
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Record Events that Modify the System's Network Environment - Add watch rule
      for /etc/hosts in /etc/audit/rules.d/
    ansible.builtin.lineinfile:
      path: '{{ all_files[0] }}'
      line: -w /etc/hosts -p wa -k audit_rules_networkconfig_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
    - 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.5.5
    - PCI-DSSv4-10.3
    - PCI-DSSv4-10.3.4
    - audit_rules_networkconfig_modification
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Record Events that Modify the System's Network Environment - Check if watch
      rule for /etc/hosts already exists in /etc/audit/audit.rules
    ansible.builtin.find:
      paths: /etc/audit/
      contains: ^\s*-w\s+/etc/hosts\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
    - 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.5.5
    - PCI-DSSv4-10.3
    - PCI-DSSv4-10.3.4
    - audit_rules_networkconfig_modification
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Record Events that Modify the System's Network Environment - Add watch rule
      for /etc/hosts in /etc/audit/audit.rules
    ansible.builtin.lineinfile:
      line: -w /etc/hosts -p wa -k audit_rules_networkconfig_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
    - 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.5.5
    - PCI-DSSv4-10.3
    - PCI-DSSv4-10.3.4
    - audit_rules_networkconfig_modification
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Record Events that Modify the System's Network Environment - Check if watch
      rule for /etc/sysconfig/network already exists in /etc/audit/rules.d/
    ansible.builtin.find:
      paths: /etc/audit/rules.d
      contains: ^\s*-w\s+/etc/sysconfig/network\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
    - 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.5.5
    - PCI-DSSv4-10.3
    - PCI-DSSv4-10.3.4
    - audit_rules_networkconfig_modification
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Record Events that Modify the System's Network Environment - Search /etc/audit/rules.d
      for other rules with specified key audit_rules_networkconfig_modification
    ansible.builtin.find:
      paths: /etc/audit/rules.d
      contains: ^.*(?:-F key=|-k\s+)audit_rules_networkconfig_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
    - 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.5.5
    - PCI-DSSv4-10.3
    - PCI-DSSv4-10.3.4
    - audit_rules_networkconfig_modification
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Record Events that Modify the System's Network Environment - Use /etc/audit/rules.d/audit_rules_networkconfig_modification.rules
      as the recipient for the rule
    ansible.builtin.set_fact:
      all_files:
      - /etc/audit/rules.d/audit_rules_networkconfig_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
    - 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.5.5
    - PCI-DSSv4-10.3
    - PCI-DSSv4-10.3.4
    - audit_rules_networkconfig_modification
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Record Events that Modify the System's Network Environment - 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
    - 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.5.5
    - PCI-DSSv4-10.3
    - PCI-DSSv4-10.3.4
    - audit_rules_networkconfig_modification
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Record Events that Modify the System's Network Environment - Add watch rule
      for /etc/sysconfig/network in /etc/audit/rules.d/
    ansible.builtin.lineinfile:
      path: '{{ all_files[0] }}'
      line: -w /etc/sysconfig/network -p wa -k audit_rules_networkconfig_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
    - 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.5.5
    - PCI-DSSv4-10.3
    - PCI-DSSv4-10.3.4
    - audit_rules_networkconfig_modification
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Record Events that Modify the System's Network Environment - Check if watch
      rule for /etc/sysconfig/network already exists in /etc/audit/audit.rules
    ansible.builtin.find:
      paths: /etc/audit/
      contains: ^\s*-w\s+/etc/sysconfig/network\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
    - 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.5.5
    - PCI-DSSv4-10.3
    - PCI-DSSv4-10.3.4
    - audit_rules_networkconfig_modification
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Record Events that Modify the System's Network Environment - Add watch rule
      for /etc/sysconfig/network in /etc/audit/audit.rules
    ansible.builtin.lineinfile:
      line: -w /etc/sysconfig/network -p wa -k audit_rules_networkconfig_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
    - 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.5.5
    - PCI-DSSv4-10.3
    - PCI-DSSv4-10.3.4
    - audit_rules_networkconfig_modification
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Record Attempts to Alter Process and Session Initiation Information btmp
      - Check if watch rule for /var/log/btmp already exists in /etc/audit/rules.d/
    ansible.builtin.find:
      paths: /etc/audit/rules.d
      contains: ^\s*-w\s+/var/log/btmp\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:
    - NIST-800-53-AU-12(c)
    - NIST-800-53-AU-12.1(iv)
    - PCI-DSSv4-10.2
    - PCI-DSSv4-10.2.1
    - PCI-DSSv4-10.2.1.3
    - audit_rules_session_events_btmp
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Record Attempts to Alter Process and Session Initiation Information btmp
      - Search /etc/audit/rules.d for other rules with specified key session
    ansible.builtin.find:
      paths: /etc/audit/rules.d
      contains: ^.*(?:-F key=|-k\s+)session$
      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:
    - NIST-800-53-AU-12(c)
    - NIST-800-53-AU-12.1(iv)
    - PCI-DSSv4-10.2
    - PCI-DSSv4-10.2.1
    - PCI-DSSv4-10.2.1.3
    - audit_rules_session_events_btmp
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Record Attempts to Alter Process and Session Initiation Information btmp
      - Use /etc/audit/rules.d/session.rules as the recipient for the rule
    ansible.builtin.set_fact:
      all_files:
      - /etc/audit/rules.d/session.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:
    - NIST-800-53-AU-12(c)
    - NIST-800-53-AU-12.1(iv)
    - PCI-DSSv4-10.2
    - PCI-DSSv4-10.2.1
    - PCI-DSSv4-10.2.1.3
    - audit_rules_session_events_btmp
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Record Attempts to Alter Process and Session Initiation Information btmp
      - 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:
    - NIST-800-53-AU-12(c)
    - NIST-800-53-AU-12.1(iv)
    - PCI-DSSv4-10.2
    - PCI-DSSv4-10.2.1
    - PCI-DSSv4-10.2.1.3
    - audit_rules_session_events_btmp
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Record Attempts to Alter Process and Session Initiation Information btmp
      - Add watch rule for /var/log/btmp in /etc/audit/rules.d/
    ansible.builtin.lineinfile:
      path: '{{ all_files[0] }}'
      line: -w /var/log/btmp -p wa -k session
      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:
    - NIST-800-53-AU-12(c)
    - NIST-800-53-AU-12.1(iv)
    - PCI-DSSv4-10.2
    - PCI-DSSv4-10.2.1
    - PCI-DSSv4-10.2.1.3
    - audit_rules_session_events_btmp
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Record Attempts to Alter Process and Session Initiation Information btmp
      - Check if watch rule for /var/log/btmp already exists in /etc/audit/audit.rules
    ansible.builtin.find:
      paths: /etc/audit/
      contains: ^\s*-w\s+/var/log/btmp\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:
    - NIST-800-53-AU-12(c)
    - NIST-800-53-AU-12.1(iv)
    - PCI-DSSv4-10.2
    - PCI-DSSv4-10.2.1
    - PCI-DSSv4-10.2.1.3
    - audit_rules_session_events_btmp
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Record Attempts to Alter Process and Session Initiation Information btmp
      - Add watch rule for /var/log/btmp in /etc/audit/audit.rules
    ansible.builtin.lineinfile:
      line: -w /var/log/btmp -p wa -k session
      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:
    - NIST-800-53-AU-12(c)
    - NIST-800-53-AU-12.1(iv)
    - PCI-DSSv4-10.2
    - PCI-DSSv4-10.2.1
    - PCI-DSSv4-10.2.1.3
    - audit_rules_session_events_btmp
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Record Attempts to Alter Process and Session Initiation Information utmp
      - Check if watch rule for /var/run/utmp already exists in /etc/audit/rules.d/
    ansible.builtin.find:
      paths: /etc/audit/rules.d
      contains: ^\s*-w\s+/var/run/utmp\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:
    - NIST-800-53-AU-12(c)
    - NIST-800-53-AU-12.1(iv)
    - PCI-DSSv4-10.2
    - PCI-DSSv4-10.2.1
    - PCI-DSSv4-10.2.1.3
    - audit_rules_session_events_utmp
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Record Attempts to Alter Process and Session Initiation Information utmp
      - Search /etc/audit/rules.d for other rules with specified key session
    ansible.builtin.find:
      paths: /etc/audit/rules.d
      contains: ^.*(?:-F key=|-k\s+)session$
      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:
    - NIST-800-53-AU-12(c)
    - NIST-800-53-AU-12.1(iv)
    - PCI-DSSv4-10.2
    - PCI-DSSv4-10.2.1
    - PCI-DSSv4-10.2.1.3
    - audit_rules_session_events_utmp
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Record Attempts to Alter Process and Session Initiation Information utmp
      - Use /etc/audit/rules.d/session.rules as the recipient for the rule
    ansible.builtin.set_fact:
      all_files:
      - /etc/audit/rules.d/session.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:
    - NIST-800-53-AU-12(c)
    - NIST-800-53-AU-12.1(iv)
    - PCI-DSSv4-10.2
    - PCI-DSSv4-10.2.1
    - PCI-DSSv4-10.2.1.3
    - audit_rules_session_events_utmp
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Record Attempts to Alter Process and Session Initiation Information utmp
      - 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:
    - NIST-800-53-AU-12(c)
    - NIST-800-53-AU-12.1(iv)
    - PCI-DSSv4-10.2
    - PCI-DSSv4-10.2.1
    - PCI-DSSv4-10.2.1.3
    - audit_rules_session_events_utmp
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Record Attempts to Alter Process and Session Initiation Information utmp
      - Add watch rule for /var/run/utmp in /etc/audit/rules.d/
    ansible.builtin.lineinfile:
      path: '{{ all_files[0] }}'
      line: -w /var/run/utmp -p wa -k session
      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:
    - NIST-800-53-AU-12(c)
    - NIST-800-53-AU-12.1(iv)
    - PCI-DSSv4-10.2
    - PCI-DSSv4-10.2.1
    - PCI-DSSv4-10.2.1.3
    - audit_rules_session_events_utmp
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Record Attempts to Alter Process and Session Initiation Information utmp
      - Check if watch rule for /var/run/utmp already exists in /etc/audit/audit.rules
    ansible.builtin.find:
      paths: /etc/audit/
      contains: ^\s*-w\s+/var/run/utmp\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:
    - NIST-800-53-AU-12(c)
    - NIST-800-53-AU-12.1(iv)
    - PCI-DSSv4-10.2
    - PCI-DSSv4-10.2.1
    - PCI-DSSv4-10.2.1.3
    - audit_rules_session_events_utmp
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Record Attempts to Alter Process and Session Initiation Information utmp
      - Add watch rule for /var/run/utmp in /etc/audit/audit.rules
    ansible.builtin.lineinfile:
      line: -w /var/run/utmp -p wa -k session
      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:
    - NIST-800-53-AU-12(c)
    - NIST-800-53-AU-12.1(iv)
    - PCI-DSSv4-10.2
    - PCI-DSSv4-10.2.1
    - PCI-DSSv4-10.2.1.3
    - audit_rules_session_events_utmp
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Record Attempts to Alter Process and Session Initiation Information wtmp
      - Check if watch rule for /var/log/wtmp already exists in /etc/audit/rules.d/
    ansible.builtin.find:
      paths: /etc/audit/rules.d
      contains: ^\s*-w\s+/var/log/wtmp\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:
    - NIST-800-53-AU-12(c)
    - NIST-800-53-AU-12.1(iv)
    - PCI-DSSv4-10.2
    - PCI-DSSv4-10.2.1
    - PCI-DSSv4-10.2.1.3
    - audit_rules_session_events_wtmp
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Record Attempts to Alter Process and Session Initiation Information wtmp
      - Search /etc/audit/rules.d for other rules with specified key session
    ansible.builtin.find:
      paths: /etc/audit/rules.d
      contains: ^.*(?:-F key=|-k\s+)session$
      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:
    - NIST-800-53-AU-12(c)
    - NIST-800-53-AU-12.1(iv)
    - PCI-DSSv4-10.2
    - PCI-DSSv4-10.2.1
    - PCI-DSSv4-10.2.1.3
    - audit_rules_session_events_wtmp
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Record Attempts to Alter Process and Session Initiation Information wtmp
      - Use /etc/audit/rules.d/session.rules as the recipient for the rule
    ansible.builtin.set_fact:
      all_files:
      - /etc/audit/rules.d/session.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:
    - NIST-800-53-AU-12(c)
    - NIST-800-53-AU-12.1(iv)
    - PCI-DSSv4-10.2
    - PCI-DSSv4-10.2.1
    - PCI-DSSv4-10.2.1.3
    - audit_rules_session_events_wtmp
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Record Attempts to Alter Process and Session Initiation Information wtmp
      - 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:
    - NIST-800-53-AU-12(c)
    - NIST-800-53-AU-12.1(iv)
    - PCI-DSSv4-10.2
    - PCI-DSSv4-10.2.1
    - PCI-DSSv4-10.2.1.3
    - audit_rules_session_events_wtmp
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Record Attempts to Alter Process and Session Initiation Information wtmp
      - Add watch rule for /var/log/wtmp in /etc/audit/rules.d/
    ansible.builtin.lineinfile:
      path: '{{ all_files[0] }}'
      line: -w /var/log/wtmp -p wa -k session
      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:
    - NIST-800-53-AU-12(c)
    - NIST-800-53-AU-12.1(iv)
    - PCI-DSSv4-10.2
    - PCI-DSSv4-10.2.1
    - PCI-DSSv4-10.2.1.3
    - audit_rules_session_events_wtmp
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Record Attempts to Alter Process and Session Initiation Information wtmp
      - Check if watch rule for /var/log/wtmp already exists in /etc/audit/audit.rules
    ansible.builtin.find:
      paths: /etc/audit/
      contains: ^\s*-w\s+/var/log/wtmp\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:
    - NIST-800-53-AU-12(c)
    - NIST-800-53-AU-12.1(iv)
    - PCI-DSSv4-10.2
    - PCI-DSSv4-10.2.1
    - PCI-DSSv4-10.2.1.3
    - audit_rules_session_events_wtmp
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Record Attempts to Alter Process and Session Initiation Information wtmp
      - Add watch rule for /var/log/wtmp in /etc/audit/audit.rules
    ansible.builtin.lineinfile:
      line: -w /var/log/wtmp -p wa -k session
      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:
    - NIST-800-53-AU-12(c)
    - NIST-800-53-AU-12.1(iv)
    - PCI-DSSv4-10.2
    - PCI-DSSv4-10.2.1
    - PCI-DSSv4-10.2.1.3
    - audit_rules_session_events_wtmp
    - 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: Ensure auditd Collects System Administrator Actions - 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:
    - CJIS-5.4.1.1
    - NIST-800-171-3.1.7
    - NIST-800-53-AC-2(7)(b)
    - 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.2
    - PCI-DSS-Req-10.2.5.b
    - PCI-DSSv4-10.2
    - PCI-DSSv4-10.2.1
    - PCI-DSSv4-10.2.1.5
    - audit_rules_sysadmin_actions
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Ensure auditd Collects System Administrator Actions - 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:
    - CJIS-5.4.1.1
    - NIST-800-171-3.1.7
    - NIST-800-53-AC-2(7)(b)
    - 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.2
    - PCI-DSS-Req-10.2.5.b
    - PCI-DSSv4-10.2
    - PCI-DSSv4-10.2.1
    - PCI-DSSv4-10.2.1.5
    - audit_rules_sysadmin_actions
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Ensure auditd Collects System Administrator Actions - 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:
    - CJIS-5.4.1.1
    - NIST-800-171-3.1.7
    - NIST-800-53-AC-2(7)(b)
    - 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.2
    - PCI-DSS-Req-10.2.5.b
    - PCI-DSSv4-10.2
    - PCI-DSSv4-10.2.1
    - PCI-DSSv4-10.2.1.5
    - audit_rules_sysadmin_actions
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Ensure auditd Collects System Administrator Actions - 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:
    - CJIS-5.4.1.1
    - NIST-800-171-3.1.7
    - NIST-800-53-AC-2(7)(b)
    - 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.2
    - PCI-DSS-Req-10.2.5.b
    - PCI-DSSv4-10.2
    - PCI-DSSv4-10.2.1
    - PCI-DSSv4-10.2.1.5
    - audit_rules_sysadmin_actions
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Ensure auditd Collects System Administrator Actions - 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:
    - CJIS-5.4.1.1
    - NIST-800-171-3.1.7
    - NIST-800-53-AC-2(7)(b)
    - 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.2
    - PCI-DSS-Req-10.2.5.b
    - PCI-DSSv4-10.2
    - PCI-DSSv4-10.2.1
    - PCI-DSSv4-10.2.1.5
    - audit_rules_sysadmin_actions
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Ensure auditd Collects System Administrator Actions - 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
    - NIST-800-171-3.1.7
    - NIST-800-53-AC-2(7)(b)
    - 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.2
    - PCI-DSS-Req-10.2.5.b
    - PCI-DSSv4-10.2
    - PCI-DSSv4-10.2.1
    - PCI-DSSv4-10.2.1.5
    - audit_rules_sysadmin_actions
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Ensure auditd Collects System Administrator Actions - 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:
    - CJIS-5.4.1.1
    - NIST-800-171-3.1.7
    - NIST-800-53-AC-2(7)(b)
    - 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.2
    - PCI-DSS-Req-10.2.5.b
    - PCI-DSSv4-10.2
    - PCI-DSSv4-10.2.1
    - PCI-DSSv4-10.2.1.5
    - audit_rules_sysadmin_actions
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Ensure auditd Collects System Administrator Actions - 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:
    - CJIS-5.4.1.1
    - NIST-800-171-3.1.7
    - NIST-800-53-AC-2(7)(b)
    - 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.2
    - PCI-DSS-Req-10.2.5.b
    - PCI-DSSv4-10.2
    - PCI-DSSv4-10.2.1
    - PCI-DSSv4-10.2.1.5
    - audit_rules_sysadmin_actions
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Ensure auditd Collects System Administrator Actions - 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:
    - CJIS-5.4.1.1
    - NIST-800-171-3.1.7
    - NIST-800-53-AC-2(7)(b)
    - 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.2
    - PCI-DSS-Req-10.2.5.b
    - PCI-DSSv4-10.2
    - PCI-DSSv4-10.2.1
    - PCI-DSSv4-10.2.1.5
    - audit_rules_sysadmin_actions
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Ensure auditd Collects System Administrator Actions - 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:
    - CJIS-5.4.1.1
    - NIST-800-171-3.1.7
    - NIST-800-53-AC-2(7)(b)
    - 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.2
    - PCI-DSS-Req-10.2.5.b
    - PCI-DSSv4-10.2
    - PCI-DSSv4-10.2.1
    - PCI-DSSv4-10.2.1.5
    - audit_rules_sysadmin_actions
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Ensure auditd Collects System Administrator Actions - 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:
    - CJIS-5.4.1.1
    - NIST-800-171-3.1.7
    - NIST-800-53-AC-2(7)(b)
    - 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.2
    - PCI-DSS-Req-10.2.5.b
    - PCI-DSSv4-10.2
    - PCI-DSSv4-10.2.1
    - PCI-DSSv4-10.2.1.5
    - audit_rules_sysadmin_actions
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Ensure auditd Collects System Administrator Actions - 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:
    - CJIS-5.4.1.1
    - NIST-800-171-3.1.7
    - NIST-800-53-AC-2(7)(b)
    - 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.2
    - PCI-DSS-Req-10.2.5.b
    - PCI-DSSv4-10.2
    - PCI-DSSv4-10.2.1
    - PCI-DSSv4-10.2.1.5
    - audit_rules_sysadmin_actions
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Ensure auditd Collects System Administrator Actions - 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
    - NIST-800-171-3.1.7
    - NIST-800-53-AC-2(7)(b)
    - 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.2
    - PCI-DSS-Req-10.2.5.b
    - PCI-DSSv4-10.2
    - PCI-DSSv4-10.2.1
    - PCI-DSSv4-10.2.1.5
    - audit_rules_sysadmin_actions
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Ensure auditd Collects System Administrator Actions - 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:
    - CJIS-5.4.1.1
    - NIST-800-171-3.1.7
    - NIST-800-53-AC-2(7)(b)
    - 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.2
    - PCI-DSS-Req-10.2.5.b
    - PCI-DSSv4-10.2
    - PCI-DSSv4-10.2.1
    - PCI-DSSv4-10.2.1.5
    - audit_rules_sysadmin_actions
    - 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/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: Record Attempts to perform maintenance activities - Check if watch rule
      for /var/log/sudo.log already exists in /etc/audit/rules.d/
    ansible.builtin.find:
      paths: /etc/audit/rules.d
      contains: ^\s*-w\s+/var/log/sudo.log\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:
    - PCI-DSS-Req-10.2.2
    - PCI-DSS-Req-10.2.5.b
    - PCI-DSSv4-10.2
    - PCI-DSSv4-10.2.1
    - PCI-DSSv4-10.2.1.3
    - audit_sudo_log_events
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Record Attempts to perform maintenance activities - Search /etc/audit/rules.d
      for other rules with specified key maintenance
    ansible.builtin.find:
      paths: /etc/audit/rules.d
      contains: ^.*(?:-F key=|-k\s+)maintenance$
      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:
    - PCI-DSS-Req-10.2.2
    - PCI-DSS-Req-10.2.5.b
    - PCI-DSSv4-10.2
    - PCI-DSSv4-10.2.1
    - PCI-DSSv4-10.2.1.3
    - audit_sudo_log_events
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Record Attempts to perform maintenance activities - Use /etc/audit/rules.d/maintenance.rules
      as the recipient for the rule
    ansible.builtin.set_fact:
      all_files:
      - /etc/audit/rules.d/maintenance.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:
    - PCI-DSS-Req-10.2.2
    - PCI-DSS-Req-10.2.5.b
    - PCI-DSSv4-10.2
    - PCI-DSSv4-10.2.1
    - PCI-DSSv4-10.2.1.3
    - audit_sudo_log_events
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Record Attempts to perform maintenance activities - 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:
    - PCI-DSS-Req-10.2.2
    - PCI-DSS-Req-10.2.5.b
    - PCI-DSSv4-10.2
    - PCI-DSSv4-10.2.1
    - PCI-DSSv4-10.2.1.3
    - audit_sudo_log_events
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Record Attempts to perform maintenance activities - Add watch rule for /var/log/sudo.log
      in /etc/audit/rules.d/
    ansible.builtin.lineinfile:
      path: '{{ all_files[0] }}'
      line: -w /var/log/sudo.log -p wa -k maintenance
      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:
    - PCI-DSS-Req-10.2.2
    - PCI-DSS-Req-10.2.5.b
    - PCI-DSSv4-10.2
    - PCI-DSSv4-10.2.1
    - PCI-DSSv4-10.2.1.3
    - audit_sudo_log_events
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Record Attempts to perform maintenance activities - Check if watch rule
      for /var/log/sudo.log already exists in /etc/audit/audit.rules
    ansible.builtin.find:
      paths: /etc/audit/
      contains: ^\s*-w\s+/var/log/sudo.log\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:
    - PCI-DSS-Req-10.2.2
    - PCI-DSS-Req-10.2.5.b
    - PCI-DSSv4-10.2
    - PCI-DSSv4-10.2.1
    - PCI-DSSv4-10.2.1.3
    - audit_sudo_log_events
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Record Attempts to perform maintenance activities - Add watch rule for /var/log/sudo.log
      in /etc/audit/audit.rules
    ansible.builtin.lineinfile:
      line: -w /var/log/sudo.log -p wa -k maintenance
      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:
    - PCI-DSS-Req-10.2.2
    - PCI-DSS-Req-10.2.5.b
    - PCI-DSSv4-10.2
    - PCI-DSSv4-10.2.1
    - PCI-DSSv4-10.2.1.3
    - audit_sudo_log_events
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Record Access Events to Audit Log Directory - Set architecture for audit
      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:
    - 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-DSSv4-10.3
    - PCI-DSSv4-10.3.1
    - directory_access_var_log_audit
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Record Access Events to Audit Log Directory - Perform remediation of Audit
      rules for /var/log/audit
    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 -F arch=b32(( -S |,)\w+)*(( -S |,){{ item }})+((
          -S |,)\w+)* -F dir=/var/log/audit/ -F perm=r -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-audit-trail.rules
      ansible.builtin.set_fact: audit_file="/etc/audit/rules.d/access-audit-trail.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 dir=/var/log/audit/ -F perm=r
          -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{{ syscalls | join(',') }} -F dir=/var/log/audit/
          -F perm=r -F auid>=1000 -F auid!=unset -F key=access-audit-trail
        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 -F arch=b32(( -S |,)\w+)*(( -S |,){{ item }})+((
          -S |,)\w+)* -F dir=/var/log/audit/ -F perm=r -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 dir=/var/log/audit/ -F perm=r
          -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{{ syscalls | join(',') }} -F dir=/var/log/audit/
          -F perm=r -F auid>=1000 -F auid!=unset -F key=access-audit-trail
        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:
    - 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-DSSv4-10.3
    - PCI-DSSv4-10.3.1
    - directory_access_var_log_audit
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Record Access Events to Audit Log Directory - Perform remediation of Audit
      rules for /var/log/audit for x86_64 platform
    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 -F arch=b64(( -S |,)\w+)*(( -S |,){{ item }})+((
          -S |,)\w+)* -F dir=/var/log/audit/ -F perm=r -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-audit-trail.rules
      ansible.builtin.set_fact: audit_file="/etc/audit/rules.d/access-audit-trail.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 dir=/var/log/audit/ -F perm=r
          -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{{ syscalls | join(',') }} -F dir=/var/log/audit/
          -F perm=r -F auid>=1000 -F auid!=unset -F key=access-audit-trail
        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 -F arch=b64(( -S |,)\w+)*(( -S |,){{ item }})+((
          -S |,)\w+)* -F dir=/var/log/audit/ -F perm=r -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 dir=/var/log/audit/ -F perm=r
          -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{{ syscalls | join(',') }} -F dir=/var/log/audit/
          -F perm=r -F auid>=1000 -F auid!=unset -F key=access-audit-trail
        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:
    - 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-DSSv4-10.3
    - PCI-DSSv4-10.3.1
    - directory_access_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
      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: 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: 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: Set architecture for audit 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
    - 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.4.2.b
    - PCI-DSSv4-10.6
    - PCI-DSSv4-10.6.3
    - audit_rules_time_adjtimex
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Perform remediation of Audit rules for adjtimex for 32bit platform
    block:

    - name: Declare list of syscalls
      ansible.builtin.set_fact:
        syscalls:
        - adjtimex
        syscall_grouping:
        - adjtimex
        - settimeofday
        - stime

    - name: Check existence of adjtimex 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+)* (-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/audit_time_rules.rules
      ansible.builtin.set_fact: audit_file="/etc/audit/rules.d/audit_time_rules.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+)+)( (?:-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 key=audit_time_rules
        create: true
        mode: g-rwx,o-rwx
        state: present
      when: syscalls_found | length == 0

    - name: Declare list of syscalls
      ansible.builtin.set_fact:
        syscalls:
        - adjtimex
        syscall_grouping:
        - adjtimex
        - settimeofday
        - stime

    - name: Check existence of adjtimex in /etc/audit/audit.rules
      ansible.builtin.find:
        paths: /etc/audit
        contains: -a always,exit -F arch=b32(( -S |,)\w+)*(( -S |,){{ item }})+((
          -S |,)\w+)* (-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+)+)( (?:-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 key=audit_time_rules
        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
    - 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.4.2.b
    - PCI-DSSv4-10.6
    - PCI-DSSv4-10.6.3
    - audit_rules_time_adjtimex
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Perform remediation of Audit rules for adjtimex for 64bit platform
    block:

    - name: Declare list of syscalls
      ansible.builtin.set_fact:
        syscalls:
        - adjtimex
        syscall_grouping:
        - adjtimex
        - settimeofday

    - name: Check existence of adjtimex 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+)* (-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/audit_time_rules.rules
      ansible.builtin.set_fact: audit_file="/etc/audit/rules.d/audit_time_rules.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+)+)( (?:-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 key=audit_time_rules
        create: true
        mode: g-rwx,o-rwx
        state: present
      when: syscalls_found | length == 0

    - name: Declare list of syscalls
      ansible.builtin.set_fact:
        syscalls:
        - adjtimex
        syscall_grouping:
        - adjtimex
        - settimeofday
        - stime

    - name: Check existence of adjtimex in /etc/audit/audit.rules
      ansible.builtin.find:
        paths: /etc/audit
        contains: -a always,exit -F arch=b64(( -S |,)\w+)*(( -S |,){{ item }})+((
          -S |,)\w+)* (-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+)+)( (?:-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 key=audit_time_rules
        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
    - 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.4.2.b
    - PCI-DSSv4-10.6
    - PCI-DSSv4-10.6.3
    - audit_rules_time_adjtimex
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Set architecture for audit 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
    - 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.4.2.b
    - PCI-DSSv4-10.6
    - PCI-DSSv4-10.6.3
    - audit_rules_time_clock_settime
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Perform remediation of Audit rules for clock_settime for 32bit platform
    block:

    - name: Declare list of syscalls
      ansible.builtin.set_fact:
        syscalls:
        - clock_settime
        syscall_grouping: []

    - name: Check existence of clock_settime 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 a0=0x0 (-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/time-change.rules
      ansible.builtin.set_fact: audit_file="/etc/audit/rules.d/time-change.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 a0=0x0 (?:-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 a0=0x0 -F
          key=time-change
        create: true
        mode: g-rwx,o-rwx
        state: present
      when: syscalls_found | length == 0

    - name: Declare list of syscalls
      ansible.builtin.set_fact:
        syscalls:
        - clock_settime
        syscall_grouping: []

    - name: Check existence of clock_settime 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 a0=0x0 (-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 a0=0x0 (?:-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 a0=0x0 -F
          key=time-change
        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
    - 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.4.2.b
    - PCI-DSSv4-10.6
    - PCI-DSSv4-10.6.3
    - audit_rules_time_clock_settime
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Perform remediation of Audit rules for clock_settime for 64bit platform
    block:

    - name: Declare list of syscalls
      ansible.builtin.set_fact:
        syscalls:
        - clock_settime
        syscall_grouping: []

    - name: Check existence of clock_settime 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 a0=0x0 (-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/time-change.rules
      ansible.builtin.set_fact: audit_file="/etc/audit/rules.d/time-change.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 a0=0x0 (?:-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 a0=0x0 -F
          key=time-change
        create: true
        mode: g-rwx,o-rwx
        state: present
      when: syscalls_found | length == 0

    - name: Declare list of syscalls
      ansible.builtin.set_fact:
        syscalls:
        - clock_settime
        syscall_grouping: []

    - name: Check existence of clock_settime 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 a0=0x0 (-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 a0=0x0 (?:-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 a0=0x0 -F
          key=time-change
        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
    - 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.4.2.b
    - PCI-DSSv4-10.6
    - PCI-DSSv4-10.6.3
    - audit_rules_time_clock_settime
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Set architecture for audit tasks
    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
    - 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.4.2.b
    - PCI-DSSv4-10.6
    - PCI-DSSv4-10.6.3
    - audit_rules_time_settimeofday
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Perform remediation of Audit rules for settimeofday for 32bit platform
    block:

    - name: Declare list of syscalls
      ansible.builtin.set_fact:
        syscalls:
        - settimeofday
        syscall_grouping:
        - adjtimex
        - settimeofday
        - stime

    - name: Check existence of settimeofday 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+)* (-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/audit_time_rules.rules
      ansible.builtin.set_fact: audit_file="/etc/audit/rules.d/audit_time_rules.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+)+)( (?:-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 key=audit_time_rules
        create: true
        mode: g-rwx,o-rwx
        state: present
      when: syscalls_found | length == 0

    - name: Declare list of syscalls
      ansible.builtin.set_fact:
        syscalls:
        - settimeofday
        syscall_grouping:
        - adjtimex
        - settimeofday
        - stime

    - name: Check existence of settimeofday in /etc/audit/audit.rules
      ansible.builtin.find:
        paths: /etc/audit
        contains: -a always,exit -F arch=b32(( -S |,)\w+)*(( -S |,){{ item }})+((
          -S |,)\w+)* (-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+)+)( (?:-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 key=audit_time_rules
        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
    - 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.4.2.b
    - PCI-DSSv4-10.6
    - PCI-DSSv4-10.6.3
    - audit_rules_time_settimeofday
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Perform remediation of Audit rules for settimeofday for 64bit platform
    block:

    - name: Declare list of syscalls
      ansible.builtin.set_fact:
        syscalls:
        - settimeofday
        syscall_grouping:
        - adjtimex
        - settimeofday
        - stime

    - name: Check existence of settimeofday 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+)* (-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/audit_time_rules.rules
      ansible.builtin.set_fact: audit_file="/etc/audit/rules.d/audit_time_rules.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+)+)( (?:-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 key=audit_time_rules
        create: true
        mode: g-rwx,o-rwx
        state: present
      when: syscalls_found | length == 0

    - name: Declare list of syscalls
      ansible.builtin.set_fact:
        syscalls:
        - settimeofday
        syscall_grouping:
        - adjtimex
        - settimeofday
        - stime

    - name: Check existence of settimeofday in /etc/audit/audit.rules
      ansible.builtin.find:
        paths: /etc/audit
        contains: -a always,exit -F arch=b64(( -S |,)\w+)*(( -S |,){{ item }})+((
          -S |,)\w+)* (-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+)+)( (?:-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 key=audit_time_rules
        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
    - 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.4.2.b
    - PCI-DSSv4-10.6
    - PCI-DSSv4-10.6.3
    - audit_rules_time_settimeofday
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Perform remediation of Audit rules for stime syscall for x86 platform
    block:

    - name: Declare list of syscalls
      ansible.builtin.set_fact:
        syscalls:
        - stime
        syscall_grouping:
        - adjtimex
        - settimeofday
        - stime

    - name: Check existence of stime 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+)* (-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/audit_time_rules.rules
      ansible.builtin.set_fact: audit_file="/etc/audit/rules.d/audit_time_rules.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+)+)( (?:-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 key=audit_time_rules
        create: true
        mode: g-rwx,o-rwx
        state: present
      when: syscalls_found | length == 0

    - name: Declare list of syscalls
      ansible.builtin.set_fact:
        syscalls:
        - stime
        syscall_grouping:
        - adjtimex
        - settimeofday
        - stime

    - name: Check existence of stime in /etc/audit/audit.rules
      ansible.builtin.find:
        paths: /etc/audit
        contains: -a always,exit -F arch=b32(( -S |,)\w+)*(( -S |,){{ item }})+((
          -S |,)\w+)* (-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+)+)( (?:-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 key=audit_time_rules
        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" ) and not ( ansible_architecture ==
      "s390x" ) )
    tags:
    - CJIS-5.4.1.1
    - 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.4.2.b
    - PCI-DSSv4-10.6
    - PCI-DSSv4-10.6.3
    - audit_rules_time_stime
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Record Attempts to Alter the localtime File - Check if watch rule for /etc/localtime
      already exists in /etc/audit/rules.d/
    ansible.builtin.find:
      paths: /etc/audit/rules.d
      contains: ^\s*-w\s+/etc/localtime\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
    - 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.4.2.b
    - PCI-DSSv4-10.6
    - PCI-DSSv4-10.6.3
    - audit_rules_time_watch_localtime
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Record Attempts to Alter the localtime File - Search /etc/audit/rules.d
      for other rules with specified key audit_time_rules
    ansible.builtin.find:
      paths: /etc/audit/rules.d
      contains: ^.*(?:-F key=|-k\s+)audit_time_rules$
      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
    - 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.4.2.b
    - PCI-DSSv4-10.6
    - PCI-DSSv4-10.6.3
    - audit_rules_time_watch_localtime
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Record Attempts to Alter the localtime File - Use /etc/audit/rules.d/audit_time_rules.rules
      as the recipient for the rule
    ansible.builtin.set_fact:
      all_files:
      - /etc/audit/rules.d/audit_time_rules.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
    - 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.4.2.b
    - PCI-DSSv4-10.6
    - PCI-DSSv4-10.6.3
    - audit_rules_time_watch_localtime
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Record Attempts to Alter the localtime File - 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
    - 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.4.2.b
    - PCI-DSSv4-10.6
    - PCI-DSSv4-10.6.3
    - audit_rules_time_watch_localtime
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Record Attempts to Alter the localtime File - Add watch rule for /etc/localtime
      in /etc/audit/rules.d/
    ansible.builtin.lineinfile:
      path: '{{ all_files[0] }}'
      line: -w /etc/localtime -p wa -k audit_time_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_rules_d.matched is defined and find_existing_watch_rules_d.matched
      == 0
    tags:
    - CJIS-5.4.1.1
    - 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.4.2.b
    - PCI-DSSv4-10.6
    - PCI-DSSv4-10.6.3
    - audit_rules_time_watch_localtime
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Record Attempts to Alter the localtime File - Check if watch rule for /etc/localtime
      already exists in /etc/audit/audit.rules
    ansible.builtin.find:
      paths: /etc/audit/
      contains: ^\s*-w\s+/etc/localtime\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
    - 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.4.2.b
    - PCI-DSSv4-10.6
    - PCI-DSSv4-10.6.3
    - audit_rules_time_watch_localtime
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Record Attempts to Alter the localtime File - Add watch rule for /etc/localtime
      in /etc/audit/audit.rules
    ansible.builtin.lineinfile:
      line: -w /etc/localtime -p wa -k audit_time_rules
      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
    - 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.4.2.b
    - PCI-DSSv4-10.6
    - PCI-DSSv4-10.6.3
    - audit_rules_time_watch_localtime
    - 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 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 space_left on Low Disk Space
    ansible.builtin.lineinfile:
      dest: /etc/audit/auditd.conf
      line: space_left = {{ var_auditd_space_left }}
      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:
    - 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
    - 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: 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

Youez - 2016 - github.com/yon3zu
LinuXploit