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/ol7-playbook-ospp.yml
---
###############################################################################
#
# Ansible Playbook for DRAFT - Protection Profile for General Purpose Operating Systems
#
# Profile Description:
# This profile reflects mandatory configuration controls identified in the
# NIAP Configuration Annex to the Protection Profile for General Purpose
# Operating Systems (Protection Profile Version 4.2.1).
# This configuration profile is consistent with CNSSI-1253, which requires
# U.S. National Security Systems to adhere to certain configuration
# parameters. Accordingly, this configuration profile is suitable for
# use in U.S. National Security Systems.
#
# Profile ID:  xccdf_org.ssgproject.content_profile_ospp
# Benchmark ID:  xccdf_org.ssgproject.content_benchmark_OL-7
# 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_ospp --fix-type ansible ssg-ol7-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_ospp
  hosts: all
  vars:
    var_password_pam_unix_remember: '5'
    var_accounts_passwords_pam_faillock_deny: '3'
    var_accounts_passwords_pam_faillock_fail_interval: '900'
    var_accounts_passwords_pam_faillock_unlock_time: '0'
    var_password_pam_dcredit: '-1'
    var_password_pam_difok: '4'
    var_password_pam_lcredit: '-1'
    var_password_pam_maxclassrepeat: '4'
    var_password_pam_maxrepeat: '3'
    var_password_pam_minlen: '12'
    var_password_pam_ocredit: '-1'
    var_password_pam_ucredit: '-1'
    var_accounts_password_minlen_login_defs: '12'
    var_accounts_max_concurrent_login_sessions: '10'
    var_accounts_user_umask: '027'
    sysctl_net_ipv6_conf_all_accept_ra_value: '0'
    sysctl_net_ipv6_conf_all_accept_redirects_value: '0'
    sysctl_net_ipv6_conf_all_accept_source_route_value: '0'
    sysctl_net_ipv6_conf_default_accept_ra_value: '0'
    sysctl_net_ipv6_conf_default_accept_redirects_value: '0'
    sysctl_net_ipv6_conf_default_accept_source_route_value: '0'
    sysctl_net_ipv4_conf_all_accept_redirects_value: '0'
    sysctl_net_ipv4_conf_all_accept_source_route_value: '0'
    sysctl_net_ipv4_conf_all_log_martians_value: '1'
    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_conf_default_accept_source_route_value: '0'
    sysctl_net_ipv4_conf_default_log_martians_value: '1'
    sysctl_net_ipv4_conf_default_rp_filter_value: '1'
    sysctl_net_ipv4_conf_default_secure_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'
    sysctl_kernel_kptr_restrict_value: '1'
    var_slub_debug_options: P
    var_selinux_policy_name: targeted
    var_selinux_state: enforcing
    sshd_idle_timeout_value: '600'
    sshd_approved_ciphers: aes128-ctr,aes192-ctr,aes256-ctr,aes128-cbc,3des-cbc,aes192-cbc,aes256-cbc,[email protected]
    sshd_approved_macs: hmac-sha2-512,hmac-sha2-256,hmac-sha1,[email protected],[email protected],[email protected]
    var_audit_backlog_limit: '8192'
    var_auditd_flush: incremental_async
  tasks:

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

  - name: Ensure dracut-fips is installed
    ansible.builtin.package:
      name: dracut-fips
      state: present
    when: ( not ( lookup("env", "container") == "bwrap-osbuild" ) and ("kernel" in
      ansible_facts.packages or "kernel-uek" in ansible_facts.packages) )
    tags:
    - CJIS-5.10.1.2
    - NIST-800-171-3.13.11
    - NIST-800-171-3.13.8
    - NIST-800-53-CM-6(a)
    - NIST-800-53-IA-7
    - NIST-800-53-SC-12
    - NIST-800-53-SC-12(2)
    - NIST-800-53-SC-12(3)
    - NIST-800-53-SC-13
    - enable_strategy
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - package_dracut-fips_installed

  - name: Ensure dracut-fips-aesni is installed
    ansible.builtin.package:
      name: dracut-fips-aesni
      state: present
    when:
    - ( "grub2-common" in ansible_facts.packages and not ( lookup("env", "container")
      == "bwrap-osbuild" ) and ("kernel" in ansible_facts.packages or "kernel-uek"
      in ansible_facts.packages) )
    - aesni_supported.rc == 0
    tags:
    - CJIS-5.10.1.2
    - DISA-STIG-OL07-00-021350
    - NIST-800-171-3.13.11
    - NIST-800-171-3.13.8
    - NIST-800-53-CM-6(a)
    - NIST-800-53-IA-7
    - NIST-800-53-SC-12
    - NIST-800-53-SC-12(2)
    - NIST-800-53-SC-12(3)
    - NIST-800-53-SC-13
    - grub2_enable_fips_mode
    - high_complexity
    - high_severity
    - medium_disruption
    - reboot_required
    - restrict_strategy

  - name: Install dracut-fips
    ansible.builtin.package:
      name: dracut-fips
      state: present
    when: ( "grub2-common" in ansible_facts.packages and not ( lookup("env", "container")
      == "bwrap-osbuild" ) and ("kernel" in ansible_facts.packages or "kernel-uek"
      in ansible_facts.packages) )
    tags:
    - CJIS-5.10.1.2
    - DISA-STIG-OL07-00-021350
    - NIST-800-171-3.13.11
    - NIST-800-171-3.13.8
    - NIST-800-53-CM-6(a)
    - NIST-800-53-IA-7
    - NIST-800-53-SC-12
    - NIST-800-53-SC-12(2)
    - NIST-800-53-SC-12(3)
    - NIST-800-53-SC-13
    - grub2_enable_fips_mode
    - high_complexity
    - high_severity
    - medium_disruption
    - reboot_required
    - restrict_strategy

  - name: Ensure screen is installed
    ansible.builtin.package:
      name: screen
      state: present
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL07-00-010090
    - NIST-800-171-3.1.10
    - NIST-800-53-CM-6(a)
    - enable_strategy
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - package_screen_installed

  - name: 'Uninstall Automatic Bug Reporting Tool (abrt): Ensure abrt is removed'
    ansible.builtin.package:
      name: abrt
      state: absent
    tags:
    - disable_strategy
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - package_abrt_removed

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

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

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

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

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

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

  - name: 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-OL07-00-040520
    - NIST-800-171-3.1.3
    - NIST-800-171-3.4.7
    - NIST-800-53-AC-4
    - NIST-800-53-CA-3(5)
    - NIST-800-53-CM-6(a)
    - NIST-800-53-CM-7(b)
    - NIST-800-53-SC-7(21)
    - PCI-DSSv4-1.2
    - PCI-DSSv4-1.2.1
    - enable_strategy
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - service_firewalld_enabled
    - special_service_block
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - '"firewalld" in ansible_facts.packages'

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

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

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

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

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

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

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

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

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

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

  - name: Disable rpcbind Service - Disable service rpcbind
    block:

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

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

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

    - name: Disable rpcbind Service - Disable Socket rpcbind
      ansible.builtin.systemd:
        name: rpcbind.socket
        enabled: false
        state: stopped
        masked: true
      when: socket_file_exists.stdout_lines is search("rpcbind.socket", multiline=True)
    tags:
    - PCI-DSSv4-2.2
    - PCI-DSSv4-2.2.4
    - disable_strategy
    - low_complexity
    - low_disruption
    - low_severity
    - no_reboot_needed
    - service_rpcbind_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-OL07-00-030000
    - 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: Check prelink binary installed
    ansible.builtin.stat:
      path: /usr/sbin/prelink
    register: prelink_exists
    when: ( "grub2-common" in ansible_facts.packages and not ( lookup("env", "container")
      == "bwrap-osbuild" ) and ("kernel" in ansible_facts.packages or "kernel-uek"
      in ansible_facts.packages) )
    tags:
    - CJIS-5.10.1.2
    - DISA-STIG-OL07-00-021350
    - NIST-800-171-3.13.11
    - NIST-800-171-3.13.8
    - NIST-800-53-CM-6(a)
    - NIST-800-53-IA-7
    - NIST-800-53-SC-12
    - NIST-800-53-SC-12(2)
    - NIST-800-53-SC-12(3)
    - NIST-800-53-SC-13
    - grub2_enable_fips_mode
    - high_complexity
    - high_severity
    - medium_disruption
    - reboot_required
    - restrict_strategy

  - name: Disable prelink
    ansible.builtin.lineinfile:
      dest: /etc/sysconfig/prelink
      regexp: ^#?PRELINKING
      line: PRELINKING=no
    when:
    - ( "grub2-common" in ansible_facts.packages and not ( lookup("env", "container")
      == "bwrap-osbuild" ) and ("kernel" in ansible_facts.packages or "kernel-uek"
      in ansible_facts.packages) )
    - prelink_exists.stat.exists
    tags:
    - CJIS-5.10.1.2
    - DISA-STIG-OL07-00-021350
    - NIST-800-171-3.13.11
    - NIST-800-171-3.13.8
    - NIST-800-53-CM-6(a)
    - NIST-800-53-IA-7
    - NIST-800-53-SC-12
    - NIST-800-53-SC-12(2)
    - NIST-800-53-SC-12(3)
    - NIST-800-53-SC-13
    - grub2_enable_fips_mode
    - high_complexity
    - high_severity
    - medium_disruption
    - reboot_required
    - restrict_strategy

  - name: Revert prelinking binaries
    ansible.builtin.command: /usr/sbin/prelink -ua
    when:
    - ( "grub2-common" in ansible_facts.packages and not ( lookup("env", "container")
      == "bwrap-osbuild" ) and ("kernel" in ansible_facts.packages or "kernel-uek"
      in ansible_facts.packages) )
    - prelink_exists.stat.exists
    tags:
    - CJIS-5.10.1.2
    - DISA-STIG-OL07-00-021350
    - NIST-800-171-3.13.11
    - NIST-800-171-3.13.8
    - NIST-800-53-CM-6(a)
    - NIST-800-53-IA-7
    - NIST-800-53-SC-12
    - NIST-800-53-SC-12(2)
    - NIST-800-53-SC-12(3)
    - NIST-800-53-SC-13
    - grub2_enable_fips_mode
    - high_complexity
    - high_severity
    - medium_disruption
    - reboot_required
    - restrict_strategy

  - name: Check if system supports AES-NI
    ansible.builtin.command: grep -q -m1 -o aes /proc/cpuinfo
    failed_when: aesni_supported.rc > 1
    register: aesni_supported
    check_mode: false
    when: ( "grub2-common" in ansible_facts.packages and not ( lookup("env", "container")
      == "bwrap-osbuild" ) and ("kernel" in ansible_facts.packages or "kernel-uek"
      in ansible_facts.packages) )
    tags:
    - CJIS-5.10.1.2
    - DISA-STIG-OL07-00-021350
    - NIST-800-171-3.13.11
    - NIST-800-171-3.13.8
    - NIST-800-53-CM-6(a)
    - NIST-800-53-IA-7
    - NIST-800-53-SC-12
    - NIST-800-53-SC-12(2)
    - NIST-800-53-SC-12(3)
    - NIST-800-53-SC-13
    - grub2_enable_fips_mode
    - high_complexity
    - high_severity
    - medium_disruption
    - reboot_required
    - restrict_strategy

  - name: Rebuild initramfs
    ansible.builtin.command: dracut -f
    when: ( "grub2-common" in ansible_facts.packages and not ( lookup("env", "container")
      == "bwrap-osbuild" ) and ("kernel" in ansible_facts.packages or "kernel-uek"
      in ansible_facts.packages) )
    tags:
    - CJIS-5.10.1.2
    - DISA-STIG-OL07-00-021350
    - NIST-800-171-3.13.11
    - NIST-800-171-3.13.8
    - NIST-800-53-CM-6(a)
    - NIST-800-53-IA-7
    - NIST-800-53-SC-12
    - NIST-800-53-SC-12(2)
    - NIST-800-53-SC-12(3)
    - NIST-800-53-SC-13
    - grub2_enable_fips_mode
    - high_complexity
    - high_severity
    - medium_disruption
    - reboot_required
    - restrict_strategy

  - name: Check fips argument exists
    ansible.builtin.command: grep 'GRUB_CMDLINE_LINUX.*fips=' /etc/default/grub
    failed_when: false
    register: fipsargcheck
    check_mode: false
    when: ( "grub2-common" in ansible_facts.packages and not ( lookup("env", "container")
      == "bwrap-osbuild" ) and ("kernel" in ansible_facts.packages or "kernel-uek"
      in ansible_facts.packages) )
    tags:
    - CJIS-5.10.1.2
    - DISA-STIG-OL07-00-021350
    - NIST-800-171-3.13.11
    - NIST-800-171-3.13.8
    - NIST-800-53-CM-6(a)
    - NIST-800-53-IA-7
    - NIST-800-53-SC-12
    - NIST-800-53-SC-12(2)
    - NIST-800-53-SC-12(3)
    - NIST-800-53-SC-13
    - grub2_enable_fips_mode
    - high_complexity
    - high_severity
    - medium_disruption
    - reboot_required
    - restrict_strategy

  - name: Replace existing fips argument
    ansible.builtin.replace:
      path: /etc/default/grub
      regexp: fips=.
      replace: fips=1
    when:
    - ( "grub2-common" in ansible_facts.packages and not ( lookup("env", "container")
      == "bwrap-osbuild" ) and ("kernel" in ansible_facts.packages or "kernel-uek"
      in ansible_facts.packages) )
    - fipsargcheck.rc == 0
    tags:
    - CJIS-5.10.1.2
    - DISA-STIG-OL07-00-021350
    - NIST-800-171-3.13.11
    - NIST-800-171-3.13.8
    - NIST-800-53-CM-6(a)
    - NIST-800-53-IA-7
    - NIST-800-53-SC-12
    - NIST-800-53-SC-12(2)
    - NIST-800-53-SC-12(3)
    - NIST-800-53-SC-13
    - grub2_enable_fips_mode
    - high_complexity
    - high_severity
    - medium_disruption
    - reboot_required
    - restrict_strategy

  - name: Add fips argument
    ansible.builtin.replace:
      path: /etc/default/grub
      regexp: (GRUB_CMDLINE_LINUX=.*)"
      replace: \1 fips=1"
    when:
    - ( "grub2-common" in ansible_facts.packages and not ( lookup("env", "container")
      == "bwrap-osbuild" ) and ("kernel" in ansible_facts.packages or "kernel-uek"
      in ansible_facts.packages) )
    - fipsargcheck.rc != 0
    tags:
    - CJIS-5.10.1.2
    - DISA-STIG-OL07-00-021350
    - NIST-800-171-3.13.11
    - NIST-800-171-3.13.8
    - NIST-800-53-CM-6(a)
    - NIST-800-53-IA-7
    - NIST-800-53-SC-12
    - NIST-800-53-SC-12(2)
    - NIST-800-53-SC-12(3)
    - NIST-800-53-SC-13
    - grub2_enable_fips_mode
    - high_complexity
    - high_severity
    - medium_disruption
    - reboot_required
    - restrict_strategy

  - name: Get boot device uuid
    ansible.builtin.command: findmnt --noheadings --output uuid --target /boot
    register: bootuuid
    check_mode: false
    when: ( "grub2-common" in ansible_facts.packages and not ( lookup("env", "container")
      == "bwrap-osbuild" ) and ("kernel" in ansible_facts.packages or "kernel-uek"
      in ansible_facts.packages) )
    tags:
    - CJIS-5.10.1.2
    - DISA-STIG-OL07-00-021350
    - NIST-800-171-3.13.11
    - NIST-800-171-3.13.8
    - NIST-800-53-CM-6(a)
    - NIST-800-53-IA-7
    - NIST-800-53-SC-12
    - NIST-800-53-SC-12(2)
    - NIST-800-53-SC-12(3)
    - NIST-800-53-SC-13
    - grub2_enable_fips_mode
    - high_complexity
    - high_severity
    - medium_disruption
    - reboot_required
    - restrict_strategy

  - name: Check boot argument exists
    ansible.builtin.command: grep 'GRUB_CMDLINE_LINUX.*boot=' /etc/default/grub
    failed_when: false
    register: bootargcheck
    check_mode: false
    when: ( "grub2-common" in ansible_facts.packages and not ( lookup("env", "container")
      == "bwrap-osbuild" ) and ("kernel" in ansible_facts.packages or "kernel-uek"
      in ansible_facts.packages) )
    tags:
    - CJIS-5.10.1.2
    - DISA-STIG-OL07-00-021350
    - NIST-800-171-3.13.11
    - NIST-800-171-3.13.8
    - NIST-800-53-CM-6(a)
    - NIST-800-53-IA-7
    - NIST-800-53-SC-12
    - NIST-800-53-SC-12(2)
    - NIST-800-53-SC-12(3)
    - NIST-800-53-SC-13
    - grub2_enable_fips_mode
    - high_complexity
    - high_severity
    - medium_disruption
    - reboot_required
    - restrict_strategy

  - name: Replace existing boot argument
    ansible.builtin.replace:
      path: /etc/default/grub
      regexp: boot=\w*-\w*-\w*-\w*-\w*
      replace: boot={{ bootuuid.stdout }}
    when:
    - ( "grub2-common" in ansible_facts.packages and not ( lookup("env", "container")
      == "bwrap-osbuild" ) and ("kernel" in ansible_facts.packages or "kernel-uek"
      in ansible_facts.packages) )
    - bootargcheck.rc == 0
    tags:
    - CJIS-5.10.1.2
    - DISA-STIG-OL07-00-021350
    - NIST-800-171-3.13.11
    - NIST-800-171-3.13.8
    - NIST-800-53-CM-6(a)
    - NIST-800-53-IA-7
    - NIST-800-53-SC-12
    - NIST-800-53-SC-12(2)
    - NIST-800-53-SC-12(3)
    - NIST-800-53-SC-13
    - grub2_enable_fips_mode
    - high_complexity
    - high_severity
    - medium_disruption
    - reboot_required
    - restrict_strategy

  - name: Add boot argument
    ansible.builtin.replace:
      path: /etc/default/grub
      regexp: (GRUB_CMDLINE_LINUX=.*)"
      replace: \1 boot=UUID={{ bootuuid.stdout }}"
    when:
    - ( "grub2-common" in ansible_facts.packages and not ( lookup("env", "container")
      == "bwrap-osbuild" ) and ("kernel" in ansible_facts.packages or "kernel-uek"
      in ansible_facts.packages) )
    - bootargcheck.rc != 0
    tags:
    - CJIS-5.10.1.2
    - DISA-STIG-OL07-00-021350
    - NIST-800-171-3.13.11
    - NIST-800-171-3.13.8
    - NIST-800-53-CM-6(a)
    - NIST-800-53-IA-7
    - NIST-800-53-SC-12
    - NIST-800-53-SC-12(2)
    - NIST-800-53-SC-12(3)
    - NIST-800-53-SC-13
    - grub2_enable_fips_mode
    - high_complexity
    - high_severity
    - medium_disruption
    - reboot_required
    - restrict_strategy

  - name: Update bootloader menu
    ansible.builtin.command: /sbin/grubby --update-kernel=ALL --args="fips=1 boot=UUID={{
      bootuuid.stdout }}"
    when: ( "grub2-common" in ansible_facts.packages and not ( lookup("env", "container")
      == "bwrap-osbuild" ) and ("kernel" in ansible_facts.packages or "kernel-uek"
      in ansible_facts.packages) )
    tags:
    - CJIS-5.10.1.2
    - DISA-STIG-OL07-00-021350
    - NIST-800-171-3.13.11
    - NIST-800-171-3.13.8
    - NIST-800-53-CM-6(a)
    - NIST-800-53-IA-7
    - NIST-800-53-SC-12
    - NIST-800-53-SC-12(2)
    - NIST-800-53-SC-12(3)
    - NIST-800-53-SC-13
    - grub2_enable_fips_mode
    - high_complexity
    - high_severity
    - medium_disruption
    - reboot_required
    - restrict_strategy

  - 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-OL07-00-020050
    - NIST-800-171-3.4.8
    - NIST-800-53-CM-11(a)
    - NIST-800-53-CM-11(b)
    - NIST-800-53-CM-5(3)
    - NIST-800-53-CM-6(a)
    - NIST-800-53-SA-12
    - NIST-800-53-SA-12(10)
    - NIST-800-53-SC-12
    - NIST-800-53-SC-12(3)
    - NIST-800-53-SI-7
    - PCI-DSS-Req-6.2
    - PCI-DSSv4-6.3
    - PCI-DSSv4-6.3.3
    - configure_strategy
    - ensure_gpgcheck_globally_activated
    - high_severity
    - low_complexity
    - medium_disruption
    - no_reboot_needed

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

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

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

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

  - name: Grep for yum repo section names
    ansible.builtin.shell: |
      set -o pipefail
      grep -HEr '^\[.+\]' -r /etc/yum.repos.d/
    register: repo_grep_results
    failed_when: repo_grep_results.rc not in [0, 1]
    changed_when: false
    tags:
    - CJIS-5.10.4.1
    - 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
    - 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-OL07-00-010019
    - 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 --with-fingerprint --with-colons "/etc/pki/rpm-gpg/RPM-GPG-KEY-oracle"
    changed_when: false
    register: gpg_fingerprints
    check_mode: false
    tags:
    - DISA-STIG-OL07-00-010019
    - 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-OL07-00-010019
    - 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:
      - 42144123FECFC55B9086313D72F97B74EC551F03
      - ''
    tags:
    - DISA-STIG-OL07-00-010019
    - 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-OL07-00-010019
    - 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: 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-OL07-00-010320
    - 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-OL07-00-010320
    - 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-OL07-00-010320
    - 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-OL07-00-010320
    - 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-OL07-00-010320
    - 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-OL07-00-010320
    - 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-OL07-00-010320
    - 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 Interval For Counting Failed Password Attempts - Check if system relies
      on authselect tool
    ansible.builtin.stat:
      path: /usr/bin/authselect
    register: result_authselect_present
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - '"pam" in ansible_facts.packages'
    tags:
    - DISA-STIG-OL07-00-010320
    - NIST-800-53-AC-7(a)
    - NIST-800-53-CM-6(a)
    - accounts_passwords_pam_faillock_interval
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

  - name: Set Lockout Time for Failed Password Attempts - Check if system relies on
      authselect tool
    ansible.builtin.stat:
      path: /usr/bin/authselect
    register: result_authselect_present
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - '"pam" in ansible_facts.packages'
    tags:
    - CJIS-5.5.3
    - DISA-STIG-OL07-00-010320
    - 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-OL07-00-010320
    - 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-OL07-00-010320
    - 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-OL07-00-010320
    - 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-OL07-00-010320
    - 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-OL07-00-010320
    - 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-OL07-00-010320
    - 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-OL07-00-010140
    - 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-OL07-00-010140
    - 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-OL07-00-010140
    - 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-OL07-00-010140
    - 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-OL07-00-010140
    - 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-OL07-00-010140
    - 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-OL07-00-010140
    - 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 Different Characters
      - Find pwquality.conf.d files
    ansible.builtin.find:
      paths: /etc/security/pwquality.conf.d/
      patterns: '*.conf'
    register: pwquality_conf_d_files
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - '"libpwquality" in ansible_facts.packages'
    tags:
    - CJIS-5.6.2.1.1
    - DISA-STIG-OL07-00-010160
    - NIST-800-53-CM-6(a)
    - NIST-800-53-IA-5(1)(b)
    - NIST-800-53-IA-5(4)
    - NIST-800-53-IA-5(c)
    - accounts_password_pam_difok
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Ensure PAM Enforces Password Requirements - Minimum Different Characters
      - Ensure difok is not set in pwquality.conf.d
    ansible.builtin.lineinfile:
      path: '{{ item.path }}'
      regexp: ^\s*\bdifok\b.*
      state: absent
    with_items: '{{ pwquality_conf_d_files.files }}'
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - '"libpwquality" in ansible_facts.packages'
    tags:
    - CJIS-5.6.2.1.1
    - DISA-STIG-OL07-00-010160
    - NIST-800-53-CM-6(a)
    - NIST-800-53-IA-5(1)(b)
    - NIST-800-53-IA-5(4)
    - NIST-800-53-IA-5(c)
    - accounts_password_pam_difok
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Ensure PAM Enforces Password Requirements - Minimum Different Characters
      - Check if /etc/pam.d/system-auth file is present
    ansible.builtin.stat:
      path: /etc/pam.d/system-auth
    register: result_pam_auth_file_present
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - '"libpwquality" in ansible_facts.packages'
    tags:
    - CJIS-5.6.2.1.1
    - DISA-STIG-OL07-00-010160
    - NIST-800-53-CM-6(a)
    - NIST-800-53-IA-5(1)(b)
    - NIST-800-53-IA-5(4)
    - NIST-800-53-IA-5(c)
    - accounts_password_pam_difok
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    - name: Ensure PAM Enforces Password Requirements - Minimum Different Characters
        - Ensure authselect changes are applied
      ansible.builtin.command:
        cmd: authselect apply-changes -b
      when:
      - result_authselect_present.stat.exists
      - result_pam_option_removal is changed
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - '"libpwquality" in ansible_facts.packages'
    - result_pam_auth_file_present.stat.exists
    tags:
    - CJIS-5.6.2.1.1
    - DISA-STIG-OL07-00-010160
    - NIST-800-53-CM-6(a)
    - NIST-800-53-IA-5(1)(b)
    - NIST-800-53-IA-5(4)
    - NIST-800-53-IA-5(c)
    - accounts_password_pam_difok
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Ensure PAM Enforces Password Requirements - Minimum Different Characters
      - Check if /etc/pam.d/password-auth file is present
    ansible.builtin.stat:
      path: /etc/pam.d/password-auth
    register: result_pam_password_auth_file_present
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - '"libpwquality" in ansible_facts.packages'
    tags:
    - CJIS-5.6.2.1.1
    - DISA-STIG-OL07-00-010160
    - NIST-800-53-CM-6(a)
    - NIST-800-53-IA-5(1)(b)
    - NIST-800-53-IA-5(4)
    - NIST-800-53-IA-5(c)
    - accounts_password_pam_difok
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    - name: Ensure PAM Enforces Password Requirements - Minimum Different Characters
        - Ensure authselect changes are applied
      ansible.builtin.command:
        cmd: authselect apply-changes -b
      when:
      - result_authselect_present.stat.exists
      - result_pam_option_removal is changed
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - '"libpwquality" in ansible_facts.packages'
    - result_pam_password_auth_file_present.stat.exists
    tags:
    - CJIS-5.6.2.1.1
    - DISA-STIG-OL07-00-010160
    - NIST-800-53-CM-6(a)
    - NIST-800-53-IA-5(1)(b)
    - NIST-800-53-IA-5(4)
    - NIST-800-53-IA-5(c)
    - accounts_password_pam_difok
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Ensure PAM Enforces Password Requirements - Minimum Different Characters
      - Ensure PAM variable difok is set accordingly
    ansible.builtin.lineinfile:
      create: true
      dest: /etc/security/pwquality.conf
      regexp: ^#?\s*difok
      line: difok = {{ var_password_pam_difok }}
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - '"libpwquality" in ansible_facts.packages'
    tags:
    - CJIS-5.6.2.1.1
    - DISA-STIG-OL07-00-010160
    - NIST-800-53-CM-6(a)
    - NIST-800-53-IA-5(1)(b)
    - NIST-800-53-IA-5(4)
    - NIST-800-53-IA-5(c)
    - accounts_password_pam_difok
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Ensure PAM Enforces Password Requirements - Minimum 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-OL07-00-010130
    - 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-OL07-00-010130
    - 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-OL07-00-010130
    - 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-OL07-00-010130
    - 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-OL07-00-010130
    - 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-OL07-00-010130
    - 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-OL07-00-010130
    - NIST-800-53-CM-6(a)
    - NIST-800-53-IA-5(1)(a)
    - NIST-800-53-IA-5(4)
    - NIST-800-53-IA-5(c)
    - PCI-DSS-Req-8.2.3
    - PCI-DSSv4-8.3
    - PCI-DSSv4-8.3.6
    - accounts_password_pam_lcredit
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Ensure PAM Enforces Password Requirements - Maximum Consecutive Repeating
      Characters from Same Character Class - Find pwquality.conf.d files
    ansible.builtin.find:
      paths: /etc/security/pwquality.conf.d/
      patterns: '*.conf'
    register: pwquality_conf_d_files
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - '"libpwquality" in ansible_facts.packages'
    tags:
    - DISA-STIG-OL07-00-010190
    - NIST-800-53-CM-6(a)
    - NIST-800-53-IA-5(1)(a)
    - NIST-800-53-IA-5(4)
    - NIST-800-53-IA-5(c)
    - accounts_password_pam_maxclassrepeat
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Ensure PAM Enforces Password Requirements - Maximum Consecutive Repeating
      Characters from Same Character Class - Ensure maxclassrepeat is not set in pwquality.conf.d
    ansible.builtin.lineinfile:
      path: '{{ item.path }}'
      regexp: ^\s*\bmaxclassrepeat\b.*
      state: absent
    with_items: '{{ pwquality_conf_d_files.files }}'
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - '"libpwquality" in ansible_facts.packages'
    tags:
    - DISA-STIG-OL07-00-010190
    - NIST-800-53-CM-6(a)
    - NIST-800-53-IA-5(1)(a)
    - NIST-800-53-IA-5(4)
    - NIST-800-53-IA-5(c)
    - accounts_password_pam_maxclassrepeat
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Ensure PAM Enforces Password Requirements - Maximum Consecutive Repeating
      Characters from Same Character Class - Check if /etc/pam.d/system-auth file
      is present
    ansible.builtin.stat:
      path: /etc/pam.d/system-auth
    register: result_pam_auth_file_present
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - '"libpwquality" in ansible_facts.packages'
    tags:
    - DISA-STIG-OL07-00-010190
    - NIST-800-53-CM-6(a)
    - NIST-800-53-IA-5(1)(a)
    - NIST-800-53-IA-5(4)
    - NIST-800-53-IA-5(c)
    - accounts_password_pam_maxclassrepeat
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Ensure PAM Enforces Password Requirements - Maximum Consecutive Repeating
      Characters from Same Character Class - Check the proper remediation for the
      system
    block:

    - name: Ensure PAM Enforces Password Requirements - Maximum Consecutive Repeating
        Characters from Same Character Class - Define the PAM file to be edited as
        a local fact
      ansible.builtin.set_fact:
        pam_file_path: /etc/pam.d/system-auth

    - name: Ensure PAM Enforces Password Requirements - Maximum Consecutive Repeating
        Characters from Same Character Class - Check if system relies on authselect
        tool
      ansible.builtin.stat:
        path: /usr/bin/authselect
      register: result_authselect_present

    - name: Ensure PAM Enforces Password Requirements - Maximum Consecutive Repeating
        Characters from Same Character Class - Ensure authselect custom profile is
        used if authselect is present
      block:

      - name: Ensure PAM Enforces Password Requirements - Maximum Consecutive Repeating
          Characters from Same Character Class - Check integrity of authselect current
          profile
        ansible.builtin.command:
          cmd: authselect check
        register: result_authselect_check_cmd
        changed_when: false
        check_mode: false
        failed_when: false

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

      - name: Ensure PAM Enforces Password Requirements - Maximum Consecutive Repeating
          Characters from Same Character Class - Get authselect current profile
        ansible.builtin.shell:
          cmd: authselect current -r | awk '{ print $1 }'
        register: result_authselect_profile
        changed_when: false
        when:
        - result_authselect_check_cmd is success

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

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

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

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

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

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

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

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

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

      - name: Ensure PAM Enforces Password Requirements - Maximum Consecutive Repeating
          Characters from Same Character Class - Ensure authselect changes are applied
        ansible.builtin.command:
          cmd: authselect apply-changes -b --backup=after-hardening-custom-profile
        when:
        - result_authselect_check_cmd is success
        - result_authselect_profile is not skipped
        - result_pam_authselect_restore_features is not skipped

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

    - name: Ensure PAM Enforces Password Requirements - Maximum Consecutive Repeating
        Characters from Same Character Class - Define a fact for control already filtered
        in case filters are used
      ansible.builtin.set_fact:
        pam_module_control: ''

    - name: Ensure PAM Enforces Password Requirements - Maximum Consecutive Repeating
        Characters from Same Character Class - Check if {{ pam_file_path }} file is
        present
      ansible.builtin.stat:
        path: '{{ pam_file_path }}'
      register: result_pam_file_present

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

    - name: Ensure PAM Enforces Password Requirements - Maximum Consecutive Repeating
        Characters from Same Character Class - Ensure authselect changes are applied
      ansible.builtin.command:
        cmd: authselect apply-changes -b
      when:
      - result_authselect_present.stat.exists
      - result_pam_option_removal is changed
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - '"libpwquality" in ansible_facts.packages'
    - result_pam_auth_file_present.stat.exists
    tags:
    - DISA-STIG-OL07-00-010190
    - NIST-800-53-CM-6(a)
    - NIST-800-53-IA-5(1)(a)
    - NIST-800-53-IA-5(4)
    - NIST-800-53-IA-5(c)
    - accounts_password_pam_maxclassrepeat
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Ensure PAM Enforces Password Requirements - Maximum Consecutive Repeating
      Characters from Same Character Class - Check if /etc/pam.d/password-auth file
      is present
    ansible.builtin.stat:
      path: /etc/pam.d/password-auth
    register: result_pam_password_auth_file_present
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - '"libpwquality" in ansible_facts.packages'
    tags:
    - DISA-STIG-OL07-00-010190
    - NIST-800-53-CM-6(a)
    - NIST-800-53-IA-5(1)(a)
    - NIST-800-53-IA-5(4)
    - NIST-800-53-IA-5(c)
    - accounts_password_pam_maxclassrepeat
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Ensure PAM Enforces Password Requirements - Maximum Consecutive Repeating
      Characters from Same Character Class - Check the proper remediation for the
      system
    block:

    - name: Ensure PAM Enforces Password Requirements - Maximum Consecutive Repeating
        Characters from Same Character Class - Define the PAM file to be edited as
        a local fact
      ansible.builtin.set_fact:
        pam_file_path: /etc/pam.d/password-auth

    - name: Ensure PAM Enforces Password Requirements - Maximum Consecutive Repeating
        Characters from Same Character Class - Check if system relies on authselect
        tool
      ansible.builtin.stat:
        path: /usr/bin/authselect
      register: result_authselect_present

    - name: Ensure PAM Enforces Password Requirements - Maximum Consecutive Repeating
        Characters from Same Character Class - Ensure authselect custom profile is
        used if authselect is present
      block:

      - name: Ensure PAM Enforces Password Requirements - Maximum Consecutive Repeating
          Characters from Same Character Class - Check integrity of authselect current
          profile
        ansible.builtin.command:
          cmd: authselect check
        register: result_authselect_check_cmd
        changed_when: false
        check_mode: false
        failed_when: false

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

      - name: Ensure PAM Enforces Password Requirements - Maximum Consecutive Repeating
          Characters from Same Character Class - Get authselect current profile
        ansible.builtin.shell:
          cmd: authselect current -r | awk '{ print $1 }'
        register: result_authselect_profile
        changed_when: false
        when:
        - result_authselect_check_cmd is success

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

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

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

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

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

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

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

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

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

      - name: Ensure PAM Enforces Password Requirements - Maximum Consecutive Repeating
          Characters from Same Character Class - Ensure authselect changes are applied
        ansible.builtin.command:
          cmd: authselect apply-changes -b --backup=after-hardening-custom-profile
        when:
        - result_authselect_check_cmd is success
        - result_authselect_profile is not skipped
        - result_pam_authselect_restore_features is not skipped

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

    - name: Ensure PAM Enforces Password Requirements - Maximum Consecutive Repeating
        Characters from Same Character Class - Define a fact for control already filtered
        in case filters are used
      ansible.builtin.set_fact:
        pam_module_control: ''

    - name: Ensure PAM Enforces Password Requirements - Maximum Consecutive Repeating
        Characters from Same Character Class - Check if {{ pam_file_path }} file is
        present
      ansible.builtin.stat:
        path: '{{ pam_file_path }}'
      register: result_pam_file_present

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

    - name: Ensure PAM Enforces Password Requirements - Maximum Consecutive Repeating
        Characters from Same Character Class - Ensure authselect changes are applied
      ansible.builtin.command:
        cmd: authselect apply-changes -b
      when:
      - result_authselect_present.stat.exists
      - result_pam_option_removal is changed
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - '"libpwquality" in ansible_facts.packages'
    - result_pam_password_auth_file_present.stat.exists
    tags:
    - DISA-STIG-OL07-00-010190
    - NIST-800-53-CM-6(a)
    - NIST-800-53-IA-5(1)(a)
    - NIST-800-53-IA-5(4)
    - NIST-800-53-IA-5(c)
    - accounts_password_pam_maxclassrepeat
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Ensure PAM Enforces Password Requirements - Maximum Consecutive Repeating
      Characters from Same Character Class - Ensure PAM variable maxclassrepeat is
      set accordingly
    ansible.builtin.lineinfile:
      create: true
      dest: /etc/security/pwquality.conf
      regexp: ^#?\s*maxclassrepeat
      line: maxclassrepeat = {{ var_password_pam_maxclassrepeat }}
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - '"libpwquality" in ansible_facts.packages'
    tags:
    - DISA-STIG-OL07-00-010190
    - NIST-800-53-CM-6(a)
    - NIST-800-53-IA-5(1)(a)
    - NIST-800-53-IA-5(4)
    - NIST-800-53-IA-5(c)
    - accounts_password_pam_maxclassrepeat
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Set Password Maximum Consecutive Repeating Characters - Find pwquality.conf.d
      files
    ansible.builtin.find:
      paths: /etc/security/pwquality.conf.d/
      patterns: '*.conf'
    register: pwquality_conf_d_files
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - '"libpwquality" in ansible_facts.packages'
    tags:
    - DISA-STIG-OL07-00-010180
    - NIST-800-53-CM-6(a)
    - NIST-800-53-IA-5(4)
    - NIST-800-53-IA-5(c)
    - accounts_password_pam_maxrepeat
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Set Password Maximum Consecutive Repeating Characters - Ensure maxrepeat
      is not set in pwquality.conf.d
    ansible.builtin.lineinfile:
      path: '{{ item.path }}'
      regexp: ^\s*\bmaxrepeat\b.*
      state: absent
    with_items: '{{ pwquality_conf_d_files.files }}'
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - '"libpwquality" in ansible_facts.packages'
    tags:
    - DISA-STIG-OL07-00-010180
    - NIST-800-53-CM-6(a)
    - NIST-800-53-IA-5(4)
    - NIST-800-53-IA-5(c)
    - accounts_password_pam_maxrepeat
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Set Password Maximum Consecutive Repeating Characters - Check if /etc/pam.d/system-auth
      file is present
    ansible.builtin.stat:
      path: /etc/pam.d/system-auth
    register: result_pam_auth_file_present
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - '"libpwquality" in ansible_facts.packages'
    tags:
    - DISA-STIG-OL07-00-010180
    - NIST-800-53-CM-6(a)
    - NIST-800-53-IA-5(4)
    - NIST-800-53-IA-5(c)
    - accounts_password_pam_maxrepeat
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Set Password Maximum Consecutive Repeating Characters - Check the proper
      remediation for the system
    block:

    - name: Set Password Maximum Consecutive Repeating Characters - Define the PAM
        file to be edited as a local fact
      ansible.builtin.set_fact:
        pam_file_path: /etc/pam.d/system-auth

    - name: Set Password Maximum Consecutive Repeating Characters - Check if system
        relies on authselect tool
      ansible.builtin.stat:
        path: /usr/bin/authselect
      register: result_authselect_present

    - name: Set Password Maximum Consecutive Repeating Characters - Ensure authselect
        custom profile is used if authselect is present
      block:

      - name: Set Password Maximum Consecutive Repeating Characters - Check integrity
          of authselect current profile
        ansible.builtin.command:
          cmd: authselect check
        register: result_authselect_check_cmd
        changed_when: false
        check_mode: false
        failed_when: false

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

      - name: Set Password Maximum Consecutive Repeating Characters - Get authselect
          current profile
        ansible.builtin.shell:
          cmd: authselect current -r | awk '{ print $1 }'
        register: result_authselect_profile
        changed_when: false
        when:
        - result_authselect_check_cmd is success

      - name: Set Password Maximum Consecutive Repeating Characters - Define the current
          authselect profile as a local fact
        ansible.builtin.set_fact:
          authselect_current_profile: '{{ result_authselect_profile.stdout }}'
          authselect_custom_profile: '{{ result_authselect_profile.stdout }}'
        when:
        - result_authselect_profile is not skipped
        - result_authselect_profile.stdout is match("custom/")

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

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

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

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

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

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

      - name: Set Password Maximum Consecutive Repeating Characters - Ensure the authselect
          custom profile is selected
        ansible.builtin.command:
          cmd: authselect select {{ authselect_custom_profile }}
        register: result_pam_authselect_select_profile
        when:
        - result_authselect_check_cmd is success
        - result_authselect_profile is not skipped
        - authselect_current_profile is not match("custom/")
        - authselect_custom_profile is not match(authselect_current_profile)

      - name: Set Password Maximum Consecutive Repeating Characters - Restore the
          authselect features in the custom profile
        ansible.builtin.command:
          cmd: authselect enable-feature {{ item }}
        loop: '{{ result_authselect_features.stdout_lines }}'
        register: result_pam_authselect_restore_features
        when:
        - result_authselect_profile is not skipped
        - result_authselect_features is not skipped
        - result_pam_authselect_select_profile is not skipped

      - name: Set Password Maximum Consecutive Repeating Characters - Ensure authselect
          changes are applied
        ansible.builtin.command:
          cmd: authselect apply-changes -b --backup=after-hardening-custom-profile
        when:
        - result_authselect_check_cmd is success
        - result_authselect_profile is not skipped
        - result_pam_authselect_restore_features is not skipped

      - name: Set Password Maximum Consecutive Repeating Characters - Change the PAM
          file to be edited according to the custom authselect profile
        ansible.builtin.set_fact:
          pam_file_path: /etc/authselect/{{ authselect_custom_profile }}/{{ pam_file_path
            | basename }}
        when:
        - authselect_custom_profile is defined
      when:
      - result_authselect_present.stat.exists

    - name: Set Password Maximum Consecutive Repeating Characters - Define a fact
        for control already filtered in case filters are used
      ansible.builtin.set_fact:
        pam_module_control: ''

    - name: Set Password Maximum Consecutive Repeating Characters - Check if {{ pam_file_path
        }} file is present
      ansible.builtin.stat:
        path: '{{ pam_file_path }}'
      register: result_pam_file_present

    - name: Set Password Maximum Consecutive Repeating Characters - Ensure the "maxrepeat"
        option from "pam_pwquality.so" is not present in {{ pam_file_path }}
      ansible.builtin.replace:
        dest: '{{ pam_file_path }}'
        regexp: (.*password.*pam_pwquality.so.*)\bmaxrepeat\b=?[0-9a-zA-Z]*(.*)
        replace: \1\2
      register: result_pam_option_removal
      when:
      - result_pam_file_present.stat.exists

    - name: Set Password Maximum Consecutive Repeating Characters - Ensure authselect
        changes are applied
      ansible.builtin.command:
        cmd: authselect apply-changes -b
      when:
      - result_authselect_present.stat.exists
      - result_pam_option_removal is changed
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - '"libpwquality" in ansible_facts.packages'
    - result_pam_auth_file_present.stat.exists
    tags:
    - DISA-STIG-OL07-00-010180
    - NIST-800-53-CM-6(a)
    - NIST-800-53-IA-5(4)
    - NIST-800-53-IA-5(c)
    - accounts_password_pam_maxrepeat
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Set Password Maximum Consecutive Repeating Characters - Check if /etc/pam.d/password-auth
      file is present
    ansible.builtin.stat:
      path: /etc/pam.d/password-auth
    register: result_pam_password_auth_file_present
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - '"libpwquality" in ansible_facts.packages'
    tags:
    - DISA-STIG-OL07-00-010180
    - NIST-800-53-CM-6(a)
    - NIST-800-53-IA-5(4)
    - NIST-800-53-IA-5(c)
    - accounts_password_pam_maxrepeat
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Set Password Maximum Consecutive Repeating Characters - Check the proper
      remediation for the system
    block:

    - name: Set Password Maximum Consecutive Repeating Characters - Define the PAM
        file to be edited as a local fact
      ansible.builtin.set_fact:
        pam_file_path: /etc/pam.d/password-auth

    - name: Set Password Maximum Consecutive Repeating Characters - Check if system
        relies on authselect tool
      ansible.builtin.stat:
        path: /usr/bin/authselect
      register: result_authselect_present

    - name: Set Password Maximum Consecutive Repeating Characters - Ensure authselect
        custom profile is used if authselect is present
      block:

      - name: Set Password Maximum Consecutive Repeating Characters - Check integrity
          of authselect current profile
        ansible.builtin.command:
          cmd: authselect check
        register: result_authselect_check_cmd
        changed_when: false
        check_mode: false
        failed_when: false

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

      - name: Set Password Maximum Consecutive Repeating Characters - Get authselect
          current profile
        ansible.builtin.shell:
          cmd: authselect current -r | awk '{ print $1 }'
        register: result_authselect_profile
        changed_when: false
        when:
        - result_authselect_check_cmd is success

      - name: Set Password Maximum Consecutive Repeating Characters - Define the current
          authselect profile as a local fact
        ansible.builtin.set_fact:
          authselect_current_profile: '{{ result_authselect_profile.stdout }}'
          authselect_custom_profile: '{{ result_authselect_profile.stdout }}'
        when:
        - result_authselect_profile is not skipped
        - result_authselect_profile.stdout is match("custom/")

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

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

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

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

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

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

      - name: Set Password Maximum Consecutive Repeating Characters - Ensure the authselect
          custom profile is selected
        ansible.builtin.command:
          cmd: authselect select {{ authselect_custom_profile }}
        register: result_pam_authselect_select_profile
        when:
        - result_authselect_check_cmd is success
        - result_authselect_profile is not skipped
        - authselect_current_profile is not match("custom/")
        - authselect_custom_profile is not match(authselect_current_profile)

      - name: Set Password Maximum Consecutive Repeating Characters - Restore the
          authselect features in the custom profile
        ansible.builtin.command:
          cmd: authselect enable-feature {{ item }}
        loop: '{{ result_authselect_features.stdout_lines }}'
        register: result_pam_authselect_restore_features
        when:
        - result_authselect_profile is not skipped
        - result_authselect_features is not skipped
        - result_pam_authselect_select_profile is not skipped

      - name: Set Password Maximum Consecutive Repeating Characters - Ensure authselect
          changes are applied
        ansible.builtin.command:
          cmd: authselect apply-changes -b --backup=after-hardening-custom-profile
        when:
        - result_authselect_check_cmd is success
        - result_authselect_profile is not skipped
        - result_pam_authselect_restore_features is not skipped

      - name: Set Password Maximum Consecutive Repeating Characters - Change the PAM
          file to be edited according to the custom authselect profile
        ansible.builtin.set_fact:
          pam_file_path: /etc/authselect/{{ authselect_custom_profile }}/{{ pam_file_path
            | basename }}
        when:
        - authselect_custom_profile is defined
      when:
      - result_authselect_present.stat.exists

    - name: Set Password Maximum Consecutive Repeating Characters - Define a fact
        for control already filtered in case filters are used
      ansible.builtin.set_fact:
        pam_module_control: ''

    - name: Set Password Maximum Consecutive Repeating Characters - Check if {{ pam_file_path
        }} file is present
      ansible.builtin.stat:
        path: '{{ pam_file_path }}'
      register: result_pam_file_present

    - name: Set Password Maximum Consecutive Repeating Characters - Ensure the "maxrepeat"
        option from "pam_pwquality.so" is not present in {{ pam_file_path }}
      ansible.builtin.replace:
        dest: '{{ pam_file_path }}'
        regexp: (.*password.*pam_pwquality.so.*)\bmaxrepeat\b=?[0-9a-zA-Z]*(.*)
        replace: \1\2
      register: result_pam_option_removal
      when:
      - result_pam_file_present.stat.exists

    - name: Set Password Maximum Consecutive Repeating Characters - Ensure authselect
        changes are applied
      ansible.builtin.command:
        cmd: authselect apply-changes -b
      when:
      - result_authselect_present.stat.exists
      - result_pam_option_removal is changed
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - '"libpwquality" in ansible_facts.packages'
    - result_pam_password_auth_file_present.stat.exists
    tags:
    - DISA-STIG-OL07-00-010180
    - NIST-800-53-CM-6(a)
    - NIST-800-53-IA-5(4)
    - NIST-800-53-IA-5(c)
    - accounts_password_pam_maxrepeat
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Set Password Maximum Consecutive Repeating Characters - Ensure PAM variable
      maxrepeat is set accordingly
    ansible.builtin.lineinfile:
      create: true
      dest: /etc/security/pwquality.conf
      regexp: ^#?\s*maxrepeat
      line: maxrepeat = {{ var_password_pam_maxrepeat }}
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - '"libpwquality" in ansible_facts.packages'
    tags:
    - DISA-STIG-OL07-00-010180
    - NIST-800-53-CM-6(a)
    - NIST-800-53-IA-5(4)
    - NIST-800-53-IA-5(c)
    - accounts_password_pam_maxrepeat
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Ensure PAM Enforces Password Requirements - Minimum 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-OL07-00-010280
    - 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-OL07-00-010280
    - 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-OL07-00-010280
    - 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-OL07-00-010280
    - 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-OL07-00-010280
    - 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-OL07-00-010280
    - 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-OL07-00-010280
    - NIST-800-53-CM-6(a)
    - NIST-800-53-IA-5(1)(a)
    - NIST-800-53-IA-5(4)
    - NIST-800-53-IA-5(c)
    - PCI-DSS-Req-8.2.3
    - PCI-DSSv4-8.3
    - PCI-DSSv4-8.3.6
    - accounts_password_pam_minlen
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Ensure PAM Enforces Password Requirements - Minimum Special Characters -
      Find pwquality.conf.d files
    ansible.builtin.find:
      paths: /etc/security/pwquality.conf.d/
      patterns: '*.conf'
    register: pwquality_conf_d_files
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - '"libpwquality" in ansible_facts.packages'
    tags:
    - DISA-STIG-OL07-00-010150
    - NIST-800-53-CM-6(a)
    - NIST-800-53-IA-5(1)(a)
    - NIST-800-53-IA-5(4)
    - NIST-800-53-IA-5(c)
    - accounts_password_pam_ocredit
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Ensure PAM Enforces Password Requirements - Minimum Special Characters -
      Ensure ocredit is not set in pwquality.conf.d
    ansible.builtin.lineinfile:
      path: '{{ item.path }}'
      regexp: ^\s*\bocredit\b.*
      state: absent
    with_items: '{{ pwquality_conf_d_files.files }}'
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - '"libpwquality" in ansible_facts.packages'
    tags:
    - DISA-STIG-OL07-00-010150
    - NIST-800-53-CM-6(a)
    - NIST-800-53-IA-5(1)(a)
    - NIST-800-53-IA-5(4)
    - NIST-800-53-IA-5(c)
    - accounts_password_pam_ocredit
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

  - name: Ensure PAM Enforces Password Requirements - Minimum Special Characters -
      Ensure PAM variable ocredit is set accordingly
    ansible.builtin.lineinfile:
      create: true
      dest: /etc/security/pwquality.conf
      regexp: ^#?\s*ocredit
      line: ocredit = {{ var_password_pam_ocredit }}
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - '"libpwquality" in ansible_facts.packages'
    tags:
    - DISA-STIG-OL07-00-010150
    - NIST-800-53-CM-6(a)
    - NIST-800-53-IA-5(1)(a)
    - NIST-800-53-IA-5(4)
    - NIST-800-53-IA-5(c)
    - accounts_password_pam_ocredit
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

  - name: Disable Ctrl-Alt-Del Burst Action
    ansible.builtin.lineinfile:
      dest: /etc/systemd/system.conf
      state: present
      regexp: ^CtrlAltDelBurstAction
      line: CtrlAltDelBurstAction=none
      create: true
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - '"systemd" in ansible_facts.packages'
    tags:
    - NIST-800-171-3.4.5
    - NIST-800-53-AC-6(1)
    - NIST-800-53-CM-6(a)
    - NIST-800-53-CM-6(a)
    - disable_ctrlaltdel_burstaction
    - disable_strategy
    - high_severity
    - low_complexity
    - low_disruption
    - no_reboot_needed

  - name: Disable Ctrl-Alt-Del Reboot Activation
    ansible.builtin.systemd:
      name: ctrl-alt-del.target
      force: true
      masked: true
      state: stopped
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL07-00-020230
    - NIST-800-171-3.4.5
    - NIST-800-53-AC-6(1)
    - NIST-800-53-CM-6(a)
    - disable_ctrlaltdel_reboot
    - disable_strategy
    - high_severity
    - low_complexity
    - low_disruption
    - no_reboot_needed

  - name: Verify that Interactive Boot is Disabled - Verify GRUB_DISABLE_RECOVERY=true
    ansible.builtin.lineinfile:
      path: /etc/default/grub
      regexp: ^GRUB_DISABLE_RECOVERY=.*
      line: GRUB_DISABLE_RECOVERY=true
      state: present
    register: grub_disable_recovery_changed
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - '"grub2-common" in ansible_facts.packages'
    tags:
    - NIST-800-171-3.1.2
    - NIST-800-171-3.4.5
    - NIST-800-53-CM-6(a)
    - NIST-800-53-SC-2(1)
    - grub2_disable_interactive_boot
    - low_complexity
    - low_disruption
    - medium_severity
    - reboot_required
    - restrict_strategy

  - name: Verify that Interactive Boot is Disabled - Verify that Interactive Boot
      is Disabled in /etc/default/grub
    ansible.builtin.replace:
      dest: /etc/default/grub
      regexp: systemd.confirm_spawn(=(1|yes|true|on)|\b)
      replace: systemd.confirm_spawn=no
    register: grub_confirm_spawn_changed
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - '"grub2-common" in ansible_facts.packages'
    tags:
    - NIST-800-171-3.1.2
    - NIST-800-171-3.4.5
    - NIST-800-53-CM-6(a)
    - NIST-800-53-SC-2(1)
    - grub2_disable_interactive_boot
    - low_complexity
    - low_disruption
    - medium_severity
    - reboot_required
    - restrict_strategy

  - name: Verify that Interactive Boot is Disabled - Verify that Interactive Boot
      is Disabled (runtime)
    ansible.builtin.command: /sbin/grubby --update-kernel=ALL --remove-args="systemd.confirm_spawn"
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - '"grub2-common" in ansible_facts.packages'
    - grub_confirm_spawn_changed is changed
    tags:
    - NIST-800-171-3.1.2
    - NIST-800-171-3.4.5
    - NIST-800-53-CM-6(a)
    - NIST-800-53-SC-2(1)
    - grub2_disable_interactive_boot
    - low_complexity
    - low_disruption
    - medium_severity
    - reboot_required
    - restrict_strategy

  - name: Verify that Interactive Boot is Disabled - Regen grub.cfg handle updated
      GRUB_DISABLE_RECOVERY and confirm_spawn
    ansible.builtin.command: grub2-mkconfig -o  /boot/grub2/grub.cfg
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - '"grub2-common" in ansible_facts.packages'
    - grub_disable_recovery_changed is changed or grub_confirm_spawn_changed is changed
    tags:
    - NIST-800-171-3.1.2
    - NIST-800-171-3.4.5
    - NIST-800-53-CM-6(a)
    - NIST-800-53-SC-2(1)
    - grub2_disable_interactive_boot
    - low_complexity
    - low_disruption
    - medium_severity
    - reboot_required
    - restrict_strategy

  - name: Require Authentication for Single User Mode - find files which already override
      Execstart of rescue.service
    ansible.builtin.find:
      paths: /etc/systemd/system/rescue.service.d
      patterns: '*.conf'
      contains: ^\s*ExecStart=.*$
    register: rescue_service_overrides_found
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL07-00-010481
    - NIST-800-171-3.1.1
    - NIST-800-171-3.4.5
    - NIST-800-53-AC-3
    - NIST-800-53-CM-6(a)
    - NIST-800-53-IA-2
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - require_singleuser_auth
    - restrict_strategy

  - name: Require Authentication for Single User Mode - set files containing ExecStart
      overrides as target
    ansible.builtin.set_fact:
      rescue_service_remediation_target_file: '{{ rescue_service_overrides_found.files
        | map(attribute=''path'') | list }}'
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - rescue_service_overrides_found.matched is defined and rescue_service_overrides_found.matched
      > 0
    tags:
    - DISA-STIG-OL07-00-010481
    - NIST-800-171-3.1.1
    - NIST-800-171-3.4.5
    - NIST-800-53-AC-3
    - NIST-800-53-CM-6(a)
    - NIST-800-53-IA-2
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - require_singleuser_auth
    - restrict_strategy

  - name: Require Authentication for Single User Mode - set default target for rescue.service
      override
    ansible.builtin.set_fact:
      rescue_service_remediation_target_file:
      - /etc/systemd/system/rescue.service.d/10-oscap.conf
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - rescue_service_overrides_found.matched is defined and rescue_service_overrides_found.matched
      == 0
    tags:
    - DISA-STIG-OL07-00-010481
    - NIST-800-171-3.1.1
    - NIST-800-171-3.4.5
    - NIST-800-53-AC-3
    - NIST-800-53-CM-6(a)
    - NIST-800-53-IA-2
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - require_singleuser_auth
    - restrict_strategy

  - name: Require Authentication for Single User Mode - Require emergency user mode
      password
    community.general.ini_file:
      path: '{{ item }}'
      section: Service
      option: ExecStart
      values:
      - ''
      - -/usr/lib/systemd/systemd-sulogin-shell rescue
    loop: '{{ rescue_service_remediation_target_file }}'
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL07-00-010481
    - NIST-800-171-3.1.1
    - NIST-800-171-3.4.5
    - NIST-800-53-AC-3
    - NIST-800-53-CM-6(a)
    - NIST-800-53-IA-2
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - require_singleuser_auth
    - restrict_strategy

  - name: Set Password Minimum Length in login.defs
    ansible.builtin.lineinfile:
      dest: /etc/login.defs
      regexp: ^PASS_MIN_LEN *[0-9]*
      state: present
      line: PASS_MIN_LEN        {{ var_accounts_password_minlen_login_defs }}
      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.1
    - NIST-800-171-3.5.7
    - NIST-800-53-CM-6(a)
    - NIST-800-53-IA-5(1)(a)
    - NIST-800-53-IA-5(f)
    - accounts_password_minlen_login_defs
    - 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-OL07-00-010290
    - 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-OL07-00-010290
    - 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-OL07-00-010290
    - 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: 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: Find /etc/security/limits.d files containing maxlogins configuration
    ansible.builtin.find:
      paths: /etc/security/limits.d
      contains: ^[\s]*\*[\s]+(?:(?:hard)|(?:-))[\s]+maxlogins
      patterns: '*.conf'
    register: maxlogins
    when: ( "pam" in ansible_facts.packages and ("kernel" in ansible_facts.packages
      or "kernel-uek" in ansible_facts.packages) )
    tags:
    - CJIS-5.5.2.2
    - DISA-STIG-OL07-00-040000
    - NIST-800-53-AC-10
    - NIST-800-53-CM-6(a)
    - accounts_max_concurrent_login_sessions
    - low_complexity
    - low_disruption
    - low_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Limit the Number of Concurrent Login Sessions Allowed Per User in files
      from limits.d
    ansible.builtin.replace:
      dest: '{{ item.path }}'
      regexp: ^#?\*.*maxlogins.*
      replace: '*          hard    maxlogins     {{ var_accounts_max_concurrent_login_sessions
        }}'
    with_items:
    - '{{ maxlogins.files }}'
    when: ( "pam" in ansible_facts.packages and ("kernel" in ansible_facts.packages
      or "kernel-uek" in ansible_facts.packages) )
    tags:
    - CJIS-5.5.2.2
    - DISA-STIG-OL07-00-040000
    - NIST-800-53-AC-10
    - NIST-800-53-CM-6(a)
    - accounts_max_concurrent_login_sessions
    - low_complexity
    - low_disruption
    - low_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Limit the Number of Concurrent Login Sessions Allowed Per User
    ansible.builtin.lineinfile:
      state: present
      dest: /etc/security/limits.conf
      insertbefore: ^# End of file
      regexp: ^#?\*.*maxlogins
      line: '*          hard    maxlogins     {{ var_accounts_max_concurrent_login_sessions
        }}'
      create: true
    when:
    - ( "pam" in ansible_facts.packages and ("kernel" in ansible_facts.packages or
      "kernel-uek" in ansible_facts.packages) )
    - maxlogins.matched == 0
    tags:
    - CJIS-5.5.2.2
    - DISA-STIG-OL07-00-040000
    - NIST-800-53-AC-10
    - NIST-800-53-CM-6(a)
    - accounts_max_concurrent_login_sessions
    - low_complexity
    - low_disruption
    - low_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Check if umask in /etc/bashrc is already set
    ansible.builtin.lineinfile:
      path: /etc/bashrc
      regexp: ^[^#]*\bumask\s+\d+$
      state: absent
    check_mode: true
    changed_when: false
    register: umask_replace
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - '"bash" in ansible_facts.packages'
    tags:
    - NIST-800-53-AC-6(1)
    - NIST-800-53-CM-6(a)
    - accounts_umask_etc_bashrc
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Replace user umask in /etc/bashrc
    ansible.builtin.replace:
      path: /etc/bashrc
      regexp: ^([^#]*\b)umask\s+\d+$
      replace: \g<1>umask {{ var_accounts_user_umask }}
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - '"bash" in ansible_facts.packages'
    - umask_replace.found > 0
    tags:
    - NIST-800-53-AC-6(1)
    - NIST-800-53-CM-6(a)
    - accounts_umask_etc_bashrc
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Ensure the Default umask is Appended Correctly
    ansible.builtin.lineinfile:
      create: true
      path: /etc/bashrc
      line: umask {{ var_accounts_user_umask }}
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - '"bash" in ansible_facts.packages'
    - umask_replace.found == 0
    tags:
    - NIST-800-53-AC-6(1)
    - NIST-800-53-CM-6(a)
    - accounts_umask_etc_bashrc
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Check if umask in /etc/csh.cshrc is already set
    ansible.builtin.lineinfile:
      path: /etc/csh.cshrc
      regexp: ^(\s*)umask\s+.*
      state: absent
    check_mode: true
    changed_when: false
    register: umask_replace
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - NIST-800-53-AC-6(1)
    - NIST-800-53-CM-6(a)
    - accounts_umask_etc_csh_cshrc
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Replace user umask in /etc/csh.cshrc
    ansible.builtin.replace:
      path: /etc/csh.cshrc
      regexp: ^(\s*)umask(\s+).*
      replace: \g<1>umask\g<2>{{ var_accounts_user_umask }}
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - umask_replace.found > 0
    tags:
    - NIST-800-53-AC-6(1)
    - NIST-800-53-CM-6(a)
    - accounts_umask_etc_csh_cshrc
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Ensure the Default umask is Appended Correctly
    ansible.builtin.lineinfile:
      create: true
      path: /etc/csh.cshrc
      line: umask {{ var_accounts_user_umask }}
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - umask_replace.found == 0
    tags:
    - NIST-800-53-AC-6(1)
    - NIST-800-53-CM-6(a)
    - accounts_umask_etc_csh_cshrc
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Ensure the Default Umask is Set Correctly in /etc/profile - Locate Profile
      Configuration Files Where umask Is Defined
    ansible.builtin.find:
      paths:
      - /etc/profile.d
      patterns:
      - sh.local
      - '*.sh'
      contains: ^[\s]*umask\s+\d+
    register: result_profile_d_files
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - NIST-800-53-AC-6(1)
    - NIST-800-53-CM-6(a)
    - accounts_umask_etc_profile
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Ensure the Default Umask is Set Correctly in /etc/profile - Replace Existing
      umask Value in Files From /etc/profile.d
    ansible.builtin.replace:
      path: '{{ item.path }}'
      regexp: ^(\s*)umask\s+\d+
      replace: \1umask {{ var_accounts_user_umask }}
    loop: '{{ result_profile_d_files.files }}'
    register: result_umask_replaced_profile_d
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - result_profile_d_files.matched
    tags:
    - NIST-800-53-AC-6(1)
    - NIST-800-53-CM-6(a)
    - accounts_umask_etc_profile
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Ensure the Default Umask is Set Correctly in /etc/profile - Ensure umask
      Is Set in /etc/profile if Not Already Set Elsewhere
    ansible.builtin.lineinfile:
      create: true
      mode: 420
      path: /etc/profile
      line: umask {{ var_accounts_user_umask }}
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - not result_profile_d_files.matched
    tags:
    - NIST-800-53-AC-6(1)
    - NIST-800-53-CM-6(a)
    - accounts_umask_etc_profile
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Ensure the Default Umask is Set Correctly in /etc/profile - Ensure umask
      Value For All Existing umask Definition in /etc/profile
    ansible.builtin.replace:
      path: /etc/profile
      regexp: ^(\s*)umask\s+\d+
      replace: \1umask {{ var_accounts_user_umask }}
    register: result_umask_replaced_profile
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - NIST-800-53-AC-6(1)
    - NIST-800-53-CM-6(a)
    - accounts_umask_etc_profile
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Check vsyscall argument exists
    ansible.builtin.command: grep '^\s*GRUB_CMDLINE_LINUX=.*vsyscall=' /etc/default/grub
    check_mode: false
    failed_when: false
    changed_when: false
    register: argcheck
    when:
    - ( "grub2-common" in ansible_facts.packages and ("kernel" in ansible_facts.packages
      or "kernel-uek" in ansible_facts.packages) )
    - ansible_architecture == "x86_64"
    tags:
    - NIST-800-53-CM-7(a)
    - grub2_vsyscall_argument
    - low_disruption
    - medium_complexity
    - medium_severity
    - reboot_required
    - restrict_strategy

  - name: Check vsyscall argument exists
    ansible.builtin.command: grep '^\s*GRUB_CMDLINE_LINUX=' /etc/default/grub
    check_mode: false
    failed_when: false
    changed_when: false
    register: linecheck
    when:
    - ( "grub2-common" in ansible_facts.packages and ("kernel" in ansible_facts.packages
      or "kernel-uek" in ansible_facts.packages) )
    - ansible_architecture == "x86_64"
    tags:
    - NIST-800-53-CM-7(a)
    - grub2_vsyscall_argument
    - low_disruption
    - medium_complexity
    - medium_severity
    - reboot_required
    - restrict_strategy

  - name: Add vsyscall argument
    ansible.builtin.lineinfile:
      line: GRUB_CMDLINE_LINUX="vsyscall=none "
      state: present
      dest: /etc/default/grub
      create: true
      mode: '0644'
    when:
    - ( "grub2-common" in ansible_facts.packages and ("kernel" in ansible_facts.packages
      or "kernel-uek" in ansible_facts.packages) )
    - ansible_architecture == "x86_64"
    - argcheck is not skipped and linecheck is not skipped and argcheck.rc != 0 and
      linecheck.rc != 0
    tags:
    - NIST-800-53-CM-7(a)
    - grub2_vsyscall_argument
    - low_disruption
    - medium_complexity
    - medium_severity
    - reboot_required
    - restrict_strategy

  - name: Replace existing vsyscall argument
    ansible.builtin.replace:
      path: /etc/default/grub
      regexp: vsyscall=[a-zA-Z0-9,]+
      replace: vsyscall=none
    when:
    - ( "grub2-common" in ansible_facts.packages and ("kernel" in ansible_facts.packages
      or "kernel-uek" in ansible_facts.packages) )
    - ansible_architecture == "x86_64"
    - argcheck is not skipped and linecheck is not skipped and argcheck.rc == 0 and
      linecheck.rc == 0
    tags:
    - NIST-800-53-CM-7(a)
    - grub2_vsyscall_argument
    - low_disruption
    - medium_complexity
    - medium_severity
    - reboot_required
    - restrict_strategy

  - name: Add vsyscall argument
    ansible.builtin.replace:
      path: /etc/default/grub
      regexp: (^\s*GRUB_CMDLINE_LINUX=.*)"
      replace: \1 vsyscall=none"
    when:
    - ( "grub2-common" in ansible_facts.packages and ("kernel" in ansible_facts.packages
      or "kernel-uek" in ansible_facts.packages) )
    - ansible_architecture == "x86_64"
    - argcheck is not skipped and linecheck is not skipped and argcheck.rc != 0 and
      linecheck.rc == 0
    tags:
    - NIST-800-53-CM-7(a)
    - grub2_vsyscall_argument
    - low_disruption
    - medium_complexity
    - medium_severity
    - reboot_required
    - restrict_strategy

  - name: Check if vsyscall argument is already present in /etc/default/grub
    ansible.builtin.slurp:
      src: /etc/default/grub
    register: etc_default_grub
    when:
    - ( "grub2-common" in ansible_facts.packages and ("kernel" in ansible_facts.packages
      or "kernel-uek" in ansible_facts.packages) )
    - ansible_architecture == "x86_64"
    tags:
    - NIST-800-53-CM-7(a)
    - grub2_vsyscall_argument
    - low_disruption
    - medium_complexity
    - medium_severity
    - reboot_required
    - restrict_strategy

  - name: Check if vsyscall argument is already present
    ansible.builtin.command: /sbin/grubby --info=ALL
    register: grubby_info
    check_mode: false
    changed_when: false
    failed_when: false
    when:
    - ( "grub2-common" in ansible_facts.packages and ("kernel" in ansible_facts.packages
      or "kernel-uek" in ansible_facts.packages) )
    - ansible_architecture == "x86_64"
    tags:
    - NIST-800-53-CM-7(a)
    - grub2_vsyscall_argument
    - low_disruption
    - medium_complexity
    - medium_severity
    - reboot_required
    - restrict_strategy

  - name: Update grub defaults and the bootloader menu
    ansible.builtin.command: /sbin/grubby --update-kernel=ALL --args="vsyscall=none"
    when:
    - ( "grub2-common" in ansible_facts.packages and ("kernel" in ansible_facts.packages
      or "kernel-uek" in ansible_facts.packages) )
    - ansible_architecture == "x86_64"
    - (grubby_info.stdout is not search('vsyscall=none')) or ((etc_default_grub['content']
      | b64decode) is not search('vsyscall=none'))
    tags:
    - NIST-800-53-CM-7(a)
    - grub2_vsyscall_argument
    - low_disruption
    - medium_complexity
    - medium_severity
    - reboot_required
    - restrict_strategy

  - name: Configure Accepting Router Advertisements on All IPv6 Interfaces - Set fact
      for sysctl paths
    ansible.builtin.set_fact:
      sysctl_paths:
      - /etc/sysctl.d/
      - /run/sysctl.d/
      - /usr/local/lib/sysctl.d/
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - NIST-800-171-3.1.20
    - NIST-800-53-CM-6(a)
    - NIST-800-53-CM-7(a)
    - NIST-800-53-CM-7(b)
    - disable_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - reboot_required
    - sysctl_net_ipv6_conf_all_accept_ra

  - name: Configure Accepting Router Advertisements on All IPv6 Interfaces - Find
      all files that contain net.ipv6.conf.all.accept_ra
    ansible.builtin.shell:
      cmd: find -L {{ sysctl_paths | join(" ") }} -type f -name '*.conf' | xargs grep
        -HP '^\s*net.ipv6.conf.all.accept_ra\s*=\s*.*$'
    register: find_all_values
    check_mode: false
    changed_when: false
    failed_when: false
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - NIST-800-171-3.1.20
    - NIST-800-53-CM-6(a)
    - NIST-800-53-CM-7(a)
    - NIST-800-53-CM-7(b)
    - disable_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - reboot_required
    - sysctl_net_ipv6_conf_all_accept_ra

  - name: Configure Accepting Router Advertisements on All IPv6 Interfaces - Find
      all files that set net.ipv6.conf.all.accept_ra to correct value
    ansible.builtin.shell:
      cmd: find -L {{ sysctl_paths | join(" ") }} -type f -name '*.conf' | xargs grep
        -HP '^\s*net.ipv6.conf.all.accept_ra\s*=\s*{{ sysctl_net_ipv6_conf_all_accept_ra_value
        }}$'
    register: find_correct_value
    check_mode: false
    changed_when: false
    failed_when: false
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - NIST-800-171-3.1.20
    - NIST-800-53-CM-6(a)
    - NIST-800-53-CM-7(a)
    - NIST-800-53-CM-7(b)
    - disable_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - reboot_required
    - sysctl_net_ipv6_conf_all_accept_ra

  - name: Configure Accepting Router Advertisements on All IPv6 Interfaces - Comment
      out any occurrences of net.ipv6.conf.all.accept_ra from config files
    ansible.builtin.replace:
      path: '{{ item | split(":") | first }}'
      regexp: ^[\s]*net.ipv6.conf.all.accept_ra
      replace: '#net.ipv6.conf.all.accept_ra'
    loop: '{{ find_all_values.stdout_lines }}'
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - find_correct_value.stdout_lines | length == 0 or find_all_values.stdout_lines
      | length > find_correct_value.stdout_lines | length
    tags:
    - NIST-800-171-3.1.20
    - NIST-800-53-CM-6(a)
    - NIST-800-53-CM-7(a)
    - NIST-800-53-CM-7(b)
    - disable_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - reboot_required
    - sysctl_net_ipv6_conf_all_accept_ra

  - name: Configure Accepting Router Advertisements on All IPv6 Interfaces - Ensure
      sysctl net.ipv6.conf.all.accept_ra is set
    ansible.posix.sysctl:
      name: net.ipv6.conf.all.accept_ra
      value: '{{ sysctl_net_ipv6_conf_all_accept_ra_value }}'
      sysctl_file: /etc/sysctl.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)
    - disable_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - reboot_required
    - sysctl_net_ipv6_conf_all_accept_ra

  - name: Disable Accepting ICMP Redirects for All IPv6 Interfaces - Set fact for
      sysctl paths
    ansible.builtin.set_fact:
      sysctl_paths:
      - /etc/sysctl.d/
      - /run/sysctl.d/
      - /usr/local/lib/sysctl.d/
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - NIST-800-171-3.1.20
    - NIST-800-53-CM-6(a)
    - NIST-800-53-CM-6(b)
    - NIST-800-53-CM-6.1(iv)
    - NIST-800-53-CM-7(a)
    - NIST-800-53-CM-7(b)
    - disable_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - reboot_required
    - sysctl_net_ipv6_conf_all_accept_redirects

  - name: Disable Accepting ICMP Redirects for All IPv6 Interfaces - Find all files
      that contain net.ipv6.conf.all.accept_redirects
    ansible.builtin.shell:
      cmd: find -L {{ sysctl_paths | join(" ") }} -type f -name '*.conf' | xargs grep
        -HP '^\s*net.ipv6.conf.all.accept_redirects\s*=\s*.*$'
    register: find_all_values
    check_mode: false
    changed_when: false
    failed_when: false
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - NIST-800-171-3.1.20
    - NIST-800-53-CM-6(a)
    - NIST-800-53-CM-6(b)
    - NIST-800-53-CM-6.1(iv)
    - NIST-800-53-CM-7(a)
    - NIST-800-53-CM-7(b)
    - disable_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - reboot_required
    - sysctl_net_ipv6_conf_all_accept_redirects

  - name: Disable Accepting ICMP Redirects for All IPv6 Interfaces - Find all files
      that set net.ipv6.conf.all.accept_redirects to correct value
    ansible.builtin.shell:
      cmd: find -L {{ sysctl_paths | join(" ") }} -type f -name '*.conf' | xargs grep
        -HP '^\s*net.ipv6.conf.all.accept_redirects\s*=\s*{{ sysctl_net_ipv6_conf_all_accept_redirects_value
        }}$'
    register: find_correct_value
    check_mode: false
    changed_when: false
    failed_when: false
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - NIST-800-171-3.1.20
    - NIST-800-53-CM-6(a)
    - NIST-800-53-CM-6(b)
    - NIST-800-53-CM-6.1(iv)
    - NIST-800-53-CM-7(a)
    - NIST-800-53-CM-7(b)
    - disable_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - reboot_required
    - sysctl_net_ipv6_conf_all_accept_redirects

  - name: Disable Accepting ICMP Redirects for All IPv6 Interfaces - Comment out any
      occurrences of net.ipv6.conf.all.accept_redirects from config files
    ansible.builtin.replace:
      path: '{{ item | split(":") | first }}'
      regexp: ^[\s]*net.ipv6.conf.all.accept_redirects
      replace: '#net.ipv6.conf.all.accept_redirects'
    loop: '{{ find_all_values.stdout_lines }}'
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - find_correct_value.stdout_lines | length == 0 or find_all_values.stdout_lines
      | length > find_correct_value.stdout_lines | length
    tags:
    - NIST-800-171-3.1.20
    - NIST-800-53-CM-6(a)
    - NIST-800-53-CM-6(b)
    - NIST-800-53-CM-6.1(iv)
    - NIST-800-53-CM-7(a)
    - NIST-800-53-CM-7(b)
    - disable_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - reboot_required
    - sysctl_net_ipv6_conf_all_accept_redirects

  - name: Disable Accepting ICMP Redirects for All IPv6 Interfaces - Ensure sysctl
      net.ipv6.conf.all.accept_redirects is set
    ansible.posix.sysctl:
      name: net.ipv6.conf.all.accept_redirects
      value: '{{ sysctl_net_ipv6_conf_all_accept_redirects_value }}'
      sysctl_file: /etc/sysctl.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-6(b)
    - NIST-800-53-CM-6.1(iv)
    - NIST-800-53-CM-7(a)
    - NIST-800-53-CM-7(b)
    - disable_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - reboot_required
    - sysctl_net_ipv6_conf_all_accept_redirects

  - name: Disable Kernel Parameter for Accepting Source-Routed Packets on all IPv6
      Interfaces - Set fact for sysctl paths
    ansible.builtin.set_fact:
      sysctl_paths:
      - /etc/sysctl.d/
      - /run/sysctl.d/
      - /usr/local/lib/sysctl.d/
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL07-00-040830
    - NIST-800-171-3.1.20
    - NIST-800-53-CM-6(a)
    - NIST-800-53-CM-7(a)
    - NIST-800-53-CM-7(b)
    - disable_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - reboot_required
    - sysctl_net_ipv6_conf_all_accept_source_route

  - name: Disable Kernel Parameter for Accepting Source-Routed Packets on all IPv6
      Interfaces - Find all files that contain net.ipv6.conf.all.accept_source_route
    ansible.builtin.shell:
      cmd: find -L {{ sysctl_paths | join(" ") }} -type f -name '*.conf' | xargs grep
        -HP '^\s*net.ipv6.conf.all.accept_source_route\s*=\s*.*$'
    register: find_all_values
    check_mode: false
    changed_when: false
    failed_when: false
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL07-00-040830
    - NIST-800-171-3.1.20
    - NIST-800-53-CM-6(a)
    - NIST-800-53-CM-7(a)
    - NIST-800-53-CM-7(b)
    - disable_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - reboot_required
    - sysctl_net_ipv6_conf_all_accept_source_route

  - name: Disable Kernel Parameter for Accepting Source-Routed Packets on all IPv6
      Interfaces - Find all files that set net.ipv6.conf.all.accept_source_route to
      correct value
    ansible.builtin.shell:
      cmd: find -L {{ sysctl_paths | join(" ") }} -type f -name '*.conf' | xargs grep
        -HP '^\s*net.ipv6.conf.all.accept_source_route\s*=\s*{{ sysctl_net_ipv6_conf_all_accept_source_route_value
        }}$'
    register: find_correct_value
    check_mode: false
    changed_when: false
    failed_when: false
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL07-00-040830
    - NIST-800-171-3.1.20
    - NIST-800-53-CM-6(a)
    - NIST-800-53-CM-7(a)
    - NIST-800-53-CM-7(b)
    - disable_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - reboot_required
    - sysctl_net_ipv6_conf_all_accept_source_route

  - name: Disable Kernel Parameter for Accepting Source-Routed Packets on all IPv6
      Interfaces - Comment out any occurrences of net.ipv6.conf.all.accept_source_route
      from config files
    ansible.builtin.replace:
      path: '{{ item | split(":") | first }}'
      regexp: ^[\s]*net.ipv6.conf.all.accept_source_route
      replace: '#net.ipv6.conf.all.accept_source_route'
    loop: '{{ find_all_values.stdout_lines }}'
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - find_correct_value.stdout_lines | length == 0 or find_all_values.stdout_lines
      | length > find_correct_value.stdout_lines | length
    tags:
    - DISA-STIG-OL07-00-040830
    - NIST-800-171-3.1.20
    - NIST-800-53-CM-6(a)
    - NIST-800-53-CM-7(a)
    - NIST-800-53-CM-7(b)
    - disable_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - reboot_required
    - sysctl_net_ipv6_conf_all_accept_source_route

  - name: Disable Kernel Parameter for Accepting Source-Routed Packets on all IPv6
      Interfaces - Ensure sysctl net.ipv6.conf.all.accept_source_route is set
    ansible.posix.sysctl:
      name: net.ipv6.conf.all.accept_source_route
      value: '{{ sysctl_net_ipv6_conf_all_accept_source_route_value }}'
      sysctl_file: /etc/sysctl.conf
      state: present
      reload: true
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL07-00-040830
    - NIST-800-171-3.1.20
    - NIST-800-53-CM-6(a)
    - NIST-800-53-CM-7(a)
    - NIST-800-53-CM-7(b)
    - disable_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - reboot_required
    - sysctl_net_ipv6_conf_all_accept_source_route

  - name: Disable Accepting Router Advertisements on all IPv6 Interfaces by Default
      - Set fact for sysctl paths
    ansible.builtin.set_fact:
      sysctl_paths:
      - /etc/sysctl.d/
      - /run/sysctl.d/
      - /usr/local/lib/sysctl.d/
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - NIST-800-171-3.1.20
    - NIST-800-53-CM-6(a)
    - NIST-800-53-CM-7(a)
    - NIST-800-53-CM-7(b)
    - disable_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - reboot_required
    - sysctl_net_ipv6_conf_default_accept_ra

  - name: Disable Accepting Router Advertisements on all IPv6 Interfaces by Default
      - Find all files that contain net.ipv6.conf.default.accept_ra
    ansible.builtin.shell:
      cmd: find -L {{ sysctl_paths | join(" ") }} -type f -name '*.conf' | xargs grep
        -HP '^\s*net.ipv6.conf.default.accept_ra\s*=\s*.*$'
    register: find_all_values
    check_mode: false
    changed_when: false
    failed_when: false
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - NIST-800-171-3.1.20
    - NIST-800-53-CM-6(a)
    - NIST-800-53-CM-7(a)
    - NIST-800-53-CM-7(b)
    - disable_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - reboot_required
    - sysctl_net_ipv6_conf_default_accept_ra

  - name: Disable Accepting Router Advertisements on all IPv6 Interfaces by Default
      - Find all files that set net.ipv6.conf.default.accept_ra to correct value
    ansible.builtin.shell:
      cmd: find -L {{ sysctl_paths | join(" ") }} -type f -name '*.conf' | xargs grep
        -HP '^\s*net.ipv6.conf.default.accept_ra\s*=\s*{{ sysctl_net_ipv6_conf_default_accept_ra_value
        }}$'
    register: find_correct_value
    check_mode: false
    changed_when: false
    failed_when: false
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - NIST-800-171-3.1.20
    - NIST-800-53-CM-6(a)
    - NIST-800-53-CM-7(a)
    - NIST-800-53-CM-7(b)
    - disable_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - reboot_required
    - sysctl_net_ipv6_conf_default_accept_ra

  - name: Disable Accepting Router Advertisements on all IPv6 Interfaces by Default
      - Comment out any occurrences of net.ipv6.conf.default.accept_ra from config
      files
    ansible.builtin.replace:
      path: '{{ item | split(":") | first }}'
      regexp: ^[\s]*net.ipv6.conf.default.accept_ra
      replace: '#net.ipv6.conf.default.accept_ra'
    loop: '{{ find_all_values.stdout_lines }}'
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - find_correct_value.stdout_lines | length == 0 or find_all_values.stdout_lines
      | length > find_correct_value.stdout_lines | length
    tags:
    - NIST-800-171-3.1.20
    - NIST-800-53-CM-6(a)
    - NIST-800-53-CM-7(a)
    - NIST-800-53-CM-7(b)
    - disable_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - reboot_required
    - sysctl_net_ipv6_conf_default_accept_ra

  - name: Disable Accepting Router Advertisements on all IPv6 Interfaces by Default
      - Ensure sysctl net.ipv6.conf.default.accept_ra is set
    ansible.posix.sysctl:
      name: net.ipv6.conf.default.accept_ra
      value: '{{ sysctl_net_ipv6_conf_default_accept_ra_value }}'
      sysctl_file: /etc/sysctl.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)
    - disable_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - reboot_required
    - sysctl_net_ipv6_conf_default_accept_ra

  - name: Disable Kernel Parameter for Accepting ICMP Redirects by Default on IPv6
      Interfaces - Set fact for sysctl paths
    ansible.builtin.set_fact:
      sysctl_paths:
      - /etc/sysctl.d/
      - /run/sysctl.d/
      - /usr/local/lib/sysctl.d/
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - NIST-800-171-3.1.20
    - NIST-800-53-CM-6(a)
    - NIST-800-53-CM-7(a)
    - NIST-800-53-CM-7(b)
    - disable_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - reboot_required
    - sysctl_net_ipv6_conf_default_accept_redirects

  - name: Disable Kernel Parameter for Accepting ICMP Redirects by Default on IPv6
      Interfaces - Find all files that contain net.ipv6.conf.default.accept_redirects
    ansible.builtin.shell:
      cmd: find -L {{ sysctl_paths | join(" ") }} -type f -name '*.conf' | xargs grep
        -HP '^\s*net.ipv6.conf.default.accept_redirects\s*=\s*.*$'
    register: find_all_values
    check_mode: false
    changed_when: false
    failed_when: false
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - NIST-800-171-3.1.20
    - NIST-800-53-CM-6(a)
    - NIST-800-53-CM-7(a)
    - NIST-800-53-CM-7(b)
    - disable_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - reboot_required
    - sysctl_net_ipv6_conf_default_accept_redirects

  - name: Disable Kernel Parameter for Accepting ICMP Redirects by Default on IPv6
      Interfaces - Find all files that set net.ipv6.conf.default.accept_redirects
      to correct value
    ansible.builtin.shell:
      cmd: find -L {{ sysctl_paths | join(" ") }} -type f -name '*.conf' | xargs grep
        -HP '^\s*net.ipv6.conf.default.accept_redirects\s*=\s*{{ sysctl_net_ipv6_conf_default_accept_redirects_value
        }}$'
    register: find_correct_value
    check_mode: false
    changed_when: false
    failed_when: false
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - NIST-800-171-3.1.20
    - NIST-800-53-CM-6(a)
    - NIST-800-53-CM-7(a)
    - NIST-800-53-CM-7(b)
    - disable_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - reboot_required
    - sysctl_net_ipv6_conf_default_accept_redirects

  - name: Disable Kernel Parameter for Accepting ICMP Redirects by Default on IPv6
      Interfaces - Comment out any occurrences of net.ipv6.conf.default.accept_redirects
      from config files
    ansible.builtin.replace:
      path: '{{ item | split(":") | first }}'
      regexp: ^[\s]*net.ipv6.conf.default.accept_redirects
      replace: '#net.ipv6.conf.default.accept_redirects'
    loop: '{{ find_all_values.stdout_lines }}'
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - find_correct_value.stdout_lines | length == 0 or find_all_values.stdout_lines
      | length > find_correct_value.stdout_lines | length
    tags:
    - NIST-800-171-3.1.20
    - NIST-800-53-CM-6(a)
    - NIST-800-53-CM-7(a)
    - NIST-800-53-CM-7(b)
    - disable_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - reboot_required
    - sysctl_net_ipv6_conf_default_accept_redirects

  - name: Disable Kernel Parameter for Accepting ICMP Redirects by Default on IPv6
      Interfaces - Ensure sysctl net.ipv6.conf.default.accept_redirects is set
    ansible.posix.sysctl:
      name: net.ipv6.conf.default.accept_redirects
      value: '{{ sysctl_net_ipv6_conf_default_accept_redirects_value }}'
      sysctl_file: /etc/sysctl.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)
    - disable_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - reboot_required
    - sysctl_net_ipv6_conf_default_accept_redirects

  - name: Disable Kernel Parameter for Accepting Source-Routed Packets on IPv6 Interfaces
      by Default - Set fact for sysctl paths
    ansible.builtin.set_fact:
      sysctl_paths:
      - /etc/sysctl.d/
      - /run/sysctl.d/
      - /usr/local/lib/sysctl.d/
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - 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:
    - 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:
    - 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:
    - 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.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-6(b)
    - NIST-800-53-CM-6.1(iv)
    - NIST-800-53-CM-7(a)
    - NIST-800-53-CM-7(b)
    - PCI-DSS-Req-1.4.3
    - PCI-DSSv4-1.4
    - PCI-DSSv4-1.4.2
    - disable_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - reboot_required
    - sysctl_net_ipv6_conf_default_accept_source_route

  - name: Disable Accepting ICMP Redirects for All IPv4 Interfaces - Set fact for
      sysctl paths
    ansible.builtin.set_fact:
      sysctl_paths:
      - /etc/sysctl.d/
      - /run/sysctl.d/
      - /usr/local/lib/sysctl.d/
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - CJIS-5.10.1.1
    - DISA-STIG-OL07-00-040641
    - NIST-800-171-3.1.20
    - NIST-800-53-CM-6(a)
    - NIST-800-53-CM-7(a)
    - NIST-800-53-CM-7(b)
    - NIST-800-53-SC-7(a)
    - disable_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - reboot_required
    - sysctl_net_ipv4_conf_all_accept_redirects

  - name: Disable Accepting ICMP Redirects for All IPv4 Interfaces - Find all files
      that contain net.ipv4.conf.all.accept_redirects
    ansible.builtin.shell:
      cmd: find -L {{ sysctl_paths | join(" ") }} -type f -name '*.conf' | xargs grep
        -HP '^\s*net.ipv4.conf.all.accept_redirects\s*=\s*.*$'
    register: find_all_values
    check_mode: false
    changed_when: false
    failed_when: false
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - CJIS-5.10.1.1
    - DISA-STIG-OL07-00-040641
    - NIST-800-171-3.1.20
    - NIST-800-53-CM-6(a)
    - NIST-800-53-CM-7(a)
    - NIST-800-53-CM-7(b)
    - NIST-800-53-SC-7(a)
    - disable_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - reboot_required
    - sysctl_net_ipv4_conf_all_accept_redirects

  - name: Disable Accepting ICMP Redirects for All IPv4 Interfaces - Find all files
      that set net.ipv4.conf.all.accept_redirects to correct value
    ansible.builtin.shell:
      cmd: find -L {{ sysctl_paths | join(" ") }} -type f -name '*.conf' | xargs grep
        -HP '^\s*net.ipv4.conf.all.accept_redirects\s*=\s*{{ sysctl_net_ipv4_conf_all_accept_redirects_value
        }}$'
    register: find_correct_value
    check_mode: false
    changed_when: false
    failed_when: false
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - CJIS-5.10.1.1
    - DISA-STIG-OL07-00-040641
    - NIST-800-171-3.1.20
    - NIST-800-53-CM-6(a)
    - NIST-800-53-CM-7(a)
    - NIST-800-53-CM-7(b)
    - NIST-800-53-SC-7(a)
    - disable_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - reboot_required
    - sysctl_net_ipv4_conf_all_accept_redirects

  - name: Disable Accepting ICMP Redirects for All IPv4 Interfaces - Comment out any
      occurrences of net.ipv4.conf.all.accept_redirects from config files
    ansible.builtin.replace:
      path: '{{ item | split(":") | first }}'
      regexp: ^[\s]*net.ipv4.conf.all.accept_redirects
      replace: '#net.ipv4.conf.all.accept_redirects'
    loop: '{{ find_all_values.stdout_lines }}'
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - find_correct_value.stdout_lines | length == 0 or find_all_values.stdout_lines
      | length > find_correct_value.stdout_lines | length
    tags:
    - CJIS-5.10.1.1
    - DISA-STIG-OL07-00-040641
    - NIST-800-171-3.1.20
    - NIST-800-53-CM-6(a)
    - NIST-800-53-CM-7(a)
    - NIST-800-53-CM-7(b)
    - NIST-800-53-SC-7(a)
    - disable_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - reboot_required
    - sysctl_net_ipv4_conf_all_accept_redirects

  - name: Disable Accepting ICMP Redirects for All IPv4 Interfaces - Ensure sysctl
      net.ipv4.conf.all.accept_redirects is set
    ansible.posix.sysctl:
      name: net.ipv4.conf.all.accept_redirects
      value: '{{ sysctl_net_ipv4_conf_all_accept_redirects_value }}'
      sysctl_file: /etc/sysctl.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-OL07-00-040641
    - NIST-800-171-3.1.20
    - NIST-800-53-CM-6(a)
    - NIST-800-53-CM-7(a)
    - NIST-800-53-CM-7(b)
    - NIST-800-53-SC-7(a)
    - disable_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - reboot_required
    - sysctl_net_ipv4_conf_all_accept_redirects

  - name: Disable Kernel Parameter for Accepting Source-Routed Packets on all IPv4
      Interfaces - Set fact for sysctl paths
    ansible.builtin.set_fact:
      sysctl_paths:
      - /etc/sysctl.d/
      - /run/sysctl.d/
      - /usr/local/lib/sysctl.d/
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL07-00-040610
    - NIST-800-171-3.1.20
    - NIST-800-53-CM-6(a)
    - NIST-800-53-CM-7(a)
    - NIST-800-53-CM-7(b)
    - NIST-800-53-SC-5
    - NIST-800-53-SC-7(a)
    - disable_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - reboot_required
    - sysctl_net_ipv4_conf_all_accept_source_route

  - name: Disable Kernel Parameter for Accepting Source-Routed Packets on all IPv4
      Interfaces - Find all files that contain net.ipv4.conf.all.accept_source_route
    ansible.builtin.shell:
      cmd: find -L {{ sysctl_paths | join(" ") }} -type f -name '*.conf' | xargs grep
        -HP '^\s*net.ipv4.conf.all.accept_source_route\s*=\s*.*$'
    register: find_all_values
    check_mode: false
    changed_when: false
    failed_when: false
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL07-00-040610
    - NIST-800-171-3.1.20
    - NIST-800-53-CM-6(a)
    - NIST-800-53-CM-7(a)
    - NIST-800-53-CM-7(b)
    - NIST-800-53-SC-5
    - NIST-800-53-SC-7(a)
    - disable_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - reboot_required
    - sysctl_net_ipv4_conf_all_accept_source_route

  - name: Disable Kernel Parameter for Accepting Source-Routed Packets on all IPv4
      Interfaces - Find all files that set net.ipv4.conf.all.accept_source_route to
      correct value
    ansible.builtin.shell:
      cmd: find -L {{ sysctl_paths | join(" ") }} -type f -name '*.conf' | xargs grep
        -HP '^\s*net.ipv4.conf.all.accept_source_route\s*=\s*{{ sysctl_net_ipv4_conf_all_accept_source_route_value
        }}$'
    register: find_correct_value
    check_mode: false
    changed_when: false
    failed_when: false
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL07-00-040610
    - NIST-800-171-3.1.20
    - NIST-800-53-CM-6(a)
    - NIST-800-53-CM-7(a)
    - NIST-800-53-CM-7(b)
    - NIST-800-53-SC-5
    - NIST-800-53-SC-7(a)
    - disable_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - reboot_required
    - sysctl_net_ipv4_conf_all_accept_source_route

  - name: Disable Kernel Parameter for Accepting Source-Routed Packets on all IPv4
      Interfaces - Comment out any occurrences of net.ipv4.conf.all.accept_source_route
      from config files
    ansible.builtin.replace:
      path: '{{ item | split(":") | first }}'
      regexp: ^[\s]*net.ipv4.conf.all.accept_source_route
      replace: '#net.ipv4.conf.all.accept_source_route'
    loop: '{{ find_all_values.stdout_lines }}'
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - find_correct_value.stdout_lines | length == 0 or find_all_values.stdout_lines
      | length > find_correct_value.stdout_lines | length
    tags:
    - DISA-STIG-OL07-00-040610
    - NIST-800-171-3.1.20
    - NIST-800-53-CM-6(a)
    - NIST-800-53-CM-7(a)
    - NIST-800-53-CM-7(b)
    - NIST-800-53-SC-5
    - NIST-800-53-SC-7(a)
    - disable_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - reboot_required
    - sysctl_net_ipv4_conf_all_accept_source_route

  - name: Disable Kernel Parameter for Accepting Source-Routed Packets on all IPv4
      Interfaces - Ensure sysctl net.ipv4.conf.all.accept_source_route is set
    ansible.posix.sysctl:
      name: net.ipv4.conf.all.accept_source_route
      value: '{{ sysctl_net_ipv4_conf_all_accept_source_route_value }}'
      sysctl_file: /etc/sysctl.conf
      state: present
      reload: true
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL07-00-040610
    - NIST-800-171-3.1.20
    - NIST-800-53-CM-6(a)
    - NIST-800-53-CM-7(a)
    - NIST-800-53-CM-7(b)
    - NIST-800-53-SC-5
    - NIST-800-53-SC-7(a)
    - disable_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - reboot_required
    - sysctl_net_ipv4_conf_all_accept_source_route

  - name: Enable Kernel Parameter to Log Martian Packets on all IPv4 Interfaces -
      Set fact for sysctl paths
    ansible.builtin.set_fact:
      sysctl_paths:
      - /etc/sysctl.d/
      - /run/sysctl.d/
      - /usr/local/lib/sysctl.d/
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - NIST-800-171-3.1.20
    - NIST-800-53-CM-7(a)
    - NIST-800-53-CM-7(b)
    - NIST-800-53-SC-5(3)(a)
    - disable_strategy
    - low_complexity
    - medium_disruption
    - reboot_required
    - sysctl_net_ipv4_conf_all_log_martians
    - unknown_severity

  - name: Enable Kernel Parameter to Log Martian Packets on all IPv4 Interfaces -
      Find all files that contain net.ipv4.conf.all.log_martians
    ansible.builtin.shell:
      cmd: find -L {{ sysctl_paths | join(" ") }} -type f -name '*.conf' | xargs grep
        -HP '^\s*net.ipv4.conf.all.log_martians\s*=\s*.*$'
    register: find_all_values
    check_mode: false
    changed_when: false
    failed_when: false
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - NIST-800-171-3.1.20
    - NIST-800-53-CM-7(a)
    - NIST-800-53-CM-7(b)
    - NIST-800-53-SC-5(3)(a)
    - disable_strategy
    - low_complexity
    - medium_disruption
    - reboot_required
    - sysctl_net_ipv4_conf_all_log_martians
    - unknown_severity

  - name: Enable Kernel Parameter to Log Martian Packets on all IPv4 Interfaces -
      Find all files that set net.ipv4.conf.all.log_martians to correct value
    ansible.builtin.shell:
      cmd: find -L {{ sysctl_paths | join(" ") }} -type f -name '*.conf' | xargs grep
        -HP '^\s*net.ipv4.conf.all.log_martians\s*=\s*{{ sysctl_net_ipv4_conf_all_log_martians_value
        }}$'
    register: find_correct_value
    check_mode: false
    changed_when: false
    failed_when: false
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - NIST-800-171-3.1.20
    - NIST-800-53-CM-7(a)
    - NIST-800-53-CM-7(b)
    - NIST-800-53-SC-5(3)(a)
    - disable_strategy
    - low_complexity
    - medium_disruption
    - reboot_required
    - sysctl_net_ipv4_conf_all_log_martians
    - unknown_severity

  - name: Enable Kernel Parameter to Log Martian Packets on all IPv4 Interfaces -
      Comment out any occurrences of net.ipv4.conf.all.log_martians from config files
    ansible.builtin.replace:
      path: '{{ item | split(":") | first }}'
      regexp: ^[\s]*net.ipv4.conf.all.log_martians
      replace: '#net.ipv4.conf.all.log_martians'
    loop: '{{ find_all_values.stdout_lines }}'
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - find_correct_value.stdout_lines | length == 0 or find_all_values.stdout_lines
      | length > find_correct_value.stdout_lines | length
    tags:
    - NIST-800-171-3.1.20
    - NIST-800-53-CM-7(a)
    - NIST-800-53-CM-7(b)
    - NIST-800-53-SC-5(3)(a)
    - disable_strategy
    - low_complexity
    - medium_disruption
    - reboot_required
    - sysctl_net_ipv4_conf_all_log_martians
    - unknown_severity

  - name: Enable Kernel Parameter to Log Martian Packets on all IPv4 Interfaces -
      Ensure sysctl net.ipv4.conf.all.log_martians is set
    ansible.posix.sysctl:
      name: net.ipv4.conf.all.log_martians
      value: '{{ sysctl_net_ipv4_conf_all_log_martians_value }}'
      sysctl_file: /etc/sysctl.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-7(a)
    - NIST-800-53-CM-7(b)
    - NIST-800-53-SC-5(3)(a)
    - disable_strategy
    - low_complexity
    - medium_disruption
    - reboot_required
    - sysctl_net_ipv4_conf_all_log_martians
    - unknown_severity

  - name: Enable Kernel Parameter to Use Reverse Path Filtering on all IPv4 Interfaces
      - Set fact for sysctl paths
    ansible.builtin.set_fact:
      sysctl_paths:
      - /etc/sysctl.d/
      - /run/sysctl.d/
      - /usr/local/lib/sysctl.d/
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL07-00-040611
    - 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-OL07-00-040611
    - 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-OL07-00-040611
    - 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-OL07-00-040611
    - 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.conf
      state: present
      reload: true
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL07-00-040611
    - 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 - 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.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-OL07-00-040640
    - 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-OL07-00-040640
    - 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-OL07-00-040640
    - 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-OL07-00-040640
    - 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.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-OL07-00-040640
    - NIST-800-171-3.1.20
    - NIST-800-53-CM-6(a)
    - NIST-800-53-CM-7(a)
    - NIST-800-53-CM-7(b)
    - NIST-800-53-SC-7(a)
    - PCI-DSS-Req-1.4.3
    - PCI-DSSv4-1.4
    - PCI-DSSv4-1.4.3
    - disable_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - reboot_required
    - sysctl_net_ipv4_conf_default_accept_redirects

  - name: Disable Kernel Parameter for Accepting Source-Routed Packets on IPv4 Interfaces
      by Default - Set fact for sysctl paths
    ansible.builtin.set_fact:
      sysctl_paths:
      - /etc/sysctl.d/
      - /run/sysctl.d/
      - /usr/local/lib/sysctl.d/
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - CJIS-5.10.1.1
    - DISA-STIG-OL07-00-040620
    - NIST-800-171-3.1.20
    - NIST-800-53-CM-7(a)
    - NIST-800-53-CM-7(b)
    - NIST-800-53-SC-5
    - NIST-800-53-SC-7(a)
    - disable_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - reboot_required
    - sysctl_net_ipv4_conf_default_accept_source_route

  - name: Disable Kernel Parameter for Accepting Source-Routed Packets on IPv4 Interfaces
      by Default - Find all files that contain net.ipv4.conf.default.accept_source_route
    ansible.builtin.shell:
      cmd: find -L {{ sysctl_paths | join(" ") }} -type f -name '*.conf' | xargs grep
        -HP '^\s*net.ipv4.conf.default.accept_source_route\s*=\s*.*$'
    register: find_all_values
    check_mode: false
    changed_when: false
    failed_when: false
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - CJIS-5.10.1.1
    - DISA-STIG-OL07-00-040620
    - NIST-800-171-3.1.20
    - NIST-800-53-CM-7(a)
    - NIST-800-53-CM-7(b)
    - NIST-800-53-SC-5
    - NIST-800-53-SC-7(a)
    - disable_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - reboot_required
    - sysctl_net_ipv4_conf_default_accept_source_route

  - name: Disable Kernel Parameter for Accepting Source-Routed Packets on IPv4 Interfaces
      by Default - Find all files that set net.ipv4.conf.default.accept_source_route
      to correct value
    ansible.builtin.shell:
      cmd: find -L {{ sysctl_paths | join(" ") }} -type f -name '*.conf' | xargs grep
        -HP '^\s*net.ipv4.conf.default.accept_source_route\s*=\s*{{ sysctl_net_ipv4_conf_default_accept_source_route_value
        }}$'
    register: find_correct_value
    check_mode: false
    changed_when: false
    failed_when: false
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - CJIS-5.10.1.1
    - DISA-STIG-OL07-00-040620
    - NIST-800-171-3.1.20
    - NIST-800-53-CM-7(a)
    - NIST-800-53-CM-7(b)
    - NIST-800-53-SC-5
    - NIST-800-53-SC-7(a)
    - disable_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - reboot_required
    - sysctl_net_ipv4_conf_default_accept_source_route

  - name: Disable Kernel Parameter for Accepting Source-Routed Packets on IPv4 Interfaces
      by Default - Comment out any occurrences of net.ipv4.conf.default.accept_source_route
      from config files
    ansible.builtin.replace:
      path: '{{ item | split(":") | first }}'
      regexp: ^[\s]*net.ipv4.conf.default.accept_source_route
      replace: '#net.ipv4.conf.default.accept_source_route'
    loop: '{{ find_all_values.stdout_lines }}'
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - find_correct_value.stdout_lines | length == 0 or find_all_values.stdout_lines
      | length > find_correct_value.stdout_lines | length
    tags:
    - CJIS-5.10.1.1
    - DISA-STIG-OL07-00-040620
    - NIST-800-171-3.1.20
    - NIST-800-53-CM-7(a)
    - NIST-800-53-CM-7(b)
    - NIST-800-53-SC-5
    - NIST-800-53-SC-7(a)
    - disable_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - reboot_required
    - sysctl_net_ipv4_conf_default_accept_source_route

  - name: Disable Kernel Parameter for Accepting Source-Routed Packets on IPv4 Interfaces
      by Default - Ensure sysctl net.ipv4.conf.default.accept_source_route is set
    ansible.posix.sysctl:
      name: net.ipv4.conf.default.accept_source_route
      value: '{{ sysctl_net_ipv4_conf_default_accept_source_route_value }}'
      sysctl_file: /etc/sysctl.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-OL07-00-040620
    - NIST-800-171-3.1.20
    - NIST-800-53-CM-7(a)
    - NIST-800-53-CM-7(b)
    - NIST-800-53-SC-5
    - NIST-800-53-SC-7(a)
    - disable_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - reboot_required
    - sysctl_net_ipv4_conf_default_accept_source_route

  - name: Enable Kernel Parameter to Log Martian Packets on all IPv4 Interfaces by
      Default - Set fact for sysctl paths
    ansible.builtin.set_fact:
      sysctl_paths:
      - /etc/sysctl.d/
      - /run/sysctl.d/
      - /usr/local/lib/sysctl.d/
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - NIST-800-171-3.1.20
    - NIST-800-53-CM-7(a)
    - NIST-800-53-CM-7(b)
    - NIST-800-53-SC-5(3)(a)
    - disable_strategy
    - low_complexity
    - medium_disruption
    - reboot_required
    - sysctl_net_ipv4_conf_default_log_martians
    - unknown_severity

  - name: Enable Kernel Parameter to Log Martian Packets on all IPv4 Interfaces by
      Default - Find all files that contain net.ipv4.conf.default.log_martians
    ansible.builtin.shell:
      cmd: find -L {{ sysctl_paths | join(" ") }} -type f -name '*.conf' | xargs grep
        -HP '^\s*net.ipv4.conf.default.log_martians\s*=\s*.*$'
    register: find_all_values
    check_mode: false
    changed_when: false
    failed_when: false
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - NIST-800-171-3.1.20
    - NIST-800-53-CM-7(a)
    - NIST-800-53-CM-7(b)
    - NIST-800-53-SC-5(3)(a)
    - disable_strategy
    - low_complexity
    - medium_disruption
    - reboot_required
    - sysctl_net_ipv4_conf_default_log_martians
    - unknown_severity

  - name: Enable Kernel Parameter to Log Martian Packets on all IPv4 Interfaces by
      Default - Find all files that set net.ipv4.conf.default.log_martians to correct
      value
    ansible.builtin.shell:
      cmd: find -L {{ sysctl_paths | join(" ") }} -type f -name '*.conf' | xargs grep
        -HP '^\s*net.ipv4.conf.default.log_martians\s*=\s*{{ sysctl_net_ipv4_conf_default_log_martians_value
        }}$'
    register: find_correct_value
    check_mode: false
    changed_when: false
    failed_when: false
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - NIST-800-171-3.1.20
    - NIST-800-53-CM-7(a)
    - NIST-800-53-CM-7(b)
    - NIST-800-53-SC-5(3)(a)
    - disable_strategy
    - low_complexity
    - medium_disruption
    - reboot_required
    - sysctl_net_ipv4_conf_default_log_martians
    - unknown_severity

  - name: Enable Kernel Parameter to Log Martian Packets on all IPv4 Interfaces by
      Default - Comment out any occurrences of net.ipv4.conf.default.log_martians
      from config files
    ansible.builtin.replace:
      path: '{{ item | split(":") | first }}'
      regexp: ^[\s]*net.ipv4.conf.default.log_martians
      replace: '#net.ipv4.conf.default.log_martians'
    loop: '{{ find_all_values.stdout_lines }}'
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - find_correct_value.stdout_lines | length == 0 or find_all_values.stdout_lines
      | length > find_correct_value.stdout_lines | length
    tags:
    - NIST-800-171-3.1.20
    - NIST-800-53-CM-7(a)
    - NIST-800-53-CM-7(b)
    - NIST-800-53-SC-5(3)(a)
    - disable_strategy
    - low_complexity
    - medium_disruption
    - reboot_required
    - sysctl_net_ipv4_conf_default_log_martians
    - unknown_severity

  - name: Enable Kernel Parameter to Log Martian Packets on all IPv4 Interfaces by
      Default - Ensure sysctl net.ipv4.conf.default.log_martians is set
    ansible.posix.sysctl:
      name: net.ipv4.conf.default.log_martians
      value: '{{ sysctl_net_ipv4_conf_default_log_martians_value }}'
      sysctl_file: /etc/sysctl.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-7(a)
    - NIST-800-53-CM-7(b)
    - NIST-800-53-SC-5(3)(a)
    - disable_strategy
    - low_complexity
    - medium_disruption
    - reboot_required
    - sysctl_net_ipv4_conf_default_log_martians
    - unknown_severity

  - name: Enable Kernel Parameter to Use Reverse Path Filtering on all IPv4 Interfaces
      by Default - Set fact for sysctl paths
    ansible.builtin.set_fact:
      sysctl_paths:
      - /etc/sysctl.d/
      - /run/sysctl.d/
      - /usr/local/lib/sysctl.d/
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL07-00-040612
    - NIST-800-171-3.1.20
    - NIST-800-53-CM-6(a)
    - NIST-800-53-CM-7(a)
    - NIST-800-53-CM-7(b)
    - NIST-800-53-SC-7(a)
    - disable_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - reboot_required
    - sysctl_net_ipv4_conf_default_rp_filter

  - name: Enable Kernel Parameter to Use Reverse Path Filtering on all IPv4 Interfaces
      by Default - Find all files that contain net.ipv4.conf.default.rp_filter
    ansible.builtin.shell:
      cmd: find -L {{ sysctl_paths | join(" ") }} -type f -name '*.conf' | xargs grep
        -HP '^\s*net.ipv4.conf.default.rp_filter\s*=\s*.*$'
    register: find_all_values
    check_mode: false
    changed_when: false
    failed_when: false
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL07-00-040612
    - NIST-800-171-3.1.20
    - NIST-800-53-CM-6(a)
    - NIST-800-53-CM-7(a)
    - NIST-800-53-CM-7(b)
    - NIST-800-53-SC-7(a)
    - disable_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - reboot_required
    - sysctl_net_ipv4_conf_default_rp_filter

  - name: Enable Kernel Parameter to Use Reverse Path Filtering on all IPv4 Interfaces
      by Default - Find all files that set net.ipv4.conf.default.rp_filter to correct
      value
    ansible.builtin.shell:
      cmd: find -L {{ sysctl_paths | join(" ") }} -type f -name '*.conf' | xargs grep
        -HP '^\s*net.ipv4.conf.default.rp_filter\s*=\s*{{ sysctl_net_ipv4_conf_default_rp_filter_value
        }}$'
    register: find_correct_value
    check_mode: false
    changed_when: false
    failed_when: false
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL07-00-040612
    - NIST-800-171-3.1.20
    - NIST-800-53-CM-6(a)
    - NIST-800-53-CM-7(a)
    - NIST-800-53-CM-7(b)
    - NIST-800-53-SC-7(a)
    - disable_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - reboot_required
    - sysctl_net_ipv4_conf_default_rp_filter

  - name: Enable Kernel Parameter to Use Reverse Path Filtering on all IPv4 Interfaces
      by Default - Comment out any occurrences of net.ipv4.conf.default.rp_filter
      from config files
    ansible.builtin.replace:
      path: '{{ item | split(":") | first }}'
      regexp: ^[\s]*net.ipv4.conf.default.rp_filter
      replace: '#net.ipv4.conf.default.rp_filter'
    loop: '{{ find_all_values.stdout_lines }}'
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - find_correct_value.stdout_lines | length == 0 or find_all_values.stdout_lines
      | length > find_correct_value.stdout_lines | length
    tags:
    - DISA-STIG-OL07-00-040612
    - NIST-800-171-3.1.20
    - NIST-800-53-CM-6(a)
    - NIST-800-53-CM-7(a)
    - NIST-800-53-CM-7(b)
    - NIST-800-53-SC-7(a)
    - disable_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - reboot_required
    - sysctl_net_ipv4_conf_default_rp_filter

  - name: Enable Kernel Parameter to Use Reverse Path Filtering on all IPv4 Interfaces
      by Default - Ensure sysctl net.ipv4.conf.default.rp_filter is set
    ansible.posix.sysctl:
      name: net.ipv4.conf.default.rp_filter
      value: '{{ sysctl_net_ipv4_conf_default_rp_filter_value }}'
      sysctl_file: /etc/sysctl.conf
      state: present
      reload: true
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL07-00-040612
    - NIST-800-171-3.1.20
    - NIST-800-53-CM-6(a)
    - NIST-800-53-CM-7(a)
    - NIST-800-53-CM-7(b)
    - NIST-800-53-SC-7(a)
    - disable_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - reboot_required
    - sysctl_net_ipv4_conf_default_rp_filter

  - name: Configure Kernel Parameter for Accepting Secure Redirects 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:
    - NIST-800-171-3.1.20
    - NIST-800-53-CM-7(a)
    - NIST-800-53-CM-7(b)
    - NIST-800-53-SC-5
    - NIST-800-53-SC-7(a)
    - disable_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - reboot_required
    - sysctl_net_ipv4_conf_default_secure_redirects

  - name: Configure Kernel Parameter for Accepting Secure Redirects By Default - Find
      all files that contain net.ipv4.conf.default.secure_redirects
    ansible.builtin.shell:
      cmd: find -L {{ sysctl_paths | join(" ") }} -type f -name '*.conf' | xargs grep
        -HP '^\s*net.ipv4.conf.default.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-7(a)
    - NIST-800-53-CM-7(b)
    - NIST-800-53-SC-5
    - NIST-800-53-SC-7(a)
    - disable_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - reboot_required
    - sysctl_net_ipv4_conf_default_secure_redirects

  - name: Configure Kernel Parameter for Accepting Secure Redirects By Default - Find
      all files that set net.ipv4.conf.default.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.default.secure_redirects\s*=\s*{{ sysctl_net_ipv4_conf_default_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-7(a)
    - NIST-800-53-CM-7(b)
    - NIST-800-53-SC-5
    - NIST-800-53-SC-7(a)
    - disable_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - reboot_required
    - sysctl_net_ipv4_conf_default_secure_redirects

  - name: Configure Kernel Parameter for Accepting Secure Redirects By Default - Comment
      out any occurrences of net.ipv4.conf.default.secure_redirects from config files
    ansible.builtin.replace:
      path: '{{ item | split(":") | first }}'
      regexp: ^[\s]*net.ipv4.conf.default.secure_redirects
      replace: '#net.ipv4.conf.default.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-7(a)
    - NIST-800-53-CM-7(b)
    - NIST-800-53-SC-5
    - NIST-800-53-SC-7(a)
    - disable_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - reboot_required
    - sysctl_net_ipv4_conf_default_secure_redirects

  - name: Configure Kernel Parameter for Accepting Secure Redirects By Default - Ensure
      sysctl net.ipv4.conf.default.secure_redirects is set
    ansible.posix.sysctl:
      name: net.ipv4.conf.default.secure_redirects
      value: '{{ sysctl_net_ipv4_conf_default_secure_redirects_value }}'
      sysctl_file: /etc/sysctl.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-7(a)
    - NIST-800-53-CM-7(b)
    - NIST-800-53-SC-5
    - NIST-800-53-SC-7(a)
    - disable_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - reboot_required
    - sysctl_net_ipv4_conf_default_secure_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-OL07-00-040630
    - 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-OL07-00-040630
    - 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-OL07-00-040630
    - 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-OL07-00-040630
    - 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.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-OL07-00-040630
    - 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:
    - 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:
    - 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:
    - 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:
    - 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.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-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
    - 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
    - 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
    - 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
    - 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.conf
      state: present
      reload: true
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - CJIS-5.10.1.1
    - 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-OL07-00-040660
    - 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-OL07-00-040660
    - 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-OL07-00-040660
    - 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-OL07-00-040660
    - 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.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-OL07-00-040660
    - 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-OL07-00-040650
    - 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-OL07-00-040650
    - 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-OL07-00-040650
    - 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-OL07-00-040650
    - 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.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-OL07-00-040650
    - 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:
    - DISA-STIG-OL07-00-040740
    - 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:
    - DISA-STIG-OL07-00-040740
    - 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:
    - DISA-STIG-OL07-00-040740
    - 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:
    - DISA-STIG-OL07-00-040740
    - 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.conf
      state: present
      reload: true
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL07-00-040740
    - 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
    - DISA-STIG-OL07-00-020101
    - 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
    - DISA-STIG-OL07-00-020101
    - 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
    - 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
    - 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 'bluetooth' is disabled
    ansible.builtin.lineinfile:
      create: true
      dest: /etc/modprobe.d/bluetooth.conf
      regexp: install\s+bluetooth
      line: install bluetooth /bin/false
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - CJIS-5.13.1.3
    - NIST-800-171-3.1.16
    - NIST-800-53-AC-18(3)
    - NIST-800-53-AC-18(a)
    - NIST-800-53-CM-6(a)
    - NIST-800-53-CM-7(a)
    - NIST-800-53-CM-7(b)
    - NIST-800-53-MP-7
    - disable_strategy
    - kernel_module_bluetooth_disabled
    - low_complexity
    - medium_disruption
    - medium_severity
    - reboot_required

  - name: Ensure kernel module 'bluetooth' is blacklisted
    ansible.builtin.lineinfile:
      create: true
      dest: /etc/modprobe.d/bluetooth.conf
      regexp: ^blacklist bluetooth$
      line: blacklist bluetooth
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - CJIS-5.13.1.3
    - NIST-800-171-3.1.16
    - NIST-800-53-AC-18(3)
    - NIST-800-53-AC-18(a)
    - NIST-800-53-CM-6(a)
    - NIST-800-53-CM-7(a)
    - NIST-800-53-CM-7(b)
    - NIST-800-53-MP-7
    - disable_strategy
    - kernel_module_bluetooth_disabled
    - low_complexity
    - medium_disruption
    - medium_severity
    - reboot_required

  - name: Enable Kernel Parameter to Enforce DAC on Hardlinks - Set fact for sysctl
      paths
    ansible.builtin.set_fact:
      sysctl_paths:
      - /etc/sysctl.d/
      - /run/sysctl.d/
      - /usr/local/lib/sysctl.d/
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - NIST-800-53-AC-6(1)
    - NIST-800-53-CM-6(a)
    - disable_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - reboot_required
    - sysctl_fs_protected_hardlinks

  - name: Enable Kernel Parameter to Enforce DAC on Hardlinks - Find all files that
      contain fs.protected_hardlinks
    ansible.builtin.shell:
      cmd: find -L {{ sysctl_paths | join(" ") }} -type f -name '*.conf' | xargs grep
        -HP '^\s*fs.protected_hardlinks\s*=\s*.*$'
    register: find_all_values
    check_mode: false
    changed_when: false
    failed_when: false
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - NIST-800-53-AC-6(1)
    - NIST-800-53-CM-6(a)
    - disable_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - reboot_required
    - sysctl_fs_protected_hardlinks

  - name: Enable Kernel Parameter to Enforce DAC on Hardlinks - Find all files that
      set fs.protected_hardlinks to correct value
    ansible.builtin.shell:
      cmd: find -L {{ sysctl_paths | join(" ") }} -type f -name '*.conf' | xargs grep
        -HP '^\s*fs.protected_hardlinks\s*=\s*1$'
    register: find_correct_value
    check_mode: false
    changed_when: false
    failed_when: false
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - NIST-800-53-AC-6(1)
    - NIST-800-53-CM-6(a)
    - disable_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - reboot_required
    - sysctl_fs_protected_hardlinks

  - name: Enable Kernel Parameter to Enforce DAC on Hardlinks - Comment out any occurrences
      of fs.protected_hardlinks from config files
    ansible.builtin.replace:
      path: '{{ item | split(":") | first }}'
      regexp: ^[\s]*fs.protected_hardlinks
      replace: '#fs.protected_hardlinks'
    loop: '{{ find_all_values.stdout_lines }}'
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - find_correct_value.stdout_lines | length == 0 or find_all_values.stdout_lines
      | length > find_correct_value.stdout_lines | length
    tags:
    - NIST-800-53-AC-6(1)
    - NIST-800-53-CM-6(a)
    - disable_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - reboot_required
    - sysctl_fs_protected_hardlinks

  - name: Enable Kernel Parameter to Enforce DAC on Hardlinks - Ensure sysctl fs.protected_hardlinks
      is set to 1
    ansible.posix.sysctl:
      name: fs.protected_hardlinks
      value: '1'
      sysctl_file: /etc/sysctl.conf
      state: present
      reload: true
    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)
    - disable_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - reboot_required
    - sysctl_fs_protected_hardlinks

  - name: Enable Kernel Parameter to Enforce DAC on Symlinks - Set fact for sysctl
      paths
    ansible.builtin.set_fact:
      sysctl_paths:
      - /etc/sysctl.d/
      - /run/sysctl.d/
      - /usr/local/lib/sysctl.d/
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - NIST-800-53-AC-6(1)
    - NIST-800-53-CM-6(a)
    - disable_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - reboot_required
    - sysctl_fs_protected_symlinks

  - name: Enable Kernel Parameter to Enforce DAC on Symlinks - Find all files that
      contain fs.protected_symlinks
    ansible.builtin.shell:
      cmd: find -L {{ sysctl_paths | join(" ") }} -type f -name '*.conf' | xargs grep
        -HP '^\s*fs.protected_symlinks\s*=\s*.*$'
    register: find_all_values
    check_mode: false
    changed_when: false
    failed_when: false
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - NIST-800-53-AC-6(1)
    - NIST-800-53-CM-6(a)
    - disable_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - reboot_required
    - sysctl_fs_protected_symlinks

  - name: Enable Kernel Parameter to Enforce DAC on Symlinks - Find all files that
      set fs.protected_symlinks to correct value
    ansible.builtin.shell:
      cmd: find -L {{ sysctl_paths | join(" ") }} -type f -name '*.conf' | xargs grep
        -HP '^\s*fs.protected_symlinks\s*=\s*1$'
    register: find_correct_value
    check_mode: false
    changed_when: false
    failed_when: false
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - NIST-800-53-AC-6(1)
    - NIST-800-53-CM-6(a)
    - disable_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - reboot_required
    - sysctl_fs_protected_symlinks

  - name: Enable Kernel Parameter to Enforce DAC on Symlinks - Comment out any occurrences
      of fs.protected_symlinks from config files
    ansible.builtin.replace:
      path: '{{ item | split(":") | first }}'
      regexp: ^[\s]*fs.protected_symlinks
      replace: '#fs.protected_symlinks'
    loop: '{{ find_all_values.stdout_lines }}'
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - find_correct_value.stdout_lines | length == 0 or find_all_values.stdout_lines
      | length > find_correct_value.stdout_lines | length
    tags:
    - NIST-800-53-AC-6(1)
    - NIST-800-53-CM-6(a)
    - disable_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - reboot_required
    - sysctl_fs_protected_symlinks

  - name: Enable Kernel Parameter to Enforce DAC on Symlinks - Ensure sysctl fs.protected_symlinks
      is set to 1
    ansible.posix.sysctl:
      name: fs.protected_symlinks
      value: '1'
      sysctl_file: /etc/sysctl.conf
      state: present
      reload: true
    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)
    - disable_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - reboot_required
    - sysctl_fs_protected_symlinks

  - name: Ensure kernel module 'cramfs' is disabled
    ansible.builtin.lineinfile:
      create: true
      dest: /etc/modprobe.d/cramfs.conf
      regexp: install\s+cramfs
      line: install cramfs /bin/false
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - NIST-800-171-3.4.6
    - NIST-800-53-CM-6(a)
    - NIST-800-53-CM-7(a)
    - NIST-800-53-CM-7(b)
    - disable_strategy
    - kernel_module_cramfs_disabled
    - low_complexity
    - low_severity
    - medium_disruption
    - reboot_required

  - name: Ensure kernel module 'cramfs' is blacklisted
    ansible.builtin.lineinfile:
      create: true
      dest: /etc/modprobe.d/cramfs.conf
      regexp: ^blacklist cramfs$
      line: blacklist cramfs
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - NIST-800-171-3.4.6
    - NIST-800-53-CM-6(a)
    - NIST-800-53-CM-7(a)
    - NIST-800-53-CM-7(b)
    - disable_strategy
    - kernel_module_cramfs_disabled
    - low_complexity
    - low_severity
    - medium_disruption
    - reboot_required

  - name: Ensure kernel module 'usb-storage' is disabled
    ansible.builtin.lineinfile:
      create: true
      dest: /etc/modprobe.d/usb-storage.conf
      regexp: install\s+usb-storage
      line: install usb-storage /bin/false
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL07-00-020100
    - 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-OL07-00-020100
    - NIST-800-171-3.1.21
    - NIST-800-53-CM-6(a)
    - NIST-800-53-CM-7(a)
    - NIST-800-53-CM-7(b)
    - NIST-800-53-MP-7
    - PCI-DSSv4-3.4
    - PCI-DSSv4-3.4.2
    - disable_strategy
    - kernel_module_usb-storage_disabled
    - low_complexity
    - medium_disruption
    - medium_severity
    - reboot_required

  - name: 'Add nodev Option to /dev/shm: Check information associated to mountpoint'
    ansible.builtin.command: findmnt  '/dev/shm'
    register: device_name
    failed_when: device_name.rc > 1
    changed_when: false
    check_mode: false
    when: ( not ( "kernel" in ansible_facts.packages and "rpm-ostree" in ansible_facts.packages
      and "bootc" in ansible_facts.packages and not "openshift-kubelet" in ansible_facts.packages
      and "ostree" in ansible_proc_cmdline ) and not ( ansible_virtualization_type
      in ["docker", "lxc", "openvz", "podman", "container"] ) )
    tags:
    - DISA-STIG-OL07-00-021024
    - NIST-800-53-AC-6
    - NIST-800-53-AC-6(1)
    - NIST-800-53-CM-6(a)
    - NIST-800-53-CM-7(a)
    - NIST-800-53-CM-7(b)
    - NIST-800-53-MP-7
    - configure_strategy
    - high_disruption
    - low_complexity
    - medium_severity
    - mount_option_dev_shm_nodev
    - no_reboot_needed

  - name: 'Add nodev Option to /dev/shm: Create mount_info dictionary variable'
    set_fact:
      mount_info: '{{ mount_info|default({})|combine({item.0: item.1}) }}'
    with_together:
    - '{{ device_name.stdout_lines[0].split() | map(''lower'') | list }}'
    - '{{ device_name.stdout_lines[1].split() | list }}'
    when:
    - ( not ( "kernel" in ansible_facts.packages and "rpm-ostree" in ansible_facts.packages
      and "bootc" in ansible_facts.packages and not "openshift-kubelet" in ansible_facts.packages
      and "ostree" in ansible_proc_cmdline ) and not ( ansible_virtualization_type
      in ["docker", "lxc", "openvz", "podman", "container"] ) )
    - device_name.stdout is defined and device_name.stdout_lines is defined
    - (device_name.stdout | length > 0)
    tags:
    - DISA-STIG-OL07-00-021024
    - NIST-800-53-AC-6
    - NIST-800-53-AC-6(1)
    - NIST-800-53-CM-6(a)
    - NIST-800-53-CM-7(a)
    - NIST-800-53-CM-7(b)
    - NIST-800-53-MP-7
    - configure_strategy
    - high_disruption
    - low_complexity
    - medium_severity
    - mount_option_dev_shm_nodev
    - no_reboot_needed

  - name: 'Add nodev Option to /dev/shm: If /dev/shm not mounted, craft mount_info
      manually'
    set_fact:
      mount_info: '{{ mount_info|default({})|combine({item.0: item.1}) }}'
    with_together:
    - - target
      - source
      - fstype
      - options
    - - /dev/shm
      - tmpfs
      - tmpfs
      - defaults
    when:
    - ( not ( "kernel" in ansible_facts.packages and "rpm-ostree" in ansible_facts.packages
      and "bootc" in ansible_facts.packages and not "openshift-kubelet" in ansible_facts.packages
      and "ostree" in ansible_proc_cmdline ) and not ( ansible_virtualization_type
      in ["docker", "lxc", "openvz", "podman", "container"] ) )
    - ("" | length == 0)
    - device_name.stdout is defined and device_name.stdout_lines is defined
    - (device_name.stdout | length == 0)
    tags:
    - DISA-STIG-OL07-00-021024
    - NIST-800-53-AC-6
    - NIST-800-53-AC-6(1)
    - NIST-800-53-CM-6(a)
    - NIST-800-53-CM-7(a)
    - NIST-800-53-CM-7(b)
    - NIST-800-53-MP-7
    - configure_strategy
    - high_disruption
    - low_complexity
    - medium_severity
    - mount_option_dev_shm_nodev
    - no_reboot_needed

  - name: 'Add nodev Option to /dev/shm: Make sure nodev option is part of the to
      /dev/shm options'
    set_fact:
      mount_info: '{{ mount_info | combine( {''options'':''''~(mount_info.options
        | default(''''))~('','' if (mount_info.options | default('''')) else '''')~''nodev''
        }) }}'
    when:
    - ( not ( "kernel" in ansible_facts.packages and "rpm-ostree" in ansible_facts.packages
      and "bootc" in ansible_facts.packages and not "openshift-kubelet" in ansible_facts.packages
      and "ostree" in ansible_proc_cmdline ) and not ( ansible_virtualization_type
      in ["docker", "lxc", "openvz", "podman", "container"] ) )
    - mount_info is defined and "nodev" not in (mount_info.options | default(''))
    tags:
    - DISA-STIG-OL07-00-021024
    - NIST-800-53-AC-6
    - NIST-800-53-AC-6(1)
    - NIST-800-53-CM-6(a)
    - NIST-800-53-CM-7(a)
    - NIST-800-53-CM-7(b)
    - NIST-800-53-MP-7
    - configure_strategy
    - high_disruption
    - low_complexity
    - medium_severity
    - mount_option_dev_shm_nodev
    - no_reboot_needed

  - name: 'Add nodev Option to /dev/shm: Ensure /dev/shm is mounted with nodev option'
    ansible.posix.mount:
      path: /dev/shm
      src: '{{ mount_info.source | default('''') }}'
      opts: '{{ mount_info.options | default('''') }}'
      state: mounted
      fstype: '{{ mount_info.fstype | default('''') }}'
    register: mount_result
    failed_when:
    - mount_result is failed
    - '''target is busy'' not in (mount_result.msg | default(''''))'
    - '''already mounted'' not in (mount_result.msg | default(''''))'
    when:
    - ( not ( "kernel" in ansible_facts.packages and "rpm-ostree" in ansible_facts.packages
      and "bootc" in ansible_facts.packages and not "openshift-kubelet" in ansible_facts.packages
      and "ostree" in ansible_proc_cmdline ) and not ( ansible_virtualization_type
      in ["docker", "lxc", "openvz", "podman", "container"] ) )
    - mount_info is defined
    - (device_name.stdout is defined and (device_name.stdout | length > 0)) or (""
      | length == 0)
    tags:
    - DISA-STIG-OL07-00-021024
    - NIST-800-53-AC-6
    - NIST-800-53-AC-6(1)
    - NIST-800-53-CM-6(a)
    - NIST-800-53-CM-7(a)
    - NIST-800-53-CM-7(b)
    - NIST-800-53-MP-7
    - configure_strategy
    - high_disruption
    - low_complexity
    - medium_severity
    - mount_option_dev_shm_nodev
    - no_reboot_needed

  - name: 'Add noexec Option to /dev/shm: Check information associated to mountpoint'
    ansible.builtin.command: findmnt  '/dev/shm'
    register: device_name
    failed_when: device_name.rc > 1
    changed_when: false
    check_mode: false
    when: ( not ( "kernel" in ansible_facts.packages and "rpm-ostree" in ansible_facts.packages
      and "bootc" in ansible_facts.packages and not "openshift-kubelet" in ansible_facts.packages
      and "ostree" in ansible_proc_cmdline ) and not ( ansible_virtualization_type
      in ["docker", "lxc", "openvz", "podman", "container"] ) )
    tags:
    - DISA-STIG-OL07-00-021024
    - NIST-800-53-AC-6
    - NIST-800-53-AC-6(1)
    - NIST-800-53-CM-6(a)
    - NIST-800-53-CM-7(a)
    - NIST-800-53-CM-7(b)
    - NIST-800-53-MP-7
    - configure_strategy
    - high_disruption
    - low_complexity
    - medium_severity
    - mount_option_dev_shm_noexec
    - no_reboot_needed

  - name: 'Add noexec Option to /dev/shm: Create mount_info dictionary variable'
    set_fact:
      mount_info: '{{ mount_info|default({})|combine({item.0: item.1}) }}'
    with_together:
    - '{{ device_name.stdout_lines[0].split() | map(''lower'') | list }}'
    - '{{ device_name.stdout_lines[1].split() | list }}'
    when:
    - ( not ( "kernel" in ansible_facts.packages and "rpm-ostree" in ansible_facts.packages
      and "bootc" in ansible_facts.packages and not "openshift-kubelet" in ansible_facts.packages
      and "ostree" in ansible_proc_cmdline ) and not ( ansible_virtualization_type
      in ["docker", "lxc", "openvz", "podman", "container"] ) )
    - device_name.stdout is defined and device_name.stdout_lines is defined
    - (device_name.stdout | length > 0)
    tags:
    - DISA-STIG-OL07-00-021024
    - NIST-800-53-AC-6
    - NIST-800-53-AC-6(1)
    - NIST-800-53-CM-6(a)
    - NIST-800-53-CM-7(a)
    - NIST-800-53-CM-7(b)
    - NIST-800-53-MP-7
    - configure_strategy
    - high_disruption
    - low_complexity
    - medium_severity
    - mount_option_dev_shm_noexec
    - no_reboot_needed

  - name: 'Add noexec Option to /dev/shm: If /dev/shm not mounted, craft mount_info
      manually'
    set_fact:
      mount_info: '{{ mount_info|default({})|combine({item.0: item.1}) }}'
    with_together:
    - - target
      - source
      - fstype
      - options
    - - /dev/shm
      - tmpfs
      - tmpfs
      - defaults
    when:
    - ( not ( "kernel" in ansible_facts.packages and "rpm-ostree" in ansible_facts.packages
      and "bootc" in ansible_facts.packages and not "openshift-kubelet" in ansible_facts.packages
      and "ostree" in ansible_proc_cmdline ) and not ( ansible_virtualization_type
      in ["docker", "lxc", "openvz", "podman", "container"] ) )
    - ("" | length == 0)
    - device_name.stdout is defined and device_name.stdout_lines is defined
    - (device_name.stdout | length == 0)
    tags:
    - DISA-STIG-OL07-00-021024
    - NIST-800-53-AC-6
    - NIST-800-53-AC-6(1)
    - NIST-800-53-CM-6(a)
    - NIST-800-53-CM-7(a)
    - NIST-800-53-CM-7(b)
    - NIST-800-53-MP-7
    - configure_strategy
    - high_disruption
    - low_complexity
    - medium_severity
    - mount_option_dev_shm_noexec
    - no_reboot_needed

  - name: 'Add noexec Option to /dev/shm: Make sure noexec option is part of the to
      /dev/shm options'
    set_fact:
      mount_info: '{{ mount_info | combine( {''options'':''''~(mount_info.options
        | default(''''))~('','' if (mount_info.options | default('''')) else '''')~''noexec''
        }) }}'
    when:
    - ( not ( "kernel" in ansible_facts.packages and "rpm-ostree" in ansible_facts.packages
      and "bootc" in ansible_facts.packages and not "openshift-kubelet" in ansible_facts.packages
      and "ostree" in ansible_proc_cmdline ) and not ( ansible_virtualization_type
      in ["docker", "lxc", "openvz", "podman", "container"] ) )
    - mount_info is defined and "noexec" not in (mount_info.options | default(''))
    tags:
    - DISA-STIG-OL07-00-021024
    - NIST-800-53-AC-6
    - NIST-800-53-AC-6(1)
    - NIST-800-53-CM-6(a)
    - NIST-800-53-CM-7(a)
    - NIST-800-53-CM-7(b)
    - NIST-800-53-MP-7
    - configure_strategy
    - high_disruption
    - low_complexity
    - medium_severity
    - mount_option_dev_shm_noexec
    - no_reboot_needed

  - name: 'Add noexec Option to /dev/shm: Ensure /dev/shm is mounted with noexec option'
    ansible.posix.mount:
      path: /dev/shm
      src: '{{ mount_info.source | default('''') }}'
      opts: '{{ mount_info.options | default('''') }}'
      state: mounted
      fstype: '{{ mount_info.fstype | default('''') }}'
    register: mount_result
    failed_when:
    - mount_result is failed
    - '''target is busy'' not in (mount_result.msg | default(''''))'
    - '''already mounted'' not in (mount_result.msg | default(''''))'
    when:
    - ( not ( "kernel" in ansible_facts.packages and "rpm-ostree" in ansible_facts.packages
      and "bootc" in ansible_facts.packages and not "openshift-kubelet" in ansible_facts.packages
      and "ostree" in ansible_proc_cmdline ) and not ( ansible_virtualization_type
      in ["docker", "lxc", "openvz", "podman", "container"] ) )
    - mount_info is defined
    - (device_name.stdout is defined and (device_name.stdout | length > 0)) or (""
      | length == 0)
    tags:
    - DISA-STIG-OL07-00-021024
    - NIST-800-53-AC-6
    - NIST-800-53-AC-6(1)
    - NIST-800-53-CM-6(a)
    - NIST-800-53-CM-7(a)
    - NIST-800-53-CM-7(b)
    - NIST-800-53-MP-7
    - configure_strategy
    - high_disruption
    - low_complexity
    - medium_severity
    - mount_option_dev_shm_noexec
    - no_reboot_needed

  - name: 'Add nosuid Option to /dev/shm: Check information associated to mountpoint'
    ansible.builtin.command: findmnt  '/dev/shm'
    register: device_name
    failed_when: device_name.rc > 1
    changed_when: false
    check_mode: false
    when: ( not ( "kernel" in ansible_facts.packages and "rpm-ostree" in ansible_facts.packages
      and "bootc" in ansible_facts.packages and not "openshift-kubelet" in ansible_facts.packages
      and "ostree" in ansible_proc_cmdline ) and not ( ansible_virtualization_type
      in ["docker", "lxc", "openvz", "podman", "container"] ) )
    tags:
    - DISA-STIG-OL07-00-021024
    - NIST-800-53-AC-6
    - NIST-800-53-AC-6(1)
    - NIST-800-53-CM-6(a)
    - NIST-800-53-CM-7(a)
    - NIST-800-53-CM-7(b)
    - NIST-800-53-MP-7
    - configure_strategy
    - high_disruption
    - low_complexity
    - medium_severity
    - mount_option_dev_shm_nosuid
    - no_reboot_needed

  - name: 'Add nosuid Option to /dev/shm: Create mount_info dictionary variable'
    set_fact:
      mount_info: '{{ mount_info|default({})|combine({item.0: item.1}) }}'
    with_together:
    - '{{ device_name.stdout_lines[0].split() | map(''lower'') | list }}'
    - '{{ device_name.stdout_lines[1].split() | list }}'
    when:
    - ( not ( "kernel" in ansible_facts.packages and "rpm-ostree" in ansible_facts.packages
      and "bootc" in ansible_facts.packages and not "openshift-kubelet" in ansible_facts.packages
      and "ostree" in ansible_proc_cmdline ) and not ( ansible_virtualization_type
      in ["docker", "lxc", "openvz", "podman", "container"] ) )
    - device_name.stdout is defined and device_name.stdout_lines is defined
    - (device_name.stdout | length > 0)
    tags:
    - DISA-STIG-OL07-00-021024
    - NIST-800-53-AC-6
    - NIST-800-53-AC-6(1)
    - NIST-800-53-CM-6(a)
    - NIST-800-53-CM-7(a)
    - NIST-800-53-CM-7(b)
    - NIST-800-53-MP-7
    - configure_strategy
    - high_disruption
    - low_complexity
    - medium_severity
    - mount_option_dev_shm_nosuid
    - no_reboot_needed

  - name: 'Add nosuid Option to /dev/shm: If /dev/shm not mounted, craft mount_info
      manually'
    set_fact:
      mount_info: '{{ mount_info|default({})|combine({item.0: item.1}) }}'
    with_together:
    - - target
      - source
      - fstype
      - options
    - - /dev/shm
      - tmpfs
      - tmpfs
      - defaults
    when:
    - ( not ( "kernel" in ansible_facts.packages and "rpm-ostree" in ansible_facts.packages
      and "bootc" in ansible_facts.packages and not "openshift-kubelet" in ansible_facts.packages
      and "ostree" in ansible_proc_cmdline ) and not ( ansible_virtualization_type
      in ["docker", "lxc", "openvz", "podman", "container"] ) )
    - ("" | length == 0)
    - device_name.stdout is defined and device_name.stdout_lines is defined
    - (device_name.stdout | length == 0)
    tags:
    - DISA-STIG-OL07-00-021024
    - NIST-800-53-AC-6
    - NIST-800-53-AC-6(1)
    - NIST-800-53-CM-6(a)
    - NIST-800-53-CM-7(a)
    - NIST-800-53-CM-7(b)
    - NIST-800-53-MP-7
    - configure_strategy
    - high_disruption
    - low_complexity
    - medium_severity
    - mount_option_dev_shm_nosuid
    - no_reboot_needed

  - name: 'Add nosuid Option to /dev/shm: Make sure nosuid option is part of the to
      /dev/shm options'
    set_fact:
      mount_info: '{{ mount_info | combine( {''options'':''''~(mount_info.options
        | default(''''))~('','' if (mount_info.options | default('''')) else '''')~''nosuid''
        }) }}'
    when:
    - ( not ( "kernel" in ansible_facts.packages and "rpm-ostree" in ansible_facts.packages
      and "bootc" in ansible_facts.packages and not "openshift-kubelet" in ansible_facts.packages
      and "ostree" in ansible_proc_cmdline ) and not ( ansible_virtualization_type
      in ["docker", "lxc", "openvz", "podman", "container"] ) )
    - mount_info is defined and "nosuid" not in (mount_info.options | default(''))
    tags:
    - DISA-STIG-OL07-00-021024
    - NIST-800-53-AC-6
    - NIST-800-53-AC-6(1)
    - NIST-800-53-CM-6(a)
    - NIST-800-53-CM-7(a)
    - NIST-800-53-CM-7(b)
    - NIST-800-53-MP-7
    - configure_strategy
    - high_disruption
    - low_complexity
    - medium_severity
    - mount_option_dev_shm_nosuid
    - no_reboot_needed

  - name: 'Add nosuid Option to /dev/shm: Ensure /dev/shm is mounted with nosuid option'
    ansible.posix.mount:
      path: /dev/shm
      src: '{{ mount_info.source | default('''') }}'
      opts: '{{ mount_info.options | default('''') }}'
      state: mounted
      fstype: '{{ mount_info.fstype | default('''') }}'
    register: mount_result
    failed_when:
    - mount_result is failed
    - '''target is busy'' not in (mount_result.msg | default(''''))'
    - '''already mounted'' not in (mount_result.msg | default(''''))'
    when:
    - ( not ( "kernel" in ansible_facts.packages and "rpm-ostree" in ansible_facts.packages
      and "bootc" in ansible_facts.packages and not "openshift-kubelet" in ansible_facts.packages
      and "ostree" in ansible_proc_cmdline ) and not ( ansible_virtualization_type
      in ["docker", "lxc", "openvz", "podman", "container"] ) )
    - mount_info is defined
    - (device_name.stdout is defined and (device_name.stdout | length > 0)) or (""
      | length == 0)
    tags:
    - DISA-STIG-OL07-00-021024
    - NIST-800-53-AC-6
    - NIST-800-53-AC-6(1)
    - NIST-800-53-CM-6(a)
    - NIST-800-53-CM-7(a)
    - NIST-800-53-CM-7(b)
    - NIST-800-53-MP-7
    - configure_strategy
    - high_disruption
    - low_complexity
    - medium_severity
    - mount_option_dev_shm_nosuid
    - no_reboot_needed

  - name: Add nodev Option to /home - Initialize variables
    ansible.builtin.set_fact:
      non_allowed_partitions:
      - /
      - /lib
      - /opt
      - /usr
      - /bin
      - /sbin
      - /boot
      - /dev
      - /proc
      home_directories: []
      allowed_mount_point: []
      fstab_mount_point_info: []
    when:
    - ( not ( "kernel" in ansible_facts.packages and "rpm-ostree" in ansible_facts.packages
      and "bootc" in ansible_facts.packages and not "openshift-kubelet" in ansible_facts.packages
      and "ostree" in ansible_proc_cmdline ) and not ( ansible_virtualization_type
      in ["docker", "lxc", "openvz", "podman", "container"] ) )
    - '"/home" in ansible_mounts | map(attribute="mount") | list'
    tags:
    - configure_strategy
    - high_disruption
    - low_complexity
    - mount_option_home_nodev
    - no_reboot_needed
    - unknown_severity

  - name: Add nodev Option to /home - Get home directories from passwd
    ansible.builtin.getent:
      database: passwd
    when:
    - ( not ( "kernel" in ansible_facts.packages and "rpm-ostree" in ansible_facts.packages
      and "bootc" in ansible_facts.packages and not "openshift-kubelet" in ansible_facts.packages
      and "ostree" in ansible_proc_cmdline ) and not ( ansible_virtualization_type
      in ["docker", "lxc", "openvz", "podman", "container"] ) )
    - '"/home" in ansible_mounts | map(attribute="mount") | list'
    tags:
    - configure_strategy
    - high_disruption
    - low_complexity
    - mount_option_home_nodev
    - no_reboot_needed
    - unknown_severity

  - name: Add nodev Option to /home - Filter home directories based on UID range
    ansible.builtin.set_fact:
      home_directories: '{{ home_directories + [item.data[4]] }}'
    when:
    - ( not ( "kernel" in ansible_facts.packages and "rpm-ostree" in ansible_facts.packages
      and "bootc" in ansible_facts.packages and not "openshift-kubelet" in ansible_facts.packages
      and "ostree" in ansible_proc_cmdline ) and not ( ansible_virtualization_type
      in ["docker", "lxc", "openvz", "podman", "container"] ) )
    - '"/home" in ansible_mounts | map(attribute="mount") | list'
    - item.data[4] is defined
    - item.data[2]|int >= 1000
    - item.data[2]|int != 65534
    - item.data[4] not in non_allowed_partitions
    with_items: '{{ ansible_facts.getent_passwd | dict2items(key_name=''user'', value_name=''data'')}}'
    tags:
    - configure_strategy
    - high_disruption
    - low_complexity
    - mount_option_home_nodev
    - no_reboot_needed
    - unknown_severity

  - name: Add nodev Option to /home - Gather mount points
    ansible.builtin.setup:
      filter: ansible_mounts
    when:
    - ( not ( "kernel" in ansible_facts.packages and "rpm-ostree" in ansible_facts.packages
      and "bootc" in ansible_facts.packages and not "openshift-kubelet" in ansible_facts.packages
      and "ostree" in ansible_proc_cmdline ) and not ( ansible_virtualization_type
      in ["docker", "lxc", "openvz", "podman", "container"] ) )
    - '"/home" in ansible_mounts | map(attribute="mount") | list'
    tags:
    - configure_strategy
    - high_disruption
    - low_complexity
    - mount_option_home_nodev
    - no_reboot_needed
    - unknown_severity

  - name: Add nodev Option to /home - Ensure mount options for home directories
    block:

    - name: ' Add nodev Option to /home - Obtain mount point using df and shell'
      ansible.builtin.shell: |
        df {{ item }} | awk '/^\/dev/ {print $6}'
      register: df_output
      with_items: '{{ home_directories }}'

    - name: Add nodev Option to /home - Set mount point for each home directory
      ansible.builtin.set_fact:
        allowed_mount_point: '{{ allowed_mount_point + [item.stdout_lines[0]] }}'
      with_items: '{{ df_output.results }}'
      when:
      - item.stdout_lines is defined
      - item.stdout_lines | length > 0
      - item.stdout_lines[0] != ""

    - name: Add nodev Option to /home - Obtain full mount information for allowed
        mount point
      ansible.builtin.set_fact:
        fstab_mount_point_info: '{{ fstab_mount_point_info + [ ansible_mounts | selectattr(''mount'',
          ''equalto'', item) | first ]}}'
      with_items: '{{ allowed_mount_point }}'
      when: allowed_mount_point is defined

    - name: Add nodev Option to /home - Ensure mount option nodev is in fstab for
        allowed mount point
      ansible.posix.mount:
        path: '{{ item.mount }}'
        src: '{{ item.device }}'
        opts: '{{ item.options }},nodev'
        state: mounted
        fstype: '{{ item.fstype }}'
      with_items: '{{ fstab_mount_point_info }}'
      when:
      - allowed_mount_point is defined
      - item.mount not in non_allowed_partitions
      - '''nodev'' not in item.options'
    when:
    - ( not ( "kernel" in ansible_facts.packages and "rpm-ostree" in ansible_facts.packages
      and "bootc" in ansible_facts.packages and not "openshift-kubelet" in ansible_facts.packages
      and "ostree" in ansible_proc_cmdline ) and not ( ansible_virtualization_type
      in ["docker", "lxc", "openvz", "podman", "container"] ) )
    - '"/home" in ansible_mounts | map(attribute="mount") | list'
    tags:
    - configure_strategy
    - high_disruption
    - low_complexity
    - mount_option_home_nodev
    - no_reboot_needed
    - unknown_severity

  - name: Add nosuid Option to /home - Initialize variables
    ansible.builtin.set_fact:
      non_allowed_partitions:
      - /
      - /lib
      - /opt
      - /usr
      - /bin
      - /sbin
      - /boot
      - /dev
      - /proc
      home_directories: []
      allowed_mount_point: []
      fstab_mount_point_info: []
    when: ( not ( "kernel" in ansible_facts.packages and "rpm-ostree" in ansible_facts.packages
      and "bootc" in ansible_facts.packages and not "openshift-kubelet" in ansible_facts.packages
      and "ostree" in ansible_proc_cmdline ) and not ( ansible_virtualization_type
      in ["docker", "lxc", "openvz", "podman", "container"] ) )
    tags:
    - DISA-STIG-OL07-00-021000
    - NIST-800-53-AC-6
    - NIST-800-53-AC-6(1)
    - NIST-800-53-CM-6(a)
    - NIST-800-53-CM-7(a)
    - NIST-800-53-CM-7(b)
    - NIST-800-53-MP-7
    - configure_strategy
    - high_disruption
    - low_complexity
    - medium_severity
    - mount_option_home_nosuid
    - no_reboot_needed

  - name: Add nosuid Option to /home - Get home directories from passwd
    ansible.builtin.getent:
      database: passwd
    when: ( not ( "kernel" in ansible_facts.packages and "rpm-ostree" in ansible_facts.packages
      and "bootc" in ansible_facts.packages and not "openshift-kubelet" in ansible_facts.packages
      and "ostree" in ansible_proc_cmdline ) and not ( ansible_virtualization_type
      in ["docker", "lxc", "openvz", "podman", "container"] ) )
    tags:
    - DISA-STIG-OL07-00-021000
    - NIST-800-53-AC-6
    - NIST-800-53-AC-6(1)
    - NIST-800-53-CM-6(a)
    - NIST-800-53-CM-7(a)
    - NIST-800-53-CM-7(b)
    - NIST-800-53-MP-7
    - configure_strategy
    - high_disruption
    - low_complexity
    - medium_severity
    - mount_option_home_nosuid
    - no_reboot_needed

  - name: Add nosuid Option to /home - Filter home directories based on UID range
    ansible.builtin.set_fact:
      home_directories: '{{ home_directories + [item.data[4]] }}'
    when:
    - ( not ( "kernel" in ansible_facts.packages and "rpm-ostree" in ansible_facts.packages
      and "bootc" in ansible_facts.packages and not "openshift-kubelet" in ansible_facts.packages
      and "ostree" in ansible_proc_cmdline ) and not ( ansible_virtualization_type
      in ["docker", "lxc", "openvz", "podman", "container"] ) )
    - item.data[4] is defined
    - item.data[2]|int >= 1000
    - item.data[2]|int != 65534
    - item.data[4] not in non_allowed_partitions
    with_items: '{{ ansible_facts.getent_passwd | dict2items(key_name=''user'', value_name=''data'')}}'
    tags:
    - DISA-STIG-OL07-00-021000
    - NIST-800-53-AC-6
    - NIST-800-53-AC-6(1)
    - NIST-800-53-CM-6(a)
    - NIST-800-53-CM-7(a)
    - NIST-800-53-CM-7(b)
    - NIST-800-53-MP-7
    - configure_strategy
    - high_disruption
    - low_complexity
    - medium_severity
    - mount_option_home_nosuid
    - no_reboot_needed

  - name: Add nosuid Option to /home - Gather mount points
    ansible.builtin.setup:
      filter: ansible_mounts
    when: ( not ( "kernel" in ansible_facts.packages and "rpm-ostree" in ansible_facts.packages
      and "bootc" in ansible_facts.packages and not "openshift-kubelet" in ansible_facts.packages
      and "ostree" in ansible_proc_cmdline ) and not ( ansible_virtualization_type
      in ["docker", "lxc", "openvz", "podman", "container"] ) )
    tags:
    - DISA-STIG-OL07-00-021000
    - NIST-800-53-AC-6
    - NIST-800-53-AC-6(1)
    - NIST-800-53-CM-6(a)
    - NIST-800-53-CM-7(a)
    - NIST-800-53-CM-7(b)
    - NIST-800-53-MP-7
    - configure_strategy
    - high_disruption
    - low_complexity
    - medium_severity
    - mount_option_home_nosuid
    - no_reboot_needed

  - name: Add nosuid Option to /home - Ensure mount options for home directories
    block:

    - name: ' Add nosuid Option to /home - Obtain mount point using df and shell'
      ansible.builtin.shell: |
        df {{ item }} | awk '/^\/dev/ {print $6}'
      register: df_output
      with_items: '{{ home_directories }}'

    - name: Add nosuid Option to /home - Set mount point for each home directory
      ansible.builtin.set_fact:
        allowed_mount_point: '{{ allowed_mount_point + [item.stdout_lines[0]] }}'
      with_items: '{{ df_output.results }}'
      when:
      - item.stdout_lines is defined
      - item.stdout_lines | length > 0
      - item.stdout_lines[0] != ""

    - name: Add nosuid Option to /home - Obtain full mount information for allowed
        mount point
      ansible.builtin.set_fact:
        fstab_mount_point_info: '{{ fstab_mount_point_info + [ ansible_mounts | selectattr(''mount'',
          ''equalto'', item) | first ]}}'
      with_items: '{{ allowed_mount_point }}'
      when: allowed_mount_point is defined

    - name: Add nosuid Option to /home - Ensure mount option nosuid is in fstab for
        allowed mount point
      ansible.posix.mount:
        path: '{{ item.mount }}'
        src: '{{ item.device }}'
        opts: '{{ item.options }},nosuid'
        state: mounted
        fstype: '{{ item.fstype }}'
      with_items: '{{ fstab_mount_point_info }}'
      when:
      - allowed_mount_point is defined
      - item.mount not in non_allowed_partitions
      - '''nosuid'' not in item.options'
    when: ( not ( "kernel" in ansible_facts.packages and "rpm-ostree" in ansible_facts.packages
      and "bootc" in ansible_facts.packages and not "openshift-kubelet" in ansible_facts.packages
      and "ostree" in ansible_proc_cmdline ) and not ( ansible_virtualization_type
      in ["docker", "lxc", "openvz", "podman", "container"] ) )
    tags:
    - DISA-STIG-OL07-00-021000
    - NIST-800-53-AC-6
    - NIST-800-53-AC-6(1)
    - NIST-800-53-CM-6(a)
    - NIST-800-53-CM-7(a)
    - NIST-800-53-CM-7(b)
    - NIST-800-53-MP-7
    - configure_strategy
    - high_disruption
    - low_complexity
    - medium_severity
    - mount_option_home_nosuid
    - no_reboot_needed

  - name: 'Add nodev Option to /tmp: Check information associated to mountpoint'
    ansible.builtin.command: findmnt --fstab '/tmp'
    register: device_name
    failed_when: device_name.rc > 1
    changed_when: false
    check_mode: false
    when:
    - ( not ( "kernel" in ansible_facts.packages and "rpm-ostree" in ansible_facts.packages
      and "bootc" in ansible_facts.packages and not "openshift-kubelet" in ansible_facts.packages
      and "ostree" in ansible_proc_cmdline ) and not ( ansible_virtualization_type
      in ["docker", "lxc", "openvz", "podman", "container"] ) )
    - '"/tmp" in ansible_mounts | map(attribute="mount") | list'
    tags:
    - NIST-800-53-AC-6
    - NIST-800-53-AC-6(1)
    - NIST-800-53-CM-6(a)
    - NIST-800-53-CM-7(a)
    - NIST-800-53-CM-7(b)
    - NIST-800-53-MP-7
    - configure_strategy
    - high_disruption
    - low_complexity
    - medium_severity
    - mount_option_tmp_nodev
    - no_reboot_needed

  - name: 'Add nodev Option to /tmp: Create mount_info dictionary variable'
    set_fact:
      mount_info: '{{ mount_info|default({})|combine({item.0: item.1}) }}'
    with_together:
    - '{{ device_name.stdout_lines[0].split() | map(''lower'') | list }}'
    - '{{ device_name.stdout_lines[1].split() | list }}'
    when:
    - ( not ( "kernel" in ansible_facts.packages and "rpm-ostree" in ansible_facts.packages
      and "bootc" in ansible_facts.packages and not "openshift-kubelet" in ansible_facts.packages
      and "ostree" in ansible_proc_cmdline ) and not ( ansible_virtualization_type
      in ["docker", "lxc", "openvz", "podman", "container"] ) )
    - '"/tmp" in ansible_mounts | map(attribute="mount") | list'
    - device_name.stdout is defined and device_name.stdout_lines is defined
    - (device_name.stdout | length > 0)
    tags:
    - NIST-800-53-AC-6
    - NIST-800-53-AC-6(1)
    - NIST-800-53-CM-6(a)
    - NIST-800-53-CM-7(a)
    - NIST-800-53-CM-7(b)
    - NIST-800-53-MP-7
    - configure_strategy
    - high_disruption
    - low_complexity
    - medium_severity
    - mount_option_tmp_nodev
    - no_reboot_needed

  - name: 'Add nodev Option to /tmp: If /tmp not mounted, craft mount_info manually'
    set_fact:
      mount_info: '{{ mount_info|default({})|combine({item.0: item.1}) }}'
    with_together:
    - - target
      - source
      - fstype
      - options
    - - /tmp
      - ''
      - ''
      - defaults
    when:
    - ( not ( "kernel" in ansible_facts.packages and "rpm-ostree" in ansible_facts.packages
      and "bootc" in ansible_facts.packages and not "openshift-kubelet" in ansible_facts.packages
      and "ostree" in ansible_proc_cmdline ) and not ( ansible_virtualization_type
      in ["docker", "lxc", "openvz", "podman", "container"] ) )
    - '"/tmp" in ansible_mounts | map(attribute="mount") | list'
    - ("--fstab" | length == 0)
    - device_name.stdout is defined and device_name.stdout_lines is defined
    - (device_name.stdout | length == 0)
    tags:
    - NIST-800-53-AC-6
    - NIST-800-53-AC-6(1)
    - NIST-800-53-CM-6(a)
    - NIST-800-53-CM-7(a)
    - NIST-800-53-CM-7(b)
    - NIST-800-53-MP-7
    - configure_strategy
    - high_disruption
    - low_complexity
    - medium_severity
    - mount_option_tmp_nodev
    - no_reboot_needed

  - name: 'Add nodev Option to /tmp: Make sure nodev option is part of the to /tmp
      options'
    set_fact:
      mount_info: '{{ mount_info | combine( {''options'':''''~(mount_info.options
        | default(''''))~('','' if (mount_info.options | default('''')) else '''')~''nodev''
        }) }}'
    when:
    - ( not ( "kernel" in ansible_facts.packages and "rpm-ostree" in ansible_facts.packages
      and "bootc" in ansible_facts.packages and not "openshift-kubelet" in ansible_facts.packages
      and "ostree" in ansible_proc_cmdline ) and not ( ansible_virtualization_type
      in ["docker", "lxc", "openvz", "podman", "container"] ) )
    - '"/tmp" in ansible_mounts | map(attribute="mount") | list'
    - mount_info is defined and "nodev" not in (mount_info.options | default(''))
    tags:
    - NIST-800-53-AC-6
    - NIST-800-53-AC-6(1)
    - NIST-800-53-CM-6(a)
    - NIST-800-53-CM-7(a)
    - NIST-800-53-CM-7(b)
    - NIST-800-53-MP-7
    - configure_strategy
    - high_disruption
    - low_complexity
    - medium_severity
    - mount_option_tmp_nodev
    - no_reboot_needed

  - name: 'Add nodev Option to /tmp: Ensure /tmp is mounted with nodev option'
    ansible.posix.mount:
      path: /tmp
      src: '{{ mount_info.source | default('''') }}'
      opts: '{{ mount_info.options | default('''') }}'
      state: mounted
      fstype: '{{ mount_info.fstype | default('''') }}'
    register: mount_result
    failed_when:
    - mount_result is failed
    - '''target is busy'' not in (mount_result.msg | default(''''))'
    - '''already mounted'' not in (mount_result.msg | default(''''))'
    when:
    - ( not ( "kernel" in ansible_facts.packages and "rpm-ostree" in ansible_facts.packages
      and "bootc" in ansible_facts.packages and not "openshift-kubelet" in ansible_facts.packages
      and "ostree" in ansible_proc_cmdline ) and not ( ansible_virtualization_type
      in ["docker", "lxc", "openvz", "podman", "container"] ) )
    - '"/tmp" in ansible_mounts | map(attribute="mount") | list'
    - mount_info is defined
    - (device_name.stdout is defined and (device_name.stdout | length > 0)) or ("--fstab"
      | length == 0)
    tags:
    - NIST-800-53-AC-6
    - NIST-800-53-AC-6(1)
    - NIST-800-53-CM-6(a)
    - NIST-800-53-CM-7(a)
    - NIST-800-53-CM-7(b)
    - NIST-800-53-MP-7
    - configure_strategy
    - high_disruption
    - low_complexity
    - medium_severity
    - mount_option_tmp_nodev
    - no_reboot_needed

  - name: 'Add noexec Option to /tmp: Check information associated to mountpoint'
    ansible.builtin.command: findmnt --fstab '/tmp'
    register: device_name
    failed_when: device_name.rc > 1
    changed_when: false
    check_mode: false
    when:
    - ( not ( "kernel" in ansible_facts.packages and "rpm-ostree" in ansible_facts.packages
      and "bootc" in ansible_facts.packages and not "openshift-kubelet" in ansible_facts.packages
      and "ostree" in ansible_proc_cmdline ) and not ( ansible_virtualization_type
      in ["docker", "lxc", "openvz", "podman", "container"] ) )
    - '"/tmp" in ansible_mounts | map(attribute="mount") | list'
    tags:
    - NIST-800-53-AC-6
    - NIST-800-53-AC-6(1)
    - NIST-800-53-CM-6(a)
    - NIST-800-53-CM-7(a)
    - NIST-800-53-CM-7(b)
    - NIST-800-53-MP-7
    - configure_strategy
    - high_disruption
    - low_complexity
    - medium_severity
    - mount_option_tmp_noexec
    - no_reboot_needed

  - name: 'Add noexec Option to /tmp: Create mount_info dictionary variable'
    set_fact:
      mount_info: '{{ mount_info|default({})|combine({item.0: item.1}) }}'
    with_together:
    - '{{ device_name.stdout_lines[0].split() | map(''lower'') | list }}'
    - '{{ device_name.stdout_lines[1].split() | list }}'
    when:
    - ( not ( "kernel" in ansible_facts.packages and "rpm-ostree" in ansible_facts.packages
      and "bootc" in ansible_facts.packages and not "openshift-kubelet" in ansible_facts.packages
      and "ostree" in ansible_proc_cmdline ) and not ( ansible_virtualization_type
      in ["docker", "lxc", "openvz", "podman", "container"] ) )
    - '"/tmp" in ansible_mounts | map(attribute="mount") | list'
    - device_name.stdout is defined and device_name.stdout_lines is defined
    - (device_name.stdout | length > 0)
    tags:
    - NIST-800-53-AC-6
    - NIST-800-53-AC-6(1)
    - NIST-800-53-CM-6(a)
    - NIST-800-53-CM-7(a)
    - NIST-800-53-CM-7(b)
    - NIST-800-53-MP-7
    - configure_strategy
    - high_disruption
    - low_complexity
    - medium_severity
    - mount_option_tmp_noexec
    - no_reboot_needed

  - name: 'Add noexec Option to /tmp: If /tmp not mounted, craft mount_info manually'
    set_fact:
      mount_info: '{{ mount_info|default({})|combine({item.0: item.1}) }}'
    with_together:
    - - target
      - source
      - fstype
      - options
    - - /tmp
      - ''
      - ''
      - defaults
    when:
    - ( not ( "kernel" in ansible_facts.packages and "rpm-ostree" in ansible_facts.packages
      and "bootc" in ansible_facts.packages and not "openshift-kubelet" in ansible_facts.packages
      and "ostree" in ansible_proc_cmdline ) and not ( ansible_virtualization_type
      in ["docker", "lxc", "openvz", "podman", "container"] ) )
    - '"/tmp" in ansible_mounts | map(attribute="mount") | list'
    - ("--fstab" | length == 0)
    - device_name.stdout is defined and device_name.stdout_lines is defined
    - (device_name.stdout | length == 0)
    tags:
    - NIST-800-53-AC-6
    - NIST-800-53-AC-6(1)
    - NIST-800-53-CM-6(a)
    - NIST-800-53-CM-7(a)
    - NIST-800-53-CM-7(b)
    - NIST-800-53-MP-7
    - configure_strategy
    - high_disruption
    - low_complexity
    - medium_severity
    - mount_option_tmp_noexec
    - no_reboot_needed

  - name: 'Add noexec Option to /tmp: Make sure noexec option is part of the to /tmp
      options'
    set_fact:
      mount_info: '{{ mount_info | combine( {''options'':''''~(mount_info.options
        | default(''''))~('','' if (mount_info.options | default('''')) else '''')~''noexec''
        }) }}'
    when:
    - ( not ( "kernel" in ansible_facts.packages and "rpm-ostree" in ansible_facts.packages
      and "bootc" in ansible_facts.packages and not "openshift-kubelet" in ansible_facts.packages
      and "ostree" in ansible_proc_cmdline ) and not ( ansible_virtualization_type
      in ["docker", "lxc", "openvz", "podman", "container"] ) )
    - '"/tmp" in ansible_mounts | map(attribute="mount") | list'
    - mount_info is defined and "noexec" not in (mount_info.options | default(''))
    tags:
    - NIST-800-53-AC-6
    - NIST-800-53-AC-6(1)
    - NIST-800-53-CM-6(a)
    - NIST-800-53-CM-7(a)
    - NIST-800-53-CM-7(b)
    - NIST-800-53-MP-7
    - configure_strategy
    - high_disruption
    - low_complexity
    - medium_severity
    - mount_option_tmp_noexec
    - no_reboot_needed

  - name: 'Add noexec Option to /tmp: Ensure /tmp is mounted with noexec option'
    ansible.posix.mount:
      path: /tmp
      src: '{{ mount_info.source | default('''') }}'
      opts: '{{ mount_info.options | default('''') }}'
      state: mounted
      fstype: '{{ mount_info.fstype | default('''') }}'
    register: mount_result
    failed_when:
    - mount_result is failed
    - '''target is busy'' not in (mount_result.msg | default(''''))'
    - '''already mounted'' not in (mount_result.msg | default(''''))'
    when:
    - ( not ( "kernel" in ansible_facts.packages and "rpm-ostree" in ansible_facts.packages
      and "bootc" in ansible_facts.packages and not "openshift-kubelet" in ansible_facts.packages
      and "ostree" in ansible_proc_cmdline ) and not ( ansible_virtualization_type
      in ["docker", "lxc", "openvz", "podman", "container"] ) )
    - '"/tmp" in ansible_mounts | map(attribute="mount") | list'
    - mount_info is defined
    - (device_name.stdout is defined and (device_name.stdout | length > 0)) or ("--fstab"
      | length == 0)
    tags:
    - NIST-800-53-AC-6
    - NIST-800-53-AC-6(1)
    - NIST-800-53-CM-6(a)
    - NIST-800-53-CM-7(a)
    - NIST-800-53-CM-7(b)
    - NIST-800-53-MP-7
    - configure_strategy
    - high_disruption
    - low_complexity
    - medium_severity
    - mount_option_tmp_noexec
    - no_reboot_needed

  - name: 'Add nosuid Option to /tmp: Check information associated to mountpoint'
    ansible.builtin.command: findmnt --fstab '/tmp'
    register: device_name
    failed_when: device_name.rc > 1
    changed_when: false
    check_mode: false
    when:
    - ( not ( "kernel" in ansible_facts.packages and "rpm-ostree" in ansible_facts.packages
      and "bootc" in ansible_facts.packages and not "openshift-kubelet" in ansible_facts.packages
      and "ostree" in ansible_proc_cmdline ) and not ( ansible_virtualization_type
      in ["docker", "lxc", "openvz", "podman", "container"] ) )
    - '"/tmp" in ansible_mounts | map(attribute="mount") | list'
    tags:
    - NIST-800-53-AC-6
    - NIST-800-53-AC-6(1)
    - NIST-800-53-CM-6(a)
    - NIST-800-53-CM-7(a)
    - NIST-800-53-CM-7(b)
    - NIST-800-53-MP-7
    - configure_strategy
    - high_disruption
    - low_complexity
    - medium_severity
    - mount_option_tmp_nosuid
    - no_reboot_needed

  - name: 'Add nosuid Option to /tmp: Create mount_info dictionary variable'
    set_fact:
      mount_info: '{{ mount_info|default({})|combine({item.0: item.1}) }}'
    with_together:
    - '{{ device_name.stdout_lines[0].split() | map(''lower'') | list }}'
    - '{{ device_name.stdout_lines[1].split() | list }}'
    when:
    - ( not ( "kernel" in ansible_facts.packages and "rpm-ostree" in ansible_facts.packages
      and "bootc" in ansible_facts.packages and not "openshift-kubelet" in ansible_facts.packages
      and "ostree" in ansible_proc_cmdline ) and not ( ansible_virtualization_type
      in ["docker", "lxc", "openvz", "podman", "container"] ) )
    - '"/tmp" in ansible_mounts | map(attribute="mount") | list'
    - device_name.stdout is defined and device_name.stdout_lines is defined
    - (device_name.stdout | length > 0)
    tags:
    - NIST-800-53-AC-6
    - NIST-800-53-AC-6(1)
    - NIST-800-53-CM-6(a)
    - NIST-800-53-CM-7(a)
    - NIST-800-53-CM-7(b)
    - NIST-800-53-MP-7
    - configure_strategy
    - high_disruption
    - low_complexity
    - medium_severity
    - mount_option_tmp_nosuid
    - no_reboot_needed

  - name: 'Add nosuid Option to /tmp: If /tmp not mounted, craft mount_info manually'
    set_fact:
      mount_info: '{{ mount_info|default({})|combine({item.0: item.1}) }}'
    with_together:
    - - target
      - source
      - fstype
      - options
    - - /tmp
      - ''
      - ''
      - defaults
    when:
    - ( not ( "kernel" in ansible_facts.packages and "rpm-ostree" in ansible_facts.packages
      and "bootc" in ansible_facts.packages and not "openshift-kubelet" in ansible_facts.packages
      and "ostree" in ansible_proc_cmdline ) and not ( ansible_virtualization_type
      in ["docker", "lxc", "openvz", "podman", "container"] ) )
    - '"/tmp" in ansible_mounts | map(attribute="mount") | list'
    - ("--fstab" | length == 0)
    - device_name.stdout is defined and device_name.stdout_lines is defined
    - (device_name.stdout | length == 0)
    tags:
    - NIST-800-53-AC-6
    - NIST-800-53-AC-6(1)
    - NIST-800-53-CM-6(a)
    - NIST-800-53-CM-7(a)
    - NIST-800-53-CM-7(b)
    - NIST-800-53-MP-7
    - configure_strategy
    - high_disruption
    - low_complexity
    - medium_severity
    - mount_option_tmp_nosuid
    - no_reboot_needed

  - name: 'Add nosuid Option to /tmp: Make sure nosuid option is part of the to /tmp
      options'
    set_fact:
      mount_info: '{{ mount_info | combine( {''options'':''''~(mount_info.options
        | default(''''))~('','' if (mount_info.options | default('''')) else '''')~''nosuid''
        }) }}'
    when:
    - ( not ( "kernel" in ansible_facts.packages and "rpm-ostree" in ansible_facts.packages
      and "bootc" in ansible_facts.packages and not "openshift-kubelet" in ansible_facts.packages
      and "ostree" in ansible_proc_cmdline ) and not ( ansible_virtualization_type
      in ["docker", "lxc", "openvz", "podman", "container"] ) )
    - '"/tmp" in ansible_mounts | map(attribute="mount") | list'
    - mount_info is defined and "nosuid" not in (mount_info.options | default(''))
    tags:
    - NIST-800-53-AC-6
    - NIST-800-53-AC-6(1)
    - NIST-800-53-CM-6(a)
    - NIST-800-53-CM-7(a)
    - NIST-800-53-CM-7(b)
    - NIST-800-53-MP-7
    - configure_strategy
    - high_disruption
    - low_complexity
    - medium_severity
    - mount_option_tmp_nosuid
    - no_reboot_needed

  - name: 'Add nosuid Option to /tmp: Ensure /tmp is mounted with nosuid option'
    ansible.posix.mount:
      path: /tmp
      src: '{{ mount_info.source | default('''') }}'
      opts: '{{ mount_info.options | default('''') }}'
      state: mounted
      fstype: '{{ mount_info.fstype | default('''') }}'
    register: mount_result
    failed_when:
    - mount_result is failed
    - '''target is busy'' not in (mount_result.msg | default(''''))'
    - '''already mounted'' not in (mount_result.msg | default(''''))'
    when:
    - ( not ( "kernel" in ansible_facts.packages and "rpm-ostree" in ansible_facts.packages
      and "bootc" in ansible_facts.packages and not "openshift-kubelet" in ansible_facts.packages
      and "ostree" in ansible_proc_cmdline ) and not ( ansible_virtualization_type
      in ["docker", "lxc", "openvz", "podman", "container"] ) )
    - '"/tmp" in ansible_mounts | map(attribute="mount") | list'
    - mount_info is defined
    - (device_name.stdout is defined and (device_name.stdout | length > 0)) or ("--fstab"
      | length == 0)
    tags:
    - NIST-800-53-AC-6
    - NIST-800-53-AC-6(1)
    - NIST-800-53-CM-6(a)
    - NIST-800-53-CM-7(a)
    - NIST-800-53-CM-7(b)
    - NIST-800-53-MP-7
    - configure_strategy
    - high_disruption
    - low_complexity
    - medium_severity
    - mount_option_tmp_nosuid
    - no_reboot_needed

  - name: 'Add nodev Option to /var/tmp: Check information associated to mountpoint'
    ansible.builtin.command: findmnt --fstab '/var/tmp'
    register: device_name
    failed_when: device_name.rc > 1
    changed_when: false
    check_mode: false
    when:
    - ( not ( "kernel" in ansible_facts.packages and "rpm-ostree" in ansible_facts.packages
      and "bootc" in ansible_facts.packages and not "openshift-kubelet" in ansible_facts.packages
      and "ostree" in ansible_proc_cmdline ) and not ( ansible_virtualization_type
      in ["docker", "lxc", "openvz", "podman", "container"] ) )
    - '"/var/tmp" in ansible_mounts | map(attribute="mount") | list'
    tags:
    - configure_strategy
    - high_disruption
    - low_complexity
    - medium_severity
    - mount_option_var_tmp_nodev
    - no_reboot_needed

  - name: 'Add nodev Option to /var/tmp: Create mount_info dictionary variable'
    set_fact:
      mount_info: '{{ mount_info|default({})|combine({item.0: item.1}) }}'
    with_together:
    - '{{ device_name.stdout_lines[0].split() | map(''lower'') | list }}'
    - '{{ device_name.stdout_lines[1].split() | list }}'
    when:
    - ( not ( "kernel" in ansible_facts.packages and "rpm-ostree" in ansible_facts.packages
      and "bootc" in ansible_facts.packages and not "openshift-kubelet" in ansible_facts.packages
      and "ostree" in ansible_proc_cmdline ) and not ( ansible_virtualization_type
      in ["docker", "lxc", "openvz", "podman", "container"] ) )
    - '"/var/tmp" in ansible_mounts | map(attribute="mount") | list'
    - device_name.stdout is defined and device_name.stdout_lines is defined
    - (device_name.stdout | length > 0)
    tags:
    - configure_strategy
    - high_disruption
    - low_complexity
    - medium_severity
    - mount_option_var_tmp_nodev
    - no_reboot_needed

  - name: 'Add nodev Option to /var/tmp: If /var/tmp not mounted, craft mount_info
      manually'
    set_fact:
      mount_info: '{{ mount_info|default({})|combine({item.0: item.1}) }}'
    with_together:
    - - target
      - source
      - fstype
      - options
    - - /var/tmp
      - ''
      - ''
      - defaults
    when:
    - ( not ( "kernel" in ansible_facts.packages and "rpm-ostree" in ansible_facts.packages
      and "bootc" in ansible_facts.packages and not "openshift-kubelet" in ansible_facts.packages
      and "ostree" in ansible_proc_cmdline ) and not ( ansible_virtualization_type
      in ["docker", "lxc", "openvz", "podman", "container"] ) )
    - '"/var/tmp" in ansible_mounts | map(attribute="mount") | list'
    - ("--fstab" | length == 0)
    - device_name.stdout is defined and device_name.stdout_lines is defined
    - (device_name.stdout | length == 0)
    tags:
    - configure_strategy
    - high_disruption
    - low_complexity
    - medium_severity
    - mount_option_var_tmp_nodev
    - no_reboot_needed

  - name: 'Add nodev Option to /var/tmp: Make sure nodev option is part of the to
      /var/tmp options'
    set_fact:
      mount_info: '{{ mount_info | combine( {''options'':''''~(mount_info.options
        | default(''''))~('','' if (mount_info.options | default('''')) else '''')~''nodev''
        }) }}'
    when:
    - ( not ( "kernel" in ansible_facts.packages and "rpm-ostree" in ansible_facts.packages
      and "bootc" in ansible_facts.packages and not "openshift-kubelet" in ansible_facts.packages
      and "ostree" in ansible_proc_cmdline ) and not ( ansible_virtualization_type
      in ["docker", "lxc", "openvz", "podman", "container"] ) )
    - '"/var/tmp" in ansible_mounts | map(attribute="mount") | list'
    - mount_info is defined and "nodev" not in (mount_info.options | default(''))
    tags:
    - configure_strategy
    - high_disruption
    - low_complexity
    - medium_severity
    - mount_option_var_tmp_nodev
    - no_reboot_needed

  - name: 'Add nodev Option to /var/tmp: Ensure /var/tmp is mounted with nodev option'
    ansible.posix.mount:
      path: /var/tmp
      src: '{{ mount_info.source | default('''') }}'
      opts: '{{ mount_info.options | default('''') }}'
      state: mounted
      fstype: '{{ mount_info.fstype | default('''') }}'
    register: mount_result
    failed_when:
    - mount_result is failed
    - '''target is busy'' not in (mount_result.msg | default(''''))'
    - '''already mounted'' not in (mount_result.msg | default(''''))'
    when:
    - ( not ( "kernel" in ansible_facts.packages and "rpm-ostree" in ansible_facts.packages
      and "bootc" in ansible_facts.packages and not "openshift-kubelet" in ansible_facts.packages
      and "ostree" in ansible_proc_cmdline ) and not ( ansible_virtualization_type
      in ["docker", "lxc", "openvz", "podman", "container"] ) )
    - '"/var/tmp" in ansible_mounts | map(attribute="mount") | list'
    - mount_info is defined
    - (device_name.stdout is defined and (device_name.stdout | length > 0)) or ("--fstab"
      | length == 0)
    tags:
    - configure_strategy
    - high_disruption
    - low_complexity
    - medium_severity
    - mount_option_var_tmp_nodev
    - no_reboot_needed

  - name: 'Add noexec Option to /var/tmp: Check information associated to mountpoint'
    ansible.builtin.command: findmnt --fstab '/var/tmp'
    register: device_name
    failed_when: device_name.rc > 1
    changed_when: false
    check_mode: false
    when:
    - ( not ( "kernel" in ansible_facts.packages and "rpm-ostree" in ansible_facts.packages
      and "bootc" in ansible_facts.packages and not "openshift-kubelet" in ansible_facts.packages
      and "ostree" in ansible_proc_cmdline ) and not ( ansible_virtualization_type
      in ["docker", "lxc", "openvz", "podman", "container"] ) )
    - '"/var/tmp" in ansible_mounts | map(attribute="mount") | list'
    tags:
    - configure_strategy
    - high_disruption
    - low_complexity
    - medium_severity
    - mount_option_var_tmp_noexec
    - no_reboot_needed

  - name: 'Add noexec Option to /var/tmp: Create mount_info dictionary variable'
    set_fact:
      mount_info: '{{ mount_info|default({})|combine({item.0: item.1}) }}'
    with_together:
    - '{{ device_name.stdout_lines[0].split() | map(''lower'') | list }}'
    - '{{ device_name.stdout_lines[1].split() | list }}'
    when:
    - ( not ( "kernel" in ansible_facts.packages and "rpm-ostree" in ansible_facts.packages
      and "bootc" in ansible_facts.packages and not "openshift-kubelet" in ansible_facts.packages
      and "ostree" in ansible_proc_cmdline ) and not ( ansible_virtualization_type
      in ["docker", "lxc", "openvz", "podman", "container"] ) )
    - '"/var/tmp" in ansible_mounts | map(attribute="mount") | list'
    - device_name.stdout is defined and device_name.stdout_lines is defined
    - (device_name.stdout | length > 0)
    tags:
    - configure_strategy
    - high_disruption
    - low_complexity
    - medium_severity
    - mount_option_var_tmp_noexec
    - no_reboot_needed

  - name: 'Add noexec Option to /var/tmp: If /var/tmp not mounted, craft mount_info
      manually'
    set_fact:
      mount_info: '{{ mount_info|default({})|combine({item.0: item.1}) }}'
    with_together:
    - - target
      - source
      - fstype
      - options
    - - /var/tmp
      - ''
      - ''
      - defaults
    when:
    - ( not ( "kernel" in ansible_facts.packages and "rpm-ostree" in ansible_facts.packages
      and "bootc" in ansible_facts.packages and not "openshift-kubelet" in ansible_facts.packages
      and "ostree" in ansible_proc_cmdline ) and not ( ansible_virtualization_type
      in ["docker", "lxc", "openvz", "podman", "container"] ) )
    - '"/var/tmp" in ansible_mounts | map(attribute="mount") | list'
    - ("--fstab" | length == 0)
    - device_name.stdout is defined and device_name.stdout_lines is defined
    - (device_name.stdout | length == 0)
    tags:
    - configure_strategy
    - high_disruption
    - low_complexity
    - medium_severity
    - mount_option_var_tmp_noexec
    - no_reboot_needed

  - name: 'Add noexec Option to /var/tmp: Make sure noexec option is part of the to
      /var/tmp options'
    set_fact:
      mount_info: '{{ mount_info | combine( {''options'':''''~(mount_info.options
        | default(''''))~('','' if (mount_info.options | default('''')) else '''')~''noexec''
        }) }}'
    when:
    - ( not ( "kernel" in ansible_facts.packages and "rpm-ostree" in ansible_facts.packages
      and "bootc" in ansible_facts.packages and not "openshift-kubelet" in ansible_facts.packages
      and "ostree" in ansible_proc_cmdline ) and not ( ansible_virtualization_type
      in ["docker", "lxc", "openvz", "podman", "container"] ) )
    - '"/var/tmp" in ansible_mounts | map(attribute="mount") | list'
    - mount_info is defined and "noexec" not in (mount_info.options | default(''))
    tags:
    - configure_strategy
    - high_disruption
    - low_complexity
    - medium_severity
    - mount_option_var_tmp_noexec
    - no_reboot_needed

  - name: 'Add noexec Option to /var/tmp: Ensure /var/tmp is mounted with noexec option'
    ansible.posix.mount:
      path: /var/tmp
      src: '{{ mount_info.source | default('''') }}'
      opts: '{{ mount_info.options | default('''') }}'
      state: mounted
      fstype: '{{ mount_info.fstype | default('''') }}'
    register: mount_result
    failed_when:
    - mount_result is failed
    - '''target is busy'' not in (mount_result.msg | default(''''))'
    - '''already mounted'' not in (mount_result.msg | default(''''))'
    when:
    - ( not ( "kernel" in ansible_facts.packages and "rpm-ostree" in ansible_facts.packages
      and "bootc" in ansible_facts.packages and not "openshift-kubelet" in ansible_facts.packages
      and "ostree" in ansible_proc_cmdline ) and not ( ansible_virtualization_type
      in ["docker", "lxc", "openvz", "podman", "container"] ) )
    - '"/var/tmp" in ansible_mounts | map(attribute="mount") | list'
    - mount_info is defined
    - (device_name.stdout is defined and (device_name.stdout | length > 0)) or ("--fstab"
      | length == 0)
    tags:
    - configure_strategy
    - high_disruption
    - low_complexity
    - medium_severity
    - mount_option_var_tmp_noexec
    - no_reboot_needed

  - name: 'Add nosuid Option to /var/tmp: Check information associated to mountpoint'
    ansible.builtin.command: findmnt --fstab '/var/tmp'
    register: device_name
    failed_when: device_name.rc > 1
    changed_when: false
    check_mode: false
    when:
    - ( not ( "kernel" in ansible_facts.packages and "rpm-ostree" in ansible_facts.packages
      and "bootc" in ansible_facts.packages and not "openshift-kubelet" in ansible_facts.packages
      and "ostree" in ansible_proc_cmdline ) and not ( ansible_virtualization_type
      in ["docker", "lxc", "openvz", "podman", "container"] ) )
    - '"/var/tmp" in ansible_mounts | map(attribute="mount") | list'
    tags:
    - configure_strategy
    - high_disruption
    - low_complexity
    - medium_severity
    - mount_option_var_tmp_nosuid
    - no_reboot_needed

  - name: 'Add nosuid Option to /var/tmp: Create mount_info dictionary variable'
    set_fact:
      mount_info: '{{ mount_info|default({})|combine({item.0: item.1}) }}'
    with_together:
    - '{{ device_name.stdout_lines[0].split() | map(''lower'') | list }}'
    - '{{ device_name.stdout_lines[1].split() | list }}'
    when:
    - ( not ( "kernel" in ansible_facts.packages and "rpm-ostree" in ansible_facts.packages
      and "bootc" in ansible_facts.packages and not "openshift-kubelet" in ansible_facts.packages
      and "ostree" in ansible_proc_cmdline ) and not ( ansible_virtualization_type
      in ["docker", "lxc", "openvz", "podman", "container"] ) )
    - '"/var/tmp" in ansible_mounts | map(attribute="mount") | list'
    - device_name.stdout is defined and device_name.stdout_lines is defined
    - (device_name.stdout | length > 0)
    tags:
    - configure_strategy
    - high_disruption
    - low_complexity
    - medium_severity
    - mount_option_var_tmp_nosuid
    - no_reboot_needed

  - name: 'Add nosuid Option to /var/tmp: If /var/tmp not mounted, craft mount_info
      manually'
    set_fact:
      mount_info: '{{ mount_info|default({})|combine({item.0: item.1}) }}'
    with_together:
    - - target
      - source
      - fstype
      - options
    - - /var/tmp
      - ''
      - ''
      - defaults
    when:
    - ( not ( "kernel" in ansible_facts.packages and "rpm-ostree" in ansible_facts.packages
      and "bootc" in ansible_facts.packages and not "openshift-kubelet" in ansible_facts.packages
      and "ostree" in ansible_proc_cmdline ) and not ( ansible_virtualization_type
      in ["docker", "lxc", "openvz", "podman", "container"] ) )
    - '"/var/tmp" in ansible_mounts | map(attribute="mount") | list'
    - ("--fstab" | length == 0)
    - device_name.stdout is defined and device_name.stdout_lines is defined
    - (device_name.stdout | length == 0)
    tags:
    - configure_strategy
    - high_disruption
    - low_complexity
    - medium_severity
    - mount_option_var_tmp_nosuid
    - no_reboot_needed

  - name: 'Add nosuid Option to /var/tmp: Make sure nosuid option is part of the to
      /var/tmp options'
    set_fact:
      mount_info: '{{ mount_info | combine( {''options'':''''~(mount_info.options
        | default(''''))~('','' if (mount_info.options | default('''')) else '''')~''nosuid''
        }) }}'
    when:
    - ( not ( "kernel" in ansible_facts.packages and "rpm-ostree" in ansible_facts.packages
      and "bootc" in ansible_facts.packages and not "openshift-kubelet" in ansible_facts.packages
      and "ostree" in ansible_proc_cmdline ) and not ( ansible_virtualization_type
      in ["docker", "lxc", "openvz", "podman", "container"] ) )
    - '"/var/tmp" in ansible_mounts | map(attribute="mount") | list'
    - mount_info is defined and "nosuid" not in (mount_info.options | default(''))
    tags:
    - configure_strategy
    - high_disruption
    - low_complexity
    - medium_severity
    - mount_option_var_tmp_nosuid
    - no_reboot_needed

  - name: 'Add nosuid Option to /var/tmp: Ensure /var/tmp is mounted with nosuid option'
    ansible.posix.mount:
      path: /var/tmp
      src: '{{ mount_info.source | default('''') }}'
      opts: '{{ mount_info.options | default('''') }}'
      state: mounted
      fstype: '{{ mount_info.fstype | default('''') }}'
    register: mount_result
    failed_when:
    - mount_result is failed
    - '''target is busy'' not in (mount_result.msg | default(''''))'
    - '''already mounted'' not in (mount_result.msg | default(''''))'
    when:
    - ( not ( "kernel" in ansible_facts.packages and "rpm-ostree" in ansible_facts.packages
      and "bootc" in ansible_facts.packages and not "openshift-kubelet" in ansible_facts.packages
      and "ostree" in ansible_proc_cmdline ) and not ( ansible_virtualization_type
      in ["docker", "lxc", "openvz", "podman", "container"] ) )
    - '"/var/tmp" in ansible_mounts | map(attribute="mount") | list'
    - mount_info is defined
    - (device_name.stdout is defined and (device_name.stdout | length > 0)) or ("--fstab"
      | length == 0)
    tags:
    - configure_strategy
    - high_disruption
    - low_complexity
    - medium_severity
    - mount_option_var_tmp_nosuid
    - no_reboot_needed

  - name: Restrict Access to Kernel Message Buffer - Set fact for sysctl paths
    ansible.builtin.set_fact:
      sysctl_paths:
      - /etc/sysctl.d/
      - /run/sysctl.d/
      - /usr/local/lib/sysctl.d/
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL07-00-010375
    - NIST-800-171-3.1.5
    - NIST-800-53-SI-11(a)
    - NIST-800-53-SI-11(b)
    - disable_strategy
    - low_complexity
    - low_severity
    - medium_disruption
    - reboot_required
    - sysctl_kernel_dmesg_restrict

  - name: Restrict Access to Kernel Message Buffer - Find all files that contain kernel.dmesg_restrict
    ansible.builtin.shell:
      cmd: find -L {{ sysctl_paths | join(" ") }} -type f -name '*.conf' | xargs grep
        -HP '^\s*kernel.dmesg_restrict\s*=\s*.*$'
    register: find_all_values
    check_mode: false
    changed_when: false
    failed_when: false
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL07-00-010375
    - NIST-800-171-3.1.5
    - NIST-800-53-SI-11(a)
    - NIST-800-53-SI-11(b)
    - disable_strategy
    - low_complexity
    - low_severity
    - medium_disruption
    - reboot_required
    - sysctl_kernel_dmesg_restrict

  - name: Restrict Access to Kernel Message Buffer - Find all files that set kernel.dmesg_restrict
      to correct value
    ansible.builtin.shell:
      cmd: find -L {{ sysctl_paths | join(" ") }} -type f -name '*.conf' | xargs grep
        -HP '^\s*kernel.dmesg_restrict\s*=\s*1$'
    register: find_correct_value
    check_mode: false
    changed_when: false
    failed_when: false
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL07-00-010375
    - NIST-800-171-3.1.5
    - NIST-800-53-SI-11(a)
    - NIST-800-53-SI-11(b)
    - disable_strategy
    - low_complexity
    - low_severity
    - medium_disruption
    - reboot_required
    - sysctl_kernel_dmesg_restrict

  - name: Restrict Access to Kernel Message Buffer - Comment out any occurrences of
      kernel.dmesg_restrict from config files
    ansible.builtin.replace:
      path: '{{ item | split(":") | first }}'
      regexp: ^[\s]*kernel.dmesg_restrict
      replace: '#kernel.dmesg_restrict'
    loop: '{{ find_all_values.stdout_lines }}'
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - find_correct_value.stdout_lines | length == 0 or find_all_values.stdout_lines
      | length > find_correct_value.stdout_lines | length
    tags:
    - DISA-STIG-OL07-00-010375
    - NIST-800-171-3.1.5
    - NIST-800-53-SI-11(a)
    - NIST-800-53-SI-11(b)
    - disable_strategy
    - low_complexity
    - low_severity
    - medium_disruption
    - reboot_required
    - sysctl_kernel_dmesg_restrict

  - name: Restrict Access to Kernel Message Buffer - Ensure sysctl kernel.dmesg_restrict
      is set to 1
    ansible.posix.sysctl:
      name: kernel.dmesg_restrict
      value: '1'
      sysctl_file: /etc/sysctl.conf
      state: present
      reload: true
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL07-00-010375
    - NIST-800-171-3.1.5
    - NIST-800-53-SI-11(a)
    - NIST-800-53-SI-11(b)
    - disable_strategy
    - low_complexity
    - low_severity
    - medium_disruption
    - reboot_required
    - sysctl_kernel_dmesg_restrict

  - name: Disable Kernel Image Loading - Set fact for sysctl paths
    ansible.builtin.set_fact:
      sysctl_paths:
      - /etc/sysctl.d/
      - /run/sysctl.d/
      - /usr/local/lib/sysctl.d/
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - NIST-800-53-CM-6
    - disable_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - reboot_required
    - sysctl_kernel_kexec_load_disabled

  - name: Disable Kernel Image Loading - Find all files that contain kernel.kexec_load_disabled
    ansible.builtin.shell:
      cmd: find -L {{ sysctl_paths | join(" ") }} -type f -name '*.conf' | xargs grep
        -HP '^\s*kernel.kexec_load_disabled\s*=\s*.*$'
    register: find_all_values
    check_mode: false
    changed_when: false
    failed_when: false
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - NIST-800-53-CM-6
    - disable_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - reboot_required
    - sysctl_kernel_kexec_load_disabled

  - name: Disable Kernel Image Loading - Find all files that set kernel.kexec_load_disabled
      to correct value
    ansible.builtin.shell:
      cmd: find -L {{ sysctl_paths | join(" ") }} -type f -name '*.conf' | xargs grep
        -HP '^\s*kernel.kexec_load_disabled\s*=\s*1$'
    register: find_correct_value
    check_mode: false
    changed_when: false
    failed_when: false
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - NIST-800-53-CM-6
    - disable_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - reboot_required
    - sysctl_kernel_kexec_load_disabled

  - name: Disable Kernel Image Loading - Comment out any occurrences of kernel.kexec_load_disabled
      from config files
    ansible.builtin.replace:
      path: '{{ item | split(":") | first }}'
      regexp: ^[\s]*kernel.kexec_load_disabled
      replace: '#kernel.kexec_load_disabled'
    loop: '{{ find_all_values.stdout_lines }}'
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - find_correct_value.stdout_lines | length == 0 or find_all_values.stdout_lines
      | length > find_correct_value.stdout_lines | length
    tags:
    - NIST-800-53-CM-6
    - disable_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - reboot_required
    - sysctl_kernel_kexec_load_disabled

  - name: Disable Kernel Image Loading - Ensure sysctl kernel.kexec_load_disabled
      is set to 1
    ansible.posix.sysctl:
      name: kernel.kexec_load_disabled
      value: '1'
      sysctl_file: /etc/sysctl.conf
      state: present
      reload: true
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - NIST-800-53-CM-6
    - disable_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - reboot_required
    - sysctl_kernel_kexec_load_disabled

  - name: Restrict usage of ptrace to descendant processes - Set fact for sysctl paths
    ansible.builtin.set_fact:
      sysctl_paths:
      - /etc/sysctl.d/
      - /run/sysctl.d/
      - /usr/local/lib/sysctl.d/
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - NIST-800-53-SC-7(10)
    - disable_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - reboot_required
    - sysctl_kernel_yama_ptrace_scope

  - name: Restrict usage of ptrace to descendant processes - Find all files that contain
      kernel.yama.ptrace_scope
    ansible.builtin.shell:
      cmd: find -L {{ sysctl_paths | join(" ") }} -type f -name '*.conf' | xargs grep
        -HP '^\s*kernel.yama.ptrace_scope\s*=\s*.*$'
    register: find_all_values
    check_mode: false
    changed_when: false
    failed_when: false
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - NIST-800-53-SC-7(10)
    - disable_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - reboot_required
    - sysctl_kernel_yama_ptrace_scope

  - name: Restrict usage of ptrace to descendant processes - Find all files that set
      kernel.yama.ptrace_scope to correct value
    ansible.builtin.shell:
      cmd: find -L {{ sysctl_paths | join(" ") }} -type f -name '*.conf' | xargs grep
        -HP '^\s*kernel.yama.ptrace_scope\s*=\s*1$'
    register: find_correct_value
    check_mode: false
    changed_when: false
    failed_when: false
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - NIST-800-53-SC-7(10)
    - disable_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - reboot_required
    - sysctl_kernel_yama_ptrace_scope

  - name: Restrict usage of ptrace to descendant processes - Comment out any occurrences
      of kernel.yama.ptrace_scope from config files
    ansible.builtin.replace:
      path: '{{ item | split(":") | first }}'
      regexp: ^[\s]*kernel.yama.ptrace_scope
      replace: '#kernel.yama.ptrace_scope'
    loop: '{{ find_all_values.stdout_lines }}'
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - find_correct_value.stdout_lines | length == 0 or find_all_values.stdout_lines
      | length > find_correct_value.stdout_lines | length
    tags:
    - NIST-800-53-SC-7(10)
    - disable_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - reboot_required
    - sysctl_kernel_yama_ptrace_scope

  - name: Restrict usage of ptrace to descendant processes - Ensure sysctl kernel.yama.ptrace_scope
      is set to 1
    ansible.posix.sysctl:
      name: kernel.yama.ptrace_scope
      value: '1'
      sysctl_file: /etc/sysctl.conf
      state: present
      reload: true
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - NIST-800-53-SC-7(10)
    - disable_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - reboot_required
    - sysctl_kernel_yama_ptrace_scope

  - 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:
    - 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:
    - 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:
    - 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:
    - 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:
    - 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:
    - 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:
    - 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:
    - 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:
    - 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: Restrict Exposed Kernel Pointer Addresses Access - Set fact for sysctl paths
    ansible.builtin.set_fact:
      sysctl_paths:
      - /etc/sysctl.d/
      - /run/sysctl.d/
      - /usr/local/lib/sysctl.d/
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - NIST-800-53-CM-6(a)
    - NIST-800-53-SC-30
    - NIST-800-53-SC-30(2)
    - NIST-800-53-SC-30(5)
    - disable_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - reboot_required
    - sysctl_kernel_kptr_restrict

  - name: Restrict Exposed Kernel Pointer Addresses Access - Find all files that contain
      kernel.kptr_restrict
    ansible.builtin.shell:
      cmd: find -L {{ sysctl_paths | join(" ") }} -type f -name '*.conf' | xargs grep
        -HP '^\s*kernel.kptr_restrict\s*=\s*.*$'
    register: find_all_values
    check_mode: false
    changed_when: false
    failed_when: false
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - NIST-800-53-CM-6(a)
    - NIST-800-53-SC-30
    - NIST-800-53-SC-30(2)
    - NIST-800-53-SC-30(5)
    - disable_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - reboot_required
    - sysctl_kernel_kptr_restrict

  - name: Restrict Exposed Kernel Pointer Addresses Access - Find all files that set
      kernel.kptr_restrict to correct value
    ansible.builtin.shell:
      cmd: find -L {{ sysctl_paths | join(" ") }} -type f -name '*.conf' | xargs grep
        -HP '^\s*kernel.kptr_restrict\s*=\s*{{ sysctl_kernel_kptr_restrict_value }}$'
    register: find_correct_value
    check_mode: false
    changed_when: false
    failed_when: false
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - NIST-800-53-CM-6(a)
    - NIST-800-53-SC-30
    - NIST-800-53-SC-30(2)
    - NIST-800-53-SC-30(5)
    - disable_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - reboot_required
    - sysctl_kernel_kptr_restrict

  - name: Restrict Exposed Kernel Pointer Addresses Access - Comment out any occurrences
      of kernel.kptr_restrict from config files
    ansible.builtin.replace:
      path: '{{ item | split(":") | first }}'
      regexp: ^[\s]*kernel.kptr_restrict
      replace: '#kernel.kptr_restrict'
    loop: '{{ find_all_values.stdout_lines }}'
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - find_correct_value.stdout_lines | length == 0 or find_all_values.stdout_lines
      | length > find_correct_value.stdout_lines | length
    tags:
    - NIST-800-53-CM-6(a)
    - NIST-800-53-SC-30
    - NIST-800-53-SC-30(2)
    - NIST-800-53-SC-30(5)
    - disable_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - reboot_required
    - sysctl_kernel_kptr_restrict

  - name: Restrict Exposed Kernel Pointer Addresses Access - Ensure sysctl kernel.kptr_restrict
      is set
    ansible.posix.sysctl:
      name: kernel.kptr_restrict
      value: '{{ sysctl_kernel_kptr_restrict_value }}'
      sysctl_file: /etc/sysctl.conf
      state: present
      reload: true
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - NIST-800-53-CM-6(a)
    - NIST-800-53-SC-30
    - NIST-800-53-SC-30(2)
    - NIST-800-53-SC-30(5)
    - disable_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - reboot_required
    - sysctl_kernel_kptr_restrict

  - name: Check page_poison argument exists
    ansible.builtin.command: grep '^\s*GRUB_CMDLINE_LINUX=.*page_poison=' /etc/default/grub
    check_mode: false
    failed_when: false
    changed_when: false
    register: argcheck
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - '"grub2-common" in ansible_facts.packages'
    tags:
    - NIST-800-53-CM-6(a)
    - grub2_page_poison_argument
    - low_disruption
    - medium_complexity
    - medium_severity
    - reboot_required
    - restrict_strategy

  - name: Check page_poison argument exists
    ansible.builtin.command: grep '^\s*GRUB_CMDLINE_LINUX=' /etc/default/grub
    check_mode: false
    failed_when: false
    changed_when: false
    register: linecheck
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - '"grub2-common" in ansible_facts.packages'
    tags:
    - NIST-800-53-CM-6(a)
    - grub2_page_poison_argument
    - low_disruption
    - medium_complexity
    - medium_severity
    - reboot_required
    - restrict_strategy

  - name: Add page_poison argument
    ansible.builtin.lineinfile:
      line: GRUB_CMDLINE_LINUX="page_poison=1 "
      state: present
      dest: /etc/default/grub
      create: true
      mode: '0644'
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - '"grub2-common" in ansible_facts.packages'
    - argcheck is not skipped and linecheck is not skipped and argcheck.rc != 0 and
      linecheck.rc != 0
    tags:
    - NIST-800-53-CM-6(a)
    - grub2_page_poison_argument
    - low_disruption
    - medium_complexity
    - medium_severity
    - reboot_required
    - restrict_strategy

  - name: Replace existing page_poison argument
    ansible.builtin.replace:
      path: /etc/default/grub
      regexp: page_poison=[a-zA-Z0-9,]+
      replace: page_poison=1
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - '"grub2-common" in ansible_facts.packages'
    - argcheck is not skipped and linecheck is not skipped and argcheck.rc == 0 and
      linecheck.rc == 0
    tags:
    - NIST-800-53-CM-6(a)
    - grub2_page_poison_argument
    - low_disruption
    - medium_complexity
    - medium_severity
    - reboot_required
    - restrict_strategy

  - name: Add page_poison argument
    ansible.builtin.replace:
      path: /etc/default/grub
      regexp: (^\s*GRUB_CMDLINE_LINUX=.*)"
      replace: \1 page_poison=1"
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - '"grub2-common" in ansible_facts.packages'
    - argcheck is not skipped and linecheck is not skipped and argcheck.rc != 0 and
      linecheck.rc == 0
    tags:
    - NIST-800-53-CM-6(a)
    - grub2_page_poison_argument
    - low_disruption
    - medium_complexity
    - medium_severity
    - reboot_required
    - restrict_strategy

  - name: Check if page_poison argument is already present 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:
    - NIST-800-53-CM-6(a)
    - grub2_page_poison_argument
    - low_disruption
    - medium_complexity
    - medium_severity
    - reboot_required
    - restrict_strategy

  - name: Check if page_poison argument is already present
    ansible.builtin.command: /sbin/grubby --info=ALL
    register: grubby_info
    check_mode: false
    changed_when: false
    failed_when: false
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - '"grub2-common" in ansible_facts.packages'
    tags:
    - NIST-800-53-CM-6(a)
    - grub2_page_poison_argument
    - low_disruption
    - medium_complexity
    - medium_severity
    - reboot_required
    - restrict_strategy

  - name: Update grub defaults and the bootloader menu
    ansible.builtin.command: /sbin/grubby --update-kernel=ALL --args="page_poison=1"
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - '"grub2-common" in ansible_facts.packages'
    - (grubby_info.stdout is not search('page_poison=1')) or ((etc_default_grub['content']
      | b64decode) is not search('page_poison=1'))
    tags:
    - NIST-800-53-CM-6(a)
    - grub2_page_poison_argument
    - low_disruption
    - medium_complexity
    - medium_severity
    - reboot_required
    - restrict_strategy

  - name: Check slub_debug argument exists
    ansible.builtin.command: grep '^\s*GRUB_CMDLINE_LINUX=.*slub_debug=' /etc/default/grub
    check_mode: false
    failed_when: false
    changed_when: false
    register: argcheck
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - '"grub2-common" in ansible_facts.packages'
    tags:
    - NIST-800-53-CM-6(a)
    - grub2_slub_debug_argument
    - low_disruption
    - medium_complexity
    - medium_severity
    - reboot_required
    - restrict_strategy

  - name: Check slub_debug argument exists
    ansible.builtin.command: grep '^\s*GRUB_CMDLINE_LINUX=' /etc/default/grub
    check_mode: false
    failed_when: false
    changed_when: false
    register: linecheck
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - '"grub2-common" in ansible_facts.packages'
    tags:
    - NIST-800-53-CM-6(a)
    - grub2_slub_debug_argument
    - low_disruption
    - medium_complexity
    - medium_severity
    - reboot_required
    - restrict_strategy

  - name: Add slub_debug argument
    ansible.builtin.lineinfile:
      line: GRUB_CMDLINE_LINUX="slub_debug={{ var_slub_debug_options }} "
      state: present
      dest: /etc/default/grub
      create: true
      mode: '0644'
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - '"grub2-common" in ansible_facts.packages'
    - argcheck is not skipped and linecheck is not skipped and argcheck.rc != 0 and
      linecheck.rc != 0
    tags:
    - NIST-800-53-CM-6(a)
    - grub2_slub_debug_argument
    - low_disruption
    - medium_complexity
    - medium_severity
    - reboot_required
    - restrict_strategy

  - name: Replace existing slub_debug argument
    ansible.builtin.replace:
      path: /etc/default/grub
      regexp: slub_debug=[a-zA-Z0-9,]+
      replace: slub_debug={{ var_slub_debug_options }}
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - '"grub2-common" in ansible_facts.packages'
    - argcheck is not skipped and linecheck is not skipped and argcheck.rc == 0 and
      linecheck.rc == 0
    tags:
    - NIST-800-53-CM-6(a)
    - grub2_slub_debug_argument
    - low_disruption
    - medium_complexity
    - medium_severity
    - reboot_required
    - restrict_strategy

  - name: Add slub_debug argument
    ansible.builtin.replace:
      path: /etc/default/grub
      regexp: (^\s*GRUB_CMDLINE_LINUX=.*)"
      replace: \1 slub_debug={{ var_slub_debug_options }}"
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - '"grub2-common" in ansible_facts.packages'
    - argcheck is not skipped and linecheck is not skipped and argcheck.rc != 0 and
      linecheck.rc == 0
    tags:
    - NIST-800-53-CM-6(a)
    - grub2_slub_debug_argument
    - low_disruption
    - medium_complexity
    - medium_severity
    - reboot_required
    - restrict_strategy

  - name: Check if slub_debug argument is already present 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:
    - NIST-800-53-CM-6(a)
    - grub2_slub_debug_argument
    - low_disruption
    - medium_complexity
    - medium_severity
    - reboot_required
    - restrict_strategy

  - name: Check if slub_debug argument is already present
    ansible.builtin.command: /sbin/grubby --info=ALL
    register: grubby_info
    check_mode: false
    changed_when: false
    failed_when: false
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - '"grub2-common" in ansible_facts.packages'
    tags:
    - NIST-800-53-CM-6(a)
    - grub2_slub_debug_argument
    - low_disruption
    - medium_complexity
    - medium_severity
    - reboot_required
    - restrict_strategy

  - name: Update grub defaults and the bootloader menu
    ansible.builtin.command: /sbin/grubby --update-kernel=ALL --args="slub_debug={{
      var_slub_debug_options }}"
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - '"grub2-common" in ansible_facts.packages'
    - (grubby_info.stdout is not search('slub_debug=' ~ var_slub_debug_options)) or
      ((etc_default_grub['content'] | b64decode) is not search('slub_debug=' ~ var_slub_debug_options))
    tags:
    - NIST-800-53-CM-6(a)
    - grub2_slub_debug_argument
    - low_disruption
    - medium_complexity
    - medium_severity
    - reboot_required
    - restrict_strategy

  - name: Configure SELinux Policy
    block:

    - name: Check for duplicate values
      ansible.builtin.lineinfile:
        path: /etc/selinux/config
        create: true
        regexp: (?i)^SELINUXTYPE=
        state: absent
      check_mode: true
      changed_when: false
      register: dupes

    - name: Deduplicate values from /etc/selinux/config
      ansible.builtin.lineinfile:
        path: /etc/selinux/config
        create: true
        regexp: (?i)^SELINUXTYPE=
        state: absent
      when: dupes.found is defined and dupes.found > 1

    - name: Insert correct line to /etc/selinux/config
      ansible.builtin.lineinfile:
        path: /etc/selinux/config
        create: true
        regexp: (?i)^SELINUXTYPE=
        line: SELINUXTYPE={{ var_selinux_policy_name }}
        state: present
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL07-00-020220
    - 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-OL07-00-020210
    - 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-OL07-00-020210
    - 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-OL07-00-020210
    - 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 SSH Client Alive Count Max to zero
    block:

    - name: Check for duplicate values
      ansible.builtin.lineinfile:
        path: /etc/ssh/sshd_config
        create: true
        regexp: (?i)(?i)^\s*ClientAliveCountMax\s+
        state: absent
      check_mode: true
      changed_when: false
      register: dupes

    - name: Deduplicate values from /etc/ssh/sshd_config
      ansible.builtin.lineinfile:
        path: /etc/ssh/sshd_config
        create: true
        regexp: (?i)(?i)^\s*ClientAliveCountMax\s+
        state: absent
      when: dupes.found is defined and dupes.found > 1

    - name: Insert correct line to /etc/ssh/sshd_config
      ansible.builtin.lineinfile:
        path: /etc/ssh/sshd_config
        create: true
        regexp: (?i)(?i)^\s*ClientAliveCountMax\s+
        line: ClientAliveCountMax 0
        state: present
        insertbefore: BOF
        validate: /usr/sbin/sshd -t -f %s
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - CJIS-5.5.6
    - DISA-STIG-OL07-00-040340
    - 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
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy
    - sshd_set_keepalive_0

  - name: Set SSH Client Alive Interval
    block:

    - name: Check for duplicate values
      ansible.builtin.lineinfile:
        path: /etc/ssh/sshd_config
        create: true
        regexp: (?i)(?i)^\s*ClientAliveInterval\s+
        state: absent
      check_mode: true
      changed_when: false
      register: dupes

    - name: Deduplicate values from /etc/ssh/sshd_config
      ansible.builtin.lineinfile:
        path: /etc/ssh/sshd_config
        create: true
        regexp: (?i)(?i)^\s*ClientAliveInterval\s+
        state: absent
      when: dupes.found is defined and dupes.found > 1

    - name: Insert correct line to /etc/ssh/sshd_config
      ansible.builtin.lineinfile:
        path: /etc/ssh/sshd_config
        create: true
        regexp: (?i)(?i)^\s*ClientAliveInterval\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)
    tags:
    - CJIS-5.5.6
    - DISA-STIG-OL07-00-040320
    - 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: Disable Host-Based Authentication
    block:

    - name: Check for duplicate values
      ansible.builtin.lineinfile:
        path: /etc/ssh/sshd_config
        create: true
        regexp: (?i)(?i)^\s*HostbasedAuthentication\s+
        state: absent
      check_mode: true
      changed_when: false
      register: dupes

    - name: Deduplicate values from /etc/ssh/sshd_config
      ansible.builtin.lineinfile:
        path: /etc/ssh/sshd_config
        create: true
        regexp: (?i)(?i)^\s*HostbasedAuthentication\s+
        state: absent
      when: dupes.found is defined and dupes.found > 1

    - name: Insert correct line to /etc/ssh/sshd_config
      ansible.builtin.lineinfile:
        path: /etc/ssh/sshd_config
        create: true
        regexp: (?i)(?i)^\s*HostbasedAuthentication\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)
    tags:
    - CJIS-5.5.6
    - DISA-STIG-OL07-00-010470
    - 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 SSH Access via Empty Passwords
    block:

    - name: Check for duplicate values
      ansible.builtin.lineinfile:
        path: /etc/ssh/sshd_config
        create: true
        regexp: (?i)(?i)^\s*PermitEmptyPasswords\s+
        state: absent
      check_mode: true
      changed_when: false
      register: dupes

    - name: Deduplicate values from /etc/ssh/sshd_config
      ansible.builtin.lineinfile:
        path: /etc/ssh/sshd_config
        create: true
        regexp: (?i)(?i)^\s*PermitEmptyPasswords\s+
        state: absent
      when: dupes.found is defined and dupes.found > 1

    - name: Insert correct line to /etc/ssh/sshd_config
      ansible.builtin.lineinfile:
        path: /etc/ssh/sshd_config
        create: true
        regexp: (?i)(?i)^\s*PermitEmptyPasswords\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)
    tags:
    - CJIS-5.5.6
    - DISA-STIG-OL07-00-010300
    - 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 GSSAPI Authentication
    block:

    - name: Check for duplicate values
      ansible.builtin.lineinfile:
        path: /etc/ssh/sshd_config
        create: true
        regexp: (?i)(?i)^\s*GSSAPIAuthentication\s+
        state: absent
      check_mode: true
      changed_when: false
      register: dupes

    - name: Deduplicate values from /etc/ssh/sshd_config
      ansible.builtin.lineinfile:
        path: /etc/ssh/sshd_config
        create: true
        regexp: (?i)(?i)^\s*GSSAPIAuthentication\s+
        state: absent
      when: dupes.found is defined and dupes.found > 1

    - name: Insert correct line to /etc/ssh/sshd_config
      ansible.builtin.lineinfile:
        path: /etc/ssh/sshd_config
        create: true
        regexp: (?i)(?i)^\s*GSSAPIAuthentication\s+
        line: GSSAPIAuthentication no
        state: present
        insertbefore: BOF
        validate: /usr/sbin/sshd -t -f %s
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL07-00-040430
    - NIST-800-171-3.1.12
    - NIST-800-53-AC-17(a)
    - NIST-800-53-CM-6(a)
    - NIST-800-53-CM-7(a)
    - NIST-800-53-CM-7(b)
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy
    - sshd_disable_gssapi_auth

  - name: Disable Kerberos Authentication
    block:

    - name: Check for duplicate values
      ansible.builtin.lineinfile:
        path: /etc/ssh/sshd_config
        create: true
        regexp: (?i)(?i)^\s*KerberosAuthentication\s+
        state: absent
      check_mode: true
      changed_when: false
      register: dupes

    - name: Deduplicate values from /etc/ssh/sshd_config
      ansible.builtin.lineinfile:
        path: /etc/ssh/sshd_config
        create: true
        regexp: (?i)(?i)^\s*KerberosAuthentication\s+
        state: absent
      when: dupes.found is defined and dupes.found > 1

    - name: Insert correct line to /etc/ssh/sshd_config
      ansible.builtin.lineinfile:
        path: /etc/ssh/sshd_config
        create: true
        regexp: (?i)(?i)^\s*KerberosAuthentication\s+
        line: KerberosAuthentication no
        state: present
        insertbefore: BOF
        validate: /usr/sbin/sshd -t -f %s
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL07-00-040440
    - NIST-800-171-3.1.12
    - NIST-800-53-AC-17(a)
    - NIST-800-53-CM-6(a)
    - NIST-800-53-CM-7(a)
    - NIST-800-53-CM-7(b)
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy
    - sshd_disable_kerb_auth

  - name: Disable SSH Support for Rhosts RSA Authentication
    block:

    - name: Check for duplicate values
      ansible.builtin.lineinfile:
        path: /etc/ssh/sshd_config
        create: true
        regexp: (?i)(?i)^\s*RhostsRSAAuthentication\s+
        state: absent
      check_mode: true
      changed_when: false
      register: dupes

    - name: Deduplicate values from /etc/ssh/sshd_config
      ansible.builtin.lineinfile:
        path: /etc/ssh/sshd_config
        create: true
        regexp: (?i)(?i)^\s*RhostsRSAAuthentication\s+
        state: absent
      when: dupes.found is defined and dupes.found > 1

    - name: Insert correct line to /etc/ssh/sshd_config
      ansible.builtin.lineinfile:
        path: /etc/ssh/sshd_config
        create: true
        regexp: (?i)(?i)^\s*RhostsRSAAuthentication\s+
        line: RhostsRSAAuthentication 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)
    tags:
    - DISA-STIG-OL07-00-040330
    - NIST-800-171-3.1.12
    - NIST-800-53-AC-17(a)
    - NIST-800-53-CM-6(a)
    - NIST-800-53-CM-7(a)
    - NIST-800-53-CM-7(b)
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy
    - sshd_disable_rhosts_rsa

  - name: Disable SSH Root Login
    block:

    - name: Check for duplicate values
      ansible.builtin.lineinfile:
        path: /etc/ssh/sshd_config
        create: true
        regexp: (?i)(?i)^\s*PermitRootLogin\s+
        state: absent
      check_mode: true
      changed_when: false
      register: dupes

    - name: Deduplicate values from /etc/ssh/sshd_config
      ansible.builtin.lineinfile:
        path: /etc/ssh/sshd_config
        create: true
        regexp: (?i)(?i)^\s*PermitRootLogin\s+
        state: absent
      when: dupes.found is defined and dupes.found > 1

    - name: Insert correct line to /etc/ssh/sshd_config
      ansible.builtin.lineinfile:
        path: /etc/ssh/sshd_config
        create: true
        regexp: (?i)(?i)^\s*PermitRootLogin\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)
    tags:
    - CJIS-5.5.6
    - DISA-STIG-OL07-00-040370
    - 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: Enable Use of Strict Mode Checking
    block:

    - name: Check for duplicate values
      ansible.builtin.lineinfile:
        path: /etc/ssh/sshd_config
        create: true
        regexp: (?i)(?i)^\s*StrictModes\s+
        state: absent
      check_mode: true
      changed_when: false
      register: dupes

    - name: Deduplicate values from /etc/ssh/sshd_config
      ansible.builtin.lineinfile:
        path: /etc/ssh/sshd_config
        create: true
        regexp: (?i)(?i)^\s*StrictModes\s+
        state: absent
      when: dupes.found is defined and dupes.found > 1

    - name: Insert correct line to /etc/ssh/sshd_config
      ansible.builtin.lineinfile:
        path: /etc/ssh/sshd_config
        create: true
        regexp: (?i)(?i)^\s*StrictModes\s+
        line: StrictModes yes
        state: present
        insertbefore: BOF
        validate: /usr/sbin/sshd -t -f %s
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL07-00-040450
    - NIST-800-171-3.1.12
    - NIST-800-53-AC-17(a)
    - NIST-800-53-AC-6
    - NIST-800-53-CM-6(a)
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy
    - sshd_enable_strictmodes

  - name: Enable SSH Warning Banner
    block:

    - name: Check for duplicate values
      ansible.builtin.lineinfile:
        path: /etc/ssh/sshd_config
        create: true
        regexp: (?i)(?i)^\s*Banner\s+
        state: absent
      check_mode: true
      changed_when: false
      register: dupes

    - name: Deduplicate values from /etc/ssh/sshd_config
      ansible.builtin.lineinfile:
        path: /etc/ssh/sshd_config
        create: true
        regexp: (?i)(?i)^\s*Banner\s+
        state: absent
      when: dupes.found is defined and dupes.found > 1

    - name: Insert correct line to /etc/ssh/sshd_config
      ansible.builtin.lineinfile:
        path: /etc/ssh/sshd_config
        create: true
        regexp: (?i)(?i)^\s*Banner\s+
        line: Banner /etc/issue
        state: present
        insertbefore: BOF
        validate: /usr/sbin/sshd -t -f %s
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - CJIS-5.5.6
    - DISA-STIG-OL07-00-040170
    - NIST-800-171-3.1.9
    - NIST-800-53-AC-17(a)
    - NIST-800-53-AC-8(a)
    - NIST-800-53-AC-8(c)
    - NIST-800-53-CM-6(a)
    - PCI-DSS-Req-2.2.4
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy
    - sshd_enable_warning_banner

  - name: Use Only FIPS 140-2 Validated Ciphers
    block:

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

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

    - name: Insert correct line to /etc/ssh/sshd_config
      ansible.builtin.lineinfile:
        path: /etc/ssh/sshd_config
        create: true
        regexp: (?i)(?i)^\s*Ciphers\s+
        line: Ciphers {{ sshd_approved_ciphers }}
        state: present
        insertbefore: BOF
        validate: /usr/sbin/sshd -t -f %s
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - CJIS-5.5.6
    - NIST-800-171-3.1.13
    - NIST-800-171-3.13.11
    - NIST-800-171-3.13.8
    - NIST-800-53-AC-17(2)
    - NIST-800-53-AC-17(a)
    - NIST-800-53-CM-6(a)
    - NIST-800-53-IA-5(1)(c)
    - 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
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy
    - sshd_use_approved_ciphers

  - name: Use Only FIPS 140-2 Validated MACs
    block:

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

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

    - name: Insert correct line to /etc/ssh/sshd_config
      ansible.builtin.lineinfile:
        path: /etc/ssh/sshd_config
        create: true
        regexp: (?i)(?i)^\s*MACs\s+
        line: MACs {{ sshd_approved_macs }}
        state: present
        insertbefore: BOF
        validate: /usr/sbin/sshd -t -f %s
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - NIST-800-171-3.1.13
    - NIST-800-171-3.13.11
    - NIST-800-171-3.13.8
    - 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
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy
    - sshd_use_approved_macs

  - name: Check audit argument exists
    ansible.builtin.command: grep '^\s*GRUB_CMDLINE_LINUX=.*audit=' /etc/default/grub
    check_mode: false
    failed_when: false
    changed_when: false
    register: argcheck
    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
    - 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 audit argument exists
    ansible.builtin.command: grep '^\s*GRUB_CMDLINE_LINUX=' /etc/default/grub
    check_mode: false
    failed_when: false
    changed_when: false
    register: linecheck
    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
    - 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: Add audit argument
    ansible.builtin.lineinfile:
      line: GRUB_CMDLINE_LINUX="audit=1 "
      state: present
      dest: /etc/default/grub
      create: true
      mode: '0644'
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - '"grub2-common" in ansible_facts.packages'
    - argcheck is not skipped and linecheck is not skipped and argcheck.rc != 0 and
      linecheck.rc != 0
    tags:
    - CJIS-5.4.1.1
    - 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: Replace existing audit argument
    ansible.builtin.replace:
      path: /etc/default/grub
      regexp: audit=[a-zA-Z0-9,]+
      replace: audit=1
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - '"grub2-common" in ansible_facts.packages'
    - argcheck is not skipped and linecheck is not skipped and argcheck.rc == 0 and
      linecheck.rc == 0
    tags:
    - CJIS-5.4.1.1
    - 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: Add audit argument
    ansible.builtin.replace:
      path: /etc/default/grub
      regexp: (^\s*GRUB_CMDLINE_LINUX=.*)"
      replace: \1 audit=1"
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - '"grub2-common" in ansible_facts.packages'
    - argcheck is not skipped and linecheck is not skipped and argcheck.rc != 0 and
      linecheck.rc == 0
    tags:
    - CJIS-5.4.1.1
    - 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 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
    - 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
    - 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
    - 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 audit_backlog_limit argument exists
    ansible.builtin.command: grep '^\s*GRUB_CMDLINE_LINUX=.*audit_backlog_limit='
      /etc/default/grub
    check_mode: false
    failed_when: false
    changed_when: false
    register: argcheck
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - '"grub2-common" in ansible_facts.packages'
    tags:
    - 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 audit_backlog_limit argument exists
    ansible.builtin.command: grep '^\s*GRUB_CMDLINE_LINUX=' /etc/default/grub
    check_mode: false
    failed_when: false
    changed_when: false
    register: linecheck
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - '"grub2-common" in ansible_facts.packages'
    tags:
    - 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: Add audit_backlog_limit argument
    ansible.builtin.lineinfile:
      line: GRUB_CMDLINE_LINUX="audit_backlog_limit={{ var_audit_backlog_limit }}
        "
      state: present
      dest: /etc/default/grub
      create: true
      mode: '0644'
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - '"grub2-common" in ansible_facts.packages'
    - argcheck is not skipped and linecheck is not skipped and argcheck.rc != 0 and
      linecheck.rc != 0
    tags:
    - 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: Replace existing audit_backlog_limit argument
    ansible.builtin.replace:
      path: /etc/default/grub
      regexp: audit_backlog_limit=[a-zA-Z0-9,]+
      replace: 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'
    - argcheck is not skipped and linecheck is not skipped and argcheck.rc == 0 and
      linecheck.rc == 0
    tags:
    - 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: Add audit_backlog_limit argument
    ansible.builtin.replace:
      path: /etc/default/grub
      regexp: (^\s*GRUB_CMDLINE_LINUX=.*)"
      replace: \1 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'
    - argcheck is not skipped and linecheck is not skipped and argcheck.rc != 0 and
      linecheck.rc == 0
    tags:
    - 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 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:
    - 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:
    - 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:
    - 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: Configure auditd Flush Priority
    ansible.builtin.lineinfile:
      dest: /etc/audit/auditd.conf
      regexp: ^\s*flush\s*=\s*.*$
      line: flush = {{ var_auditd_flush }}
      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-171-3.3.1
    - NIST-800-53-AU-11
    - NIST-800-53-CM-6(a)
    - auditd_data_retention_flush
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

Youez - 2016 - github.com/yon3zu
LinuXploit