---
###############################################################################
#
# Ansible Playbook for Standard System Security Profile for Ubuntu 22.04
#
# Profile Description:
# This profile contains rules to ensure standard security baseline of an Ubuntu 22.04 system. Regardless of your system's workload all of these checks should pass.
#
# Profile ID:  xccdf_org.ssgproject.content_profile_standard
# Benchmark ID:  xccdf_org.ssgproject.content_benchmark_UBUNTU_22-04
# 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_standard --fix-type ansible ssg-ubuntu2204-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_standard
  hosts: all
  vars:
    var_timesync_service: systemd-timesyncd
    var_sshd_set_keepalive: '0'
    sshd_idle_timeout_value: '300'
  tasks:

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

  - name: Ensure rsyslog is installed
    ansible.builtin.package:
      name: rsyslog
      state: present
    when: '"linux-base" in ansible_facts.packages'
    tags:
    - NIST-800-53-CM-6(a)
    - enable_strategy
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - package_rsyslog_installed

  - name: Ensure cron is installed
    ansible.builtin.package:
      name: cron
      state: present
    when: '"linux-base" in ansible_facts.packages'
    tags:
    - NIST-800-53-CM-6(a)
    - PCI-DSSv4-2.2
    - PCI-DSSv4-2.2.6
    - enable_strategy
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - package_cron_installed

  - name: 'Uninstall the inet-based telnet server: Ensure inetutils-telnetd is removed'
    ansible.builtin.package:
      name: inetutils-telnetd
      state: absent
    tags:
    - NIST-800-53-CM-6(a)
    - NIST-800-53-CM-7(a)
    - NIST-800-53-CM-7(b)
    - disable_strategy
    - high_severity
    - low_complexity
    - low_disruption
    - no_reboot_needed
    - package_inetutils-telnetd_removed

  - name: 'Uninstall the nis package: Ensure nis is removed'
    ansible.builtin.package:
      name: nis
      state: absent
    tags:
    - disable_strategy
    - low_complexity
    - low_disruption
    - low_severity
    - no_reboot_needed
    - package_nis_removed

  - name: 'Uninstall the ntpdate package: Ensure ntpdate is removed'
    ansible.builtin.package:
      name: ntpdate
      state: absent
    tags:
    - disable_strategy
    - low_complexity
    - low_disruption
    - low_severity
    - no_reboot_needed
    - package_ntpdate_removed

  - name: 'Uninstall the ssl compliant telnet server: Ensure telnetd-ssl is removed'
    ansible.builtin.package:
      name: telnetd-ssl
      state: absent
    tags:
    - NIST-800-53-CM-6(a)
    - NIST-800-53-CM-7(a)
    - NIST-800-53-CM-7(b)
    - disable_strategy
    - high_severity
    - low_complexity
    - low_disruption
    - no_reboot_needed
    - package_telnetd-ssl_removed

  - name: 'Uninstall the telnet server: Ensure telnetd is removed'
    ansible.builtin.package:
      name: telnetd
      state: absent
    tags:
    - DISA-STIG-UBTU-22-215035
    - NIST-800-53-CM-6(a)
    - NIST-800-53-CM-7(a)
    - NIST-800-53-CM-7(b)
    - disable_strategy
    - high_severity
    - low_complexity
    - low_disruption
    - no_reboot_needed
    - package_telnetd_removed

  - name: Ensure systemd-timesyncd is installed
    ansible.builtin.package:
      name: systemd-timesyncd
      state: present
    when:
    - '"linux-base" in ansible_facts.packages'
    - var_timesync_service == "systemd-timesyncd"
    tags:
    - NIST-800-53-CM-6(a)
    - PCI-DSS-Req-10.4
    - enable_strategy
    - high_severity
    - low_complexity
    - low_disruption
    - no_reboot_needed
    - package_timesyncd_installed

  - name: Ensure auditd is installed
    ansible.builtin.package:
      name: auditd
      state: present
    when: '"linux-base" in ansible_facts.packages'
    tags:
    - DISA-STIG-UBTU-22-653010
    - 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 rsyslog Service - Enable service rsyslog
    block:

    - name: Enable rsyslog Service - Enable Service rsyslog
      ansible.builtin.systemd:
        name: rsyslog
        enabled: true
        state: started
        masked: false
      when:
      - '"rsyslog" in ansible_facts.packages'
    tags:
    - DISA-STIG-UBTU-22-652010
    - NIST-800-53-AU-4(1)
    - NIST-800-53-CM-6(a)
    - enable_strategy
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - service_rsyslog_enabled
    - special_service_block
    when: '"linux-base" in ansible_facts.packages'

  - name: Disable Apport Service - Disable service apport
    block:

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

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

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

    - name: Disable Apport Service - Disable Socket apport
      ansible.builtin.systemd:
        name: apport.socket
        enabled: false
        state: stopped
        masked: true
      when: socket_file_exists.stdout_lines is search("apport.socket", multiline=True)
    tags:
    - disable_strategy
    - low_complexity
    - low_disruption
    - no_reboot_needed
    - service_apport_disabled
    - special_service_block
    - unknown_severity
    when: '"apport" in ansible_facts.packages'

  - name: Enable cron Service - Enable service cron
    block:

    - name: Enable cron Service - Enable Service cron
      ansible.builtin.systemd:
        name: cron
        enabled: true
        state: started
        masked: false
      when:
      - '"cron" in ansible_facts.packages'
    tags:
    - NIST-800-53-CM-6(a)
    - enable_strategy
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - service_cron_enabled
    - special_service_block
    when: '"linux-base" 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:
      - '"auditd" in ansible_facts.packages'
    tags:
    - CJIS-5.4.1.1
    - DISA-STIG-UBTU-22-653015
    - 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:
    - '"linux-base" in ansible_facts.packages'
    - '"auditd" in ansible_facts.packages'

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

  - name: Configure daily log rotation in /etc/logrotate.conf
    ansible.builtin.lineinfile:
      create: true
      dest: /etc/logrotate.conf
      regexp: ^\s*(weekly|monthly|yearly)$
      line: daily
      state: present
      insertbefore: BOF
    when:
    - '"linux-base" in ansible_facts.packages'
    - '"logrotate" in ansible_facts.packages'
    tags:
    - NIST-800-53-CM-6(a)
    - PCI-DSS-Req-10.7
    - configure_strategy
    - ensure_logrotate_activated
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

  - name: Make sure daily log rotation setting is not overridden in /etc/logrotate.conf
    ansible.builtin.lineinfile:
      create: false
      dest: /etc/logrotate.conf
      regexp: ^[\s]*(weekly|monthly|yearly)$
      state: absent
    when:
    - '"linux-base" in ansible_facts.packages'
    - '"logrotate" in ansible_facts.packages'
    tags:
    - NIST-800-53-CM-6(a)
    - PCI-DSS-Req-10.7
    - configure_strategy
    - ensure_logrotate_activated
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

  - name: Configure cron.daily if not already
    block:

    - name: Add shebang
      ansible.builtin.lineinfile:
        path: /etc/cron.daily/logrotate
        line: '#!/bin/sh'
        insertbefore: BOF
        create: true

    - name: Add logrotate call
      ansible.builtin.lineinfile:
        path: /etc/cron.daily/logrotate
        line: /usr/sbin/logrotate /etc/logrotate.conf
        regexp: ^[\s]*/usr/sbin/logrotate[\s\S]*/etc/logrotate.conf$
        create: true
    when:
    - '"linux-base" in ansible_facts.packages'
    - '"logrotate" in ansible_facts.packages'
    tags:
    - NIST-800-53-CM-6(a)
    - PCI-DSS-Req-10.7
    - configure_strategy
    - ensure_logrotate_activated
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

  - name: Find /boot/ file(s)
    ansible.builtin.command: find -P /boot/ -maxdepth 1 -perm /u+xs,g+xwrs,o+xwrt  -type
      f -regextype posix-extended -regex "^.*System\.map.*$"
    register: files_found
    changed_when: false
    failed_when: false
    check_mode: false
    when: '"linux-base" in ansible_facts.packages'
    tags:
    - configure_strategy
    - file_permissions_systemmap
    - low_complexity
    - low_disruption
    - low_severity
    - no_reboot_needed

  - name: Set permissions for /boot/ file(s)
    ansible.builtin.file:
      path: '{{ item }}'
      mode: u-xs,g-xwrs,o-xwrt
      state: file
    with_items:
    - '{{ files_found.stdout_lines }}'
    when: '"linux-base" in ansible_facts.packages'
    tags:
    - configure_strategy
    - file_permissions_systemmap
    - low_complexity
    - low_disruption
    - low_severity
    - no_reboot_needed

  - 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: '"linux-base" in ansible_facts.packages'
    tags:
    - NIST-800-53-AC-6(1)
    - NIST-800-53-CM-6(a)
    - disable_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - reboot_required
    - sysctl_fs_protected_hardlinks

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

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

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

  - name: Enable Kernel Parameter to Enforce DAC on Hardlinks - Comment out any occurrences
      of fs.protected_hardlinks from /etc/ufw/sysctl.conf
    ansible.builtin.replace:
      path: /etc/ufw/sysctl.conf
      regexp: (^[\s]*fs.protected_hardlinks.*$)
      replace: '# \1'
    when: '"linux-base" in ansible_facts.packages'
    tags:
    - NIST-800-53-AC-6(1)
    - NIST-800-53-CM-6(a)
    - disable_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - reboot_required
    - sysctl_fs_protected_hardlinks

  - name: Enable Kernel Parameter to Enforce DAC on Hardlinks - Ensure sysctl fs.protected_hardlinks
      is set to 1
    ansible.posix.sysctl:
      name: fs.protected_hardlinks
      value: '1'
      sysctl_file: /etc/sysctl.conf
      state: present
      reload: true
    when: '"linux-base" in ansible_facts.packages'
    tags:
    - NIST-800-53-AC-6(1)
    - NIST-800-53-CM-6(a)
    - disable_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - reboot_required
    - sysctl_fs_protected_hardlinks

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

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

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

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

  - name: Enable Kernel Parameter to Enforce DAC on Symlinks - Comment out any occurrences
      of fs.protected_symlinks from /etc/ufw/sysctl.conf
    ansible.builtin.replace:
      path: /etc/ufw/sysctl.conf
      regexp: (^[\s]*fs.protected_symlinks.*$)
      replace: '# \1'
    when: '"linux-base" in ansible_facts.packages'
    tags:
    - NIST-800-53-AC-6(1)
    - NIST-800-53-CM-6(a)
    - disable_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - reboot_required
    - sysctl_fs_protected_symlinks

  - name: Enable Kernel Parameter to Enforce DAC on Symlinks - Ensure sysctl fs.protected_symlinks
      is set to 1
    ansible.posix.sysctl:
      name: fs.protected_symlinks
      value: '1'
      sysctl_file: /etc/sysctl.conf
      state: present
      reload: true
    when: '"linux-base" in ansible_facts.packages'
    tags:
    - NIST-800-53-AC-6(1)
    - NIST-800-53-CM-6(a)
    - disable_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - reboot_required
    - sysctl_fs_protected_symlinks

  - name: 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
    - 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
    - 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
    - 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: '42'
    tags:
    - 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:
    - 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:
    - 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
    - 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
    - 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
    - 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: '42'
    tags:
    - CJIS-5.5.2.2
    - 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
    - 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
    - NIST-800-53-AC-6(1)
    - NIST-800-53-CM-6(a)
    - PCI-DSS-Req-8.7.c
    - PCI-DSSv4-2.2
    - PCI-DSSv4-2.2.6
    - configure_strategy
    - file_groupowner_etc_shadow
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

  - name: Set the file_owner_etc_group_newown variable if represented by uid
    ansible.builtin.set_fact:
      file_owner_etc_group_newown: '0'
    tags:
    - CJIS-5.5.2.2
    - 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
    - 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
    - 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:
    - 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:
    - 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:
    - 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
    - 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
    - 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
    - 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
    - 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
    - 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
    - NIST-800-53-AC-6(1)
    - NIST-800-53-CM-6(a)
    - PCI-DSS-Req-8.7.c
    - PCI-DSSv4-2.2
    - PCI-DSSv4-2.2.6
    - configure_strategy
    - file_owner_etc_shadow
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed

  - name: Test for existence /etc/group
    ansible.builtin.stat:
      path: /etc/group
    register: file_exists
    tags:
    - CJIS-5.5.2.2
    - 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
    - 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:
    - 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-xs,g-xws,o-xwrt on /etc/gshadow
    ansible.builtin.file:
      path: /etc/gshadow
      mode: u-xs,g-xws,o-xwrt
    when: file_exists.stat is defined and file_exists.stat.exists
    tags:
    - 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
    - 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
    - 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
    - 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-xs,g-xws,o-xwrt on /etc/shadow
    ansible.builtin.file:
      path: /etc/shadow
      mode: u-xs,g-xws,o-xwrt
    when: file_exists.stat is defined and file_exists.stat.exists
    tags:
    - CJIS-5.5.2.2
    - 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: 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: '"linux-base" 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: '"linux-base" 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: '"linux-base" 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:
    - '"linux-base" 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/ufw/sysctl.conf
    ansible.builtin.replace:
      path: /etc/ufw/sysctl.conf
      regexp: (^[\s]*fs.suid_dumpable.*$)
      replace: '# \1'
    when: '"linux-base" 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.conf
      state: present
      reload: true
    when: '"linux-base" in ansible_facts.packages'
    tags:
    - NIST-800-53-SI-11(a)
    - NIST-800-53-SI-11(b)
    - PCI-DSSv4-3.3
    - PCI-DSSv4-3.3.1
    - PCI-DSSv4-3.3.1.1
    - disable_strategy
    - low_complexity
    - medium_disruption
    - medium_severity
    - reboot_required
    - sysctl_fs_suid_dumpable

  - name: Enable Randomized Layout of Virtual Address Space - Set fact for sysctl
      paths
    ansible.builtin.set_fact:
      sysctl_paths:
      - /etc/sysctl.d/
      - /run/sysctl.d/
      - /usr/local/lib/sysctl.d/
    when: '"linux-base" in ansible_facts.packages'
    tags:
    - DISA-STIG-UBTU-22-213020
    - 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: '"linux-base" in ansible_facts.packages'
    tags:
    - DISA-STIG-UBTU-22-213020
    - 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: '"linux-base" in ansible_facts.packages'
    tags:
    - DISA-STIG-UBTU-22-213020
    - 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:
    - '"linux-base" 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-UBTU-22-213020
    - 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/ufw/sysctl.conf
    ansible.builtin.replace:
      path: /etc/ufw/sysctl.conf
      regexp: (^[\s]*kernel.randomize_va_space.*$)
      replace: '# \1'
    when: '"linux-base" in ansible_facts.packages'
    tags:
    - DISA-STIG-UBTU-22-213020
    - 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.conf
      state: present
      reload: true
    when: '"linux-base" in ansible_facts.packages'
    tags:
    - DISA-STIG-UBTU-22-213020
    - 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 service systemd-timesyncd
    block:

    - name: Enable service systemd-timesyncd
      ansible.builtin.systemd:
        name: systemd-timesyncd
        enabled: 'yes'
        state: started
        masked: 'no'
      when:
      - '"systemd-timesyncd" in ansible_facts.packages'
      - var_timesync_service == "systemd-timesyncd"
      - var_timesync_service == "systemd-timesyncd"
    when:
    - '"linux-base" in ansible_facts.packages'
    - ( not ( "chrony" in ansible_facts.packages ) and not ( "ntp" in ansible_facts.packages
      ) )
    tags:
    - NIST-800-53-AU-8(1)(a)
    - NIST-800-53-CM-6(a)
    - PCI-DSS-Req-10.4
    - PCI-DSSv4-10.6
    - PCI-DSSv4-10.6.1
    - enable_strategy
    - high_severity
    - low_complexity
    - low_disruption
    - no_reboot_needed
    - service_timesyncd_enabled

  - name: Set SSH Client Alive Count Max - Check if the parameter ClientAliveCountMax
      is configured
    ansible.builtin.find:
      paths:
      - /etc/ssh/sshd_config
      - /etc/ssh/sshd_config.d
      contains: (?i)^\s*{{ "ClientAliveCountMax"| regex_escape }}\s+
    register: _sshd_config_has_parameter
    when: '"linux-base" in ansible_facts.packages'
    tags:
    - CJIS-5.5.6
    - DISA-STIG-UBTU-22-255030
    - NIST-800-171-3.1.11
    - NIST-800-53-AC-12
    - NIST-800-53-AC-17(a)
    - NIST-800-53-AC-2(5)
    - NIST-800-53-CM-6(a)
    - NIST-800-53-SC-10
    - PCI-DSS-Req-8.1.8
    - PCI-DSSv4-8.2
    - PCI-DSSv4-8.2.8
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy
    - sshd_set_keepalive

  - name: Set SSH Client Alive Count Max - Check if the parameter ClientAliveCountMax
      is configured correctly
    ansible.builtin.find:
      paths:
      - /etc/ssh/sshd_config
      - /etc/ssh/sshd_config.d
      contains: (?i)^\s*{{ "ClientAliveCountMax"| regex_escape }}\s+{{ var_sshd_set_keepalive
        }}$
    register: _sshd_config_correctly
    when: '"linux-base" in ansible_facts.packages'
    tags:
    - CJIS-5.5.6
    - DISA-STIG-UBTU-22-255030
    - NIST-800-171-3.1.11
    - NIST-800-53-AC-12
    - NIST-800-53-AC-17(a)
    - NIST-800-53-AC-2(5)
    - NIST-800-53-CM-6(a)
    - NIST-800-53-SC-10
    - PCI-DSS-Req-8.1.8
    - PCI-DSSv4-8.2
    - PCI-DSSv4-8.2.8
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy
    - sshd_set_keepalive

  - name: Set SSH Client Alive Count Max
    block:

    - name: Deduplicate values from /etc/ssh/sshd_config
      ansible.builtin.lineinfile:
        path: /etc/ssh/sshd_config
        create: false
        regexp: (?i)(?i)^\s*{{ "ClientAliveCountMax"| regex_escape }}\s+
        state: absent

    - name: Check if /etc/ssh/sshd_config.d exists
      ansible.builtin.stat:
        path: /etc/ssh/sshd_config.d
      register: _etc_ssh_sshd_config_d_exists

    - name: Check if the parameter ClientAliveCountMax is present in /etc/ssh/sshd_config.d
      ansible.builtin.find:
        paths: /etc/ssh/sshd_config.d
        recurse: 'yes'
        follow: 'no'
        contains: (?i)^\s*{{ "ClientAliveCountMax"| regex_escape }}\s+
      register: _etc_ssh_sshd_config_d_has_parameter
      when: _etc_ssh_sshd_config_d_exists.stat.isdir is defined and _etc_ssh_sshd_config_d_exists.stat.isdir

    - name: Remove parameter from files in /etc/ssh/sshd_config.d
      ansible.builtin.lineinfile:
        path: '{{ item.path }}'
        create: false
        regexp: (?i)(?i)^\s*{{ "ClientAliveCountMax"| regex_escape }}\s+
        state: absent
      with_items: '{{ _etc_ssh_sshd_config_d_has_parameter.files }}'
      when: _etc_ssh_sshd_config_d_has_parameter.matched | bool

    - name: Insert correct line to /etc/ssh/sshd_config.d/00-complianceascode-hardening.conf
      ansible.builtin.lineinfile:
        path: /etc/ssh/sshd_config.d/00-complianceascode-hardening.conf
        create: true
        regexp: (?i)(?i)^\s*{{ "ClientAliveCountMax"| regex_escape }}\s+
        line: ClientAliveCountMax {{ var_sshd_set_keepalive }}
        state: present
        insertbefore: BOF
        validate: /usr/sbin/sshd -t -f %s
    when:
    - '"linux-base" in ansible_facts.packages'
    - _sshd_config_correctly.matched == 0 or _sshd_config_has_parameter.matched !=
      1
    tags:
    - CJIS-5.5.6
    - DISA-STIG-UBTU-22-255030
    - NIST-800-171-3.1.11
    - NIST-800-53-AC-12
    - NIST-800-53-AC-17(a)
    - NIST-800-53-AC-2(5)
    - NIST-800-53-CM-6(a)
    - NIST-800-53-SC-10
    - PCI-DSS-Req-8.1.8
    - PCI-DSSv4-8.2
    - PCI-DSSv4-8.2.8
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy
    - sshd_set_keepalive

  - name: Set SSH Client Alive Count Max - set file mode for /etc/ssh/sshd_config.d/00-complianceascode-hardening.conf
    ansible.builtin.file:
      path: /etc/ssh/sshd_config.d/00-complianceascode-hardening.conf
      mode: '0600'
      state: touch
      modification_time: preserve
      access_time: preserve
    when: '"linux-base" in ansible_facts.packages'
    tags:
    - CJIS-5.5.6
    - DISA-STIG-UBTU-22-255030
    - NIST-800-171-3.1.11
    - NIST-800-53-AC-12
    - NIST-800-53-AC-17(a)
    - NIST-800-53-AC-2(5)
    - NIST-800-53-CM-6(a)
    - NIST-800-53-SC-10
    - PCI-DSS-Req-8.1.8
    - PCI-DSSv4-8.2
    - PCI-DSSv4-8.2.8
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy
    - sshd_set_keepalive

  - name: Set SSH Client Alive Interval - Check if the parameter ClientAliveInterval
      is configured
    ansible.builtin.find:
      paths:
      - /etc/ssh/sshd_config
      - /etc/ssh/sshd_config.d
      contains: (?i)^\s*{{ "ClientAliveInterval"| regex_escape }}\s+
    register: _sshd_config_has_parameter
    when: '"linux-base" in ansible_facts.packages'
    tags:
    - CJIS-5.5.6
    - DISA-STIG-UBTU-22-255035
    - NIST-800-171-3.1.11
    - NIST-800-53-AC-12
    - NIST-800-53-AC-17(a)
    - NIST-800-53-AC-17(a)
    - NIST-800-53-AC-2(5)
    - NIST-800-53-CM-6(a)
    - NIST-800-53-CM-6(a)
    - NIST-800-53-SC-10
    - PCI-DSS-Req-8.1.8
    - PCI-DSSv4-8.2
    - PCI-DSSv4-8.2.8
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy
    - sshd_set_idle_timeout

  - name: Set SSH Client Alive Interval - Check if the parameter ClientAliveInterval
      is configured correctly
    ansible.builtin.find:
      paths:
      - /etc/ssh/sshd_config
      - /etc/ssh/sshd_config.d
      contains: (?i)^\s*{{ "ClientAliveInterval"| regex_escape }}\s+{{ sshd_idle_timeout_value
        }}$
    register: _sshd_config_correctly
    when: '"linux-base" in ansible_facts.packages'
    tags:
    - CJIS-5.5.6
    - DISA-STIG-UBTU-22-255035
    - NIST-800-171-3.1.11
    - NIST-800-53-AC-12
    - NIST-800-53-AC-17(a)
    - NIST-800-53-AC-17(a)
    - NIST-800-53-AC-2(5)
    - NIST-800-53-CM-6(a)
    - NIST-800-53-CM-6(a)
    - NIST-800-53-SC-10
    - PCI-DSS-Req-8.1.8
    - PCI-DSSv4-8.2
    - PCI-DSSv4-8.2.8
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy
    - sshd_set_idle_timeout

  - name: Set SSH Client Alive Interval
    block:

    - name: Deduplicate values from /etc/ssh/sshd_config
      ansible.builtin.lineinfile:
        path: /etc/ssh/sshd_config
        create: false
        regexp: (?i)(?i)^\s*{{ "ClientAliveInterval"| regex_escape }}\s+
        state: absent

    - name: Check if /etc/ssh/sshd_config.d exists
      ansible.builtin.stat:
        path: /etc/ssh/sshd_config.d
      register: _etc_ssh_sshd_config_d_exists

    - name: Check if the parameter ClientAliveInterval is present in /etc/ssh/sshd_config.d
      ansible.builtin.find:
        paths: /etc/ssh/sshd_config.d
        recurse: 'yes'
        follow: 'no'
        contains: (?i)^\s*{{ "ClientAliveInterval"| regex_escape }}\s+
      register: _etc_ssh_sshd_config_d_has_parameter
      when: _etc_ssh_sshd_config_d_exists.stat.isdir is defined and _etc_ssh_sshd_config_d_exists.stat.isdir

    - name: Remove parameter from files in /etc/ssh/sshd_config.d
      ansible.builtin.lineinfile:
        path: '{{ item.path }}'
        create: false
        regexp: (?i)(?i)^\s*{{ "ClientAliveInterval"| regex_escape }}\s+
        state: absent
      with_items: '{{ _etc_ssh_sshd_config_d_has_parameter.files }}'
      when: _etc_ssh_sshd_config_d_has_parameter.matched | bool

    - name: Insert correct line to /etc/ssh/sshd_config.d/00-complianceascode-hardening.conf
      ansible.builtin.lineinfile:
        path: /etc/ssh/sshd_config.d/00-complianceascode-hardening.conf
        create: true
        regexp: (?i)(?i)^\s*{{ "ClientAliveInterval"| regex_escape }}\s+
        line: ClientAliveInterval {{ sshd_idle_timeout_value }}
        state: present
        insertbefore: BOF
        validate: /usr/sbin/sshd -t -f %s
    when:
    - '"linux-base" in ansible_facts.packages'
    - _sshd_config_correctly.matched == 0 or _sshd_config_has_parameter.matched !=
      1
    tags:
    - CJIS-5.5.6
    - DISA-STIG-UBTU-22-255035
    - NIST-800-171-3.1.11
    - NIST-800-53-AC-12
    - NIST-800-53-AC-17(a)
    - NIST-800-53-AC-17(a)
    - NIST-800-53-AC-2(5)
    - NIST-800-53-CM-6(a)
    - NIST-800-53-CM-6(a)
    - NIST-800-53-SC-10
    - PCI-DSS-Req-8.1.8
    - PCI-DSSv4-8.2
    - PCI-DSSv4-8.2.8
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy
    - sshd_set_idle_timeout

  - name: Set SSH Client Alive Interval - set file mode for /etc/ssh/sshd_config.d/00-complianceascode-hardening.conf
    ansible.builtin.file:
      path: /etc/ssh/sshd_config.d/00-complianceascode-hardening.conf
      mode: '0600'
      state: touch
      modification_time: preserve
      access_time: preserve
    when: '"linux-base" in ansible_facts.packages'
    tags:
    - CJIS-5.5.6
    - DISA-STIG-UBTU-22-255035
    - NIST-800-171-3.1.11
    - NIST-800-53-AC-12
    - NIST-800-53-AC-17(a)
    - NIST-800-53-AC-17(a)
    - NIST-800-53-AC-2(5)
    - NIST-800-53-CM-6(a)
    - NIST-800-53-CM-6(a)
    - NIST-800-53-SC-10
    - PCI-DSS-Req-8.1.8
    - PCI-DSSv4-8.2
    - PCI-DSSv4-8.2.8
    - low_complexity
    - low_disruption
    - medium_severity
    - no_reboot_needed
    - restrict_strategy
    - sshd_set_idle_timeout

  - name: Disable SSH Access via Empty Passwords - Check if the parameter PermitEmptyPasswords
      is configured
    ansible.builtin.find:
      paths:
      - /etc/ssh/sshd_config
      - /etc/ssh/sshd_config.d
      contains: (?i)^\s*{{ "PermitEmptyPasswords"| regex_escape }}\s+
    register: _sshd_config_has_parameter
    when: '"linux-base" in ansible_facts.packages'
    tags:
    - CJIS-5.5.6
    - DISA-STIG-UBTU-22-255025
    - NIST-800-171-3.1.1
    - NIST-800-171-3.1.5
    - NIST-800-53-AC-17(a)
    - NIST-800-53-CM-6(a)
    - NIST-800-53-CM-7(a)
    - NIST-800-53-CM-7(b)
    - PCI-DSS-Req-2.2.4
    - PCI-DSSv4-2.2
    - PCI-DSSv4-2.2.6
    - high_severity
    - low_complexity
    - low_disruption
    - no_reboot_needed
    - restrict_strategy
    - sshd_disable_empty_passwords

  - name: Disable SSH Access via Empty Passwords - Check if the parameter PermitEmptyPasswords
      is configured correctly
    ansible.builtin.find:
      paths:
      - /etc/ssh/sshd_config
      - /etc/ssh/sshd_config.d
      contains: (?i)^\s*{{ "PermitEmptyPasswords"| regex_escape }}\s+no$
    register: _sshd_config_correctly
    when: '"linux-base" in ansible_facts.packages'
    tags:
    - CJIS-5.5.6
    - DISA-STIG-UBTU-22-255025
    - NIST-800-171-3.1.1
    - NIST-800-171-3.1.5
    - NIST-800-53-AC-17(a)
    - NIST-800-53-CM-6(a)
    - NIST-800-53-CM-7(a)
    - NIST-800-53-CM-7(b)
    - PCI-DSS-Req-2.2.4
    - PCI-DSSv4-2.2
    - PCI-DSSv4-2.2.6
    - high_severity
    - low_complexity
    - low_disruption
    - no_reboot_needed
    - restrict_strategy
    - sshd_disable_empty_passwords

  - name: Disable SSH Access via Empty Passwords
    block:

    - name: Deduplicate values from /etc/ssh/sshd_config
      ansible.builtin.lineinfile:
        path: /etc/ssh/sshd_config
        create: false
        regexp: (?i)(?i)^\s*{{ "PermitEmptyPasswords"| regex_escape }}\s+
        state: absent

    - name: Check if /etc/ssh/sshd_config.d exists
      ansible.builtin.stat:
        path: /etc/ssh/sshd_config.d
      register: _etc_ssh_sshd_config_d_exists

    - name: Check if the parameter PermitEmptyPasswords is present in /etc/ssh/sshd_config.d
      ansible.builtin.find:
        paths: /etc/ssh/sshd_config.d
        recurse: 'yes'
        follow: 'no'
        contains: (?i)^\s*{{ "PermitEmptyPasswords"| regex_escape }}\s+
      register: _etc_ssh_sshd_config_d_has_parameter
      when: _etc_ssh_sshd_config_d_exists.stat.isdir is defined and _etc_ssh_sshd_config_d_exists.stat.isdir

    - name: Remove parameter from files in /etc/ssh/sshd_config.d
      ansible.builtin.lineinfile:
        path: '{{ item.path }}'
        create: false
        regexp: (?i)(?i)^\s*{{ "PermitEmptyPasswords"| regex_escape }}\s+
        state: absent
      with_items: '{{ _etc_ssh_sshd_config_d_has_parameter.files }}'
      when: _etc_ssh_sshd_config_d_has_parameter.matched | bool

    - name: Insert correct line to /etc/ssh/sshd_config.d/01-complianceascode-reinforce-os-defaults.conf
      ansible.builtin.lineinfile:
        path: /etc/ssh/sshd_config.d/01-complianceascode-reinforce-os-defaults.conf
        create: true
        regexp: (?i)(?i)^\s*{{ "PermitEmptyPasswords"| regex_escape }}\s+
        line: PermitEmptyPasswords no
        state: present
        insertbefore: BOF
        validate: /usr/sbin/sshd -t -f %s
    when:
    - '"linux-base" in ansible_facts.packages'
    - _sshd_config_correctly.matched == 0 or _sshd_config_has_parameter.matched !=
      1
    tags:
    - CJIS-5.5.6
    - DISA-STIG-UBTU-22-255025
    - NIST-800-171-3.1.1
    - NIST-800-171-3.1.5
    - NIST-800-53-AC-17(a)
    - NIST-800-53-CM-6(a)
    - NIST-800-53-CM-7(a)
    - NIST-800-53-CM-7(b)
    - PCI-DSS-Req-2.2.4
    - PCI-DSSv4-2.2
    - PCI-DSSv4-2.2.6
    - high_severity
    - low_complexity
    - low_disruption
    - no_reboot_needed
    - restrict_strategy
    - sshd_disable_empty_passwords

  - name: Disable SSH Access via Empty Passwords - set file mode for /etc/ssh/sshd_config.d/01-complianceascode-reinforce-os-defaults.conf
    ansible.builtin.file:
      path: /etc/ssh/sshd_config.d/01-complianceascode-reinforce-os-defaults.conf
      mode: '0600'
      state: touch
      modification_time: preserve
      access_time: preserve
    when: '"linux-base" in ansible_facts.packages'
    tags:
    - CJIS-5.5.6
    - DISA-STIG-UBTU-22-255025
    - NIST-800-171-3.1.1
    - NIST-800-171-3.1.5
    - NIST-800-53-AC-17(a)
    - NIST-800-53-CM-6(a)
    - NIST-800-53-CM-7(a)
    - NIST-800-53-CM-7(b)
    - PCI-DSS-Req-2.2.4
    - PCI-DSSv4-2.2
    - PCI-DSSv4-2.2.6
    - high_severity
    - low_complexity
    - low_disruption
    - no_reboot_needed
    - restrict_strategy
    - sshd_disable_empty_passwords

  - name: Disable SSH 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: '"linux-base" in ansible_facts.packages'
    tags:
    - CJIS-5.5.6
    - 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: '"linux-base" in ansible_facts.packages'
    tags:
    - CJIS-5.5.6
    - 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 | bool

    - 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:
    - '"linux-base" in ansible_facts.packages'
    - _sshd_config_correctly.matched == 0 or _sshd_config_has_parameter.matched !=
      1
    tags:
    - CJIS-5.5.6
    - 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: '"linux-base" in ansible_facts.packages'
    tags:
    - CJIS-5.5.6
    - 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
