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

Upload File :
current_dir [ Writeable ] document_root [ Writeable ]

 

Command :


[ Back ]     

Current File : /usr/share/scap-security-guide/ansible/ol9-playbook-anssi_bp28_intermediary.yml
---
###############################################################################
#
# Ansible Playbook for ANSSI-BP-028 (intermediary)
#
# Profile Description:
# This profile contains configurations that align to ANSSI-BP-028 at the intermediary hardening
# level. ANSSI is the French National Information Security Agency, and stands for Agence
# nationale de la sécurité des systèmes d'information. ANSSI-BP-028 is a configuration
# recommendation for GNU/Linux systems.
# A copy of the ANSSI-BP-028 can be found at the ANSSI website:
# https://www.ssi.gouv.fr/administration/guide/recommandations-de-securite-relatives-a-un-systeme-gnulinux/
#
# Profile ID:  xccdf_org.ssgproject.content_profile_anssi_bp28_intermediary
# Benchmark ID:  xccdf_org.ssgproject.content_benchmark_OL-9
# Benchmark Version:  0.1.80
# XCCDF Version:  1.2
#
# This file can be generated by OpenSCAP using:
# $ oscap xccdf generate fix --profile xccdf_org.ssgproject.content_profile_anssi_bp28_intermediary --fix-type ansible ssg-ol9-ds.xml
#
# This Ansible Playbook is generated from an XCCDF profile without preliminary evaluation.
# It attempts to fix every selected rule, even if the system is already compliant.
#
# How to apply this Ansible Playbook:
# $ ansible-playbook -i "localhost," -c local playbook.yml
# $ ansible-playbook -i "192.168.1.155," playbook.yml
# $ ansible-playbook -i inventory.ini playbook.yml
#
###############################################################################

- name: Ansible Playbook for xccdf_org.ssgproject.content_profile_anssi_bp28_intermediary
  hosts: all
  vars:
    var_authselect_profile: minimal
    var_password_pam_unix_remember: '2'
    var_accounts_passwords_pam_faillock_deny: '3'
    var_accounts_passwords_pam_faillock_fail_interval: '900'
    var_accounts_passwords_pam_faillock_unlock_time: '900'
    var_password_pam_dcredit: '-1'
    var_password_pam_lcredit: '-1'
    var_password_pam_minclass: '4'
    var_password_pam_minlen: '15'
    var_password_pam_ocredit: '-1'
    var_password_pam_retry: '3'
    var_password_pam_ucredit: '-1'
    var_password_hashing_algorithm_pam: sha512
    var_logind_session_timeout: '600'
    var_accounts_password_minlen_login_defs: '15'
    var_password_pam_unix_rounds: '65536'
    var_accounts_tmout: '600'
    var_user_initialization_files_regex: ^(\.bashrc|\.zshrc|\.cshrc|\.profile|\.bash_login|\.bash_profile)$
    var_l1tf_options: full,force
    var_mds_options: full,nosmt
    var_rng_core_default_quality: '500'
    var_spec_store_bypass_disable_options: seccomp
    sysctl_net_ipv6_conf_all_accept_ra_defrtr_value: '0'
    sysctl_net_ipv6_conf_all_accept_ra_pinfo_value: '0'
    sysctl_net_ipv6_conf_all_accept_ra_rtr_pref_value: '0'
    sysctl_net_ipv6_conf_all_accept_redirects_value: '0'
    sysctl_net_ipv6_conf_all_accept_source_route_value: '0'
    sysctl_net_ipv6_conf_all_autoconf_value: '0'
    sysctl_net_ipv6_conf_all_max_addresses_value: '1'
    sysctl_net_ipv6_conf_all_router_solicitations_value: '0'
    sysctl_net_ipv6_conf_default_accept_ra_defrtr_value: '0'
    sysctl_net_ipv6_conf_default_accept_ra_pinfo_value: '0'
    sysctl_net_ipv6_conf_default_accept_ra_rtr_pref_value: '0'
    sysctl_net_ipv6_conf_default_accept_redirects_value: '0'
    sysctl_net_ipv6_conf_default_accept_source_route_value: '0'
    sysctl_net_ipv6_conf_default_autoconf_value: '0'
    sysctl_net_ipv6_conf_default_max_addresses_value: '1'
    sysctl_net_ipv6_conf_default_router_solicitations_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_arp_filter_value: '0'
    sysctl_net_ipv4_conf_all_arp_ignore_value: '2'
    sysctl_net_ipv4_conf_all_rp_filter_value: '1'
    sysctl_net_ipv4_conf_all_secure_redirects_value: '0'
    sysctl_net_ipv4_conf_all_shared_media_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_rp_filter_value: '1'
    sysctl_net_ipv4_conf_default_secure_redirects_value: '0'
    sysctl_net_ipv4_conf_default_shared_media_value: '0'
    sysctl_net_ipv4_icmp_ignore_bogus_error_responses_value: '1'
    sysctl_net_ipv4_tcp_rfc1337_value: '1'
    sysctl_net_ipv4_tcp_syncookies_value: '1'
    sysctl_kernel_kptr_restrict_value: '2'
    var_slub_debug_options: FZP
    var_selinux_state: enforcing
    var_polyinstantiation_enabled: 'true'
    var_postfix_inet_interfaces: loopback-only
  tasks:

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

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

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

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

  - name: Ensure dnf-automatic is installed
    ansible.builtin.package:
      name: dnf-automatic
      state: present
    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:
    - enable_strategy
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - package_dnf-automatic_installed

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

  - name: Configure the polyinstantiation_enabled SELinux Boolean - Ensure python3-libsemanage
      Installed
    ansible.builtin.package:
      name: python3-libsemanage
      state: present
    when:
    - ( "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 or lookup("env", "container") == "bwrap-osbuild"
      or ansible_facts.selinux.status != "disabled" )
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - enable_strategy
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - sebool_polyinstantiation_enabled

  - name: 'Uninstall DHCP Server Package: Ensure dhcp is removed'
    ansible.builtin.package:
      name: dhcp
      state: absent
    tags:
    - NIST-800-53-CM-6(a)
    - NIST-800-53-CM-7(a)
    - NIST-800-53-CM-7(b)
    - PCI-DSSv4-2.2
    - PCI-DSSv4-2.2.4
    - disable_strategy
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - package_dhcp_removed

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

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

  - name: 'Remove telnet Clients: Ensure telnet is removed'
    ansible.builtin.package:
      name: telnet
      state: absent
    tags:
    - NIST-800-171-3.1.13
    - PCI-DSSv4-2.2
    - PCI-DSSv4-2.2.4
    - disable_strategy
    - low_complexity
    - low_disruption
    - low_severity
    - no_reboot_needed
    - package_telnet_removed

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

  - name: 'Remove tftp Daemon: Ensure tftp is removed'
    ansible.builtin.package:
      name: tftp
      state: absent
    tags:
    - PCI-DSSv4-2.2
    - PCI-DSSv4-2.2.4
    - disable_strategy
    - low_complexity
    - low_disruption
    - low_severity
    - no_reboot_needed
    - package_tftp_removed

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

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

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

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

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

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

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

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

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

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

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

  - name: Enable mount tmp
    ansible.builtin.systemd:
      name: tmp.mount
      enabled: 'yes'
      state: started
      masked: '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:
    - enable_strategy
    - low_complexity
    - low_disruption
    - low_severity
    - no_reboot_needed
    - systemd_tmp_mount_enabled

  - name: Check that the root group is defined
    ansible.builtin.getent:
      database: group
      key: root
    ignore_errors: true
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - directory_groupowner_etc_sudoersd_newgroup is undefined
    tags:
    - configure_strategy
    - directory_groupowner_etc_sudoersd
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

  - name: Set the directory_groupowner_etc_sudoersd_newgroup variable if root found
    ansible.builtin.set_fact:
      directory_groupowner_etc_sudoersd_newgroup: root
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - ansible_facts.getent_group["root"] is defined
    tags:
    - configure_strategy
    - directory_groupowner_etc_sudoersd
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

  - name: Ensure group owner on /etc/sudoers.d/
    ansible.builtin.file:
      path: /etc/sudoers.d/
      follow: false
      state: directory
      group: '{{ directory_groupowner_etc_sudoersd_newgroup }}'
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - configure_strategy
    - directory_groupowner_etc_sudoersd
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

  - name: Set the directory_owner_etc_sudoersd_newown variable if represented by uid
    ansible.builtin.set_fact:
      directory_owner_etc_sudoersd_newown: '0'
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - configure_strategy
    - directory_owner_etc_sudoersd
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

  - name: Ensure owner on directory /etc/sudoers.d/
    ansible.builtin.file:
      path: /etc/sudoers.d/
      follow: false
      state: directory
      owner: '{{ directory_owner_etc_sudoersd_newown }}'
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - configure_strategy
    - directory_owner_etc_sudoersd
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

  - name: Find /etc/sudoers.d/ file(s)
    ansible.builtin.command: 'find -P /etc/sudoers.d/ -maxdepth 0 -perm /u+s,g+ws,o+xwrt  -type
      d '
    register: files_found
    changed_when: false
    failed_when: false
    check_mode: false
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - configure_strategy
    - directory_permissions_etc_sudoersd
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

  - name: Set permissions for /etc/sudoers.d/ file(s)
    ansible.builtin.file:
      path: '{{ item }}'
      mode: u-s,g-ws,o-xwrt
      state: directory
    with_items:
    - '{{ files_found.stdout_lines }}'
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - configure_strategy
    - directory_permissions_etc_sudoersd
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

  - name: Check that the root group is defined
    ansible.builtin.getent:
      database: group
      key: root
    ignore_errors: true
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - file_groupowner_etc_sudoers_newgroup is undefined
    tags:
    - configure_strategy
    - file_groupowner_etc_sudoers
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

  - name: Set the file_groupowner_etc_sudoers_newgroup variable if root found
    ansible.builtin.set_fact:
      file_groupowner_etc_sudoers_newgroup: root
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - ansible_facts.getent_group["root"] is defined
    tags:
    - configure_strategy
    - file_groupowner_etc_sudoers
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

  - name: Test for existence /etc/sudoers
    ansible.builtin.stat:
      path: /etc/sudoers
    register: file_exists
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - configure_strategy
    - file_groupowner_etc_sudoers
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

  - name: Ensure group owner on /etc/sudoers
    ansible.builtin.file:
      path: /etc/sudoers
      follow: false
      group: '{{ file_groupowner_etc_sudoers_newgroup }}'
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - file_exists.stat is defined and file_exists.stat.exists
    tags:
    - configure_strategy
    - file_groupowner_etc_sudoers
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

  - name: Set the file_owner_etc_sudoers_newown variable if represented by uid
    ansible.builtin.set_fact:
      file_owner_etc_sudoers_newown: '0'
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - configure_strategy
    - file_owner_etc_sudoers
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

  - name: Test for existence /etc/sudoers
    ansible.builtin.stat:
      path: /etc/sudoers
    register: file_exists
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - configure_strategy
    - file_owner_etc_sudoers
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

  - name: Ensure owner on /etc/sudoers
    ansible.builtin.file:
      path: /etc/sudoers
      follow: false
      owner: '{{ file_owner_etc_sudoers_newown }}'
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - file_exists.stat is defined and file_exists.stat.exists
    tags:
    - configure_strategy
    - file_owner_etc_sudoers
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

  - name: Test for existence /etc/sudoers
    ansible.builtin.stat:
      path: /etc/sudoers
    register: file_exists
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - configure_strategy
    - file_permissions_etc_sudoers
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

  - name: Ensure permission u-xws,g-xws,o-xwrt on /etc/sudoers
    ansible.builtin.file:
      path: /etc/sudoers
      mode: u-xws,g-xws,o-xwrt
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - file_exists.stat is defined and file_exists.stat.exists
    tags:
    - configure_strategy
    - file_permissions_etc_sudoers
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

  - name: Ensure noexec is enabled in /etc/sudoers
    ansible.builtin.lineinfile:
      path: /etc/sudoers
      regexp: ^[\s]*Defaults.*\bnoexec\b.*$
      line: Defaults noexec
      validate: /usr/sbin/visudo -cf %s
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - high_severity
    - low_complexity
    - low_disruption
    - no_reboot_needed
    - restrict_strategy
    - sudo_add_noexec

  - name: Ensure requiretty is enabled in /etc/sudoers
    ansible.builtin.lineinfile:
      path: /etc/sudoers
      regexp: ^[\s]*Defaults.*\brequiretty\b.*$
      line: Defaults requiretty
      validate: /usr/sbin/visudo -cf %s
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy
    - sudo_add_requiretty

  - name: Ensure use_pty is enabled in /etc/sudoers
    ansible.builtin.lineinfile:
      path: /etc/sudoers
      regexp: ^[\s]*Defaults.*\buse_pty\b.*$
      line: Defaults use_pty
      validate: /usr/sbin/visudo -cf %s
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - '"sudo" in ansible_facts.packages'
    tags:
    - PCI-DSS-Req-10.2.5
    - PCI-DSSv4-2.2
    - PCI-DSSv4-2.2.6
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy
    - sudo_add_use_pty

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

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

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

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

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

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

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

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

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

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

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

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

  - name: Enable timer dnf-automatic
    block:

    - name: Enable timer dnf-automatic
      ansible.builtin.systemd:
        name: dnf-automatic.timer
        enabled: 'yes'
        state: started
      when:
      - '"dnf-automatic" in ansible_facts.packages'
    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:
    - NIST-800-53-CM-6(a)
    - NIST-800-53-SI-2(5)
    - NIST-800-53-SI-2(c)
    - enable_strategy
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - timer_dnf-automatic_enabled

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

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

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

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

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

  - name: Limit Password Reuse - Check if system relies on authselect tool
    ansible.builtin.stat:
      path: /usr/bin/authselect
    register: result_authselect_present
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - '"libpwquality" in ansible_facts.packages'
    tags:
    - CJIS-5.6.2.1.1
    - NIST-800-171-3.5.8
    - NIST-800-53-IA-5(1)(e)
    - NIST-800-53-IA-5(f)
    - PCI-DSS-Req-8.2.5
    - PCI-DSSv4-8.3
    - PCI-DSSv4-8.3.7
    - accounts_password_pam_unix_remember
    - configure_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - no_reboot_needed

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

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

    - name: Limit Password Reuse - Check integrity of authselect current profile
      ansible.builtin.command:
        cmd: authselect check
      register: result_authselect_check_cmd
      changed_when: false
      check_mode: false
      failed_when: false

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

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

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

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

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

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

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

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

      - name: Limit Password Reuse - Check integrity of authselect current profile
        ansible.builtin.command:
          cmd: authselect check
        register: result_authselect_check_cmd
        changed_when: false
        check_mode: false
        failed_when: false

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

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

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

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

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

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

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

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

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

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

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

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

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

    - name: Limit Password Reuse - Define a fact for control already filtered in case
        filters are used
      ansible.builtin.set_fact:
        pam_module_control: requisite

    - name: Limit Password Reuse - Check if expected PAM module line is present in
        {{ pam_file_path }}
      ansible.builtin.lineinfile:
        path: '{{ pam_file_path }}'
        regexp: ^\s*password\s+{{ pam_module_control | regex_escape() }}\s+pam_pwhistory.so\s*.*
        state: absent
      check_mode: true
      changed_when: false
      register: result_pam_line_present

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

      - name: Limit Password Reuse - Check if required PAM module line is present
          in {{ pam_file_path }} with different control
        ansible.builtin.lineinfile:
          path: '{{ pam_file_path }}'
          regexp: ^\s*password\s+.*\s+pam_pwhistory.so\s*
          state: absent
        check_mode: true
        changed_when: false
        register: result_pam_line_other_control_present

      - name: Limit Password Reuse - Ensure the correct control for the required PAM
          module line in {{ pam_file_path }}
        ansible.builtin.replace:
          dest: '{{ pam_file_path }}'
          regexp: ^(\s*password\s+).*(\bpam_pwhistory.so.*)
          replace: \1{{ pam_module_control }} \2
        register: result_pam_module_edit
        when:
        - result_pam_line_other_control_present.found == 1

      - name: Limit Password Reuse - Ensure the required PAM module line is included
          in {{ pam_file_path }}
        ansible.builtin.lineinfile:
          dest: '{{ pam_file_path }}'
          insertafter: ^password.*requisite.*pam_pwquality\.so
          line: password    {{ pam_module_control }}    pam_pwhistory.so
        register: result_pam_module_add
        when:
        - result_pam_line_other_control_present.found == 0 or result_pam_line_other_control_present.found
          > 1

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

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

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

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

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

      - name: Limit Password Reuse - Check if /etc/pam.d/system-auth file is present
        ansible.builtin.stat:
          path: /etc/pam.d/system-auth
        register: result_pam_auth_file_present

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

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

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

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

          - name: Limit Password Reuse - Check integrity of authselect current profile
            ansible.builtin.command:
              cmd: authselect check
            register: result_authselect_check_cmd
            changed_when: false
            check_mode: false
            failed_when: false

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

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

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

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

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

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

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

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

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

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

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

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

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

        - name: Limit Password Reuse - Define a fact for control already filtered
            in case filters are used
          ansible.builtin.set_fact:
            pam_module_control: ''

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

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

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

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

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

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

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

      - name: Limit Password Reuse - Check integrity of authselect current profile
        ansible.builtin.command:
          cmd: authselect check
        register: result_authselect_check_cmd
        changed_when: false
        check_mode: false
        failed_when: false

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

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

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

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

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

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

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

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

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

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

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

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

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

    - name: Limit Password Reuse - Define a fact for control already filtered in case
        filters are used
      ansible.builtin.set_fact:
        pam_module_control: requisite

    - name: Limit Password Reuse - Check if expected PAM module line is present in
        {{ pam_file_path }}
      ansible.builtin.lineinfile:
        path: '{{ pam_file_path }}'
        regexp: ^\s*password\s+{{ pam_module_control | regex_escape() }}\s+pam_pwhistory.so\s*.*
        state: absent
      check_mode: true
      changed_when: false
      register: result_pam_line_present

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

      - name: Limit Password Reuse - Check if required PAM module line is present
          in {{ pam_file_path }} with different control
        ansible.builtin.lineinfile:
          path: '{{ pam_file_path }}'
          regexp: ^\s*password\s+.*\s+pam_pwhistory.so\s*
          state: absent
        check_mode: true
        changed_when: false
        register: result_pam_line_other_control_present

      - name: Limit Password Reuse - Ensure the correct control for the required PAM
          module line in {{ pam_file_path }}
        ansible.builtin.replace:
          dest: '{{ pam_file_path }}'
          regexp: ^(\s*password\s+).*(\bpam_pwhistory.so.*)
          replace: \1{{ pam_module_control }} \2
        register: result_pam_module_edit
        when:
        - result_pam_line_other_control_present.found == 1

      - name: Limit Password Reuse - Ensure the required PAM module line is included
          in {{ pam_file_path }}
        ansible.builtin.lineinfile:
          dest: '{{ pam_file_path }}'
          line: password    {{ pam_module_control }}    pam_pwhistory.so
        register: result_pam_module_add
        when:
        - result_pam_line_other_control_present.found == 0 or result_pam_line_other_control_present.found
          > 1

      - name: Limit Password Reuse - Ensure authselect changes are applied
        ansible.builtin.command:
          cmd: authselect apply-changes -b
        when:
        - result_authselect_present is defined
        - result_authselect_present.stat.exists
        - |-
          (result_pam_module_add is defined and result_pam_module_add.changed)
           or (result_pam_module_edit is defined and result_pam_module_edit.changed)
      when:
      - result_pam_line_present.found is defined
      - result_pam_line_present.found == 0

    - name: Limit Password Reuse - Define a fact for control already filtered in case
        filters are used
      ansible.builtin.set_fact:
        pam_module_control: requisite

    - name: Limit Password Reuse - Check if the required PAM module option is present
        in {{ pam_file_path }}
      ansible.builtin.lineinfile:
        path: '{{ pam_file_path }}'
        regexp: ^\s*password\s+{{ pam_module_control | regex_escape() }}\s+pam_pwhistory.so\s*.*\sremember\b
        state: absent
      check_mode: true
      changed_when: false
      register: result_pam_module_accounts_password_pam_unix_remember_option_present

    - name: Limit Password Reuse - Ensure the "remember" PAM option for "pam_pwhistory.so"
        is included in {{ pam_file_path }}
      ansible.builtin.lineinfile:
        path: '{{ pam_file_path }}'
        backrefs: true
        regexp: ^(\s*password\s+{{ pam_module_control | regex_escape() }}\s+pam_pwhistory.so.*)
        line: \1 remember={{ var_password_pam_unix_remember }}
        state: present
      register: result_pam_accounts_password_pam_unix_remember_add
      when:
      - result_pam_module_accounts_password_pam_unix_remember_option_present.found
        is defined
      - result_pam_module_accounts_password_pam_unix_remember_option_present.found
        == 0

    - name: Limit Password Reuse - Ensure the required value for "remember" PAM option
        from "pam_pwhistory.so" in {{ pam_file_path }}
      ansible.builtin.lineinfile:
        path: '{{ pam_file_path }}'
        backrefs: true
        regexp: ^(\s*password\s+{{ pam_module_control | regex_escape() }}\s+pam_pwhistory.so\s+.*)(remember)=[0-9a-zA-Z]*\s*(.*)
        line: \1\2={{ var_password_pam_unix_remember }} \3
      register: result_pam_accounts_password_pam_unix_remember_edit
      when:
      - result_pam_module_accounts_password_pam_unix_remember_option_present.found
        > 0

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

  - name: Ensure PAM Enforces Password Requirements - Authentication Retry Prompts
      Permitted Per-Session - Define a fact for control already filtered in case filters
      are used
    ansible.builtin.set_fact:
      pam_module_control: requisite
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - '"libpwquality" in ansible_facts.packages'
    tags:
    - CJIS-5.5.3
    - NIST-800-53-AC-7(a)
    - NIST-800-53-CM-6(a)
    - NIST-800-53-IA-5(4)
    - accounts_password_pam_retry
    - configure_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - no_reboot_needed

  - name: Ensure PAM Enforces Password Requirements - Authentication Retry Prompts
      Permitted Per-Session - Check if expected PAM module line is present in /etc/pam.d/password-auth
    ansible.builtin.lineinfile:
      path: /etc/pam.d/password-auth
      regexp: ^\s*password\s+{{ pam_module_control | regex_escape() }}\s+pam_pwquality.so\s*.*
      state: absent
    check_mode: true
    changed_when: false
    register: result_pam_line_present
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - '"libpwquality" in ansible_facts.packages'
    tags:
    - CJIS-5.5.3
    - NIST-800-53-AC-7(a)
    - NIST-800-53-CM-6(a)
    - NIST-800-53-IA-5(4)
    - accounts_password_pam_retry
    - configure_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - no_reboot_needed

  - name: Ensure PAM Enforces Password Requirements - Authentication Retry Prompts
      Permitted Per-Session - Include or update the PAM module line in /etc/pam.d/password-auth
    block:

    - name: Ensure PAM Enforces Password Requirements - Authentication Retry Prompts
        Permitted Per-Session - Check if required PAM module line is present in /etc/pam.d/password-auth
        with different control
      ansible.builtin.lineinfile:
        path: /etc/pam.d/password-auth
        regexp: ^\s*password\s+.*\s+pam_pwquality.so\s*
        state: absent
      check_mode: true
      changed_when: false
      register: result_pam_line_other_control_present

    - name: Ensure PAM Enforces Password Requirements - Authentication Retry Prompts
        Permitted Per-Session - Ensure the correct control for the required PAM module
        line in /etc/pam.d/password-auth
      ansible.builtin.replace:
        dest: /etc/pam.d/password-auth
        regexp: ^(\s*password\s+).*(\bpam_pwquality.so.*)
        replace: \1{{ pam_module_control }} \2
      register: result_pam_module_edit
      when:
      - result_pam_line_other_control_present.found == 1

    - name: Ensure PAM Enforces Password Requirements - Authentication Retry Prompts
        Permitted Per-Session - Ensure the required PAM module line is included in
        /etc/pam.d/password-auth
      ansible.builtin.lineinfile:
        dest: /etc/pam.d/password-auth
        insertafter: ^\s*account
        line: password    {{ pam_module_control }}    pam_pwquality.so
      register: result_pam_module_add
      when:
      - result_pam_line_other_control_present.found == 0 or result_pam_line_other_control_present.found
        > 1

    - name: Ensure PAM Enforces Password Requirements - Authentication Retry Prompts
        Permitted Per-Session - 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:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - '"libpwquality" in ansible_facts.packages'
    - result_pam_line_present.found is defined
    - result_pam_line_present.found == 0
    tags:
    - CJIS-5.5.3
    - NIST-800-53-AC-7(a)
    - NIST-800-53-CM-6(a)
    - NIST-800-53-IA-5(4)
    - accounts_password_pam_retry
    - configure_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - no_reboot_needed

  - name: Ensure PAM Enforces Password Requirements - Authentication Retry Prompts
      Permitted Per-Session - Define a fact for control already filtered in case filters
      are used
    ansible.builtin.set_fact:
      pam_module_control: requisite
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - '"libpwquality" in ansible_facts.packages'
    tags:
    - CJIS-5.5.3
    - NIST-800-53-AC-7(a)
    - NIST-800-53-CM-6(a)
    - NIST-800-53-IA-5(4)
    - accounts_password_pam_retry
    - configure_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - no_reboot_needed

  - name: Ensure PAM Enforces Password Requirements - Authentication Retry Prompts
      Permitted Per-Session - Check if the required PAM module option is present in
      /etc/pam.d/password-auth
    ansible.builtin.lineinfile:
      path: /etc/pam.d/password-auth
      regexp: ^\s*password\s+{{ pam_module_control | regex_escape() }}\s+pam_pwquality.so\s*.*\sretry\b
      state: absent
    check_mode: true
    changed_when: false
    register: result_pam_module_accounts_password_pam_retry_option_present
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - '"libpwquality" in ansible_facts.packages'
    tags:
    - CJIS-5.5.3
    - NIST-800-53-AC-7(a)
    - NIST-800-53-CM-6(a)
    - NIST-800-53-IA-5(4)
    - accounts_password_pam_retry
    - configure_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - no_reboot_needed

  - name: Ensure PAM Enforces Password Requirements - Authentication Retry Prompts
      Permitted Per-Session - Ensure the "retry" PAM option for "pam_pwquality.so"
      is included in /etc/pam.d/password-auth
    ansible.builtin.lineinfile:
      path: /etc/pam.d/password-auth
      backrefs: true
      regexp: ^(\s*password\s+{{ pam_module_control | regex_escape() }}\s+pam_pwquality.so.*)
      line: \1 retry={{ var_password_pam_retry }}
      state: present
    register: result_pam_accounts_password_pam_retry_add
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - '"libpwquality" in ansible_facts.packages'
    - result_pam_module_accounts_password_pam_retry_option_present.found is defined
    - result_pam_module_accounts_password_pam_retry_option_present.found == 0
    tags:
    - CJIS-5.5.3
    - NIST-800-53-AC-7(a)
    - NIST-800-53-CM-6(a)
    - NIST-800-53-IA-5(4)
    - accounts_password_pam_retry
    - configure_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - no_reboot_needed

  - name: Ensure PAM Enforces Password Requirements - Authentication Retry Prompts
      Permitted Per-Session - Ensure the required value for "retry" PAM option from
      "pam_pwquality.so" in /etc/pam.d/password-auth
    ansible.builtin.lineinfile:
      path: /etc/pam.d/password-auth
      backrefs: true
      regexp: ^(\s*password\s+{{ pam_module_control | regex_escape() }}\s+pam_pwquality.so\s+.*)(retry)=[0-9a-zA-Z]*\s*(.*)
      line: \1\2={{ var_password_pam_retry }} \3
    register: result_pam_accounts_password_pam_retry_edit
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - '"libpwquality" in ansible_facts.packages'
    - result_pam_module_accounts_password_pam_retry_option_present.found > 0
    tags:
    - CJIS-5.5.3
    - NIST-800-53-AC-7(a)
    - NIST-800-53-CM-6(a)
    - NIST-800-53-IA-5(4)
    - accounts_password_pam_retry
    - configure_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - no_reboot_needed

  - name: Ensure PAM Enforces Password Requirements - Authentication Retry Prompts
      Permitted Per-Session - Define a fact for control already filtered in case filters
      are used
    ansible.builtin.set_fact:
      pam_module_control: requisite
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - '"libpwquality" in ansible_facts.packages'
    tags:
    - CJIS-5.5.3
    - NIST-800-53-AC-7(a)
    - NIST-800-53-CM-6(a)
    - NIST-800-53-IA-5(4)
    - accounts_password_pam_retry
    - configure_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - no_reboot_needed

  - name: Ensure PAM Enforces Password Requirements - Authentication Retry Prompts
      Permitted Per-Session - Check if expected PAM module line is present in /etc/pam.d/system-auth
    ansible.builtin.lineinfile:
      path: /etc/pam.d/system-auth
      regexp: ^\s*password\s+{{ pam_module_control | regex_escape() }}\s+pam_pwquality.so\s*.*
      state: absent
    check_mode: true
    changed_when: false
    register: result_pam_line_present
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - '"libpwquality" in ansible_facts.packages'
    tags:
    - CJIS-5.5.3
    - NIST-800-53-AC-7(a)
    - NIST-800-53-CM-6(a)
    - NIST-800-53-IA-5(4)
    - accounts_password_pam_retry
    - configure_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - no_reboot_needed

  - name: Ensure PAM Enforces Password Requirements - Authentication Retry Prompts
      Permitted Per-Session - Include or update the PAM module line in /etc/pam.d/system-auth
    block:

    - name: Ensure PAM Enforces Password Requirements - Authentication Retry Prompts
        Permitted Per-Session - Check if required PAM module line is present in /etc/pam.d/system-auth
        with different control
      ansible.builtin.lineinfile:
        path: /etc/pam.d/system-auth
        regexp: ^\s*password\s+.*\s+pam_pwquality.so\s*
        state: absent
      check_mode: true
      changed_when: false
      register: result_pam_line_other_control_present

    - name: Ensure PAM Enforces Password Requirements - Authentication Retry Prompts
        Permitted Per-Session - Ensure the correct control for the required PAM module
        line in /etc/pam.d/system-auth
      ansible.builtin.replace:
        dest: /etc/pam.d/system-auth
        regexp: ^(\s*password\s+).*(\bpam_pwquality.so.*)
        replace: \1{{ pam_module_control }} \2
      register: result_pam_module_edit
      when:
      - result_pam_line_other_control_present.found == 1

    - name: Ensure PAM Enforces Password Requirements - Authentication Retry Prompts
        Permitted Per-Session - Ensure the required PAM module line is included in
        /etc/pam.d/system-auth
      ansible.builtin.lineinfile:
        dest: /etc/pam.d/system-auth
        insertafter: ^\s*account
        line: password    {{ pam_module_control }}    pam_pwquality.so
      register: result_pam_module_add
      when:
      - result_pam_line_other_control_present.found == 0 or result_pam_line_other_control_present.found
        > 1

    - name: Ensure PAM Enforces Password Requirements - Authentication Retry Prompts
        Permitted Per-Session - 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:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - '"libpwquality" in ansible_facts.packages'
    - result_pam_line_present.found is defined
    - result_pam_line_present.found == 0
    tags:
    - CJIS-5.5.3
    - NIST-800-53-AC-7(a)
    - NIST-800-53-CM-6(a)
    - NIST-800-53-IA-5(4)
    - accounts_password_pam_retry
    - configure_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - no_reboot_needed

  - name: Ensure PAM Enforces Password Requirements - Authentication Retry Prompts
      Permitted Per-Session - Define a fact for control already filtered in case filters
      are used
    ansible.builtin.set_fact:
      pam_module_control: requisite
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - '"libpwquality" in ansible_facts.packages'
    tags:
    - CJIS-5.5.3
    - NIST-800-53-AC-7(a)
    - NIST-800-53-CM-6(a)
    - NIST-800-53-IA-5(4)
    - accounts_password_pam_retry
    - configure_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - no_reboot_needed

  - name: Ensure PAM Enforces Password Requirements - Authentication Retry Prompts
      Permitted Per-Session - Check if the required PAM module option is present in
      /etc/pam.d/system-auth
    ansible.builtin.lineinfile:
      path: /etc/pam.d/system-auth
      regexp: ^\s*password\s+{{ pam_module_control | regex_escape() }}\s+pam_pwquality.so\s*.*\sretry\b
      state: absent
    check_mode: true
    changed_when: false
    register: result_pam_module_accounts_password_pam_retry_option_present
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - '"libpwquality" in ansible_facts.packages'
    tags:
    - CJIS-5.5.3
    - NIST-800-53-AC-7(a)
    - NIST-800-53-CM-6(a)
    - NIST-800-53-IA-5(4)
    - accounts_password_pam_retry
    - configure_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - no_reboot_needed

  - name: Ensure PAM Enforces Password Requirements - Authentication Retry Prompts
      Permitted Per-Session - Ensure the "retry" PAM option for "pam_pwquality.so"
      is included in /etc/pam.d/system-auth
    ansible.builtin.lineinfile:
      path: /etc/pam.d/system-auth
      backrefs: true
      regexp: ^(\s*password\s+{{ pam_module_control | regex_escape() }}\s+pam_pwquality.so.*)
      line: \1 retry={{ var_password_pam_retry }}
      state: present
    register: result_pam_accounts_password_pam_retry_add
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - '"libpwquality" in ansible_facts.packages'
    - result_pam_module_accounts_password_pam_retry_option_present.found is defined
    - result_pam_module_accounts_password_pam_retry_option_present.found == 0
    tags:
    - CJIS-5.5.3
    - NIST-800-53-AC-7(a)
    - NIST-800-53-CM-6(a)
    - NIST-800-53-IA-5(4)
    - accounts_password_pam_retry
    - configure_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - no_reboot_needed

  - name: Ensure PAM Enforces Password Requirements - Authentication Retry Prompts
      Permitted Per-Session - Ensure the required value for "retry" PAM option from
      "pam_pwquality.so" in /etc/pam.d/system-auth
    ansible.builtin.lineinfile:
      path: /etc/pam.d/system-auth
      backrefs: true
      regexp: ^(\s*password\s+{{ pam_module_control | regex_escape() }}\s+pam_pwquality.so\s+.*)(retry)=[0-9a-zA-Z]*\s*(.*)
      line: \1\2={{ var_password_pam_retry }} \3
    register: result_pam_accounts_password_pam_retry_edit
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - '"libpwquality" in ansible_facts.packages'
    - result_pam_module_accounts_password_pam_retry_option_present.found > 0
    tags:
    - CJIS-5.5.3
    - NIST-800-53-AC-7(a)
    - NIST-800-53-CM-6(a)
    - NIST-800-53-IA-5(4)
    - accounts_password_pam_retry
    - configure_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - no_reboot_needed

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

  - name: Set PAM Password Hashing Algorithm - system-auth - Check if /etc/pam.d/system-auth
      file is present
    ansible.builtin.stat:
      path: /etc/pam.d/system-auth
    register: result_pam_auth_file_present
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - '"pam" in ansible_facts.packages'
    tags:
    - CJIS-5.6.2.2
    - NIST-800-171-3.13.11
    - NIST-800-53-CM-6(a)
    - NIST-800-53-IA-5(1)(c)
    - NIST-800-53-IA-5(c)
    - PCI-DSS-Req-8.2.1
    - PCI-DSSv4-8.3
    - PCI-DSSv4-8.3.2
    - configure_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - no_reboot_needed
    - set_password_hashing_algorithm_systemauth

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

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

    - name: Set PAM Password Hashing Algorithm - system-auth - Check if system relies
        on authselect tool
      ansible.builtin.stat:
        path: /usr/bin/authselect
      register: result_authselect_present

    - name: Set PAM Password Hashing Algorithm - system-auth - Ensure authselect custom
        profile is used if authselect is present
      block:

      - name: Set PAM Password Hashing Algorithm - system-auth - Check integrity of
          authselect current profile
        ansible.builtin.command:
          cmd: authselect check
        register: result_authselect_check_cmd
        changed_when: false
        check_mode: false
        failed_when: false

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

      - name: Set PAM Password Hashing Algorithm - system-auth - Get authselect current
          profile
        ansible.builtin.shell:
          cmd: authselect current -r | awk '{ print $1 }'
        register: result_authselect_profile
        changed_when: false
        when:
        - result_authselect_check_cmd is success

      - name: Set PAM Password Hashing Algorithm - system-auth - Define the current
          authselect profile as a local fact
        ansible.builtin.set_fact:
          authselect_current_profile: '{{ result_authselect_profile.stdout }}'
          authselect_custom_profile: '{{ result_authselect_profile.stdout }}'
        when:
        - result_authselect_profile is not skipped
        - result_authselect_profile.stdout is match("custom/")

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

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

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

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

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

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

      - name: Set PAM Password Hashing Algorithm - system-auth - Ensure the authselect
          custom profile is selected
        ansible.builtin.command:
          cmd: authselect select {{ authselect_custom_profile }}
        register: result_pam_authselect_select_profile
        when:
        - result_authselect_check_cmd is success
        - result_authselect_profile is not skipped
        - authselect_current_profile is not match("custom/")
        - authselect_custom_profile is not match(authselect_current_profile)

      - name: Set PAM Password Hashing Algorithm - system-auth - Restore the authselect
          features in the custom profile
        ansible.builtin.command:
          cmd: authselect enable-feature {{ item }}
        loop: '{{ result_authselect_features.stdout_lines }}'
        register: result_pam_authselect_restore_features
        when:
        - result_authselect_profile is not skipped
        - result_authselect_features is not skipped
        - result_pam_authselect_select_profile is not skipped

      - name: Set PAM Password Hashing Algorithm - system-auth - Ensure authselect
          changes are applied
        ansible.builtin.command:
          cmd: authselect apply-changes -b --backup=after-hardening-custom-profile
        when:
        - result_authselect_check_cmd is success
        - result_authselect_profile is not skipped
        - result_pam_authselect_restore_features is not skipped

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

    - name: Set PAM Password Hashing Algorithm - system-auth - Define a fact for control
        already filtered in case filters are used
      ansible.builtin.set_fact:
        pam_module_control: sufficient

    - name: Set PAM Password Hashing Algorithm - system-auth - Check if expected PAM
        module line is present in {{ pam_file_path }}
      ansible.builtin.lineinfile:
        path: '{{ pam_file_path }}'
        regexp: ^\s*password\s+{{ pam_module_control | regex_escape() }}\s+pam_unix.so\s*.*
        state: absent
      check_mode: true
      changed_when: false
      register: result_pam_line_present

    - name: Set PAM Password Hashing Algorithm - system-auth - Include or update the
        PAM module line in {{ pam_file_path }}
      block:

      - name: Set PAM Password Hashing Algorithm - system-auth - Check if required
          PAM module line is present in {{ pam_file_path }} with different control
        ansible.builtin.lineinfile:
          path: '{{ pam_file_path }}'
          regexp: ^\s*password\s+.*\s+pam_unix.so\s*
          state: absent
        check_mode: true
        changed_when: false
        register: result_pam_line_other_control_present

      - name: Set PAM Password Hashing Algorithm - system-auth - Ensure the correct
          control for the required PAM module line in {{ pam_file_path }}
        ansible.builtin.replace:
          dest: '{{ pam_file_path }}'
          regexp: ^(\s*password\s+).*(\bpam_unix.so.*)
          replace: \1{{ pam_module_control }} \2
        register: result_pam_module_edit
        when:
        - result_pam_line_other_control_present.found == 1

      - name: Set PAM Password Hashing Algorithm - system-auth - Ensure the required
          PAM module line is included in {{ pam_file_path }}
        ansible.builtin.lineinfile:
          dest: '{{ pam_file_path }}'
          line: password    {{ pam_module_control }}    pam_unix.so
        register: result_pam_module_add
        when:
        - result_pam_line_other_control_present.found == 0 or result_pam_line_other_control_present.found
          > 1

      - name: Set PAM Password Hashing Algorithm - system-auth - Ensure authselect
          changes are applied
        ansible.builtin.command:
          cmd: authselect apply-changes -b
        when:
        - result_authselect_present is defined
        - result_authselect_present.stat.exists
        - |-
          (result_pam_module_add is defined and result_pam_module_add.changed)
           or (result_pam_module_edit is defined and result_pam_module_edit.changed)
      when:
      - result_pam_line_present.found is defined
      - result_pam_line_present.found == 0

    - name: Set PAM Password Hashing Algorithm - system-auth - Define a fact for control
        already filtered in case filters are used
      ansible.builtin.set_fact:
        pam_module_control: sufficient

    - name: Set PAM Password Hashing Algorithm - system-auth - Check if the required
        PAM module option is present in {{ pam_file_path }}
      ansible.builtin.lineinfile:
        path: '{{ pam_file_path }}'
        regexp: ^\s*password\s+{{ pam_module_control | regex_escape() }}\s+pam_unix.so\s*.*\s{{
          var_password_hashing_algorithm_pam.split("|")[0] }}\b
        state: absent
      check_mode: true
      changed_when: false
      register: result_pam_module_set_password_hashing_algorithm_systemauth_option_present

    - name: Set PAM Password Hashing Algorithm - system-auth - Ensure the "{{ var_password_hashing_algorithm_pam.split("|")[0]
        }}" PAM option for "pam_unix.so" is included in {{ pam_file_path }}
      ansible.builtin.lineinfile:
        path: '{{ pam_file_path }}'
        backrefs: true
        regexp: ^(\s*password\s+{{ pam_module_control | regex_escape() }}\s+pam_unix.so.*)
        line: \1 {{ var_password_hashing_algorithm_pam.split("|")[0] }}
        state: present
      register: result_pam_set_password_hashing_algorithm_systemauth_add
      when:
      - result_pam_module_set_password_hashing_algorithm_systemauth_option_present.found
        is defined
      - result_pam_module_set_password_hashing_algorithm_systemauth_option_present.found
        == 0

    - name: Set PAM Password Hashing Algorithm - system-auth - Ensure authselect changes
        are applied
      ansible.builtin.command:
        cmd: authselect apply-changes -b
      when:
      - result_authselect_present.stat.exists
      - |-
        (result_pam_set_password_hashing_algorithm_systemauth_add is defined and result_pam_set_password_hashing_algorithm_systemauth_add.changed)
         or (result_pam_set_password_hashing_algorithm_systemauth_edit is defined and result_pam_set_password_hashing_algorithm_systemauth_edit.changed)
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - '"pam" in ansible_facts.packages'
    - result_pam_auth_file_present.stat.exists
    tags:
    - CJIS-5.6.2.2
    - NIST-800-171-3.13.11
    - NIST-800-53-CM-6(a)
    - NIST-800-53-IA-5(1)(c)
    - NIST-800-53-IA-5(c)
    - PCI-DSS-Req-8.2.1
    - PCI-DSSv4-8.3
    - PCI-DSSv4-8.3.2
    - configure_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - no_reboot_needed
    - set_password_hashing_algorithm_systemauth

  - name: Set PAM Password Hashing Algorithm - system-auth - Check if /etc/pam.d/system-auth
      File is Present
    ansible.builtin.stat:
      path: /etc/pam.d/system-auth
    register: result_pam_auth_file_present
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - '"pam" in ansible_facts.packages'
    tags:
    - CJIS-5.6.2.2
    - NIST-800-171-3.13.11
    - NIST-800-53-CM-6(a)
    - NIST-800-53-IA-5(1)(c)
    - NIST-800-53-IA-5(c)
    - PCI-DSS-Req-8.2.1
    - PCI-DSSv4-8.3
    - PCI-DSSv4-8.3.2
    - configure_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - no_reboot_needed
    - set_password_hashing_algorithm_systemauth

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

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

    - name: Set PAM Password Hashing Algorithm - system-auth - Check if system relies
        on authselect tool
      ansible.builtin.stat:
        path: /usr/bin/authselect
      register: result_authselect_present

    - name: Set PAM Password Hashing Algorithm - system-auth - Ensure authselect custom
        profile is used if authselect is present
      block:

      - name: Set PAM Password Hashing Algorithm - system-auth - Check integrity of
          authselect current profile
        ansible.builtin.command:
          cmd: authselect check
        register: result_authselect_check_cmd
        changed_when: false
        check_mode: false
        failed_when: false

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

      - name: Set PAM Password Hashing Algorithm - system-auth - Get authselect current
          profile
        ansible.builtin.shell:
          cmd: authselect current -r | awk '{ print $1 }'
        register: result_authselect_profile
        changed_when: false
        when:
        - result_authselect_check_cmd is success

      - name: Set PAM Password Hashing Algorithm - system-auth - Define the current
          authselect profile as a local fact
        ansible.builtin.set_fact:
          authselect_current_profile: '{{ result_authselect_profile.stdout }}'
          authselect_custom_profile: '{{ result_authselect_profile.stdout }}'
        when:
        - result_authselect_profile is not skipped
        - result_authselect_profile.stdout is match("custom/")

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

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

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

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

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

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

      - name: Set PAM Password Hashing Algorithm - system-auth - Ensure the authselect
          custom profile is selected
        ansible.builtin.command:
          cmd: authselect select {{ authselect_custom_profile }}
        register: result_pam_authselect_select_profile
        when:
        - result_authselect_check_cmd is success
        - result_authselect_profile is not skipped
        - authselect_current_profile is not match("custom/")
        - authselect_custom_profile is not match(authselect_current_profile)

      - name: Set PAM Password Hashing Algorithm - system-auth - Restore the authselect
          features in the custom profile
        ansible.builtin.command:
          cmd: authselect enable-feature {{ item }}
        loop: '{{ result_authselect_features.stdout_lines }}'
        register: result_pam_authselect_restore_features
        when:
        - result_authselect_profile is not skipped
        - result_authselect_features is not skipped
        - result_pam_authselect_select_profile is not skipped

      - name: Set PAM Password Hashing Algorithm - system-auth - Ensure authselect
          changes are applied
        ansible.builtin.command:
          cmd: authselect apply-changes -b --backup=after-hardening-custom-profile
        when:
        - result_authselect_check_cmd is success
        - result_authselect_profile is not skipped
        - result_pam_authselect_restore_features is not skipped

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

    - name: Set PAM Password Hashing Algorithm - system-auth - Check if "{{ pam_file_path
        }}" File is Present
      ansible.builtin.stat:
        path: '{{ pam_file_path }}'
      register: pam_file_path_present

    - name: Set PAM Password Hashing Algorithm - system-auth - Ensure That Only the
        Correct Hashing Algorithm Option For pam_unix.so Is Used in {{ pam_file_path
        }}
      ansible.builtin.replace:
        dest: '{{ pam_file_path }}'
        regexp: (^\s*password.*pam_unix\.so.*)\b{{ item }}\b\s*(.*)
        replace: \1\2
      when:
      - item != var_password_hashing_algorithm_pam.split('|')[0]
      - pam_file_path_present.stat.exists
      loop:
      - sha512
      - yescrypt
      - gost_yescrypt
      - blowfish
      - sha256
      - md5
      - bigcrypt
      register: result_pam_hashing_options_removal

    - name: Set PAM Password Hashing Algorithm - system-auth - Ensure authselect changes
        are applied
      ansible.builtin.command:
        cmd: authselect apply-changes -b
      when:
      - result_authselect_present.stat.exists
      - result_pam_hashing_options_removal is changed
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - '"pam" in ansible_facts.packages'
    - result_pam_auth_file_present.stat.exists
    tags:
    - CJIS-5.6.2.2
    - NIST-800-171-3.13.11
    - NIST-800-53-CM-6(a)
    - NIST-800-53-IA-5(1)(c)
    - NIST-800-53-IA-5(c)
    - PCI-DSS-Req-8.2.1
    - PCI-DSSv4-8.3
    - PCI-DSSv4-8.3.2
    - configure_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - no_reboot_needed
    - set_password_hashing_algorithm_systemauth

  - name: Set 'StopIdleSessionSec' to '{{ var_logind_session_timeout }}' in the [Login]
      section of '/etc/systemd/logind.conf.d/oscap-idle-sessions.conf'
    community.general.ini_file:
      path: /etc/systemd/logind.conf.d/oscap-idle-sessions.conf
      section: Login
      option: StopIdleSessionSec
      value: '{{ var_logind_session_timeout }}'
      create: true
      mode: 420
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - ( ansible_distribution == 'RedHat' and ansible_distribution_version is version('8.7',
      '>=') and ansible_distribution == 'RedHat' and ansible_distribution_version
      is version('9.0', '!=') ) or ansible_distribution == 'OracleLinux' and ansible_distribution_version
      is version('8.7', '>=') or ansible_distribution == 'SLES' and ansible_distribution_version
      is version('15', '>=')
    tags:
    - CJIS-5.5.6
    - 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
    - logind_session_timeout
    - low_complexity
    - low_disruption
    - medium_severity
    - reboot_required
    - 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: Set number of Password Hashing Rounds - password-auth - Check if /etc/pam.d/password-auth
      file is present
    ansible.builtin.stat:
      path: /etc/pam.d/password-auth
    register: result_pam_password_auth_file_present
    when: ( "pam" in ansible_facts.packages and ("kernel" in ansible_facts.packages
      or "kernel-uek" in ansible_facts.packages) )
    tags:
    - DISA-STIG-OL09-00-001065
    - accounts_password_pam_unix_rounds_password_auth
    - configure_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - no_reboot_needed

  - name: Set number of Password Hashing Rounds - password-auth - Check the proper
      remediation for the system
    block:

    - name: Set number of Password Hashing Rounds - password-auth - Define the PAM
        file to be edited as a local fact
      ansible.builtin.set_fact:
        pam_file_path: /etc/pam.d/password-auth

    - name: Set number of Password Hashing Rounds - password-auth - Check if system
        relies on authselect tool
      ansible.builtin.stat:
        path: /usr/bin/authselect
      register: result_authselect_present

    - name: Set number of Password Hashing Rounds - password-auth - Ensure authselect
        custom profile is used if authselect is present
      block:

      - name: Set number of Password Hashing Rounds - password-auth - Check integrity
          of authselect current profile
        ansible.builtin.command:
          cmd: authselect check
        register: result_authselect_check_cmd
        changed_when: false
        check_mode: false
        failed_when: false

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

      - name: Set number of Password Hashing Rounds - password-auth - Get authselect
          current profile
        ansible.builtin.shell:
          cmd: authselect current -r | awk '{ print $1 }'
        register: result_authselect_profile
        changed_when: false
        when:
        - result_authselect_check_cmd is success

      - name: Set number of Password Hashing Rounds - password-auth - Define the current
          authselect profile as a local fact
        ansible.builtin.set_fact:
          authselect_current_profile: '{{ result_authselect_profile.stdout }}'
          authselect_custom_profile: '{{ result_authselect_profile.stdout }}'
        when:
        - result_authselect_profile is not skipped
        - result_authselect_profile.stdout is match("custom/")

      - name: Set number of Password Hashing Rounds - password-auth - Define the new
          authselect custom profile as a local fact
        ansible.builtin.set_fact:
          authselect_current_profile: '{{ result_authselect_profile.stdout }}'
          authselect_custom_profile: custom/hardening
        when:
        - result_authselect_profile is not skipped
        - result_authselect_profile.stdout is not match("custom/")

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

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

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

      - name: Set number of Password Hashing Rounds - password-auth - Create an authselect
          custom profile based on sssd profile
        ansible.builtin.command:
          cmd: authselect create-profile hardening -b sssd
        when:
        - result_authselect_profile is not skipped
        - result_authselect_check_cmd is success
        - authselect_current_profile is match("local")
        - not result_authselect_custom_profile_present.stat.exists

      - name: Set number of Password Hashing Rounds - password-auth - Ensure authselect
          changes are applied
        ansible.builtin.command:
          cmd: authselect apply-changes -b --backup=before-hardening-custom-profile
        when:
        - result_authselect_check_cmd is success
        - result_authselect_profile is not skipped
        - authselect_current_profile is not match("custom/")
        - authselect_custom_profile is not match(authselect_current_profile)

      - name: Set number of Password Hashing Rounds - password-auth - Ensure the authselect
          custom profile is selected
        ansible.builtin.command:
          cmd: authselect select {{ authselect_custom_profile }}
        register: result_pam_authselect_select_profile
        when:
        - result_authselect_check_cmd is success
        - result_authselect_profile is not skipped
        - authselect_current_profile is not match("custom/")
        - authselect_custom_profile is not match(authselect_current_profile)

      - name: Set number of Password Hashing Rounds - password-auth - Restore the
          authselect features in the custom profile
        ansible.builtin.command:
          cmd: authselect enable-feature {{ item }}
        loop: '{{ result_authselect_features.stdout_lines }}'
        register: result_pam_authselect_restore_features
        when:
        - result_authselect_profile is not skipped
        - result_authselect_features is not skipped
        - result_pam_authselect_select_profile is not skipped

      - name: Set number of Password Hashing Rounds - password-auth - Ensure authselect
          changes are applied
        ansible.builtin.command:
          cmd: authselect apply-changes -b --backup=after-hardening-custom-profile
        when:
        - result_authselect_check_cmd is success
        - result_authselect_profile is not skipped
        - result_pam_authselect_restore_features is not skipped

      - name: Set number of Password Hashing Rounds - password-auth - Change the PAM
          file to be edited according to the custom authselect profile
        ansible.builtin.set_fact:
          pam_file_path: /etc/authselect/{{ authselect_custom_profile }}/{{ pam_file_path
            | basename }}
        when:
        - authselect_custom_profile is defined
      when:
      - result_authselect_present.stat.exists

    - name: Set number of Password Hashing Rounds - password-auth - Define a fact
        for control already filtered in case filters are used
      ansible.builtin.set_fact:
        pam_module_control: sufficient

    - name: Set number of Password Hashing Rounds - password-auth - Check if expected
        PAM module line is present in {{ pam_file_path }}
      ansible.builtin.lineinfile:
        path: '{{ pam_file_path }}'
        regexp: ^\s*password\s+{{ pam_module_control | regex_escape() }}\s+pam_unix.so\s*.*
        state: absent
      check_mode: true
      changed_when: false
      register: result_pam_line_present

    - name: Set number of Password Hashing Rounds - password-auth - Include or update
        the PAM module line in {{ pam_file_path }}
      block:

      - name: Set number of Password Hashing Rounds - password-auth - Check if required
          PAM module line is present in {{ pam_file_path }} with different control
        ansible.builtin.lineinfile:
          path: '{{ pam_file_path }}'
          regexp: ^\s*password\s+.*\s+pam_unix.so\s*
          state: absent
        check_mode: true
        changed_when: false
        register: result_pam_line_other_control_present

      - name: Set number of Password Hashing Rounds - password-auth - Ensure the correct
          control for the required PAM module line in {{ pam_file_path }}
        ansible.builtin.replace:
          dest: '{{ pam_file_path }}'
          regexp: ^(\s*password\s+).*(\bpam_unix.so.*)
          replace: \1{{ pam_module_control }} \2
        register: result_pam_module_edit
        when:
        - result_pam_line_other_control_present.found == 1

      - name: Set number of Password Hashing Rounds - password-auth - Ensure the required
          PAM module line is included in {{ pam_file_path }}
        ansible.builtin.lineinfile:
          dest: '{{ pam_file_path }}'
          line: password    {{ pam_module_control }}    pam_unix.so
        register: result_pam_module_add
        when:
        - result_pam_line_other_control_present.found == 0 or result_pam_line_other_control_present.found
          > 1

      - name: Set number of Password Hashing Rounds - password-auth - Ensure authselect
          changes are applied
        ansible.builtin.command:
          cmd: authselect apply-changes -b
        when:
        - result_authselect_present is defined
        - result_authselect_present.stat.exists
        - |-
          (result_pam_module_add is defined and result_pam_module_add.changed)
           or (result_pam_module_edit is defined and result_pam_module_edit.changed)
      when:
      - result_pam_line_present.found is defined
      - result_pam_line_present.found == 0

    - name: Set number of Password Hashing Rounds - password-auth - Define a fact
        for control already filtered in case filters are used
      ansible.builtin.set_fact:
        pam_module_control: sufficient

    - name: Set number of Password Hashing Rounds - password-auth - Check if the required
        PAM module option is present in {{ pam_file_path }}
      ansible.builtin.lineinfile:
        path: '{{ pam_file_path }}'
        regexp: ^\s*password\s+{{ pam_module_control | regex_escape() }}\s+pam_unix.so\s*.*\srounds\b
        state: absent
      check_mode: true
      changed_when: false
      register: result_pam_module_accounts_password_pam_unix_rounds_password_auth_option_present

    - name: Set number of Password Hashing Rounds - password-auth - Ensure the "rounds"
        PAM option for "pam_unix.so" is included in {{ pam_file_path }}
      ansible.builtin.lineinfile:
        path: '{{ pam_file_path }}'
        backrefs: true
        regexp: ^(\s*password\s+{{ pam_module_control | regex_escape() }}\s+pam_unix.so.*)
        line: \1 rounds={{ var_password_pam_unix_rounds }}
        state: present
      register: result_pam_accounts_password_pam_unix_rounds_password_auth_add
      when:
      - result_pam_module_accounts_password_pam_unix_rounds_password_auth_option_present.found
        is defined
      - result_pam_module_accounts_password_pam_unix_rounds_password_auth_option_present.found
        == 0

    - name: Set number of Password Hashing Rounds - password-auth - Ensure the required
        value for "rounds" PAM option from "pam_unix.so" in {{ pam_file_path }}
      ansible.builtin.lineinfile:
        path: '{{ pam_file_path }}'
        backrefs: true
        regexp: ^(\s*password\s+{{ pam_module_control | regex_escape() }}\s+pam_unix.so\s+.*)(rounds)=[0-9a-zA-Z]*\s*(.*)
        line: \1\2={{ var_password_pam_unix_rounds }} \3
      register: result_pam_accounts_password_pam_unix_rounds_password_auth_edit
      when:
      - result_pam_module_accounts_password_pam_unix_rounds_password_auth_option_present.found
        > 0

    - name: Set number of Password Hashing Rounds - password-auth - Ensure authselect
        changes are applied
      ansible.builtin.command:
        cmd: authselect apply-changes -b
      when:
      - result_authselect_present.stat.exists
      - |-
        (result_pam_accounts_password_pam_unix_rounds_password_auth_add is defined and result_pam_accounts_password_pam_unix_rounds_password_auth_add.changed)
         or (result_pam_accounts_password_pam_unix_rounds_password_auth_edit is defined and result_pam_accounts_password_pam_unix_rounds_password_auth_edit.changed)
    when:
    - ( "pam" in ansible_facts.packages and ("kernel" in ansible_facts.packages or
      "kernel-uek" in ansible_facts.packages) )
    - result_pam_password_auth_file_present.stat.exists
    tags:
    - DISA-STIG-OL09-00-001065
    - accounts_password_pam_unix_rounds_password_auth
    - configure_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - no_reboot_needed

  - name: Set number of Password Hashing Rounds - system-auth - Check if /etc/pam.d/system-auth
      file is present
    ansible.builtin.stat:
      path: /etc/pam.d/system-auth
    register: result_pam_auth_file_present
    when: ( "pam" in ansible_facts.packages and ("kernel" in ansible_facts.packages
      or "kernel-uek" in ansible_facts.packages) )
    tags:
    - DISA-STIG-OL09-00-001070
    - accounts_password_pam_unix_rounds_system_auth
    - configure_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - no_reboot_needed

  - name: Set number of Password Hashing Rounds - system-auth - Check the proper remediation
      for the system
    block:

    - name: Set number of Password Hashing Rounds - system-auth - Define the PAM file
        to be edited as a local fact
      ansible.builtin.set_fact:
        pam_file_path: /etc/pam.d/system-auth

    - name: Set number of Password Hashing Rounds - system-auth - Check if system
        relies on authselect tool
      ansible.builtin.stat:
        path: /usr/bin/authselect
      register: result_authselect_present

    - name: Set number of Password Hashing Rounds - system-auth - Ensure authselect
        custom profile is used if authselect is present
      block:

      - name: Set number of Password Hashing Rounds - system-auth - Check integrity
          of authselect current profile
        ansible.builtin.command:
          cmd: authselect check
        register: result_authselect_check_cmd
        changed_when: false
        check_mode: false
        failed_when: false

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

      - name: Set number of Password Hashing Rounds - system-auth - Get authselect
          current profile
        ansible.builtin.shell:
          cmd: authselect current -r | awk '{ print $1 }'
        register: result_authselect_profile
        changed_when: false
        when:
        - result_authselect_check_cmd is success

      - name: Set number of Password Hashing Rounds - system-auth - Define the current
          authselect profile as a local fact
        ansible.builtin.set_fact:
          authselect_current_profile: '{{ result_authselect_profile.stdout }}'
          authselect_custom_profile: '{{ result_authselect_profile.stdout }}'
        when:
        - result_authselect_profile is not skipped
        - result_authselect_profile.stdout is match("custom/")

      - name: Set number of Password Hashing Rounds - system-auth - Define the new
          authselect custom profile as a local fact
        ansible.builtin.set_fact:
          authselect_current_profile: '{{ result_authselect_profile.stdout }}'
          authselect_custom_profile: custom/hardening
        when:
        - result_authselect_profile is not skipped
        - result_authselect_profile.stdout is not match("custom/")

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

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

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

      - name: Set number of Password Hashing Rounds - system-auth - Create an authselect
          custom profile based on sssd profile
        ansible.builtin.command:
          cmd: authselect create-profile hardening -b sssd
        when:
        - result_authselect_profile is not skipped
        - result_authselect_check_cmd is success
        - authselect_current_profile is match("local")
        - not result_authselect_custom_profile_present.stat.exists

      - name: Set number of Password Hashing Rounds - system-auth - Ensure authselect
          changes are applied
        ansible.builtin.command:
          cmd: authselect apply-changes -b --backup=before-hardening-custom-profile
        when:
        - result_authselect_check_cmd is success
        - result_authselect_profile is not skipped
        - authselect_current_profile is not match("custom/")
        - authselect_custom_profile is not match(authselect_current_profile)

      - name: Set number of Password Hashing Rounds - system-auth - Ensure the authselect
          custom profile is selected
        ansible.builtin.command:
          cmd: authselect select {{ authselect_custom_profile }}
        register: result_pam_authselect_select_profile
        when:
        - result_authselect_check_cmd is success
        - result_authselect_profile is not skipped
        - authselect_current_profile is not match("custom/")
        - authselect_custom_profile is not match(authselect_current_profile)

      - name: Set number of Password Hashing Rounds - system-auth - Restore the authselect
          features in the custom profile
        ansible.builtin.command:
          cmd: authselect enable-feature {{ item }}
        loop: '{{ result_authselect_features.stdout_lines }}'
        register: result_pam_authselect_restore_features
        when:
        - result_authselect_profile is not skipped
        - result_authselect_features is not skipped
        - result_pam_authselect_select_profile is not skipped

      - name: Set number of Password Hashing Rounds - system-auth - Ensure authselect
          changes are applied
        ansible.builtin.command:
          cmd: authselect apply-changes -b --backup=after-hardening-custom-profile
        when:
        - result_authselect_check_cmd is success
        - result_authselect_profile is not skipped
        - result_pam_authselect_restore_features is not skipped

      - name: Set number of Password Hashing Rounds - system-auth - Change the PAM
          file to be edited according to the custom authselect profile
        ansible.builtin.set_fact:
          pam_file_path: /etc/authselect/{{ authselect_custom_profile }}/{{ pam_file_path
            | basename }}
        when:
        - authselect_custom_profile is defined
      when:
      - result_authselect_present.stat.exists

    - name: Set number of Password Hashing Rounds - system-auth - Define a fact for
        control already filtered in case filters are used
      ansible.builtin.set_fact:
        pam_module_control: sufficient

    - name: Set number of Password Hashing Rounds - system-auth - Check if expected
        PAM module line is present in {{ pam_file_path }}
      ansible.builtin.lineinfile:
        path: '{{ pam_file_path }}'
        regexp: ^\s*password\s+{{ pam_module_control | regex_escape() }}\s+pam_unix.so\s*.*
        state: absent
      check_mode: true
      changed_when: false
      register: result_pam_line_present

    - name: Set number of Password Hashing Rounds - system-auth - Include or update
        the PAM module line in {{ pam_file_path }}
      block:

      - name: Set number of Password Hashing Rounds - system-auth - Check if required
          PAM module line is present in {{ pam_file_path }} with different control
        ansible.builtin.lineinfile:
          path: '{{ pam_file_path }}'
          regexp: ^\s*password\s+.*\s+pam_unix.so\s*
          state: absent
        check_mode: true
        changed_when: false
        register: result_pam_line_other_control_present

      - name: Set number of Password Hashing Rounds - system-auth - Ensure the correct
          control for the required PAM module line in {{ pam_file_path }}
        ansible.builtin.replace:
          dest: '{{ pam_file_path }}'
          regexp: ^(\s*password\s+).*(\bpam_unix.so.*)
          replace: \1{{ pam_module_control }} \2
        register: result_pam_module_edit
        when:
        - result_pam_line_other_control_present.found == 1

      - name: Set number of Password Hashing Rounds - system-auth - Ensure the required
          PAM module line is included in {{ pam_file_path }}
        ansible.builtin.lineinfile:
          dest: '{{ pam_file_path }}'
          line: password    {{ pam_module_control }}    pam_unix.so
        register: result_pam_module_add
        when:
        - result_pam_line_other_control_present.found == 0 or result_pam_line_other_control_present.found
          > 1

      - name: Set number of Password Hashing Rounds - system-auth - Ensure authselect
          changes are applied
        ansible.builtin.command:
          cmd: authselect apply-changes -b
        when:
        - result_authselect_present is defined
        - result_authselect_present.stat.exists
        - |-
          (result_pam_module_add is defined and result_pam_module_add.changed)
           or (result_pam_module_edit is defined and result_pam_module_edit.changed)
      when:
      - result_pam_line_present.found is defined
      - result_pam_line_present.found == 0

    - name: Set number of Password Hashing Rounds - system-auth - Define a fact for
        control already filtered in case filters are used
      ansible.builtin.set_fact:
        pam_module_control: sufficient

    - name: Set number of Password Hashing Rounds - system-auth - Check if the required
        PAM module option is present in {{ pam_file_path }}
      ansible.builtin.lineinfile:
        path: '{{ pam_file_path }}'
        regexp: ^\s*password\s+{{ pam_module_control | regex_escape() }}\s+pam_unix.so\s*.*\srounds\b
        state: absent
      check_mode: true
      changed_when: false
      register: result_pam_module_accounts_password_pam_unix_rounds_system_auth_option_present

    - name: Set number of Password Hashing Rounds - system-auth - Ensure the "rounds"
        PAM option for "pam_unix.so" is included in {{ pam_file_path }}
      ansible.builtin.lineinfile:
        path: '{{ pam_file_path }}'
        backrefs: true
        regexp: ^(\s*password\s+{{ pam_module_control | regex_escape() }}\s+pam_unix.so.*)
        line: \1 rounds={{ var_password_pam_unix_rounds }}
        state: present
      register: result_pam_accounts_password_pam_unix_rounds_system_auth_add
      when:
      - result_pam_module_accounts_password_pam_unix_rounds_system_auth_option_present.found
        is defined
      - result_pam_module_accounts_password_pam_unix_rounds_system_auth_option_present.found
        == 0

    - name: Set number of Password Hashing Rounds - system-auth - Ensure the required
        value for "rounds" PAM option from "pam_unix.so" in {{ pam_file_path }}
      ansible.builtin.lineinfile:
        path: '{{ pam_file_path }}'
        backrefs: true
        regexp: ^(\s*password\s+{{ pam_module_control | regex_escape() }}\s+pam_unix.so\s+.*)(rounds)=[0-9a-zA-Z]*\s*(.*)
        line: \1\2={{ var_password_pam_unix_rounds }} \3
      register: result_pam_accounts_password_pam_unix_rounds_system_auth_edit
      when:
      - result_pam_module_accounts_password_pam_unix_rounds_system_auth_option_present.found
        > 0

    - name: Set number of Password Hashing Rounds - system-auth - Ensure authselect
        changes are applied
      ansible.builtin.command:
        cmd: authselect apply-changes -b
      when:
      - result_authselect_present.stat.exists
      - |-
        (result_pam_accounts_password_pam_unix_rounds_system_auth_add is defined and result_pam_accounts_password_pam_unix_rounds_system_auth_add.changed)
         or (result_pam_accounts_password_pam_unix_rounds_system_auth_edit is defined and result_pam_accounts_password_pam_unix_rounds_system_auth_edit.changed)
    when:
    - ( "pam" in ansible_facts.packages and ("kernel" in ansible_facts.packages or
      "kernel-uek" in ansible_facts.packages) )
    - result_pam_auth_file_present.stat.exists
    tags:
    - DISA-STIG-OL09-00-001070
    - accounts_password_pam_unix_rounds_system_auth
    - configure_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - no_reboot_needed

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

  - name: Correct any occurrence of TMOUT in /etc/profile
    ansible.builtin.replace:
      path: /etc/profile
      regexp: ^[^#].*TMOUT=.*
      replace: typeset -xr TMOUT={{ var_accounts_tmout }}
    register: profile_replaced
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-002411
    - NIST-800-171-3.1.11
    - NIST-800-53-AC-12
    - NIST-800-53-AC-2(5)
    - NIST-800-53-CM-6(a)
    - NIST-800-53-SC-10
    - PCI-DSSv4-8.6
    - PCI-DSSv4-8.6.1
    - accounts_tmout
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Set Interactive Session Timeout
    ansible.builtin.lineinfile:
      path: /etc/profile.d/tmout.sh
      create: true
      regexp: TMOUT=
      line: typeset -xr TMOUT={{ var_accounts_tmout }}
      state: present
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-002411
    - NIST-800-171-3.1.11
    - NIST-800-53-AC-12
    - NIST-800-53-AC-2(5)
    - NIST-800-53-CM-6(a)
    - NIST-800-53-SC-10
    - PCI-DSSv4-8.6
    - PCI-DSSv4-8.6.1
    - accounts_tmout
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: User Initialization Files Must Be Group-Owned By The Primary Group - Get
      interactive users from passwd file
    ansible.builtin.getent:
      database: passwd
    register: passwd_entries
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - accounts_user_dot_group_ownership
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: User Initialization Files Must Be Group-Owned By The Primary Group - Create
      list of interactive users with GID and home directory
    ansible.builtin.set_fact:
      interactive_users: '{{ interactive_users | default([]) + [{''home'': item.value[4],
        ''gid'': item.value[2]}] }}'
    loop: '{{ passwd_entries.ansible_facts.getent_passwd | dict2items }}'
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - item.value[2] | int >= 1000 | int
    - item.value[2] | int != 65534 | int
    - item.value[4] != ""
    tags:
    - accounts_user_dot_group_ownership
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: User Initialization Files Must Be Group-Owned By The Primary Group - Find
      dot files in interactive user home directories
    ansible.builtin.find:
      paths: '{{ item.home }}'
      patterns: .*
      file_type: file
      hidden: true
      depth: 1
      follow: false
    register: user_dotfiles
    loop: '{{ interactive_users | default([]) }}'
    failed_when: false
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - item.home != ""
    tags:
    - accounts_user_dot_group_ownership
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: User Initialization Files Must Be Group-Owned By The Primary Group - Set
      correct group ownership for user initialization files
    ansible.builtin.file:
      path: '{{ item.1.path }}'
      group: '{{ item.0.item.gid }}'
      follow: false
    loop: '{{ user_dotfiles.results | subelements(''files'', skip_missing=True) }}'
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - item.0 is not skipped
    - item.1.path is defined
    tags:
    - accounts_user_dot_group_ownership
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: User Initialization Files Must Be Owned By the Primary User - Get interactive
      users from passwd file
    ansible.builtin.getent:
      database: passwd
    register: passwd_entries
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - accounts_user_dot_user_ownership
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: User Initialization Files Must Be Owned By the Primary User - Create list
      of interactive users with UID and home directory
    ansible.builtin.set_fact:
      interactive_users: '{{ interactive_users | default([]) + [{''uid'': item.value[1],
        ''home'': item.value[4], ''username'': item.key}] }}'
    loop: '{{ passwd_entries.ansible_facts.getent_passwd | dict2items }}'
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - item.value[1] | int >= 1000 | int
    - item.value[1] | int != 65534 | int
    - item.value[4] != ""
    tags:
    - accounts_user_dot_user_ownership
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: User Initialization Files Must Be Owned By the Primary User - Find dot files
      in interactive user home directories
    ansible.builtin.find:
      paths: '{{ item.home }}'
      patterns: .*
      file_type: file
      hidden: true
      depth: 1
      follow: false
    register: user_dotfiles
    loop: '{{ interactive_users | default([]) }}'
    failed_when: false
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - item.home != ""
    tags:
    - accounts_user_dot_user_ownership
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: User Initialization Files Must Be Owned By the Primary User - Set correct
      ownership for user initialization files
    ansible.builtin.file:
      path: '{{ item.1.path }}'
      owner: '{{ item.0.item.username }}'
      follow: false
    loop: '{{ user_dotfiles.results | subelements(''files'', skip_missing=True) }}'
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - item.0 is not skipped
    - item.0 is not failed
    - item.0.item is defined
    - item.0.item.username is defined
    - item.1.path is defined
    tags:
    - accounts_user_dot_user_ownership
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Get all local users from /etc/passwd
    ansible.builtin.getent:
      database: passwd
      split: ':'
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - accounts_users_home_files_groupownership
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Create local_users variable from the getent output
    ansible.builtin.set_fact:
      local_users: '{{ ansible_facts.getent_passwd|dict2items }}'
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - accounts_users_home_files_groupownership
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Test for existence of home directories to avoid creating them, but only
      fixing ownership
    ansible.builtin.stat:
      path: '{{ item.value[4] }}'
    register: path_exists
    loop: '{{ local_users }}'
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - item.value[1]|int >= 1000
    - item.value[1]|int != 65534
    - item.value[4] != "/"
    tags:
    - accounts_users_home_files_groupownership
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Ensure interactive local users are the owners of their respective home directories
    ansible.builtin.file:
      path: '{{ item.0.value[4] }}'
      group: '{{ item.0.value[2] }}'
      recurse: true
    loop: '{{ local_users|zip(path_exists.results)|list }}'
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - item.1.stat is defined and item.1.stat.exists
    tags:
    - accounts_users_home_files_groupownership
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Get all local users from /etc/passwd
    ansible.builtin.getent:
      database: passwd
      split: ':'
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - accounts_users_home_files_ownership
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Create local_users variable from the getent output
    ansible.builtin.set_fact:
      local_users: '{{ ansible_facts.getent_passwd|dict2items }}'
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - accounts_users_home_files_ownership
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Test for existence of home directories to avoid creating them, but only
      fixing ownership
    ansible.builtin.stat:
      path: '{{ item.value[4] }}'
    register: path_exists
    loop: '{{ local_users }}'
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - item.value[1]|int >= 1000
    - item.value[1]|int != 65534
    - item.value[4] != "/"
    tags:
    - accounts_users_home_files_ownership
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Ensure interactive local users are the owners of their respective home directories
    ansible.builtin.file:
      path: '{{ item.0.value[4] }}'
      owner: '{{ item.0.value[1] }}'
      recurse: true
    loop: '{{ local_users|zip(path_exists.results)|list }}'
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - item.1.stat is defined and item.1.stat.exists
    tags:
    - accounts_users_home_files_ownership
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Get all local users from /etc/passwd
    ansible.builtin.getent:
      database: passwd
      split: ':'
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - accounts_users_home_files_permissions
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Create local_users variable from the getent output
    ansible.builtin.set_fact:
      local_users: '{{ ansible_facts.getent_passwd|dict2items }}'
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - accounts_users_home_files_permissions
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Test for existence home directories to avoid creating them.
    ansible.builtin.stat:
      path: '{{ item.value[4] }}'
    register: path_exists
    loop: '{{ local_users }}'
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - item.value[1]|int >= 1000
    - item.value[1]|int != 65534
    - item.value[4] != "/"
    tags:
    - accounts_users_home_files_permissions
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Ensure interactive local users have proper permissions on their respective
      home directories
    ansible.builtin.file:
      path: '{{ item.0.value[4] }}'
      mode: u-s,g-w-s,o=-
      follow: false
      recurse: true
    loop: '{{ local_users|zip(path_exists.results)|list }}'
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - item.1.stat is defined and item.1.stat.exists
    tags:
    - accounts_users_home_files_permissions
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Ensure All User Initialization Files Have Mode 0740 Or Less Permissive -
      Gather User Info
    ansible.builtin.getent:
      database: passwd
    tags:
    - file_permission_user_init_files
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Ensure All User Initialization Files Have Mode 0740 Or Less Permissive -
      Find Init Files
    ansible.builtin.find:
      paths: '{{ item.value[4] }}'
      pattern: '{{ var_user_initialization_files_regex }}'
      hidden: true
      use_regex: true
    with_dict: '{{ ansible_facts.getent_passwd }}'
    when:
    - item.value[4] != "/sbin/nologin"
    - item.key not in ["nobody", "nfsnobody"]
    - item.value[1] | int >= 1000
    register: found_init_files
    tags:
    - file_permission_user_init_files
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Ensure All User Initialization Files Have Mode 0740 Or Less Permissive -
      Fix Init Files Permissions
    ansible.builtin.file:
      path: '{{ item.1.path }}'
      mode: u-s,g-wxs,o=
    loop: '{{ q(''ansible.builtin.subelements'', found_init_files.results, ''files'',
      {''skip_missing'': True}) }}'
    tags:
    - file_permission_user_init_files
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Check if l1tf argument is already present in /etc/default/grub
    ansible.builtin.slurp:
      src: /etc/default/grub
    register: etc_default_grub
    when: ( "grub2-common" in ansible_facts.packages and ("kernel" in ansible_facts.packages
      or "kernel-uek" in ansible_facts.packages) )
    tags:
    - grub2_l1tf_argument
    - high_severity
    - low_disruption
    - medium_complexity
    - reboot_required
    - restrict_strategy

  - name: Check if l1tf argument is already present
    ansible.builtin.command: /sbin/grubby --info=ALL
    register: grubby_info
    check_mode: false
    changed_when: false
    failed_when: false
    when: ( "grub2-common" in ansible_facts.packages and ("kernel" in ansible_facts.packages
      or "kernel-uek" in ansible_facts.packages) )
    tags:
    - grub2_l1tf_argument
    - high_severity
    - low_disruption
    - medium_complexity
    - reboot_required
    - restrict_strategy

  - name: Update grub defaults and the bootloader menu
    ansible.builtin.command: /sbin/grubby --update-kernel=ALL --args="l1tf={{ var_l1tf_options
      }}"
    when:
    - ( "grub2-common" in ansible_facts.packages and ("kernel" in ansible_facts.packages
      or "kernel-uek" in ansible_facts.packages) )
    - (grubby_info.stdout is not search('l1tf=' ~ var_l1tf_options)) or ((etc_default_grub['content']
      | b64decode) is not search('l1tf=' ~ var_l1tf_options))
    tags:
    - grub2_l1tf_argument
    - high_severity
    - low_disruption
    - medium_complexity
    - reboot_required
    - restrict_strategy

  - name: Check if mce argument is already present in /etc/default/grub
    ansible.builtin.slurp:
      src: /etc/default/grub
    register: etc_default_grub
    when: ( "grub2-common" in ansible_facts.packages and ("kernel" in ansible_facts.packages
      or "kernel-uek" in ansible_facts.packages) )
    tags:
    - grub2_mce_argument
    - low_disruption
    - medium_complexity
    - medium_severity
    - reboot_required
    - restrict_strategy

  - name: Check if mce argument is already present
    ansible.builtin.command: /sbin/grubby --info=ALL
    register: grubby_info
    check_mode: false
    changed_when: false
    failed_when: false
    when: ( "grub2-common" in ansible_facts.packages and ("kernel" in ansible_facts.packages
      or "kernel-uek" in ansible_facts.packages) )
    tags:
    - grub2_mce_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="mce=0"
    when:
    - ( "grub2-common" in ansible_facts.packages and ("kernel" in ansible_facts.packages
      or "kernel-uek" in ansible_facts.packages) )
    - (grubby_info.stdout is not search('mce=0')) or ((etc_default_grub['content']
      | b64decode) is not search('mce=0'))
    tags:
    - grub2_mce_argument
    - low_disruption
    - medium_complexity
    - medium_severity
    - reboot_required
    - restrict_strategy

  - name: Check if mds argument is already present in /etc/default/grub
    ansible.builtin.slurp:
      src: /etc/default/grub
    register: etc_default_grub
    when: ( "grub2-common" in ansible_facts.packages and ("kernel" in ansible_facts.packages
      or "kernel-uek" in ansible_facts.packages) )
    tags:
    - grub2_mds_argument
    - low_disruption
    - medium_complexity
    - medium_severity
    - reboot_required
    - restrict_strategy

  - name: Check if mds argument is already present
    ansible.builtin.command: /sbin/grubby --info=ALL
    register: grubby_info
    check_mode: false
    changed_when: false
    failed_when: false
    when: ( "grub2-common" in ansible_facts.packages and ("kernel" in ansible_facts.packages
      or "kernel-uek" in ansible_facts.packages) )
    tags:
    - grub2_mds_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="mds={{ var_mds_options
      }}"
    when:
    - ( "grub2-common" in ansible_facts.packages and ("kernel" in ansible_facts.packages
      or "kernel-uek" in ansible_facts.packages) )
    - (grubby_info.stdout is not search('mds=' ~ var_mds_options)) or ((etc_default_grub['content']
      | b64decode) is not search('mds=' ~ var_mds_options))
    tags:
    - grub2_mds_argument
    - low_disruption
    - medium_complexity
    - medium_severity
    - reboot_required
    - restrict_strategy

  - name: Check if page_alloc.shuffle argument is already present in /etc/default/grub
    ansible.builtin.slurp:
      src: /etc/default/grub
    register: etc_default_grub
    when: ( "grub2-common" in ansible_facts.packages and ("kernel" in ansible_facts.packages
      or "kernel-uek" in ansible_facts.packages) )
    tags:
    - grub2_page_alloc_shuffle_argument
    - low_disruption
    - medium_complexity
    - medium_severity
    - reboot_required
    - restrict_strategy

  - name: Check if page_alloc.shuffle argument is already present
    ansible.builtin.command: /sbin/grubby --info=ALL
    register: grubby_info
    check_mode: false
    changed_when: false
    failed_when: false
    when: ( "grub2-common" in ansible_facts.packages and ("kernel" in ansible_facts.packages
      or "kernel-uek" in ansible_facts.packages) )
    tags:
    - grub2_page_alloc_shuffle_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_alloc.shuffle=1"
    when:
    - ( "grub2-common" in ansible_facts.packages and ("kernel" in ansible_facts.packages
      or "kernel-uek" in ansible_facts.packages) )
    - (grubby_info.stdout is not search('page_alloc.shuffle=1')) or ((etc_default_grub['content']
      | b64decode) is not search('page_alloc.shuffle=1'))
    tags:
    - grub2_page_alloc_shuffle_argument
    - low_disruption
    - medium_complexity
    - medium_severity
    - reboot_required
    - restrict_strategy

  - name: Check if pti argument is already present in /etc/default/grub
    ansible.builtin.slurp:
      src: /etc/default/grub
    register: etc_default_grub
    when: ( "grub2-common" in ansible_facts.packages and ("kernel" in ansible_facts.packages
      or "kernel-uek" in ansible_facts.packages) )
    tags:
    - DISA-STIG-OL09-00-002391
    - NIST-800-53-SI-16
    - grub2_pti_argument
    - low_disruption
    - low_severity
    - medium_complexity
    - reboot_required
    - restrict_strategy

  - name: Check if pti argument is already present
    ansible.builtin.command: /sbin/grubby --info=ALL
    register: grubby_info
    check_mode: false
    changed_when: false
    failed_when: false
    when: ( "grub2-common" in ansible_facts.packages and ("kernel" in ansible_facts.packages
      or "kernel-uek" in ansible_facts.packages) )
    tags:
    - DISA-STIG-OL09-00-002391
    - NIST-800-53-SI-16
    - grub2_pti_argument
    - low_disruption
    - low_severity
    - medium_complexity
    - reboot_required
    - restrict_strategy

  - name: Update grub defaults and the bootloader menu
    ansible.builtin.command: /sbin/grubby --update-kernel=ALL --args="pti=on"
    when:
    - ( "grub2-common" in ansible_facts.packages and ("kernel" in ansible_facts.packages
      or "kernel-uek" in ansible_facts.packages) )
    - (grubby_info.stdout is not search('pti=on')) or ((etc_default_grub['content']
      | b64decode) is not search('pti=on'))
    tags:
    - DISA-STIG-OL09-00-002391
    - NIST-800-53-SI-16
    - grub2_pti_argument
    - low_disruption
    - low_severity
    - medium_complexity
    - reboot_required
    - restrict_strategy

  - name: Check if rng_core.default_quality argument is already present in /etc/default/grub
    ansible.builtin.slurp:
      src: /etc/default/grub
    register: etc_default_grub
    when: ( "grub2-common" in ansible_facts.packages and ("kernel" in ansible_facts.packages
      or "kernel-uek" in ansible_facts.packages) )
    tags:
    - grub2_rng_core_default_quality_argument
    - low_disruption
    - low_severity
    - medium_complexity
    - reboot_required
    - restrict_strategy

  - name: Check if rng_core.default_quality argument is already present
    ansible.builtin.command: /sbin/grubby --info=ALL
    register: grubby_info
    check_mode: false
    changed_when: false
    failed_when: false
    when: ( "grub2-common" in ansible_facts.packages and ("kernel" in ansible_facts.packages
      or "kernel-uek" in ansible_facts.packages) )
    tags:
    - grub2_rng_core_default_quality_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="rng_core.default_quality={{
      var_rng_core_default_quality }}"
    when:
    - ( "grub2-common" in ansible_facts.packages and ("kernel" in ansible_facts.packages
      or "kernel-uek" in ansible_facts.packages) )
    - (grubby_info.stdout is not search('rng_core.default_quality=' ~ var_rng_core_default_quality))
      or ((etc_default_grub['content'] | b64decode) is not search('rng_core.default_quality='
      ~ var_rng_core_default_quality))
    tags:
    - grub2_rng_core_default_quality_argument
    - low_disruption
    - low_severity
    - medium_complexity
    - reboot_required
    - restrict_strategy

  - name: Check if slab_nomerge argument is already present in /etc/default/grub
    ansible.builtin.slurp:
      src: /etc/default/grub
    register: etc_default_grub
    when: ( "grub2-common" in ansible_facts.packages and ("kernel" in ansible_facts.packages
      or "kernel-uek" in ansible_facts.packages) )
    tags:
    - grub2_slab_nomerge_argument
    - low_disruption
    - medium_complexity
    - medium_severity
    - reboot_required
    - restrict_strategy

  - name: Check if slab_nomerge argument is already present
    ansible.builtin.command: /sbin/grubby --info=ALL
    register: grubby_info
    check_mode: false
    changed_when: false
    failed_when: false
    when: ( "grub2-common" in ansible_facts.packages and ("kernel" in ansible_facts.packages
      or "kernel-uek" in ansible_facts.packages) )
    tags:
    - grub2_slab_nomerge_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="slab_nomerge=yes"
    when:
    - ( "grub2-common" in ansible_facts.packages and ("kernel" in ansible_facts.packages
      or "kernel-uek" in ansible_facts.packages) )
    - (grubby_info.stdout is not search('slab_nomerge=yes')) or ((etc_default_grub['content']
      | b64decode) is not search('slab_nomerge=yes'))
    tags:
    - grub2_slab_nomerge_argument
    - low_disruption
    - medium_complexity
    - medium_severity
    - reboot_required
    - restrict_strategy

  - name: Check if spec_store_bypass_disable argument is already present in /etc/default/grub
    ansible.builtin.slurp:
      src: /etc/default/grub
    register: etc_default_grub
    when: ( "grub2-common" in ansible_facts.packages and ("kernel" in ansible_facts.packages
      or "kernel-uek" in ansible_facts.packages) )
    tags:
    - grub2_spec_store_bypass_disable_argument
    - low_disruption
    - medium_complexity
    - medium_severity
    - reboot_required
    - restrict_strategy

  - name: Check if spec_store_bypass_disable argument is already present
    ansible.builtin.command: /sbin/grubby --info=ALL
    register: grubby_info
    check_mode: false
    changed_when: false
    failed_when: false
    when: ( "grub2-common" in ansible_facts.packages and ("kernel" in ansible_facts.packages
      or "kernel-uek" in ansible_facts.packages) )
    tags:
    - grub2_spec_store_bypass_disable_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="spec_store_bypass_disable={{
      var_spec_store_bypass_disable_options }}"
    when:
    - ( "grub2-common" in ansible_facts.packages and ("kernel" in ansible_facts.packages
      or "kernel-uek" in ansible_facts.packages) )
    - (grubby_info.stdout is not search('spec_store_bypass_disable=' ~ var_spec_store_bypass_disable_options))
      or ((etc_default_grub['content'] | b64decode) is not search('spec_store_bypass_disable='
      ~ var_spec_store_bypass_disable_options))
    tags:
    - grub2_spec_store_bypass_disable_argument
    - low_disruption
    - medium_complexity
    - medium_severity
    - reboot_required
    - restrict_strategy

  - name: Check if spectre_v2 argument is already present in /etc/default/grub
    ansible.builtin.slurp:
      src: /etc/default/grub
    register: etc_default_grub
    when: ( "grub2-common" in ansible_facts.packages and ("kernel" in ansible_facts.packages
      or "kernel-uek" in ansible_facts.packages) )
    tags:
    - grub2_spectre_v2_argument
    - high_severity
    - low_disruption
    - medium_complexity
    - reboot_required
    - restrict_strategy

  - name: Check if spectre_v2 argument is already present
    ansible.builtin.command: /sbin/grubby --info=ALL
    register: grubby_info
    check_mode: false
    changed_when: false
    failed_when: false
    when: ( "grub2-common" in ansible_facts.packages and ("kernel" in ansible_facts.packages
      or "kernel-uek" in ansible_facts.packages) )
    tags:
    - grub2_spectre_v2_argument
    - high_severity
    - low_disruption
    - medium_complexity
    - reboot_required
    - restrict_strategy

  - name: Update grub defaults and the bootloader menu
    ansible.builtin.command: /sbin/grubby --update-kernel=ALL --args="spectre_v2=on"
    when:
    - ( "grub2-common" in ansible_facts.packages and ("kernel" in ansible_facts.packages
      or "kernel-uek" in ansible_facts.packages) )
    - (grubby_info.stdout is not search('spectre_v2=on')) or ((etc_default_grub['content']
      | b64decode) is not search('spectre_v2=on'))
    tags:
    - grub2_spectre_v2_argument
    - high_severity
    - low_disruption
    - medium_complexity
    - reboot_required
    - restrict_strategy

  - name: Check that the root group is defined
    ansible.builtin.getent:
      database: group
      key: root
    ignore_errors: true
    when:
    - '"libreswan" in ansible_facts.packages'
    - directory_groupowner_etc_ipsecd_newgroup is undefined
    tags:
    - configure_strategy
    - directory_groupowner_etc_ipsecd
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

  - name: Set the directory_groupowner_etc_ipsecd_newgroup variable if root found
    ansible.builtin.set_fact:
      directory_groupowner_etc_ipsecd_newgroup: root
    when:
    - '"libreswan" in ansible_facts.packages'
    - ansible_facts.getent_group["root"] is defined
    tags:
    - configure_strategy
    - directory_groupowner_etc_ipsecd
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

  - name: Ensure group owner on /etc/ipsec.d/
    ansible.builtin.file:
      path: /etc/ipsec.d/
      follow: false
      state: directory
      group: '{{ directory_groupowner_etc_ipsecd_newgroup }}'
    when: '"libreswan" in ansible_facts.packages'
    tags:
    - configure_strategy
    - directory_groupowner_etc_ipsecd
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

  - name: Set the directory_owner_etc_ipsecd_newown variable if represented by uid
    ansible.builtin.set_fact:
      directory_owner_etc_ipsecd_newown: '0'
    when: '"libreswan" in ansible_facts.packages'
    tags:
    - configure_strategy
    - directory_owner_etc_ipsecd
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

  - name: Ensure owner on directory /etc/ipsec.d/
    ansible.builtin.file:
      path: /etc/ipsec.d/
      follow: false
      state: directory
      owner: '{{ directory_owner_etc_ipsecd_newown }}'
    when: '"libreswan" in ansible_facts.packages'
    tags:
    - configure_strategy
    - directory_owner_etc_ipsecd
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

  - name: Find /etc/ipsec.d/ file(s)
    ansible.builtin.command: 'find -P /etc/ipsec.d/ -maxdepth 0 -perm /u+s,g+xwrs,o+xwrt  -type
      d '
    register: files_found
    changed_when: false
    failed_when: false
    check_mode: false
    when: '"libreswan" in ansible_facts.packages'
    tags:
    - configure_strategy
    - directory_permissions_etc_ipsecd
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

  - name: Set permissions for /etc/ipsec.d/ file(s)
    ansible.builtin.file:
      path: '{{ item }}'
      mode: u-s,g-xwrs,o-xwrt
      state: directory
    with_items:
    - '{{ files_found.stdout_lines }}'
    when: '"libreswan" in ansible_facts.packages'
    tags:
    - configure_strategy
    - directory_permissions_etc_ipsecd
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

  - name: Check that the root group is defined
    ansible.builtin.getent:
      database: group
      key: root
    ignore_errors: true
    when:
    - '"libreswan" in ansible_facts.packages'
    - file_groupowner_etc_ipsec_conf_newgroup is undefined
    tags:
    - configure_strategy
    - file_groupowner_etc_ipsec_conf
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

  - name: Set the file_groupowner_etc_ipsec_conf_newgroup variable if root found
    ansible.builtin.set_fact:
      file_groupowner_etc_ipsec_conf_newgroup: root
    when:
    - '"libreswan" in ansible_facts.packages'
    - ansible_facts.getent_group["root"] is defined
    tags:
    - configure_strategy
    - file_groupowner_etc_ipsec_conf
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

  - name: Test for existence /etc/ipsec.conf
    ansible.builtin.stat:
      path: /etc/ipsec.conf
    register: file_exists
    when: '"libreswan" in ansible_facts.packages'
    tags:
    - configure_strategy
    - file_groupowner_etc_ipsec_conf
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

  - name: Ensure group owner on /etc/ipsec.conf
    ansible.builtin.file:
      path: /etc/ipsec.conf
      follow: false
      group: '{{ file_groupowner_etc_ipsec_conf_newgroup }}'
    when:
    - '"libreswan" in ansible_facts.packages'
    - file_exists.stat is defined and file_exists.stat.exists
    tags:
    - configure_strategy
    - file_groupowner_etc_ipsec_conf
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

  - name: Check that the root group is defined
    ansible.builtin.getent:
      database: group
      key: root
    ignore_errors: true
    when:
    - '"libreswan" in ansible_facts.packages'
    - file_groupowner_etc_ipsec_secrets_newgroup is undefined
    tags:
    - configure_strategy
    - file_groupowner_etc_ipsec_secrets
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

  - name: Set the file_groupowner_etc_ipsec_secrets_newgroup variable if root found
    ansible.builtin.set_fact:
      file_groupowner_etc_ipsec_secrets_newgroup: root
    when:
    - '"libreswan" in ansible_facts.packages'
    - ansible_facts.getent_group["root"] is defined
    tags:
    - configure_strategy
    - file_groupowner_etc_ipsec_secrets
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

  - name: Test for existence /etc/ipsec.secrets
    ansible.builtin.stat:
      path: /etc/ipsec.secrets
    register: file_exists
    when: '"libreswan" in ansible_facts.packages'
    tags:
    - configure_strategy
    - file_groupowner_etc_ipsec_secrets
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

  - name: Ensure group owner on /etc/ipsec.secrets
    ansible.builtin.file:
      path: /etc/ipsec.secrets
      follow: false
      group: '{{ file_groupowner_etc_ipsec_secrets_newgroup }}'
    when:
    - '"libreswan" in ansible_facts.packages'
    - file_exists.stat is defined and file_exists.stat.exists
    tags:
    - configure_strategy
    - file_groupowner_etc_ipsec_secrets
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

  - name: Set the file_owner_etc_ipsec_conf_newown variable if represented by uid
    ansible.builtin.set_fact:
      file_owner_etc_ipsec_conf_newown: '0'
    when: '"libreswan" in ansible_facts.packages'
    tags:
    - configure_strategy
    - file_owner_etc_ipsec_conf
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

  - name: Test for existence /etc/ipsec.conf
    ansible.builtin.stat:
      path: /etc/ipsec.conf
    register: file_exists
    when: '"libreswan" in ansible_facts.packages'
    tags:
    - configure_strategy
    - file_owner_etc_ipsec_conf
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

  - name: Ensure owner on /etc/ipsec.conf
    ansible.builtin.file:
      path: /etc/ipsec.conf
      follow: false
      owner: '{{ file_owner_etc_ipsec_conf_newown }}'
    when:
    - '"libreswan" in ansible_facts.packages'
    - file_exists.stat is defined and file_exists.stat.exists
    tags:
    - configure_strategy
    - file_owner_etc_ipsec_conf
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

  - name: Set the file_owner_etc_ipsec_secrets_newown variable if represented by uid
    ansible.builtin.set_fact:
      file_owner_etc_ipsec_secrets_newown: '0'
    when: '"libreswan" in ansible_facts.packages'
    tags:
    - configure_strategy
    - file_owner_etc_ipsec_secrets
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

  - name: Test for existence /etc/ipsec.secrets
    ansible.builtin.stat:
      path: /etc/ipsec.secrets
    register: file_exists
    when: '"libreswan" in ansible_facts.packages'
    tags:
    - configure_strategy
    - file_owner_etc_ipsec_secrets
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

  - name: Ensure owner on /etc/ipsec.secrets
    ansible.builtin.file:
      path: /etc/ipsec.secrets
      follow: false
      owner: '{{ file_owner_etc_ipsec_secrets_newown }}'
    when:
    - '"libreswan" in ansible_facts.packages'
    - file_exists.stat is defined and file_exists.stat.exists
    tags:
    - configure_strategy
    - file_owner_etc_ipsec_secrets
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

  - name: Test for existence /etc/ipsec.conf
    ansible.builtin.stat:
      path: /etc/ipsec.conf
    register: file_exists
    when: '"libreswan" in ansible_facts.packages'
    tags:
    - configure_strategy
    - file_permissions_etc_ipsec_conf
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

  - name: Ensure permission u-xs,g-xws,o-xwt on /etc/ipsec.conf
    ansible.builtin.file:
      path: /etc/ipsec.conf
      mode: u-xs,g-xws,o-xwt
    when:
    - '"libreswan" in ansible_facts.packages'
    - file_exists.stat is defined and file_exists.stat.exists
    tags:
    - configure_strategy
    - file_permissions_etc_ipsec_conf
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

  - name: Test for existence /etc/ipsec.secrets
    ansible.builtin.stat:
      path: /etc/ipsec.secrets
    register: file_exists
    when: '"libreswan" in ansible_facts.packages'
    tags:
    - configure_strategy
    - file_permissions_etc_ipsec_secrets
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

  - name: Ensure permission u-xs,g-xws,o-xwt on /etc/ipsec.secrets
    ansible.builtin.file:
      path: /etc/ipsec.secrets
      mode: u-xs,g-xws,o-xwt
    when:
    - '"libreswan" in ansible_facts.packages'
    - file_exists.stat is defined and file_exists.stat.exists
    tags:
    - configure_strategy
    - file_permissions_etc_ipsec_secrets
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

  - name: Check that the root group is defined
    ansible.builtin.getent:
      database: group
      key: root
    ignore_errors: true
    when:
    - '"iptables" in ansible_facts.packages'
    - directory_groupowner_etc_iptables_newgroup is undefined
    tags:
    - configure_strategy
    - directory_groupowner_etc_iptables
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

  - name: Set the directory_groupowner_etc_iptables_newgroup variable if root found
    ansible.builtin.set_fact:
      directory_groupowner_etc_iptables_newgroup: root
    when:
    - '"iptables" in ansible_facts.packages'
    - ansible_facts.getent_group["root"] is defined
    tags:
    - configure_strategy
    - directory_groupowner_etc_iptables
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

  - name: Ensure group owner on /etc/iptables/
    ansible.builtin.file:
      path: /etc/iptables/
      follow: false
      state: directory
      group: '{{ directory_groupowner_etc_iptables_newgroup }}'
    when: '"iptables" in ansible_facts.packages'
    tags:
    - configure_strategy
    - directory_groupowner_etc_iptables
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

  - name: Set the directory_owner_etc_iptables_newown variable if represented by uid
    ansible.builtin.set_fact:
      directory_owner_etc_iptables_newown: '0'
    when: '"iptables" in ansible_facts.packages'
    tags:
    - configure_strategy
    - directory_owner_etc_iptables
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

  - name: Ensure owner on directory /etc/iptables/
    ansible.builtin.file:
      path: /etc/iptables/
      follow: false
      state: directory
      owner: '{{ directory_owner_etc_iptables_newown }}'
    when: '"iptables" in ansible_facts.packages'
    tags:
    - configure_strategy
    - directory_owner_etc_iptables
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

  - name: Find /etc/iptables/ file(s)
    ansible.builtin.command: 'find -P /etc/iptables/ -maxdepth 0 -perm /u+s,g+xwrs,o+xwrt  -type
      d '
    register: files_found
    changed_when: false
    failed_when: false
    check_mode: false
    when: '"iptables" in ansible_facts.packages'
    tags:
    - configure_strategy
    - directory_permissions_etc_iptables
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

  - name: Set permissions for /etc/iptables/ file(s)
    ansible.builtin.file:
      path: '{{ item }}'
      mode: u-s,g-xwrs,o-xwrt
      state: directory
    with_items:
    - '{{ files_found.stdout_lines }}'
    when: '"iptables" in ansible_facts.packages'
    tags:
    - configure_strategy
    - directory_permissions_etc_iptables
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

  - name: Configure Accepting Default Router in 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:
    - disable_strategy
    - low_complexity
    - medium_disruption
    - reboot_required
    - sysctl_net_ipv6_conf_all_accept_ra_defrtr
    - unknown_severity

  - name: Configure Accepting Default Router in Router Advertisements on All IPv6
      Interfaces - Find all files that contain net.ipv6.conf.all.accept_ra_defrtr
    ansible.builtin.shell:
      cmd: find -L {{ sysctl_paths | join(" ") }} -type f -name '*.conf' | xargs grep
        -HP '^\s*net.ipv6.conf.all.accept_ra_defrtr\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:
    - disable_strategy
    - low_complexity
    - medium_disruption
    - reboot_required
    - sysctl_net_ipv6_conf_all_accept_ra_defrtr
    - unknown_severity

  - name: Configure Accepting Default Router in Router Advertisements on All IPv6
      Interfaces - Find all files that set net.ipv6.conf.all.accept_ra_defrtr 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_defrtr\s*=\s*{{ sysctl_net_ipv6_conf_all_accept_ra_defrtr_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:
    - disable_strategy
    - low_complexity
    - medium_disruption
    - reboot_required
    - sysctl_net_ipv6_conf_all_accept_ra_defrtr
    - unknown_severity

  - name: Configure Accepting Default Router in Router Advertisements on All IPv6
      Interfaces - Comment out any occurrences of net.ipv6.conf.all.accept_ra_defrtr
      from config files
    ansible.builtin.replace:
      path: '{{ item | split(":") | first }}'
      regexp: ^[\s]*net.ipv6.conf.all.accept_ra_defrtr
      replace: '#net.ipv6.conf.all.accept_ra_defrtr'
    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:
    - disable_strategy
    - low_complexity
    - medium_disruption
    - reboot_required
    - sysctl_net_ipv6_conf_all_accept_ra_defrtr
    - unknown_severity

  - name: Configure Accepting Default Router in Router Advertisements on All IPv6
      Interfaces - Comment out any occurrences of net.ipv6.conf.all.accept_ra_defrtr
      from /etc/sysctl.conf
    ansible.builtin.replace:
      path: '{{ item }}'
      regexp: ^[\s]*net.ipv6.conf.all.accept_ra_defrtr
      replace: '#net.ipv6.conf.all.accept_ra_defrtr'
    with_fileglob:
    - /etc/sysctl.conf
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - disable_strategy
    - low_complexity
    - medium_disruption
    - reboot_required
    - sysctl_net_ipv6_conf_all_accept_ra_defrtr
    - unknown_severity

  - name: Configure Accepting Default Router in Router Advertisements on All IPv6
      Interfaces - Ensure sysctl net.ipv6.conf.all.accept_ra_defrtr is set
    ansible.posix.sysctl:
      name: net.ipv6.conf.all.accept_ra_defrtr
      value: '{{ sysctl_net_ipv6_conf_all_accept_ra_defrtr_value }}'
      sysctl_file: /etc/sysctl.d/net_ipv6_conf_all_accept_ra_defrtr.conf
      state: present
      reload: true
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - disable_strategy
    - low_complexity
    - medium_disruption
    - reboot_required
    - sysctl_net_ipv6_conf_all_accept_ra_defrtr
    - unknown_severity

  - name: Configure Accepting Prefix Information in 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:
    - disable_strategy
    - low_complexity
    - medium_disruption
    - reboot_required
    - sysctl_net_ipv6_conf_all_accept_ra_pinfo
    - unknown_severity

  - name: Configure Accepting Prefix Information in Router Advertisements on All IPv6
      Interfaces - Find all files that contain net.ipv6.conf.all.accept_ra_pinfo
    ansible.builtin.shell:
      cmd: find -L {{ sysctl_paths | join(" ") }} -type f -name '*.conf' | xargs grep
        -HP '^\s*net.ipv6.conf.all.accept_ra_pinfo\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:
    - disable_strategy
    - low_complexity
    - medium_disruption
    - reboot_required
    - sysctl_net_ipv6_conf_all_accept_ra_pinfo
    - unknown_severity

  - name: Configure Accepting Prefix Information in Router Advertisements on All IPv6
      Interfaces - Find all files that set net.ipv6.conf.all.accept_ra_pinfo 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_pinfo\s*=\s*{{ sysctl_net_ipv6_conf_all_accept_ra_pinfo_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:
    - disable_strategy
    - low_complexity
    - medium_disruption
    - reboot_required
    - sysctl_net_ipv6_conf_all_accept_ra_pinfo
    - unknown_severity

  - name: Configure Accepting Prefix Information in Router Advertisements on All IPv6
      Interfaces - Comment out any occurrences of net.ipv6.conf.all.accept_ra_pinfo
      from config files
    ansible.builtin.replace:
      path: '{{ item | split(":") | first }}'
      regexp: ^[\s]*net.ipv6.conf.all.accept_ra_pinfo
      replace: '#net.ipv6.conf.all.accept_ra_pinfo'
    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:
    - disable_strategy
    - low_complexity
    - medium_disruption
    - reboot_required
    - sysctl_net_ipv6_conf_all_accept_ra_pinfo
    - unknown_severity

  - name: Configure Accepting Prefix Information in Router Advertisements on All IPv6
      Interfaces - Comment out any occurrences of net.ipv6.conf.all.accept_ra_pinfo
      from /etc/sysctl.conf
    ansible.builtin.replace:
      path: '{{ item }}'
      regexp: ^[\s]*net.ipv6.conf.all.accept_ra_pinfo
      replace: '#net.ipv6.conf.all.accept_ra_pinfo'
    with_fileglob:
    - /etc/sysctl.conf
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - disable_strategy
    - low_complexity
    - medium_disruption
    - reboot_required
    - sysctl_net_ipv6_conf_all_accept_ra_pinfo
    - unknown_severity

  - name: Configure Accepting Prefix Information in Router Advertisements on All IPv6
      Interfaces - Ensure sysctl net.ipv6.conf.all.accept_ra_pinfo is set
    ansible.posix.sysctl:
      name: net.ipv6.conf.all.accept_ra_pinfo
      value: '{{ sysctl_net_ipv6_conf_all_accept_ra_pinfo_value }}'
      sysctl_file: /etc/sysctl.d/net_ipv6_conf_all_accept_ra_pinfo.conf
      state: present
      reload: true
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - disable_strategy
    - low_complexity
    - medium_disruption
    - reboot_required
    - sysctl_net_ipv6_conf_all_accept_ra_pinfo
    - unknown_severity

  - name: Configure Accepting Router Preference in 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:
    - disable_strategy
    - low_complexity
    - medium_disruption
    - reboot_required
    - sysctl_net_ipv6_conf_all_accept_ra_rtr_pref
    - unknown_severity

  - name: Configure Accepting Router Preference in Router Advertisements on All IPv6
      Interfaces - Find all files that contain net.ipv6.conf.all.accept_ra_rtr_pref
    ansible.builtin.shell:
      cmd: find -L {{ sysctl_paths | join(" ") }} -type f -name '*.conf' | xargs grep
        -HP '^\s*net.ipv6.conf.all.accept_ra_rtr_pref\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:
    - disable_strategy
    - low_complexity
    - medium_disruption
    - reboot_required
    - sysctl_net_ipv6_conf_all_accept_ra_rtr_pref
    - unknown_severity

  - name: Configure Accepting Router Preference in Router Advertisements on All IPv6
      Interfaces - Find all files that set net.ipv6.conf.all.accept_ra_rtr_pref 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_rtr_pref\s*=\s*{{ sysctl_net_ipv6_conf_all_accept_ra_rtr_pref_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:
    - disable_strategy
    - low_complexity
    - medium_disruption
    - reboot_required
    - sysctl_net_ipv6_conf_all_accept_ra_rtr_pref
    - unknown_severity

  - name: Configure Accepting Router Preference in Router Advertisements on All IPv6
      Interfaces - Comment out any occurrences of net.ipv6.conf.all.accept_ra_rtr_pref
      from config files
    ansible.builtin.replace:
      path: '{{ item | split(":") | first }}'
      regexp: ^[\s]*net.ipv6.conf.all.accept_ra_rtr_pref
      replace: '#net.ipv6.conf.all.accept_ra_rtr_pref'
    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:
    - disable_strategy
    - low_complexity
    - medium_disruption
    - reboot_required
    - sysctl_net_ipv6_conf_all_accept_ra_rtr_pref
    - unknown_severity

  - name: Configure Accepting Router Preference in Router Advertisements on All IPv6
      Interfaces - Comment out any occurrences of net.ipv6.conf.all.accept_ra_rtr_pref
      from /etc/sysctl.conf
    ansible.builtin.replace:
      path: '{{ item }}'
      regexp: ^[\s]*net.ipv6.conf.all.accept_ra_rtr_pref
      replace: '#net.ipv6.conf.all.accept_ra_rtr_pref'
    with_fileglob:
    - /etc/sysctl.conf
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - disable_strategy
    - low_complexity
    - medium_disruption
    - reboot_required
    - sysctl_net_ipv6_conf_all_accept_ra_rtr_pref
    - unknown_severity

  - name: Configure Accepting Router Preference in Router Advertisements on All IPv6
      Interfaces - Ensure sysctl net.ipv6.conf.all.accept_ra_rtr_pref is set
    ansible.posix.sysctl:
      name: net.ipv6.conf.all.accept_ra_rtr_pref
      value: '{{ sysctl_net_ipv6_conf_all_accept_ra_rtr_pref_value }}'
      sysctl_file: /etc/sysctl.d/net_ipv6_conf_all_accept_ra_rtr_pref.conf
      state: present
      reload: true
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - disable_strategy
    - low_complexity
    - medium_disruption
    - reboot_required
    - sysctl_net_ipv6_conf_all_accept_ra_rtr_pref
    - unknown_severity

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

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

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

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

  - name: Disable Accepting ICMP Redirects for All IPv6 Interfaces - Comment out any
      occurrences of net.ipv6.conf.all.accept_redirects from /etc/sysctl.conf
    ansible.builtin.replace:
      path: '{{ item }}'
      regexp: ^[\s]*net.ipv6.conf.all.accept_redirects
      replace: '#net.ipv6.conf.all.accept_redirects'
    with_fileglob:
    - /etc/sysctl.conf
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-006041
    - NIST-800-171-3.1.20
    - NIST-800-53-CM-6(a)
    - NIST-800-53-CM-6(b)
    - NIST-800-53-CM-6.1(iv)
    - NIST-800-53-CM-7(a)
    - NIST-800-53-CM-7(b)
    - disable_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - reboot_required
    - sysctl_net_ipv6_conf_all_accept_redirects

  - name: Disable Accepting ICMP Redirects for All IPv6 Interfaces - Ensure sysctl
      net.ipv6.conf.all.accept_redirects is set
    ansible.posix.sysctl:
      name: net.ipv6.conf.all.accept_redirects
      value: '{{ sysctl_net_ipv6_conf_all_accept_redirects_value }}'
      sysctl_file: /etc/sysctl.d/net_ipv6_conf_all_accept_redirects.conf
      state: present
      reload: true
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-006041
    - NIST-800-171-3.1.20
    - NIST-800-53-CM-6(a)
    - NIST-800-53-CM-6(b)
    - NIST-800-53-CM-6.1(iv)
    - NIST-800-53-CM-7(a)
    - NIST-800-53-CM-7(b)
    - disable_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - reboot_required
    - sysctl_net_ipv6_conf_all_accept_redirects

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

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

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

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

  - name: Disable Kernel Parameter for Accepting Source-Routed Packets on all IPv6
      Interfaces - Comment out any occurrences of net.ipv6.conf.all.accept_source_route
      from /etc/sysctl.conf
    ansible.builtin.replace:
      path: '{{ item }}'
      regexp: ^[\s]*net.ipv6.conf.all.accept_source_route
      replace: '#net.ipv6.conf.all.accept_source_route'
    with_fileglob:
    - /etc/sysctl.conf
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-006042
    - NIST-800-171-3.1.20
    - NIST-800-53-CM-6(a)
    - NIST-800-53-CM-7(a)
    - NIST-800-53-CM-7(b)
    - disable_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - reboot_required
    - sysctl_net_ipv6_conf_all_accept_source_route

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

  - name: Configure Auto Configuration 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:
    - disable_strategy
    - low_complexity
    - medium_disruption
    - reboot_required
    - sysctl_net_ipv6_conf_all_autoconf
    - unknown_severity

  - name: Configure Auto Configuration on All IPv6 Interfaces - Find all files that
      contain net.ipv6.conf.all.autoconf
    ansible.builtin.shell:
      cmd: find -L {{ sysctl_paths | join(" ") }} -type f -name '*.conf' | xargs grep
        -HP '^\s*net.ipv6.conf.all.autoconf\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:
    - disable_strategy
    - low_complexity
    - medium_disruption
    - reboot_required
    - sysctl_net_ipv6_conf_all_autoconf
    - unknown_severity

  - name: Configure Auto Configuration on All IPv6 Interfaces - Find all files that
      set net.ipv6.conf.all.autoconf to correct value
    ansible.builtin.shell:
      cmd: find -L {{ sysctl_paths | join(" ") }} -type f -name '*.conf' | xargs grep
        -HP '^\s*net.ipv6.conf.all.autoconf\s*=\s*{{ sysctl_net_ipv6_conf_all_autoconf_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:
    - disable_strategy
    - low_complexity
    - medium_disruption
    - reboot_required
    - sysctl_net_ipv6_conf_all_autoconf
    - unknown_severity

  - name: Configure Auto Configuration on All IPv6 Interfaces - Comment out any occurrences
      of net.ipv6.conf.all.autoconf from config files
    ansible.builtin.replace:
      path: '{{ item | split(":") | first }}'
      regexp: ^[\s]*net.ipv6.conf.all.autoconf
      replace: '#net.ipv6.conf.all.autoconf'
    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:
    - disable_strategy
    - low_complexity
    - medium_disruption
    - reboot_required
    - sysctl_net_ipv6_conf_all_autoconf
    - unknown_severity

  - name: Configure Auto Configuration on All IPv6 Interfaces - Comment out any occurrences
      of net.ipv6.conf.all.autoconf from /etc/sysctl.conf
    ansible.builtin.replace:
      path: '{{ item }}'
      regexp: ^[\s]*net.ipv6.conf.all.autoconf
      replace: '#net.ipv6.conf.all.autoconf'
    with_fileglob:
    - /etc/sysctl.conf
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - disable_strategy
    - low_complexity
    - medium_disruption
    - reboot_required
    - sysctl_net_ipv6_conf_all_autoconf
    - unknown_severity

  - name: Configure Auto Configuration on All IPv6 Interfaces - Ensure sysctl net.ipv6.conf.all.autoconf
      is set
    ansible.posix.sysctl:
      name: net.ipv6.conf.all.autoconf
      value: '{{ sysctl_net_ipv6_conf_all_autoconf_value }}'
      sysctl_file: /etc/sysctl.d/net_ipv6_conf_all_autoconf.conf
      state: present
      reload: true
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - disable_strategy
    - low_complexity
    - medium_disruption
    - reboot_required
    - sysctl_net_ipv6_conf_all_autoconf
    - unknown_severity

  - name: Configure Maximum Number of Autoconfigured Addresses 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:
    - disable_strategy
    - low_complexity
    - medium_disruption
    - reboot_required
    - sysctl_net_ipv6_conf_all_max_addresses
    - unknown_severity

  - name: Configure Maximum Number of Autoconfigured Addresses on All IPv6 Interfaces
      - Find all files that contain net.ipv6.conf.all.max_addresses
    ansible.builtin.shell:
      cmd: find -L {{ sysctl_paths | join(" ") }} -type f -name '*.conf' | xargs grep
        -HP '^\s*net.ipv6.conf.all.max_addresses\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:
    - disable_strategy
    - low_complexity
    - medium_disruption
    - reboot_required
    - sysctl_net_ipv6_conf_all_max_addresses
    - unknown_severity

  - name: Configure Maximum Number of Autoconfigured Addresses on All IPv6 Interfaces
      - Find all files that set net.ipv6.conf.all.max_addresses to correct value
    ansible.builtin.shell:
      cmd: find -L {{ sysctl_paths | join(" ") }} -type f -name '*.conf' | xargs grep
        -HP '^\s*net.ipv6.conf.all.max_addresses\s*=\s*{{ sysctl_net_ipv6_conf_all_max_addresses_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:
    - disable_strategy
    - low_complexity
    - medium_disruption
    - reboot_required
    - sysctl_net_ipv6_conf_all_max_addresses
    - unknown_severity

  - name: Configure Maximum Number of Autoconfigured Addresses on All IPv6 Interfaces
      - Comment out any occurrences of net.ipv6.conf.all.max_addresses from config
      files
    ansible.builtin.replace:
      path: '{{ item | split(":") | first }}'
      regexp: ^[\s]*net.ipv6.conf.all.max_addresses
      replace: '#net.ipv6.conf.all.max_addresses'
    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:
    - disable_strategy
    - low_complexity
    - medium_disruption
    - reboot_required
    - sysctl_net_ipv6_conf_all_max_addresses
    - unknown_severity

  - name: Configure Maximum Number of Autoconfigured Addresses on All IPv6 Interfaces
      - Comment out any occurrences of net.ipv6.conf.all.max_addresses from /etc/sysctl.conf
    ansible.builtin.replace:
      path: '{{ item }}'
      regexp: ^[\s]*net.ipv6.conf.all.max_addresses
      replace: '#net.ipv6.conf.all.max_addresses'
    with_fileglob:
    - /etc/sysctl.conf
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - disable_strategy
    - low_complexity
    - medium_disruption
    - reboot_required
    - sysctl_net_ipv6_conf_all_max_addresses
    - unknown_severity

  - name: Configure Maximum Number of Autoconfigured Addresses on All IPv6 Interfaces
      - Ensure sysctl net.ipv6.conf.all.max_addresses is set
    ansible.posix.sysctl:
      name: net.ipv6.conf.all.max_addresses
      value: '{{ sysctl_net_ipv6_conf_all_max_addresses_value }}'
      sysctl_file: /etc/sysctl.d/net_ipv6_conf_all_max_addresses.conf
      state: present
      reload: true
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - disable_strategy
    - low_complexity
    - medium_disruption
    - reboot_required
    - sysctl_net_ipv6_conf_all_max_addresses
    - unknown_severity

  - name: Configure Denying Router Solicitations 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:
    - disable_strategy
    - low_complexity
    - medium_disruption
    - reboot_required
    - sysctl_net_ipv6_conf_all_router_solicitations
    - unknown_severity

  - name: Configure Denying Router Solicitations on All IPv6 Interfaces - Find all
      files that contain net.ipv6.conf.all.router_solicitations
    ansible.builtin.shell:
      cmd: find -L {{ sysctl_paths | join(" ") }} -type f -name '*.conf' | xargs grep
        -HP '^\s*net.ipv6.conf.all.router_solicitations\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:
    - disable_strategy
    - low_complexity
    - medium_disruption
    - reboot_required
    - sysctl_net_ipv6_conf_all_router_solicitations
    - unknown_severity

  - name: Configure Denying Router Solicitations on All IPv6 Interfaces - Find all
      files that set net.ipv6.conf.all.router_solicitations to correct value
    ansible.builtin.shell:
      cmd: find -L {{ sysctl_paths | join(" ") }} -type f -name '*.conf' | xargs grep
        -HP '^\s*net.ipv6.conf.all.router_solicitations\s*=\s*{{ sysctl_net_ipv6_conf_all_router_solicitations_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:
    - disable_strategy
    - low_complexity
    - medium_disruption
    - reboot_required
    - sysctl_net_ipv6_conf_all_router_solicitations
    - unknown_severity

  - name: Configure Denying Router Solicitations on All IPv6 Interfaces - Comment
      out any occurrences of net.ipv6.conf.all.router_solicitations from config files
    ansible.builtin.replace:
      path: '{{ item | split(":") | first }}'
      regexp: ^[\s]*net.ipv6.conf.all.router_solicitations
      replace: '#net.ipv6.conf.all.router_solicitations'
    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:
    - disable_strategy
    - low_complexity
    - medium_disruption
    - reboot_required
    - sysctl_net_ipv6_conf_all_router_solicitations
    - unknown_severity

  - name: Configure Denying Router Solicitations on All IPv6 Interfaces - Comment
      out any occurrences of net.ipv6.conf.all.router_solicitations from /etc/sysctl.conf
    ansible.builtin.replace:
      path: '{{ item }}'
      regexp: ^[\s]*net.ipv6.conf.all.router_solicitations
      replace: '#net.ipv6.conf.all.router_solicitations'
    with_fileglob:
    - /etc/sysctl.conf
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - disable_strategy
    - low_complexity
    - medium_disruption
    - reboot_required
    - sysctl_net_ipv6_conf_all_router_solicitations
    - unknown_severity

  - name: Configure Denying Router Solicitations on All IPv6 Interfaces - Ensure sysctl
      net.ipv6.conf.all.router_solicitations is set
    ansible.posix.sysctl:
      name: net.ipv6.conf.all.router_solicitations
      value: '{{ sysctl_net_ipv6_conf_all_router_solicitations_value }}'
      sysctl_file: /etc/sysctl.d/net_ipv6_conf_all_router_solicitations.conf
      state: present
      reload: true
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - disable_strategy
    - low_complexity
    - medium_disruption
    - reboot_required
    - sysctl_net_ipv6_conf_all_router_solicitations
    - unknown_severity

  - name: Configure Accepting Default Router in 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:
    - disable_strategy
    - low_complexity
    - medium_disruption
    - reboot_required
    - sysctl_net_ipv6_conf_default_accept_ra_defrtr
    - unknown_severity

  - name: Configure Accepting Default Router in Router Advertisements on All IPv6
      Interfaces By Default - Find all files that contain net.ipv6.conf.default.accept_ra_defrtr
    ansible.builtin.shell:
      cmd: find -L {{ sysctl_paths | join(" ") }} -type f -name '*.conf' | xargs grep
        -HP '^\s*net.ipv6.conf.default.accept_ra_defrtr\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:
    - disable_strategy
    - low_complexity
    - medium_disruption
    - reboot_required
    - sysctl_net_ipv6_conf_default_accept_ra_defrtr
    - unknown_severity

  - name: Configure Accepting Default Router in Router Advertisements on All IPv6
      Interfaces By Default - Find all files that set net.ipv6.conf.default.accept_ra_defrtr
      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_defrtr\s*=\s*{{ sysctl_net_ipv6_conf_default_accept_ra_defrtr_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:
    - disable_strategy
    - low_complexity
    - medium_disruption
    - reboot_required
    - sysctl_net_ipv6_conf_default_accept_ra_defrtr
    - unknown_severity

  - name: Configure Accepting Default Router in Router Advertisements on All IPv6
      Interfaces By Default - Comment out any occurrences of net.ipv6.conf.default.accept_ra_defrtr
      from config files
    ansible.builtin.replace:
      path: '{{ item | split(":") | first }}'
      regexp: ^[\s]*net.ipv6.conf.default.accept_ra_defrtr
      replace: '#net.ipv6.conf.default.accept_ra_defrtr'
    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:
    - disable_strategy
    - low_complexity
    - medium_disruption
    - reboot_required
    - sysctl_net_ipv6_conf_default_accept_ra_defrtr
    - unknown_severity

  - name: Configure Accepting Default Router in Router Advertisements on All IPv6
      Interfaces By Default - Comment out any occurrences of net.ipv6.conf.default.accept_ra_defrtr
      from /etc/sysctl.conf
    ansible.builtin.replace:
      path: '{{ item }}'
      regexp: ^[\s]*net.ipv6.conf.default.accept_ra_defrtr
      replace: '#net.ipv6.conf.default.accept_ra_defrtr'
    with_fileglob:
    - /etc/sysctl.conf
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - disable_strategy
    - low_complexity
    - medium_disruption
    - reboot_required
    - sysctl_net_ipv6_conf_default_accept_ra_defrtr
    - unknown_severity

  - name: Configure Accepting Default Router in Router Advertisements on All IPv6
      Interfaces By Default - Ensure sysctl net.ipv6.conf.default.accept_ra_defrtr
      is set
    ansible.posix.sysctl:
      name: net.ipv6.conf.default.accept_ra_defrtr
      value: '{{ sysctl_net_ipv6_conf_default_accept_ra_defrtr_value }}'
      sysctl_file: /etc/sysctl.d/net_ipv6_conf_default_accept_ra_defrtr.conf
      state: present
      reload: true
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - disable_strategy
    - low_complexity
    - medium_disruption
    - reboot_required
    - sysctl_net_ipv6_conf_default_accept_ra_defrtr
    - unknown_severity

  - name: Configure Accepting Prefix Information in 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:
    - disable_strategy
    - low_complexity
    - medium_disruption
    - reboot_required
    - sysctl_net_ipv6_conf_default_accept_ra_pinfo
    - unknown_severity

  - name: Configure Accepting Prefix Information in Router Advertisements on All IPv6
      Interfaces By Default - Find all files that contain net.ipv6.conf.default.accept_ra_pinfo
    ansible.builtin.shell:
      cmd: find -L {{ sysctl_paths | join(" ") }} -type f -name '*.conf' | xargs grep
        -HP '^\s*net.ipv6.conf.default.accept_ra_pinfo\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:
    - disable_strategy
    - low_complexity
    - medium_disruption
    - reboot_required
    - sysctl_net_ipv6_conf_default_accept_ra_pinfo
    - unknown_severity

  - name: Configure Accepting Prefix Information in Router Advertisements on All IPv6
      Interfaces By Default - Find all files that set net.ipv6.conf.default.accept_ra_pinfo
      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_pinfo\s*=\s*{{ sysctl_net_ipv6_conf_default_accept_ra_pinfo_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:
    - disable_strategy
    - low_complexity
    - medium_disruption
    - reboot_required
    - sysctl_net_ipv6_conf_default_accept_ra_pinfo
    - unknown_severity

  - name: Configure Accepting Prefix Information in Router Advertisements on All IPv6
      Interfaces By Default - Comment out any occurrences of net.ipv6.conf.default.accept_ra_pinfo
      from config files
    ansible.builtin.replace:
      path: '{{ item | split(":") | first }}'
      regexp: ^[\s]*net.ipv6.conf.default.accept_ra_pinfo
      replace: '#net.ipv6.conf.default.accept_ra_pinfo'
    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:
    - disable_strategy
    - low_complexity
    - medium_disruption
    - reboot_required
    - sysctl_net_ipv6_conf_default_accept_ra_pinfo
    - unknown_severity

  - name: Configure Accepting Prefix Information in Router Advertisements on All IPv6
      Interfaces By Default - Comment out any occurrences of net.ipv6.conf.default.accept_ra_pinfo
      from /etc/sysctl.conf
    ansible.builtin.replace:
      path: '{{ item }}'
      regexp: ^[\s]*net.ipv6.conf.default.accept_ra_pinfo
      replace: '#net.ipv6.conf.default.accept_ra_pinfo'
    with_fileglob:
    - /etc/sysctl.conf
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - disable_strategy
    - low_complexity
    - medium_disruption
    - reboot_required
    - sysctl_net_ipv6_conf_default_accept_ra_pinfo
    - unknown_severity

  - name: Configure Accepting Prefix Information in Router Advertisements on All IPv6
      Interfaces By Default - Ensure sysctl net.ipv6.conf.default.accept_ra_pinfo
      is set
    ansible.posix.sysctl:
      name: net.ipv6.conf.default.accept_ra_pinfo
      value: '{{ sysctl_net_ipv6_conf_default_accept_ra_pinfo_value }}'
      sysctl_file: /etc/sysctl.d/net_ipv6_conf_default_accept_ra_pinfo.conf
      state: present
      reload: true
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - disable_strategy
    - low_complexity
    - medium_disruption
    - reboot_required
    - sysctl_net_ipv6_conf_default_accept_ra_pinfo
    - unknown_severity

  - name: Configure Accepting Router Preference in 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:
    - disable_strategy
    - low_complexity
    - medium_disruption
    - reboot_required
    - sysctl_net_ipv6_conf_default_accept_ra_rtr_pref
    - unknown_severity

  - name: Configure Accepting Router Preference in Router Advertisements on All IPv6
      Interfaces By Default - Find all files that contain net.ipv6.conf.default.accept_ra_rtr_pref
    ansible.builtin.shell:
      cmd: find -L {{ sysctl_paths | join(" ") }} -type f -name '*.conf' | xargs grep
        -HP '^\s*net.ipv6.conf.default.accept_ra_rtr_pref\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:
    - disable_strategy
    - low_complexity
    - medium_disruption
    - reboot_required
    - sysctl_net_ipv6_conf_default_accept_ra_rtr_pref
    - unknown_severity

  - name: Configure Accepting Router Preference in Router Advertisements on All IPv6
      Interfaces By Default - Find all files that set net.ipv6.conf.default.accept_ra_rtr_pref
      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_rtr_pref\s*=\s*{{ sysctl_net_ipv6_conf_default_accept_ra_rtr_pref_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:
    - disable_strategy
    - low_complexity
    - medium_disruption
    - reboot_required
    - sysctl_net_ipv6_conf_default_accept_ra_rtr_pref
    - unknown_severity

  - name: Configure Accepting Router Preference in Router Advertisements on All IPv6
      Interfaces By Default - Comment out any occurrences of net.ipv6.conf.default.accept_ra_rtr_pref
      from config files
    ansible.builtin.replace:
      path: '{{ item | split(":") | first }}'
      regexp: ^[\s]*net.ipv6.conf.default.accept_ra_rtr_pref
      replace: '#net.ipv6.conf.default.accept_ra_rtr_pref'
    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:
    - disable_strategy
    - low_complexity
    - medium_disruption
    - reboot_required
    - sysctl_net_ipv6_conf_default_accept_ra_rtr_pref
    - unknown_severity

  - name: Configure Accepting Router Preference in Router Advertisements on All IPv6
      Interfaces By Default - Comment out any occurrences of net.ipv6.conf.default.accept_ra_rtr_pref
      from /etc/sysctl.conf
    ansible.builtin.replace:
      path: '{{ item }}'
      regexp: ^[\s]*net.ipv6.conf.default.accept_ra_rtr_pref
      replace: '#net.ipv6.conf.default.accept_ra_rtr_pref'
    with_fileglob:
    - /etc/sysctl.conf
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - disable_strategy
    - low_complexity
    - medium_disruption
    - reboot_required
    - sysctl_net_ipv6_conf_default_accept_ra_rtr_pref
    - unknown_severity

  - name: Configure Accepting Router Preference in Router Advertisements on All IPv6
      Interfaces By Default - Ensure sysctl net.ipv6.conf.default.accept_ra_rtr_pref
      is set
    ansible.posix.sysctl:
      name: net.ipv6.conf.default.accept_ra_rtr_pref
      value: '{{ sysctl_net_ipv6_conf_default_accept_ra_rtr_pref_value }}'
      sysctl_file: /etc/sysctl.d/net_ipv6_conf_default_accept_ra_rtr_pref.conf
      state: present
      reload: true
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - disable_strategy
    - low_complexity
    - medium_disruption
    - reboot_required
    - sysctl_net_ipv6_conf_default_accept_ra_rtr_pref
    - unknown_severity

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

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

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

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

  - name: Disable Kernel Parameter for Accepting ICMP Redirects by Default on IPv6
      Interfaces - Comment out any occurrences of net.ipv6.conf.default.accept_redirects
      from /etc/sysctl.conf
    ansible.builtin.replace:
      path: '{{ item }}'
      regexp: ^[\s]*net.ipv6.conf.default.accept_redirects
      replace: '#net.ipv6.conf.default.accept_redirects'
    with_fileglob:
    - /etc/sysctl.conf
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-006045
    - NIST-800-171-3.1.20
    - NIST-800-53-CM-6(a)
    - NIST-800-53-CM-7(a)
    - NIST-800-53-CM-7(b)
    - disable_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - reboot_required
    - sysctl_net_ipv6_conf_default_accept_redirects

  - name: Disable Kernel Parameter for Accepting ICMP Redirects by Default on IPv6
      Interfaces - Ensure sysctl net.ipv6.conf.default.accept_redirects is set
    ansible.posix.sysctl:
      name: net.ipv6.conf.default.accept_redirects
      value: '{{ sysctl_net_ipv6_conf_default_accept_redirects_value }}'
      sysctl_file: /etc/sysctl.d/net_ipv6_conf_default_accept_redirects.conf
      state: present
      reload: true
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-006045
    - NIST-800-171-3.1.20
    - NIST-800-53-CM-6(a)
    - NIST-800-53-CM-7(a)
    - NIST-800-53-CM-7(b)
    - disable_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - reboot_required
    - sysctl_net_ipv6_conf_default_accept_redirects

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

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

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

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

  - name: Disable Kernel Parameter for Accepting Source-Routed Packets on IPv6 Interfaces
      by Default - Comment out any occurrences of net.ipv6.conf.default.accept_source_route
      from /etc/sysctl.conf
    ansible.builtin.replace:
      path: '{{ item }}'
      regexp: ^[\s]*net.ipv6.conf.default.accept_source_route
      replace: '#net.ipv6.conf.default.accept_source_route'
    with_fileglob:
    - /etc/sysctl.conf
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-006046
    - NIST-800-171-3.1.20
    - NIST-800-53-CM-6(a)
    - NIST-800-53-CM-6(b)
    - NIST-800-53-CM-6.1(iv)
    - NIST-800-53-CM-7(a)
    - NIST-800-53-CM-7(b)
    - PCI-DSS-Req-1.4.3
    - PCI-DSSv4-1.4
    - PCI-DSSv4-1.4.2
    - disable_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - reboot_required
    - sysctl_net_ipv6_conf_default_accept_source_route

  - name: Disable Kernel Parameter for Accepting Source-Routed Packets on IPv6 Interfaces
      by Default - Ensure sysctl net.ipv6.conf.default.accept_source_route is set
    ansible.posix.sysctl:
      name: net.ipv6.conf.default.accept_source_route
      value: '{{ sysctl_net_ipv6_conf_default_accept_source_route_value }}'
      sysctl_file: /etc/sysctl.d/net_ipv6_conf_default_accept_source_route.conf
      state: present
      reload: true
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-006046
    - NIST-800-171-3.1.20
    - NIST-800-53-CM-6(a)
    - NIST-800-53-CM-6(b)
    - NIST-800-53-CM-6.1(iv)
    - NIST-800-53-CM-7(a)
    - NIST-800-53-CM-7(b)
    - PCI-DSS-Req-1.4.3
    - PCI-DSSv4-1.4
    - PCI-DSSv4-1.4.2
    - disable_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - reboot_required
    - sysctl_net_ipv6_conf_default_accept_source_route

  - name: Configure Auto Configuration 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:
    - disable_strategy
    - low_complexity
    - medium_disruption
    - reboot_required
    - sysctl_net_ipv6_conf_default_autoconf
    - unknown_severity

  - name: Configure Auto Configuration on All IPv6 Interfaces By Default - Find all
      files that contain net.ipv6.conf.default.autoconf
    ansible.builtin.shell:
      cmd: find -L {{ sysctl_paths | join(" ") }} -type f -name '*.conf' | xargs grep
        -HP '^\s*net.ipv6.conf.default.autoconf\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:
    - disable_strategy
    - low_complexity
    - medium_disruption
    - reboot_required
    - sysctl_net_ipv6_conf_default_autoconf
    - unknown_severity

  - name: Configure Auto Configuration on All IPv6 Interfaces By Default - Find all
      files that set net.ipv6.conf.default.autoconf to correct value
    ansible.builtin.shell:
      cmd: find -L {{ sysctl_paths | join(" ") }} -type f -name '*.conf' | xargs grep
        -HP '^\s*net.ipv6.conf.default.autoconf\s*=\s*{{ sysctl_net_ipv6_conf_default_autoconf_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:
    - disable_strategy
    - low_complexity
    - medium_disruption
    - reboot_required
    - sysctl_net_ipv6_conf_default_autoconf
    - unknown_severity

  - name: Configure Auto Configuration on All IPv6 Interfaces By Default - Comment
      out any occurrences of net.ipv6.conf.default.autoconf from config files
    ansible.builtin.replace:
      path: '{{ item | split(":") | first }}'
      regexp: ^[\s]*net.ipv6.conf.default.autoconf
      replace: '#net.ipv6.conf.default.autoconf'
    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:
    - disable_strategy
    - low_complexity
    - medium_disruption
    - reboot_required
    - sysctl_net_ipv6_conf_default_autoconf
    - unknown_severity

  - name: Configure Auto Configuration on All IPv6 Interfaces By Default - Comment
      out any occurrences of net.ipv6.conf.default.autoconf from /etc/sysctl.conf
    ansible.builtin.replace:
      path: '{{ item }}'
      regexp: ^[\s]*net.ipv6.conf.default.autoconf
      replace: '#net.ipv6.conf.default.autoconf'
    with_fileglob:
    - /etc/sysctl.conf
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - disable_strategy
    - low_complexity
    - medium_disruption
    - reboot_required
    - sysctl_net_ipv6_conf_default_autoconf
    - unknown_severity

  - name: Configure Auto Configuration on All IPv6 Interfaces By Default - Ensure
      sysctl net.ipv6.conf.default.autoconf is set
    ansible.posix.sysctl:
      name: net.ipv6.conf.default.autoconf
      value: '{{ sysctl_net_ipv6_conf_default_autoconf_value }}'
      sysctl_file: /etc/sysctl.d/net_ipv6_conf_default_autoconf.conf
      state: present
      reload: true
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - disable_strategy
    - low_complexity
    - medium_disruption
    - reboot_required
    - sysctl_net_ipv6_conf_default_autoconf
    - unknown_severity

  - name: Configure Maximum Number of Autoconfigured Addresses 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:
    - disable_strategy
    - low_complexity
    - medium_disruption
    - reboot_required
    - sysctl_net_ipv6_conf_default_max_addresses
    - unknown_severity

  - name: Configure Maximum Number of Autoconfigured Addresses on All IPv6 Interfaces
      By Default - Find all files that contain net.ipv6.conf.default.max_addresses
    ansible.builtin.shell:
      cmd: find -L {{ sysctl_paths | join(" ") }} -type f -name '*.conf' | xargs grep
        -HP '^\s*net.ipv6.conf.default.max_addresses\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:
    - disable_strategy
    - low_complexity
    - medium_disruption
    - reboot_required
    - sysctl_net_ipv6_conf_default_max_addresses
    - unknown_severity

  - name: Configure Maximum Number of Autoconfigured Addresses on All IPv6 Interfaces
      By Default - Find all files that set net.ipv6.conf.default.max_addresses to
      correct value
    ansible.builtin.shell:
      cmd: find -L {{ sysctl_paths | join(" ") }} -type f -name '*.conf' | xargs grep
        -HP '^\s*net.ipv6.conf.default.max_addresses\s*=\s*{{ sysctl_net_ipv6_conf_default_max_addresses_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:
    - disable_strategy
    - low_complexity
    - medium_disruption
    - reboot_required
    - sysctl_net_ipv6_conf_default_max_addresses
    - unknown_severity

  - name: Configure Maximum Number of Autoconfigured Addresses on All IPv6 Interfaces
      By Default - Comment out any occurrences of net.ipv6.conf.default.max_addresses
      from config files
    ansible.builtin.replace:
      path: '{{ item | split(":") | first }}'
      regexp: ^[\s]*net.ipv6.conf.default.max_addresses
      replace: '#net.ipv6.conf.default.max_addresses'
    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:
    - disable_strategy
    - low_complexity
    - medium_disruption
    - reboot_required
    - sysctl_net_ipv6_conf_default_max_addresses
    - unknown_severity

  - name: Configure Maximum Number of Autoconfigured Addresses on All IPv6 Interfaces
      By Default - Comment out any occurrences of net.ipv6.conf.default.max_addresses
      from /etc/sysctl.conf
    ansible.builtin.replace:
      path: '{{ item }}'
      regexp: ^[\s]*net.ipv6.conf.default.max_addresses
      replace: '#net.ipv6.conf.default.max_addresses'
    with_fileglob:
    - /etc/sysctl.conf
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - disable_strategy
    - low_complexity
    - medium_disruption
    - reboot_required
    - sysctl_net_ipv6_conf_default_max_addresses
    - unknown_severity

  - name: Configure Maximum Number of Autoconfigured Addresses on All IPv6 Interfaces
      By Default - Ensure sysctl net.ipv6.conf.default.max_addresses is set
    ansible.posix.sysctl:
      name: net.ipv6.conf.default.max_addresses
      value: '{{ sysctl_net_ipv6_conf_default_max_addresses_value }}'
      sysctl_file: /etc/sysctl.d/net_ipv6_conf_default_max_addresses.conf
      state: present
      reload: true
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - disable_strategy
    - low_complexity
    - medium_disruption
    - reboot_required
    - sysctl_net_ipv6_conf_default_max_addresses
    - unknown_severity

  - name: Configure Denying Router Solicitations 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:
    - disable_strategy
    - low_complexity
    - medium_disruption
    - reboot_required
    - sysctl_net_ipv6_conf_default_router_solicitations
    - unknown_severity

  - name: Configure Denying Router Solicitations on All IPv6 Interfaces By Default
      - Find all files that contain net.ipv6.conf.default.router_solicitations
    ansible.builtin.shell:
      cmd: find -L {{ sysctl_paths | join(" ") }} -type f -name '*.conf' | xargs grep
        -HP '^\s*net.ipv6.conf.default.router_solicitations\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:
    - disable_strategy
    - low_complexity
    - medium_disruption
    - reboot_required
    - sysctl_net_ipv6_conf_default_router_solicitations
    - unknown_severity

  - name: Configure Denying Router Solicitations on All IPv6 Interfaces By Default
      - Find all files that set net.ipv6.conf.default.router_solicitations to correct
      value
    ansible.builtin.shell:
      cmd: find -L {{ sysctl_paths | join(" ") }} -type f -name '*.conf' | xargs grep
        -HP '^\s*net.ipv6.conf.default.router_solicitations\s*=\s*{{ sysctl_net_ipv6_conf_default_router_solicitations_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:
    - disable_strategy
    - low_complexity
    - medium_disruption
    - reboot_required
    - sysctl_net_ipv6_conf_default_router_solicitations
    - unknown_severity

  - name: Configure Denying Router Solicitations on All IPv6 Interfaces By Default
      - Comment out any occurrences of net.ipv6.conf.default.router_solicitations
      from config files
    ansible.builtin.replace:
      path: '{{ item | split(":") | first }}'
      regexp: ^[\s]*net.ipv6.conf.default.router_solicitations
      replace: '#net.ipv6.conf.default.router_solicitations'
    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:
    - disable_strategy
    - low_complexity
    - medium_disruption
    - reboot_required
    - sysctl_net_ipv6_conf_default_router_solicitations
    - unknown_severity

  - name: Configure Denying Router Solicitations on All IPv6 Interfaces By Default
      - Comment out any occurrences of net.ipv6.conf.default.router_solicitations
      from /etc/sysctl.conf
    ansible.builtin.replace:
      path: '{{ item }}'
      regexp: ^[\s]*net.ipv6.conf.default.router_solicitations
      replace: '#net.ipv6.conf.default.router_solicitations'
    with_fileglob:
    - /etc/sysctl.conf
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - disable_strategy
    - low_complexity
    - medium_disruption
    - reboot_required
    - sysctl_net_ipv6_conf_default_router_solicitations
    - unknown_severity

  - name: Configure Denying Router Solicitations on All IPv6 Interfaces By Default
      - Ensure sysctl net.ipv6.conf.default.router_solicitations is set
    ansible.posix.sysctl:
      name: net.ipv6.conf.default.router_solicitations
      value: '{{ sysctl_net_ipv6_conf_default_router_solicitations_value }}'
      sysctl_file: /etc/sysctl.d/net_ipv6_conf_default_router_solicitations.conf
      state: present
      reload: true
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - disable_strategy
    - low_complexity
    - medium_disruption
    - reboot_required
    - sysctl_net_ipv6_conf_default_router_solicitations
    - unknown_severity

  - name: Disable Accepting Packets Routed Between Local 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:
    - disable_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - reboot_required
    - sysctl_net_ipv4_conf_all_accept_local

  - name: Disable Accepting Packets Routed Between Local Interfaces - Find all files
      that contain net.ipv4.conf.all.accept_local
    ansible.builtin.shell:
      cmd: find -L {{ sysctl_paths | join(" ") }} -type f -name '*.conf' | xargs grep
        -HP '^\s*net.ipv4.conf.all.accept_local\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:
    - disable_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - reboot_required
    - sysctl_net_ipv4_conf_all_accept_local

  - name: Disable Accepting Packets Routed Between Local Interfaces - Find all files
      that set net.ipv4.conf.all.accept_local 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_local\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:
    - disable_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - reboot_required
    - sysctl_net_ipv4_conf_all_accept_local

  - name: Disable Accepting Packets Routed Between Local Interfaces - Comment out
      any occurrences of net.ipv4.conf.all.accept_local from config files
    ansible.builtin.replace:
      path: '{{ item | split(":") | first }}'
      regexp: ^[\s]*net.ipv4.conf.all.accept_local
      replace: '#net.ipv4.conf.all.accept_local'
    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:
    - disable_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - reboot_required
    - sysctl_net_ipv4_conf_all_accept_local

  - name: Disable Accepting Packets Routed Between Local Interfaces - Comment out
      any occurrences of net.ipv4.conf.all.accept_local from /etc/sysctl.conf
    ansible.builtin.replace:
      path: '{{ item }}'
      regexp: ^[\s]*net.ipv4.conf.all.accept_local
      replace: '#net.ipv4.conf.all.accept_local'
    with_fileglob:
    - /etc/sysctl.conf
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - disable_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - reboot_required
    - sysctl_net_ipv4_conf_all_accept_local

  - name: Disable Accepting Packets Routed Between Local Interfaces - Ensure sysctl
      net.ipv4.conf.all.accept_local is set to 0
    ansible.posix.sysctl:
      name: net.ipv4.conf.all.accept_local
      value: '0'
      sysctl_file: /etc/sysctl.d/net_ipv4_conf_all_accept_local.conf
      state: present
      reload: true
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - disable_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - reboot_required
    - sysctl_net_ipv4_conf_all_accept_local

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

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

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

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

  - name: Disable Accepting ICMP Redirects for All IPv4 Interfaces - Comment out any
      occurrences of net.ipv4.conf.all.accept_redirects from /etc/sysctl.conf
    ansible.builtin.replace:
      path: '{{ item }}'
      regexp: ^[\s]*net.ipv4.conf.all.accept_redirects
      replace: '#net.ipv4.conf.all.accept_redirects'
    with_fileglob:
    - /etc/sysctl.conf
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - CJIS-5.10.1.1
    - DISA-STIG-OL09-00-006020
    - NIST-800-171-3.1.20
    - NIST-800-53-CM-6(a)
    - NIST-800-53-CM-7(a)
    - NIST-800-53-CM-7(b)
    - NIST-800-53-SC-7(a)
    - disable_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - reboot_required
    - sysctl_net_ipv4_conf_all_accept_redirects

  - name: Disable Accepting ICMP Redirects for All IPv4 Interfaces - Ensure sysctl
      net.ipv4.conf.all.accept_redirects is set
    ansible.posix.sysctl:
      name: net.ipv4.conf.all.accept_redirects
      value: '{{ sysctl_net_ipv4_conf_all_accept_redirects_value }}'
      sysctl_file: /etc/sysctl.d/net_ipv4_conf_all_accept_redirects.conf
      state: present
      reload: true
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - CJIS-5.10.1.1
    - DISA-STIG-OL09-00-006020
    - NIST-800-171-3.1.20
    - NIST-800-53-CM-6(a)
    - NIST-800-53-CM-7(a)
    - NIST-800-53-CM-7(b)
    - NIST-800-53-SC-7(a)
    - disable_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - reboot_required
    - sysctl_net_ipv4_conf_all_accept_redirects

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

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

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

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

  - name: Disable Kernel Parameter for Accepting Source-Routed Packets on all IPv4
      Interfaces - Comment out any occurrences of net.ipv4.conf.all.accept_source_route
      from /etc/sysctl.conf
    ansible.builtin.replace:
      path: '{{ item }}'
      regexp: ^[\s]*net.ipv4.conf.all.accept_source_route
      replace: '#net.ipv4.conf.all.accept_source_route'
    with_fileglob:
    - /etc/sysctl.conf
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-006021
    - NIST-800-171-3.1.20
    - NIST-800-53-CM-6(a)
    - NIST-800-53-CM-7(a)
    - NIST-800-53-CM-7(b)
    - NIST-800-53-SC-5
    - NIST-800-53-SC-7(a)
    - disable_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - reboot_required
    - sysctl_net_ipv4_conf_all_accept_source_route

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

  - name: Configure ARP filtering 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:
    - disable_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - reboot_required
    - sysctl_net_ipv4_conf_all_arp_filter

  - name: Configure ARP filtering for All IPv4 Interfaces - Find all files that contain
      net.ipv4.conf.all.arp_filter
    ansible.builtin.shell:
      cmd: find -L {{ sysctl_paths | join(" ") }} -type f -name '*.conf' | xargs grep
        -HP '^\s*net.ipv4.conf.all.arp_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:
    - disable_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - reboot_required
    - sysctl_net_ipv4_conf_all_arp_filter

  - name: Configure ARP filtering for All IPv4 Interfaces - Find all files that set
      net.ipv4.conf.all.arp_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.arp_filter\s*=\s*{{ sysctl_net_ipv4_conf_all_arp_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:
    - disable_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - reboot_required
    - sysctl_net_ipv4_conf_all_arp_filter

  - name: Configure ARP filtering for All IPv4 Interfaces - Comment out any occurrences
      of net.ipv4.conf.all.arp_filter from config files
    ansible.builtin.replace:
      path: '{{ item | split(":") | first }}'
      regexp: ^[\s]*net.ipv4.conf.all.arp_filter
      replace: '#net.ipv4.conf.all.arp_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:
    - disable_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - reboot_required
    - sysctl_net_ipv4_conf_all_arp_filter

  - name: Configure ARP filtering for All IPv4 Interfaces - Comment out any occurrences
      of net.ipv4.conf.all.arp_filter from /etc/sysctl.conf
    ansible.builtin.replace:
      path: '{{ item }}'
      regexp: ^[\s]*net.ipv4.conf.all.arp_filter
      replace: '#net.ipv4.conf.all.arp_filter'
    with_fileglob:
    - /etc/sysctl.conf
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - disable_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - reboot_required
    - sysctl_net_ipv4_conf_all_arp_filter

  - name: Configure ARP filtering for All IPv4 Interfaces - Ensure sysctl net.ipv4.conf.all.arp_filter
      is set
    ansible.posix.sysctl:
      name: net.ipv4.conf.all.arp_filter
      value: '{{ sysctl_net_ipv4_conf_all_arp_filter_value }}'
      sysctl_file: /etc/sysctl.d/net_ipv4_conf_all_arp_filter.conf
      state: present
      reload: true
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - disable_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - reboot_required
    - sysctl_net_ipv4_conf_all_arp_filter

  - name: Configure Response Mode of ARP Requests 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:
    - disable_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - reboot_required
    - sysctl_net_ipv4_conf_all_arp_ignore

  - name: Configure Response Mode of ARP Requests for All IPv4 Interfaces - Find all
      files that contain net.ipv4.conf.all.arp_ignore
    ansible.builtin.shell:
      cmd: find -L {{ sysctl_paths | join(" ") }} -type f -name '*.conf' | xargs grep
        -HP '^\s*net.ipv4.conf.all.arp_ignore\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:
    - disable_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - reboot_required
    - sysctl_net_ipv4_conf_all_arp_ignore

  - name: Configure Response Mode of ARP Requests for All IPv4 Interfaces - Find all
      files that set net.ipv4.conf.all.arp_ignore to correct value
    ansible.builtin.shell:
      cmd: find -L {{ sysctl_paths | join(" ") }} -type f -name '*.conf' | xargs grep
        -HP '^\s*net.ipv4.conf.all.arp_ignore\s*=\s*{{ sysctl_net_ipv4_conf_all_arp_ignore_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:
    - disable_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - reboot_required
    - sysctl_net_ipv4_conf_all_arp_ignore

  - name: Configure Response Mode of ARP Requests for All IPv4 Interfaces - Comment
      out any occurrences of net.ipv4.conf.all.arp_ignore from config files
    ansible.builtin.replace:
      path: '{{ item | split(":") | first }}'
      regexp: ^[\s]*net.ipv4.conf.all.arp_ignore
      replace: '#net.ipv4.conf.all.arp_ignore'
    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:
    - disable_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - reboot_required
    - sysctl_net_ipv4_conf_all_arp_ignore

  - name: Configure Response Mode of ARP Requests for All IPv4 Interfaces - Comment
      out any occurrences of net.ipv4.conf.all.arp_ignore from /etc/sysctl.conf
    ansible.builtin.replace:
      path: '{{ item }}'
      regexp: ^[\s]*net.ipv4.conf.all.arp_ignore
      replace: '#net.ipv4.conf.all.arp_ignore'
    with_fileglob:
    - /etc/sysctl.conf
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - disable_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - reboot_required
    - sysctl_net_ipv4_conf_all_arp_ignore

  - name: Configure Response Mode of ARP Requests for All IPv4 Interfaces - Ensure
      sysctl net.ipv4.conf.all.arp_ignore is set
    ansible.posix.sysctl:
      name: net.ipv4.conf.all.arp_ignore
      value: '{{ sysctl_net_ipv4_conf_all_arp_ignore_value }}'
      sysctl_file: /etc/sysctl.d/net_ipv4_conf_all_arp_ignore.conf
      state: present
      reload: true
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - disable_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - reboot_required
    - sysctl_net_ipv4_conf_all_arp_ignore

  - name: Drop Gratuitous ARP frames 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:
    - disable_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - reboot_required
    - sysctl_net_ipv4_conf_all_drop_gratuitous_arp

  - name: Drop Gratuitous ARP frames on All IPv4 Interfaces - Find all files that
      contain net.ipv4.conf.all.drop_gratuitous_arp
    ansible.builtin.shell:
      cmd: find -L {{ sysctl_paths | join(" ") }} -type f -name '*.conf' | xargs grep
        -HP '^\s*net.ipv4.conf.all.drop_gratuitous_arp\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:
    - disable_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - reboot_required
    - sysctl_net_ipv4_conf_all_drop_gratuitous_arp

  - name: Drop Gratuitous ARP frames on All IPv4 Interfaces - Find all files that
      set net.ipv4.conf.all.drop_gratuitous_arp to correct value
    ansible.builtin.shell:
      cmd: find -L {{ sysctl_paths | join(" ") }} -type f -name '*.conf' | xargs grep
        -HP '^\s*net.ipv4.conf.all.drop_gratuitous_arp\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:
    - disable_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - reboot_required
    - sysctl_net_ipv4_conf_all_drop_gratuitous_arp

  - name: Drop Gratuitous ARP frames on All IPv4 Interfaces - Comment out any occurrences
      of net.ipv4.conf.all.drop_gratuitous_arp from config files
    ansible.builtin.replace:
      path: '{{ item | split(":") | first }}'
      regexp: ^[\s]*net.ipv4.conf.all.drop_gratuitous_arp
      replace: '#net.ipv4.conf.all.drop_gratuitous_arp'
    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:
    - disable_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - reboot_required
    - sysctl_net_ipv4_conf_all_drop_gratuitous_arp

  - name: Drop Gratuitous ARP frames on All IPv4 Interfaces - Comment out any occurrences
      of net.ipv4.conf.all.drop_gratuitous_arp from /etc/sysctl.conf
    ansible.builtin.replace:
      path: '{{ item }}'
      regexp: ^[\s]*net.ipv4.conf.all.drop_gratuitous_arp
      replace: '#net.ipv4.conf.all.drop_gratuitous_arp'
    with_fileglob:
    - /etc/sysctl.conf
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - disable_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - reboot_required
    - sysctl_net_ipv4_conf_all_drop_gratuitous_arp

  - name: Drop Gratuitous ARP frames on All IPv4 Interfaces - Ensure sysctl net.ipv4.conf.all.drop_gratuitous_arp
      is set to 1
    ansible.posix.sysctl:
      name: net.ipv4.conf.all.drop_gratuitous_arp
      value: '1'
      sysctl_file: /etc/sysctl.d/net_ipv4_conf_all_drop_gratuitous_arp.conf
      state: present
      reload: true
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - disable_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - reboot_required
    - sysctl_net_ipv4_conf_all_drop_gratuitous_arp

  - name: Prevent Routing External Traffic to Local Loopback 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:
    - disable_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - reboot_required
    - sysctl_net_ipv4_conf_all_route_localnet

  - name: Prevent Routing External Traffic to Local Loopback on All IPv4 Interfaces
      - Find all files that contain net.ipv4.conf.all.route_localnet
    ansible.builtin.shell:
      cmd: find -L {{ sysctl_paths | join(" ") }} -type f -name '*.conf' | xargs grep
        -HP '^\s*net.ipv4.conf.all.route_localnet\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:
    - disable_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - reboot_required
    - sysctl_net_ipv4_conf_all_route_localnet

  - name: Prevent Routing External Traffic to Local Loopback on All IPv4 Interfaces
      - Find all files that set net.ipv4.conf.all.route_localnet to correct value
    ansible.builtin.shell:
      cmd: find -L {{ sysctl_paths | join(" ") }} -type f -name '*.conf' | xargs grep
        -HP '^\s*net.ipv4.conf.all.route_localnet\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:
    - disable_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - reboot_required
    - sysctl_net_ipv4_conf_all_route_localnet

  - name: Prevent Routing External Traffic to Local Loopback on All IPv4 Interfaces
      - Comment out any occurrences of net.ipv4.conf.all.route_localnet from config
      files
    ansible.builtin.replace:
      path: '{{ item | split(":") | first }}'
      regexp: ^[\s]*net.ipv4.conf.all.route_localnet
      replace: '#net.ipv4.conf.all.route_localnet'
    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:
    - disable_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - reboot_required
    - sysctl_net_ipv4_conf_all_route_localnet

  - name: Prevent Routing External Traffic to Local Loopback on All IPv4 Interfaces
      - Comment out any occurrences of net.ipv4.conf.all.route_localnet from /etc/sysctl.conf
    ansible.builtin.replace:
      path: '{{ item }}'
      regexp: ^[\s]*net.ipv4.conf.all.route_localnet
      replace: '#net.ipv4.conf.all.route_localnet'
    with_fileglob:
    - /etc/sysctl.conf
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - disable_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - reboot_required
    - sysctl_net_ipv4_conf_all_route_localnet

  - name: Prevent Routing External Traffic to Local Loopback on All IPv4 Interfaces
      - Ensure sysctl net.ipv4.conf.all.route_localnet is set to 0
    ansible.posix.sysctl:
      name: net.ipv4.conf.all.route_localnet
      value: '0'
      sysctl_file: /etc/sysctl.d/net_ipv4_conf_all_route_localnet.conf
      state: present
      reload: true
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - disable_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - reboot_required
    - sysctl_net_ipv4_conf_all_route_localnet

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

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

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

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

  - name: Enable Kernel Parameter to Use Reverse Path Filtering on all IPv4 Interfaces
      - Comment out any occurrences of net.ipv4.conf.all.rp_filter from /etc/sysctl.conf
    ansible.builtin.replace:
      path: '{{ item }}'
      regexp: ^[\s]*net.ipv4.conf.all.rp_filter
      replace: '#net.ipv4.conf.all.rp_filter'
    with_fileglob:
    - /etc/sysctl.conf
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-006024
    - NIST-800-171-3.1.20
    - NIST-800-53-CM-6(a)
    - NIST-800-53-CM-7(a)
    - NIST-800-53-CM-7(b)
    - NIST-800-53-SC-7(a)
    - PCI-DSS-Req-1.4.3
    - PCI-DSSv4-1.4
    - PCI-DSSv4-1.4.3
    - disable_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - reboot_required
    - sysctl_net_ipv4_conf_all_rp_filter

  - name: Enable Kernel Parameter to Use Reverse Path Filtering on all IPv4 Interfaces
      - Ensure sysctl net.ipv4.conf.all.rp_filter is set
    ansible.posix.sysctl:
      name: net.ipv4.conf.all.rp_filter
      value: '{{ sysctl_net_ipv4_conf_all_rp_filter_value }}'
      sysctl_file: /etc/sysctl.d/net_ipv4_conf_all_rp_filter.conf
      state: present
      reload: true
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-006024
    - NIST-800-171-3.1.20
    - NIST-800-53-CM-6(a)
    - NIST-800-53-CM-7(a)
    - NIST-800-53-CM-7(b)
    - NIST-800-53-SC-7(a)
    - PCI-DSS-Req-1.4.3
    - PCI-DSSv4-1.4
    - PCI-DSSv4-1.4.3
    - disable_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - reboot_required
    - sysctl_net_ipv4_conf_all_rp_filter

  - name: Disable Kernel Parameter for Accepting Secure ICMP Redirects on all IPv4
      Interfaces - Set fact for sysctl paths
    ansible.builtin.set_fact:
      sysctl_paths:
      - /etc/sysctl.d/
      - /run/sysctl.d/
      - /usr/local/lib/sysctl.d/
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - NIST-800-171-3.1.20
    - NIST-800-53-CM-6(a)
    - NIST-800-53-CM-7(a)
    - NIST-800-53-CM-7(b)
    - NIST-800-53-SC-7(a)
    - PCI-DSS-Req-1.4.3
    - PCI-DSSv4-1.4
    - PCI-DSSv4-1.4.3
    - disable_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - reboot_required
    - sysctl_net_ipv4_conf_all_secure_redirects

  - name: Disable Kernel Parameter for Accepting Secure ICMP Redirects on all IPv4
      Interfaces - Find all files that contain net.ipv4.conf.all.secure_redirects
    ansible.builtin.shell:
      cmd: find -L {{ sysctl_paths | join(" ") }} -type f -name '*.conf' | xargs grep
        -HP '^\s*net.ipv4.conf.all.secure_redirects\s*=\s*.*$'
    register: find_all_values
    check_mode: false
    changed_when: false
    failed_when: false
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - NIST-800-171-3.1.20
    - NIST-800-53-CM-6(a)
    - NIST-800-53-CM-7(a)
    - NIST-800-53-CM-7(b)
    - NIST-800-53-SC-7(a)
    - PCI-DSS-Req-1.4.3
    - PCI-DSSv4-1.4
    - PCI-DSSv4-1.4.3
    - disable_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - reboot_required
    - sysctl_net_ipv4_conf_all_secure_redirects

  - name: Disable Kernel Parameter for Accepting Secure ICMP Redirects on all IPv4
      Interfaces - Find all files that set net.ipv4.conf.all.secure_redirects to correct
      value
    ansible.builtin.shell:
      cmd: find -L {{ sysctl_paths | join(" ") }} -type f -name '*.conf' | xargs grep
        -HP '^\s*net.ipv4.conf.all.secure_redirects\s*=\s*{{ sysctl_net_ipv4_conf_all_secure_redirects_value
        }}$'
    register: find_correct_value
    check_mode: false
    changed_when: false
    failed_when: false
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - NIST-800-171-3.1.20
    - NIST-800-53-CM-6(a)
    - NIST-800-53-CM-7(a)
    - NIST-800-53-CM-7(b)
    - NIST-800-53-SC-7(a)
    - PCI-DSS-Req-1.4.3
    - PCI-DSSv4-1.4
    - PCI-DSSv4-1.4.3
    - disable_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - reboot_required
    - sysctl_net_ipv4_conf_all_secure_redirects

  - name: Disable Kernel Parameter for Accepting Secure ICMP Redirects on all IPv4
      Interfaces - Comment out any occurrences of net.ipv4.conf.all.secure_redirects
      from config files
    ansible.builtin.replace:
      path: '{{ item | split(":") | first }}'
      regexp: ^[\s]*net.ipv4.conf.all.secure_redirects
      replace: '#net.ipv4.conf.all.secure_redirects'
    loop: '{{ find_all_values.stdout_lines }}'
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - find_correct_value.stdout_lines | length == 0 or find_all_values.stdout_lines
      | length > find_correct_value.stdout_lines | length
    tags:
    - NIST-800-171-3.1.20
    - NIST-800-53-CM-6(a)
    - NIST-800-53-CM-7(a)
    - NIST-800-53-CM-7(b)
    - NIST-800-53-SC-7(a)
    - PCI-DSS-Req-1.4.3
    - PCI-DSSv4-1.4
    - PCI-DSSv4-1.4.3
    - disable_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - reboot_required
    - sysctl_net_ipv4_conf_all_secure_redirects

  - name: Disable Kernel Parameter for Accepting Secure ICMP Redirects on all IPv4
      Interfaces - Comment out any occurrences of net.ipv4.conf.all.secure_redirects
      from /etc/sysctl.conf
    ansible.builtin.replace:
      path: '{{ item }}'
      regexp: ^[\s]*net.ipv4.conf.all.secure_redirects
      replace: '#net.ipv4.conf.all.secure_redirects'
    with_fileglob:
    - /etc/sysctl.conf
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - NIST-800-171-3.1.20
    - NIST-800-53-CM-6(a)
    - NIST-800-53-CM-7(a)
    - NIST-800-53-CM-7(b)
    - NIST-800-53-SC-7(a)
    - PCI-DSS-Req-1.4.3
    - PCI-DSSv4-1.4
    - PCI-DSSv4-1.4.3
    - disable_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - reboot_required
    - sysctl_net_ipv4_conf_all_secure_redirects

  - name: Disable Kernel Parameter for Accepting Secure ICMP Redirects on all IPv4
      Interfaces - Ensure sysctl net.ipv4.conf.all.secure_redirects is set
    ansible.posix.sysctl:
      name: net.ipv4.conf.all.secure_redirects
      value: '{{ sysctl_net_ipv4_conf_all_secure_redirects_value }}'
      sysctl_file: /etc/sysctl.d/net_ipv4_conf_all_secure_redirects.conf
      state: present
      reload: true
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - NIST-800-171-3.1.20
    - NIST-800-53-CM-6(a)
    - NIST-800-53-CM-7(a)
    - NIST-800-53-CM-7(b)
    - NIST-800-53-SC-7(a)
    - PCI-DSS-Req-1.4.3
    - PCI-DSSv4-1.4
    - PCI-DSSv4-1.4.3
    - disable_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - reboot_required
    - sysctl_net_ipv4_conf_all_secure_redirects

  - name: Configure Sending and Accepting Shared Media 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:
    - disable_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - reboot_required
    - sysctl_net_ipv4_conf_all_shared_media

  - name: Configure Sending and Accepting Shared Media Redirects for All IPv4 Interfaces
      - Find all files that contain net.ipv4.conf.all.shared_media
    ansible.builtin.shell:
      cmd: find -L {{ sysctl_paths | join(" ") }} -type f -name '*.conf' | xargs grep
        -HP '^\s*net.ipv4.conf.all.shared_media\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:
    - disable_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - reboot_required
    - sysctl_net_ipv4_conf_all_shared_media

  - name: Configure Sending and Accepting Shared Media Redirects for All IPv4 Interfaces
      - Find all files that set net.ipv4.conf.all.shared_media to correct value
    ansible.builtin.shell:
      cmd: find -L {{ sysctl_paths | join(" ") }} -type f -name '*.conf' | xargs grep
        -HP '^\s*net.ipv4.conf.all.shared_media\s*=\s*{{ sysctl_net_ipv4_conf_all_shared_media_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:
    - disable_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - reboot_required
    - sysctl_net_ipv4_conf_all_shared_media

  - name: Configure Sending and Accepting Shared Media Redirects for All IPv4 Interfaces
      - Comment out any occurrences of net.ipv4.conf.all.shared_media from config
      files
    ansible.builtin.replace:
      path: '{{ item | split(":") | first }}'
      regexp: ^[\s]*net.ipv4.conf.all.shared_media
      replace: '#net.ipv4.conf.all.shared_media'
    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:
    - disable_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - reboot_required
    - sysctl_net_ipv4_conf_all_shared_media

  - name: Configure Sending and Accepting Shared Media Redirects for All IPv4 Interfaces
      - Comment out any occurrences of net.ipv4.conf.all.shared_media from /etc/sysctl.conf
    ansible.builtin.replace:
      path: '{{ item }}'
      regexp: ^[\s]*net.ipv4.conf.all.shared_media
      replace: '#net.ipv4.conf.all.shared_media'
    with_fileglob:
    - /etc/sysctl.conf
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - disable_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - reboot_required
    - sysctl_net_ipv4_conf_all_shared_media

  - name: Configure Sending and Accepting Shared Media Redirects for All IPv4 Interfaces
      - Ensure sysctl net.ipv4.conf.all.shared_media is set
    ansible.posix.sysctl:
      name: net.ipv4.conf.all.shared_media
      value: '{{ sysctl_net_ipv4_conf_all_shared_media_value }}'
      sysctl_file: /etc/sysctl.d/net_ipv4_conf_all_shared_media.conf
      state: present
      reload: true
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - disable_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - reboot_required
    - sysctl_net_ipv4_conf_all_shared_media

  - name: Disable Kernel Parameter for Accepting ICMP Redirects by Default on IPv4
      Interfaces - Set fact for sysctl paths
    ansible.builtin.set_fact:
      sysctl_paths:
      - /etc/sysctl.d/
      - /run/sysctl.d/
      - /usr/local/lib/sysctl.d/
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - CJIS-5.10.1.1
    - DISA-STIG-OL09-00-006025
    - NIST-800-171-3.1.20
    - NIST-800-53-CM-6(a)
    - NIST-800-53-CM-7(a)
    - NIST-800-53-CM-7(b)
    - NIST-800-53-SC-7(a)
    - PCI-DSS-Req-1.4.3
    - PCI-DSSv4-1.4
    - PCI-DSSv4-1.4.3
    - disable_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - reboot_required
    - sysctl_net_ipv4_conf_default_accept_redirects

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

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

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

  - name: Disable Kernel Parameter for Accepting ICMP Redirects by Default on IPv4
      Interfaces - Comment out any occurrences of net.ipv4.conf.default.accept_redirects
      from /etc/sysctl.conf
    ansible.builtin.replace:
      path: '{{ item }}'
      regexp: ^[\s]*net.ipv4.conf.default.accept_redirects
      replace: '#net.ipv4.conf.default.accept_redirects'
    with_fileglob:
    - /etc/sysctl.conf
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - CJIS-5.10.1.1
    - DISA-STIG-OL09-00-006025
    - NIST-800-171-3.1.20
    - NIST-800-53-CM-6(a)
    - NIST-800-53-CM-7(a)
    - NIST-800-53-CM-7(b)
    - NIST-800-53-SC-7(a)
    - PCI-DSS-Req-1.4.3
    - PCI-DSSv4-1.4
    - PCI-DSSv4-1.4.3
    - disable_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - reboot_required
    - sysctl_net_ipv4_conf_default_accept_redirects

  - name: Disable Kernel Parameter for Accepting ICMP Redirects by Default on IPv4
      Interfaces - Ensure sysctl net.ipv4.conf.default.accept_redirects is set
    ansible.posix.sysctl:
      name: net.ipv4.conf.default.accept_redirects
      value: '{{ sysctl_net_ipv4_conf_default_accept_redirects_value }}'
      sysctl_file: /etc/sysctl.d/net_ipv4_conf_default_accept_redirects.conf
      state: present
      reload: true
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - CJIS-5.10.1.1
    - DISA-STIG-OL09-00-006025
    - NIST-800-171-3.1.20
    - NIST-800-53-CM-6(a)
    - NIST-800-53-CM-7(a)
    - NIST-800-53-CM-7(b)
    - NIST-800-53-SC-7(a)
    - PCI-DSS-Req-1.4.3
    - PCI-DSSv4-1.4
    - PCI-DSSv4-1.4.3
    - disable_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - reboot_required
    - sysctl_net_ipv4_conf_default_accept_redirects

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

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

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

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

  - name: Disable Kernel Parameter for Accepting Source-Routed Packets on IPv4 Interfaces
      by Default - Comment out any occurrences of net.ipv4.conf.default.accept_source_route
      from /etc/sysctl.conf
    ansible.builtin.replace:
      path: '{{ item }}'
      regexp: ^[\s]*net.ipv4.conf.default.accept_source_route
      replace: '#net.ipv4.conf.default.accept_source_route'
    with_fileglob:
    - /etc/sysctl.conf
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - CJIS-5.10.1.1
    - DISA-STIG-OL09-00-006026
    - NIST-800-171-3.1.20
    - NIST-800-53-CM-7(a)
    - NIST-800-53-CM-7(b)
    - NIST-800-53-SC-5
    - NIST-800-53-SC-7(a)
    - disable_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - reboot_required
    - sysctl_net_ipv4_conf_default_accept_source_route

  - name: Disable Kernel Parameter for Accepting Source-Routed Packets on IPv4 Interfaces
      by Default - Ensure sysctl net.ipv4.conf.default.accept_source_route is set
    ansible.posix.sysctl:
      name: net.ipv4.conf.default.accept_source_route
      value: '{{ sysctl_net_ipv4_conf_default_accept_source_route_value }}'
      sysctl_file: /etc/sysctl.d/net_ipv4_conf_default_accept_source_route.conf
      state: present
      reload: true
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - CJIS-5.10.1.1
    - DISA-STIG-OL09-00-006026
    - NIST-800-171-3.1.20
    - NIST-800-53-CM-7(a)
    - NIST-800-53-CM-7(b)
    - NIST-800-53-SC-5
    - NIST-800-53-SC-7(a)
    - disable_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - reboot_required
    - sysctl_net_ipv4_conf_default_accept_source_route

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

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

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

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

  - name: Enable Kernel Parameter to Use Reverse Path Filtering on all IPv4 Interfaces
      by Default - Comment out any occurrences of net.ipv4.conf.default.rp_filter
      from /etc/sysctl.conf
    ansible.builtin.replace:
      path: '{{ item }}'
      regexp: ^[\s]*net.ipv4.conf.default.rp_filter
      replace: '#net.ipv4.conf.default.rp_filter'
    with_fileglob:
    - /etc/sysctl.conf
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-006027
    - NIST-800-171-3.1.20
    - NIST-800-53-CM-6(a)
    - NIST-800-53-CM-7(a)
    - NIST-800-53-CM-7(b)
    - NIST-800-53-SC-7(a)
    - disable_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - reboot_required
    - sysctl_net_ipv4_conf_default_rp_filter

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

  - name: 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 - Comment
      out any occurrences of net.ipv4.conf.default.secure_redirects from /etc/sysctl.conf
    ansible.builtin.replace:
      path: '{{ item }}'
      regexp: ^[\s]*net.ipv4.conf.default.secure_redirects
      replace: '#net.ipv4.conf.default.secure_redirects'
    with_fileglob:
    - /etc/sysctl.conf
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - NIST-800-171-3.1.20
    - NIST-800-53-CM-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.d/net_ipv4_conf_default_secure_redirects.conf
      state: present
      reload: true
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - NIST-800-171-3.1.20
    - NIST-800-53-CM-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 Sending and Accepting Shared Media 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:
    - disable_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - reboot_required
    - sysctl_net_ipv4_conf_default_shared_media

  - name: Configure Sending and Accepting Shared Media Redirects by Default - Find
      all files that contain net.ipv4.conf.default.shared_media
    ansible.builtin.shell:
      cmd: find -L {{ sysctl_paths | join(" ") }} -type f -name '*.conf' | xargs grep
        -HP '^\s*net.ipv4.conf.default.shared_media\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:
    - disable_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - reboot_required
    - sysctl_net_ipv4_conf_default_shared_media

  - name: Configure Sending and Accepting Shared Media Redirects by Default - Find
      all files that set net.ipv4.conf.default.shared_media to correct value
    ansible.builtin.shell:
      cmd: find -L {{ sysctl_paths | join(" ") }} -type f -name '*.conf' | xargs grep
        -HP '^\s*net.ipv4.conf.default.shared_media\s*=\s*{{ sysctl_net_ipv4_conf_default_shared_media_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:
    - disable_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - reboot_required
    - sysctl_net_ipv4_conf_default_shared_media

  - name: Configure Sending and Accepting Shared Media Redirects by Default - Comment
      out any occurrences of net.ipv4.conf.default.shared_media from config files
    ansible.builtin.replace:
      path: '{{ item | split(":") | first }}'
      regexp: ^[\s]*net.ipv4.conf.default.shared_media
      replace: '#net.ipv4.conf.default.shared_media'
    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:
    - disable_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - reboot_required
    - sysctl_net_ipv4_conf_default_shared_media

  - name: Configure Sending and Accepting Shared Media Redirects by Default - Comment
      out any occurrences of net.ipv4.conf.default.shared_media from /etc/sysctl.conf
    ansible.builtin.replace:
      path: '{{ item }}'
      regexp: ^[\s]*net.ipv4.conf.default.shared_media
      replace: '#net.ipv4.conf.default.shared_media'
    with_fileglob:
    - /etc/sysctl.conf
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - disable_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - reboot_required
    - sysctl_net_ipv4_conf_default_shared_media

  - name: Configure Sending and Accepting Shared Media Redirects by Default - Ensure
      sysctl net.ipv4.conf.default.shared_media is set
    ansible.posix.sysctl:
      name: net.ipv4.conf.default.shared_media
      value: '{{ sysctl_net_ipv4_conf_default_shared_media_value }}'
      sysctl_file: /etc/sysctl.d/net_ipv4_conf_default_shared_media.conf
      state: present
      reload: true
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - disable_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - reboot_required
    - sysctl_net_ipv4_conf_default_shared_media

  - name: Enable Kernel Parameter to Ignore Bogus ICMP Error Responses on IPv4 Interfaces
      - Set fact for sysctl paths
    ansible.builtin.set_fact:
      sysctl_paths:
      - /etc/sysctl.d/
      - /run/sysctl.d/
      - /usr/local/lib/sysctl.d/
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-006031
    - NIST-800-171-3.1.20
    - NIST-800-53-CM-7(a)
    - NIST-800-53-CM-7(b)
    - NIST-800-53-SC-5
    - PCI-DSS-Req-1.4.3
    - PCI-DSSv4-1.4
    - PCI-DSSv4-1.4.2
    - disable_strategy
    - low_complexity
    - medium_disruption
    - reboot_required
    - sysctl_net_ipv4_icmp_ignore_bogus_error_responses
    - unknown_severity

  - name: Enable Kernel Parameter to Ignore Bogus ICMP Error Responses on IPv4 Interfaces
      - Find all files that contain net.ipv4.icmp_ignore_bogus_error_responses
    ansible.builtin.shell:
      cmd: find -L {{ sysctl_paths | join(" ") }} -type f -name '*.conf' | xargs grep
        -HP '^\s*net.ipv4.icmp_ignore_bogus_error_responses\s*=\s*.*$'
    register: find_all_values
    check_mode: false
    changed_when: false
    failed_when: false
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-006031
    - NIST-800-171-3.1.20
    - NIST-800-53-CM-7(a)
    - NIST-800-53-CM-7(b)
    - NIST-800-53-SC-5
    - PCI-DSS-Req-1.4.3
    - PCI-DSSv4-1.4
    - PCI-DSSv4-1.4.2
    - disable_strategy
    - low_complexity
    - medium_disruption
    - reboot_required
    - sysctl_net_ipv4_icmp_ignore_bogus_error_responses
    - unknown_severity

  - name: Enable Kernel Parameter to Ignore Bogus ICMP Error Responses on IPv4 Interfaces
      - Find all files that set net.ipv4.icmp_ignore_bogus_error_responses to correct
      value
    ansible.builtin.shell:
      cmd: find -L {{ sysctl_paths | join(" ") }} -type f -name '*.conf' | xargs grep
        -HP '^\s*net.ipv4.icmp_ignore_bogus_error_responses\s*=\s*{{ sysctl_net_ipv4_icmp_ignore_bogus_error_responses_value
        }}$'
    register: find_correct_value
    check_mode: false
    changed_when: false
    failed_when: false
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-006031
    - NIST-800-171-3.1.20
    - NIST-800-53-CM-7(a)
    - NIST-800-53-CM-7(b)
    - NIST-800-53-SC-5
    - PCI-DSS-Req-1.4.3
    - PCI-DSSv4-1.4
    - PCI-DSSv4-1.4.2
    - disable_strategy
    - low_complexity
    - medium_disruption
    - reboot_required
    - sysctl_net_ipv4_icmp_ignore_bogus_error_responses
    - unknown_severity

  - name: Enable Kernel Parameter to Ignore Bogus ICMP Error Responses on IPv4 Interfaces
      - Comment out any occurrences of net.ipv4.icmp_ignore_bogus_error_responses
      from config files
    ansible.builtin.replace:
      path: '{{ item | split(":") | first }}'
      regexp: ^[\s]*net.ipv4.icmp_ignore_bogus_error_responses
      replace: '#net.ipv4.icmp_ignore_bogus_error_responses'
    loop: '{{ find_all_values.stdout_lines }}'
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - find_correct_value.stdout_lines | length == 0 or find_all_values.stdout_lines
      | length > find_correct_value.stdout_lines | length
    tags:
    - DISA-STIG-OL09-00-006031
    - NIST-800-171-3.1.20
    - NIST-800-53-CM-7(a)
    - NIST-800-53-CM-7(b)
    - NIST-800-53-SC-5
    - PCI-DSS-Req-1.4.3
    - PCI-DSSv4-1.4
    - PCI-DSSv4-1.4.2
    - disable_strategy
    - low_complexity
    - medium_disruption
    - reboot_required
    - sysctl_net_ipv4_icmp_ignore_bogus_error_responses
    - unknown_severity

  - name: Enable Kernel Parameter to Ignore Bogus ICMP Error Responses on IPv4 Interfaces
      - Comment out any occurrences of net.ipv4.icmp_ignore_bogus_error_responses
      from /etc/sysctl.conf
    ansible.builtin.replace:
      path: '{{ item }}'
      regexp: ^[\s]*net.ipv4.icmp_ignore_bogus_error_responses
      replace: '#net.ipv4.icmp_ignore_bogus_error_responses'
    with_fileglob:
    - /etc/sysctl.conf
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-006031
    - NIST-800-171-3.1.20
    - NIST-800-53-CM-7(a)
    - NIST-800-53-CM-7(b)
    - NIST-800-53-SC-5
    - PCI-DSS-Req-1.4.3
    - PCI-DSSv4-1.4
    - PCI-DSSv4-1.4.2
    - disable_strategy
    - low_complexity
    - medium_disruption
    - reboot_required
    - sysctl_net_ipv4_icmp_ignore_bogus_error_responses
    - unknown_severity

  - name: Enable Kernel Parameter to Ignore Bogus ICMP Error Responses on IPv4 Interfaces
      - Ensure sysctl net.ipv4.icmp_ignore_bogus_error_responses is set
    ansible.posix.sysctl:
      name: net.ipv4.icmp_ignore_bogus_error_responses
      value: '{{ sysctl_net_ipv4_icmp_ignore_bogus_error_responses_value }}'
      sysctl_file: /etc/sysctl.d/net_ipv4_icmp_ignore_bogus_error_responses.conf
      state: present
      reload: true
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-006031
    - NIST-800-171-3.1.20
    - NIST-800-53-CM-7(a)
    - NIST-800-53-CM-7(b)
    - NIST-800-53-SC-5
    - PCI-DSS-Req-1.4.3
    - PCI-DSSv4-1.4
    - PCI-DSSv4-1.4.2
    - disable_strategy
    - low_complexity
    - medium_disruption
    - reboot_required
    - sysctl_net_ipv4_icmp_ignore_bogus_error_responses
    - unknown_severity

  - name: Set Kernel Parameter to Increase Local Port Range - 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:
    - disable_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - reboot_required
    - sysctl_net_ipv4_ip_local_port_range

  - name: Set Kernel Parameter to Increase Local Port Range - Find all files that
      contain net.ipv4.ip_local_port_range
    ansible.builtin.shell:
      cmd: find -L {{ sysctl_paths | join(" ") }} -type f -name '*.conf' | xargs grep
        -HP '^\s*net.ipv4.ip_local_port_range\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:
    - disable_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - reboot_required
    - sysctl_net_ipv4_ip_local_port_range

  - name: Set Kernel Parameter to Increase Local Port Range - Find all files that
      set net.ipv4.ip_local_port_range to correct value
    ansible.builtin.shell:
      cmd: find -L {{ sysctl_paths | join(" ") }} -type f -name '*.conf' | xargs grep
        -HP '^\s*net.ipv4.ip_local_port_range\s*=\s*32768 65535$'
    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:
    - disable_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - reboot_required
    - sysctl_net_ipv4_ip_local_port_range

  - name: Set Kernel Parameter to Increase Local Port Range - Comment out any occurrences
      of net.ipv4.ip_local_port_range from config files
    ansible.builtin.replace:
      path: '{{ item | split(":") | first }}'
      regexp: ^[\s]*net.ipv4.ip_local_port_range
      replace: '#net.ipv4.ip_local_port_range'
    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:
    - disable_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - reboot_required
    - sysctl_net_ipv4_ip_local_port_range

  - name: Set Kernel Parameter to Increase Local Port Range - Comment out any occurrences
      of net.ipv4.ip_local_port_range from /etc/sysctl.conf
    ansible.builtin.replace:
      path: '{{ item }}'
      regexp: ^[\s]*net.ipv4.ip_local_port_range
      replace: '#net.ipv4.ip_local_port_range'
    with_fileglob:
    - /etc/sysctl.conf
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - disable_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - reboot_required
    - sysctl_net_ipv4_ip_local_port_range

  - name: Set Kernel Parameter to Increase Local Port Range - Ensure sysctl net.ipv4.ip_local_port_range
      is set to 32768 65535
    ansible.posix.sysctl:
      name: net.ipv4.ip_local_port_range
      value: 32768 65535
      sysctl_file: /etc/sysctl.d/net_ipv4_ip_local_port_range.conf
      state: present
      reload: true
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - disable_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - reboot_required
    - sysctl_net_ipv4_ip_local_port_range

  - name: Enable Kernel Parameter to Use TCP RFC 1337 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:
    - disable_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - reboot_required
    - sysctl_net_ipv4_tcp_rfc1337

  - name: Enable Kernel Parameter to Use TCP RFC 1337 on IPv4 Interfaces - Find all
      files that contain net.ipv4.tcp_rfc1337
    ansible.builtin.shell:
      cmd: find -L {{ sysctl_paths | join(" ") }} -type f -name '*.conf' | xargs grep
        -HP '^\s*net.ipv4.tcp_rfc1337\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:
    - disable_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - reboot_required
    - sysctl_net_ipv4_tcp_rfc1337

  - name: Enable Kernel Parameter to Use TCP RFC 1337 on IPv4 Interfaces - Find all
      files that set net.ipv4.tcp_rfc1337 to correct value
    ansible.builtin.shell:
      cmd: find -L {{ sysctl_paths | join(" ") }} -type f -name '*.conf' | xargs grep
        -HP '^\s*net.ipv4.tcp_rfc1337\s*=\s*{{ sysctl_net_ipv4_tcp_rfc1337_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:
    - disable_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - reboot_required
    - sysctl_net_ipv4_tcp_rfc1337

  - name: Enable Kernel Parameter to Use TCP RFC 1337 on IPv4 Interfaces - Comment
      out any occurrences of net.ipv4.tcp_rfc1337 from config files
    ansible.builtin.replace:
      path: '{{ item | split(":") | first }}'
      regexp: ^[\s]*net.ipv4.tcp_rfc1337
      replace: '#net.ipv4.tcp_rfc1337'
    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:
    - disable_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - reboot_required
    - sysctl_net_ipv4_tcp_rfc1337

  - name: Enable Kernel Parameter to Use TCP RFC 1337 on IPv4 Interfaces - Comment
      out any occurrences of net.ipv4.tcp_rfc1337 from /etc/sysctl.conf
    ansible.builtin.replace:
      path: '{{ item }}'
      regexp: ^[\s]*net.ipv4.tcp_rfc1337
      replace: '#net.ipv4.tcp_rfc1337'
    with_fileglob:
    - /etc/sysctl.conf
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - disable_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - reboot_required
    - sysctl_net_ipv4_tcp_rfc1337

  - name: Enable Kernel Parameter to Use TCP RFC 1337 on IPv4 Interfaces - Ensure
      sysctl net.ipv4.tcp_rfc1337 is set
    ansible.posix.sysctl:
      name: net.ipv4.tcp_rfc1337
      value: '{{ sysctl_net_ipv4_tcp_rfc1337_value }}'
      sysctl_file: /etc/sysctl.d/net_ipv4_tcp_rfc1337.conf
      state: present
      reload: true
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - disable_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - reboot_required
    - sysctl_net_ipv4_tcp_rfc1337

  - name: Enable Kernel Parameter to Use TCP Syncookies on Network Interfaces - Set
      fact for sysctl paths
    ansible.builtin.set_fact:
      sysctl_paths:
      - /etc/sysctl.d/
      - /run/sysctl.d/
      - /usr/local/lib/sysctl.d/
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - CJIS-5.10.1.1
    - DISA-STIG-OL09-00-006050
    - NIST-800-171-3.1.20
    - NIST-800-53-CM-6(a)
    - NIST-800-53-CM-7(a)
    - NIST-800-53-CM-7(b)
    - NIST-800-53-SC-5(1)
    - NIST-800-53-SC-5(2)
    - NIST-800-53-SC-5(3)(a)
    - PCI-DSS-Req-1.4.1
    - PCI-DSSv4-1.4
    - PCI-DSSv4-1.4.3
    - disable_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - reboot_required
    - sysctl_net_ipv4_tcp_syncookies

  - name: Enable Kernel Parameter to Use TCP Syncookies on Network Interfaces - Find
      all files that contain net.ipv4.tcp_syncookies
    ansible.builtin.shell:
      cmd: find -L {{ sysctl_paths | join(" ") }} -type f -name '*.conf' | xargs grep
        -HP '^\s*net.ipv4.tcp_syncookies\s*=\s*.*$'
    register: find_all_values
    check_mode: false
    changed_when: false
    failed_when: false
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - CJIS-5.10.1.1
    - DISA-STIG-OL09-00-006050
    - NIST-800-171-3.1.20
    - NIST-800-53-CM-6(a)
    - NIST-800-53-CM-7(a)
    - NIST-800-53-CM-7(b)
    - NIST-800-53-SC-5(1)
    - NIST-800-53-SC-5(2)
    - NIST-800-53-SC-5(3)(a)
    - PCI-DSS-Req-1.4.1
    - PCI-DSSv4-1.4
    - PCI-DSSv4-1.4.3
    - disable_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - reboot_required
    - sysctl_net_ipv4_tcp_syncookies

  - name: Enable Kernel Parameter to Use TCP Syncookies on Network Interfaces - Find
      all files that set net.ipv4.tcp_syncookies to correct value
    ansible.builtin.shell:
      cmd: find -L {{ sysctl_paths | join(" ") }} -type f -name '*.conf' | xargs grep
        -HP '^\s*net.ipv4.tcp_syncookies\s*=\s*{{ sysctl_net_ipv4_tcp_syncookies_value
        }}$'
    register: find_correct_value
    check_mode: false
    changed_when: false
    failed_when: false
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - CJIS-5.10.1.1
    - DISA-STIG-OL09-00-006050
    - NIST-800-171-3.1.20
    - NIST-800-53-CM-6(a)
    - NIST-800-53-CM-7(a)
    - NIST-800-53-CM-7(b)
    - NIST-800-53-SC-5(1)
    - NIST-800-53-SC-5(2)
    - NIST-800-53-SC-5(3)(a)
    - PCI-DSS-Req-1.4.1
    - PCI-DSSv4-1.4
    - PCI-DSSv4-1.4.3
    - disable_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - reboot_required
    - sysctl_net_ipv4_tcp_syncookies

  - name: Enable Kernel Parameter to Use TCP Syncookies on Network Interfaces - Comment
      out any occurrences of net.ipv4.tcp_syncookies from config files
    ansible.builtin.replace:
      path: '{{ item | split(":") | first }}'
      regexp: ^[\s]*net.ipv4.tcp_syncookies
      replace: '#net.ipv4.tcp_syncookies'
    loop: '{{ find_all_values.stdout_lines }}'
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - find_correct_value.stdout_lines | length == 0 or find_all_values.stdout_lines
      | length > find_correct_value.stdout_lines | length
    tags:
    - CJIS-5.10.1.1
    - DISA-STIG-OL09-00-006050
    - NIST-800-171-3.1.20
    - NIST-800-53-CM-6(a)
    - NIST-800-53-CM-7(a)
    - NIST-800-53-CM-7(b)
    - NIST-800-53-SC-5(1)
    - NIST-800-53-SC-5(2)
    - NIST-800-53-SC-5(3)(a)
    - PCI-DSS-Req-1.4.1
    - PCI-DSSv4-1.4
    - PCI-DSSv4-1.4.3
    - disable_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - reboot_required
    - sysctl_net_ipv4_tcp_syncookies

  - name: Enable Kernel Parameter to Use TCP Syncookies on Network Interfaces - Comment
      out any occurrences of net.ipv4.tcp_syncookies from /etc/sysctl.conf
    ansible.builtin.replace:
      path: '{{ item }}'
      regexp: ^[\s]*net.ipv4.tcp_syncookies
      replace: '#net.ipv4.tcp_syncookies'
    with_fileglob:
    - /etc/sysctl.conf
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - CJIS-5.10.1.1
    - DISA-STIG-OL09-00-006050
    - NIST-800-171-3.1.20
    - NIST-800-53-CM-6(a)
    - NIST-800-53-CM-7(a)
    - NIST-800-53-CM-7(b)
    - NIST-800-53-SC-5(1)
    - NIST-800-53-SC-5(2)
    - NIST-800-53-SC-5(3)(a)
    - PCI-DSS-Req-1.4.1
    - PCI-DSSv4-1.4
    - PCI-DSSv4-1.4.3
    - disable_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - reboot_required
    - sysctl_net_ipv4_tcp_syncookies

  - name: Enable Kernel Parameter to Use TCP Syncookies on Network Interfaces - Ensure
      sysctl net.ipv4.tcp_syncookies is set
    ansible.posix.sysctl:
      name: net.ipv4.tcp_syncookies
      value: '{{ sysctl_net_ipv4_tcp_syncookies_value }}'
      sysctl_file: /etc/sysctl.d/net_ipv4_tcp_syncookies.conf
      state: present
      reload: true
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - CJIS-5.10.1.1
    - DISA-STIG-OL09-00-006050
    - NIST-800-171-3.1.20
    - NIST-800-53-CM-6(a)
    - NIST-800-53-CM-7(a)
    - NIST-800-53-CM-7(b)
    - NIST-800-53-SC-5(1)
    - NIST-800-53-SC-5(2)
    - NIST-800-53-SC-5(3)(a)
    - PCI-DSS-Req-1.4.1
    - PCI-DSSv4-1.4
    - PCI-DSSv4-1.4.3
    - disable_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - reboot_required
    - sysctl_net_ipv4_tcp_syncookies

  - name: Disable Kernel Parameter for Sending ICMP Redirects on all IPv4 Interfaces
      - Set fact for sysctl paths
    ansible.builtin.set_fact:
      sysctl_paths:
      - /etc/sysctl.d/
      - /run/sysctl.d/
      - /usr/local/lib/sysctl.d/
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - CJIS-5.10.1.1
    - DISA-STIG-OL09-00-006032
    - NIST-800-171-3.1.20
    - NIST-800-53-CM-6(a)
    - NIST-800-53-CM-7(a)
    - NIST-800-53-CM-7(b)
    - NIST-800-53-SC-5
    - NIST-800-53-SC-7(a)
    - PCI-DSSv4-1.4
    - PCI-DSSv4-1.4.5
    - disable_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - reboot_required
    - sysctl_net_ipv4_conf_all_send_redirects

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

  - name: Disable Kernel Parameter for Sending ICMP Redirects on all IPv4 Interfaces
      - Find all files that set net.ipv4.conf.all.send_redirects to correct value
    ansible.builtin.shell:
      cmd: find -L {{ sysctl_paths | join(" ") }} -type f -name '*.conf' | xargs grep
        -HP '^\s*net.ipv4.conf.all.send_redirects\s*=\s*0$'
    register: find_correct_value
    check_mode: false
    changed_when: false
    failed_when: false
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - CJIS-5.10.1.1
    - DISA-STIG-OL09-00-006032
    - NIST-800-171-3.1.20
    - NIST-800-53-CM-6(a)
    - NIST-800-53-CM-7(a)
    - NIST-800-53-CM-7(b)
    - NIST-800-53-SC-5
    - NIST-800-53-SC-7(a)
    - PCI-DSSv4-1.4
    - PCI-DSSv4-1.4.5
    - disable_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - reboot_required
    - sysctl_net_ipv4_conf_all_send_redirects

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

  - name: Disable Kernel Parameter for Sending ICMP Redirects on all IPv4 Interfaces
      - Comment out any occurrences of net.ipv4.conf.all.send_redirects from /etc/sysctl.conf
    ansible.builtin.replace:
      path: '{{ item }}'
      regexp: ^[\s]*net.ipv4.conf.all.send_redirects
      replace: '#net.ipv4.conf.all.send_redirects'
    with_fileglob:
    - /etc/sysctl.conf
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - CJIS-5.10.1.1
    - DISA-STIG-OL09-00-006032
    - NIST-800-171-3.1.20
    - NIST-800-53-CM-6(a)
    - NIST-800-53-CM-7(a)
    - NIST-800-53-CM-7(b)
    - NIST-800-53-SC-5
    - NIST-800-53-SC-7(a)
    - PCI-DSSv4-1.4
    - PCI-DSSv4-1.4.5
    - disable_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - reboot_required
    - sysctl_net_ipv4_conf_all_send_redirects

  - name: Disable Kernel Parameter for Sending ICMP Redirects on all IPv4 Interfaces
      - Ensure sysctl net.ipv4.conf.all.send_redirects is set to 0
    ansible.posix.sysctl:
      name: net.ipv4.conf.all.send_redirects
      value: '0'
      sysctl_file: /etc/sysctl.d/net_ipv4_conf_all_send_redirects.conf
      state: present
      reload: true
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - CJIS-5.10.1.1
    - DISA-STIG-OL09-00-006032
    - NIST-800-171-3.1.20
    - NIST-800-53-CM-6(a)
    - NIST-800-53-CM-7(a)
    - NIST-800-53-CM-7(b)
    - NIST-800-53-SC-5
    - NIST-800-53-SC-7(a)
    - PCI-DSSv4-1.4
    - PCI-DSSv4-1.4.5
    - disable_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - reboot_required
    - sysctl_net_ipv4_conf_all_send_redirects

  - name: Disable Kernel Parameter for Sending ICMP Redirects on all IPv4 Interfaces
      by Default - Set fact for sysctl paths
    ansible.builtin.set_fact:
      sysctl_paths:
      - /etc/sysctl.d/
      - /run/sysctl.d/
      - /usr/local/lib/sysctl.d/
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - CJIS-5.10.1.1
    - DISA-STIG-OL09-00-006033
    - NIST-800-171-3.1.20
    - NIST-800-53-CM-6(a)
    - NIST-800-53-CM-7(a)
    - NIST-800-53-CM-7(b)
    - NIST-800-53-SC-5
    - NIST-800-53-SC-7(a)
    - PCI-DSSv4-1.4
    - PCI-DSSv4-1.4.5
    - disable_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - reboot_required
    - sysctl_net_ipv4_conf_default_send_redirects

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

  - name: Disable Kernel Parameter for Sending ICMP Redirects on all IPv4 Interfaces
      by Default - Find all files that set net.ipv4.conf.default.send_redirects to
      correct value
    ansible.builtin.shell:
      cmd: find -L {{ sysctl_paths | join(" ") }} -type f -name '*.conf' | xargs grep
        -HP '^\s*net.ipv4.conf.default.send_redirects\s*=\s*0$'
    register: find_correct_value
    check_mode: false
    changed_when: false
    failed_when: false
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - CJIS-5.10.1.1
    - DISA-STIG-OL09-00-006033
    - NIST-800-171-3.1.20
    - NIST-800-53-CM-6(a)
    - NIST-800-53-CM-7(a)
    - NIST-800-53-CM-7(b)
    - NIST-800-53-SC-5
    - NIST-800-53-SC-7(a)
    - PCI-DSSv4-1.4
    - PCI-DSSv4-1.4.5
    - disable_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - reboot_required
    - sysctl_net_ipv4_conf_default_send_redirects

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

  - name: Disable Kernel Parameter for Sending ICMP Redirects on all IPv4 Interfaces
      by Default - Comment out any occurrences of net.ipv4.conf.default.send_redirects
      from /etc/sysctl.conf
    ansible.builtin.replace:
      path: '{{ item }}'
      regexp: ^[\s]*net.ipv4.conf.default.send_redirects
      replace: '#net.ipv4.conf.default.send_redirects'
    with_fileglob:
    - /etc/sysctl.conf
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - CJIS-5.10.1.1
    - DISA-STIG-OL09-00-006033
    - NIST-800-171-3.1.20
    - NIST-800-53-CM-6(a)
    - NIST-800-53-CM-7(a)
    - NIST-800-53-CM-7(b)
    - NIST-800-53-SC-5
    - NIST-800-53-SC-7(a)
    - PCI-DSSv4-1.4
    - PCI-DSSv4-1.4.5
    - disable_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - reboot_required
    - sysctl_net_ipv4_conf_default_send_redirects

  - name: Disable Kernel Parameter for Sending ICMP Redirects on all IPv4 Interfaces
      by Default - Ensure sysctl net.ipv4.conf.default.send_redirects is set to 0
    ansible.posix.sysctl:
      name: net.ipv4.conf.default.send_redirects
      value: '0'
      sysctl_file: /etc/sysctl.d/net_ipv4_conf_default_send_redirects.conf
      state: present
      reload: true
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - CJIS-5.10.1.1
    - DISA-STIG-OL09-00-006033
    - NIST-800-171-3.1.20
    - NIST-800-53-CM-6(a)
    - NIST-800-53-CM-7(a)
    - NIST-800-53-CM-7(b)
    - NIST-800-53-SC-5
    - NIST-800-53-SC-7(a)
    - PCI-DSSv4-1.4
    - PCI-DSSv4-1.4.5
    - disable_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - reboot_required
    - sysctl_net_ipv4_conf_default_send_redirects

  - name: Disable Kernel Parameter for IP Forwarding on IPv4 Interfaces - Set fact
      for sysctl paths
    ansible.builtin.set_fact:
      sysctl_paths:
      - /etc/sysctl.d/
      - /run/sysctl.d/
      - /usr/local/lib/sysctl.d/
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - NIST-800-171-3.1.20
    - NIST-800-53-CM-6(a)
    - NIST-800-53-CM-7(a)
    - NIST-800-53-CM-7(b)
    - NIST-800-53-SC-5
    - NIST-800-53-SC-7(a)
    - PCI-DSS-Req-1.3.1
    - PCI-DSS-Req-1.3.2
    - PCI-DSSv4-1.4
    - PCI-DSSv4-1.4.3
    - disable_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - reboot_required
    - sysctl_net_ipv4_ip_forward

  - name: Disable Kernel Parameter for IP Forwarding on IPv4 Interfaces - Find all
      files that contain net.ipv4.ip_forward
    ansible.builtin.shell:
      cmd: find -L {{ sysctl_paths | join(" ") }} -type f -name '*.conf' | xargs grep
        -HP '^\s*net.ipv4.ip_forward\s*=\s*.*$'
    register: find_all_values
    check_mode: false
    changed_when: false
    failed_when: false
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - NIST-800-171-3.1.20
    - NIST-800-53-CM-6(a)
    - NIST-800-53-CM-7(a)
    - NIST-800-53-CM-7(b)
    - NIST-800-53-SC-5
    - NIST-800-53-SC-7(a)
    - PCI-DSS-Req-1.3.1
    - PCI-DSS-Req-1.3.2
    - PCI-DSSv4-1.4
    - PCI-DSSv4-1.4.3
    - disable_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - reboot_required
    - sysctl_net_ipv4_ip_forward

  - name: Disable Kernel Parameter for IP Forwarding on IPv4 Interfaces - Find all
      files that set net.ipv4.ip_forward to correct value
    ansible.builtin.shell:
      cmd: find -L {{ sysctl_paths | join(" ") }} -type f -name '*.conf' | xargs grep
        -HP '^\s*net.ipv4.ip_forward\s*=\s*0$'
    register: find_correct_value
    check_mode: false
    changed_when: false
    failed_when: false
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - NIST-800-171-3.1.20
    - NIST-800-53-CM-6(a)
    - NIST-800-53-CM-7(a)
    - NIST-800-53-CM-7(b)
    - NIST-800-53-SC-5
    - NIST-800-53-SC-7(a)
    - PCI-DSS-Req-1.3.1
    - PCI-DSS-Req-1.3.2
    - PCI-DSSv4-1.4
    - PCI-DSSv4-1.4.3
    - disable_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - reboot_required
    - sysctl_net_ipv4_ip_forward

  - name: Disable Kernel Parameter for IP Forwarding on IPv4 Interfaces - Comment
      out any occurrences of net.ipv4.ip_forward from config files
    ansible.builtin.replace:
      path: '{{ item | split(":") | first }}'
      regexp: ^[\s]*net.ipv4.ip_forward
      replace: '#net.ipv4.ip_forward'
    loop: '{{ find_all_values.stdout_lines }}'
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - find_correct_value.stdout_lines | length == 0 or find_all_values.stdout_lines
      | length > find_correct_value.stdout_lines | length
    tags:
    - NIST-800-171-3.1.20
    - NIST-800-53-CM-6(a)
    - NIST-800-53-CM-7(a)
    - NIST-800-53-CM-7(b)
    - NIST-800-53-SC-5
    - NIST-800-53-SC-7(a)
    - PCI-DSS-Req-1.3.1
    - PCI-DSS-Req-1.3.2
    - PCI-DSSv4-1.4
    - PCI-DSSv4-1.4.3
    - disable_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - reboot_required
    - sysctl_net_ipv4_ip_forward

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

  - name: Disable Kernel Parameter for IP Forwarding on IPv4 Interfaces - Ensure sysctl
      net.ipv4.ip_forward is set to 0
    ansible.posix.sysctl:
      name: net.ipv4.ip_forward
      value: '0'
      sysctl_file: /etc/sysctl.d/net_ipv4_ip_forward.conf
      state: present
      reload: true
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - NIST-800-171-3.1.20
    - NIST-800-53-CM-6(a)
    - NIST-800-53-CM-7(a)
    - NIST-800-53-CM-7(b)
    - NIST-800-53-SC-5
    - NIST-800-53-SC-7(a)
    - PCI-DSS-Req-1.3.1
    - PCI-DSS-Req-1.3.2
    - PCI-DSSv4-1.4
    - PCI-DSSv4-1.4.3
    - disable_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - reboot_required
    - sysctl_net_ipv4_ip_forward

  - name: Check that the root group is defined
    ansible.builtin.getent:
      database: group
      key: root
    ignore_errors: true
    when:
    - '"nftables" in ansible_facts.packages'
    - directory_groupowner_etc_nftables_newgroup is undefined
    tags:
    - configure_strategy
    - directory_groupowner_etc_nftables
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

  - name: Set the directory_groupowner_etc_nftables_newgroup variable if root found
    ansible.builtin.set_fact:
      directory_groupowner_etc_nftables_newgroup: root
    when:
    - '"nftables" in ansible_facts.packages'
    - ansible_facts.getent_group["root"] is defined
    tags:
    - configure_strategy
    - directory_groupowner_etc_nftables
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

  - name: Ensure group owner on /etc/nftables/
    ansible.builtin.file:
      path: /etc/nftables/
      follow: false
      state: directory
      group: '{{ directory_groupowner_etc_nftables_newgroup }}'
    when: '"nftables" in ansible_facts.packages'
    tags:
    - configure_strategy
    - directory_groupowner_etc_nftables
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

  - name: Set the directory_owner_etc_nftables_newown variable if represented by uid
    ansible.builtin.set_fact:
      directory_owner_etc_nftables_newown: '0'
    when: '"nftables" in ansible_facts.packages'
    tags:
    - configure_strategy
    - directory_owner_etc_nftables
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

  - name: Ensure owner on directory /etc/nftables/
    ansible.builtin.file:
      path: /etc/nftables/
      follow: false
      state: directory
      owner: '{{ directory_owner_etc_nftables_newown }}'
    when: '"nftables" in ansible_facts.packages'
    tags:
    - configure_strategy
    - directory_owner_etc_nftables
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

  - name: Find /etc/nftables/ file(s)
    ansible.builtin.command: 'find -P /etc/nftables/ -maxdepth 0 -perm /u+s,g+xwrs,o+xwrt  -type
      d '
    register: files_found
    changed_when: false
    failed_when: false
    check_mode: false
    when: '"nftables" in ansible_facts.packages'
    tags:
    - configure_strategy
    - directory_permissions_etc_nftables
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

  - name: Set permissions for /etc/nftables/ file(s)
    ansible.builtin.file:
      path: '{{ item }}'
      mode: u-s,g-xwrs,o-xwrt
      state: directory
    with_items:
    - '{{ files_found.stdout_lines }}'
    when: '"nftables" in ansible_facts.packages'
    tags:
    - configure_strategy
    - directory_permissions_etc_nftables
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

  - name: Ensure All World-Writable Directories Are Owned by root User - Define Excluded
      (Non-Local) File Systems and Paths
    ansible.builtin.set_fact:
      excluded_fstypes:
      - afs
      - autofs
      - ceph
      - cifs
      - smb3
      - smbfs
      - sshfs
      - ncpfs
      - ncp
      - nfs
      - nfs4
      - gfs
      - gfs2
      - glusterfs
      - gpfs
      - pvfs2
      - ocfs2
      - lustre
      - davfs
      - fuse.sshfs
      excluded_paths:
      - dev
      - proc
      - run
      - sys
      search_paths: []
    tags:
    - dir_perms_world_writable_root_owned
    - low_complexity
    - medium_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Ensure All World-Writable Directories Are Owned by root User - Find Relevant
      Root Directories Ignoring Pre-Defined Excluded Paths
    ansible.builtin.find:
      paths: /
      file_type: directory
      excludes: '{{ excluded_paths }}'
      hidden: true
      recurse: false
    register: result_relevant_root_dirs
    tags:
    - dir_perms_world_writable_root_owned
    - low_complexity
    - medium_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Ensure All World-Writable Directories Are Owned by root User - Include Relevant
      Root Directories in a List of Paths to be Searched
    ansible.builtin.set_fact:
      search_paths: '{{ search_paths | union([item.path]) }}'
    loop: '{{ result_relevant_root_dirs.files }}'
    tags:
    - dir_perms_world_writable_root_owned
    - low_complexity
    - medium_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Ensure All World-Writable Directories Are Owned by root User - Increment
      Search Paths List with Local Partitions Mount Points
    ansible.builtin.set_fact:
      search_paths: '{{ search_paths | union([item.mount]) }}'
    loop: '{{ ansible_mounts }}'
    when:
    - item.fstype not in excluded_fstypes
    - item.mount != '/'
    tags:
    - dir_perms_world_writable_root_owned
    - low_complexity
    - medium_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Ensure All World-Writable Directories Are Owned by root User - Increment
      Search Paths List with Local NFS File System Targets
    ansible.builtin.set_fact:
      search_paths: '{{ search_paths | union([item.device.split('':'')[1]]) }}'
    loop: '{{ ansible_mounts }}'
    when: item.device is search("localhost:")
    tags:
    - dir_perms_world_writable_root_owned
    - low_complexity
    - medium_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Ensure All World-Writable Directories Are Owned by root User - Define Rule
      Specific Facts
    ansible.builtin.set_fact:
      world_writable_dirs: []
    tags:
    - dir_perms_world_writable_root_owned
    - low_complexity
    - medium_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Ensure All World-Writable Directories Are Owned by root User - Find All
      Uncompliant Directories in Local File Systems
    ansible.builtin.command:
      cmd: find {{ item }} -xdev -type d -perm -0002 -uid +0
    loop: '{{ search_paths }}'
    changed_when: false
    register: result_found_dirs
    tags:
    - dir_perms_world_writable_root_owned
    - low_complexity
    - medium_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Ensure All World-Writable Directories Are Owned by root User - Create List
      of World Writable Directories Not Owned by root
    ansible.builtin.set_fact:
      world_writable_dirs: '{{ world_writable_dirs | union(item.stdout_lines) | list
        }}'
    loop: '{{ result_found_dirs.results }}'
    when: item is not skipped
    tags:
    - dir_perms_world_writable_root_owned
    - low_complexity
    - medium_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Ensure All World-Writable Directories Are Owned by root User - Ensure root
      Ownership on Local World Writable Directories
    ansible.builtin.file:
      path: '{{ item }}'
      owner: root
    loop: '{{ world_writable_dirs }}'
    tags:
    - dir_perms_world_writable_root_owned
    - low_complexity
    - medium_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Verify that All World-Writable Directories Have Sticky Bits Set - Define
      Excluded (Non-Local) File Systems and Paths
    ansible.builtin.set_fact:
      excluded_fstypes:
      - afs
      - autofs
      - ceph
      - cifs
      - smb3
      - smbfs
      - sshfs
      - ncpfs
      - ncp
      - nfs
      - nfs4
      - gfs
      - gfs2
      - glusterfs
      - gpfs
      - pvfs2
      - ocfs2
      - lustre
      - davfs
      - fuse.sshfs
      excluded_paths:
      - dev
      - proc
      - run
      - sys
      search_paths: []
    tags:
    - DISA-STIG-OL09-00-002510
    - NIST-800-53-AC-6(1)
    - NIST-800-53-CM-6(a)
    - PCI-DSSv4-2.2
    - PCI-DSSv4-2.2.6
    - dir_perms_world_writable_sticky_bits
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Verify that All World-Writable Directories Have Sticky Bits Set - Find Relevant
      Root Directories Ignoring Pre-Defined Excluded Paths
    ansible.builtin.find:
      paths: /
      file_type: directory
      excludes: '{{ excluded_paths }}'
      hidden: true
      recurse: false
    register: result_relevant_root_dirs
    tags:
    - DISA-STIG-OL09-00-002510
    - NIST-800-53-AC-6(1)
    - NIST-800-53-CM-6(a)
    - PCI-DSSv4-2.2
    - PCI-DSSv4-2.2.6
    - dir_perms_world_writable_sticky_bits
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Verify that All World-Writable Directories Have Sticky Bits Set - Include
      Relevant Root Directories in a List of Paths to be Searched
    ansible.builtin.set_fact:
      search_paths: '{{ search_paths | union([item.path]) }}'
    loop: '{{ result_relevant_root_dirs.files }}'
    tags:
    - DISA-STIG-OL09-00-002510
    - NIST-800-53-AC-6(1)
    - NIST-800-53-CM-6(a)
    - PCI-DSSv4-2.2
    - PCI-DSSv4-2.2.6
    - dir_perms_world_writable_sticky_bits
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Verify that All World-Writable Directories Have Sticky Bits Set - Increment
      Search Paths List with Local Partitions Mount Points
    ansible.builtin.set_fact:
      search_paths: '{{ search_paths | union([item.mount]) }}'
    loop: '{{ ansible_mounts }}'
    when:
    - item.fstype not in excluded_fstypes
    - item.mount != '/'
    tags:
    - DISA-STIG-OL09-00-002510
    - NIST-800-53-AC-6(1)
    - NIST-800-53-CM-6(a)
    - PCI-DSSv4-2.2
    - PCI-DSSv4-2.2.6
    - dir_perms_world_writable_sticky_bits
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Verify that All World-Writable Directories Have Sticky Bits Set - Increment
      Search Paths List with Local NFS File System Targets
    ansible.builtin.set_fact:
      search_paths: '{{ search_paths | union([item.device.split('':'')[1]]) }}'
    loop: '{{ ansible_mounts }}'
    when: item.device is search("localhost:")
    tags:
    - DISA-STIG-OL09-00-002510
    - NIST-800-53-AC-6(1)
    - NIST-800-53-CM-6(a)
    - PCI-DSSv4-2.2
    - PCI-DSSv4-2.2.6
    - dir_perms_world_writable_sticky_bits
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Verify that All World-Writable Directories Have Sticky Bits Set - Define
      Rule Specific Facts
    ansible.builtin.set_fact:
      world_writable_dirs: []
    tags:
    - DISA-STIG-OL09-00-002510
    - NIST-800-53-AC-6(1)
    - NIST-800-53-CM-6(a)
    - PCI-DSSv4-2.2
    - PCI-DSSv4-2.2.6
    - dir_perms_world_writable_sticky_bits
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Verify that All World-Writable Directories Have Sticky Bits Set - Find All
      Uncompliant Directories in Local File Systems
    ansible.builtin.command:
      cmd: find {{ item }} -xdev -type d ( -perm -0002 -a ! -perm -1000 )
    loop: '{{ search_paths }}'
    changed_when: false
    register: result_found_dirs
    tags:
    - DISA-STIG-OL09-00-002510
    - NIST-800-53-AC-6(1)
    - NIST-800-53-CM-6(a)
    - PCI-DSSv4-2.2
    - PCI-DSSv4-2.2.6
    - dir_perms_world_writable_sticky_bits
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Verify that All World-Writable Directories Have Sticky Bits Set - Create
      List of World Writable Directories Without Sticky Bit
    ansible.builtin.set_fact:
      world_writable_dirs: '{{ world_writable_dirs | union(item.stdout_lines) | list
        }}'
    loop: '{{ result_found_dirs.results }}'
    when: result_found_dirs is not skipped and item is not skipped
    tags:
    - DISA-STIG-OL09-00-002510
    - NIST-800-53-AC-6(1)
    - NIST-800-53-CM-6(a)
    - PCI-DSSv4-2.2
    - PCI-DSSv4-2.2.6
    - dir_perms_world_writable_sticky_bits
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Verify that All World-Writable Directories Have Sticky Bits Set - Ensure
      Sticky Bit is Set on Local World Writable Directories
    ansible.builtin.file:
      path: '{{ item }}'
      mode: a+t
    loop: '{{ world_writable_dirs }}'
    tags:
    - DISA-STIG-OL09-00-002510
    - NIST-800-53-AC-6(1)
    - NIST-800-53-CM-6(a)
    - PCI-DSSv4-2.2
    - PCI-DSSv4-2.2.6
    - dir_perms_world_writable_sticky_bits
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Verify that system commands directories have root as a group owner - Set
      group ownership of directories that contain system commands to root
    ansible.builtin.file:
      path: '{{ item }}'
      group: root
      recurse: 'yes'
      state: directory
      follow: 'yes'
    with_items:
    - /bin
    - /sbin
    - /usr/bin
    - /usr/sbin
    - /usr/local/bin
    - /usr/local/sbin
    tags:
    - NIST-800-53-CM-5(6)
    - NIST-800-53-CM-5(6).1
    - dir_system_commands_group_root_owned
    - medium_complexity
    - medium_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Verify that system commands directories have root ownership - Set ownership
      of directories that contain system commands to root
    ansible.builtin.file:
      path: '{{ item }}'
      owner: root
      recurse: 'yes'
      state: directory
      follow: 'yes'
    with_items:
    - /bin
    - /sbin
    - /usr/bin
    - /usr/sbin
    - /usr/local/bin
    - /usr/local/sbin
    tags:
    - NIST-800-53-CM-5(6)
    - NIST-800-53-CM-5(6).1
    - dir_system_commands_root_owned
    - medium_complexity
    - medium_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Check that the root group is defined
    ansible.builtin.getent:
      database: group
      key: root
    ignore_errors: true
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - file_groupowner_etc_crypttab_newgroup is undefined
    tags:
    - configure_strategy
    - file_groupowner_etc_crypttab
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

  - name: Set the file_groupowner_etc_crypttab_newgroup variable if root found
    ansible.builtin.set_fact:
      file_groupowner_etc_crypttab_newgroup: root
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - ansible_facts.getent_group["root"] is defined
    tags:
    - configure_strategy
    - file_groupowner_etc_crypttab
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

  - name: Test for existence /etc/crypttab
    ansible.builtin.stat:
      path: /etc/crypttab
    register: file_exists
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - configure_strategy
    - file_groupowner_etc_crypttab
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

  - name: Ensure group owner on /etc/crypttab
    ansible.builtin.file:
      path: /etc/crypttab
      follow: false
      group: '{{ file_groupowner_etc_crypttab_newgroup }}'
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - file_exists.stat is defined and file_exists.stat.exists
    tags:
    - configure_strategy
    - file_groupowner_etc_crypttab
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

  - name: Set the file_owner_etc_crypttab_newown variable if represented by uid
    ansible.builtin.set_fact:
      file_owner_etc_crypttab_newown: '0'
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - configure_strategy
    - file_owner_etc_crypttab
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

  - name: Test for existence /etc/crypttab
    ansible.builtin.stat:
      path: /etc/crypttab
    register: file_exists
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - configure_strategy
    - file_owner_etc_crypttab
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

  - name: Ensure owner on /etc/crypttab
    ansible.builtin.file:
      path: /etc/crypttab
      follow: false
      owner: '{{ file_owner_etc_crypttab_newown }}'
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - file_exists.stat is defined and file_exists.stat.exists
    tags:
    - configure_strategy
    - file_owner_etc_crypttab
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

  - name: Test for existence /etc/crypttab
    ansible.builtin.stat:
      path: /etc/crypttab
    register: file_exists
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - configure_strategy
    - file_permissions_etc_crypttab
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

  - name: Ensure permission u-xs,g-xwrs,o-xwrt on /etc/crypttab
    ansible.builtin.file:
      path: /etc/crypttab
      mode: u-xs,g-xwrs,o-xwrt
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - file_exists.stat is defined and file_exists.stat.exists
    tags:
    - configure_strategy
    - file_permissions_etc_crypttab
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

  - name: Enable Kernel Parameter to Enforce DAC on FIFOs - 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_fifos

  - name: Enable Kernel Parameter to Enforce DAC on FIFOs - Find all files that contain
      fs.protected_fifos
    ansible.builtin.shell:
      cmd: find -L {{ sysctl_paths | join(" ") }} -type f -name '*.conf' | xargs grep
        -HP '^\s*fs.protected_fifos\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_fifos

  - name: Enable Kernel Parameter to Enforce DAC on FIFOs - Find all files that set
      fs.protected_fifos to correct value
    ansible.builtin.shell:
      cmd: find -L {{ sysctl_paths | join(" ") }} -type f -name '*.conf' | xargs grep
        -HP '^\s*fs.protected_fifos\s*=\s*2$'
    register: find_correct_value
    check_mode: false
    changed_when: false
    failed_when: false
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - 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_fifos

  - name: Enable Kernel Parameter to Enforce DAC on FIFOs - Comment out any occurrences
      of fs.protected_fifos from config files
    ansible.builtin.replace:
      path: '{{ item | split(":") | first }}'
      regexp: ^[\s]*fs.protected_fifos
      replace: '#fs.protected_fifos'
    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_fifos

  - name: Enable Kernel Parameter to Enforce DAC on FIFOs - Comment out any occurrences
      of fs.protected_fifos from /etc/sysctl.conf
    ansible.builtin.replace:
      path: '{{ item }}'
      regexp: ^[\s]*fs.protected_fifos
      replace: '#fs.protected_fifos'
    with_fileglob:
    - /etc/sysctl.conf
    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_fifos

  - name: Enable Kernel Parameter to Enforce DAC on FIFOs - Ensure sysctl fs.protected_fifos
      is set to 2
    ansible.posix.sysctl:
      name: fs.protected_fifos
      value: '2'
      sysctl_file: /etc/sysctl.d/fs_protected_fifos.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_fifos

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

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

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

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

  - name: Enable Kernel Parameter to Enforce DAC on Hardlinks - Comment out any occurrences
      of fs.protected_hardlinks from /etc/sysctl.conf
    ansible.builtin.replace:
      path: '{{ item }}'
      regexp: ^[\s]*fs.protected_hardlinks
      replace: '#fs.protected_hardlinks'
    with_fileglob:
    - /etc/sysctl.conf
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-002401
    - NIST-800-53-AC-6(1)
    - NIST-800-53-CM-6(a)
    - disable_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - reboot_required
    - sysctl_fs_protected_hardlinks

  - name: Enable Kernel Parameter to Enforce DAC on Hardlinks - Ensure sysctl fs.protected_hardlinks
      is set to 1
    ansible.posix.sysctl:
      name: fs.protected_hardlinks
      value: '1'
      sysctl_file: /etc/sysctl.d/fs_protected_hardlinks.conf
      state: present
      reload: true
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-002401
    - NIST-800-53-AC-6(1)
    - NIST-800-53-CM-6(a)
    - disable_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - reboot_required
    - sysctl_fs_protected_hardlinks

  - name: Enable Kernel Parameter to Enforce DAC on Regular files - 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_regular

  - name: Enable Kernel Parameter to Enforce DAC on Regular files - Find all files
      that contain fs.protected_regular
    ansible.builtin.shell:
      cmd: find -L {{ sysctl_paths | join(" ") }} -type f -name '*.conf' | xargs grep
        -HP '^\s*fs.protected_regular\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_regular

  - name: Enable Kernel Parameter to Enforce DAC on Regular files - Find all files
      that set fs.protected_regular to correct value
    ansible.builtin.shell:
      cmd: find -L {{ sysctl_paths | join(" ") }} -type f -name '*.conf' | xargs grep
        -HP '^\s*fs.protected_regular\s*=\s*2$'
    register: find_correct_value
    check_mode: false
    changed_when: false
    failed_when: false
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - 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_regular

  - name: Enable Kernel Parameter to Enforce DAC on Regular files - Comment out any
      occurrences of fs.protected_regular from config files
    ansible.builtin.replace:
      path: '{{ item | split(":") | first }}'
      regexp: ^[\s]*fs.protected_regular
      replace: '#fs.protected_regular'
    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_regular

  - name: Enable Kernel Parameter to Enforce DAC on Regular files - Comment out any
      occurrences of fs.protected_regular from /etc/sysctl.conf
    ansible.builtin.replace:
      path: '{{ item }}'
      regexp: ^[\s]*fs.protected_regular
      replace: '#fs.protected_regular'
    with_fileglob:
    - /etc/sysctl.conf
    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_regular

  - name: Enable Kernel Parameter to Enforce DAC on Regular files - Ensure sysctl
      fs.protected_regular is set to 2
    ansible.posix.sysctl:
      name: fs.protected_regular
      value: '2'
      sysctl_file: /etc/sysctl.d/fs_protected_regular.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_regular

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

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

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

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

  - name: Enable Kernel Parameter to Enforce DAC on Symlinks - Comment out any occurrences
      of fs.protected_symlinks from /etc/sysctl.conf
    ansible.builtin.replace:
      path: '{{ item }}'
      regexp: ^[\s]*fs.protected_symlinks
      replace: '#fs.protected_symlinks'
    with_fileglob:
    - /etc/sysctl.conf
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-002402
    - NIST-800-53-AC-6(1)
    - NIST-800-53-CM-6(a)
    - disable_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - reboot_required
    - sysctl_fs_protected_symlinks

  - name: Enable Kernel Parameter to Enforce DAC on Symlinks - Ensure sysctl fs.protected_symlinks
      is set to 1
    ansible.posix.sysctl:
      name: fs.protected_symlinks
      value: '1'
      sysctl_file: /etc/sysctl.d/fs_protected_symlinks.conf
      state: present
      reload: true
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-002402
    - NIST-800-53-AC-6(1)
    - NIST-800-53-CM-6(a)
    - disable_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - reboot_required
    - sysctl_fs_protected_symlinks

  - name: Set the file_groupowner_etc_group_newgroup variable if represented by gid
    ansible.builtin.set_fact:
      file_groupowner_etc_group_newgroup: '0'
    tags:
    - CJIS-5.5.2.2
    - DISA-STIG-OL09-00-002532
    - NIST-800-53-AC-6(1)
    - NIST-800-53-CM-6(a)
    - PCI-DSS-Req-8.7.c
    - PCI-DSSv4-2.2
    - PCI-DSSv4-2.2.6
    - configure_strategy
    - file_groupowner_etc_group
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

  - name: Test for existence /etc/group
    ansible.builtin.stat:
      path: /etc/group
    register: file_exists
    tags:
    - CJIS-5.5.2.2
    - DISA-STIG-OL09-00-002532
    - NIST-800-53-AC-6(1)
    - NIST-800-53-CM-6(a)
    - PCI-DSS-Req-8.7.c
    - PCI-DSSv4-2.2
    - PCI-DSSv4-2.2.6
    - configure_strategy
    - file_groupowner_etc_group
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

  - name: Ensure group owner on /etc/group
    ansible.builtin.file:
      path: /etc/group
      follow: false
      group: '{{ file_groupowner_etc_group_newgroup }}'
    when: file_exists.stat is defined and file_exists.stat.exists
    tags:
    - CJIS-5.5.2.2
    - DISA-STIG-OL09-00-002532
    - NIST-800-53-AC-6(1)
    - NIST-800-53-CM-6(a)
    - PCI-DSS-Req-8.7.c
    - PCI-DSSv4-2.2
    - PCI-DSSv4-2.2.6
    - configure_strategy
    - file_groupowner_etc_group
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

  - name: Set the file_groupowner_etc_gshadow_newgroup variable if represented by
      gid
    ansible.builtin.set_fact:
      file_groupowner_etc_gshadow_newgroup: '0'
    tags:
    - DISA-STIG-OL09-00-002538
    - NIST-800-53-AC-6(1)
    - NIST-800-53-CM-6(a)
    - configure_strategy
    - file_groupowner_etc_gshadow
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

  - name: Test for existence /etc/gshadow
    ansible.builtin.stat:
      path: /etc/gshadow
    register: file_exists
    tags:
    - DISA-STIG-OL09-00-002538
    - NIST-800-53-AC-6(1)
    - NIST-800-53-CM-6(a)
    - configure_strategy
    - file_groupowner_etc_gshadow
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

  - name: Ensure group owner on /etc/gshadow
    ansible.builtin.file:
      path: /etc/gshadow
      follow: false
      group: '{{ file_groupowner_etc_gshadow_newgroup }}'
    when: file_exists.stat is defined and file_exists.stat.exists
    tags:
    - DISA-STIG-OL09-00-002538
    - NIST-800-53-AC-6(1)
    - NIST-800-53-CM-6(a)
    - configure_strategy
    - file_groupowner_etc_gshadow
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

  - name: Set the file_groupowner_etc_passwd_newgroup variable if represented by gid
    ansible.builtin.set_fact:
      file_groupowner_etc_passwd_newgroup: '0'
    tags:
    - CJIS-5.5.2.2
    - DISA-STIG-OL09-00-002544
    - NIST-800-53-AC-6(1)
    - NIST-800-53-CM-6(a)
    - PCI-DSS-Req-8.7.c
    - PCI-DSSv4-2.2
    - PCI-DSSv4-2.2.6
    - configure_strategy
    - file_groupowner_etc_passwd
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

  - name: Test for existence /etc/passwd
    ansible.builtin.stat:
      path: /etc/passwd
    register: file_exists
    tags:
    - CJIS-5.5.2.2
    - DISA-STIG-OL09-00-002544
    - NIST-800-53-AC-6(1)
    - NIST-800-53-CM-6(a)
    - PCI-DSS-Req-8.7.c
    - PCI-DSSv4-2.2
    - PCI-DSSv4-2.2.6
    - configure_strategy
    - file_groupowner_etc_passwd
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

  - name: Ensure group owner on /etc/passwd
    ansible.builtin.file:
      path: /etc/passwd
      follow: false
      group: '{{ file_groupowner_etc_passwd_newgroup }}'
    when: file_exists.stat is defined and file_exists.stat.exists
    tags:
    - CJIS-5.5.2.2
    - DISA-STIG-OL09-00-002544
    - NIST-800-53-AC-6(1)
    - NIST-800-53-CM-6(a)
    - PCI-DSS-Req-8.7.c
    - PCI-DSSv4-2.2
    - PCI-DSSv4-2.2.6
    - configure_strategy
    - file_groupowner_etc_passwd
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

  - name: Set the file_groupowner_etc_shadow_newgroup variable if represented by gid
    ansible.builtin.set_fact:
      file_groupowner_etc_shadow_newgroup: '0'
    tags:
    - CJIS-5.5.2.2
    - DISA-STIG-OL09-00-002550
    - NIST-800-53-AC-6(1)
    - NIST-800-53-CM-6(a)
    - PCI-DSS-Req-8.7.c
    - PCI-DSSv4-2.2
    - PCI-DSSv4-2.2.6
    - configure_strategy
    - file_groupowner_etc_shadow
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

  - name: Test for existence /etc/shadow
    ansible.builtin.stat:
      path: /etc/shadow
    register: file_exists
    tags:
    - CJIS-5.5.2.2
    - DISA-STIG-OL09-00-002550
    - NIST-800-53-AC-6(1)
    - NIST-800-53-CM-6(a)
    - PCI-DSS-Req-8.7.c
    - PCI-DSSv4-2.2
    - PCI-DSSv4-2.2.6
    - configure_strategy
    - file_groupowner_etc_shadow
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

  - name: Ensure group owner on /etc/shadow
    ansible.builtin.file:
      path: /etc/shadow
      follow: false
      group: '{{ file_groupowner_etc_shadow_newgroup }}'
    when: file_exists.stat is defined and file_exists.stat.exists
    tags:
    - CJIS-5.5.2.2
    - DISA-STIG-OL09-00-002550
    - NIST-800-53-AC-6(1)
    - NIST-800-53-CM-6(a)
    - PCI-DSS-Req-8.7.c
    - PCI-DSSv4-2.2
    - PCI-DSSv4-2.2.6
    - configure_strategy
    - file_groupowner_etc_shadow
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

  - name: Set the file_groupowner_etc_shells_newgroup variable if represented by gid
    ansible.builtin.set_fact:
      file_groupowner_etc_shells_newgroup: '0'
    tags:
    - NIST-800-53-AC-3
    - NIST-800-53-MP-2
    - configure_strategy
    - file_groupowner_etc_shells
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

  - name: Test for existence /etc/shells
    ansible.builtin.stat:
      path: /etc/shells
    register: file_exists
    tags:
    - NIST-800-53-AC-3
    - NIST-800-53-MP-2
    - configure_strategy
    - file_groupowner_etc_shells
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

  - name: Ensure group owner on /etc/shells
    ansible.builtin.file:
      path: /etc/shells
      follow: false
      group: '{{ file_groupowner_etc_shells_newgroup }}'
    when: file_exists.stat is defined and file_exists.stat.exists
    tags:
    - NIST-800-53-AC-3
    - NIST-800-53-MP-2
    - configure_strategy
    - file_groupowner_etc_shells
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

  - name: Set the file_owner_etc_group_newown variable if represented by uid
    ansible.builtin.set_fact:
      file_owner_etc_group_newown: '0'
    tags:
    - CJIS-5.5.2.2
    - DISA-STIG-OL09-00-002534
    - NIST-800-53-AC-6(1)
    - NIST-800-53-CM-6(a)
    - PCI-DSS-Req-8.7.c
    - PCI-DSSv4-2.2
    - PCI-DSSv4-2.2.6
    - configure_strategy
    - file_owner_etc_group
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

  - name: Test for existence /etc/group
    ansible.builtin.stat:
      path: /etc/group
    register: file_exists
    tags:
    - CJIS-5.5.2.2
    - DISA-STIG-OL09-00-002534
    - NIST-800-53-AC-6(1)
    - NIST-800-53-CM-6(a)
    - PCI-DSS-Req-8.7.c
    - PCI-DSSv4-2.2
    - PCI-DSSv4-2.2.6
    - configure_strategy
    - file_owner_etc_group
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

  - name: Ensure owner on /etc/group
    ansible.builtin.file:
      path: /etc/group
      follow: false
      owner: '{{ file_owner_etc_group_newown }}'
    when: file_exists.stat is defined and file_exists.stat.exists
    tags:
    - CJIS-5.5.2.2
    - DISA-STIG-OL09-00-002534
    - NIST-800-53-AC-6(1)
    - NIST-800-53-CM-6(a)
    - PCI-DSS-Req-8.7.c
    - PCI-DSSv4-2.2
    - PCI-DSSv4-2.2.6
    - configure_strategy
    - file_owner_etc_group
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

  - name: Set the file_owner_etc_gshadow_newown variable if represented by uid
    ansible.builtin.set_fact:
      file_owner_etc_gshadow_newown: '0'
    tags:
    - DISA-STIG-OL09-00-002540
    - NIST-800-53-AC-6(1)
    - NIST-800-53-CM-6(a)
    - configure_strategy
    - file_owner_etc_gshadow
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

  - name: Test for existence /etc/gshadow
    ansible.builtin.stat:
      path: /etc/gshadow
    register: file_exists
    tags:
    - DISA-STIG-OL09-00-002540
    - NIST-800-53-AC-6(1)
    - NIST-800-53-CM-6(a)
    - configure_strategy
    - file_owner_etc_gshadow
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

  - name: Ensure owner on /etc/gshadow
    ansible.builtin.file:
      path: /etc/gshadow
      follow: false
      owner: '{{ file_owner_etc_gshadow_newown }}'
    when: file_exists.stat is defined and file_exists.stat.exists
    tags:
    - DISA-STIG-OL09-00-002540
    - NIST-800-53-AC-6(1)
    - NIST-800-53-CM-6(a)
    - configure_strategy
    - file_owner_etc_gshadow
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

  - name: Set the file_owner_etc_passwd_newown variable if represented by uid
    ansible.builtin.set_fact:
      file_owner_etc_passwd_newown: '0'
    tags:
    - CJIS-5.5.2.2
    - DISA-STIG-OL09-00-002546
    - NIST-800-53-AC-6(1)
    - NIST-800-53-CM-6(a)
    - PCI-DSS-Req-8.7.c
    - PCI-DSSv4-2.2
    - PCI-DSSv4-2.2.6
    - configure_strategy
    - file_owner_etc_passwd
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

  - name: Test for existence /etc/passwd
    ansible.builtin.stat:
      path: /etc/passwd
    register: file_exists
    tags:
    - CJIS-5.5.2.2
    - DISA-STIG-OL09-00-002546
    - NIST-800-53-AC-6(1)
    - NIST-800-53-CM-6(a)
    - PCI-DSS-Req-8.7.c
    - PCI-DSSv4-2.2
    - PCI-DSSv4-2.2.6
    - configure_strategy
    - file_owner_etc_passwd
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

  - name: Ensure owner on /etc/passwd
    ansible.builtin.file:
      path: /etc/passwd
      follow: false
      owner: '{{ file_owner_etc_passwd_newown }}'
    when: file_exists.stat is defined and file_exists.stat.exists
    tags:
    - CJIS-5.5.2.2
    - DISA-STIG-OL09-00-002546
    - NIST-800-53-AC-6(1)
    - NIST-800-53-CM-6(a)
    - PCI-DSS-Req-8.7.c
    - PCI-DSSv4-2.2
    - PCI-DSSv4-2.2.6
    - configure_strategy
    - file_owner_etc_passwd
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

  - name: Set the file_owner_etc_shadow_newown variable if represented by uid
    ansible.builtin.set_fact:
      file_owner_etc_shadow_newown: '0'
    tags:
    - CJIS-5.5.2.2
    - DISA-STIG-OL09-00-002552
    - NIST-800-53-AC-6(1)
    - NIST-800-53-CM-6(a)
    - PCI-DSS-Req-8.7.c
    - PCI-DSSv4-2.2
    - PCI-DSSv4-2.2.6
    - configure_strategy
    - file_owner_etc_shadow
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

  - name: Test for existence /etc/shadow
    ansible.builtin.stat:
      path: /etc/shadow
    register: file_exists
    tags:
    - CJIS-5.5.2.2
    - DISA-STIG-OL09-00-002552
    - NIST-800-53-AC-6(1)
    - NIST-800-53-CM-6(a)
    - PCI-DSS-Req-8.7.c
    - PCI-DSSv4-2.2
    - PCI-DSSv4-2.2.6
    - configure_strategy
    - file_owner_etc_shadow
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

  - name: Ensure owner on /etc/shadow
    ansible.builtin.file:
      path: /etc/shadow
      follow: false
      owner: '{{ file_owner_etc_shadow_newown }}'
    when: file_exists.stat is defined and file_exists.stat.exists
    tags:
    - CJIS-5.5.2.2
    - DISA-STIG-OL09-00-002552
    - NIST-800-53-AC-6(1)
    - NIST-800-53-CM-6(a)
    - PCI-DSS-Req-8.7.c
    - PCI-DSSv4-2.2
    - PCI-DSSv4-2.2.6
    - configure_strategy
    - file_owner_etc_shadow
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

  - name: Set the file_owner_etc_shells_newown variable if represented by uid
    ansible.builtin.set_fact:
      file_owner_etc_shells_newown: '0'
    tags:
    - NIST-800-53-AC-3
    - NIST-800-53-MP-2
    - configure_strategy
    - file_owner_etc_shells
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

  - name: Test for existence /etc/shells
    ansible.builtin.stat:
      path: /etc/shells
    register: file_exists
    tags:
    - NIST-800-53-AC-3
    - NIST-800-53-MP-2
    - configure_strategy
    - file_owner_etc_shells
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

  - name: Ensure owner on /etc/shells
    ansible.builtin.file:
      path: /etc/shells
      follow: false
      owner: '{{ file_owner_etc_shells_newown }}'
    when: file_exists.stat is defined and file_exists.stat.exists
    tags:
    - NIST-800-53-AC-3
    - NIST-800-53-MP-2
    - configure_strategy
    - file_owner_etc_shells
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

  - name: Test for existence /etc/group
    ansible.builtin.stat:
      path: /etc/group
    register: file_exists
    tags:
    - CJIS-5.5.2.2
    - DISA-STIG-OL09-00-002536
    - NIST-800-53-AC-6(1)
    - NIST-800-53-CM-6(a)
    - PCI-DSS-Req-8.7.c
    - PCI-DSSv4-2.2
    - PCI-DSSv4-2.2.6
    - configure_strategy
    - file_permissions_etc_group
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

  - name: Ensure permission u-xs,g-xws,o-xwt on /etc/group
    ansible.builtin.file:
      path: /etc/group
      mode: u-xs,g-xws,o-xwt
    when: file_exists.stat is defined and file_exists.stat.exists
    tags:
    - CJIS-5.5.2.2
    - DISA-STIG-OL09-00-002536
    - NIST-800-53-AC-6(1)
    - NIST-800-53-CM-6(a)
    - PCI-DSS-Req-8.7.c
    - PCI-DSSv4-2.2
    - PCI-DSSv4-2.2.6
    - configure_strategy
    - file_permissions_etc_group
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

  - name: Test for existence /etc/gshadow
    ansible.builtin.stat:
      path: /etc/gshadow
    register: file_exists
    tags:
    - DISA-STIG-OL09-00-002542
    - NIST-800-53-AC-6(1)
    - NIST-800-53-CM-6(a)
    - configure_strategy
    - file_permissions_etc_gshadow
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

  - name: Ensure permission u-xwrs,g-xwrs,o-xwrt on /etc/gshadow
    ansible.builtin.file:
      path: /etc/gshadow
      mode: u-xwrs,g-xwrs,o-xwrt
    when: file_exists.stat is defined and file_exists.stat.exists
    tags:
    - DISA-STIG-OL09-00-002542
    - NIST-800-53-AC-6(1)
    - NIST-800-53-CM-6(a)
    - configure_strategy
    - file_permissions_etc_gshadow
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

  - name: Test for existence /etc/passwd
    ansible.builtin.stat:
      path: /etc/passwd
    register: file_exists
    tags:
    - CJIS-5.5.2.2
    - DISA-STIG-OL09-00-002548
    - NIST-800-53-AC-6(1)
    - NIST-800-53-CM-6(a)
    - PCI-DSS-Req-8.7.c
    - PCI-DSSv4-2.2
    - PCI-DSSv4-2.2.6
    - configure_strategy
    - file_permissions_etc_passwd
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

  - name: Ensure permission u-xs,g-xws,o-xwt on /etc/passwd
    ansible.builtin.file:
      path: /etc/passwd
      mode: u-xs,g-xws,o-xwt
    when: file_exists.stat is defined and file_exists.stat.exists
    tags:
    - CJIS-5.5.2.2
    - DISA-STIG-OL09-00-002548
    - NIST-800-53-AC-6(1)
    - NIST-800-53-CM-6(a)
    - PCI-DSS-Req-8.7.c
    - PCI-DSSv4-2.2
    - PCI-DSSv4-2.2.6
    - configure_strategy
    - file_permissions_etc_passwd
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

  - name: Test for existence /etc/shadow
    ansible.builtin.stat:
      path: /etc/shadow
    register: file_exists
    tags:
    - CJIS-5.5.2.2
    - DISA-STIG-OL09-00-002555
    - NIST-800-53-AC-6(1)
    - NIST-800-53-CM-6(a)
    - PCI-DSS-Req-8.7.c
    - PCI-DSSv4-2.2
    - PCI-DSSv4-2.2.6
    - configure_strategy
    - file_permissions_etc_shadow
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

  - name: Ensure permission u-xwrs,g-xwrs,o-xwrt on /etc/shadow
    ansible.builtin.file:
      path: /etc/shadow
      mode: u-xwrs,g-xwrs,o-xwrt
    when: file_exists.stat is defined and file_exists.stat.exists
    tags:
    - CJIS-5.5.2.2
    - DISA-STIG-OL09-00-002555
    - NIST-800-53-AC-6(1)
    - NIST-800-53-CM-6(a)
    - PCI-DSS-Req-8.7.c
    - PCI-DSSv4-2.2
    - PCI-DSSv4-2.2.6
    - configure_strategy
    - file_permissions_etc_shadow
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

  - name: Test for existence /etc/shells
    ansible.builtin.stat:
      path: /etc/shells
    register: file_exists
    tags:
    - NIST-800-53-AC-3
    - NIST-800-53-MP-2
    - configure_strategy
    - file_permissions_etc_shells
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

  - name: Ensure permission u-xs,g-xws,o-xwt on /etc/shells
    ansible.builtin.file:
      path: /etc/shells
      mode: u-xs,g-xws,o-xwt
    when: file_exists.stat is defined and file_exists.stat.exists
    tags:
    - NIST-800-53-AC-3
    - NIST-800-53-MP-2
    - configure_strategy
    - file_permissions_etc_shells
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

  - name: Check that the root group is defined
    ansible.builtin.getent:
      database: group
      key: root
    ignore_errors: true
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - directory_groupowner_etc_sysctld_newgroup is undefined
    tags:
    - configure_strategy
    - directory_groupowner_etc_sysctld
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

  - name: Set the directory_groupowner_etc_sysctld_newgroup variable if root found
    ansible.builtin.set_fact:
      directory_groupowner_etc_sysctld_newgroup: root
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - ansible_facts.getent_group["root"] is defined
    tags:
    - configure_strategy
    - directory_groupowner_etc_sysctld
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

  - name: Ensure group owner on /etc/sysctl.d/
    ansible.builtin.file:
      path: /etc/sysctl.d/
      follow: false
      state: directory
      group: '{{ directory_groupowner_etc_sysctld_newgroup }}'
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - configure_strategy
    - directory_groupowner_etc_sysctld
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

  - name: Set the directory_owner_etc_sysctld_newown variable if represented by uid
    ansible.builtin.set_fact:
      directory_owner_etc_sysctld_newown: '0'
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - configure_strategy
    - directory_owner_etc_sysctld
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

  - name: Ensure owner on directory /etc/sysctl.d/
    ansible.builtin.file:
      path: /etc/sysctl.d/
      follow: false
      state: directory
      owner: '{{ directory_owner_etc_sysctld_newown }}'
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - configure_strategy
    - directory_owner_etc_sysctld
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

  - name: Find /etc/sysctl.d/ file(s)
    ansible.builtin.command: 'find -P /etc/sysctl.d/ -maxdepth 0 -perm /u+s,g+ws,o+wt  -type
      d '
    register: files_found
    changed_when: false
    failed_when: false
    check_mode: false
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - configure_strategy
    - directory_permissions_etc_sysctld
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

  - name: Set permissions for /etc/sysctl.d/ file(s)
    ansible.builtin.file:
      path: '{{ item }}'
      mode: u-s,g-ws,o-wt
      state: directory
    with_items:
    - '{{ files_found.stdout_lines }}'
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - configure_strategy
    - directory_permissions_etc_sysctld
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

  - name: Verify that system commands files are group owned by root or a system account
      - Find system command files with incorrect group ownership
    ansible.builtin.find:
      paths: '{{ item }}'
      file_type: file
      follow: false
      recurse: false
    register: system_command_files_found
    with_items:
    - /bin
    - /sbin
    - /usr/bin
    - /usr/sbin
    - /usr/libexec
    - /usr/local/bin
    - /usr/local/sbin
    changed_when: false
    tags:
    - DISA-STIG-OL09-00-002504
    - NIST-800-53-CM-5(6)
    - NIST-800-53-CM-5(6).1
    - file_groupownership_system_commands_dirs
    - medium_complexity
    - medium_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Verify that system commands files are group owned by root or a system account
      - Set group ownership to root for system command files
    ansible.builtin.file:
      path: '{{ item.path }}'
      group: root
    with_items: '{{ system_command_files_found.results | map(attribute=''files'')
      | flatten | rejectattr(''gr_name'', ''equalto'', ''root'') | list }}'
    tags:
    - DISA-STIG-OL09-00-002504
    - NIST-800-53-CM-5(6)
    - NIST-800-53-CM-5(6).1
    - file_groupownership_system_commands_dirs
    - medium_complexity
    - medium_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Read list of system executables without root ownership
    ansible.builtin.command: find /bin/ /usr/bin/ /usr/local/bin/ /sbin/ /usr/sbin/
      /usr/local/sbin/ /usr/libexec \! -user root
    register: no_root_system_executables
    changed_when: false
    failed_when: false
    check_mode: false
    tags:
    - DISA-STIG-OL09-00-002505
    - NIST-800-53-AC-6(1)
    - NIST-800-53-CM-5(6)
    - NIST-800-53-CM-5(6).1
    - NIST-800-53-CM-6(a)
    - file_ownership_binary_dirs
    - medium_complexity
    - medium_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Set ownership to root of system executables
    ansible.builtin.file:
      path: '{{ item }}'
      owner: root
    with_items: '{{ no_root_system_executables.stdout_lines }}'
    when: no_root_system_executables.stdout_lines | length > 0
    tags:
    - DISA-STIG-OL09-00-002505
    - NIST-800-53-AC-6(1)
    - NIST-800-53-CM-5(6)
    - NIST-800-53-CM-5(6).1
    - NIST-800-53-CM-6(a)
    - file_ownership_binary_dirs
    - medium_complexity
    - medium_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Read list of world and group writable system executables
    ansible.builtin.command: find -L /bin /usr/bin /usr/local/bin /sbin /usr/sbin
      /usr/local/sbin /usr/libexec -perm /022 \( -type l -o -type f \)
    register: world_writable_library_files
    changed_when: false
    failed_when: false
    check_mode: false
    tags:
    - DISA-STIG-OL09-00-002506
    - NIST-800-53-AC-6(1)
    - NIST-800-53-CM-5(6)
    - NIST-800-53-CM-5(6).1
    - NIST-800-53-CM-6(a)
    - file_permissions_binary_dirs
    - medium_complexity
    - medium_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

  - name: Remove world/group writability of system executables
    ansible.builtin.file:
      path: '{{ item }}'
      mode: go-w
      state: file
    with_items: '{{ world_writable_library_files.stdout_lines }}'
    when: world_writable_library_files.stdout_lines | length > 0
    tags:
    - DISA-STIG-OL09-00-002506
    - NIST-800-53-AC-6(1)
    - NIST-800-53-CM-5(6)
    - NIST-800-53-CM-5(6).1
    - NIST-800-53-CM-6(a)
    - file_permissions_binary_dirs
    - medium_complexity
    - medium_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

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

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

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

  - name: 'Add noexec Option to /boot: Make sure noexec option is part of the to /boot
      options'
    set_fact:
      mount_info: '{{ mount_info | combine( {''options'':''''~(mount_info.options
        | default(''''))~('','' if (mount_info.options | default('''')) else '''')~''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:
    - configure_strategy
    - high_disruption
    - low_complexity
    - medium_severity
    - mount_option_boot_noexec
    - no_reboot_needed

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

  - name: 'Add nodev Option to Non-Root Local Partitions: Refresh facts'
    ansible.builtin.setup:
      gather_subset: mounts
    when: ( not ( "kernel" in ansible_facts.packages and "rpm-ostree" in ansible_facts.packages
      and "bootc" in ansible_facts.packages and not "openshift-kubelet" in ansible_facts.packages
      and "ostree" in ansible_proc_cmdline ) and not ( ansible_virtualization_type
      in ["docker", "lxc", "openvz", "podman", "container"] ) )
    tags:
    - DISA-STIG-OL09-00-002080
    - NIST-800-53-AC-6
    - NIST-800-53-AC-6(1)
    - NIST-800-53-CM-6(a)
    - NIST-800-53-CM-7(a)
    - NIST-800-53-CM-7(b)
    - NIST-800-53-MP-7
    - configure_strategy
    - high_disruption
    - low_complexity
    - medium_severity
    - mount_option_nodev_nonroot_local_partitions
    - no_reboot_needed

  - name: 'Add nodev Option to Non-Root Local Partitions: Define excluded (non-local)
      file systems'
    ansible.builtin.set_fact:
      excluded_fstypes:
      - afs
      - autofs
      - ceph
      - cifs
      - smb3
      - smbfs
      - sshfs
      - ncpfs
      - ncp
      - nfs
      - nfs4
      - gfs
      - gfs2
      - glusterfs
      - gpfs
      - pvfs2
      - ocfs2
      - lustre
      - davfs
      - fuse.sshfs
      - vfat
    when: ( not ( "kernel" in ansible_facts.packages and "rpm-ostree" in ansible_facts.packages
      and "bootc" in ansible_facts.packages and not "openshift-kubelet" in ansible_facts.packages
      and "ostree" in ansible_proc_cmdline ) and not ( ansible_virtualization_type
      in ["docker", "lxc", "openvz", "podman", "container"] ) )
    tags:
    - DISA-STIG-OL09-00-002080
    - NIST-800-53-AC-6
    - NIST-800-53-AC-6(1)
    - NIST-800-53-CM-6(a)
    - NIST-800-53-CM-7(a)
    - NIST-800-53-CM-7(b)
    - NIST-800-53-MP-7
    - configure_strategy
    - high_disruption
    - low_complexity
    - medium_severity
    - mount_option_nodev_nonroot_local_partitions
    - no_reboot_needed

  - name: 'Add nodev Option to Non-Root Local Partitions: Ensure non-root local partitions
      are mounted with nodev option'
    ansible.posix.mount:
      path: '{{ item.mount }}'
      src: '{{ item.device }}'
      opts: '{{ item.options }},nodev'
      state: mounted
      fstype: '{{ item.fstype }}'
    when:
    - ( not ( "kernel" in ansible_facts.packages and "rpm-ostree" in ansible_facts.packages
      and "bootc" in ansible_facts.packages and not "openshift-kubelet" in ansible_facts.packages
      and "ostree" in ansible_proc_cmdline ) and not ( ansible_virtualization_type
      in ["docker", "lxc", "openvz", "podman", "container"] ) )
    - item.mount is match('/\w')
    - item.mount is not match('/(boot|efi)')
    - item.options is not search('nodev')
    - item.fstype not in excluded_fstypes
    - (not accounts_polyinstantiated_var_tmp | default(false)) or item.mount != '/var/tmp/tmp-inst'
    - (not accounts_polyinstantiated_tmp | default(false)) or item.mount != '/tmp/tmp-inst'
    with_items:
    - '{{ ansible_facts.mounts }}'
    tags:
    - DISA-STIG-OL09-00-002080
    - NIST-800-53-AC-6
    - NIST-800-53-AC-6(1)
    - NIST-800-53-CM-6(a)
    - NIST-800-53-CM-7(a)
    - NIST-800-53-CM-7(b)
    - NIST-800-53-MP-7
    - configure_strategy
    - high_disruption
    - low_complexity
    - medium_severity
    - mount_option_nodev_nonroot_local_partitions
    - no_reboot_needed

  - name: 'Add nodev Option to Non-Root Local Partitions: Ensure non-root local partitions
      are present with nodev option in /etc/fstab'
    ansible.builtin.replace:
      path: /etc/fstab
      regexp: ^\s*(?!#)(/dev/\S+|UUID=\S+)\s+(/(?!boot|efi)\w\S*)\s+(?!vfat\s)(\S+)\s+(?!.*\bnodev\b)(\S+)(.*)$
      replace: \1 \2 \3 \4,nodev \5
    when: ( not ( "kernel" in ansible_facts.packages and "rpm-ostree" in ansible_facts.packages
      and "bootc" in ansible_facts.packages and not "openshift-kubelet" in ansible_facts.packages
      and "ostree" in ansible_proc_cmdline ) and not ( ansible_virtualization_type
      in ["docker", "lxc", "openvz", "podman", "container"] ) )
    tags:
    - DISA-STIG-OL09-00-002080
    - NIST-800-53-AC-6
    - NIST-800-53-AC-6(1)
    - NIST-800-53-CM-6(a)
    - NIST-800-53-CM-7(a)
    - NIST-800-53-CM-7(b)
    - NIST-800-53-MP-7
    - configure_strategy
    - high_disruption
    - low_complexity
    - medium_severity
    - mount_option_nodev_nonroot_local_partitions
    - no_reboot_needed

  - name: 'Add nosuid Option to /opt: Check information associated to mountpoint'
    ansible.builtin.command: findmnt --fstab '/opt'
    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"] ) )
    - '"/opt" in ansible_mounts | map(attribute="mount") | list'
    tags:
    - configure_strategy
    - high_disruption
    - low_complexity
    - medium_severity
    - mount_option_opt_nosuid
    - no_reboot_needed

  - name: 'Add nosuid Option to /opt: 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"] ) )
    - '"/opt" 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_opt_nosuid
    - no_reboot_needed

  - name: 'Add nosuid Option to /opt: If /opt not mounted, craft mount_info manually'
    set_fact:
      mount_info: '{{ mount_info|default({})|combine({item.0: item.1}) }}'
    with_together:
    - - target
      - source
      - fstype
      - options
    - - /opt
      - ''
      - ''
      - 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"] ) )
    - '"/opt" 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_opt_nosuid
    - no_reboot_needed

  - name: 'Add nosuid Option to /opt: Make sure nosuid option is part of the to /opt
      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"] ) )
    - '"/opt" 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_opt_nosuid
    - no_reboot_needed

  - name: 'Add nosuid Option to /opt: Ensure /opt is mounted with nosuid option'
    ansible.posix.mount:
      path: /opt
      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"] ) )
    - '"/opt" 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_opt_nosuid
    - no_reboot_needed

  - name: 'Add nosuid Option to /srv: Check information associated to mountpoint'
    ansible.builtin.command: findmnt --fstab '/srv'
    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"] ) )
    - '"/srv" in ansible_mounts | map(attribute="mount") | list'
    tags:
    - configure_strategy
    - high_disruption
    - low_complexity
    - medium_severity
    - mount_option_srv_nosuid
    - no_reboot_needed

  - name: 'Add nosuid Option to /srv: 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"] ) )
    - '"/srv" 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_srv_nosuid
    - no_reboot_needed

  - name: 'Add nosuid Option to /srv: If /srv not mounted, craft mount_info manually'
    set_fact:
      mount_info: '{{ mount_info|default({})|combine({item.0: item.1}) }}'
    with_together:
    - - target
      - source
      - fstype
      - options
    - - /srv
      - ''
      - ''
      - 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"] ) )
    - '"/srv" 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_srv_nosuid
    - no_reboot_needed

  - name: 'Add nosuid Option to /srv: Make sure nosuid option is part of the to /srv
      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"] ) )
    - '"/srv" 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_srv_nosuid
    - no_reboot_needed

  - name: 'Add nosuid Option to /srv: Ensure /srv is mounted with nosuid option'
    ansible.posix.mount:
      path: /srv
      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"] ) )
    - '"/srv" 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_srv_nosuid
    - no_reboot_needed

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

  - name: 'Add noexec Option to /var: Make sure noexec option is part of the to /var
      options'
    set_fact:
      mount_info: '{{ mount_info | combine( {''options'':''''~(mount_info.options
        | default(''''))~('','' if (mount_info.options | default('''')) else '''')~''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" 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_noexec
    - no_reboot_needed

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

  - name: 'Add nosuid Option to /var: Check information associated to mountpoint'
    ansible.builtin.command: findmnt --fstab '/var'
    register: device_name
    failed_when: device_name.rc > 1
    changed_when: false
    check_mode: false
    when:
    - ( not ( "kernel" in ansible_facts.packages and "rpm-ostree" in ansible_facts.packages
      and "bootc" in ansible_facts.packages and not "openshift-kubelet" in ansible_facts.packages
      and "ostree" in ansible_proc_cmdline ) and not ( ansible_virtualization_type
      in ["docker", "lxc", "openvz", "podman", "container"] ) )
    - '"/var" in ansible_mounts | map(attribute="mount") | list'
    tags:
    - configure_strategy
    - high_disruption
    - low_complexity
    - medium_severity
    - mount_option_var_nosuid
    - no_reboot_needed

  - name: 'Add nosuid Option to /var: Create mount_info dictionary variable'
    set_fact:
      mount_info: '{{ mount_info|default({})|combine({item.0: item.1}) }}'
    with_together:
    - '{{ device_name.stdout_lines[0].split() | map(''lower'') | list }}'
    - '{{ device_name.stdout_lines[1].split() | list }}'
    when:
    - ( not ( "kernel" in ansible_facts.packages and "rpm-ostree" in ansible_facts.packages
      and "bootc" in ansible_facts.packages and not "openshift-kubelet" in ansible_facts.packages
      and "ostree" in ansible_proc_cmdline ) and not ( ansible_virtualization_type
      in ["docker", "lxc", "openvz", "podman", "container"] ) )
    - '"/var" in ansible_mounts | map(attribute="mount") | list'
    - device_name.stdout is defined and device_name.stdout_lines is defined
    - (device_name.stdout | length > 0)
    tags:
    - configure_strategy
    - high_disruption
    - low_complexity
    - medium_severity
    - mount_option_var_nosuid
    - no_reboot_needed

  - name: 'Add nosuid Option to /var: If /var not mounted, craft mount_info manually'
    set_fact:
      mount_info: '{{ mount_info|default({})|combine({item.0: item.1}) }}'
    with_together:
    - - target
      - source
      - fstype
      - options
    - - /var
      - ''
      - ''
      - defaults
    when:
    - ( not ( "kernel" in ansible_facts.packages and "rpm-ostree" in ansible_facts.packages
      and "bootc" in ansible_facts.packages and not "openshift-kubelet" in ansible_facts.packages
      and "ostree" in ansible_proc_cmdline ) and not ( ansible_virtualization_type
      in ["docker", "lxc", "openvz", "podman", "container"] ) )
    - '"/var" in ansible_mounts | map(attribute="mount") | list'
    - ("--fstab" | length == 0)
    - device_name.stdout is defined and device_name.stdout_lines is defined
    - (device_name.stdout | length == 0)
    tags:
    - configure_strategy
    - high_disruption
    - low_complexity
    - medium_severity
    - mount_option_var_nosuid
    - no_reboot_needed

  - name: 'Add nosuid Option to /var: Make sure nosuid option is part of the to /var
      options'
    set_fact:
      mount_info: '{{ mount_info | combine( {''options'':''''~(mount_info.options
        | default(''''))~('','' if (mount_info.options | default('''')) else '''')~''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" 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_nosuid
    - no_reboot_needed

  - name: 'Add nosuid Option to /var: Ensure /var is mounted with nosuid option'
    ansible.posix.mount:
      path: /var
      src: '{{ mount_info.source | default('''') }}'
      opts: '{{ mount_info.options | default('''') }}'
      state: mounted
      fstype: '{{ mount_info.fstype | default('''') }}'
    register: mount_result
    failed_when:
    - mount_result is failed
    - '''target is busy'' not in (mount_result.msg | default(''''))'
    - '''already mounted'' not in (mount_result.msg | default(''''))'
    when:
    - ( not ( "kernel" in ansible_facts.packages and "rpm-ostree" in ansible_facts.packages
      and "bootc" in ansible_facts.packages and not "openshift-kubelet" in ansible_facts.packages
      and "ostree" in ansible_proc_cmdline ) and not ( ansible_virtualization_type
      in ["docker", "lxc", "openvz", "podman", "container"] ) )
    - '"/var" in ansible_mounts | map(attribute="mount") | list'
    - mount_info is defined
    - (device_name.stdout is defined and (device_name.stdout | length > 0)) or ("--fstab"
      | length == 0)
    tags:
    - configure_strategy
    - high_disruption
    - low_complexity
    - medium_severity
    - mount_option_var_nosuid
    - no_reboot_needed

  - name: 'Add noexec Option to /var/tmp: Check information associated to mountpoint'
    ansible.builtin.command: findmnt --fstab '/var/tmp'
    register: device_name
    failed_when: device_name.rc > 1
    changed_when: false
    check_mode: false
    when:
    - ( not ( "kernel" in ansible_facts.packages and "rpm-ostree" in ansible_facts.packages
      and "bootc" in ansible_facts.packages and not "openshift-kubelet" in ansible_facts.packages
      and "ostree" in ansible_proc_cmdline ) and not ( ansible_virtualization_type
      in ["docker", "lxc", "openvz", "podman", "container"] ) )
    - '"/var/tmp" in ansible_mounts | map(attribute="mount") | list'
    tags:
    - DISA-STIG-OL09-00-002068
    - configure_strategy
    - high_disruption
    - low_complexity
    - medium_severity
    - mount_option_var_tmp_noexec
    - no_reboot_needed

  - name: 'Add noexec Option to /var/tmp: Create mount_info dictionary variable'
    set_fact:
      mount_info: '{{ mount_info|default({})|combine({item.0: item.1}) }}'
    with_together:
    - '{{ device_name.stdout_lines[0].split() | map(''lower'') | list }}'
    - '{{ device_name.stdout_lines[1].split() | list }}'
    when:
    - ( not ( "kernel" in ansible_facts.packages and "rpm-ostree" in ansible_facts.packages
      and "bootc" in ansible_facts.packages and not "openshift-kubelet" in ansible_facts.packages
      and "ostree" in ansible_proc_cmdline ) and not ( ansible_virtualization_type
      in ["docker", "lxc", "openvz", "podman", "container"] ) )
    - '"/var/tmp" in ansible_mounts | map(attribute="mount") | list'
    - device_name.stdout is defined and device_name.stdout_lines is defined
    - (device_name.stdout | length > 0)
    tags:
    - DISA-STIG-OL09-00-002068
    - configure_strategy
    - high_disruption
    - low_complexity
    - medium_severity
    - mount_option_var_tmp_noexec
    - no_reboot_needed

  - name: 'Add noexec Option to /var/tmp: If /var/tmp not mounted, craft mount_info
      manually'
    set_fact:
      mount_info: '{{ mount_info|default({})|combine({item.0: item.1}) }}'
    with_together:
    - - target
      - source
      - fstype
      - options
    - - /var/tmp
      - ''
      - ''
      - defaults
    when:
    - ( not ( "kernel" in ansible_facts.packages and "rpm-ostree" in ansible_facts.packages
      and "bootc" in ansible_facts.packages and not "openshift-kubelet" in ansible_facts.packages
      and "ostree" in ansible_proc_cmdline ) and not ( ansible_virtualization_type
      in ["docker", "lxc", "openvz", "podman", "container"] ) )
    - '"/var/tmp" in ansible_mounts | map(attribute="mount") | list'
    - ("--fstab" | length == 0)
    - device_name.stdout is defined and device_name.stdout_lines is defined
    - (device_name.stdout | length == 0)
    tags:
    - DISA-STIG-OL09-00-002068
    - configure_strategy
    - high_disruption
    - low_complexity
    - medium_severity
    - mount_option_var_tmp_noexec
    - no_reboot_needed

  - name: 'Add noexec Option to /var/tmp: Make sure noexec option is part of the to
      /var/tmp options'
    set_fact:
      mount_info: '{{ mount_info | combine( {''options'':''''~(mount_info.options
        | default(''''))~('','' if (mount_info.options | default('''')) else '''')~''noexec''
        }) }}'
    when:
    - ( not ( "kernel" in ansible_facts.packages and "rpm-ostree" in ansible_facts.packages
      and "bootc" in ansible_facts.packages and not "openshift-kubelet" in ansible_facts.packages
      and "ostree" in ansible_proc_cmdline ) and not ( ansible_virtualization_type
      in ["docker", "lxc", "openvz", "podman", "container"] ) )
    - '"/var/tmp" in ansible_mounts | map(attribute="mount") | list'
    - mount_info is defined and "noexec" not in (mount_info.options | default(''))
    tags:
    - DISA-STIG-OL09-00-002068
    - configure_strategy
    - high_disruption
    - low_complexity
    - medium_severity
    - mount_option_var_tmp_noexec
    - no_reboot_needed

  - name: 'Add noexec Option to /var/tmp: Ensure /var/tmp is mounted with noexec option'
    ansible.posix.mount:
      path: /var/tmp
      src: '{{ mount_info.source | default('''') }}'
      opts: '{{ mount_info.options | default('''') }}'
      state: mounted
      fstype: '{{ mount_info.fstype | default('''') }}'
    register: mount_result
    failed_when:
    - mount_result is failed
    - '''target is busy'' not in (mount_result.msg | default(''''))'
    - '''already mounted'' not in (mount_result.msg | default(''''))'
    when:
    - ( not ( "kernel" in ansible_facts.packages and "rpm-ostree" in ansible_facts.packages
      and "bootc" in ansible_facts.packages and not "openshift-kubelet" in ansible_facts.packages
      and "ostree" in ansible_proc_cmdline ) and not ( ansible_virtualization_type
      in ["docker", "lxc", "openvz", "podman", "container"] ) )
    - '"/var/tmp" in ansible_mounts | map(attribute="mount") | list'
    - mount_info is defined
    - (device_name.stdout is defined and (device_name.stdout | length > 0)) or ("--fstab"
      | length == 0)
    tags:
    - DISA-STIG-OL09-00-002068
    - configure_strategy
    - high_disruption
    - low_complexity
    - medium_severity
    - mount_option_var_tmp_noexec
    - no_reboot_needed

  - name: 'Add nosuid Option to /var/tmp: Check information associated to mountpoint'
    ansible.builtin.command: findmnt --fstab '/var/tmp'
    register: device_name
    failed_when: device_name.rc > 1
    changed_when: false
    check_mode: false
    when:
    - ( not ( "kernel" in ansible_facts.packages and "rpm-ostree" in ansible_facts.packages
      and "bootc" in ansible_facts.packages and not "openshift-kubelet" in ansible_facts.packages
      and "ostree" in ansible_proc_cmdline ) and not ( ansible_virtualization_type
      in ["docker", "lxc", "openvz", "podman", "container"] ) )
    - '"/var/tmp" in ansible_mounts | map(attribute="mount") | list'
    tags:
    - DISA-STIG-OL09-00-002069
    - configure_strategy
    - high_disruption
    - low_complexity
    - medium_severity
    - mount_option_var_tmp_nosuid
    - no_reboot_needed

  - name: 'Add nosuid Option to /var/tmp: Create mount_info dictionary variable'
    set_fact:
      mount_info: '{{ mount_info|default({})|combine({item.0: item.1}) }}'
    with_together:
    - '{{ device_name.stdout_lines[0].split() | map(''lower'') | list }}'
    - '{{ device_name.stdout_lines[1].split() | list }}'
    when:
    - ( not ( "kernel" in ansible_facts.packages and "rpm-ostree" in ansible_facts.packages
      and "bootc" in ansible_facts.packages and not "openshift-kubelet" in ansible_facts.packages
      and "ostree" in ansible_proc_cmdline ) and not ( ansible_virtualization_type
      in ["docker", "lxc", "openvz", "podman", "container"] ) )
    - '"/var/tmp" in ansible_mounts | map(attribute="mount") | list'
    - device_name.stdout is defined and device_name.stdout_lines is defined
    - (device_name.stdout | length > 0)
    tags:
    - DISA-STIG-OL09-00-002069
    - configure_strategy
    - high_disruption
    - low_complexity
    - medium_severity
    - mount_option_var_tmp_nosuid
    - no_reboot_needed

  - name: 'Add nosuid Option to /var/tmp: If /var/tmp not mounted, craft mount_info
      manually'
    set_fact:
      mount_info: '{{ mount_info|default({})|combine({item.0: item.1}) }}'
    with_together:
    - - target
      - source
      - fstype
      - options
    - - /var/tmp
      - ''
      - ''
      - defaults
    when:
    - ( not ( "kernel" in ansible_facts.packages and "rpm-ostree" in ansible_facts.packages
      and "bootc" in ansible_facts.packages and not "openshift-kubelet" in ansible_facts.packages
      and "ostree" in ansible_proc_cmdline ) and not ( ansible_virtualization_type
      in ["docker", "lxc", "openvz", "podman", "container"] ) )
    - '"/var/tmp" in ansible_mounts | map(attribute="mount") | list'
    - ("--fstab" | length == 0)
    - device_name.stdout is defined and device_name.stdout_lines is defined
    - (device_name.stdout | length == 0)
    tags:
    - DISA-STIG-OL09-00-002069
    - configure_strategy
    - high_disruption
    - low_complexity
    - medium_severity
    - mount_option_var_tmp_nosuid
    - no_reboot_needed

  - name: 'Add nosuid Option to /var/tmp: Make sure nosuid option is part of the to
      /var/tmp options'
    set_fact:
      mount_info: '{{ mount_info | combine( {''options'':''''~(mount_info.options
        | default(''''))~('','' if (mount_info.options | default('''')) else '''')~''nosuid''
        }) }}'
    when:
    - ( not ( "kernel" in ansible_facts.packages and "rpm-ostree" in ansible_facts.packages
      and "bootc" in ansible_facts.packages and not "openshift-kubelet" in ansible_facts.packages
      and "ostree" in ansible_proc_cmdline ) and not ( ansible_virtualization_type
      in ["docker", "lxc", "openvz", "podman", "container"] ) )
    - '"/var/tmp" in ansible_mounts | map(attribute="mount") | list'
    - mount_info is defined and "nosuid" not in (mount_info.options | default(''))
    tags:
    - DISA-STIG-OL09-00-002069
    - configure_strategy
    - high_disruption
    - low_complexity
    - medium_severity
    - mount_option_var_tmp_nosuid
    - no_reboot_needed

  - name: 'Add nosuid Option to /var/tmp: Ensure /var/tmp is mounted with nosuid option'
    ansible.posix.mount:
      path: /var/tmp
      src: '{{ mount_info.source | default('''') }}'
      opts: '{{ mount_info.options | default('''') }}'
      state: mounted
      fstype: '{{ mount_info.fstype | default('''') }}'
    register: mount_result
    failed_when:
    - mount_result is failed
    - '''target is busy'' not in (mount_result.msg | default(''''))'
    - '''already mounted'' not in (mount_result.msg | default(''''))'
    when:
    - ( not ( "kernel" in ansible_facts.packages and "rpm-ostree" in ansible_facts.packages
      and "bootc" in ansible_facts.packages and not "openshift-kubelet" in ansible_facts.packages
      and "ostree" in ansible_proc_cmdline ) and not ( ansible_virtualization_type
      in ["docker", "lxc", "openvz", "podman", "container"] ) )
    - '"/var/tmp" in ansible_mounts | map(attribute="mount") | list'
    - mount_info is defined
    - (device_name.stdout is defined and (device_name.stdout | length > 0)) or ("--fstab"
      | length == 0)
    tags:
    - DISA-STIG-OL09-00-002069
    - configure_strategy
    - high_disruption
    - low_complexity
    - medium_severity
    - mount_option_var_tmp_nosuid
    - no_reboot_needed

  - name: Restrict Access to Kernel Message Buffer - Set fact for sysctl paths
    ansible.builtin.set_fact:
      sysctl_paths:
      - /etc/sysctl.d/
      - /run/sysctl.d/
      - /usr/local/lib/sysctl.d/
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-002406
    - NIST-800-171-3.1.5
    - NIST-800-53-SI-11(a)
    - NIST-800-53-SI-11(b)
    - disable_strategy
    - low_complexity
    - low_severity
    - medium_disruption
    - reboot_required
    - sysctl_kernel_dmesg_restrict

  - name: Restrict Access to Kernel Message Buffer - Find all files that contain kernel.dmesg_restrict
    ansible.builtin.shell:
      cmd: find -L {{ sysctl_paths | join(" ") }} -type f -name '*.conf' | xargs grep
        -HP '^\s*kernel.dmesg_restrict\s*=\s*.*$'
    register: find_all_values
    check_mode: false
    changed_when: false
    failed_when: false
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-002406
    - NIST-800-171-3.1.5
    - NIST-800-53-SI-11(a)
    - NIST-800-53-SI-11(b)
    - disable_strategy
    - low_complexity
    - low_severity
    - medium_disruption
    - reboot_required
    - sysctl_kernel_dmesg_restrict

  - name: Restrict Access to Kernel Message Buffer - Find all files that set kernel.dmesg_restrict
      to correct value
    ansible.builtin.shell:
      cmd: find -L {{ sysctl_paths | join(" ") }} -type f -name '*.conf' | xargs grep
        -HP '^\s*kernel.dmesg_restrict\s*=\s*1$'
    register: find_correct_value
    check_mode: false
    changed_when: false
    failed_when: false
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-002406
    - NIST-800-171-3.1.5
    - NIST-800-53-SI-11(a)
    - NIST-800-53-SI-11(b)
    - disable_strategy
    - low_complexity
    - low_severity
    - medium_disruption
    - reboot_required
    - sysctl_kernel_dmesg_restrict

  - name: Restrict Access to Kernel Message Buffer - Comment out any occurrences of
      kernel.dmesg_restrict from config files
    ansible.builtin.replace:
      path: '{{ item | split(":") | first }}'
      regexp: ^[\s]*kernel.dmesg_restrict
      replace: '#kernel.dmesg_restrict'
    loop: '{{ find_all_values.stdout_lines }}'
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - find_correct_value.stdout_lines | length == 0 or find_all_values.stdout_lines
      | length > find_correct_value.stdout_lines | length
    tags:
    - DISA-STIG-OL09-00-002406
    - NIST-800-171-3.1.5
    - NIST-800-53-SI-11(a)
    - NIST-800-53-SI-11(b)
    - disable_strategy
    - low_complexity
    - low_severity
    - medium_disruption
    - reboot_required
    - sysctl_kernel_dmesg_restrict

  - name: Restrict Access to Kernel Message Buffer - Comment out any occurrences of
      kernel.dmesg_restrict from /etc/sysctl.conf
    ansible.builtin.replace:
      path: '{{ item }}'
      regexp: ^[\s]*kernel.dmesg_restrict
      replace: '#kernel.dmesg_restrict'
    with_fileglob:
    - /etc/sysctl.conf
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-002406
    - NIST-800-171-3.1.5
    - NIST-800-53-SI-11(a)
    - NIST-800-53-SI-11(b)
    - disable_strategy
    - low_complexity
    - low_severity
    - medium_disruption
    - reboot_required
    - sysctl_kernel_dmesg_restrict

  - name: Restrict Access to Kernel Message Buffer - Ensure sysctl kernel.dmesg_restrict
      is set to 1
    ansible.posix.sysctl:
      name: kernel.dmesg_restrict
      value: '1'
      sysctl_file: /etc/sysctl.d/kernel_dmesg_restrict.conf
      state: present
      reload: true
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-002406
    - NIST-800-171-3.1.5
    - NIST-800-53-SI-11(a)
    - NIST-800-53-SI-11(b)
    - disable_strategy
    - low_complexity
    - low_severity
    - medium_disruption
    - reboot_required
    - sysctl_kernel_dmesg_restrict

  - name: Kernel panic on oops - 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:
    - disable_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - reboot_required
    - sysctl_kernel_panic_on_oops

  - name: Kernel panic on oops - Find all files that contain kernel.panic_on_oops
    ansible.builtin.shell:
      cmd: find -L {{ sysctl_paths | join(" ") }} -type f -name '*.conf' | xargs grep
        -HP '^\s*kernel.panic_on_oops\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:
    - disable_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - reboot_required
    - sysctl_kernel_panic_on_oops

  - name: Kernel panic on oops - Find all files that set kernel.panic_on_oops to correct
      value
    ansible.builtin.shell:
      cmd: find -L {{ sysctl_paths | join(" ") }} -type f -name '*.conf' | xargs grep
        -HP '^\s*kernel.panic_on_oops\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:
    - disable_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - reboot_required
    - sysctl_kernel_panic_on_oops

  - name: Kernel panic on oops - Comment out any occurrences of kernel.panic_on_oops
      from config files
    ansible.builtin.replace:
      path: '{{ item | split(":") | first }}'
      regexp: ^[\s]*kernel.panic_on_oops
      replace: '#kernel.panic_on_oops'
    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:
    - disable_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - reboot_required
    - sysctl_kernel_panic_on_oops

  - name: Kernel panic on oops - Comment out any occurrences of kernel.panic_on_oops
      from /etc/sysctl.conf
    ansible.builtin.replace:
      path: '{{ item }}'
      regexp: ^[\s]*kernel.panic_on_oops
      replace: '#kernel.panic_on_oops'
    with_fileglob:
    - /etc/sysctl.conf
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - disable_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - reboot_required
    - sysctl_kernel_panic_on_oops

  - name: Kernel panic on oops - Ensure sysctl kernel.panic_on_oops is set to 1
    ansible.posix.sysctl:
      name: kernel.panic_on_oops
      value: '1'
      sysctl_file: /etc/sysctl.d/kernel_panic_on_oops.conf
      state: present
      reload: true
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - disable_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - reboot_required
    - sysctl_kernel_panic_on_oops

  - name: Limit CPU consumption of the Perf system - 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:
    - disable_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - reboot_required
    - sysctl_kernel_perf_cpu_time_max_percent

  - name: Limit CPU consumption of the Perf system - Find all files that contain kernel.perf_cpu_time_max_percent
    ansible.builtin.shell:
      cmd: find -L {{ sysctl_paths | join(" ") }} -type f -name '*.conf' | xargs grep
        -HP '^\s*kernel.perf_cpu_time_max_percent\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:
    - disable_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - reboot_required
    - sysctl_kernel_perf_cpu_time_max_percent

  - name: Limit CPU consumption of the Perf system - Find all files that set kernel.perf_cpu_time_max_percent
      to correct value
    ansible.builtin.shell:
      cmd: find -L {{ sysctl_paths | join(" ") }} -type f -name '*.conf' | xargs grep
        -HP '^\s*kernel.perf_cpu_time_max_percent\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:
    - disable_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - reboot_required
    - sysctl_kernel_perf_cpu_time_max_percent

  - name: Limit CPU consumption of the Perf system - Comment out any occurrences of
      kernel.perf_cpu_time_max_percent from config files
    ansible.builtin.replace:
      path: '{{ item | split(":") | first }}'
      regexp: ^[\s]*kernel.perf_cpu_time_max_percent
      replace: '#kernel.perf_cpu_time_max_percent'
    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:
    - disable_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - reboot_required
    - sysctl_kernel_perf_cpu_time_max_percent

  - name: Limit CPU consumption of the Perf system - Comment out any occurrences of
      kernel.perf_cpu_time_max_percent from /etc/sysctl.conf
    ansible.builtin.replace:
      path: '{{ item }}'
      regexp: ^[\s]*kernel.perf_cpu_time_max_percent
      replace: '#kernel.perf_cpu_time_max_percent'
    with_fileglob:
    - /etc/sysctl.conf
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - disable_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - reboot_required
    - sysctl_kernel_perf_cpu_time_max_percent

  - name: Limit CPU consumption of the Perf system - Ensure sysctl kernel.perf_cpu_time_max_percent
      is set to 1
    ansible.posix.sysctl:
      name: kernel.perf_cpu_time_max_percent
      value: '1'
      sysctl_file: /etc/sysctl.d/kernel_perf_cpu_time_max_percent.conf
      state: present
      reload: true
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - disable_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - reboot_required
    - sysctl_kernel_perf_cpu_time_max_percent

  - name: Limit sampling frequency of the Perf system - 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:
    - disable_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - reboot_required
    - sysctl_kernel_perf_event_max_sample_rate

  - name: Limit sampling frequency of the Perf system - Find all files that contain
      kernel.perf_event_max_sample_rate
    ansible.builtin.shell:
      cmd: find -L {{ sysctl_paths | join(" ") }} -type f -name '*.conf' | xargs grep
        -HP '^\s*kernel.perf_event_max_sample_rate\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:
    - disable_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - reboot_required
    - sysctl_kernel_perf_event_max_sample_rate

  - name: Limit sampling frequency of the Perf system - Find all files that set kernel.perf_event_max_sample_rate
      to correct value
    ansible.builtin.shell:
      cmd: find -L {{ sysctl_paths | join(" ") }} -type f -name '*.conf' | xargs grep
        -HP '^\s*kernel.perf_event_max_sample_rate\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:
    - disable_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - reboot_required
    - sysctl_kernel_perf_event_max_sample_rate

  - name: Limit sampling frequency of the Perf system - Comment out any occurrences
      of kernel.perf_event_max_sample_rate from config files
    ansible.builtin.replace:
      path: '{{ item | split(":") | first }}'
      regexp: ^[\s]*kernel.perf_event_max_sample_rate
      replace: '#kernel.perf_event_max_sample_rate'
    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:
    - disable_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - reboot_required
    - sysctl_kernel_perf_event_max_sample_rate

  - name: Limit sampling frequency of the Perf system - Comment out any occurrences
      of kernel.perf_event_max_sample_rate from /etc/sysctl.conf
    ansible.builtin.replace:
      path: '{{ item }}'
      regexp: ^[\s]*kernel.perf_event_max_sample_rate
      replace: '#kernel.perf_event_max_sample_rate'
    with_fileglob:
    - /etc/sysctl.conf
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - disable_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - reboot_required
    - sysctl_kernel_perf_event_max_sample_rate

  - name: Limit sampling frequency of the Perf system - Ensure sysctl kernel.perf_event_max_sample_rate
      is set to 1
    ansible.posix.sysctl:
      name: kernel.perf_event_max_sample_rate
      value: '1'
      sysctl_file: /etc/sysctl.d/kernel_perf_event_max_sample_rate.conf
      state: present
      reload: true
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - disable_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - reboot_required
    - sysctl_kernel_perf_event_max_sample_rate

  - name: Disallow kernel profiling by unprivileged users - Set fact for sysctl paths
    ansible.builtin.set_fact:
      sysctl_paths:
      - /etc/sysctl.d/
      - /run/sysctl.d/
      - /usr/local/lib/sysctl.d/
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-002407
    - NIST-800-53-AC-6
    - disable_strategy
    - low_complexity
    - low_severity
    - medium_disruption
    - reboot_required
    - sysctl_kernel_perf_event_paranoid

  - name: Disallow kernel profiling by unprivileged users - Find all files that contain
      kernel.perf_event_paranoid
    ansible.builtin.shell:
      cmd: find -L {{ sysctl_paths | join(" ") }} -type f -name '*.conf' | xargs grep
        -HP '^\s*kernel.perf_event_paranoid\s*=\s*.*$'
    register: find_all_values
    check_mode: false
    changed_when: false
    failed_when: false
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-002407
    - NIST-800-53-AC-6
    - disable_strategy
    - low_complexity
    - low_severity
    - medium_disruption
    - reboot_required
    - sysctl_kernel_perf_event_paranoid

  - name: Disallow kernel profiling by unprivileged users - Find all files that set
      kernel.perf_event_paranoid to correct value
    ansible.builtin.shell:
      cmd: find -L {{ sysctl_paths | join(" ") }} -type f -name '*.conf' | xargs grep
        -HP '^\s*kernel.perf_event_paranoid\s*=\s*2$'
    register: find_correct_value
    check_mode: false
    changed_when: false
    failed_when: false
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-002407
    - NIST-800-53-AC-6
    - disable_strategy
    - low_complexity
    - low_severity
    - medium_disruption
    - reboot_required
    - sysctl_kernel_perf_event_paranoid

  - name: Disallow kernel profiling by unprivileged users - Comment out any occurrences
      of kernel.perf_event_paranoid from config files
    ansible.builtin.replace:
      path: '{{ item | split(":") | first }}'
      regexp: ^[\s]*kernel.perf_event_paranoid
      replace: '#kernel.perf_event_paranoid'
    loop: '{{ find_all_values.stdout_lines }}'
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - find_correct_value.stdout_lines | length == 0 or find_all_values.stdout_lines
      | length > find_correct_value.stdout_lines | length
    tags:
    - DISA-STIG-OL09-00-002407
    - NIST-800-53-AC-6
    - disable_strategy
    - low_complexity
    - low_severity
    - medium_disruption
    - reboot_required
    - sysctl_kernel_perf_event_paranoid

  - name: Disallow kernel profiling by unprivileged users - Comment out any occurrences
      of kernel.perf_event_paranoid from /etc/sysctl.conf
    ansible.builtin.replace:
      path: '{{ item }}'
      regexp: ^[\s]*kernel.perf_event_paranoid
      replace: '#kernel.perf_event_paranoid'
    with_fileglob:
    - /etc/sysctl.conf
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-002407
    - NIST-800-53-AC-6
    - disable_strategy
    - low_complexity
    - low_severity
    - medium_disruption
    - reboot_required
    - sysctl_kernel_perf_event_paranoid

  - name: Disallow kernel profiling by unprivileged users - Ensure sysctl kernel.perf_event_paranoid
      is set to 2
    ansible.posix.sysctl:
      name: kernel.perf_event_paranoid
      value: '2'
      sysctl_file: /etc/sysctl.d/kernel_perf_event_paranoid.conf
      state: present
      reload: true
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-002407
    - NIST-800-53-AC-6
    - disable_strategy
    - low_complexity
    - low_severity
    - medium_disruption
    - reboot_required
    - sysctl_kernel_perf_event_paranoid

  - name: Configure maximum number of process identifiers - 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:
    - disable_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - reboot_required
    - sysctl_kernel_pid_max

  - name: Configure maximum number of process identifiers - Find all files that contain
      kernel.pid_max
    ansible.builtin.shell:
      cmd: find -L {{ sysctl_paths | join(" ") }} -type f -name '*.conf' | xargs grep
        -HP '^\s*kernel.pid_max\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:
    - disable_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - reboot_required
    - sysctl_kernel_pid_max

  - name: Configure maximum number of process identifiers - Find all files that set
      kernel.pid_max to correct value
    ansible.builtin.shell:
      cmd: find -L {{ sysctl_paths | join(" ") }} -type f -name '*.conf' | xargs grep
        -HP '^\s*kernel.pid_max\s*=\s*65536$'
    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:
    - disable_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - reboot_required
    - sysctl_kernel_pid_max

  - name: Configure maximum number of process identifiers - Comment out any occurrences
      of kernel.pid_max from config files
    ansible.builtin.replace:
      path: '{{ item | split(":") | first }}'
      regexp: ^[\s]*kernel.pid_max
      replace: '#kernel.pid_max'
    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:
    - disable_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - reboot_required
    - sysctl_kernel_pid_max

  - name: Configure maximum number of process identifiers - Comment out any occurrences
      of kernel.pid_max from /etc/sysctl.conf
    ansible.builtin.replace:
      path: '{{ item }}'
      regexp: ^[\s]*kernel.pid_max
      replace: '#kernel.pid_max'
    with_fileglob:
    - /etc/sysctl.conf
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - disable_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - reboot_required
    - sysctl_kernel_pid_max

  - name: Configure maximum number of process identifiers - Ensure sysctl kernel.pid_max
      is set to 65536
    ansible.posix.sysctl:
      name: kernel.pid_max
      value: '65536'
      sysctl_file: /etc/sysctl.d/kernel_pid_max.conf
      state: present
      reload: true
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - disable_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - reboot_required
    - sysctl_kernel_pid_max

  - name: Disallow magic SysRq key - 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:
    - disable_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - reboot_required
    - sysctl_kernel_sysrq

  - name: Disallow magic SysRq key - Find all files that contain kernel.sysrq
    ansible.builtin.shell:
      cmd: find -L {{ sysctl_paths | join(" ") }} -type f -name '*.conf' | xargs grep
        -HP '^\s*kernel.sysrq\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:
    - disable_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - reboot_required
    - sysctl_kernel_sysrq

  - name: Disallow magic SysRq key - Find all files that set kernel.sysrq to correct
      value
    ansible.builtin.shell:
      cmd: find -L {{ sysctl_paths | join(" ") }} -type f -name '*.conf' | xargs grep
        -HP '^\s*kernel.sysrq\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:
    - disable_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - reboot_required
    - sysctl_kernel_sysrq

  - name: Disallow magic SysRq key - Comment out any occurrences of kernel.sysrq from
      config files
    ansible.builtin.replace:
      path: '{{ item | split(":") | first }}'
      regexp: ^[\s]*kernel.sysrq
      replace: '#kernel.sysrq'
    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:
    - disable_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - reboot_required
    - sysctl_kernel_sysrq

  - name: Disallow magic SysRq key - Comment out any occurrences of kernel.sysrq from
      /etc/sysctl.conf
    ansible.builtin.replace:
      path: '{{ item }}'
      regexp: ^[\s]*kernel.sysrq
      replace: '#kernel.sysrq'
    with_fileglob:
    - /etc/sysctl.conf
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - disable_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - reboot_required
    - sysctl_kernel_sysrq

  - name: Disallow magic SysRq key - Ensure sysctl kernel.sysrq is set to 0
    ansible.posix.sysctl:
      name: kernel.sysrq
      value: '0'
      sysctl_file: /etc/sysctl.d/kernel_sysrq.conf
      state: present
      reload: true
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - disable_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - reboot_required
    - sysctl_kernel_sysrq

  - name: Disable Access to Network bpf() Syscall From Unprivileged Processes - Set
      fact for sysctl paths
    ansible.builtin.set_fact:
      sysctl_paths:
      - /etc/sysctl.d/
      - /run/sysctl.d/
      - /usr/local/lib/sysctl.d/
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-002409
    - NIST-800-53-AC-6
    - NIST-800-53-SC-7(10)
    - disable_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - reboot_required
    - sysctl_kernel_unprivileged_bpf_disabled

  - name: Disable Access to Network bpf() Syscall From Unprivileged Processes - Find
      all files that contain kernel.unprivileged_bpf_disabled
    ansible.builtin.shell:
      cmd: find -L {{ sysctl_paths | join(" ") }} -type f -name '*.conf' | xargs grep
        -HP '^\s*kernel.unprivileged_bpf_disabled\s*=\s*.*$'
    register: find_all_values
    check_mode: false
    changed_when: false
    failed_when: false
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-002409
    - NIST-800-53-AC-6
    - NIST-800-53-SC-7(10)
    - disable_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - reboot_required
    - sysctl_kernel_unprivileged_bpf_disabled

  - name: Disable Access to Network bpf() Syscall From Unprivileged Processes - Find
      all files that set kernel.unprivileged_bpf_disabled to correct value
    ansible.builtin.shell:
      cmd: find -L {{ sysctl_paths | join(" ") }} -type f -name '*.conf' | xargs grep
        -HP '^\s*kernel.unprivileged_bpf_disabled\s*=\s*1$'
    register: find_correct_value
    check_mode: false
    changed_when: false
    failed_when: false
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-002409
    - NIST-800-53-AC-6
    - NIST-800-53-SC-7(10)
    - disable_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - reboot_required
    - sysctl_kernel_unprivileged_bpf_disabled

  - name: Disable Access to Network bpf() Syscall From Unprivileged Processes - Comment
      out any occurrences of kernel.unprivileged_bpf_disabled from config files
    ansible.builtin.replace:
      path: '{{ item | split(":") | first }}'
      regexp: ^[\s]*kernel.unprivileged_bpf_disabled
      replace: '#kernel.unprivileged_bpf_disabled'
    loop: '{{ find_all_values.stdout_lines }}'
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - find_correct_value.stdout_lines | length == 0 or find_all_values.stdout_lines
      | length > find_correct_value.stdout_lines | length
    tags:
    - DISA-STIG-OL09-00-002409
    - NIST-800-53-AC-6
    - NIST-800-53-SC-7(10)
    - disable_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - reboot_required
    - sysctl_kernel_unprivileged_bpf_disabled

  - name: Disable Access to Network bpf() Syscall From Unprivileged Processes - Comment
      out any occurrences of kernel.unprivileged_bpf_disabled from /etc/sysctl.conf
    ansible.builtin.replace:
      path: '{{ item }}'
      regexp: ^[\s]*kernel.unprivileged_bpf_disabled
      replace: '#kernel.unprivileged_bpf_disabled'
    with_fileglob:
    - /etc/sysctl.conf
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-002409
    - NIST-800-53-AC-6
    - NIST-800-53-SC-7(10)
    - disable_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - reboot_required
    - sysctl_kernel_unprivileged_bpf_disabled

  - name: Disable Access to Network bpf() Syscall From Unprivileged Processes - Ensure
      sysctl kernel.unprivileged_bpf_disabled is set to 1
    ansible.posix.sysctl:
      name: kernel.unprivileged_bpf_disabled
      value: '1'
      sysctl_file: /etc/sysctl.d/kernel_unprivileged_bpf_disabled.conf
      state: present
      reload: true
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-002409
    - NIST-800-53-AC-6
    - NIST-800-53-SC-7(10)
    - disable_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - reboot_required
    - sysctl_kernel_unprivileged_bpf_disabled

  - name: Restrict usage of ptrace to descendant processes - Set fact for sysctl paths
    ansible.builtin.set_fact:
      sysctl_paths:
      - /etc/sysctl.d/
      - /run/sysctl.d/
      - /usr/local/lib/sysctl.d/
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-002410
    - NIST-800-53-SC-7(10)
    - disable_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - reboot_required
    - sysctl_kernel_yama_ptrace_scope

  - name: Restrict usage of ptrace to descendant processes - Find all files that contain
      kernel.yama.ptrace_scope
    ansible.builtin.shell:
      cmd: find -L {{ sysctl_paths | join(" ") }} -type f -name '*.conf' | xargs grep
        -HP '^\s*kernel.yama.ptrace_scope\s*=\s*.*$'
    register: find_all_values
    check_mode: false
    changed_when: false
    failed_when: false
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-002410
    - NIST-800-53-SC-7(10)
    - disable_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - reboot_required
    - sysctl_kernel_yama_ptrace_scope

  - name: Restrict usage of ptrace to descendant processes - Find all files that set
      kernel.yama.ptrace_scope to correct value
    ansible.builtin.shell:
      cmd: find -L {{ sysctl_paths | join(" ") }} -type f -name '*.conf' | xargs grep
        -HP '^\s*kernel.yama.ptrace_scope\s*=\s*1$'
    register: find_correct_value
    check_mode: false
    changed_when: false
    failed_when: false
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-002410
    - NIST-800-53-SC-7(10)
    - disable_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - reboot_required
    - sysctl_kernel_yama_ptrace_scope

  - name: Restrict usage of ptrace to descendant processes - Comment out any occurrences
      of kernel.yama.ptrace_scope from config files
    ansible.builtin.replace:
      path: '{{ item | split(":") | first }}'
      regexp: ^[\s]*kernel.yama.ptrace_scope
      replace: '#kernel.yama.ptrace_scope'
    loop: '{{ find_all_values.stdout_lines }}'
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - find_correct_value.stdout_lines | length == 0 or find_all_values.stdout_lines
      | length > find_correct_value.stdout_lines | length
    tags:
    - DISA-STIG-OL09-00-002410
    - NIST-800-53-SC-7(10)
    - disable_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - reboot_required
    - sysctl_kernel_yama_ptrace_scope

  - name: Restrict usage of ptrace to descendant processes - Comment out any occurrences
      of kernel.yama.ptrace_scope from /etc/sysctl.conf
    ansible.builtin.replace:
      path: '{{ item }}'
      regexp: ^[\s]*kernel.yama.ptrace_scope
      replace: '#kernel.yama.ptrace_scope'
    with_fileglob:
    - /etc/sysctl.conf
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-002410
    - NIST-800-53-SC-7(10)
    - disable_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - reboot_required
    - sysctl_kernel_yama_ptrace_scope

  - name: Restrict usage of ptrace to descendant processes - Ensure sysctl kernel.yama.ptrace_scope
      is set to 1
    ansible.posix.sysctl:
      name: kernel.yama.ptrace_scope
      value: '1'
      sysctl_file: /etc/sysctl.d/kernel_yama_ptrace_scope.conf
      state: present
      reload: true
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-002410
    - NIST-800-53-SC-7(10)
    - disable_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - reboot_required
    - sysctl_kernel_yama_ptrace_scope

  - name: Harden the operation of the BPF just-in-time compiler - Set fact for sysctl
      paths
    ansible.builtin.set_fact:
      sysctl_paths:
      - /etc/sysctl.d/
      - /run/sysctl.d/
      - /usr/local/lib/sysctl.d/
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-002430
    - NIST-800-53-CM-6
    - NIST-800-53-SC-7(10)
    - disable_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - reboot_required
    - sysctl_net_core_bpf_jit_harden

  - name: Harden the operation of the BPF just-in-time compiler - Find all files that
      contain net.core.bpf_jit_harden
    ansible.builtin.shell:
      cmd: find -L {{ sysctl_paths | join(" ") }} -type f -name '*.conf' | xargs grep
        -HP '^\s*net.core.bpf_jit_harden\s*=\s*.*$'
    register: find_all_values
    check_mode: false
    changed_when: false
    failed_when: false
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-002430
    - NIST-800-53-CM-6
    - NIST-800-53-SC-7(10)
    - disable_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - reboot_required
    - sysctl_net_core_bpf_jit_harden

  - name: Harden the operation of the BPF just-in-time compiler - Find all files that
      set net.core.bpf_jit_harden to correct value
    ansible.builtin.shell:
      cmd: find -L {{ sysctl_paths | join(" ") }} -type f -name '*.conf' | xargs grep
        -HP '^\s*net.core.bpf_jit_harden\s*=\s*2$'
    register: find_correct_value
    check_mode: false
    changed_when: false
    failed_when: false
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-002430
    - NIST-800-53-CM-6
    - NIST-800-53-SC-7(10)
    - disable_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - reboot_required
    - sysctl_net_core_bpf_jit_harden

  - name: Harden the operation of the BPF just-in-time compiler - Comment out any
      occurrences of net.core.bpf_jit_harden from config files
    ansible.builtin.replace:
      path: '{{ item | split(":") | first }}'
      regexp: ^[\s]*net.core.bpf_jit_harden
      replace: '#net.core.bpf_jit_harden'
    loop: '{{ find_all_values.stdout_lines }}'
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - find_correct_value.stdout_lines | length == 0 or find_all_values.stdout_lines
      | length > find_correct_value.stdout_lines | length
    tags:
    - DISA-STIG-OL09-00-002430
    - NIST-800-53-CM-6
    - NIST-800-53-SC-7(10)
    - disable_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - reboot_required
    - sysctl_net_core_bpf_jit_harden

  - name: Harden the operation of the BPF just-in-time compiler - Comment out any
      occurrences of net.core.bpf_jit_harden from /etc/sysctl.conf
    ansible.builtin.replace:
      path: '{{ item }}'
      regexp: ^[\s]*net.core.bpf_jit_harden
      replace: '#net.core.bpf_jit_harden'
    with_fileglob:
    - /etc/sysctl.conf
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-002430
    - NIST-800-53-CM-6
    - NIST-800-53-SC-7(10)
    - disable_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - reboot_required
    - sysctl_net_core_bpf_jit_harden

  - name: Harden the operation of the BPF just-in-time compiler - Ensure sysctl net.core.bpf_jit_harden
      is set to 2
    ansible.posix.sysctl:
      name: net.core.bpf_jit_harden
      value: '2'
      sysctl_file: /etc/sysctl.d/net_core_bpf_jit_harden.conf
      state: present
      reload: true
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-002430
    - NIST-800-53-CM-6
    - NIST-800-53-SC-7(10)
    - disable_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - reboot_required
    - sysctl_net_core_bpf_jit_harden

  - name: Prevent applications from mapping low portion of virtual memory - 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:
    - disable_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - reboot_required
    - sysctl_vm_mmap_min_addr

  - name: Prevent applications from mapping low portion of virtual memory - Find all
      files that contain vm.mmap_min_addr
    ansible.builtin.shell:
      cmd: find -L {{ sysctl_paths | join(" ") }} -type f -name '*.conf' | xargs grep
        -HP '^\s*vm.mmap_min_addr\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:
    - disable_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - reboot_required
    - sysctl_vm_mmap_min_addr

  - name: Prevent applications from mapping low portion of virtual memory - Find all
      files that set vm.mmap_min_addr to correct value
    ansible.builtin.shell:
      cmd: find -L {{ sysctl_paths | join(" ") }} -type f -name '*.conf' | xargs grep
        -HP '^\s*vm.mmap_min_addr\s*=\s*65536$'
    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:
    - disable_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - reboot_required
    - sysctl_vm_mmap_min_addr

  - name: Prevent applications from mapping low portion of virtual memory - Comment
      out any occurrences of vm.mmap_min_addr from config files
    ansible.builtin.replace:
      path: '{{ item | split(":") | first }}'
      regexp: ^[\s]*vm.mmap_min_addr
      replace: '#vm.mmap_min_addr'
    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:
    - disable_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - reboot_required
    - sysctl_vm_mmap_min_addr

  - name: Prevent applications from mapping low portion of virtual memory - Comment
      out any occurrences of vm.mmap_min_addr from /etc/sysctl.conf
    ansible.builtin.replace:
      path: '{{ item }}'
      regexp: ^[\s]*vm.mmap_min_addr
      replace: '#vm.mmap_min_addr'
    with_fileglob:
    - /etc/sysctl.conf
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - disable_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - reboot_required
    - sysctl_vm_mmap_min_addr

  - name: Prevent applications from mapping low portion of virtual memory - Ensure
      sysctl vm.mmap_min_addr is set to 65536
    ansible.posix.sysctl:
      name: vm.mmap_min_addr
      value: '65536'
      sysctl_file: /etc/sysctl.d/vm_mmap_min_addr.conf
      state: present
      reload: true
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - disable_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - reboot_required
    - sysctl_vm_mmap_min_addr

  - name: Disable Core Dumps for SUID programs - Set fact for sysctl paths
    ansible.builtin.set_fact:
      sysctl_paths:
      - /etc/sysctl.d/
      - /run/sysctl.d/
      - /usr/local/lib/sysctl.d/
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - NIST-800-53-SI-11(a)
    - NIST-800-53-SI-11(b)
    - PCI-DSSv4-3.3
    - PCI-DSSv4-3.3.1
    - PCI-DSSv4-3.3.1.1
    - disable_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - reboot_required
    - sysctl_fs_suid_dumpable

  - name: Disable Core Dumps for SUID programs - Find all files that contain fs.suid_dumpable
    ansible.builtin.shell:
      cmd: find -L {{ sysctl_paths | join(" ") }} -type f -name '*.conf' | xargs grep
        -HP '^\s*fs.suid_dumpable\s*=\s*.*$'
    register: find_all_values
    check_mode: false
    changed_when: false
    failed_when: false
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - NIST-800-53-SI-11(a)
    - NIST-800-53-SI-11(b)
    - PCI-DSSv4-3.3
    - PCI-DSSv4-3.3.1
    - PCI-DSSv4-3.3.1.1
    - disable_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - reboot_required
    - sysctl_fs_suid_dumpable

  - name: Disable Core Dumps for SUID programs - Find all files that set fs.suid_dumpable
      to correct value
    ansible.builtin.shell:
      cmd: find -L {{ sysctl_paths | join(" ") }} -type f -name '*.conf' | xargs grep
        -HP '^\s*fs.suid_dumpable\s*=\s*0$'
    register: find_correct_value
    check_mode: false
    changed_when: false
    failed_when: false
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - NIST-800-53-SI-11(a)
    - NIST-800-53-SI-11(b)
    - PCI-DSSv4-3.3
    - PCI-DSSv4-3.3.1
    - PCI-DSSv4-3.3.1.1
    - disable_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - reboot_required
    - sysctl_fs_suid_dumpable

  - name: Disable Core Dumps for SUID programs - Comment out any occurrences of fs.suid_dumpable
      from config files
    ansible.builtin.replace:
      path: '{{ item | split(":") | first }}'
      regexp: ^[\s]*fs.suid_dumpable
      replace: '#fs.suid_dumpable'
    loop: '{{ find_all_values.stdout_lines }}'
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - find_correct_value.stdout_lines | length == 0 or find_all_values.stdout_lines
      | length > find_correct_value.stdout_lines | length
    tags:
    - NIST-800-53-SI-11(a)
    - NIST-800-53-SI-11(b)
    - PCI-DSSv4-3.3
    - PCI-DSSv4-3.3.1
    - PCI-DSSv4-3.3.1.1
    - disable_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - reboot_required
    - sysctl_fs_suid_dumpable

  - name: Disable Core Dumps for SUID programs - Comment out any occurrences of fs.suid_dumpable
      from /etc/sysctl.conf
    ansible.builtin.replace:
      path: '{{ item }}'
      regexp: ^[\s]*fs.suid_dumpable
      replace: '#fs.suid_dumpable'
    with_fileglob:
    - /etc/sysctl.conf
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - NIST-800-53-SI-11(a)
    - NIST-800-53-SI-11(b)
    - PCI-DSSv4-3.3
    - PCI-DSSv4-3.3.1
    - PCI-DSSv4-3.3.1.1
    - disable_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - reboot_required
    - sysctl_fs_suid_dumpable

  - name: Disable Core Dumps for SUID programs - Ensure sysctl fs.suid_dumpable is
      set to 0
    ansible.posix.sysctl:
      name: fs.suid_dumpable
      value: '0'
      sysctl_file: /etc/sysctl.d/fs_suid_dumpable.conf
      state: present
      reload: true
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - NIST-800-53-SI-11(a)
    - NIST-800-53-SI-11(b)
    - PCI-DSSv4-3.3
    - PCI-DSSv4-3.3.1
    - PCI-DSSv4-3.3.1.1
    - disable_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - reboot_required
    - sysctl_fs_suid_dumpable

  - name: Restrict Exposed Kernel Pointer Addresses Access - Set fact for sysctl paths
    ansible.builtin.set_fact:
      sysctl_paths:
      - /etc/sysctl.d/
      - /run/sysctl.d/
      - /usr/local/lib/sysctl.d/
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-002408
    - NIST-800-53-CM-6(a)
    - NIST-800-53-SC-30
    - NIST-800-53-SC-30(2)
    - NIST-800-53-SC-30(5)
    - disable_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - reboot_required
    - sysctl_kernel_kptr_restrict

  - name: Restrict Exposed Kernel Pointer Addresses Access - Find all files that contain
      kernel.kptr_restrict
    ansible.builtin.shell:
      cmd: find -L {{ sysctl_paths | join(" ") }} -type f -name '*.conf' | xargs grep
        -HP '^\s*kernel.kptr_restrict\s*=\s*.*$'
    register: find_all_values
    check_mode: false
    changed_when: false
    failed_when: false
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-002408
    - NIST-800-53-CM-6(a)
    - NIST-800-53-SC-30
    - NIST-800-53-SC-30(2)
    - NIST-800-53-SC-30(5)
    - disable_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - reboot_required
    - sysctl_kernel_kptr_restrict

  - name: Restrict Exposed Kernel Pointer Addresses Access - Find all files that set
      kernel.kptr_restrict to correct value
    ansible.builtin.shell:
      cmd: find -L {{ sysctl_paths | join(" ") }} -type f -name '*.conf' | xargs grep
        -HP '^\s*kernel.kptr_restrict\s*=\s*{{ sysctl_kernel_kptr_restrict_value }}$'
    register: find_correct_value
    check_mode: false
    changed_when: false
    failed_when: false
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-002408
    - NIST-800-53-CM-6(a)
    - NIST-800-53-SC-30
    - NIST-800-53-SC-30(2)
    - NIST-800-53-SC-30(5)
    - disable_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - reboot_required
    - sysctl_kernel_kptr_restrict

  - name: Restrict Exposed Kernel Pointer Addresses Access - Comment out any occurrences
      of kernel.kptr_restrict from config files
    ansible.builtin.replace:
      path: '{{ item | split(":") | first }}'
      regexp: ^[\s]*kernel.kptr_restrict
      replace: '#kernel.kptr_restrict'
    loop: '{{ find_all_values.stdout_lines }}'
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - find_correct_value.stdout_lines | length == 0 or find_all_values.stdout_lines
      | length > find_correct_value.stdout_lines | length
    tags:
    - DISA-STIG-OL09-00-002408
    - NIST-800-53-CM-6(a)
    - NIST-800-53-SC-30
    - NIST-800-53-SC-30(2)
    - NIST-800-53-SC-30(5)
    - disable_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - reboot_required
    - sysctl_kernel_kptr_restrict

  - name: Restrict Exposed Kernel Pointer Addresses Access - Comment out any occurrences
      of kernel.kptr_restrict from /etc/sysctl.conf
    ansible.builtin.replace:
      path: '{{ item }}'
      regexp: ^[\s]*kernel.kptr_restrict
      replace: '#kernel.kptr_restrict'
    with_fileglob:
    - /etc/sysctl.conf
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-002408
    - NIST-800-53-CM-6(a)
    - NIST-800-53-SC-30
    - NIST-800-53-SC-30(2)
    - NIST-800-53-SC-30(5)
    - disable_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - reboot_required
    - sysctl_kernel_kptr_restrict

  - name: Restrict Exposed Kernel Pointer Addresses Access - Ensure sysctl kernel.kptr_restrict
      is set
    ansible.posix.sysctl:
      name: kernel.kptr_restrict
      value: '{{ sysctl_kernel_kptr_restrict_value }}'
      sysctl_file: /etc/sysctl.d/kernel_kptr_restrict.conf
      state: present
      reload: true
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-002408
    - NIST-800-53-CM-6(a)
    - NIST-800-53-SC-30
    - NIST-800-53-SC-30(2)
    - NIST-800-53-SC-30(5)
    - disable_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - reboot_required
    - sysctl_kernel_kptr_restrict

  - name: Enable Randomized Layout of Virtual Address Space - Set fact for sysctl
      paths
    ansible.builtin.set_fact:
      sysctl_paths:
      - /etc/sysctl.d/
      - /run/sysctl.d/
      - /usr/local/lib/sysctl.d/
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-002423
    - NIST-800-171-3.1.7
    - NIST-800-53-CM-6(a)
    - NIST-800-53-SC-30
    - NIST-800-53-SC-30(2)
    - PCI-DSS-Req-2.2.1
    - PCI-DSSv4-3.3
    - PCI-DSSv4-3.3.1
    - PCI-DSSv4-3.3.1.1
    - disable_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - reboot_required
    - sysctl_kernel_randomize_va_space

  - name: Enable Randomized Layout of Virtual Address Space - Find all files that
      contain kernel.randomize_va_space
    ansible.builtin.shell:
      cmd: find -L {{ sysctl_paths | join(" ") }} -type f -name '*.conf' | xargs grep
        -HP '^\s*kernel.randomize_va_space\s*=\s*.*$'
    register: find_all_values
    check_mode: false
    changed_when: false
    failed_when: false
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-002423
    - NIST-800-171-3.1.7
    - NIST-800-53-CM-6(a)
    - NIST-800-53-SC-30
    - NIST-800-53-SC-30(2)
    - PCI-DSS-Req-2.2.1
    - PCI-DSSv4-3.3
    - PCI-DSSv4-3.3.1
    - PCI-DSSv4-3.3.1.1
    - disable_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - reboot_required
    - sysctl_kernel_randomize_va_space

  - name: Enable Randomized Layout of Virtual Address Space - Find all files that
      set kernel.randomize_va_space to correct value
    ansible.builtin.shell:
      cmd: find -L {{ sysctl_paths | join(" ") }} -type f -name '*.conf' | xargs grep
        -HP '^\s*kernel.randomize_va_space\s*=\s*2$'
    register: find_correct_value
    check_mode: false
    changed_when: false
    failed_when: false
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-002423
    - NIST-800-171-3.1.7
    - NIST-800-53-CM-6(a)
    - NIST-800-53-SC-30
    - NIST-800-53-SC-30(2)
    - PCI-DSS-Req-2.2.1
    - PCI-DSSv4-3.3
    - PCI-DSSv4-3.3.1
    - PCI-DSSv4-3.3.1.1
    - disable_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - reboot_required
    - sysctl_kernel_randomize_va_space

  - name: Enable Randomized Layout of Virtual Address Space - Comment out any occurrences
      of kernel.randomize_va_space from config files
    ansible.builtin.replace:
      path: '{{ item | split(":") | first }}'
      regexp: ^[\s]*kernel.randomize_va_space
      replace: '#kernel.randomize_va_space'
    loop: '{{ find_all_values.stdout_lines }}'
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - find_correct_value.stdout_lines | length == 0 or find_all_values.stdout_lines
      | length > find_correct_value.stdout_lines | length
    tags:
    - DISA-STIG-OL09-00-002423
    - NIST-800-171-3.1.7
    - NIST-800-53-CM-6(a)
    - NIST-800-53-SC-30
    - NIST-800-53-SC-30(2)
    - PCI-DSS-Req-2.2.1
    - PCI-DSSv4-3.3
    - PCI-DSSv4-3.3.1
    - PCI-DSSv4-3.3.1.1
    - disable_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - reboot_required
    - sysctl_kernel_randomize_va_space

  - name: Enable Randomized Layout of Virtual Address Space - Comment out any occurrences
      of kernel.randomize_va_space from /etc/sysctl.conf
    ansible.builtin.replace:
      path: '{{ item }}'
      regexp: ^[\s]*kernel.randomize_va_space
      replace: '#kernel.randomize_va_space'
    with_fileglob:
    - /etc/sysctl.conf
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-002423
    - NIST-800-171-3.1.7
    - NIST-800-53-CM-6(a)
    - NIST-800-53-SC-30
    - NIST-800-53-SC-30(2)
    - PCI-DSS-Req-2.2.1
    - PCI-DSSv4-3.3
    - PCI-DSSv4-3.3.1
    - PCI-DSSv4-3.3.1.1
    - disable_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - reboot_required
    - sysctl_kernel_randomize_va_space

  - name: Enable Randomized Layout of Virtual Address Space - Ensure sysctl kernel.randomize_va_space
      is set to 2
    ansible.posix.sysctl:
      name: kernel.randomize_va_space
      value: '2'
      sysctl_file: /etc/sysctl.d/kernel_randomize_va_space.conf
      state: present
      reload: true
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-002423
    - NIST-800-171-3.1.7
    - NIST-800-53-CM-6(a)
    - NIST-800-53-SC-30
    - NIST-800-53-SC-30(2)
    - PCI-DSS-Req-2.2.1
    - PCI-DSSv4-3.3
    - PCI-DSSv4-3.3.1
    - PCI-DSSv4-3.3.1.1
    - disable_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - reboot_required
    - sysctl_kernel_randomize_va_space

  - name: Check if page_poison argument is already present in /etc/default/grub
    ansible.builtin.slurp:
      src: /etc/default/grub
    register: etc_default_grub
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - '"grub2-common" in ansible_facts.packages'
    tags:
    - DISA-STIG-OL09-00-002394
    - NIST-800-53-CM-6(a)
    - grub2_page_poison_argument
    - low_disruption
    - medium_complexity
    - medium_severity
    - reboot_required
    - restrict_strategy

  - name: Check if page_poison argument is already present
    ansible.builtin.command: /sbin/grubby --info=ALL
    register: grubby_info
    check_mode: false
    changed_when: false
    failed_when: false
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - '"grub2-common" in ansible_facts.packages'
    tags:
    - DISA-STIG-OL09-00-002394
    - NIST-800-53-CM-6(a)
    - grub2_page_poison_argument
    - low_disruption
    - medium_complexity
    - medium_severity
    - reboot_required
    - restrict_strategy

  - name: Update grub defaults and the bootloader menu
    ansible.builtin.command: /sbin/grubby --update-kernel=ALL --args="page_poison=1"
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - '"grub2-common" in ansible_facts.packages'
    - (grubby_info.stdout is not search('page_poison=1')) or ((etc_default_grub['content']
      | b64decode) is not search('page_poison=1'))
    tags:
    - DISA-STIG-OL09-00-002394
    - NIST-800-53-CM-6(a)
    - grub2_page_poison_argument
    - low_disruption
    - medium_complexity
    - medium_severity
    - reboot_required
    - restrict_strategy

  - name: Check if slub_debug argument is already present in /etc/default/grub
    ansible.builtin.slurp:
      src: /etc/default/grub
    register: etc_default_grub
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - '"grub2-common" in ansible_facts.packages'
    tags:
    - DISA-STIG-OL09-00-002390
    - NIST-800-53-CM-6(a)
    - grub2_slub_debug_argument
    - low_disruption
    - medium_complexity
    - medium_severity
    - reboot_required
    - restrict_strategy

  - name: Check if slub_debug argument is already present
    ansible.builtin.command: /sbin/grubby --info=ALL
    register: grubby_info
    check_mode: false
    changed_when: false
    failed_when: false
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - '"grub2-common" in ansible_facts.packages'
    tags:
    - DISA-STIG-OL09-00-002390
    - NIST-800-53-CM-6(a)
    - grub2_slub_debug_argument
    - low_disruption
    - medium_complexity
    - medium_severity
    - reboot_required
    - restrict_strategy

  - name: Update grub defaults and the bootloader menu
    ansible.builtin.command: /sbin/grubby --update-kernel=ALL --args="slub_debug={{
      var_slub_debug_options }}"
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - '"grub2-common" in ansible_facts.packages'
    - (grubby_info.stdout is not search('slub_debug=' ~ var_slub_debug_options)) or
      ((etc_default_grub['content'] | b64decode) is not search('slub_debug=' ~ var_slub_debug_options))
    tags:
    - DISA-STIG-OL09-00-002390
    - NIST-800-53-CM-6(a)
    - grub2_slub_debug_argument
    - low_disruption
    - medium_complexity
    - medium_severity
    - reboot_required
    - restrict_strategy

  - name: Check that the root group is defined
    ansible.builtin.getent:
      database: group
      key: root
    ignore_errors: true
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - directory_groupowner_etc_selinux_newgroup is undefined
    tags:
    - configure_strategy
    - directory_groupowner_etc_selinux
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

  - name: Set the directory_groupowner_etc_selinux_newgroup variable if root found
    ansible.builtin.set_fact:
      directory_groupowner_etc_selinux_newgroup: root
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - ansible_facts.getent_group["root"] is defined
    tags:
    - configure_strategy
    - directory_groupowner_etc_selinux
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

  - name: Ensure group owner on /etc/selinux/
    ansible.builtin.file:
      path: /etc/selinux/
      follow: false
      state: directory
      group: '{{ directory_groupowner_etc_selinux_newgroup }}'
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - configure_strategy
    - directory_groupowner_etc_selinux
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

  - name: Set the directory_owner_etc_selinux_newown variable if represented by uid
    ansible.builtin.set_fact:
      directory_owner_etc_selinux_newown: '0'
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - configure_strategy
    - directory_owner_etc_selinux
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

  - name: Ensure owner on directory /etc/selinux/
    ansible.builtin.file:
      path: /etc/selinux/
      follow: false
      state: directory
      owner: '{{ directory_owner_etc_selinux_newown }}'
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - configure_strategy
    - directory_owner_etc_selinux
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

  - name: Find /etc/selinux/ file(s)
    ansible.builtin.command: 'find -P /etc/selinux/ -maxdepth 0 -perm /u+s,g+ws,o+wt  -type
      d '
    register: files_found
    changed_when: false
    failed_when: false
    check_mode: false
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - configure_strategy
    - directory_permissions_etc_selinux
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

  - name: Set permissions for /etc/selinux/ file(s)
    ansible.builtin.file:
      path: '{{ item }}'
      mode: u-s,g-ws,o-wt
      state: directory
    with_items:
    - '{{ files_found.stdout_lines }}'
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - configure_strategy
    - directory_permissions_etc_selinux
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

  - name: Check that the root group is defined
    ansible.builtin.getent:
      database: group
      key: root
    ignore_errors: true
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - file_groupowner_etc_sestatus_conf_newgroup is undefined
    tags:
    - configure_strategy
    - file_groupowner_etc_sestatus_conf
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

  - name: Set the file_groupowner_etc_sestatus_conf_newgroup variable if root found
    ansible.builtin.set_fact:
      file_groupowner_etc_sestatus_conf_newgroup: root
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - ansible_facts.getent_group["root"] is defined
    tags:
    - configure_strategy
    - file_groupowner_etc_sestatus_conf
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

  - name: Test for existence /etc/sestatus.conf
    ansible.builtin.stat:
      path: /etc/sestatus.conf
    register: file_exists
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - configure_strategy
    - file_groupowner_etc_sestatus_conf
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

  - name: Ensure group owner on /etc/sestatus.conf
    ansible.builtin.file:
      path: /etc/sestatus.conf
      follow: false
      group: '{{ file_groupowner_etc_sestatus_conf_newgroup }}'
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - file_exists.stat is defined and file_exists.stat.exists
    tags:
    - configure_strategy
    - file_groupowner_etc_sestatus_conf
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

  - name: Set the file_owner_etc_sestatus_conf_newown variable if represented by uid
    ansible.builtin.set_fact:
      file_owner_etc_sestatus_conf_newown: '0'
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - configure_strategy
    - file_owner_etc_sestatus_conf
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

  - name: Test for existence /etc/sestatus.conf
    ansible.builtin.stat:
      path: /etc/sestatus.conf
    register: file_exists
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - configure_strategy
    - file_owner_etc_sestatus_conf
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

  - name: Ensure owner on /etc/sestatus.conf
    ansible.builtin.file:
      path: /etc/sestatus.conf
      follow: false
      owner: '{{ file_owner_etc_sestatus_conf_newown }}'
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - file_exists.stat is defined and file_exists.stat.exists
    tags:
    - configure_strategy
    - file_owner_etc_sestatus_conf
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

  - name: Test for existence /etc/sestatus.conf
    ansible.builtin.stat:
      path: /etc/sestatus.conf
    register: file_exists
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - configure_strategy
    - file_permissions_etc_sestatus_conf
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

  - name: Ensure permission u-xs,g-xws,o-xwt on /etc/sestatus.conf
    ansible.builtin.file:
      path: /etc/sestatus.conf
      mode: u-xs,g-xws,o-xwt
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - file_exists.stat is defined and file_exists.stat.exists
    tags:
    - configure_strategy
    - file_permissions_etc_sestatus_conf
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

  - name: Ensure SELinux State is Enforcing - Check current SELinux state
    ansible.builtin.command:
      cmd: getenforce
    register: current_selinux_state
    check_mode: false
    changed_when: false
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-000060
    - NIST-800-171-3.1.2
    - NIST-800-171-3.7.2
    - NIST-800-53-AC-3
    - NIST-800-53-AC-3(3)(a)
    - NIST-800-53-AU-9
    - NIST-800-53-SC-7(21)
    - PCI-DSSv4-1.2
    - PCI-DSSv4-1.2.6
    - high_severity
    - low_complexity
    - low_disruption
    - no_reboot_needed
    - restrict_strategy
    - selinux_state

  - name: Ensure SELinux State is Enforcing
    block:

    - name: Check for duplicate values
      ansible.builtin.lineinfile:
        path: /etc/selinux/config
        create: true
        regexp: (?i)^SELINUX=
        state: absent
      check_mode: true
      changed_when: false
      register: dupes

    - name: Deduplicate values from /etc/selinux/config
      ansible.builtin.lineinfile:
        path: /etc/selinux/config
        create: true
        regexp: (?i)^SELINUX=
        state: absent
      when: dupes.found is defined and dupes.found > 1

    - name: Insert correct line to /etc/selinux/config
      ansible.builtin.lineinfile:
        path: /etc/selinux/config
        create: true
        regexp: (?i)^SELINUX=
        line: SELINUX={{ var_selinux_state }}
        state: present
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-000060
    - NIST-800-171-3.1.2
    - NIST-800-171-3.7.2
    - NIST-800-53-AC-3
    - NIST-800-53-AC-3(3)(a)
    - NIST-800-53-AU-9
    - NIST-800-53-SC-7(21)
    - PCI-DSSv4-1.2
    - PCI-DSSv4-1.2.6
    - high_severity
    - low_complexity
    - low_disruption
    - no_reboot_needed
    - restrict_strategy
    - selinux_state

  - name: Ensure SELinux State is Enforcing - Mark system to relabel SELinux on next
      boot
    ansible.builtin.file:
      path: /.autorelabel
      state: touch
      access_time: preserve
      modification_time: preserve
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - current_selinux_state.stdout | lower != var_selinux_state
    tags:
    - DISA-STIG-OL09-00-000060
    - NIST-800-171-3.1.2
    - NIST-800-171-3.7.2
    - NIST-800-53-AC-3
    - NIST-800-53-AC-3(3)(a)
    - NIST-800-53-AU-9
    - NIST-800-53-SC-7(21)
    - PCI-DSSv4-1.2
    - PCI-DSSv4-1.2.6
    - high_severity
    - low_complexity
    - low_disruption
    - no_reboot_needed
    - restrict_strategy
    - selinux_state

  - name: Configure the polyinstantiation_enabled SELinux Boolean - Set SELinux Boolean
      polyinstantiation_enabled Accordingly
    ansible.posix.seboolean:
      name: polyinstantiation_enabled
      state: '{{ var_polyinstantiation_enabled }}'
      persistent: true
    when:
    - ( "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 or lookup("env", "container") == "bwrap-osbuild"
      or ansible_facts.selinux.status != "disabled" )
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - enable_strategy
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - sebool_polyinstantiation_enabled

  - name: Make changes to Postfix configuration file
    ansible.builtin.lineinfile:
      path: /etc/postfix/main.cf
      create: false
      regexp: (?i)^inet_interfaces\s*=\s.*
      line: inet_interfaces = {{ var_postfix_inet_interfaces }}
      state: present
      insertafter: ^inet_interfaces\s*=\s.*
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - '"postfix" in ansible_facts.packages'
    - '"postfix" in ansible_facts.packages'
    tags:
    - NIST-800-53-CM-6(a)
    - NIST-800-53-CM-7(a)
    - NIST-800-53-CM-7(b)
    - PCI-DSSv4-1.4
    - PCI-DSSv4-1.4.2
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - postfix_network_listening_disabled
    - restrict_strategy

  - name: Check that the chrony group is defined
    ansible.builtin.getent:
      database: group
      key: chrony
    ignore_errors: true
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - file_groupowner_etc_chrony_keys_newgroup is undefined
    tags:
    - configure_strategy
    - file_groupowner_etc_chrony_keys
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

  - name: Set the file_groupowner_etc_chrony_keys_newgroup variable if chrony found
    ansible.builtin.set_fact:
      file_groupowner_etc_chrony_keys_newgroup: chrony
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - ansible_facts.getent_group["chrony"] is defined
    tags:
    - configure_strategy
    - file_groupowner_etc_chrony_keys
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

  - name: Test for existence /etc/chrony.keys
    ansible.builtin.stat:
      path: /etc/chrony.keys
    register: file_exists
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - configure_strategy
    - file_groupowner_etc_chrony_keys
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

  - name: Ensure group owner on /etc/chrony.keys
    ansible.builtin.file:
      path: /etc/chrony.keys
      follow: false
      group: '{{ file_groupowner_etc_chrony_keys_newgroup }}'
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - file_exists.stat is defined and file_exists.stat.exists
    tags:
    - configure_strategy
    - file_groupowner_etc_chrony_keys
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

  - name: Set the file_owner_etc_chrony_keys_newown variable if represented by uid
    ansible.builtin.set_fact:
      file_owner_etc_chrony_keys_newown: '0'
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - configure_strategy
    - file_owner_etc_chrony_keys
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

  - name: Test for existence /etc/chrony.keys
    ansible.builtin.stat:
      path: /etc/chrony.keys
    register: file_exists
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - configure_strategy
    - file_owner_etc_chrony_keys
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

  - name: Ensure owner on /etc/chrony.keys
    ansible.builtin.file:
      path: /etc/chrony.keys
      follow: false
      owner: '{{ file_owner_etc_chrony_keys_newown }}'
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - file_exists.stat is defined and file_exists.stat.exists
    tags:
    - configure_strategy
    - file_owner_etc_chrony_keys
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

  - name: Test for existence /etc/chrony.keys
    ansible.builtin.stat:
      path: /etc/chrony.keys
    register: file_exists
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - configure_strategy
    - file_permissions_etc_chrony_keys
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

  - name: Ensure permission u-xs,g-xws,o-xwrt on /etc/chrony.keys
    ansible.builtin.file:
      path: /etc/chrony.keys
      mode: u-xs,g-xws,o-xwrt
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - file_exists.stat is defined and file_exists.stat.exists
    tags:
    - configure_strategy
    - file_permissions_etc_chrony_keys
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

  - name: Set the file_groupowner_sshd_config_newgroup variable if represented by
      gid
    ansible.builtin.set_fact:
      file_groupowner_sshd_config_newgroup: '0'
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-002507
    - NIST-800-53-AC-17(a)
    - NIST-800-53-AC-6(1)
    - NIST-800-53-CM-6(a)
    - configure_strategy
    - file_groupowner_sshd_config
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

  - name: Test for existence /etc/ssh/sshd_config
    ansible.builtin.stat:
      path: /etc/ssh/sshd_config
    register: file_exists
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-002507
    - NIST-800-53-AC-17(a)
    - NIST-800-53-AC-6(1)
    - NIST-800-53-CM-6(a)
    - configure_strategy
    - file_groupowner_sshd_config
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

  - name: Ensure group owner on /etc/ssh/sshd_config
    ansible.builtin.file:
      path: /etc/ssh/sshd_config
      follow: false
      group: '{{ file_groupowner_sshd_config_newgroup }}'
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - file_exists.stat is defined and file_exists.stat.exists
    tags:
    - DISA-STIG-OL09-00-002507
    - NIST-800-53-AC-17(a)
    - NIST-800-53-AC-6(1)
    - NIST-800-53-CM-6(a)
    - configure_strategy
    - file_groupowner_sshd_config
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

  - name: Check that the ssh_keys group is defined
    ansible.builtin.getent:
      database: group
      key: ssh_keys
    ignore_errors: true
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - file_groupownership_sshd_private_key_newgroup is undefined
    tags:
    - configure_strategy
    - file_groupownership_sshd_private_key
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

  - name: Set the file_groupownership_sshd_private_key_newgroup variable if ssh_keys
      found
    ansible.builtin.set_fact:
      file_groupownership_sshd_private_key_newgroup: ssh_keys
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - ansible_facts.getent_group["ssh_keys"] is defined
    tags:
    - configure_strategy
    - file_groupownership_sshd_private_key
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

  - name: Find /etc/ssh/ file(s) matching ^.*_key$
    ansible.builtin.command: find -P /etc/ssh/ -maxdepth 1 -type f  ! -group ssh_keys
      -regextype posix-extended -regex "^.*_key$"
    register: files_found
    changed_when: false
    failed_when: false
    check_mode: false
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - configure_strategy
    - file_groupownership_sshd_private_key
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

  - name: Ensure group owner on /etc/ssh/ file(s) matching ^.*_key$
    ansible.builtin.file:
      path: '{{ item }}'
      follow: false
      group: '{{ file_groupownership_sshd_private_key_newgroup }}'
      state: file
    with_items:
    - '{{ files_found.stdout_lines }}'
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - configure_strategy
    - file_groupownership_sshd_private_key
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

  - name: Set the file_groupownership_sshd_pub_key_newgroup variable if represented
      by gid
    ansible.builtin.set_fact:
      file_groupownership_sshd_pub_key_newgroup: '0'
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - configure_strategy
    - file_groupownership_sshd_pub_key
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

  - name: Find /etc/ssh/ file(s) matching ^.*\.pub$
    ansible.builtin.command: find -P /etc/ssh/ -maxdepth 1 -type f  ! -group 0 -regextype
      posix-extended -regex "^.*\.pub$"
    register: files_found
    changed_when: false
    failed_when: false
    check_mode: false
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - configure_strategy
    - file_groupownership_sshd_pub_key
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

  - name: Ensure group owner on /etc/ssh/ file(s) matching ^.*\.pub$
    ansible.builtin.file:
      path: '{{ item }}'
      follow: false
      group: '{{ file_groupownership_sshd_pub_key_newgroup }}'
      state: file
    with_items:
    - '{{ files_found.stdout_lines }}'
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - configure_strategy
    - file_groupownership_sshd_pub_key
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

  - name: Set the file_owner_sshd_config_newown variable if represented by uid
    ansible.builtin.set_fact:
      file_owner_sshd_config_newown: '0'
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-002508
    - NIST-800-53-AC-17(a)
    - NIST-800-53-AC-6(1)
    - NIST-800-53-CM-6(a)
    - configure_strategy
    - file_owner_sshd_config
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

  - name: Test for existence /etc/ssh/sshd_config
    ansible.builtin.stat:
      path: /etc/ssh/sshd_config
    register: file_exists
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-002508
    - NIST-800-53-AC-17(a)
    - NIST-800-53-AC-6(1)
    - NIST-800-53-CM-6(a)
    - configure_strategy
    - file_owner_sshd_config
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

  - name: Ensure owner on /etc/ssh/sshd_config
    ansible.builtin.file:
      path: /etc/ssh/sshd_config
      follow: false
      owner: '{{ file_owner_sshd_config_newown }}'
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - file_exists.stat is defined and file_exists.stat.exists
    tags:
    - DISA-STIG-OL09-00-002508
    - NIST-800-53-AC-17(a)
    - NIST-800-53-AC-6(1)
    - NIST-800-53-CM-6(a)
    - configure_strategy
    - file_owner_sshd_config
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

  - name: Set the file_ownership_sshd_private_key_newown variable if represented by
      uid
    ansible.builtin.set_fact:
      file_ownership_sshd_private_key_newown: '0'
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - configure_strategy
    - file_ownership_sshd_private_key
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

  - name: Find /etc/ssh/ file(s) matching ^.*_key$
    ansible.builtin.command: find -P /etc/ssh/ -maxdepth 1 -type f  ! -user 0 -regextype
      posix-extended -regex "^.*_key$"
    register: files_found
    changed_when: false
    failed_when: false
    check_mode: false
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - configure_strategy
    - file_ownership_sshd_private_key
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

  - name: Ensure owner on /etc/ssh/ file(s) matching ^.*_key$
    ansible.builtin.file:
      path: '{{ item }}'
      follow: false
      owner: '{{ file_ownership_sshd_private_key_newown }}'
      state: file
    with_items:
    - '{{ files_found.stdout_lines }}'
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - configure_strategy
    - file_ownership_sshd_private_key
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

  - name: Set the file_ownership_sshd_pub_key_newown variable if represented by uid
    ansible.builtin.set_fact:
      file_ownership_sshd_pub_key_newown: '0'
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - configure_strategy
    - file_ownership_sshd_pub_key
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

  - name: Find /etc/ssh/ file(s) matching ^.*\.pub$
    ansible.builtin.command: find -P /etc/ssh/ -maxdepth 1 -type f  ! -user 0 -regextype
      posix-extended -regex "^.*\.pub$"
    register: files_found
    changed_when: false
    failed_when: false
    check_mode: false
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - configure_strategy
    - file_ownership_sshd_pub_key
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

  - name: Ensure owner on /etc/ssh/ file(s) matching ^.*\.pub$
    ansible.builtin.file:
      path: '{{ item }}'
      follow: false
      owner: '{{ file_ownership_sshd_pub_key_newown }}'
      state: file
    with_items:
    - '{{ files_found.stdout_lines }}'
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - configure_strategy
    - file_ownership_sshd_pub_key
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

  - name: Test for existence /etc/ssh/sshd_config
    ansible.builtin.stat:
      path: /etc/ssh/sshd_config
    register: file_exists
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-002509
    - NIST-800-53-AC-17(a)
    - NIST-800-53-AC-6(1)
    - NIST-800-53-CM-6(a)
    - PCI-DSSv4-2.2
    - PCI-DSSv4-2.2.6
    - configure_strategy
    - file_permissions_sshd_config
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

  - name: Ensure permission u-xs,g-xwrs,o-xwrt on /etc/ssh/sshd_config
    ansible.builtin.file:
      path: /etc/ssh/sshd_config
      mode: u-xs,g-xwrs,o-xwrt
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - file_exists.stat is defined and file_exists.stat.exists
    tags:
    - DISA-STIG-OL09-00-002509
    - NIST-800-53-AC-17(a)
    - NIST-800-53-AC-6(1)
    - NIST-800-53-CM-6(a)
    - PCI-DSSv4-2.2
    - PCI-DSSv4-2.2.6
    - configure_strategy
    - file_permissions_sshd_config
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

  - name: Find root:root-owned keys
    ansible.builtin.command: find -H /etc/ssh/ -maxdepth 1 -user root -regex ".*_key$"
      -type f -group root -perm /u+xs,g+xws,o+xwrt
    register: root_owned_keys
    changed_when: false
    failed_when: false
    check_mode: false
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-002502
    - NIST-800-171-3.1.13
    - NIST-800-171-3.13.10
    - NIST-800-53-AC-17(a)
    - NIST-800-53-AC-6(1)
    - NIST-800-53-CM-6(a)
    - PCI-DSS-Req-2.2.4
    - PCI-DSSv4-2.2
    - PCI-DSSv4-2.2.6
    - configure_strategy
    - file_permissions_sshd_private_key
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

  - name: Set permissions for root:root-owned keys
    ansible.builtin.file:
      path: '{{ item }}'
      mode: u-xs,g-xws,o-xwrt
      state: file
    with_items:
    - '{{ root_owned_keys.stdout_lines }}'
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-002502
    - NIST-800-171-3.1.13
    - NIST-800-171-3.13.10
    - NIST-800-53-AC-17(a)
    - NIST-800-53-AC-6(1)
    - NIST-800-53-CM-6(a)
    - PCI-DSS-Req-2.2.4
    - PCI-DSSv4-2.2
    - PCI-DSSv4-2.2.6
    - configure_strategy
    - file_permissions_sshd_private_key
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

  - name: Find root:ssh_keys-owned keys
    ansible.builtin.command: find -H /etc/ssh/ -maxdepth 1 -user root -regex ".*_key$"
      -type f -group ssh_keys -perm /u+xs,g+xws,o+xwrt
    register: dedicated_group_owned_keys
    changed_when: false
    failed_when: false
    check_mode: false
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-002502
    - NIST-800-171-3.1.13
    - NIST-800-171-3.13.10
    - NIST-800-53-AC-17(a)
    - NIST-800-53-AC-6(1)
    - NIST-800-53-CM-6(a)
    - PCI-DSS-Req-2.2.4
    - PCI-DSSv4-2.2
    - PCI-DSSv4-2.2.6
    - configure_strategy
    - file_permissions_sshd_private_key
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

  - name: Set permissions for root:ssh_keys-owned keys
    ansible.builtin.file:
      path: '{{ item }}'
      mode: u-xs,g-xws,o-xwrt
      state: file
    with_items:
    - '{{ dedicated_group_owned_keys.stdout_lines }}'
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-002502
    - NIST-800-171-3.1.13
    - NIST-800-171-3.13.10
    - NIST-800-53-AC-17(a)
    - NIST-800-53-AC-6(1)
    - NIST-800-53-CM-6(a)
    - PCI-DSS-Req-2.2.4
    - PCI-DSSv4-2.2
    - PCI-DSSv4-2.2.6
    - configure_strategy
    - file_permissions_sshd_private_key
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

  - name: Find /etc/ssh/ file(s)
    ansible.builtin.command: find -P /etc/ssh/ -maxdepth 1 -perm /u+xs,g+xws,o+xwt  -type
      f -regextype posix-extended -regex "^.*\.pub$"
    register: files_found
    changed_when: false
    failed_when: false
    check_mode: false
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-002503
    - NIST-800-171-3.1.13
    - NIST-800-171-3.13.10
    - NIST-800-53-AC-17(a)
    - NIST-800-53-AC-6(1)
    - NIST-800-53-CM-6(a)
    - PCI-DSS-Req-2.2.4
    - PCI-DSSv4-2.2
    - PCI-DSSv4-2.2.6
    - configure_strategy
    - file_permissions_sshd_pub_key
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

  - name: Set permissions for /etc/ssh/ file(s)
    ansible.builtin.file:
      path: '{{ item }}'
      mode: u-xs,g-xws,o-xwt
      state: file
    with_items:
    - '{{ files_found.stdout_lines }}'
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-002503
    - NIST-800-171-3.1.13
    - NIST-800-171-3.13.10
    - NIST-800-53-AC-17(a)
    - NIST-800-53-AC-6(1)
    - NIST-800-53-CM-6(a)
    - PCI-DSS-Req-2.2.4
    - PCI-DSSv4-2.2
    - PCI-DSSv4-2.2.6
    - configure_strategy
    - file_permissions_sshd_pub_key
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

  - name: Find sshd_config included files
    ansible.builtin.shell: |-
      included_files=$(grep -oP "^\s*(?i)include.*" /etc/ssh/sshd_config | sed -e 's/\s*Include\s*//i' | sed -e 's|^[^/]|/etc/ssh/&|')
      [[ -n $included_files ]] && ls $included_files || true
    register: sshd_config_included_files
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - CJIS-5.5.6
    - DISA-STIG-OL09-00-002345
    - NIST-800-171-3.1.1
    - NIST-800-171-3.1.5
    - NIST-800-53-AC-17(a)
    - NIST-800-53-AC-6(2)
    - NIST-800-53-CM-6(a)
    - NIST-800-53-CM-7(a)
    - NIST-800-53-CM-7(b)
    - NIST-800-53-IA-2
    - NIST-800-53-IA-2(5)
    - PCI-DSS-Req-2.2.4
    - PCI-DSSv4-2.2
    - PCI-DSSv4-2.2.6
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy
    - sshd_disable_root_login

  - name: Comment conf from included files
    ansible.builtin.replace:
      path: '{{ item }}'
      regexp: ^(\s*PermitRootLogin.*)$
      replace: '# \1'
    loop: '{{ sshd_config_included_files.stdout_lines }}'
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - CJIS-5.5.6
    - DISA-STIG-OL09-00-002345
    - NIST-800-171-3.1.1
    - NIST-800-171-3.1.5
    - NIST-800-53-AC-17(a)
    - NIST-800-53-AC-6(2)
    - NIST-800-53-CM-6(a)
    - NIST-800-53-CM-7(a)
    - NIST-800-53-CM-7(b)
    - NIST-800-53-IA-2
    - NIST-800-53-IA-2(5)
    - PCI-DSS-Req-2.2.4
    - PCI-DSSv4-2.2
    - PCI-DSSv4-2.2.6
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy
    - sshd_disable_root_login

  - name: Disable SSH Root Login - Check if the parameter PermitRootLogin is configured
    ansible.builtin.find:
      paths:
      - /etc/ssh/sshd_config
      - /etc/ssh/sshd_config.d
      contains: (?i)^\s*{{ "PermitRootLogin"| regex_escape }}\s+
    register: _sshd_config_has_parameter
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - CJIS-5.5.6
    - DISA-STIG-OL09-00-002345
    - NIST-800-171-3.1.1
    - NIST-800-171-3.1.5
    - NIST-800-53-AC-17(a)
    - NIST-800-53-AC-6(2)
    - NIST-800-53-CM-6(a)
    - NIST-800-53-CM-7(a)
    - NIST-800-53-CM-7(b)
    - NIST-800-53-IA-2
    - NIST-800-53-IA-2(5)
    - PCI-DSS-Req-2.2.4
    - PCI-DSSv4-2.2
    - PCI-DSSv4-2.2.6
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy
    - sshd_disable_root_login

  - name: Disable SSH Root Login - Check if the parameter PermitRootLogin is configured
      correctly
    ansible.builtin.find:
      paths:
      - /etc/ssh/sshd_config
      - /etc/ssh/sshd_config.d
      contains: (?i)^\s*{{ "PermitRootLogin"| regex_escape }}\s+no$
    register: _sshd_config_correctly
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - CJIS-5.5.6
    - DISA-STIG-OL09-00-002345
    - NIST-800-171-3.1.1
    - NIST-800-171-3.1.5
    - NIST-800-53-AC-17(a)
    - NIST-800-53-AC-6(2)
    - NIST-800-53-CM-6(a)
    - NIST-800-53-CM-7(a)
    - NIST-800-53-CM-7(b)
    - NIST-800-53-IA-2
    - NIST-800-53-IA-2(5)
    - PCI-DSS-Req-2.2.4
    - PCI-DSSv4-2.2
    - PCI-DSSv4-2.2.6
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy
    - sshd_disable_root_login

  - name: Disable SSH Root Login
    block:

    - name: Deduplicate values from /etc/ssh/sshd_config
      ansible.builtin.lineinfile:
        path: /etc/ssh/sshd_config
        create: false
        regexp: (?i)(?i)^\s*{{ "PermitRootLogin"| regex_escape }}\s+
        state: absent

    - name: Check if /etc/ssh/sshd_config.d exists
      ansible.builtin.stat:
        path: /etc/ssh/sshd_config.d
      register: _etc_ssh_sshd_config_d_exists

    - name: Check if the parameter PermitRootLogin is present in /etc/ssh/sshd_config.d
      ansible.builtin.find:
        paths: /etc/ssh/sshd_config.d
        recurse: 'yes'
        follow: 'no'
        contains: (?i)^\s*{{ "PermitRootLogin"| regex_escape }}\s+
      register: _etc_ssh_sshd_config_d_has_parameter
      when: _etc_ssh_sshd_config_d_exists.stat.isdir is defined and _etc_ssh_sshd_config_d_exists.stat.isdir

    - name: Remove parameter from files in /etc/ssh/sshd_config.d
      ansible.builtin.lineinfile:
        path: '{{ item.path }}'
        create: false
        regexp: (?i)(?i)^\s*{{ "PermitRootLogin"| regex_escape }}\s+
        state: absent
      with_items: '{{ _etc_ssh_sshd_config_d_has_parameter.files }}'
      when: _etc_ssh_sshd_config_d_has_parameter.matched > 0

    - name: Insert correct line to /etc/ssh/sshd_config.d/00-complianceascode-hardening.conf
      ansible.builtin.lineinfile:
        path: /etc/ssh/sshd_config.d/00-complianceascode-hardening.conf
        create: true
        regexp: (?i)(?i)^\s*{{ "PermitRootLogin"| regex_escape }}\s+
        line: PermitRootLogin no
        state: present
        insertbefore: BOF
        validate: /usr/sbin/sshd -t -f %s
    when:
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - _sshd_config_correctly.matched == 0 or _sshd_config_has_parameter.matched !=
      1
    tags:
    - CJIS-5.5.6
    - DISA-STIG-OL09-00-002345
    - NIST-800-171-3.1.1
    - NIST-800-171-3.1.5
    - NIST-800-53-AC-17(a)
    - NIST-800-53-AC-6(2)
    - NIST-800-53-CM-6(a)
    - NIST-800-53-CM-7(a)
    - NIST-800-53-CM-7(b)
    - NIST-800-53-IA-2
    - NIST-800-53-IA-2(5)
    - PCI-DSS-Req-2.2.4
    - PCI-DSSv4-2.2
    - PCI-DSSv4-2.2.6
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy
    - sshd_disable_root_login

  - name: Disable SSH Root Login - set file mode for /etc/ssh/sshd_config.d/00-complianceascode-hardening.conf
    ansible.builtin.file:
      path: /etc/ssh/sshd_config.d/00-complianceascode-hardening.conf
      mode: '0600'
      state: touch
      modification_time: preserve
      access_time: preserve
    when: ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - CJIS-5.5.6
    - DISA-STIG-OL09-00-002345
    - NIST-800-171-3.1.1
    - NIST-800-171-3.1.5
    - NIST-800-53-AC-17(a)
    - NIST-800-53-AC-6(2)
    - NIST-800-53-CM-6(a)
    - NIST-800-53-CM-7(a)
    - NIST-800-53-CM-7(b)
    - NIST-800-53-IA-2
    - NIST-800-53-IA-2(5)
    - PCI-DSS-Req-2.2.4
    - PCI-DSSv4-2.2
    - PCI-DSSv4-2.2.6
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy
    - sshd_disable_root_login

  - name: Configure PAM in SSSD Services - Find all the conf files inside the /etc/sssd/conf.d/
      directory
    ansible.builtin.find:
      paths:
      - /etc/sssd/conf.d/
      patterns: '*.conf'
    register: sssd_conf_d_files
    when: '"sssd-common" in ansible_facts.packages'
    tags:
    - NIST-800-53-CM-6(a)
    - NIST-800-53-IA-2(1)
    - configure_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - no_reboot_needed
    - sssd_enable_pam_services

  - name: Configure PAM in SSSD Services - Modify lines in files in the /etc/sssd/conf.d/
      directory
    ansible.builtin.replace:
      path: '{{ item }}'
      regexp: ^(\s*\[sssd\].*(?:\n\s*[^[\s].*)*\n\s*services\s*=(?!.*\bpam\b).*)$
      replace: \1,pam
    with_items: '{{ sssd_conf_d_files.files | map(attribute=''path'') }}'
    register: modify_lines_sssd_conf_d_files
    when:
    - '"sssd-common" in ansible_facts.packages'
    - sssd_conf_d_files.matched is defined and sssd_conf_d_files.matched >= 1
    tags:
    - NIST-800-53-CM-6(a)
    - NIST-800-53-IA-2(1)
    - configure_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - no_reboot_needed
    - sssd_enable_pam_services

  - name: Configure PAM in SSSD Services - Find /etc/sssd/sssd.conf
    ansible.builtin.stat:
      path: /etc/sssd/sssd.conf
    register: sssd_conf_file
    when: '"sssd-common" in ansible_facts.packages'
    tags:
    - NIST-800-53-CM-6(a)
    - NIST-800-53-IA-2(1)
    - configure_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - no_reboot_needed
    - sssd_enable_pam_services

  - name: Configure PAM in SSSD Services - Modify lines in /etc/sssd/sssd.conf
    ansible.builtin.replace:
      path: /etc/sssd/sssd.conf
      regexp: ^(\s*\[sssd\].*(?:\n\s*[^[\s].*)*\n\s*services\s*=(?!.*\bpam\b).*)$
      replace: \1,pam
    register: modify_lines_sssd_conf_file
    when:
    - '"sssd-common" in ansible_facts.packages'
    - sssd_conf_file.stat.exists
    tags:
    - NIST-800-53-CM-6(a)
    - NIST-800-53-IA-2(1)
    - configure_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - no_reboot_needed
    - sssd_enable_pam_services

  - name: Configure PAM in SSSD Services - Find services key in /etc/sssd/sssd.conf
    ansible.builtin.replace:
      path: /etc/sssd/sssd.conf
      regexp: ^\s*\[sssd\][^\[\]]*?(?:\n(?!\[)[^\n]*?services\s*=)+
      replace: ''
    changed_when: false
    check_mode: true
    register: sssd_conf_file_services
    when:
    - '"sssd-common" in ansible_facts.packages'
    - sssd_conf_file.stat.exists
    tags:
    - NIST-800-53-CM-6(a)
    - NIST-800-53-IA-2(1)
    - configure_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - no_reboot_needed
    - sssd_enable_pam_services

  - name: Configure PAM in SSSD Services - Insert entry to /etc/sssd/sssd.conf
    community.general.ini_file:
      path: /etc/sssd/sssd.conf
      section: sssd
      option: services
      value: pam
    when:
    - '"sssd-common" in ansible_facts.packages'
    - not modify_lines_sssd_conf_d_files.changed
    - not modify_lines_sssd_conf_file.changed
    - (sssd_conf_file_services.msg is defined and "replacements" not in sssd_conf_file_services.msg)
      or not sssd_conf_file.stat.exists
    tags:
    - NIST-800-53-CM-6(a)
    - NIST-800-53-IA-2(1)
    - configure_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - no_reboot_needed
    - sssd_enable_pam_services

  - name: Test for id_provider different than Active Directory (ad)
    ansible.builtin.command: grep -qzosP '[[:space:]]*\[domain\/[^]]*]([^(\n)]*(\n)+)+?[[:space:]]*id_provider[[:space:]]*=[[:space:]]*((?i)ad)[[:space:]]*$'
      /etc/sssd/sssd.conf
    register: test_id_provider
    failed_when: false
    changed_when: false
    check_mode: false
    when:
    - '"sssd-common" in ansible_facts.packages'
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - NIST-800-53-CM-6(a)
    - NIST-800-53-SC-12(3)
    - low_complexity
    - medium_disruption
    - medium_severity
    - no_reboot_needed
    - sssd_ldap_configure_tls_reqcert
    - unknown_strategy

  - name: Test for domain group
    ansible.builtin.command: grep '\s*\[domain\/[^]]*]' /etc/sssd/sssd.conf
    register: test_grep_domain
    failed_when: false
    changed_when: false
    check_mode: false
    when:
    - '"sssd-common" in ansible_facts.packages'
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - NIST-800-53-CM-6(a)
    - NIST-800-53-SC-12(3)
    - low_complexity
    - medium_disruption
    - medium_severity
    - no_reboot_needed
    - sssd_ldap_configure_tls_reqcert
    - unknown_strategy

  - name: Add default domain group and set ldap_tls_reqcert in sssd configuration
      (if no domain there)
    community.general.ini_file:
      path: /etc/sssd/sssd.conf
      section: '{{ item.section }}'
      option: '{{ item.option }}'
      value: '{{ item.value }}'
      mode: 384
    with_items:
    - section: sssd
      option: domains
      value: default
    - section: domain/default
      option: ldap_tls_reqcert
      value: demand
    when:
    - '"sssd-common" in ansible_facts.packages'
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - test_grep_domain.stdout is defined
    - test_grep_domain.stdout | length < 1
    - test_id_provider.stdout is defined
    - test_id_provider.stdout | length < 1
    tags:
    - NIST-800-53-CM-6(a)
    - NIST-800-53-SC-12(3)
    - low_complexity
    - medium_disruption
    - medium_severity
    - no_reboot_needed
    - sssd_ldap_configure_tls_reqcert
    - unknown_strategy

  - name: Set ldap_tls_reqcert in sssd configuration
    community.general.ini_file:
      path: /etc/sssd/sssd.conf
      section: '{{ test_grep_domain.stdout | regex_replace(''\[(.*)\]'',''\1'') }}'
      option: ldap_tls_reqcert
      value: demand
      mode: 384
    when:
    - '"sssd-common" in ansible_facts.packages'
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - test_grep_domain.stdout is defined
    - test_grep_domain.stdout | length > 0
    - test_id_provider.stdout is defined
    - test_id_provider.stdout | length < 1
    tags:
    - NIST-800-53-CM-6(a)
    - NIST-800-53-SC-12(3)
    - low_complexity
    - medium_disruption
    - medium_severity
    - no_reboot_needed
    - sssd_ldap_configure_tls_reqcert
    - unknown_strategy

  - name: Find all the conf files inside /etc/sssd/conf.d/
    ansible.builtin.find:
      paths: /etc/sssd/conf.d/
      patterns: '*.conf'
    register: sssd_conf_d_files
    when:
    - '"sssd-common" in ansible_facts.packages'
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - NIST-800-53-CM-6(a)
    - NIST-800-53-SC-12(3)
    - low_complexity
    - medium_disruption
    - medium_severity
    - no_reboot_needed
    - sssd_ldap_configure_tls_reqcert
    - unknown_strategy

  - name: Set ldap_tls_reqcert to demand in /etc/sssd/conf.d/ if exists
    ansible.builtin.replace:
      path: '{{ item.path }}'
      regexp: '[^#]*ldap_tls_reqcert.*'
      replace: ldap_tls_reqcert = demand
    with_items: '{{ sssd_conf_d_files.files }}'
    when:
    - '"sssd-common" in ansible_facts.packages'
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - NIST-800-53-CM-6(a)
    - NIST-800-53-SC-12(3)
    - low_complexity
    - medium_disruption
    - medium_severity
    - no_reboot_needed
    - sssd_ldap_configure_tls_reqcert
    - unknown_strategy

  - name: Test for id_provider different than Active Directory (ad)
    ansible.builtin.command: grep -qzosP '[[:space:]]*\[domain\/[^]]*]([^(\n)]*(\n)+)+?[[:space:]]*id_provider[[:space:]]*=[[:space:]]*((?i)ad)[[:space:]]*$'
      /etc/sssd/sssd.conf
    register: test_id_provider
    failed_when: false
    changed_when: false
    check_mode: false
    when:
    - '"sssd-common" in ansible_facts.packages'
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - NIST-800-53-CM-6(a)
    - NIST-800-53-CM-7(a)
    - NIST-800-53-CM-7(b)
    - high_severity
    - low_complexity
    - medium_disruption
    - no_reboot_needed
    - sssd_ldap_start_tls
    - unknown_strategy

  - name: Test for domain group
    ansible.builtin.command: grep '\s*\[domain\/[^]]*]' /etc/sssd/sssd.conf
    register: test_grep_domain
    failed_when: false
    changed_when: false
    check_mode: false
    when:
    - '"sssd-common" in ansible_facts.packages'
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - NIST-800-53-CM-6(a)
    - NIST-800-53-CM-7(a)
    - NIST-800-53-CM-7(b)
    - high_severity
    - low_complexity
    - medium_disruption
    - no_reboot_needed
    - sssd_ldap_start_tls
    - unknown_strategy

  - name: Add default domain group and set ldap_id_use_start_tls in sssd configuration
      (if no domain there)
    community.general.ini_file:
      path: /etc/sssd/sssd.conf
      section: '{{ item.section }}'
      option: '{{ item.option }}'
      value: '{{ item.value }}'
      mode: 384
    with_items:
    - section: sssd
      option: domains
      value: default
    - section: domain/default
      option: ldap_id_use_start_tls
      value: 'true'
    when:
    - '"sssd-common" in ansible_facts.packages'
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - test_grep_domain.stdout is defined
    - test_grep_domain.stdout | length < 1
    - test_id_provider.stdout is defined
    - test_id_provider.stdout | length < 1
    tags:
    - NIST-800-53-CM-6(a)
    - NIST-800-53-CM-7(a)
    - NIST-800-53-CM-7(b)
    - high_severity
    - low_complexity
    - medium_disruption
    - no_reboot_needed
    - sssd_ldap_start_tls
    - unknown_strategy

  - name: Set ldap_id_use_start_tls in sssd configuration
    community.general.ini_file:
      path: /etc/sssd/sssd.conf
      section: '{{ test_grep_domain.stdout | regex_replace(''\[(.*)\]'',''\1'') }}'
      option: ldap_id_use_start_tls
      value: 'true'
      mode: 384
    when:
    - '"sssd-common" in ansible_facts.packages'
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    - test_grep_domain.stdout is defined
    - test_grep_domain.stdout | length > 0
    - test_id_provider.stdout is defined
    - test_id_provider.stdout | length < 1
    tags:
    - NIST-800-53-CM-6(a)
    - NIST-800-53-CM-7(a)
    - NIST-800-53-CM-7(b)
    - high_severity
    - low_complexity
    - medium_disruption
    - no_reboot_needed
    - sssd_ldap_start_tls
    - unknown_strategy

  - name: Find all the conf files inside /etc/sssd/conf.d/
    ansible.builtin.find:
      paths: /etc/sssd/conf.d/
      patterns: '*.conf'
    register: sssd_conf_d_files
    when:
    - '"sssd-common" in ansible_facts.packages'
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - NIST-800-53-CM-6(a)
    - NIST-800-53-CM-7(a)
    - NIST-800-53-CM-7(b)
    - high_severity
    - low_complexity
    - medium_disruption
    - no_reboot_needed
    - sssd_ldap_start_tls
    - unknown_strategy

  - name: Set ldap_id_use_start_tls to true in /etc/sssd/conf.d/ if exists
    ansible.builtin.replace:
      path: '{{ item.path }}'
      regexp: '[^#]*ldap_id_use_start_tls.*'
      replace: ldap_id_use_start_tls = true
    with_items: '{{ sssd_conf_d_files.files }}'
    when:
    - '"sssd-common" in ansible_facts.packages'
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - NIST-800-53-CM-6(a)
    - NIST-800-53-CM-7(a)
    - NIST-800-53-CM-7(b)
    - high_severity
    - low_complexity
    - medium_disruption
    - no_reboot_needed
    - sssd_ldap_start_tls
    - unknown_strategy

  - name: Ensure auditd Collects Information on the Use of Privileged Commands - sudo
      - Perform remediation of Audit rules for /usr/bin/sudo
    block:

    - name: Declare list of syscalls
      ansible.builtin.set_fact:
        syscalls: []
        syscall_grouping: []

    - name: Check existence of  in /etc/audit/rules.d/
      ansible.builtin.find:
        paths: /etc/audit/rules.d
        contains: -a always,exit(( -S |,)\w+)*(( -S |,){{ item }})+(( -S |,)\w+)*
          -F path=/usr/bin/sudo -F perm=x -F auid>=1000 -F auid!=unset (-k\s+|-F\s+key=)\S+\s*$
        patterns: '*.rules'
      register: find_command
      loop: '{{ (syscall_grouping + syscalls) | unique }}'

    - name: Reset syscalls found per file
      ansible.builtin.set_fact:
        syscalls_per_file: {}
        found_paths_dict: {}

    - name: Declare syscalls found per file
      ansible.builtin.set_fact: syscalls_per_file="{{ syscalls_per_file | combine(
        {item.files[0].path :[item.item] + syscalls_per_file.get(item.files[0].path,
        []) } ) }}"
      loop: '{{ find_command.results | selectattr(''matched'') | list }}'

    - name: Declare files where syscalls were found
      ansible.builtin.set_fact: found_paths="{{ find_command.results | map(attribute='files')
        | flatten | map(attribute='path') | list }}"

    - name: Count occurrences of syscalls in paths
      ansible.builtin.set_fact: found_paths_dict="{{ found_paths_dict | combine({
        item:1+found_paths_dict.get(item, 0) }) }}"
      loop: '{{ find_command.results | map(attribute=''files'') | flatten | map(attribute=''path'')
        | list }}'

    - name: Get path with most syscalls
      ansible.builtin.set_fact: audit_file="{{ (found_paths_dict | dict2items() |
        sort(attribute='value') | last).key }}"
      when: found_paths | length >= 1

    - name: No file with syscall found, set path to /etc/audit/rules.d/privileged.rules
      ansible.builtin.set_fact: audit_file="/etc/audit/rules.d/privileged.rules"
      when: found_paths | length == 0

    - name: Declare found syscalls
      ansible.builtin.set_fact: syscalls_found="{{ find_command.results | selectattr('matched')
        | map(attribute='item') | list }}"

    - name: Declare missing syscalls
      ansible.builtin.set_fact: missing_syscalls="{{ syscalls | difference(syscalls_found)
        }}"

    - name: Replace the audit rule in {{ audit_file }}
      ansible.builtin.lineinfile:
        path: '{{ audit_file }}'
        regexp: (-a always,exit)(?=.*(?:(?:-S |,)(?:{{ syscalls_per_file[audit_file]
          | join("|") }}))\b)((?:( -S |,)\w+)+)( -F path=/usr/bin/sudo -F perm=x -F
          auid>=1000 -F auid!=unset (?:-k |-F key=)\w+)
        line: \1\2\3{{ missing_syscalls | join("\3") }}\4
        backrefs: true
        state: present
        mode: g-rwx,o-rwx
      when: syscalls_found | length > 0 and missing_syscalls | length > 0

    - name: Add the audit rule to {{ audit_file }}
      ansible.builtin.lineinfile:
        path: '{{ audit_file }}'
        line: -a always,exit{{ syscalls | join(',') }} -F path=/usr/bin/sudo -F perm=x
          -F auid>=1000 -F auid!=unset -F key=privileged
        create: true
        mode: g-rwx,o-rwx
        state: present
      when: syscalls_found | length == 0

    - name: Declare list of syscalls
      ansible.builtin.set_fact:
        syscalls: []
        syscall_grouping: []

    - name: Check existence of  in /etc/audit/audit.rules
      ansible.builtin.find:
        paths: /etc/audit
        contains: -a always,exit(( -S |,)\w+)*(( -S |,){{ item }})+(( -S |,)\w+)*
          -F path=/usr/bin/sudo -F perm=x -F auid>=1000 -F auid!=unset (-k\s+|-F\s+key=)\S+\s*$
        patterns: audit.rules
      register: find_command
      loop: '{{ (syscall_grouping + syscalls) | unique }}'

    - name: Set path to /etc/audit/audit.rules
      ansible.builtin.set_fact: audit_file="/etc/audit/audit.rules"

    - name: Declare found syscalls
      ansible.builtin.set_fact: syscalls_found="{{ find_command.results | selectattr('matched')
        | map(attribute='item') | list }}"

    - name: Declare missing syscalls
      ansible.builtin.set_fact: missing_syscalls="{{ syscalls | difference(syscalls_found)
        }}"

    - name: Replace the audit rule in {{ audit_file }}
      ansible.builtin.lineinfile:
        path: '{{ audit_file }}'
        regexp: (-a always,exit)(?=.*(?:(?:-S |,)(?:{{ syscalls_found | join("|")
          }}))\b)((?:( -S |,)\w+)+)( -F path=/usr/bin/sudo -F perm=x -F auid>=1000
          -F auid!=unset (?:-k |-F key=)\w+)
        line: \1\2\3{{ missing_syscalls | join("\3") }}\4
        backrefs: true
        state: present
        mode: g-rwx,o-rwx
      when: syscalls_found | length > 0 and missing_syscalls | length > 0

    - name: Add the audit rule to {{ audit_file }}
      ansible.builtin.lineinfile:
        path: '{{ audit_file }}'
        line: -a always,exit{{ syscalls | join(',') }} -F path=/usr/bin/sudo -F perm=x
          -F auid>=1000 -F auid!=unset -F key=privileged
        create: true
        mode: g-rwx,o-rwx
        state: present
      when: syscalls_found | length == 0
    when:
    - '"audit" in ansible_facts.packages'
    - ("kernel" in ansible_facts.packages or "kernel-uek" in ansible_facts.packages)
    tags:
    - DISA-STIG-OL09-00-000670
    - NIST-800-171-3.1.7
    - NIST-800-53-AC-6(9)
    - NIST-800-53-AU-12(c)
    - NIST-800-53-AU-2(d)
    - NIST-800-53-CM-6(a)
    - audit_rules_privileged_commands_sudo
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy

Youez - 2016 - github.com/yon3zu
LinuXploit