Guide to the Secure Configuration of Debian 12

with profile Profile for ANSSI DAT-NT28 High (Enforced) Level
This profile contains items for GNU/Linux installations storing sensitive information that can be accessible from unauthenticated or uncontroled networks.
This guide presents a catalog of security-relevant configuration settings for Debian 12. It is a rendering of content structured in the eXtensible Configuration Checklist Description Format (XCCDF) in order to support security automation. The SCAP content is is available in the scap-security-guide package which is developed at https://www.open-scap.org/security-policies/scap-security-guide.

Providing system administrators with such guidance informs them how to securely configure systems under their control in a variety of network roles. Policy makers and baseline creators can use this catalog of settings, with its associated references to higher-level security control catalogs, in order to assist them in security baseline creation. This guide is a catalog, not a checklist, and satisfaction of every item is not likely to be possible or sensible in many operational scenarios. However, the XCCDF format enables granular selection and adjustment of settings, and their association with OVAL and OCIL content provides an automated checking capability. Transformations of this document, and its associated automated checking content, are capable of providing baselines that meet a diverse set of policy objectives. Some example XCCDF Profiles, which are selections of items that form checklists and can be used as baselines, are available with this guide. They can be processed, in an automated fashion, with tools that support the Security Content Automation Protocol (SCAP). The DISA STIG, which provides required settings for US Department of Defense systems, is one example of a baseline created from this guidance.
Do not attempt to implement any of the settings in this guide without first testing them in a non-operational environment. The creators of this guidance assume no responsibility whatsoever for its use by other parties, and makes no guarantees, expressed or implied, about its quality, reliability, or any other characteristic.

Profile Information

Profile TitleProfile for ANSSI DAT-NT28 High (Enforced) Level
Profile IDxccdf_org.ssgproject.content_profile_anssi_np_nt28_high

CPE Platforms

  • cpe:/o:debian:debian_linux:12

Revision History

Current version: 0.1.76

  • draft (as of 2024-12-21)

Table of Contents

  1. System Settings
    1. Installing and Maintaining Software
    2. GRUB2 bootloader configuration
    3. Configure Syslog
    4. File Permissions and Masks
  2. Services
    1. APT service configuration
    2. Cron and At Daemons
    3. Deprecated services
    4. Network Time Protocol
    5. SSH Server
  3. System Accounting with auditd

    Checklist

    Group   Guide to the Secure Configuration of Debian 12   Group contains 23 groups and 50 rules
    Group   System Settings   Group contains 14 groups and 33 rules
    [ref]   Contains rules that check correct system settings.
    Group   Installing and Maintaining Software   Group contains 2 groups and 7 rules
    [ref]   The following sections contain information on security-relevant choices during the initial operating system installation process and the setup of software updates.
    Group   Disk Partitioning   Group contains 5 rules
    [ref]   To ensure separation and protection of data, there are top-level system directories which should be placed on their own physical partition or logical volume. The installer's default partitioning scheme creates separate logical volumes for /, /boot, and swap.
    • If starting with any of the default layouts, check the box to \"Review and modify partitioning.\" This allows for the easy creation of additional logical volumes inside the volume group already created, though it may require making /'s logical volume smaller to create space. In general, using logical volumes is preferable to using partitions because they can be more easily adjusted later.
    • If creating a custom layout, create the partitions mentioned in the previous paragraph (which the installer will require anyway), as well as separate ones described in the following sections.
    If a system has already been installed, and the default partitioning scheme was used, it is possible but nontrivial to modify it to create separate logical volumes for the directories listed above. The Logical Volume Manager (LVM) makes this possible.

    Rule   Ensure /home Located On Separate Partition   [ref]

    If user home directories will be stored locally, create a separate partition for /home at installation time (or migrate it later using LVM). If /home will be mounted from another system such as an NFS server, then creating a separate partition is not necessary at installation time, and the mountpoint can instead be configured later.
    Rationale:
    Ensuring that /home is mounted on its own partition enables the setting of more restrictive mount options, and also helps ensure that users cannot trivially fill partitions used for log or audit data storage.
    Severity: 
    low
    Rule ID:xccdf_org.ssgproject.content_rule_partition_for_home
    References:
    cis-csc12, 15, 8
    cobit5APO13.01, DSS05.02
    disaCCI-000366
    isa-62443-2013SR 3.1, SR 3.5, SR 3.8, SR 4.1, SR 4.3, SR 5.1, SR 5.2, SR 5.3, SR 7.1, SR 7.6
    iso27001-2013A.13.1.1, A.13.2.1, A.14.1.3
    nistCM-6(a), SC-5(2)
    nist-csfPR.PT-4
    os-srgSRG-OS-000480-GPOS-00227
    anssiR28

    Rule   Ensure /tmp Located On Separate Partition   [ref]

    The /tmp directory is a world-writable directory used for temporary file storage. Ensure it has its own partition or logical volume at installation time, or migrate it using LVM.
    Rationale:
    The /tmp partition is used as temporary storage by many programs. Placing /tmp in its own partition enables the setting of more restrictive mount options, which can help protect programs which use it.
    Severity: 
    low
    Rule ID:xccdf_org.ssgproject.content_rule_partition_for_tmp
    References:
    cis-csc12, 15, 8
    cobit5APO13.01, DSS05.02
    disaCCI-000366
    isa-62443-2013SR 3.1, SR 3.5, SR 3.8, SR 4.1, SR 4.3, SR 5.1, SR 5.2, SR 5.3, SR 7.1, SR 7.6
    iso27001-2013A.13.1.1, A.13.2.1, A.14.1.3
    nistCM-6(a), SC-5(2)
    nist-csfPR.PT-4
    os-srgSRG-OS-000480-GPOS-00227

    Rule   Ensure /var Located On Separate Partition   [ref]

    The /var directory is used by daemons and other system services to store frequently-changing data. Ensure that /var has its own partition or logical volume at installation time, or migrate it using LVM.
    Rationale:
    Ensuring that /var is mounted on its own partition enables the setting of more restrictive mount options. This helps protect system services such as daemons or other programs which use it. It is not uncommon for the /var directory to contain world-writable directories installed by other software packages.
    Severity: 
    low
    Rule ID:xccdf_org.ssgproject.content_rule_partition_for_var
    References:
    cis-csc12, 15, 8
    cobit5APO13.01, DSS05.02
    disaCCI-000366
    isa-62443-2013SR 3.1, SR 3.5, SR 3.8, SR 4.1, SR 4.3, SR 5.1, SR 5.2, SR 5.3, SR 7.1, SR 7.6
    iso27001-2013A.13.1.1, A.13.2.1, A.14.1.3
    nistCM-6(a), SC-5(2)
    nist-csfPR.PT-4
    os-srgSRG-OS-000480-GPOS-00227
    anssiR28

    Rule   Ensure /var/log Located On Separate Partition   [ref]

    System logs are stored in the /var/log directory. Ensure that /var/log has its own partition or logical volume at installation time, or migrate it using LVM.
    Rationale:
    Placing /var/log in its own partition enables better separation between log files and other files in /var/.
    Severity: 
    low
    Rule ID:xccdf_org.ssgproject.content_rule_partition_for_var_log
    References:
    cis-csc1, 12, 14, 15, 16, 3, 5, 6, 8
    cobit5APO11.04, APO13.01, BAI03.05, DSS05.02, DSS05.04, DSS05.07, MEA02.01
    disaCCI-000366
    isa-62443-20094.3.3.3.9, 4.3.3.5.8, 4.3.4.4.7, 4.4.2.1, 4.4.2.2, 4.4.2.4
    isa-62443-2013SR 2.10, SR 2.11, SR 2.12, SR 2.8, SR 2.9, SR 3.1, SR 3.5, SR 3.8, SR 4.1, SR 4.3, SR 5.1, SR 5.2, SR 5.3, SR 7.1, SR 7.6
    iso27001-2013A.12.4.1, A.12.4.2, A.12.4.3, A.12.4.4, A.12.7.1, A.13.1.1, A.13.2.1, A.14.1.3
    nerc-cipCIP-007-3 R6.5
    nistCM-6(a), AU-4, SC-5(2)
    nist-csfPR.PT-1, PR.PT-4
    os-srgSRG-OS-000480-GPOS-00227
    anssiR28

    Rule   Ensure /var/log/audit Located On Separate Partition   [ref]

    Audit logs are stored in the /var/log/audit directory. Ensure that /var/log/audit has its own partition or logical volume at installation time, or migrate it using LVM. Make absolutely certain that it is large enough to store all audit logs that will be created by the auditing daemon.
    Rationale:
    Placing /var/log/audit in its own partition enables better separation between audit files and other files, and helps ensure that auditing cannot be halted due to the partition running out of space.
    Severity: 
    low
    Rule ID:xccdf_org.ssgproject.content_rule_partition_for_var_log_audit
    References:
    cis-csc1, 12, 13, 14, 15, 16, 2, 3, 5, 6, 8
    cobit5APO11.04, APO13.01, BAI03.05, BAI04.04, DSS05.02, DSS05.04, DSS05.07, MEA02.01
    disaCCI-000366, CCI-001849
    hipaa164.312(a)(2)(ii)
    isa-62443-20094.3.3.3.9, 4.3.3.5.8, 4.3.4.4.7, 4.4.2.1, 4.4.2.2, 4.4.2.4
    isa-62443-2013SR 2.10, SR 2.11, SR 2.12, SR 2.8, SR 2.9, SR 3.1, SR 3.5, SR 3.8, SR 4.1, SR 4.3, SR 5.1, SR 5.2, SR 5.3, SR 7.1, SR 7.2, SR 7.6
    iso27001-2013A.12.1.3, A.12.4.1, A.12.4.2, A.12.4.3, A.12.4.4, A.12.7.1, A.13.1.1, A.13.2.1, A.14.1.3, A.17.2.1
    nerc-cipCIP-007-3 R6.5
    nistCM-6(a), AU-4, SC-5(2)
    nist-csfPR.DS-4, PR.PT-1, PR.PT-4
    osppFMT_SMF_EXT.1
    os-srgSRG-OS-000341-GPOS-00132, SRG-OS-000480-GPOS-00227
    app-srg-ctrSRG-APP-000357-CTR-000800
    anssiR71
    Group   Sudo   Group contains 2 rules
    [ref]   Sudo, which stands for "su 'do'", provides the ability to delegate authority to certain users, groups of users, or system administrators. When configured for system users and/or groups, Sudo can allow a user or group to execute privileged commands that normally only root is allowed to execute.

    For more information on Sudo and addition Sudo configuration options, see https://www.sudo.ws.

    Rule   Ensure Users Re-Authenticate for Privilege Escalation - sudo !authenticate   [ref]

    The sudo !authenticate option, when specified, allows a user to execute commands using sudo without having to authenticate. This should be disabled by making sure that the !authenticate option does not exist in /etc/sudoers configuration file or any sudo configuration snippets in /etc/sudoers.d/.
    Rationale:
    Without re-authentication, users may access resources or perform tasks for which they do not have authorization.

    When operating systems provide the capability to escalate a functional capability, it is critical that the user re-authenticate.
    Severity: 
    medium
    Rule ID:xccdf_org.ssgproject.content_rule_sudo_remove_no_authenticate
    References:
    cis-csc1, 12, 15, 16, 5
    cobit5DSS05.04, DSS05.10, DSS06.03, DSS06.10
    disaCCI-004895
    isa-62443-20094.3.3.5.1, 4.3.3.6.1, 4.3.3.6.2, 4.3.3.6.3, 4.3.3.6.4, 4.3.3.6.5, 4.3.3.6.6, 4.3.3.6.7, 4.3.3.6.8, 4.3.3.6.9
    isa-62443-2013SR 1.1, SR 1.10, SR 1.2, SR 1.3, SR 1.4, SR 1.5, SR 1.7, SR 1.8, SR 1.9
    iso27001-2013A.18.1.4, A.9.2.1, A.9.2.2, A.9.2.3, A.9.2.4, A.9.2.6, A.9.3.1, A.9.4.2, A.9.4.3
    nistIA-11, CM-6(a)
    nist-csfPR.AC-1, PR.AC-7
    os-srgSRG-OS-000373-GPOS-00156, SRG-OS-000373-GPOS-00157, SRG-OS-000373-GPOS-00158

    Complexity:low
    Disruption:low
    Reboot:false
    Strategy:restrict
    
    for f in /etc/sudoers /etc/sudoers.d/* ; do
      if [ ! -e "$f" ] ; then
        continue
      fi
      matching_list=$(grep -P '^(?!#).*[\s]+\!authenticate.*$' $f | uniq )
      if ! test -z "$matching_list"; then
        while IFS= read -r entry; do
          # comment out "!authenticate" matches to preserve user data
          sed -i "s/^${entry}$/# &/g" $f
        done <<< "$matching_list"
    
        /usr/sbin/visudo -cf $f &> /dev/null || echo "Fail to validate $f with visudo"
      fi
    done
    

    Complexity:low
    Disruption:low
    Reboot:false
    Strategy:restrict
    - name: Find /etc/sudoers.d/ files
      ansible.builtin.find:
        paths:
        - /etc/sudoers.d/
      register: sudoers
      tags:
      - NIST-800-53-CM-6(a)
      - NIST-800-53-IA-11
      - low_complexity
      - low_disruption
      - medium_severity
      - no_reboot_needed
      - restrict_strategy
      - sudo_remove_no_authenticate
    
    - name: Remove lines containing !authenticate from sudoers files
      ansible.builtin.replace:
        regexp: (^(?!#).*[\s]+\!authenticate.*$)
        replace: '# \g<1>'
        path: '{{ item.path }}'
        validate: /usr/sbin/visudo -cf %s
      with_items:
      - path: /etc/sudoers
      - '{{ sudoers.files }}'
      tags:
      - NIST-800-53-CM-6(a)
      - NIST-800-53-IA-11
      - low_complexity
      - low_disruption
      - medium_severity
      - no_reboot_needed
      - restrict_strategy
      - sudo_remove_no_authenticate
    

    Rule   Ensure Users Re-Authenticate for Privilege Escalation - sudo NOPASSWD   [ref]

    The sudo NOPASSWD tag, when specified, allows a user to execute commands using sudo without having to authenticate. This should be disabled by making sure that the NOPASSWD tag does not exist in /etc/sudoers configuration file or any sudo configuration snippets in /etc/sudoers.d/.
    Rationale:
    Without re-authentication, users may access resources or perform tasks for which they do not have authorization.

    When operating systems provide the capability to escalate a functional capability, it is critical that the user re-authenticate.
    Severity: 
    medium
    Rule ID:xccdf_org.ssgproject.content_rule_sudo_remove_nopasswd
    References:
    cis-csc1, 12, 15, 16, 5
    cobit5DSS05.04, DSS05.10, DSS06.03, DSS06.10
    disaCCI-004895
    isa-62443-20094.3.3.5.1, 4.3.3.6.1, 4.3.3.6.2, 4.3.3.6.3, 4.3.3.6.4, 4.3.3.6.5, 4.3.3.6.6, 4.3.3.6.7, 4.3.3.6.8, 4.3.3.6.9
    isa-62443-2013SR 1.1, SR 1.10, SR 1.2, SR 1.3, SR 1.4, SR 1.5, SR 1.7, SR 1.8, SR 1.9
    iso27001-2013A.18.1.4, A.9.2.1, A.9.2.2, A.9.2.3, A.9.2.4, A.9.2.6, A.9.3.1, A.9.4.2, A.9.4.3
    nistIA-11, CM-6(a)
    nist-csfPR.AC-1, PR.AC-7
    os-srgSRG-OS-000373-GPOS-00156, SRG-OS-000373-GPOS-00157, SRG-OS-000373-GPOS-00158

    Complexity:low
    Disruption:low
    Reboot:false
    Strategy:restrict
    
    for f in /etc/sudoers /etc/sudoers.d/* ; do
      if [ ! -e "$f" ] ; then
        continue
      fi
      matching_list=$(grep -P '^(?!#).*[\s]+NOPASSWD[\s]*\:.*$' $f | uniq )
      if ! test -z "$matching_list"; then
        while IFS= read -r entry; do
          # comment out "NOPASSWD" matches to preserve user data
          sed -i "s/^${entry}$/# &/g" $f
        done <<< "$matching_list"
    
        /usr/sbin/visudo -cf $f &> /dev/null || echo "Fail to validate $f with visudo"
      fi
    done
    

    Complexity:low
    Disruption:low
    Reboot:false
    Strategy:restrict
    - name: Find /etc/sudoers.d/ files
      ansible.builtin.find:
        paths:
        - /etc/sudoers.d/
      register: sudoers
      tags:
      - NIST-800-53-CM-6(a)
      - NIST-800-53-IA-11
      - low_complexity
      - low_disruption
      - medium_severity
      - no_reboot_needed
      - restrict_strategy
      - sudo_remove_nopasswd
    
    - name: Remove lines containing NOPASSWD from sudoers files
      ansible.builtin.replace:
        regexp: (^(?!#).*[\s]+NOPASSWD[\s]*\:.*$)
        replace: '# \g<1>'
        path: '{{ item.path }}'
        validate: /usr/sbin/visudo -cf %s
      with_items:
      - path: /etc/sudoers
      - '{{ sudoers.files }}'
      tags:
      - NIST-800-53-CM-6(a)
      - NIST-800-53-IA-11
      - low_complexity
      - low_disruption
      - medium_severity
      - no_reboot_needed
      - restrict_strategy
      - sudo_remove_nopasswd
    
    Group   GRUB2 bootloader configuration   Group contains 1 rule
    [ref]   During the boot process, the boot loader is responsible for starting the execution of the kernel and passing options to it. The boot loader allows for the selection of different kernels - possibly on different partitions or media. The default Debian 12 boot loader for x86 systems is called GRUB2. Options it can pass to the kernel include single-user mode, which provides root access without any authentication, and the ability to disable SELinux. To prevent local users from modifying the boot parameters and endangering security, protect the boot loader configuration with a password and ensure its configuration file's permissions are set properly.

    Rule   IOMMU configuration directive   [ref]

    On x86 architecture supporting VT-d, the IOMMU manages the access control policy between the hardware devices and some of the system critical units such as the memory. Configure the default Grub2 kernel command line to contain iommu=force as follows:
    # grub2-editenv - set "$(grub2-editenv - list | grep kernelopts) iommu=force"
    Warning:  Depending on the hardware, devices and operating system used, enabling IOMMU can cause hardware instabilities. Proper function and stability should be assessed before applying remediation to production systems.
    Rationale:
    On x86 architectures, activating the I/OMMU prevents the system from arbitrary accesses potentially made by hardware devices.
    Severity: 
    unknown
    Rule ID:xccdf_org.ssgproject.content_rule_grub2_enable_iommu_force
    References:
    anssiR7

    # Remediation is applicable only in certain platforms
    if dpkg-query --show --showformat='${db:Status-Status}\n' 'grub2-common' 2>/dev/null | grep -q installed && { [ ! -f /.dockerenv ] && [ ! -f /run/.containerenv ]; }; then
    
    # Correct the form of default kernel command line in GRUB
    if grep -q '^\s*GRUB_CMDLINE_LINUX=.*iommu=.*"'  '/etc/default/grub' ; then
           # modify the GRUB command-line if an iommu= arg already exists
           sed -i "s/\(^\s*GRUB_CMDLINE_LINUX=\".*\)iommu=[^[:space:]]\+\(.*\"\)/\1iommu=force\2/"  '/etc/default/grub'
    # Add to already existing GRUB_CMDLINE_LINUX parameters
    elif grep -q '^\s*GRUB_CMDLINE_LINUX='  '/etc/default/grub' ; then
           # no iommu=arg is present, append it
           sed -i "s/\(^\s*GRUB_CMDLINE_LINUX=\".*\)\"/\1 iommu=force\"/"  '/etc/default/grub'
    # Add GRUB_CMDLINE_LINUX parameters line
    else
           echo "GRUB_CMDLINE_LINUX=\"iommu=force\"" >> '/etc/default/grub'
    fi
    update-grub
    
    else
        >&2 echo 'Remediation is not applicable, nothing was done'
    fi
    

    Complexity:medium
    Disruption:low
    Reboot:true
    Strategy:restrict
    - name: Gather the package facts
      package_facts:
        manager: auto
      tags:
      - grub2_enable_iommu_force
      - low_disruption
      - medium_complexity
      - reboot_required
      - restrict_strategy
      - unknown_severity
    
    - name: Check iommu argument exists
      command: grep '^\s*GRUB_CMDLINE_LINUX=.*iommu=' /etc/default/grub
      failed_when: false
      register: argcheck
      when:
      - '"grub2-common" in ansible_facts.packages'
      - ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"]
      tags:
      - grub2_enable_iommu_force
      - low_disruption
      - medium_complexity
      - reboot_required
      - restrict_strategy
      - unknown_severity
    
    - name: Check iommu argument exists
      command: grep '^\s*GRUB_CMDLINE_LINUX=' /etc/default/grub
      failed_when: false
      register: linecheck
      when:
      - '"grub2-common" in ansible_facts.packages'
      - ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"]
      tags:
      - grub2_enable_iommu_force
      - low_disruption
      - medium_complexity
      - reboot_required
      - restrict_strategy
      - unknown_severity
    
    - name: Add iommu argument
      ansible.builtin.lineinfile:
        line: GRUB_CMDLINE_LINUX="iommu=force "
        state: present
        dest: /etc/default/grub
        create: true
        mode: '0644'
      when:
      - '"grub2-common" in ansible_facts.packages'
      - ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"]
      - argcheck is not skipped and linecheck is not skipped and argcheck.rc != 0 and
        linecheck.rc != 0
      tags:
      - grub2_enable_iommu_force
      - low_disruption
      - medium_complexity
      - reboot_required
      - restrict_strategy
      - unknown_severity
    
    - name: Replace existing iommu argument
      replace:
        path: /etc/default/grub
        regexp: iommu=[a-zA-Z0-9,]+
        replace: iommu=force
      when:
      - '"grub2-common" in ansible_facts.packages'
      - ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"]
      - argcheck is not skipped and linecheck is not skipped and argcheck.rc == 0 and
        linecheck.rc == 0
      tags:
      - grub2_enable_iommu_force
      - low_disruption
      - medium_complexity
      - reboot_required
      - restrict_strategy
      - unknown_severity
    
    - name: Add iommu argument
      replace:
        path: /etc/default/grub
        regexp: (^\s*GRUB_CMDLINE_LINUX=.*)"
        replace: \1 iommu=force"
      when:
      - '"grub2-common" in ansible_facts.packages'
      - ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"]
      - argcheck is not skipped and linecheck is not skipped and argcheck.rc != 0 and
        linecheck.rc == 0
      tags:
      - grub2_enable_iommu_force
      - low_disruption
      - medium_complexity
      - reboot_required
      - restrict_strategy
      - unknown_severity
    
    - name: Update grub defaults and the bootloader menu
      command: /usr/sbin/update-grub
      when:
      - '"grub2-common" in ansible_facts.packages'
      - ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"]
      tags:
      - grub2_enable_iommu_force
      - low_disruption
      - medium_complexity
      - reboot_required
      - restrict_strategy
      - unknown_severity
    
    Group   Configure Syslog   Group contains 3 groups and 8 rules
    [ref]   The syslog service has been the default Unix logging mechanism for many years. It has a number of downsides, including inconsistent log format, lack of authentication for received messages, and lack of authentication, encryption, or reliable transport for messages sent over a network. However, due to its long history, syslog is a de facto standard which is supported by almost all Unix applications.

    In Debian 12, rsyslog has replaced ksyslogd as the syslog daemon of choice, and it includes some additional security features such as reliable, connection-oriented (i.e. TCP) transmission of logs, the option to log to database formats, and the encryption of log data en route to a central logging server. This section discusses how to configure rsyslog for best effect, and how to use tools provided with the system to maintain and monitor logs.
    Group   Ensure Proper Configuration of Log Files   Group contains 3 rules
    [ref]   The file /etc/rsyslog.conf controls where log message are written. These are controlled by lines called rules, which consist of a selector and an action. These rules are often customized depending on the role of the system, the requirements of the environment, and whatever may enable the administrator to most effectively make use of log data. The default rules in Debian 12 are:
    *.info;mail.none;authpriv.none;cron.none                /var/log/messages
    authpriv.*                                              /var/log/secure
    mail.*                                                  -/var/log/maillog
    cron.*                                                  /var/log/cron
    *.emerg                                                 *
    uucp,news.crit                                          /var/log/spooler
    local7.*                                                /var/log/boot.log
    See the man page rsyslog.conf(5) for more information. Note that the rsyslog daemon can be configured to use a timestamp format that some log processing programs may not understand. If this occurs, edit the file /etc/rsyslog.conf and add or edit the following line:
    $ ActionFileDefaultTemplate RSYSLOG_TraditionalFileFormat

    Rule   Ensure Log Files Are Owned By Appropriate Group   [ref]

    The group-owner of all log files written by rsyslog should be adm. These log files are determined by the second part of each Rule line in /etc/rsyslog.conf and typically all appear in /var/log. For each log file LOGFILE referenced in /etc/rsyslog.conf, run the following command to inspect the file's group owner:
    $ ls -l LOGFILE
            
    If the owner is not adm, run the following command to correct this:
    $ sudo chgrp adm LOGFILE
            
    Rationale:
    The log files generated by rsyslog contain valuable information regarding system configuration, user authentication, and other such information. Log files should be protected from unauthorized access.
    Severity: 
    medium
    Rule ID:xccdf_org.ssgproject.content_rule_rsyslog_files_groupownership
    References:
    cis-csc12, 13, 14, 15, 16, 18, 3, 5
    cobit5APO01.06, DSS05.04, DSS05.07, DSS06.02
    disaCCI-001314
    isa-62443-20094.3.3.7.3
    isa-62443-2013SR 2.1, SR 5.2
    ism0988, 1405
    iso27001-2013A.10.1.1, A.11.1.4, A.11.1.5, A.11.2.1, A.13.1.1, A.13.1.3, A.13.2.1, A.13.2.3, A.13.2.4, A.14.1.2, A.14.1.3, A.6.1.2, A.7.1.1, A.7.1.2, A.7.3.1, A.8.2.2, A.8.2.3, A.9.1.1, A.9.1.2, A.9.2.3, A.9.4.1, A.9.4.4, A.9.4.5
    nerc-cipCIP-003-8 R5.1.1, CIP-003-8 R5.3, CIP-004-6 R2.3, CIP-007-3 R2.1, CIP-007-3 R2.2, CIP-007-3 R2.3, CIP-007-3 R5.1, CIP-007-3 R5.1.1, CIP-007-3 R5.1.2
    nistCM-6(a), AC-6(1)
    nist-csfPR.AC-4, PR.DS-5
    pcidssReq-10.5.1, Req-10.5.2
    anssiR71
    pcidss410.3.2, 10.3

    # Remediation is applicable only in certain platforms
    if dpkg-query --show --showformat='${db:Status-Status}
    ' 'linux-base' 2>/dev/null | grep -q ^installed && dpkg-query --show --showformat='${db:Status-Status}\n' 'rsyslog' 2>/dev/null | grep -q installed; then
    
    # List of log file paths to be inspected for correct permissions
    # * Primarily inspect log file paths listed in /etc/rsyslog.conf
    RSYSLOG_ETC_CONFIG="/etc/rsyslog.conf"
    # * And also the log file paths listed after rsyslog's $IncludeConfig directive
    #   (store the result into array for the case there's shell glob used as value of IncludeConfig)
    readarray -t OLD_INC < <(grep -e "\$IncludeConfig[[:space:]]\+[^[:space:];]\+" /etc/rsyslog.conf | cut -d ' ' -f 2)
    readarray -t RSYSLOG_INCLUDE_CONFIG < <(for INCPATH in "${OLD_INC[@]}"; do eval printf '%s\\n' "${INCPATH}"; done)
    readarray -t NEW_INC < <(sed -n '/^\s*include(/,/)/Ip' /etc/rsyslog.conf | sed -n 's@.*file\s*=\s*"\([/[:alnum:][:punct:]]*\)".*@\1@Ip')
    readarray -t RSYSLOG_INCLUDE < <(for INCPATH in "${NEW_INC[@]}"; do eval printf '%s\\n' "${INCPATH}"; done)
    
    # Declare an array to hold the final list of different log file paths
    declare -a LOG_FILE_PATHS
    
    # Array to hold all rsyslog config entries
    RSYSLOG_CONFIGS=()
    RSYSLOG_CONFIGS=("${RSYSLOG_ETC_CONFIG}" "${RSYSLOG_INCLUDE_CONFIG[@]}" "${RSYSLOG_INCLUDE[@]}")
    
    # Get full list of files to be checked
    # RSYSLOG_CONFIGS may contain globs such as
    # /etc/rsyslog.d/*.conf /etc/rsyslog.d/*.frule
    # So, loop over the entries in RSYSLOG_CONFIGS and use find to get the list of included files.
    RSYSLOG_CONFIG_FILES=()
    for ENTRY in "${RSYSLOG_CONFIGS[@]}"
    do
    	# If directory, rsyslog will search for config files in recursively.
    	# However, files in hidden sub-directories or hidden files will be ignored.
    	if [ -d "${ENTRY}" ]
    	then
    		readarray -t FINDOUT < <(find "${ENTRY}" -not -path '*/.*' -type f)
    		RSYSLOG_CONFIG_FILES+=("${FINDOUT[@]}")
    	elif [ -f "${ENTRY}" ]
    	then
    		RSYSLOG_CONFIG_FILES+=("${ENTRY}")
    	else
    		echo "Invalid include object: ${ENTRY}"
    	fi
    done
    
    # Browse each file selected above as containing paths of log files
    # ('/etc/rsyslog.conf' and '/etc/rsyslog.d/*.conf' in the default configuration)
    for LOG_FILE in "${RSYSLOG_CONFIG_FILES[@]}"
    do
    	# From each of these files extract just particular log file path(s), thus:
    	# * Ignore lines starting with space (' '), comment ('#"), or variable syntax ('$') characters,
    	# * Ignore empty lines,
    	# * Strip quotes and closing brackets from paths.
    	# * Ignore paths that match /dev|/etc.*\.conf, as those are paths, but likely not log files
    	# * From the remaining valid rows select only fields constituting a log file path
    	# Text file column is understood to represent a log file path if and only if all of the
    	# following are met:
    	# * it contains at least one slash '/' character,
    	# * it is preceded by space
    	# * it doesn't contain space (' '), colon (':'), and semicolon (';') characters
    	# Search log file for path(s) only in case it exists!
    	if [[ -f "${LOG_FILE}" ]]
    	then
    		NORMALIZED_CONFIG_FILE_LINES=$(sed -e "/^[#|$]/d" "${LOG_FILE}")
    		LINES_WITH_PATHS=$(grep '[^/]*\s\+\S*/\S\+$' <<< "${NORMALIZED_CONFIG_FILE_LINES}")
    		FILTERED_PATHS=$(awk '{if(NF>=2&&($NF~/^\//||$NF~/^-\//)){sub(/^-\//,"/",$NF);print $NF}}' <<< "${LINES_WITH_PATHS}")
    		CLEANED_PATHS=$(sed -e "s/[\"')]//g; /\\/etc.*\.conf/d; /\\/dev\\//d" <<< "${FILTERED_PATHS}")
    		MATCHED_ITEMS=$(sed -e "/^$/d" <<< "${CLEANED_PATHS}")
    		# Since above sed command might return more than one item (delimited by newline), split
    		# the particular matches entries into new array specific for this log file
    		readarray -t ARRAY_FOR_LOG_FILE <<< "$MATCHED_ITEMS"
    		# Concatenate the two arrays - previous content of $LOG_FILE_PATHS array with
    		# items from newly created array for this log file
    		LOG_FILE_PATHS+=("${ARRAY_FOR_LOG_FILE[@]}")
    		# Delete the temporary array
    		unset ARRAY_FOR_LOG_FILE
    	fi
    done
    
    # Check for RainerScript action log format which might be also multiline so grep regex is a bit
    # curly:
    # extract possibly multiline action omfile expressions
    # extract File="logfile" expression
    # match only "logfile" expression
    for LOG_FILE in "${RSYSLOG_CONFIG_FILES[@]}"
    do
    	ACTION_OMFILE_LINES=$(grep -iozP "action\s*\(\s*type\s*=\s*\"omfile\"[^\)]*\)" "${LOG_FILE}")
    	OMFILE_LINES=$(echo "${ACTION_OMFILE_LINES}"| grep -iaoP "\bFile\s*=\s*\"([/[:alnum:][:punct:]]*)\"\s*\)")
    	LOG_FILE_PATHS+=("$(echo "${OMFILE_LINES}"| grep -oE "\"([/[:alnum:][:punct:]]*)\""|tr -d "\"")")
    done
    
    # Ensure the correct attribute if file exists
    FILE_CMD="chgrp"
    for LOG_FILE_PATH in "${LOG_FILE_PATHS[@]}"
    do
    	# Sanity check - if particular $LOG_FILE_PATH is empty string, skip it from further processing
    	if [ -z "$LOG_FILE_PATH" ]
    	then
    		continue
    	fi
    	$FILE_CMD "adm" "$LOG_FILE_PATH"
    done
    
    else
        >&2 echo 'Remediation is not applicable, nothing was done'
    fi
    

    Complexity:low
    Disruption:medium
    Reboot:false
    Strategy:configure
    - name: Gather the package facts
      package_facts:
        manager: auto
      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 - 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: |
        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: |
        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: |
        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: |
        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
    

    Rule   Ensure Log Files Are Owned By Appropriate User   [ref]

    The owner of all log files written by rsyslog should be adm. These log files are determined by the second part of each Rule line in /etc/rsyslog.conf and typically all appear in /var/log. For each log file LOGFILE referenced in /etc/rsyslog.conf, run the following command to inspect the file's owner:
    $ ls -l LOGFILE
            
    If the owner is not adm, run the following command to correct this:
    $ sudo chown adm LOGFILE
            
    Rationale:
    The log files generated by rsyslog contain valuable information regarding system configuration, user authentication, and other such information. Log files should be protected from unauthorized access.
    Severity: 
    medium
    Rule ID:xccdf_org.ssgproject.content_rule_rsyslog_files_ownership
    References:
    cis-csc12, 13, 14, 15, 16, 18, 3, 5
    cobit5APO01.06, DSS05.04, DSS05.07, DSS06.02
    disaCCI-001314
    isa-62443-20094.3.3.7.3
    isa-62443-2013SR 2.1, SR 5.2
    ism0988, 1405
    iso27001-2013A.10.1.1, A.11.1.4, A.11.1.5, A.11.2.1, A.13.1.1, A.13.1.3, A.13.2.1, A.13.2.3, A.13.2.4, A.14.1.2, A.14.1.3, A.6.1.2, A.7.1.1, A.7.1.2, A.7.3.1, A.8.2.2, A.8.2.3, A.9.1.1, A.9.1.2, A.9.2.3, A.9.4.1, A.9.4.4, A.9.4.5
    nerc-cipCIP-003-8 R5.1.1, CIP-003-8 R5.3, CIP-004-6 R2.3, CIP-007-3 R2.1, CIP-007-3 R2.2, CIP-007-3 R2.3, CIP-007-3 R5.1, CIP-007-3 R5.1.1, CIP-007-3 R5.1.2
    nistCM-6(a), AC-6(1)
    nist-csfPR.AC-4, PR.DS-5
    pcidssReq-10.5.1, Req-10.5.2
    anssiR71
    pcidss410.3.2, 10.3

    # Remediation is applicable only in certain platforms
    if dpkg-query --show --showformat='${db:Status-Status}
    ' 'linux-base' 2>/dev/null | grep -q ^installed && dpkg-query --show --showformat='${db:Status-Status}\n' 'rsyslog' 2>/dev/null | grep -q installed; then
    
    # List of log file paths to be inspected for correct permissions
    # * Primarily inspect log file paths listed in /etc/rsyslog.conf
    RSYSLOG_ETC_CONFIG="/etc/rsyslog.conf"
    # * And also the log file paths listed after rsyslog's $IncludeConfig directive
    #   (store the result into array for the case there's shell glob used as value of IncludeConfig)
    readarray -t OLD_INC < <(grep -e "\$IncludeConfig[[:space:]]\+[^[:space:];]\+" /etc/rsyslog.conf | cut -d ' ' -f 2)
    readarray -t RSYSLOG_INCLUDE_CONFIG < <(for INCPATH in "${OLD_INC[@]}"; do eval printf '%s\\n' "${INCPATH}"; done)
    readarray -t NEW_INC < <(sed -n '/^\s*include(/,/)/Ip' /etc/rsyslog.conf | sed -n 's@.*file\s*=\s*"\([/[:alnum:][:punct:]]*\)".*@\1@Ip')
    readarray -t RSYSLOG_INCLUDE < <(for INCPATH in "${NEW_INC[@]}"; do eval printf '%s\\n' "${INCPATH}"; done)
    
    # Declare an array to hold the final list of different log file paths
    declare -a LOG_FILE_PATHS
    
    # Array to hold all rsyslog config entries
    RSYSLOG_CONFIGS=()
    RSYSLOG_CONFIGS=("${RSYSLOG_ETC_CONFIG}" "${RSYSLOG_INCLUDE_CONFIG[@]}" "${RSYSLOG_INCLUDE[@]}")
    
    # Get full list of files to be checked
    # RSYSLOG_CONFIGS may contain globs such as
    # /etc/rsyslog.d/*.conf /etc/rsyslog.d/*.frule
    # So, loop over the entries in RSYSLOG_CONFIGS and use find to get the list of included files.
    RSYSLOG_CONFIG_FILES=()
    for ENTRY in "${RSYSLOG_CONFIGS[@]}"
    do
    	# If directory, rsyslog will search for config files in recursively.
    	# However, files in hidden sub-directories or hidden files will be ignored.
    	if [ -d "${ENTRY}" ]
    	then
    		readarray -t FINDOUT < <(find "${ENTRY}" -not -path '*/.*' -type f)
    		RSYSLOG_CONFIG_FILES+=("${FINDOUT[@]}")
    	elif [ -f "${ENTRY}" ]
    	then
    		RSYSLOG_CONFIG_FILES+=("${ENTRY}")
    	else
    		echo "Invalid include object: ${ENTRY}"
    	fi
    done
    
    # Browse each file selected above as containing paths of log files
    # ('/etc/rsyslog.conf' and '/etc/rsyslog.d/*.conf' in the default configuration)
    for LOG_FILE in "${RSYSLOG_CONFIG_FILES[@]}"
    do
    	# From each of these files extract just particular log file path(s), thus:
    	# * Ignore lines starting with space (' '), comment ('#"), or variable syntax ('$') characters,
    	# * Ignore empty lines,
    	# * Strip quotes and closing brackets from paths.
    	# * Ignore paths that match /dev|/etc.*\.conf, as those are paths, but likely not log files
    	# * From the remaining valid rows select only fields constituting a log file path
    	# Text file column is understood to represent a log file path if and only if all of the
    	# following are met:
    	# * it contains at least one slash '/' character,
    	# * it is preceded by space
    	# * it doesn't contain space (' '), colon (':'), and semicolon (';') characters
    	# Search log file for path(s) only in case it exists!
    	if [[ -f "${LOG_FILE}" ]]
    	then
    		NORMALIZED_CONFIG_FILE_LINES=$(sed -e "/^[#|$]/d" "${LOG_FILE}")
    		LINES_WITH_PATHS=$(grep '[^/]*\s\+\S*/\S\+$' <<< "${NORMALIZED_CONFIG_FILE_LINES}")
    		FILTERED_PATHS=$(awk '{if(NF>=2&&($NF~/^\//||$NF~/^-\//)){sub(/^-\//,"/",$NF);print $NF}}' <<< "${LINES_WITH_PATHS}")
    		CLEANED_PATHS=$(sed -e "s/[\"')]//g; /\\/etc.*\.conf/d; /\\/dev\\//d" <<< "${FILTERED_PATHS}")
    		MATCHED_ITEMS=$(sed -e "/^$/d" <<< "${CLEANED_PATHS}")
    		# Since above sed command might return more than one item (delimited by newline), split
    		# the particular matches entries into new array specific for this log file
    		readarray -t ARRAY_FOR_LOG_FILE <<< "$MATCHED_ITEMS"
    		# Concatenate the two arrays - previous content of $LOG_FILE_PATHS array with
    		# items from newly created array for this log file
    		LOG_FILE_PATHS+=("${ARRAY_FOR_LOG_FILE[@]}")
    		# Delete the temporary array
    		unset ARRAY_FOR_LOG_FILE
    	fi
    done
    
    # Check for RainerScript action log format which might be also multiline so grep regex is a bit
    # curly:
    # extract possibly multiline action omfile expressions
    # extract File="logfile" expression
    # match only "logfile" expression
    for LOG_FILE in "${RSYSLOG_CONFIG_FILES[@]}"
    do
    	ACTION_OMFILE_LINES=$(grep -iozP "action\s*\(\s*type\s*=\s*\"omfile\"[^\)]*\)" "${LOG_FILE}")
    	OMFILE_LINES=$(echo "${ACTION_OMFILE_LINES}"| grep -iaoP "\bFile\s*=\s*\"([/[:alnum:][:punct:]]*)\"\s*\)")
    	LOG_FILE_PATHS+=("$(echo "${OMFILE_LINES}"| grep -oE "\"([/[:alnum:][:punct:]]*)\""|tr -d "\"")")
    done
    
    # Ensure the correct attribute if file exists
    FILE_CMD="chown"
    for LOG_FILE_PATH in "${LOG_FILE_PATHS[@]}"
    do
    	# Sanity check - if particular $LOG_FILE_PATH is empty string, skip it from further processing
    	if [ -z "$LOG_FILE_PATH" ]
    	then
    		continue
    	fi
    	$FILE_CMD "root" "$LOG_FILE_PATH"
    done
    
    else
        >&2 echo 'Remediation is not applicable, nothing was done'
    fi
    

    Complexity:low
    Disruption:medium
    Reboot:false
    Strategy:configure
    - name: Gather the package facts
      package_facts:
        manager: auto
      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 - 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: |
        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: |
        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: |
        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: |
        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: root
        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
    

    Rule   Ensure System Log Files Have Correct Permissions   [ref]

    The file permissions for all log files written by rsyslog should be set to 640, or more restrictive. These log files are determined by the second part of each Rule line in /etc/rsyslog.conf and typically all appear in /var/log. For each log file LOGFILE referenced in /etc/rsyslog.conf, run the following command to inspect the file's permissions:
    $ ls -l LOGFILE
            
    If the permissions are not 640 or more restrictive, run the following command to correct this:
    $ sudo chmod 640 LOGFILE
            
    "
    Rationale:
    Log files can contain valuable information regarding system configuration. If the system log files are not protected unauthorized users could change the logged data, eliminating their forensic value.
    Severity: 
    medium
    Rule ID:xccdf_org.ssgproject.content_rule_rsyslog_files_permissions
    References:
    disaCCI-001314
    ism0988, 1405
    nerc-cipCIP-003-8 R5.1.1, CIP-003-8 R5.3, CIP-004-6 R2.3, CIP-007-3 R2.1, CIP-007-3 R2.2, CIP-007-3 R2.3, CIP-007-3 R5.1, CIP-007-3 R5.1.1, CIP-007-3 R5.1.2
    nistCM-6(a), AC-6(1)
    pcidssReq-10.5.1, Req-10.5.2
    anssiR71
    pcidss410.3.1, 10.3

    # Remediation is applicable only in certain platforms
    if dpkg-query --show --showformat='${db:Status-Status}
    ' 'linux-base' 2>/dev/null | grep -q ^installed && dpkg-query --show --showformat='${db:Status-Status}\n' 'rsyslog' 2>/dev/null | grep -q installed; then
    
    # List of log file paths to be inspected for correct permissions
    # * Primarily inspect log file paths listed in /etc/rsyslog.conf
    RSYSLOG_ETC_CONFIG="/etc/rsyslog.conf"
    # * And also the log file paths listed after rsyslog's $IncludeConfig directive
    #   (store the result into array for the case there's shell glob used as value of IncludeConfig)
    readarray -t OLD_INC < <(grep -e "\$IncludeConfig[[:space:]]\+[^[:space:];]\+" /etc/rsyslog.conf | cut -d ' ' -f 2)
    readarray -t RSYSLOG_INCLUDE_CONFIG < <(for INCPATH in "${OLD_INC[@]}"; do eval printf '%s\\n' "${INCPATH}"; done)
    readarray -t NEW_INC < <(sed -n '/^\s*include(/,/)/Ip' /etc/rsyslog.conf | sed -n 's@.*file\s*=\s*"\([/[:alnum:][:punct:]]*\)".*@\1@Ip')
    readarray -t RSYSLOG_INCLUDE < <(for INCPATH in "${NEW_INC[@]}"; do eval printf '%s\\n' "${INCPATH}"; done)
    
    # Declare an array to hold the final list of different log file paths
    declare -a LOG_FILE_PATHS
    
    # Array to hold all rsyslog config entries
    RSYSLOG_CONFIGS=()
    RSYSLOG_CONFIGS=("${RSYSLOG_ETC_CONFIG}" "${RSYSLOG_INCLUDE_CONFIG[@]}" "${RSYSLOG_INCLUDE[@]}")
    
    # Get full list of files to be checked
    # RSYSLOG_CONFIGS may contain globs such as
    # /etc/rsyslog.d/*.conf /etc/rsyslog.d/*.frule
    # So, loop over the entries in RSYSLOG_CONFIGS and use find to get the list of included files.
    RSYSLOG_CONFIG_FILES=()
    for ENTRY in "${RSYSLOG_CONFIGS[@]}"
    do
    	# If directory, rsyslog will search for config files in recursively.
    	# However, files in hidden sub-directories or hidden files will be ignored.
    	if [ -d "${ENTRY}" ]
    	then
    		readarray -t FINDOUT < <(find "${ENTRY}" -not -path '*/.*' -type f)
    		RSYSLOG_CONFIG_FILES+=("${FINDOUT[@]}")
    	elif [ -f "${ENTRY}" ]
    	then
    		RSYSLOG_CONFIG_FILES+=("${ENTRY}")
    	else
    		echo "Invalid include object: ${ENTRY}"
    	fi
    done
    
    # Browse each file selected above as containing paths of log files
    # ('/etc/rsyslog.conf' and '/etc/rsyslog.d/*.conf' in the default configuration)
    for LOG_FILE in "${RSYSLOG_CONFIG_FILES[@]}"
    do
    	# From each of these files extract just particular log file path(s), thus:
    	# * Ignore lines starting with space (' '), comment ('#"), or variable syntax ('$') characters,
    	# * Ignore empty lines,
    	# * Strip quotes and closing brackets from paths.
    	# * Ignore paths that match /dev|/etc.*\.conf, as those are paths, but likely not log files
    	# * From the remaining valid rows select only fields constituting a log file path
    	# Text file column is understood to represent a log file path if and only if all of the
    	# following are met:
    	# * it contains at least one slash '/' character,
    	# * it is preceded by space
    	# * it doesn't contain space (' '), colon (':'), and semicolon (';') characters
    	# Search log file for path(s) only in case it exists!
    	if [[ -f "${LOG_FILE}" ]]
    	then
    		NORMALIZED_CONFIG_FILE_LINES=$(sed -e "/^[#|$]/d" "${LOG_FILE}")
    		LINES_WITH_PATHS=$(grep '[^/]*\s\+\S*/\S\+$' <<< "${NORMALIZED_CONFIG_FILE_LINES}")
    		FILTERED_PATHS=$(awk '{if(NF>=2&&($NF~/^\//||$NF~/^-\//)){sub(/^-\//,"/",$NF);print $NF}}' <<< "${LINES_WITH_PATHS}")
    		CLEANED_PATHS=$(sed -e "s/[\"')]//g; /\\/etc.*\.conf/d; /\\/dev\\//d" <<< "${FILTERED_PATHS}")
    		MATCHED_ITEMS=$(sed -e "/^$/d" <<< "${CLEANED_PATHS}")
    		# Since above sed command might return more than one item (delimited by newline), split
    		# the particular matches entries into new array specific for this log file
    		readarray -t ARRAY_FOR_LOG_FILE <<< "$MATCHED_ITEMS"
    		# Concatenate the two arrays - previous content of $LOG_FILE_PATHS array with
    		# items from newly created array for this log file
    		LOG_FILE_PATHS+=("${ARRAY_FOR_LOG_FILE[@]}")
    		# Delete the temporary array
    		unset ARRAY_FOR_LOG_FILE
    	fi
    done
    
    # Check for RainerScript action log format which might be also multiline so grep regex is a bit
    # curly:
    # extract possibly multiline action omfile expressions
    # extract File="logfile" expression
    # match only "logfile" expression
    for LOG_FILE in "${RSYSLOG_CONFIG_FILES[@]}"
    do
    	ACTION_OMFILE_LINES=$(grep -iozP "action\s*\(\s*type\s*=\s*\"omfile\"[^\)]*\)" "${LOG_FILE}")
    	OMFILE_LINES=$(echo "${ACTION_OMFILE_LINES}"| grep -iaoP "\bFile\s*=\s*\"([/[:alnum:][:punct:]]*)\"\s*\)")
    	LOG_FILE_PATHS+=("$(echo "${OMFILE_LINES}"| grep -oE "\"([/[:alnum:][:punct:]]*)\""|tr -d "\"")")
    done
    
    # Ensure the correct attribute if file exists
    FILE_CMD="chmod"
    for LOG_FILE_PATH in "${LOG_FILE_PATHS[@]}"
    do
    	# Sanity check - if particular $LOG_FILE_PATH is empty string, skip it from further processing
    	if [ -z "$LOG_FILE_PATH" ]
    	then
    		continue
    	fi
    	$FILE_CMD "0640" "$LOG_FILE_PATH"
    done
    
    else
        >&2 echo 'Remediation is not applicable, nothing was done'
    fi
    

    Complexity:low
    Disruption:medium
    Reboot:false
    Strategy:configure
    - name: Gather the package facts
      package_facts:
        manager: auto
      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 - 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: |
        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: |
        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: |
        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: |
        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
    
    Group   Ensure All Logs are Rotated by logrotate   Group contains 1 rule
    [ref]   Edit the file /etc/logrotate.d/syslog. Find the first line, which should look like this (wrapped for clarity):
    /var/log/messages /var/log/secure /var/log/maillog /var/log/spooler \
      /var/log/boot.log /var/log/cron {
    Edit this line so that it contains a one-space-separated listing of each log file referenced in /etc/rsyslog.conf.

    All logs in use on a system must be rotated regularly, or the log files will consume disk space over time, eventually interfering with system operation. The file /etc/logrotate.d/syslog is the configuration file used by the logrotate program to maintain all log files written by syslog. By default, it rotates logs weekly and stores four archival copies of each log. These settings can be modified by editing /etc/logrotate.conf, but the defaults are sufficient for purposes of this guide.

    Note that logrotate is run nightly by the cron job /etc/cron.daily/logrotate. If particularly active logs need to be rotated more often than once a day, some other mechanism must be used.

    Rule   Ensure Logrotate Runs Periodically   [ref]

    The logrotate utility allows for the automatic rotation of log files. The frequency of rotation is specified in /etc/logrotate.conf, which triggers a cron task or a timer. To configure logrotate to run daily, add or correct the following line in /etc/logrotate.conf:
    # rotate log files frequency
    daily
    Rationale:
    Log files that are not properly rotated run the risk of growing so large that they fill up the /var/log partition. Valuable logging information could be lost if the /var/log partition becomes full.
    Severity: 
    medium
    Rule ID:xccdf_org.ssgproject.content_rule_ensure_logrotate_activated
    References:
    cis-csc1, 14, 15, 16, 3, 5, 6
    cobit5APO11.04, BAI03.05, DSS05.04, DSS05.07, MEA02.01
    disaCCI-000366
    isa-62443-20094.3.3.3.9, 4.3.3.5.8, 4.3.4.4.7, 4.4.2.1, 4.4.2.2, 4.4.2.4
    isa-62443-2013SR 2.10, SR 2.11, SR 2.12, SR 2.8, SR 2.9
    iso27001-2013A.12.4.1, A.12.4.2, A.12.4.3, A.12.4.4, A.12.7.1
    nistCM-6(a)
    nist-csfPR.PT-1
    pcidssReq-10.7
    anssiR71

    # Remediation is applicable only in certain platforms
    if dpkg-query --show --showformat='${db:Status-Status}
    ' 'linux-base' 2>/dev/null | grep -q ^installed && { dpkg-query --show --showformat='${db:Status-Status}\n' 'logrotate' 2>/dev/null | grep -q installed; }; then
    
    LOGROTATE_CONF_FILE="/etc/logrotate.conf"
    
    DEBIAN_FRONTEND=noninteractive apt-get install -y "crontabs"
    CRON_DAILY_LOGROTATE_FILE="/etc/cron.daily/logrotate"
    
    
    # daily rotation is configured
    grep -q "^daily$" $LOGROTATE_CONF_FILE|| echo "daily" >> $LOGROTATE_CONF_FILE
    
    # remove any line configuring weekly, monthly or yearly rotation
    sed -i '/^\s*\(weekly\|monthly\|yearly\).*$/d' $LOGROTATE_CONF_FILE
    
    
    # configure cron.daily if not already
    if ! grep -q "^[[:space:]]*/usr/sbin/logrotate[[:alnum:][:blank:][:punct:]]*$LOGROTATE_CONF_FILE$" $CRON_DAILY_LOGROTATE_FILE; then
    	echo '#!/bin/sh' > $CRON_DAILY_LOGROTATE_FILE
    	echo "/usr/sbin/logrotate $LOGROTATE_CONF_FILE" >> $CRON_DAILY_LOGROTATE_FILE
    fi
    
    else
        >&2 echo 'Remediation is not applicable, nothing was done'
    fi
    

    Complexity:low
    Disruption:low
    Reboot:false
    Strategy:configure
    - name: Gather the package facts
      package_facts:
        manager: auto
      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 daily log rotation in /etc/logrotate.conf
      lineinfile:
        create: true
        dest: /etc/logrotate.conf
        regexp: ^daily$
        line: daily
      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 overriden in /etc/logrotate.conf
      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
        lineinfile:
          path: /etc/cron.daily/logrotate
          line: '#!/bin/sh'
          insertbefore: BOF
          create: true
    
      - name: Add logrotate call
        lineinfile:
          path: /etc/cron.daily/logrotate
          line: /usr/sbin/logrotate /etc/logrotate.conf
          regexp: ^[\s]*/usr/sbin/logrotate[\s\S]*/etc/logrotate.conf$
      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
    
    Group   Configure rsyslogd to Accept Remote Messages If Acting as a Log Server   Group contains 2 rules
    [ref]   By default, rsyslog does not listen over the network for log messages. If needed, modules can be enabled to allow the rsyslog daemon to receive messages from other systems and for the system thus to act as a log server. If the system is not a log server, then lines concerning these modules should remain commented out.

    Rule   Ensure syslog-ng is Installed   [ref]

    syslog-ng can be installed in replacement of rsyslog. The syslog-ng-core package can be installed with the following command:
    $ apt-get install syslog-ng-core
    Rationale:
    The syslog-ng-core package provides the syslog-ng daemon, which provides system logging services.
    Severity: 
    medium
    Rule ID:xccdf_org.ssgproject.content_rule_package_syslogng_installed
    References:
    cis-csc1, 14, 15, 16, 3, 5, 6
    cobit5APO11.04, BAI03.05, DSS05.04, DSS05.07, MEA02.01
    disaCCI-001311, CCI-001312
    isa-62443-20094.3.3.3.9, 4.3.3.5.8, 4.3.4.4.7, 4.4.2.1, 4.4.2.2, 4.4.2.4
    isa-62443-2013SR 2.10, SR 2.11, SR 2.12, SR 2.8, SR 2.9
    iso27001-2013A.12.4.1, A.12.4.2, A.12.4.3, A.12.4.4, A.12.7.1
    nistCM-6(a)
    nist-csfPR.PT-1

    Complexity:low
    Disruption:low
    Reboot:false
    Strategy:enable
    # Remediation is applicable only in certain platforms
    if dpkg-query --show --showformat='${db:Status-Status}
    ' 'linux-base' 2>/dev/null | grep -q ^installed; then
    
    DEBIAN_FRONTEND=noninteractive apt-get install -y "syslog-ng"
    
    else
        >&2 echo 'Remediation is not applicable, nothing was done'
    fi
    

    
    [[packages]]
    name = "syslog-ng"
    version = "*"
    

    Complexity:low
    Disruption:low
    Reboot:false
    Strategy:enable
    - name: Gather the package facts
      package_facts:
        manager: auto
      tags:
      - NIST-800-53-CM-6(a)
      - enable_strategy
      - low_complexity
      - low_disruption
      - medium_severity
      - no_reboot_needed
      - package_syslogng_installed
    
    - name: Ensure syslog-ng is installed
      package:
        name: syslog-ng
        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_syslogng_installed
    

    Complexity:low
    Disruption:low
    Reboot:false
    Strategy:enable
    include install_syslog-ng
    
    class install_syslog-ng {
      package { 'syslog-ng':
        ensure => 'installed',
      }
    }
    

    Rule   Enable syslog-ng Service   [ref]

    The syslog-ng service (in replacement of rsyslog) provides syslog-style logging by default on Debian. The syslog-ng service can be enabled with the following command:
    $ sudo systemctl enable syslog-ng.service
    Rationale:
    The syslog-ng service must be running in order to provide logging services, which are essential to system administration.
    Severity: 
    medium
    Rule ID:xccdf_org.ssgproject.content_rule_service_syslogng_enabled
    References:
    cis-csc1, 12, 13, 14, 15, 16, 2, 3, 5, 6, 7, 8, 9
    cobit5APO10.01, APO10.03, APO10.04, APO10.05, APO11.04, APO13.01, BAI03.05, BAI04.04, DSS01.03, DSS03.05, DSS05.02, DSS05.04, DSS05.05, DSS05.07, MEA01.01, MEA01.02, MEA01.03, MEA01.04, MEA01.05, MEA02.01
    disaCCI-001311, CCI-001312, CCI-001557, CCI-001851
    isa-62443-20094.3.2.6.7, 4.3.3.3.9, 4.3.3.5.8, 4.3.4.4.7, 4.4.2.1, 4.4.2.2, 4.4.2.4
    isa-62443-2013SR 2.10, SR 2.11, SR 2.12, SR 2.8, SR 2.9, SR 6.1, SR 6.2, SR 7.1, SR 7.2
    iso27001-2013A.12.1.3, A.12.4.1, A.12.4.2, A.12.4.3, A.12.4.4, A.12.7.1, A.14.2.7, A.15.2.1, A.15.2.2, A.17.2.1
    nistCM-6(a), AU-4(1)
    nist-csfDE.CM-1, DE.CM-3, DE.CM-7, ID.SC-4, PR.DS-4, PR.PT-1

    
    [customizations.services]
    enabled = ["syslog-ng"]
    

    Complexity:low
    Disruption:low
    Reboot:false
    Strategy:enable
    - name: Gather the package facts
      package_facts:
        manager: auto
      tags:
      - NIST-800-53-AU-4(1)
      - NIST-800-53-CM-6(a)
      - enable_strategy
      - low_complexity
      - low_disruption
      - medium_severity
      - no_reboot_needed
      - service_syslogng_enabled
    
    - name: Enable syslog-ng Service - Enable service syslog-ng
      block:
    
      - name: Gather the package facts
        package_facts:
          manager: auto
    
      - name: Enable syslog-ng Service - Enable Service syslog-ng
        ansible.builtin.systemd:
          name: syslog-ng
          enabled: true
          state: started
          masked: false
        when:
        - '"syslog-ng" in ansible_facts.packages'
      when: '"linux-base" in ansible_facts.packages'
      tags:
      - NIST-800-53-AU-4(1)
      - NIST-800-53-CM-6(a)
      - enable_strategy
      - low_complexity
      - low_disruption
      - medium_severity
      - no_reboot_needed
      - service_syslogng_enabled
    

    Complexity:low
    Disruption:low
    Reboot:false
    Strategy:enable
    include enable_syslog-ng
    
    class enable_syslog-ng {
      service {'syslog-ng':
        enable => true,
        ensure => 'running',
      }
    }
    

    Rule   Ensure rsyslog is Installed   [ref]

    Rsyslog is installed by default. The rsyslog package can be installed with the following command:
     $ apt-get install rsyslog
    Rationale:
    The rsyslog package provides the rsyslog daemon, which provides system logging services.
    Severity: 
    medium
    Rule ID:xccdf_org.ssgproject.content_rule_package_rsyslog_installed
    References:
    cis-csc1, 14, 15, 16, 3, 5, 6
    cobit5APO11.04, BAI03.05, DSS05.04, DSS05.07, MEA02.01
    disaCCI-000366, CCI-000154, CCI-001851
    hipaa164.312(a)(2)(ii)
    isa-62443-20094.3.3.3.9, 4.3.3.5.8, 4.3.4.4.7, 4.4.2.1, 4.4.2.2, 4.4.2.4
    isa-62443-2013SR 2.10, SR 2.11, SR 2.12, SR 2.8, SR 2.9
    iso27001-2013A.12.4.1, A.12.4.2, A.12.4.3, A.12.4.4, A.12.7.1
    nistCM-6(a)
    nist-csfPR.PT-1
    os-srgSRG-OS-000479-GPOS-00224, SRG-OS-000051-GPOS-00024, SRG-OS-000480-GPOS-00227

    Complexity:low
    Disruption:low
    Reboot:false
    Strategy:enable
    # Remediation is applicable only in certain platforms
    if dpkg-query --show --showformat='${db:Status-Status}
    ' 'linux-base' 2>/dev/null | grep -q ^installed; then
    
    DEBIAN_FRONTEND=noninteractive apt-get install -y "rsyslog"
    
    else
        >&2 echo 'Remediation is not applicable, nothing was done'
    fi
    

    
    [[packages]]
    name = "rsyslog"
    version = "*"
    

    Complexity:low
    Disruption:low
    Reboot:false
    Strategy:enable
    - name: Gather the package facts
      package_facts:
        manager: auto
      tags:
      - NIST-800-53-CM-6(a)
      - enable_strategy
      - low_complexity
      - low_disruption
      - medium_severity
      - no_reboot_needed
      - package_rsyslog_installed
    
    - name: Ensure rsyslog is installed
      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
    

    Complexity:low
    Disruption:low
    Reboot:false
    Strategy:enable
    include install_rsyslog
    
    class install_rsyslog {
      package { 'rsyslog':
        ensure => 'installed',
      }
    }
    

    Rule   Enable rsyslog Service   [ref]

    The rsyslog service provides syslog-style logging by default on Debian 12. The rsyslog service can be enabled with the following command:
    $ sudo systemctl enable rsyslog.service
    Rationale:
    The rsyslog service must be running in order to provide logging services, which are essential to system administration.
    Severity: 
    medium
    Rule ID:xccdf_org.ssgproject.content_rule_service_rsyslog_enabled
    References:
    cis-csc1, 12, 13, 14, 15, 16, 2, 3, 5, 6, 7, 8, 9
    cobit5APO10.01, APO10.03, APO10.04, APO10.05, APO11.04, APO13.01, BAI03.05, BAI04.04, DSS01.03, DSS03.05, DSS05.02, DSS05.04, DSS05.05, DSS05.07, MEA01.01, MEA01.02, MEA01.03, MEA01.04, MEA01.05, MEA02.01
    disaCCI-000366
    hipaa164.312(a)(2)(ii)
    isa-62443-20094.3.2.6.7, 4.3.3.3.9, 4.3.3.5.8, 4.3.4.4.7, 4.4.2.1, 4.4.2.2, 4.4.2.4
    isa-62443-2013SR 2.10, SR 2.11, SR 2.12, SR 2.8, SR 2.9, SR 6.1, SR 6.2, SR 7.1, SR 7.2
    iso27001-2013A.12.1.3, A.12.4.1, A.12.4.2, A.12.4.3, A.12.4.4, A.12.7.1, A.14.2.7, A.15.2.1, A.15.2.2, A.17.2.1
    nistCM-6(a), AU-4(1)
    nist-csfDE.CM-1, DE.CM-3, DE.CM-7, ID.SC-4, PR.DS-4, PR.PT-1
    os-srgSRG-OS-000480-GPOS-00227

    
    [customizations.services]
    enabled = ["rsyslog"]
    

    Complexity:low
    Disruption:low
    Reboot:false
    Strategy:enable
    - name: Gather the package facts
      package_facts:
        manager: auto
      tags:
      - 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
    
    - name: Enable rsyslog Service - Enable service rsyslog
      block:
    
      - name: Gather the package facts
        package_facts:
          manager: auto
    
      - name: Enable rsyslog Service - Enable Service rsyslog
        ansible.builtin.systemd:
          name: rsyslog
          enabled: true
          state: started
          masked: false
        when:
        - '"rsyslog" in ansible_facts.packages'
      when: '"linux-base" in ansible_facts.packages'
      tags:
      - 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
    

    Complexity:low
    Disruption:low
    Reboot:false
    Strategy:enable
    include enable_rsyslog
    
    class enable_rsyslog {
      service {'rsyslog':
        enable => true,
        ensure => 'running',
      }
    }
    
    Group   File Permissions and Masks   Group contains 5 groups and 17 rules
    [ref]   Traditional Unix security relies heavily on file and directory permissions to prevent unauthorized users from reading or modifying files to which they should not have access.

    Several of the commands in this section search filesystems for files or directories with certain characteristics, and are intended to be run on every local partition on a given system. When the variable PART appears in one of the commands below, it means that the command is intended to be run repeatedly, with the name of each local partition substituted for PART in turn.

    The following command prints a list of all xfs partitions on the local system, which is the default filesystem for Debian 12 installations:
    $ mount -t xfs | awk '{print $3}'
    For any systems that use a different local filesystem type, modify this command as appropriate.
    Group   Verify Permissions on Important Files and Directories   Group contains 1 group and 15 rules
    [ref]   Permissions for many files on a system must be set restrictively to ensure sensitive information is properly protected. This section discusses important permission restrictions which can be verified to ensure that no harmful discrepancies have arisen.
    Group   Verify Permissions on Files with Local Account Information and Credentials   Group contains 12 rules

    Rule   Verify Group Who Owns group File   [ref]

    To properly set the group owner of /etc/group, run the command:
    $ sudo chgrp root /etc/group
    Rationale:
    The /etc/group file contains information regarding groups that are configured on the system. Protection of this file is important for system security.
    Severity: 
    medium
    Rule ID:xccdf_org.ssgproject.content_rule_file_groupowner_etc_group
    References:
    cis-csc12, 13, 14, 15, 16, 18, 3, 5
    cjis5.5.2.2
    cobit5APO01.06, DSS05.04, DSS05.07, DSS06.02
    disaCCI-000366
    isa-62443-20094.3.3.7.3
    isa-62443-2013SR 2.1, SR 5.2
    iso27001-2013A.10.1.1, A.11.1.4, A.11.1.5, A.11.2.1, A.13.1.1, A.13.1.3, A.13.2.1, A.13.2.3, A.13.2.4, A.14.1.2, A.14.1.3, A.6.1.2, A.7.1.1, A.7.1.2, A.7.3.1, A.8.2.2, A.8.2.3, A.9.1.1, A.9.1.2, A.9.2.3, A.9.4.1, A.9.4.4, A.9.4.5
    nerc-cipCIP-003-8 R5.1.1, CIP-003-8 R5.3, CIP-004-6 R2.3, CIP-007-3 R2.1, CIP-007-3 R2.2, CIP-007-3 R2.3, CIP-007-3 R5.1, CIP-007-3 R5.1.1, CIP-007-3 R5.1.2
    nistCM-6(a), AC-6(1)
    nist-csfPR.AC-4, PR.DS-5
    pcidssReq-8.7.c
    os-srgSRG-OS-000480-GPOS-00227
    anssiR50
    pcidss42.2.6, 2.2

    Complexity:low
    Disruption:low
    Reboot:false
    Strategy:configure
    chgrp 0 /etc/group
    

    Complexity:low
    Disruption:low
    Reboot:false
    Strategy:configure
    - name: Test for existence /etc/group
      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 0 on /etc/group
      file:
        path: /etc/group
        group: '0'
      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
    

    Rule   Verify Group Who Owns gshadow File   [ref]

    To properly set the group owner of /etc/gshadow, run the command:
    $ sudo chgrp shadow /etc/gshadow
    Rationale:
    The /etc/gshadow file contains group password hashes. Protection of this file is critical for system security.
    Severity: 
    medium
    Rule ID:xccdf_org.ssgproject.content_rule_file_groupowner_etc_gshadow
    References:
    cis-csc12, 13, 14, 15, 16, 18, 3, 5
    cobit5APO01.06, DSS05.04, DSS05.07, DSS06.02
    disaCCI-000366
    isa-62443-20094.3.3.7.3
    isa-62443-2013SR 2.1, SR 5.2
    iso27001-2013A.10.1.1, A.11.1.4, A.11.1.5, A.11.2.1, A.13.1.1, A.13.1.3, A.13.2.1, A.13.2.3, A.13.2.4, A.14.1.2, A.14.1.3, A.6.1.2, A.7.1.1, A.7.1.2, A.7.3.1, A.8.2.2, A.8.2.3, A.9.1.1, A.9.1.2, A.9.2.3, A.9.4.1, A.9.4.4, A.9.4.5
    nerc-cipCIP-003-8 R5.1.1, CIP-003-8 R5.3, CIP-004-6 R2.3, CIP-007-3 R2.1, CIP-007-3 R2.2, CIP-007-3 R2.3, CIP-007-3 R5.1, CIP-007-3 R5.1.1, CIP-007-3 R5.1.2
    nistCM-6(a), AC-6(1)
    nist-csfPR.AC-4, PR.DS-5
    os-srgSRG-OS-000480-GPOS-00227
    anssiR50

    Complexity:low
    Disruption:low
    Reboot:false
    Strategy:configure
    chgrp 42 /etc/gshadow
    

    Complexity:low
    Disruption:low
    Reboot:false
    Strategy:configure
    - name: Test for existence /etc/gshadow
      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 42 on /etc/gshadow
      file:
        path: /etc/gshadow
        group: '42'
      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
    

    Rule   Verify Group Who Owns passwd File   [ref]

    To properly set the group owner of /etc/passwd, run the command:
    $ sudo chgrp root /etc/passwd
    Rationale:
    The /etc/passwd file contains information about the users that are configured on the system. Protection of this file is critical for system security.
    Severity: 
    medium
    Rule ID:xccdf_org.ssgproject.content_rule_file_groupowner_etc_passwd
    References:
    cis-csc12, 13, 14, 15, 16, 18, 3, 5
    cjis5.5.2.2
    cobit5APO01.06, DSS05.04, DSS05.07, DSS06.02
    disaCCI-000366
    isa-62443-20094.3.3.7.3
    isa-62443-2013SR 2.1, SR 5.2
    iso27001-2013A.10.1.1, A.11.1.4, A.11.1.5, A.11.2.1, A.13.1.1, A.13.1.3, A.13.2.1, A.13.2.3, A.13.2.4, A.14.1.2, A.14.1.3, A.6.1.2, A.7.1.1, A.7.1.2, A.7.3.1, A.8.2.2, A.8.2.3, A.9.1.1, A.9.1.2, A.9.2.3, A.9.4.1, A.9.4.4, A.9.4.5
    nerc-cipCIP-003-8 R5.1.1, CIP-003-8 R5.3, CIP-004-6 R2.3, CIP-007-3 R2.1, CIP-007-3 R2.2, CIP-007-3 R2.3, CIP-007-3 R5.1, CIP-007-3 R5.1.1, CIP-007-3 R5.1.2
    nistCM-6(a), AC-6(1)
    nist-csfPR.AC-4, PR.DS-5
    pcidssReq-8.7.c
    os-srgSRG-OS-000480-GPOS-00227
    anssiR50
    pcidss42.2.6, 2.2

    Complexity:low
    Disruption:low
    Reboot:false
    Strategy:configure
    chgrp 0 /etc/passwd
    

    Complexity:low
    Disruption:low
    Reboot:false
    Strategy:configure
    - name: Test for existence /etc/passwd
      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 0 on /etc/passwd
      file:
        path: /etc/passwd
        group: '0'
      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
    

    Rule   Verify Group Who Owns shadow File   [ref]

    To properly set the group owner of /etc/shadow, run the command:
    $ sudo chgrp shadow /etc/shadow
    Rationale:
    The /etc/shadow file stores password hashes. Protection of this file is critical for system security.
    Severity: 
    medium
    Rule ID:xccdf_org.ssgproject.content_rule_file_groupowner_etc_shadow
    References:
    cis-csc12, 13, 14, 15, 16, 18, 3, 5
    cjis5.5.2.2
    cobit5APO01.06, DSS05.04, DSS05.07, DSS06.02
    disaCCI-000366
    isa-62443-20094.3.3.7.3
    isa-62443-2013SR 2.1, SR 5.2
    iso27001-2013A.10.1.1, A.11.1.4, A.11.1.5, A.11.2.1, A.13.1.1, A.13.1.3, A.13.2.1, A.13.2.3, A.13.2.4, A.14.1.2, A.14.1.3, A.6.1.2, A.7.1.1, A.7.1.2, A.7.3.1, A.8.2.2, A.8.2.3, A.9.1.1, A.9.1.2, A.9.2.3, A.9.4.1, A.9.4.4, A.9.4.5
    nerc-cipCIP-003-8 R5.1.1, CIP-003-8 R5.3, CIP-004-6 R2.3, CIP-007-3 R2.1, CIP-007-3 R2.2, CIP-007-3 R2.3, CIP-007-3 R5.1, CIP-007-3 R5.1.1, CIP-007-3 R5.1.2
    nistCM-6(a), AC-6(1)
    nist-csfPR.AC-4, PR.DS-5
    pcidssReq-8.7.c
    os-srgSRG-OS-000480-GPOS-00227
    anssiR50
    pcidss42.2.6, 2.2

    Complexity:low
    Disruption:low
    Reboot:false
    Strategy:configure
    chgrp 42 /etc/shadow
    

    Complexity:low
    Disruption:low
    Reboot:false
    Strategy:configure
    - name: Test for existence /etc/shadow
      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 42 on /etc/shadow
      file:
        path: /etc/shadow
        group: '42'
      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
    

    Rule   Verify User Who Owns group File   [ref]

    To properly set the owner of /etc/group, run the command:
    $ sudo chown root /etc/group 
    Rationale:
    The /etc/group file contains information regarding groups that are configured on the system. Protection of this file is important for system security.
    Severity: 
    medium
    Rule ID:xccdf_org.ssgproject.content_rule_file_owner_etc_group
    References:
    cis-csc12, 13, 14, 15, 16, 18, 3, 5
    cjis5.5.2.2
    cobit5APO01.06, DSS05.04, DSS05.07, DSS06.02
    disaCCI-000366
    isa-62443-20094.3.3.7.3
    isa-62443-2013SR 2.1, SR 5.2
    iso27001-2013A.10.1.1, A.11.1.4, A.11.1.5, A.11.2.1, A.13.1.1, A.13.1.3, A.13.2.1, A.13.2.3, A.13.2.4, A.14.1.2, A.14.1.3, A.6.1.2, A.7.1.1, A.7.1.2, A.7.3.1, A.8.2.2, A.8.2.3, A.9.1.1, A.9.1.2, A.9.2.3, A.9.4.1, A.9.4.4, A.9.4.5
    nerc-cipCIP-003-8 R5.1.1, CIP-003-8 R5.3, CIP-004-6 R2.3, CIP-007-3 R2.1, CIP-007-3 R2.2, CIP-007-3 R2.3, CIP-007-3 R5.1, CIP-007-3 R5.1.1, CIP-007-3 R5.1.2
    nistCM-6(a), AC-6(1)
    nist-csfPR.AC-4, PR.DS-5
    pcidssReq-8.7.c
    os-srgSRG-OS-000480-GPOS-00227
    anssiR50
    pcidss42.2.6, 2.2

    Complexity:low
    Disruption:low
    Reboot:false
    Strategy:configure
    chown 0 /etc/group
    

    Complexity:low
    Disruption:low
    Reboot:false
    Strategy:configure
    - name: Test for existence /etc/group
      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 0 on /etc/group
      file:
        path: /etc/group
        owner: '0'
      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
    

    Rule   Verify User Who Owns gshadow File   [ref]

    To properly set the owner of /etc/gshadow, run the command:
    $ sudo chown root /etc/gshadow 
    Rationale:
    The /etc/gshadow file contains group password hashes. Protection of this file is critical for system security.
    Severity: 
    medium
    Rule ID:xccdf_org.ssgproject.content_rule_file_owner_etc_gshadow
    References:
    cis-csc12, 13, 14, 15, 16, 18, 3, 5
    cobit5APO01.06, DSS05.04, DSS05.07, DSS06.02
    disaCCI-000366
    isa-62443-20094.3.3.7.3
    isa-62443-2013SR 2.1, SR 5.2
    iso27001-2013A.10.1.1, A.11.1.4, A.11.1.5, A.11.2.1, A.13.1.1, A.13.1.3, A.13.2.1, A.13.2.3, A.13.2.4, A.14.1.2, A.14.1.3, A.6.1.2, A.7.1.1, A.7.1.2, A.7.3.1, A.8.2.2, A.8.2.3, A.9.1.1, A.9.1.2, A.9.2.3, A.9.4.1, A.9.4.4, A.9.4.5
    nerc-cipCIP-003-8 R5.1.1, CIP-003-8 R5.3, CIP-004-6 R2.3, CIP-007-3 R2.1, CIP-007-3 R2.2, CIP-007-3 R2.3, CIP-007-3 R5.1, CIP-007-3 R5.1.1, CIP-007-3 R5.1.2
    nistCM-6(a), AC-6(1)
    nist-csfPR.AC-4, PR.DS-5
    os-srgSRG-OS-000480-GPOS-00227
    anssiR50

    Complexity:low
    Disruption:low
    Reboot:false
    Strategy:configure
    chown 0 /etc/gshadow
    

    Complexity:low
    Disruption:low
    Reboot:false
    Strategy:configure
    - name: Test for existence /etc/gshadow
      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 0 on /etc/gshadow
      file:
        path: /etc/gshadow
        owner: '0'
      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
    

    Rule   Verify User Who Owns passwd File   [ref]

    To properly set the owner of /etc/passwd, run the command:
    $ sudo chown root /etc/passwd 
    Rationale:
    The /etc/passwd file contains information about the users that are configured on the system. Protection of this file is critical for system security.
    Severity: 
    medium
    Rule ID:xccdf_org.ssgproject.content_rule_file_owner_etc_passwd
    References:
    cis-csc12, 13, 14, 15, 16, 18, 3, 5
    cjis5.5.2.2
    cobit5APO01.06, DSS05.04, DSS05.07, DSS06.02
    disaCCI-000366
    isa-62443-20094.3.3.7.3
    isa-62443-2013SR 2.1, SR 5.2
    iso27001-2013A.10.1.1, A.11.1.4, A.11.1.5, A.11.2.1, A.13.1.1, A.13.1.3, A.13.2.1, A.13.2.3, A.13.2.4, A.14.1.2, A.14.1.3, A.6.1.2, A.7.1.1, A.7.1.2, A.7.3.1, A.8.2.2, A.8.2.3, A.9.1.1, A.9.1.2, A.9.2.3, A.9.4.1, A.9.4.4, A.9.4.5
    nerc-cipCIP-003-8 R5.1.1, CIP-003-8 R5.3, CIP-004-6 R2.3, CIP-007-3 R2.1, CIP-007-3 R2.2, CIP-007-3 R2.3, CIP-007-3 R5.1, CIP-007-3 R5.1.1, CIP-007-3 R5.1.2
    nistCM-6(a), AC-6(1)
    nist-csfPR.AC-4, PR.DS-5
    pcidssReq-8.7.c
    os-srgSRG-OS-000480-GPOS-00227
    anssiR50
    pcidss42.2.6, 2.2

    Complexity:low
    Disruption:low
    Reboot:false
    Strategy:configure
    chown 0 /etc/passwd
    

    Complexity:low
    Disruption:low
    Reboot:false
    Strategy:configure
    - name: Test for existence /etc/passwd
      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 0 on /etc/passwd
      file:
        path: /etc/passwd
        owner: '0'
      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
    

    Rule   Verify User Who Owns shadow File   [ref]

    To properly set the owner of /etc/shadow, run the command:
    $ sudo chown root /etc/shadow 
    Rationale:
    The /etc/shadow file contains the list of local system accounts and stores password hashes. Protection of this file is critical for system security. Failure to give ownership of this file to root provides the designated owner with access to sensitive information which could weaken the system security posture.
    Severity: 
    medium
    Rule ID:xccdf_org.ssgproject.content_rule_file_owner_etc_shadow
    References:
    cis-csc12, 13, 14, 15, 16, 18, 3, 5
    cjis5.5.2.2
    cobit5APO01.06, DSS05.04, DSS05.07, DSS06.02
    disaCCI-000366
    isa-62443-20094.3.3.7.3
    isa-62443-2013SR 2.1, SR 5.2
    iso27001-2013A.10.1.1, A.11.1.4, A.11.1.5, A.11.2.1, A.13.1.1, A.13.1.3, A.13.2.1, A.13.2.3, A.13.2.4, A.14.1.2, A.14.1.3, A.6.1.2, A.7.1.1, A.7.1.2, A.7.3.1, A.8.2.2, A.8.2.3, A.9.1.1, A.9.1.2, A.9.2.3, A.9.4.1, A.9.4.4, A.9.4.5
    nerc-cipCIP-003-8 R5.1.1, CIP-003-8 R5.3, CIP-004-6 R2.3, CIP-007-3 R2.1, CIP-007-3 R2.2, CIP-007-3 R2.3, CIP-007-3 R5.1, CIP-007-3 R5.1.1, CIP-007-3 R5.1.2
    nistCM-6(a), AC-6(1)
    nist-csfPR.AC-4, PR.DS-5
    pcidssReq-8.7.c
    os-srgSRG-OS-000480-GPOS-00227
    anssiR50
    pcidss42.2.6, 2.2

    Complexity:low
    Disruption:low
    Reboot:false
    Strategy:configure
    chown 0 /etc/shadow
    

    Complexity:low
    Disruption:low
    Reboot:false
    Strategy:configure
    - name: Test for existence /etc/shadow
      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 0 on /etc/shadow
      file:
        path: /etc/shadow
        owner: '0'
      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
    

    Rule   Verify Permissions on group File   [ref]

    To properly set the permissions of /etc/group, run the command:
    $ sudo chmod 0644 /etc/group
    Rationale:
    The /etc/group file contains information regarding groups that are configured on the system. Protection of this file is important for system security.
    Severity: 
    medium
    Rule ID:xccdf_org.ssgproject.content_rule_file_permissions_etc_group
    References:
    cis-csc12, 13, 14, 15, 16, 18, 3, 5
    cjis5.5.2.2
    cobit5APO01.06, DSS05.04, DSS05.07, DSS06.02
    disaCCI-000366
    isa-62443-20094.3.3.7.3
    isa-62443-2013SR 2.1, SR 5.2
    iso27001-2013A.10.1.1, A.11.1.4, A.11.1.5, A.11.2.1, A.13.1.1, A.13.1.3, A.13.2.1, A.13.2.3, A.13.2.4, A.14.1.2, A.14.1.3, A.6.1.2, A.7.1.1, A.7.1.2, A.7.3.1, A.8.2.2, A.8.2.3, A.9.1.1, A.9.1.2, A.9.2.3, A.9.4.1, A.9.4.4, A.9.4.5
    nerc-cipCIP-003-8 R5.1.1, CIP-003-8 R5.3, CIP-004-6 R2.3, CIP-007-3 R2.1, CIP-007-3 R2.2, CIP-007-3 R2.3, CIP-007-3 R5.1, CIP-007-3 R5.1.1, CIP-007-3 R5.1.2
    nistCM-6(a), AC-6(1)
    nist-csfPR.AC-4, PR.DS-5
    pcidssReq-8.7.c
    os-srgSRG-OS-000480-GPOS-00227
    anssiR50
    pcidss42.2.6, 2.2

    Complexity:low
    Disruption:low
    Reboot:false
    Strategy:configure
    
    
    
    
    chmod u-xs,g-xws,o-xwt /etc/group
    

    Complexity:low
    Disruption:low
    Reboot:false
    Strategy:configure
    - name: Test for existence /etc/group
      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
      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
    

    Rule   Verify Permissions on gshadow File   [ref]

    To properly set the permissions of /etc/gshadow, run the command:
    $ sudo chmod 0640 /etc/gshadow
    Rationale:
    The /etc/gshadow file contains group password hashes. Protection of this file is critical for system security.
    Severity: 
    medium
    Rule ID:xccdf_org.ssgproject.content_rule_file_permissions_etc_gshadow
    References:
    cis-csc12, 13, 14, 15, 16, 18, 3, 5
    cobit5APO01.06, DSS05.04, DSS05.07, DSS06.02
    disaCCI-000366
    isa-62443-20094.3.3.7.3
    isa-62443-2013SR 2.1, SR 5.2
    iso27001-2013A.10.1.1, A.11.1.4, A.11.1.5, A.11.2.1, A.13.1.1, A.13.1.3, A.13.2.1, A.13.2.3, A.13.2.4, A.14.1.2, A.14.1.3, A.6.1.2, A.7.1.1, A.7.1.2, A.7.3.1, A.8.2.2, A.8.2.3, A.9.1.1, A.9.1.2, A.9.2.3, A.9.4.1, A.9.4.4, A.9.4.5
    nerc-cipCIP-003-8 R5.1.1, CIP-003-8 R5.3, CIP-004-6 R2.3, CIP-007-3 R2.1, CIP-007-3 R2.2, CIP-007-3 R2.3, CIP-007-3 R5.1, CIP-007-3 R5.1.1, CIP-007-3 R5.1.2
    nistCM-6(a), AC-6(1)
    nist-csfPR.AC-4, PR.DS-5
    os-srgSRG-OS-000480-GPOS-00227
    anssiR50

    Complexity:low
    Disruption:low
    Reboot:false
    Strategy:configure
    
    
    
    
    chmod u-xs,g-xws,o-xwrt /etc/gshadow
    

    Complexity:low
    Disruption:low
    Reboot:false
    Strategy:configure
    - name: Test for existence /etc/gshadow
      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
      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
    

    Rule   Verify Permissions on passwd File   [ref]

    To properly set the permissions of /etc/passwd, run the command:
    $ sudo chmod 0644 /etc/passwd
    Rationale:
    If the /etc/passwd file is writable by a group-owner or the world the risk of its compromise is increased. The file contains the list of accounts on the system and associated information, and protection of this file is critical for system security.
    Severity: 
    medium
    Rule ID:xccdf_org.ssgproject.content_rule_file_permissions_etc_passwd
    References:
    cis-csc12, 13, 14, 15, 16, 18, 3, 5
    cjis5.5.2.2
    cobit5APO01.06, DSS05.04, DSS05.07, DSS06.02
    disaCCI-000366
    isa-62443-20094.3.3.7.3
    isa-62443-2013SR 2.1, SR 5.2
    iso27001-2013A.10.1.1, A.11.1.4, A.11.1.5, A.11.2.1, A.13.1.1, A.13.1.3, A.13.2.1, A.13.2.3, A.13.2.4, A.14.1.2, A.14.1.3, A.6.1.2, A.7.1.1, A.7.1.2, A.7.3.1, A.8.2.2, A.8.2.3, A.9.1.1, A.9.1.2, A.9.2.3, A.9.4.1, A.9.4.4, A.9.4.5
    nerc-cipCIP-003-8 R5.1.1, CIP-003-8 R5.3, CIP-004-6 R2.3, CIP-007-3 R2.1, CIP-007-3 R2.2, CIP-007-3 R2.3, CIP-007-3 R5.1, CIP-007-3 R5.1.1, CIP-007-3 R5.1.2
    nistCM-6(a), AC-6(1)
    nist-csfPR.AC-4, PR.DS-5
    pcidssReq-8.7.c
    os-srgSRG-OS-000480-GPOS-00227
    anssiR50
    pcidss42.2.6, 2.2

    Complexity:low
    Disruption:low
    Reboot:false
    Strategy:configure
    
    
    
    
    chmod u-xs,g-xws,o-xwt /etc/passwd
    

    Complexity:low
    Disruption:low
    Reboot:false
    Strategy:configure
    - name: Test for existence /etc/passwd
      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
      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
    

    Rule   Verify Permissions on shadow File   [ref]

    To properly set the permissions of /etc/shadow, run the command:
    $ sudo chmod 0640 /etc/shadow
    Rationale:
    The /etc/shadow file contains the list of local system accounts and stores password hashes. Protection of this file is critical for system security. Failure to give ownership of this file to root provides the designated owner with access to sensitive information which could weaken the system security posture.
    Severity: 
    medium
    Rule ID:xccdf_org.ssgproject.content_rule_file_permissions_etc_shadow
    References:
    cis-csc12, 13, 14, 15, 16, 18, 3, 5
    cjis5.5.2.2
    cobit5APO01.06, DSS05.04, DSS05.07, DSS06.02
    disaCCI-000366
    isa-62443-20094.3.3.7.3
    isa-62443-2013SR 2.1, SR 5.2
    iso27001-2013A.10.1.1, A.11.1.4, A.11.1.5, A.11.2.1, A.13.1.1, A.13.1.3, A.13.2.1, A.13.2.3, A.13.2.4, A.14.1.2, A.14.1.3, A.6.1.2, A.7.1.1, A.7.1.2, A.7.3.1, A.8.2.2, A.8.2.3, A.9.1.1, A.9.1.2, A.9.2.3, A.9.4.1, A.9.4.4, A.9.4.5
    nerc-cipCIP-003-8 R5.1.1, CIP-003-8 R5.3, CIP-004-6 R2.3, CIP-007-3 R2.1, CIP-007-3 R2.2, CIP-007-3 R2.3, CIP-007-3 R5.1, CIP-007-3 R5.1.1, CIP-007-3 R5.1.2
    nistCM-6(a), AC-6(1)
    nist-csfPR.AC-4, PR.DS-5
    pcidssReq-8.7.c
    os-srgSRG-OS-000480-GPOS-00227
    anssiR50
    pcidss42.2.6, 2.2

    Complexity:low
    Disruption:low
    Reboot:false
    Strategy:configure
    
    
    
    
    chmod u-xs,g-xws,o-xwrt /etc/shadow
    

    Complexity:low
    Disruption:low
    Reboot:false
    Strategy:configure
    - name: Test for existence /etc/shadow
      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
      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
    

    Rule   Verify Permissions on System.map Files   [ref]

    The System.map files are symbol map files generated during the compilation of the Linux kernel. They contain the mapping between kernel symbols and their corresponding memory addresses. In general, there is no need for non-root users to read these files. To properly set the permissions of /boot/System.map*, run the command:
    $ sudo chmod 0600 /boot/System.map*
    Rationale:
    The purpose of System.map files is primarily for debugging and profiling the kernel. Unrestricted access to these files might disclose information useful to attackers and malicious software leading to more sophisticated exploitation.
    Severity: 
    low
    Rule ID:xccdf_org.ssgproject.content_rule_file_permissions_systemmap
    References:
    anssiR29

    Complexity:low
    Disruption:low
    Reboot:false
    Strategy:configure
    
    
    
    
    find -L /boot/ -maxdepth 1 -perm /u+xs,g+xwrs,o+xwrt  -type f -regextype posix-extended -regex '^.*System\.map.*$' -exec chmod u-xs,g-xwrs,o-xwrt {} \;
    

    Complexity:low
    Disruption:low
    Reboot:false
    Strategy:configure
    - name: Find /boot/ file(s)
      command: find -H /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
      tags:
      - configure_strategy
      - file_permissions_systemmap
      - low_complexity
      - low_disruption
      - low_severity
      - no_reboot_needed
    
    - name: Set permissions for /boot/ file(s)
      file:
        path: '{{ item }}'
        mode: u-xs,g-xwrs,o-xwrt
        state: file
      with_items:
      - '{{ files_found.stdout_lines }}'
      tags:
      - configure_strategy
      - file_permissions_systemmap
      - low_complexity
      - low_disruption
      - low_severity
      - no_reboot_needed
    
    Group   Restrict Programs from Dangerous Execution Patterns   Group contains 2 groups and 2 rules
    [ref]   The recommendations in this section are designed to ensure that the system's features to protect against potentially dangerous program execution are activated. These protections are applied at the system initialization or kernel level, and defend against certain types of badly-configured or compromised programs.
    Group   Disable Core Dumps   Group contains 1 rule
    [ref]   A core dump file is the memory image of an executable program when it was terminated by the operating system due to errant behavior. In most cases, only software developers legitimately need to access these files. The core dump files may also contain sensitive information, or unnecessarily occupy large amounts of disk space.

    Once a hard limit is set in /etc/security/limits.conf, or to a file within the /etc/security/limits.d/ directory, a user cannot increase that limit within his or her own session. If access to core dumps is required, consider restricting them to only certain users or groups. See the limits.conf man page for more information.

    The core dumps of setuid programs are further protected. The sysctl variable fs.suid_dumpable controls whether the kernel allows core dumps from these programs at all. The default value of 0 is recommended.

    Rule   Disable Core Dumps for SUID programs   [ref]

    To set the runtime status of the fs.suid_dumpable kernel parameter, run the following command:
    $ sudo sysctl -w fs.suid_dumpable=0
    To make sure that the setting is persistent, add the following line to a file in the directory /etc/sysctl.d:
    fs.suid_dumpable = 0
    Rationale:
    The core dump of a setuid program is more likely to contain sensitive data, as the program itself runs with greater privileges than the user who initiated execution of the program. Disabling the ability for any setuid program to write a core file decreases the risk of unauthorized access of such data.
    Severity: 
    medium
    Rule ID:xccdf_org.ssgproject.content_rule_sysctl_fs_suid_dumpable
    References:
    hipaa164.308(a)(1)(ii)(D), 164.308(a)(3), 164.308(a)(4), 164.310(b), 164.310(c), 164.312(a), 164.312(e)
    nistSI-11(a), SI-11(b)
    anssiR14
    pcidss43.3.1.1, 3.3.1, 3.3

    Complexity:low
    Disruption:medium
    Reboot:true
    Strategy:disable
    # Remediation is applicable only in certain platforms
    if dpkg-query --show --showformat='${db:Status-Status}
    ' 'linux-base' 2>/dev/null | grep -q ^installed; then
    
    # Comment out any occurrences of fs.suid_dumpable from /etc/sysctl.d/*.conf files
    
    for f in /etc/sysctl.d/*.conf /run/sysctl.d/*.conf /usr/local/lib/sysctl.d/*.conf /usr/lib/sysctl.d/*.conf; do
    
    
      # skip systemd-sysctl symlink (/etc/sysctl.d/99-sysctl.conf -> /etc/sysctl.conf)
      if [[ "$(readlink -f "$f")" == "/etc/sysctl.conf" ]]; then continue; fi
    
      matching_list=$(grep -P '^(?!#).*[\s]*fs.suid_dumpable.*$' $f | uniq )
      if ! test -z "$matching_list"; then
        while IFS= read -r entry; do
          escaped_entry=$(sed -e 's|/|\\/|g' <<< "$entry")
          # comment out "fs.suid_dumpable" matches to preserve user data
          sed -i --follow-symlinks "s/^${escaped_entry}$/# &/g" $f
        done <<< "$matching_list"
      fi
    done
    
    #
    # Set sysctl config file which to save the desired value
    #
    
    SYSCONFIG_FILE="/etc/sysctl.conf"
    
    
    #
    # Set runtime for fs.suid_dumpable
    #
    if [[ "$OSCAP_BOOTC_BUILD" != "YES" ]] ; then
        /sbin/sysctl -q -n -w fs.suid_dumpable="0"
    fi
    
    #
    # If fs.suid_dumpable present in /etc/sysctl.conf, change value to "0"
    #	else, add "fs.suid_dumpable = 0" to /etc/sysctl.conf
    #
    
    # Strip any search characters in the key arg so that the key can be replaced without
    # adding any search characters to the config file.
    stripped_key=$(sed 's/[\^=\$,;+]*//g' <<< "^fs.suid_dumpable")
    
    # shellcheck disable=SC2059
    printf -v formatted_output "%s = %s" "$stripped_key" "0"
    
    # If the key exists, change it. Otherwise, add it to the config_file.
    # We search for the key string followed by a word boundary (matched by \>),
    # so if we search for 'setting', 'setting2' won't match.
    if LC_ALL=C grep -q -m 1 -i -e "^fs.suid_dumpable\\>" "${SYSCONFIG_FILE}"; then
        escaped_formatted_output=$(sed -e 's|/|\\/|g' <<< "$formatted_output")
        LC_ALL=C sed -i --follow-symlinks "s/^fs.suid_dumpable\\>.*/$escaped_formatted_output/gi" "${SYSCONFIG_FILE}"
    else
        if [[ -s "${SYSCONFIG_FILE}" ]] && [[ -n "$(tail -c 1 -- "${SYSCONFIG_FILE}" || true)" ]]; then
            LC_ALL=C sed -i --follow-symlinks '$a'\\ "${SYSCONFIG_FILE}"
        fi
        printf '%s\n' "$formatted_output" >> "${SYSCONFIG_FILE}"
    fi
    
    else
        >&2 echo 'Remediation is not applicable, nothing was done'
    fi
    

    Complexity:low
    Disruption:medium
    Reboot:true
    Strategy:disable
    - name: Gather the package facts
      package_facts:
        manager: auto
      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: List /etc/sysctl.d/*.conf files
      find:
        paths:
        - /etc/sysctl.d/
        - /run/sysctl.d/
        - /usr/local/lib/sysctl.d/
        - /usr/lib/sysctl.d/
        contains: ^[\s]*fs.suid_dumpable.*$
        patterns: '*.conf'
        file_type: any
      register: find_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: Comment out any occurrences of fs.suid_dumpable from config files
      replace:
        path: '{{ item.path }}'
        regexp: ^[\s]*fs.suid_dumpable
        replace: '#fs.suid_dumpable'
      loop: '{{ find_sysctl_d.files }}'
      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: Ensure sysctl fs.suid_dumpable is set to 0
      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
    
    Group   Enable ExecShield   Group contains 1 rule
    [ref]   ExecShield describes kernel features that provide protection against exploitation of memory corruption errors such as buffer overflows. These features include random placement of the stack and other memory regions, prevention of execution in memory that should only hold data, and special handling of text buffers. These protections are enabled by default on 32-bit systems and controlled through sysctl variables kernel.exec-shield and kernel.randomize_va_space. On the latest 64-bit systems, kernel.exec-shield cannot be enabled or disabled with sysctl.

    Rule   Enable Randomized Layout of Virtual Address Space   [ref]

    To set the runtime status of the kernel.randomize_va_space kernel parameter, run the following command:
    $ sudo sysctl -w kernel.randomize_va_space=2
    To make sure that the setting is persistent, add the following line to a file in the directory /etc/sysctl.d:
    kernel.randomize_va_space = 2
    Rationale:
    Address space layout randomization (ASLR) makes it more difficult for an attacker to predict the location of attack code they have introduced into a process's address space during an attempt at exploitation. Additionally, ASLR makes it more difficult for an attacker to know the location of existing code in order to re-purpose it using return oriented programming (ROP) techniques.
    Severity: 
    medium
    Rule ID:xccdf_org.ssgproject.content_rule_sysctl_kernel_randomize_va_space
    References:
    cui3.1.7
    disaCCI-000366, CCI-002824
    hipaa164.308(a)(1)(ii)(D), 164.308(a)(3), 164.308(a)(4), 164.310(b), 164.310(c), 164.312(a), 164.312(e)
    nerc-cipCIP-002-5 R1.1, CIP-002-5 R1.2, CIP-003-8 R5.1.1, CIP-003-8 R5.3, CIP-004-6 4.1, CIP-004-6 4.2, CIP-004-6 R2.2.3, CIP-004-6 R2.2.4, CIP-004-6 R2.3, CIP-004-6 R4, CIP-005-6 R1, CIP-005-6 R1.1, CIP-005-6 R1.2, CIP-007-3 R3, CIP-007-3 R3.1, CIP-007-3 R5.1, CIP-007-3 R5.1.2, CIP-007-3 R5.1.3, CIP-007-3 R5.2.1, CIP-007-3 R5.2.3, CIP-007-3 R8.4, CIP-009-6 R.1.1, CIP-009-6 R4
    nistSC-30, SC-30(2), CM-6(a)
    pcidssReq-2.2.1
    os-srgSRG-OS-000433-GPOS-00193, SRG-OS-000480-GPOS-00227
    app-srg-ctrSRG-APP-000450-CTR-001105
    anssiR9
    pcidss43.3.1.1, 3.3.1, 3.3

    Complexity:low
    Disruption:medium
    Reboot:true
    Strategy:disable
    # Remediation is applicable only in certain platforms
    if dpkg-query --show --showformat='${db:Status-Status}
    ' 'linux-base' 2>/dev/null | grep -q ^installed; then
    
    # Comment out any occurrences of kernel.randomize_va_space from /etc/sysctl.d/*.conf files
    
    for f in /etc/sysctl.d/*.conf /run/sysctl.d/*.conf /usr/local/lib/sysctl.d/*.conf /usr/lib/sysctl.d/*.conf; do
    
    
      # skip systemd-sysctl symlink (/etc/sysctl.d/99-sysctl.conf -> /etc/sysctl.conf)
      if [[ "$(readlink -f "$f")" == "/etc/sysctl.conf" ]]; then continue; fi
    
      matching_list=$(grep -P '^(?!#).*[\s]*kernel.randomize_va_space.*$' $f | uniq )
      if ! test -z "$matching_list"; then
        while IFS= read -r entry; do
          escaped_entry=$(sed -e 's|/|\\/|g' <<< "$entry")
          # comment out "kernel.randomize_va_space" matches to preserve user data
          sed -i --follow-symlinks "s/^${escaped_entry}$/# &/g" $f
        done <<< "$matching_list"
      fi
    done
    
    #
    # Set sysctl config file which to save the desired value
    #
    
    SYSCONFIG_FILE="/etc/sysctl.conf"
    
    
    #
    # Set runtime for kernel.randomize_va_space
    #
    if [[ "$OSCAP_BOOTC_BUILD" != "YES" ]] ; then
        /sbin/sysctl -q -n -w kernel.randomize_va_space="2"
    fi
    
    #
    # If kernel.randomize_va_space present in /etc/sysctl.conf, change value to "2"
    #	else, add "kernel.randomize_va_space = 2" to /etc/sysctl.conf
    #
    
    # Strip any search characters in the key arg so that the key can be replaced without
    # adding any search characters to the config file.
    stripped_key=$(sed 's/[\^=\$,;+]*//g' <<< "^kernel.randomize_va_space")
    
    # shellcheck disable=SC2059
    printf -v formatted_output "%s = %s" "$stripped_key" "2"
    
    # If the key exists, change it. Otherwise, add it to the config_file.
    # We search for the key string followed by a word boundary (matched by \>),
    # so if we search for 'setting', 'setting2' won't match.
    if LC_ALL=C grep -q -m 1 -i -e "^kernel.randomize_va_space\\>" "${SYSCONFIG_FILE}"; then
        escaped_formatted_output=$(sed -e 's|/|\\/|g' <<< "$formatted_output")
        LC_ALL=C sed -i --follow-symlinks "s/^kernel.randomize_va_space\\>.*/$escaped_formatted_output/gi" "${SYSCONFIG_FILE}"
    else
        if [[ -s "${SYSCONFIG_FILE}" ]] && [[ -n "$(tail -c 1 -- "${SYSCONFIG_FILE}" || true)" ]]; then
            LC_ALL=C sed -i --follow-symlinks '$a'\\ "${SYSCONFIG_FILE}"
        fi
        printf '%s\n' "$formatted_output" >> "${SYSCONFIG_FILE}"
    fi
    
    else
        >&2 echo 'Remediation is not applicable, nothing was done'
    fi
    

    Complexity:low
    Disruption:medium
    Reboot:true
    Strategy:disable
    - name: Gather the package facts
      package_facts:
        manager: auto
      tags:
      - 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: List /etc/sysctl.d/*.conf files
      find:
        paths:
        - /etc/sysctl.d/
        - /run/sysctl.d/
        - /usr/local/lib/sysctl.d/
        - /usr/lib/sysctl.d/
        contains: ^[\s]*kernel.randomize_va_space.*$
        patterns: '*.conf'
        file_type: any
      register: find_sysctl_d
      when: '"linux-base" in ansible_facts.packages'
      tags:
      - 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: Comment out any occurrences of kernel.randomize_va_space from config files
      replace:
        path: '{{ item.path }}'
        regexp: ^[\s]*kernel.randomize_va_space
        replace: '#kernel.randomize_va_space'
      loop: '{{ find_sysctl_d.files }}'
      when: '"linux-base" in ansible_facts.packages'
      tags:
      - NIST-800-171-3.1.7
      - NIST-800-53-CM-6(a)
      - NIST-800-53-SC-30
      - NIST-800-53-SC-30(2)
      - PCI-DSS-Req-2.2.1
      - PCI-DSSv4-3.3
      - PCI-DSSv4-3.3.1
      - PCI-DSSv4-3.3.1.1
      - disable_strategy
      - low_complexity
      - medium_disruption
      - medium_severity
      - reboot_required
      - sysctl_kernel_randomize_va_space
    
    - name: Ensure sysctl kernel.randomize_va_space is set to 2
      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:
      - 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
    
    Group   Services   Group contains 6 groups and 15 rules
    [ref]   The best protection against vulnerable software is running less software. This section describes how to review the software which Debian 12 installs on a system and disable software which is not needed. It then enumerates the software packages installed on a default Debian 12 system and provides guidance about which ones can be safely disabled.

    Debian 12 provides a convenient minimal install option that essentially installs the bare necessities for a functional system. When building Debian 12 systems, it is highly recommended to select the minimal packages and then build up the system from there.
    Group   APT service configuration   Group contains 2 rules
    [ref]   The apt service manage the package management and update of the whole system. Its configuration need to be properly defined to ensure efficient security updates, packages and repository authentication and proper lifecycle management.

    Rule   Disable unauthenticated repositories in APT configuration   [ref]

    Unauthenticated repositories should not be used for updates.
    Rationale:
    Repositories hosts all packages that will be intsalled on the system during update. If a repository is not authenticated, the associated packages can't be trusted, and then should not be installed localy.
    Severity: 
    unknown
    Rule ID:xccdf_org.ssgproject.content_rule_apt_conf_disallow_unauthenticated
    References:
    disaCCI-003992
    os-srgSRG-OS-000366-GPOS-00153

    Rule   Ensure that official distribution repositories are used   [ref]

    Check that official Debian repositories, including security repository, are configured in apt.
    Rationale:
    The Debian distribution deliver DSA (Debian Security Announce), through the official Debian security repository, to correct various vulnerabilities impacting the Debian packages. Using the official repositories is the best way to ensure that the Debian updates are integrated soon enough.
    Severity: 
    unknown
    Rule ID:xccdf_org.ssgproject.content_rule_apt_sources_list_official
    Group   Cron and At Daemons   Group contains 1 rule
    [ref]   The cron and at services are used to allow commands to be executed at a later time. The cron service is required by almost all systems to perform necessary maintenance tasks, while at may or may not be required on a given system. Both daemons should be configured defensively.

    Rule   Install the cron service   [ref]

    The Cron service should be installed.
    Rationale:
    The cron service allow periodic job execution, needed for almost all administrative tasks and services (software update, log rotating, etc.). Access to cron service should be restricted to administrative accounts only.
    Severity: 
    medium
    Rule ID:xccdf_org.ssgproject.content_rule_package_cron_installed
    References:
    cis-csc11, 14, 3, 9
    cobit5BAI10.01, BAI10.02, BAI10.03, BAI10.05, DSS05.02, DSS05.05, DSS06.06
    disaCCI-000366
    hipaa164.308(a)(4)(i), 164.308(b)(1), 164.308(b)(3), 164.310(b), 164.312(e)(1), 164.312(e)(2)(ii)
    isa-62443-20094.3.3.5.1, 4.3.3.5.2, 4.3.3.5.3, 4.3.3.5.4, 4.3.3.5.5, 4.3.3.5.6, 4.3.3.5.7, 4.3.3.5.8, 4.3.3.6.1, 4.3.3.6.2, 4.3.3.6.3, 4.3.3.6.4, 4.3.3.6.5, 4.3.3.6.6, 4.3.3.6.7, 4.3.3.6.8, 4.3.3.6.9, 4.3.3.7.1, 4.3.3.7.2, 4.3.3.7.3, 4.3.3.7.4, 4.3.4.3.2, 4.3.4.3.3
    isa-62443-2013SR 1.1, SR 1.10, SR 1.11, SR 1.12, SR 1.13, SR 1.2, SR 1.3, SR 1.4, SR 1.5, SR 1.6, SR 1.7, SR 1.8, SR 1.9, SR 2.1, SR 2.2, SR 2.3, SR 2.4, SR 2.5, SR 2.6, SR 2.7, SR 7.6
    iso27001-2013A.12.1.2, A.12.5.1, A.12.6.2, A.14.2.2, A.14.2.3, A.14.2.4, A.9.1.2
    nistCM-6(a)
    nist-csfPR.IP-1, PR.PT-3
    os-srgSRG-OS-000480-GPOS-00227

    Complexity:low
    Disruption:low
    Reboot:false
    Strategy:enable
    # Remediation is applicable only in certain platforms
    if dpkg-query --show --showformat='${db:Status-Status}
    ' 'linux-base' 2>/dev/null | grep -q ^installed; then
    
    DEBIAN_FRONTEND=noninteractive apt-get install -y "cron"
    
    else
        >&2 echo 'Remediation is not applicable, nothing was done'
    fi
    

    
    [[packages]]
    name = "cron"
    version = "*"
    

    Complexity:low
    Disruption:low
    Reboot:false
    Strategy:enable
    - name: Gather the package facts
      package_facts:
        manager: auto
      tags:
      - NIST-800-53-CM-6(a)
      - enable_strategy
      - low_complexity
      - low_disruption
      - medium_severity
      - no_reboot_needed
      - package_cron_installed
    
    - name: Ensure cron is installed
      package:
        name: cron
        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_cron_installed
    

    Complexity:low
    Disruption:low
    Reboot:false
    Strategy:enable
    include install_cron
    
    class install_cron {
      package { 'cron':
        ensure => 'installed',
      }
    }
    
    Group   Deprecated services   Group contains 5 rules
    [ref]   Some deprecated software services impact the overall system security due to their behavior (leak of confidentiality in network exchange, usage as uncontrolled communication channel, risk associated with the service due to its old age, etc.

    Rule   Uninstall the inet-based telnet server   [ref]

    The inet-based telnet daemon should be uninstalled.
    Rationale:
    telnet allows clear text communications, and does not protect any data transmission between client and server. Any confidential data can be listened and no integrity checking is made.
    Severity: 
    high
    Rule ID:xccdf_org.ssgproject.content_rule_package_inetutils-telnetd_removed
    References:
    cis-csc11, 12, 14, 15, 3, 8, 9
    cobit5APO13.01, BAI10.01, BAI10.02, BAI10.03, BAI10.05, DSS01.04, DSS05.02, DSS05.03, DSS05.05, DSS06.06
    isa-62443-20094.3.3.5.1, 4.3.3.5.2, 4.3.3.5.3, 4.3.3.5.4, 4.3.3.5.5, 4.3.3.5.6, 4.3.3.5.7, 4.3.3.5.8, 4.3.3.6.1, 4.3.3.6.2, 4.3.3.6.3, 4.3.3.6.4, 4.3.3.6.5, 4.3.3.6.6, 4.3.3.6.7, 4.3.3.6.8, 4.3.3.6.9, 4.3.3.7.1, 4.3.3.7.2, 4.3.3.7.3, 4.3.3.7.4, 4.3.4.3.2, 4.3.4.3.3
    isa-62443-2013SR 1.1, SR 1.10, SR 1.11, SR 1.12, SR 1.13, SR 1.2, SR 1.3, SR 1.4, SR 1.5, SR 1.6, SR 1.7, SR 1.8, SR 1.9, SR 2.1, SR 2.2, SR 2.3, SR 2.4, SR 2.5, SR 2.6, SR 2.7, SR 3.1, SR 3.5, SR 3.8, SR 4.1, SR 4.3, SR 5.1, SR 5.2, SR 5.3, SR 7.1, SR 7.6
    iso27001-2013A.11.2.6, A.12.1.2, A.12.5.1, A.12.6.2, A.13.1.1, A.13.2.1, A.14.1.3, A.14.2.2, A.14.2.3, A.14.2.4, A.6.2.1, A.6.2.2, A.9.1.2
    nistCM-7(a), CM-7(b), CM-6(a)
    nist-csfPR.AC-3, PR.IP-1, PR.PT-3, PR.PT-4

    Complexity:low
    Disruption:low
    Reboot:false
    Strategy:disable
    
    # CAUTION: This remediation script will remove inetutils-telnetd
    #	   from the system, and may remove any packages
    #	   that depend on inetutils-telnetd. Execute this
    #	   remediation AFTER testing on a non-production
    #	   system!
    
    DEBIAN_FRONTEND=noninteractive apt-get remove -y "inetutils-telnetd"
    

    Complexity:low
    Disruption:low
    Reboot:false
    Strategy:disable
    - name: Ensure inetutils-telnetd is removed
      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
    

    Complexity:low
    Disruption:low
    Reboot:false
    Strategy:disable
    include remove_inetutils-telnetd
    
    class remove_inetutils-telnetd {
      package { 'inetutils-telnetd':
        ensure => 'purged',
      }
    }
    

    Rule   Uninstall the nis package   [ref]

    The support for Yellowpages should not be installed unless it is required.
    Rationale:
    NIS is the historical SUN service for central account management, more and more replaced by LDAP. NIS does not support efficiently security constraints, ACL, etc. and should not be used.
    Severity: 
    low
    Rule ID:xccdf_org.ssgproject.content_rule_package_nis_removed

    Complexity:low
    Disruption:low
    Reboot:false
    Strategy:disable
    
    # CAUTION: This remediation script will remove nis
    #	   from the system, and may remove any packages
    #	   that depend on nis. Execute this
    #	   remediation AFTER testing on a non-production
    #	   system!
    
    DEBIAN_FRONTEND=noninteractive apt-get remove -y "nis"
    

    Complexity:low
    Disruption:low
    Reboot:false
    Strategy:disable
    - name: Ensure nis is removed
      package:
        name: nis
        state: absent
      tags:
      - disable_strategy
      - low_complexity
      - low_disruption
      - low_severity
      - no_reboot_needed
      - package_nis_removed
    

    Complexity:low
    Disruption:low
    Reboot:false
    Strategy:disable
    include remove_nis
    
    class remove_nis {
      package { 'nis':
        ensure => 'purged',
      }
    }
    

    Rule   Uninstall the ntpdate package   [ref]

    ntpdate is a historical ntp synchronization client for unixes. It sould be uninstalled.
    Rationale:
    ntpdate is an old not security-compliant ntp client. It should be replaced by modern ntp clients such as ntpd, able to use cryptographic mechanisms integrated in NTP.
    Severity: 
    low
    Rule ID:xccdf_org.ssgproject.content_rule_package_ntpdate_removed

    Complexity:low
    Disruption:low
    Reboot:false
    Strategy:disable
    
    # CAUTION: This remediation script will remove ntpdate
    #	   from the system, and may remove any packages
    #	   that depend on ntpdate. Execute this
    #	   remediation AFTER testing on a non-production
    #	   system!
    
    DEBIAN_FRONTEND=noninteractive apt-get remove -y "ntpdate"
    

    Complexity:low
    Disruption:low
    Reboot:false
    Strategy:disable
    - name: Ensure ntpdate is removed
      package:
        name: ntpdate
        state: absent
      tags:
      - disable_strategy
      - low_complexity
      - low_disruption
      - low_severity
      - no_reboot_needed
      - package_ntpdate_removed
    

    Complexity:low
    Disruption:low
    Reboot:false
    Strategy:disable
    include remove_ntpdate
    
    class remove_ntpdate {
      package { 'ntpdate':
        ensure => 'purged',
      }
    }
    

    Rule   Uninstall the ssl compliant telnet server   [ref]

    The telnet daemon, even with ssl support, should be uninstalled.
    Rationale:
    telnet, even with ssl support, should not be installed. When remote shell is required, up-to-date ssh daemon can be used.
    Severity: 
    high
    Rule ID:xccdf_org.ssgproject.content_rule_package_telnetd-ssl_removed
    References:
    cis-csc11, 12, 14, 15, 3, 8, 9
    cobit5APO13.01, BAI10.01, BAI10.02, BAI10.03, BAI10.05, DSS01.04, DSS05.02, DSS05.03, DSS05.05, DSS06.06
    isa-62443-20094.3.3.5.1, 4.3.3.5.2, 4.3.3.5.3, 4.3.3.5.4, 4.3.3.5.5, 4.3.3.5.6, 4.3.3.5.7, 4.3.3.5.8, 4.3.3.6.1, 4.3.3.6.2, 4.3.3.6.3, 4.3.3.6.4, 4.3.3.6.5, 4.3.3.6.6, 4.3.3.6.7, 4.3.3.6.8, 4.3.3.6.9, 4.3.3.7.1, 4.3.3.7.2, 4.3.3.7.3, 4.3.3.7.4, 4.3.4.3.2, 4.3.4.3.3
    isa-62443-2013SR 1.1, SR 1.10, SR 1.11, SR 1.12, SR 1.13, SR 1.2, SR 1.3, SR 1.4, SR 1.5, SR 1.6, SR 1.7, SR 1.8, SR 1.9, SR 2.1, SR 2.2, SR 2.3, SR 2.4, SR 2.5, SR 2.6, SR 2.7, SR 3.1, SR 3.5, SR 3.8, SR 4.1, SR 4.3, SR 5.1, SR 5.2, SR 5.3, SR 7.1, SR 7.6
    iso27001-2013A.11.2.6, A.12.1.2, A.12.5.1, A.12.6.2, A.13.1.1, A.13.2.1, A.14.1.3, A.14.2.2, A.14.2.3, A.14.2.4, A.6.2.1, A.6.2.2, A.9.1.2
    nistCM-7(a), CM-7(b), CM-6(a)
    nist-csfPR.AC-3, PR.IP-1, PR.PT-3, PR.PT-4

    Complexity:low
    Disruption:low
    Reboot:false
    Strategy:disable
    
    # CAUTION: This remediation script will remove telnetd-ssl
    #	   from the system, and may remove any packages
    #	   that depend on telnetd-ssl. Execute this
    #	   remediation AFTER testing on a non-production
    #	   system!
    
    DEBIAN_FRONTEND=noninteractive apt-get remove -y "telnetd-ssl"
    

    Complexity:low
    Disruption:low
    Reboot:false
    Strategy:disable
    - name: Ensure telnetd-ssl is removed
      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
    

    Complexity:low
    Disruption:low
    Reboot:false
    Strategy:disable
    include remove_telnetd-ssl
    
    class remove_telnetd-ssl {
      package { 'telnetd-ssl':
        ensure => 'purged',
      }
    }
    

    Rule   Uninstall the telnet server   [ref]

    The telnet daemon should be uninstalled.
    Rationale:
    telnet allows clear text communications, and does not protect any data transmission between client and server. Any confidential data can be listened and no integrity checking is made.'
    Severity: 
    high
    Rule ID:xccdf_org.ssgproject.content_rule_package_telnetd_removed
    References:
    cis-csc11, 12, 14, 15, 3, 8, 9
    cobit5APO13.01, BAI10.01, BAI10.02, BAI10.03, BAI10.05, DSS01.04, DSS05.02, DSS05.03, DSS05.05, DSS06.06
    isa-62443-20094.3.3.5.1, 4.3.3.5.2, 4.3.3.5.3, 4.3.3.5.4, 4.3.3.5.5, 4.3.3.5.6, 4.3.3.5.7, 4.3.3.5.8, 4.3.3.6.1, 4.3.3.6.2, 4.3.3.6.3, 4.3.3.6.4, 4.3.3.6.5, 4.3.3.6.6, 4.3.3.6.7, 4.3.3.6.8, 4.3.3.6.9, 4.3.3.7.1, 4.3.3.7.2, 4.3.3.7.3, 4.3.3.7.4, 4.3.4.3.2, 4.3.4.3.3
    isa-62443-2013SR 1.1, SR 1.10, SR 1.11, SR 1.12, SR 1.13, SR 1.2, SR 1.3, SR 1.4, SR 1.5, SR 1.6, SR 1.7, SR 1.8, SR 1.9, SR 2.1, SR 2.2, SR 2.3, SR 2.4, SR 2.5, SR 2.6, SR 2.7, SR 3.1, SR 3.5, SR 3.8, SR 4.1, SR 4.3, SR 5.1, SR 5.2, SR 5.3, SR 7.1, SR 7.6
    iso27001-2013A.11.2.6, A.12.1.2, A.12.5.1, A.12.6.2, A.13.1.1, A.13.2.1, A.14.1.3, A.14.2.2, A.14.2.3, A.14.2.4, A.6.2.1, A.6.2.2, A.9.1.2
    nistCM-7(a), CM-7(b), CM-6(a)
    nist-csfPR.AC-3, PR.IP-1, PR.PT-3, PR.PT-4

    Complexity:low
    Disruption:low
    Reboot:false
    Strategy:disable
    
    # CAUTION: This remediation script will remove telnetd
    #	   from the system, and may remove any packages
    #	   that depend on telnetd. Execute this
    #	   remediation AFTER testing on a non-production
    #	   system!
    
    DEBIAN_FRONTEND=noninteractive apt-get remove -y "telnetd"
    

    Complexity:low
    Disruption:low
    Reboot:false
    Strategy:disable
    - name: Ensure telnetd is removed
      package:
        name: 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_telnetd_removed
    

    Complexity:low
    Disruption:low
    Reboot:false
    Strategy:disable
    include remove_telnetd
    
    class remove_telnetd {
      package { 'telnetd':
        ensure => 'purged',
      }
    }
    
    Group   Network Time Protocol   Group contains 2 rules
    [ref]   The Network Time Protocol is used to manage the system clock over a network. Computer clocks are not very accurate, so time will drift unpredictably on unmanaged systems. Central time protocols can be used both to ensure that time is consistent among a network of systems, and that their time is consistent with the outside world.

    If every system on a network reliably reports the same time, then it is much easier to correlate log messages in case of an attack. In addition, a number of cryptographic protocols (such as Kerberos) use timestamps to prevent certain types of attacks. If your network does not have synchronized time, these protocols may be unreliable or even unusable.

    Depending on the specifics of the network, global time accuracy may be just as important as local synchronization, or not very important at all. If your network is connected to the Internet, using a public timeserver (or one provided by your enterprise) provides globally accurate timestamps which may be essential in investigating or responding to an attack which originated outside of your network.

    A typical network setup involves a small number of internal systems operating as NTP servers, and the remainder obtaining time information from those internal servers.

    There is a choice between the daemons ntpd and chronyd, which are available from the repositories in the ntp and chrony packages respectively.

    The default chronyd daemon can work well when external time references are only intermittently accesible, can perform well even when the network is congested for longer periods of time, can usually synchronize the clock faster and with better time accuracy, and quickly adapts to sudden changes in the rate of the clock, for example, due to changes in the temperature of the crystal oscillator. Chronyd should be considered for all systems which are frequently suspended or otherwise intermittently disconnected and reconnected to a network. Mobile and virtual systems for example.

    The ntpd NTP daemon fully supports NTP protocol version 4 (RFC 5905), including broadcast, multicast, manycast clients and servers, and the orphan mode. It also supports extra authentication schemes based on public-key cryptography (RFC 5906). The NTP daemon (ntpd) should be considered for systems which are normally kept permanently on. Systems which are required to use broadcast or multicast IP, or to perform authentication of packets with the Autokey protocol, should consider using ntpd.

    Refer to https://wiki.debian.org/NTP for more detailed comparison of features of chronyd and ntpd daemon features respectively, and for further guidance how to choose between the two NTP daemons.

    The upstream manual pages at https://chrony-project.org/documentation.html for chronyd and http://www.ntp.org for ntpd provide additional information on the capabilities and configuration of each of the NTP daemons.

    Rule   Install the ntp service   [ref]

    The ntpd service should be installed.
    Rationale:
    Time synchronization (using NTP) is required by almost all network and administrative tasks (syslog, cryptographic based services (authentication, etc.), etc.). Ntpd is regulary maintained and updated, supporting security features such as RFC 5906.
    Severity: 
    high
    Rule ID:xccdf_org.ssgproject.content_rule_package_ntp_installed
    References:
    cis-csc1, 14, 15, 16, 3, 5, 6
    cobit5APO11.04, BAI03.05, DSS05.04, DSS05.07, MEA02.01
    disaCCI-000160
    isa-62443-20094.3.3.3.9, 4.3.3.5.8, 4.3.4.4.7, 4.4.2.1, 4.4.2.2, 4.4.2.4
    isa-62443-2013SR 2.10, SR 2.11, SR 2.12, SR 2.8, SR 2.9
    iso27001-2013A.12.4.1, A.12.4.2, A.12.4.3, A.12.4.4, A.12.7.1
    nistCM-6(a)
    nist-csfPR.PT-1
    pcidssReq-10.4

    Complexity:low
    Disruption:low
    Reboot:false
    Strategy:enable
    # Remediation is applicable only in certain platforms
    if dpkg-query --show --showformat='${db:Status-Status}
    ' 'linux-base' 2>/dev/null | grep -q ^installed; then
    
    DEBIAN_FRONTEND=noninteractive apt-get install -y "ntp"
    
    else
        >&2 echo 'Remediation is not applicable, nothing was done'
    fi
    

    
    [[packages]]
    name = "ntp"
    version = "*"
    

    Complexity:low
    Disruption:low
    Reboot:false
    Strategy:enable
    - name: Gather the package facts
      package_facts:
        manager: auto
      tags:
      - NIST-800-53-CM-6(a)
      - PCI-DSS-Req-10.4
      - enable_strategy
      - high_severity
      - low_complexity
      - low_disruption
      - no_reboot_needed
      - package_ntp_installed
    
    - name: Ensure ntp is installed
      package:
        name: ntp
        state: present
      when: '"linux-base" in ansible_facts.packages'
      tags:
      - NIST-800-53-CM-6(a)
      - PCI-DSS-Req-10.4
      - enable_strategy
      - high_severity
      - low_complexity
      - low_disruption
      - no_reboot_needed
      - package_ntp_installed
    

    Complexity:low
    Disruption:low
    Reboot:false
    Strategy:enable
    include install_ntp
    
    class install_ntp {
      package { 'ntp':
        ensure => 'installed',
      }
    }
    

    Rule   Enable the NTP Daemon   [ref]

    The ntp service can be enabled with the following command:
    $ sudo systemctl enable ntp.service
    Rationale:
    Enabling the ntp service ensures that the ntp service will be running and that the system will synchronize its time to any servers specified. This is important whether the system is configured to be a client (and synchronize only its own clock) or it is also acting as an NTP server to other systems. Synchronizing time is essential for authentication services such as Kerberos, but it is also important for maintaining accurate logs and auditing possible security breaches.

    The NTP daemon offers all of the functionality of ntpdate, which is now deprecated.
    Severity: 
    high
    Rule ID:xccdf_org.ssgproject.content_rule_service_ntp_enabled
    References:
    cis-csc1, 14, 15, 16, 3, 5, 6
    cobit5APO11.04, BAI03.05, DSS05.04, DSS05.07, MEA02.01
    disaCCI-000160
    isa-62443-20094.3.3.3.9, 4.3.3.5.8, 4.3.4.4.7, 4.4.2.1, 4.4.2.2, 4.4.2.4
    isa-62443-2013SR 2.10, SR 2.11, SR 2.12, SR 2.8, SR 2.9
    iso27001-2013A.12.4.1, A.12.4.2, A.12.4.3, A.12.4.4, A.12.7.1
    nistCM-6(a), AU-8(1)(a)
    nist-csfPR.PT-1
    pcidssReq-10.4
    pcidss410.6.1, 10.6

    
    [customizations.services]
    enabled = ["ntp"]
    

    Complexity:low
    Disruption:low
    Reboot:false
    Strategy:enable
    - name: Gather the package facts
      package_facts:
        manager: auto
      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_ntp_enabled
    
    - name: Enable the NTP Daemon - Enable service ntp
      block:
    
      - name: Gather the package facts
        package_facts:
          manager: auto
    
      - name: Enable the NTP Daemon - Enable Service ntp
        ansible.builtin.systemd:
          name: ntp
          enabled: true
          state: started
          masked: false
        when:
        - '"ntp" in ansible_facts.packages'
      when:
      - '"linux-base" in ansible_facts.packages'
      - '"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_ntp_enabled
    

    Complexity:low
    Disruption:low
    Reboot:false
    Strategy:enable
    include enable_ntp
    
    class enable_ntp {
      service {'ntp':
        enable => true,
        ensure => 'running',
      }
    }
    
    Group   SSH Server   Group contains 1 group and 5 rules
    [ref]   The SSH protocol is recommended for remote login and remote file transfer. SSH provides confidentiality and integrity for data exchanged between two systems, as well as server authentication, through the use of public key cryptography. The implementation included with the system is called OpenSSH, and more detailed documentation is available from its website, https://www.openssh.com. Its server program is called sshd and provided by the RPM package openssh-server.
    Group   Configure OpenSSH Server if Necessary   Group contains 5 rules
    [ref]   If the system needs to act as an SSH server, then certain changes should be made to the OpenSSH daemon configuration file /etc/ssh/sshd_config. The following recommendations can be applied to this file. See the sshd_config(5) man page for more detailed information.

    Rule   Set SSH Client Alive Count Max to zero   [ref]

    The SSH server sends at most ClientAliveCountMax messages during a SSH session and waits for a response from the SSH client. The option ClientAliveInterval configures timeout after each ClientAliveCountMax message. If the SSH server does not receive a response from the client, then the connection is considered unresponsive and terminated. To ensure the SSH timeout occurs precisely when the ClientAliveInterval is set, set the ClientAliveCountMax to value of 0 in /etc/ssh/sshd_config:
    Rationale:
    This ensures a user login will be terminated as soon as the ClientAliveInterval is reached.
    Severity: 
    medium
    Rule ID:xccdf_org.ssgproject.content_rule_sshd_set_keepalive_0
    References:
    cis-csc1, 12, 13, 14, 15, 16, 18, 3, 5, 7, 8
    cjis5.5.6
    cobit5APO13.01, BAI03.01, BAI03.02, BAI03.03, DSS01.03, DSS03.05, DSS05.04, DSS05.05, DSS05.07, DSS05.10, DSS06.03, DSS06.10
    cui3.1.11
    disaCCI-000879, CCI-001133, CCI-002361
    hipaa164.308(a)(4)(i), 164.308(b)(1), 164.308(b)(3), 164.310(b), 164.312(e)(1), 164.312(e)(2)(ii)
    isa-62443-20094.3.3.2.2, 4.3.3.5.1, 4.3.3.5.2, 4.3.3.6.1, 4.3.3.6.2, 4.3.3.6.3, 4.3.3.6.4, 4.3.3.6.5, 4.3.3.6.6, 4.3.3.6.7, 4.3.3.6.8, 4.3.3.6.9, 4.3.3.7.2, 4.3.3.7.3, 4.3.3.7.4, 4.3.4.3.3
    isa-62443-2013SR 1.1, SR 1.10, SR 1.2, SR 1.3, SR 1.4, SR 1.5, SR 1.7, SR 1.8, SR 1.9, SR 2.1, SR 6.2
    iso27001-2013A.12.4.1, A.12.4.3, A.14.1.1, A.14.2.1, A.14.2.5, A.18.1.4, A.6.1.2, A.6.1.5, A.7.1.1, A.9.1.2, A.9.2.1, A.9.2.2, A.9.2.3, A.9.2.4, A.9.2.6, A.9.3.1, A.9.4.1, A.9.4.2, A.9.4.3, A.9.4.4, A.9.4.5
    nerc-cipCIP-004-6 R2.2.3, CIP-007-3 R5.1, CIP-007-3 R5.2, CIP-007-3 R5.3.1, CIP-007-3 R5.3.2, CIP-007-3 R5.3.3
    nistAC-2(5), AC-12, AC-17(a), SC-10, CM-6(a)
    nist-csfDE.CM-1, DE.CM-3, PR.AC-1, PR.AC-4, PR.AC-6, PR.AC-7, PR.IP-2
    pcidssReq-8.1.8
    os-srgSRG-OS-000126-GPOS-00066, SRG-OS-000163-GPOS-00072, SRG-OS-000279-GPOS-00109

    Complexity:low
    Disruption:low
    Reboot:false
    Strategy:restrict
    # Remediation is applicable only in certain platforms
    if dpkg-query --show --showformat='${db:Status-Status}
    ' 'linux-base' 2>/dev/null | grep -q ^installed; then
    
    if [ -e "/etc/ssh/sshd_config" ] ; then
        
        LC_ALL=C sed -i "/^\s*ClientAliveCountMax\s\+/Id" "/etc/ssh/sshd_config"
    else
        touch "/etc/ssh/sshd_config"
    fi
    # make sure file has newline at the end
    sed -i -e '$a\' "/etc/ssh/sshd_config"
    
    cp "/etc/ssh/sshd_config" "/etc/ssh/sshd_config.bak"
    # Insert at the beginning of the file
    printf '%s\n' "ClientAliveCountMax 0" > "/etc/ssh/sshd_config"
    cat "/etc/ssh/sshd_config.bak" >> "/etc/ssh/sshd_config"
    # Clean up after ourselves.
    rm "/etc/ssh/sshd_config.bak"
    
    else
        >&2 echo 'Remediation is not applicable, nothing was done'
    fi
    

    Complexity:low
    Disruption:low
    Reboot:false
    Strategy:restrict
    - name: Gather the package facts
      package_facts:
        manager: auto
      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-2(5)
      - NIST-800-53-CM-6(a)
      - NIST-800-53-SC-10
      - PCI-DSS-Req-8.1.8
      - low_complexity
      - low_disruption
      - medium_severity
      - no_reboot_needed
      - restrict_strategy
      - sshd_set_keepalive_0
    
    - name: Set SSH Client Alive Count Max to zero
      block:
    
      - name: Check for duplicate values
        lineinfile:
          path: /etc/ssh/sshd_config
          create: true
          regexp: (?i)(?i)^\s*ClientAliveCountMax\s+
          state: absent
        check_mode: true
        changed_when: false
        register: dupes
    
      - name: Deduplicate values from /etc/ssh/sshd_config
        lineinfile:
          path: /etc/ssh/sshd_config
          create: true
          regexp: (?i)(?i)^\s*ClientAliveCountMax\s+
          state: absent
        when: dupes.found is defined and dupes.found > 1
    
      - name: Insert correct line to /etc/ssh/sshd_config
        lineinfile:
          path: /etc/ssh/sshd_config
          create: true
          regexp: (?i)(?i)^\s*ClientAliveCountMax\s+
          line: ClientAliveCountMax 0
          state: present
          insertbefore: BOF
          validate: /usr/sbin/sshd -t -f %s
      when: '"linux-base" in ansible_facts.packages'
      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-2(5)
      - NIST-800-53-CM-6(a)
      - NIST-800-53-SC-10
      - PCI-DSS-Req-8.1.8
      - low_complexity
      - low_disruption
      - medium_severity
      - no_reboot_needed
      - restrict_strategy
      - sshd_set_keepalive_0
    

    Rule   Set SSH Client Alive Interval   [ref]

    SSH allows administrators to set a network responsiveness timeout interval. After this interval has passed, the unresponsive client will be automatically logged out.

    To set this timeout interval, edit the following line in /etc/ssh/sshd_config as follows:
    ClientAliveInterval 300
            


    The timeout interval is given in seconds. For example, have a timeout of 10 minutes, set interval to 600.

    If a shorter timeout has already been set for the login shell, that value will preempt any SSH setting made in /etc/ssh/sshd_config. Keep in mind that some processes may stop SSH from correctly detecting that the user is idle.
    Warning:  SSH disconnecting unresponsive clients will not have desired effect without also configuring ClientAliveCountMax in the SSH service configuration.
    Warning:  Following conditions may prevent the SSH session to time out:
    • Remote processes on the remote machine generates output. As the output has to be transferred over the network to the client, the timeout is reset every time such transfer happens.
    • Any scp or sftp activity by the same user to the host resets the timeout.
    Rationale:
    Terminating an idle ssh session within a short time period reduces the window of opportunity for unauthorized personnel to take control of a management session enabled on the console or console port that has been let unattended.
    Severity: 
    medium
    Rule ID:xccdf_org.ssgproject.content_rule_sshd_set_idle_timeout
    References:
    cis-csc1, 12, 13, 14, 15, 16, 18, 3, 5, 7, 8
    cjis5.5.6
    cobit5APO13.01, BAI03.01, BAI03.02, BAI03.03, DSS01.03, DSS03.05, DSS05.04, DSS05.05, DSS05.07, DSS05.10, DSS06.03, DSS06.10
    cui3.1.11
    disaCCI-001133, CCI-002361, CCI-002891
    isa-62443-20094.3.3.2.2, 4.3.3.5.1, 4.3.3.5.2, 4.3.3.6.1, 4.3.3.6.2, 4.3.3.6.3, 4.3.3.6.4, 4.3.3.6.5, 4.3.3.6.6, 4.3.3.6.7, 4.3.3.6.8, 4.3.3.6.9, 4.3.3.7.2, 4.3.3.7.3, 4.3.3.7.4, 4.3.4.3.3
    isa-62443-2013SR 1.1, SR 1.10, SR 1.2, SR 1.3, SR 1.4, SR 1.5, SR 1.7, SR 1.8, SR 1.9, SR 2.1, SR 6.2
    iso27001-2013A.12.4.1, A.12.4.3, A.14.1.1, A.14.2.1, A.14.2.5, A.18.1.4, A.6.1.2, A.6.1.5, A.7.1.1, A.9.1.2, A.9.2.1, A.9.2.2, A.9.2.3, A.9.2.4, A.9.2.6, A.9.3.1, A.9.4.1, A.9.4.2, A.9.4.3, A.9.4.4, A.9.4.5
    nerc-cipCIP-004-6 R2.2.3, CIP-007-3 R5.1, CIP-007-3 R5.2, CIP-007-3 R5.3.1, CIP-007-3 R5.3.2, CIP-007-3 R5.3.3
    nistCM-6(a), AC-17(a), AC-2(5), AC-12, AC-17(a), SC-10, CM-6(a)
    nist-csfDE.CM-1, DE.CM-3, PR.AC-1, PR.AC-4, PR.AC-6, PR.AC-7, PR.IP-2
    pcidssReq-8.1.8
    os-srgSRG-OS-000126-GPOS-00066, SRG-OS-000163-GPOS-00072, SRG-OS-000279-GPOS-00109, SRG-OS-000395-GPOS-00175
    pcidss48.2.8, 8.2

    Complexity:low
    Disruption:low
    Reboot:false
    Strategy:restrict
    # Remediation is applicable only in certain platforms
    if dpkg-query --show --showformat='${db:Status-Status}
    ' 'linux-base' 2>/dev/null | grep -q ^installed; then
    
    sshd_idle_timeout_value='300'
    
    
    
    if [ -e "/etc/ssh/sshd_config" ] ; then
        
        LC_ALL=C sed -i "/^\s*ClientAliveInterval\s\+/Id" "/etc/ssh/sshd_config"
    else
        touch "/etc/ssh/sshd_config"
    fi
    # make sure file has newline at the end
    sed -i -e '$a\' "/etc/ssh/sshd_config"
    
    cp "/etc/ssh/sshd_config" "/etc/ssh/sshd_config.bak"
    # Insert at the beginning of the file
    printf '%s\n' "ClientAliveInterval $sshd_idle_timeout_value" > "/etc/ssh/sshd_config"
    cat "/etc/ssh/sshd_config.bak" >> "/etc/ssh/sshd_config"
    # Clean up after ourselves.
    rm "/etc/ssh/sshd_config.bak"
    
    else
        >&2 echo 'Remediation is not applicable, nothing was done'
    fi
    

    Complexity:low
    Disruption:low
    Reboot:false
    Strategy:restrict
    - name: Gather the package facts
      package_facts:
        manager: auto
      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
      - 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: XCCDF Value sshd_idle_timeout_value # promote to variable
      set_fact:
        sshd_idle_timeout_value: !!str 300
      tags:
        - always
    
    - name: Set SSH Client Alive Interval
      block:
    
      - name: Check for duplicate values
        lineinfile:
          path: /etc/ssh/sshd_config
          create: true
          regexp: (?i)(?i)^\s*ClientAliveInterval\s+
          state: absent
        check_mode: true
        changed_when: false
        register: dupes
    
      - name: Deduplicate values from /etc/ssh/sshd_config
        lineinfile:
          path: /etc/ssh/sshd_config
          create: true
          regexp: (?i)(?i)^\s*ClientAliveInterval\s+
          state: absent
        when: dupes.found is defined and dupes.found > 1
    
      - name: Insert correct line to /etc/ssh/sshd_config
        lineinfile:
          path: /etc/ssh/sshd_config
          create: true
          regexp: (?i)(?i)^\s*ClientAliveInterval\s+
          line: ClientAliveInterval {{ sshd_idle_timeout_value }}
          state: present
          insertbefore: BOF
          validate: /usr/sbin/sshd -t -f %s
      when: '"linux-base" in ansible_facts.packages'
      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
      - PCI-DSSv4-8.2
      - PCI-DSSv4-8.2.8
      - low_complexity
      - low_disruption
      - medium_severity
      - no_reboot_needed
      - restrict_strategy
      - sshd_set_idle_timeout
    

    Rule   Allow Only SSH Protocol 2   [ref]

    Only SSH protocol version 2 connections should be permitted. The default setting in /etc/ssh/sshd_config is correct, and can be verified by ensuring that the following line appears:
    Protocol 2
    Warning:  As of openssh-server version 7.4 and above, the only protocol supported is version 2, and line
    Protocol 2
    in /etc/ssh/sshd_config is not necessary.
    Rationale:
    SSH protocol version 1 is an insecure implementation of the SSH protocol and has many well-known vulnerability exploits. Exploits of the SSH daemon could provide immediate root access to the system.
    Severity: 
    high
    Rule ID:xccdf_org.ssgproject.content_rule_sshd_allow_only_protocol2
    References:
    cis-csc1, 12, 15, 16, 5, 8
    cjis5.5.6
    cobit5APO13.01, DSS01.04, DSS05.02, DSS05.03, DSS05.04, DSS05.05, DSS05.07, DSS05.10, DSS06.03, DSS06.10
    cui3.1.13, 3.5.4
    disaCCI-000197, CCI-000366
    hipaa164.308(a)(4)(i), 164.308(b)(1), 164.308(b)(3), 164.310(b), 164.312(e)(1), 164.312(e)(2)(ii)
    isa-62443-20094.3.3.2.2, 4.3.3.5.1, 4.3.3.5.2, 4.3.3.6.1, 4.3.3.6.2, 4.3.3.6.3, 4.3.3.6.4, 4.3.3.6.5, 4.3.3.6.6, 4.3.3.6.7, 4.3.3.6.8, 4.3.3.6.9, 4.3.3.7.2, 4.3.3.7.4
    isa-62443-2013SR 1.1, SR 1.10, SR 1.13, SR 1.2, SR 1.3, SR 1.4, SR 1.5, SR 1.7, SR 1.8, SR 1.9, SR 2.1, SR 2.6, SR 3.1, SR 3.5, SR 3.8, SR 4.1, SR 4.3, SR 5.1, SR 5.2, SR 5.3, SR 7.1, SR 7.6
    ism0487, 1449, 1506
    iso27001-2013A.11.2.6, A.13.1.1, A.13.2.1, A.14.1.3, A.18.1.4, A.6.2.1, A.6.2.2, A.7.1.1, A.9.2.1, A.9.2.2, A.9.2.3, A.9.2.4, A.9.2.6, A.9.3.1, A.9.4.2, A.9.4.3
    nerc-cipCIP-003-8 R4.2, CIP-007-3 R5.1, CIP-007-3 R7.1
    nistCM-6(a), AC-17(a), AC-17(2), IA-5(1)(c), SC-13, MA-4(6)
    nist-csfPR.AC-1, PR.AC-3, PR.AC-6, PR.AC-7, PR.PT-4
    os-srgSRG-OS-000074-GPOS-00042, SRG-OS-000480-GPOS-00227

    Complexity:low
    Disruption:low
    Reboot:false
    Strategy:restrict
    # Remediation is applicable only in certain platforms
    if dpkg-query --show --showformat='${db:Status-Status}
    ' 'linux-base' 2>/dev/null | grep -q ^installed; then
    
    if [ -e "/etc/ssh/sshd_config" ] ; then
        
        LC_ALL=C sed -i "/^\s*Protocol\s\+/Id" "/etc/ssh/sshd_config"
    else
        touch "/etc/ssh/sshd_config"
    fi
    # make sure file has newline at the end
    sed -i -e '$a\' "/etc/ssh/sshd_config"
    
    cp "/etc/ssh/sshd_config" "/etc/ssh/sshd_config.bak"
    # Insert at the beginning of the file
    printf '%s\n' "Protocol 2" > "/etc/ssh/sshd_config"
    cat "/etc/ssh/sshd_config.bak" >> "/etc/ssh/sshd_config"
    # Clean up after ourselves.
    rm "/etc/ssh/sshd_config.bak"
    
    else
        >&2 echo 'Remediation is not applicable, nothing was done'
    fi
    

    Complexity:low
    Disruption:low
    Reboot:false
    Strategy:restrict
    - name: Gather the package facts
      package_facts:
        manager: auto
      tags:
      - CJIS-5.5.6
      - NIST-800-171-3.1.13
      - NIST-800-171-3.5.4
      - NIST-800-53-AC-17(2)
      - NIST-800-53-AC-17(a)
      - NIST-800-53-CM-6(a)
      - NIST-800-53-IA-5(1)(c)
      - NIST-800-53-MA-4(6)
      - NIST-800-53-SC-13
      - high_severity
      - low_complexity
      - low_disruption
      - no_reboot_needed
      - restrict_strategy
      - sshd_allow_only_protocol2
    
    - name: Allow Only SSH Protocol 2
      block:
    
      - name: Check for duplicate values
        lineinfile:
          path: /etc/ssh/sshd_config
          create: true
          regexp: (?i)(?i)^\s*Protocol\s+
          state: absent
        check_mode: true
        changed_when: false
        register: dupes
    
      - name: Deduplicate values from /etc/ssh/sshd_config
        lineinfile:
          path: /etc/ssh/sshd_config
          create: true
          regexp: (?i)(?i)^\s*Protocol\s+
          state: absent
        when: dupes.found is defined and dupes.found > 1
    
      - name: Insert correct line to /etc/ssh/sshd_config
        lineinfile:
          path: /etc/ssh/sshd_config
          create: true
          regexp: (?i)(?i)^\s*Protocol\s+
          line: Protocol 2
          state: present
          insertbefore: BOF
          validate: /usr/sbin/sshd -t -f %s
      when: '"linux-base" in ansible_facts.packages'
      tags:
      - CJIS-5.5.6
      - NIST-800-171-3.1.13
      - NIST-800-171-3.5.4
      - NIST-800-53-AC-17(2)
      - NIST-800-53-AC-17(a)
      - NIST-800-53-CM-6(a)
      - NIST-800-53-IA-5(1)(c)
      - NIST-800-53-MA-4(6)
      - NIST-800-53-SC-13
      - high_severity
      - low_complexity
      - low_disruption
      - no_reboot_needed
      - restrict_strategy
      - sshd_allow_only_protocol2
    

    Rule   Disable SSH Access via Empty Passwords   [ref]

    Disallow SSH login with empty passwords. The default SSH configuration disables logins with empty passwords. The appropriate configuration is used if no value is set for PermitEmptyPasswords.
    To explicitly disallow SSH login from accounts with empty passwords, add or correct the following line in /etc/ssh/sshd_config:
    PermitEmptyPasswords no
    Any accounts with empty passwords should be disabled immediately, and PAM configuration should prevent users from being able to assign themselves empty passwords.
    Rationale:
    Configuring this setting for the SSH daemon provides additional assurance that remote login via SSH will require a password, even in the event of misconfiguration elsewhere.
    Severity: 
    high
    Rule ID:xccdf_org.ssgproject.content_rule_sshd_disable_empty_passwords
    References:
    cis-csc11, 12, 13, 14, 15, 16, 18, 3, 5, 9
    cjis5.5.6
    cobit5APO01.06, BAI10.01, BAI10.02, BAI10.03, BAI10.05, DSS05.02, DSS05.04, DSS05.05, DSS05.07, DSS06.02, DSS06.03, DSS06.06
    cui3.1.1, 3.1.5
    disaCCI-000766, CCI-000366
    hipaa164.308(a)(4)(i), 164.308(b)(1), 164.308(b)(3), 164.310(b), 164.312(e)(1), 164.312(e)(2)(ii)
    isa-62443-20094.3.3.2.2, 4.3.3.5.1, 4.3.3.5.2, 4.3.3.5.3, 4.3.3.5.4, 4.3.3.5.5, 4.3.3.5.6, 4.3.3.5.7, 4.3.3.5.8, 4.3.3.6.1, 4.3.3.6.2, 4.3.3.6.3, 4.3.3.6.4, 4.3.3.6.5, 4.3.3.6.6, 4.3.3.6.7, 4.3.3.6.8, 4.3.3.6.9, 4.3.3.7.1, 4.3.3.7.2, 4.3.3.7.3, 4.3.3.7.4, 4.3.4.3.2, 4.3.4.3.3
    isa-62443-2013SR 1.1, SR 1.10, SR 1.11, SR 1.12, SR 1.13, SR 1.2, SR 1.3, SR 1.4, SR 1.5, SR 1.6, SR 1.7, SR 1.8, SR 1.9, SR 2.1, SR 2.2, SR 2.3, SR 2.4, SR 2.5, SR 2.6, SR 2.7, SR 5.2, SR 7.6
    iso27001-2013A.10.1.1, A.11.1.4, A.11.1.5, A.11.2.1, A.12.1.2, A.12.5.1, A.12.6.2, A.13.1.1, A.13.1.3, A.13.2.1, A.13.2.3, A.13.2.4, A.14.1.2, A.14.1.3, A.14.2.2, A.14.2.3, A.14.2.4, A.6.1.2, A.7.1.1, A.7.1.2, A.7.3.1, A.8.2.2, A.8.2.3, A.9.1.1, A.9.1.2, A.9.2.1, A.9.2.3, A.9.4.1, A.9.4.4, A.9.4.5
    nistAC-17(a), CM-7(a), CM-7(b), CM-6(a)
    nist-csfPR.AC-4, PR.AC-6, PR.DS-5, PR.IP-1, PR.PT-3
    osppFIA_UAU.1
    pcidssReq-2.2.4
    os-srgSRG-OS-000106-GPOS-00053, SRG-OS-000480-GPOS-00229, SRG-OS-000480-GPOS-00227
    pcidss42.2.6, 2.2

    Complexity:low
    Disruption:low
    Reboot:false
    Strategy:restrict
    # Remediation is applicable only in certain platforms
    if dpkg-query --show --showformat='${db:Status-Status}
    ' 'linux-base' 2>/dev/null | grep -q ^installed; then
    
    if [ -e "/etc/ssh/sshd_config" ] ; then
        
        LC_ALL=C sed -i "/^\s*PermitEmptyPasswords\s\+/Id" "/etc/ssh/sshd_config"
    else
        touch "/etc/ssh/sshd_config"
    fi
    # make sure file has newline at the end
    sed -i -e '$a\' "/etc/ssh/sshd_config"
    
    cp "/etc/ssh/sshd_config" "/etc/ssh/sshd_config.bak"
    # Insert at the beginning of the file
    printf '%s\n' "PermitEmptyPasswords no" > "/etc/ssh/sshd_config"
    cat "/etc/ssh/sshd_config.bak" >> "/etc/ssh/sshd_config"
    # Clean up after ourselves.
    rm "/etc/ssh/sshd_config.bak"
    
    else
        >&2 echo 'Remediation is not applicable, nothing was done'
    fi
    

    Complexity:low
    Disruption:low
    Reboot:false
    Strategy:restrict
    - name: Gather the package facts
      package_facts:
        manager: auto
      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-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: Check for duplicate values
        lineinfile:
          path: /etc/ssh/sshd_config
          create: true
          regexp: (?i)(?i)^\s*PermitEmptyPasswords\s+
          state: absent
        check_mode: true
        changed_when: false
        register: dupes
    
      - name: Deduplicate values from /etc/ssh/sshd_config
        lineinfile:
          path: /etc/ssh/sshd_config
          create: true
          regexp: (?i)(?i)^\s*PermitEmptyPasswords\s+
          state: absent
        when: dupes.found is defined and dupes.found > 1
    
      - name: Insert correct line to /etc/ssh/sshd_config
        lineinfile:
          path: /etc/ssh/sshd_config
          create: true
          regexp: (?i)(?i)^\s*PermitEmptyPasswords\s+
          line: PermitEmptyPasswords no
          state: present
          insertbefore: BOF
          validate: /usr/sbin/sshd -t -f %s
      when: '"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-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
    
    Group   System Accounting with auditd   Group contains 2 rules
    [ref]   The audit service provides substantial capabilities for recording system activities. By default, the service audits about SELinux AVC denials and certain types of security-relevant events such as system logins, account modifications, and authentication events performed by programs such as sudo. Under its default configuration, auditd has modest disk space requirements, and should not noticeably impact system performance.

    NOTE: The Linux Audit daemon auditd can be configured to use the augenrules program to read audit rules files (*.rules) located in /etc/audit/rules.d location and compile them to create the resulting form of the /etc/audit/audit.rules configuration file during the daemon startup (default configuration). Alternatively, the auditd daemon can use the auditctl utility to read audit rules from the /etc/audit/audit.rules configuration file during daemon startup, and load them into the kernel. The expected behavior is configured via the appropriate ExecStartPost directive setting in the /usr/lib/systemd/system/auditd.service configuration file. To instruct the auditd daemon to use the augenrules program to read audit rules (default configuration), use the following setting:
    ExecStartPost=-/sbin/augenrules --load
    in the /usr/lib/systemd/system/auditd.service configuration file. In order to instruct the auditd daemon to use the auditctl utility to read audit rules, use the following setting:
    ExecStartPost=-/sbin/auditctl -R /etc/audit/audit.rules
    in the /usr/lib/systemd/system/auditd.service configuration file. Refer to [Service] section of the /usr/lib/systemd/system/auditd.service configuration file for further details.

    Government networks often have substantial auditing requirements and auditd can be configured to meet these requirements. Examining some example audit records demonstrates how the Linux audit system satisfies common requirements. The following example from Red Hat Enterprise Linux 7 Documentation available at https://access.redhat.com/documentation/en-us/red_hat_enterprise_linux/7/html-single/selinux_users_and_administrators_guide/index#sect-Security-Enhanced_Linux-Fixing_Problems-Raw_Audit_Messages shows the substantial amount of information captured in a two typical "raw" audit messages, followed by a breakdown of the most important fields. In this example the message is SELinux-related and reports an AVC denial (and the associated system call) that occurred when the Apache HTTP Server attempted to access the /var/www/html/file1 file (labeled with the samba_share_t type):
    type=AVC msg=audit(1226874073.147:96): avc:  denied  { getattr } for pid=2465 comm="httpd"
    path="/var/www/html/file1" dev=dm-0 ino=284133 scontext=unconfined_u:system_r:httpd_t:s0
    tcontext=unconfined_u:object_r:samba_share_t:s0 tclass=file
    
    type=SYSCALL msg=audit(1226874073.147:96): arch=40000003 syscall=196 success=no exit=-13
    a0=b98df198 a1=bfec85dc a2=54dff4 a3=2008171 items=0 ppid=2463 pid=2465 auid=502 uid=48
    gid=48 euid=48 suid=48 fsuid=48 egid=48 sgid=48 fsgid=48 tty=(none) ses=6 comm="httpd"
    exe="/usr/sbin/httpd" subj=unconfined_u:system_r:httpd_t:s0 key=(null)
    
    • msg=audit(1226874073.147:96)
      • The number in parentheses is the unformatted time stamp (Epoch time) for the event, which can be converted to standard time by using the date command.
    • { getattr }
      • The item in braces indicates the permission that was denied. getattr indicates the source process was trying to read the target file's status information. This occurs before reading files. This action is denied due to the file being accessed having the wrong label. Commonly seen permissions include getattr, read, and write.
    • comm="httpd"
      • The executable that launched the process. The full path of the executable is found in the exe= section of the system call (SYSCALL) message, which in this case, is exe="/usr/sbin/httpd".
    • path="/var/www/html/file1"
      • The path to the object (target) the process attempted to access.
    • scontext="unconfined_u:system_r:httpd_t:s0"
      • The SELinux context of the process that attempted the denied action. In this case, it is the SELinux context of the Apache HTTP Server, which is running in the httpd_t domain.
    • tcontext="unconfined_u:object_r:samba_share_t:s0"
      • The SELinux context of the object (target) the process attempted to access. In this case, it is the SELinux context of file1. Note: the samba_share_t type is not accessible to processes running in the httpd_t domain.
    • From the system call (SYSCALL) message, two items are of interest:
      • success=no: indicates whether the denial (AVC) was enforced or not. success=no indicates the system call was not successful (SELinux denied access). success=yes indicates the system call was successful - this can be seen for permissive domains or unconfined domains, such as initrc_t and kernel_t.
      • exe="/usr/sbin/httpd": the full path to the executable that launched the process, which in this case, is exe="/usr/sbin/httpd".

    Rule   Ensure the audit Subsystem is Installed   [ref]

    The audit package should be installed.
    Rationale:
    The auditd service is an access monitoring and accounting daemon, watching system calls to audit any access, in comparison with potential local access control policy such as SELinux policy.
    Severity: 
    medium
    Rule ID:xccdf_org.ssgproject.content_rule_package_audit_installed
    References:
    disaCCI-000133, CCI-001881, CCI-001875, CCI-000154, CCI-001882, CCI-000158, CCI-001914, CCI-000169, CCI-001464, CCI-001878, CCI-001877, CCI-001889, CCI-000135, CCI-002884, CCI-001487, CCI-003938, CCI-000132, CCI-000134, CCI-000172, CCI-000130, CCI-000131, CCI-001879, CCI-001880, CCI-001876, CCI-000159
    hipaa164.308(a)(1)(ii)(D), 164.308(a)(5)(ii)(C), 164.310(a)(2)(iv), 164.310(d)(2)(iii), 164.312(b)
    nerc-cipCIP-004-6 R3.3, CIP-007-3 R6.5
    nistAC-7(a), AU-7(1), AU-7(2), AU-14, AU-12(2), AU-2(a), CM-6(a)
    osppFAU_GEN.1
    pcidssReq-10.1
    os-srgSRG-OS-000062-GPOS-00031, SRG-OS-000037-GPOS-00015, SRG-OS-000038-GPOS-00016, SRG-OS-000039-GPOS-00017, SRG-OS-000040-GPOS-00018, SRG-OS-000041-GPOS-00019, SRG-OS-000042-GPOS-00021, SRG-OS-000051-GPOS-00024, SRG-OS-000054-GPOS-00025, SRG-OS-000122-GPOS-00063, SRG-OS-000254-GPOS-00095, SRG-OS-000255-GPOS-00096, SRG-OS-000337-GPOS-00129, SRG-OS-000348-GPOS-00136, SRG-OS-000349-GPOS-00137, SRG-OS-000350-GPOS-00138, SRG-OS-000351-GPOS-00139, SRG-OS-000352-GPOS-00140, SRG-OS-000353-GPOS-00141, SRG-OS-000354-GPOS-00142, SRG-OS-000358-GPOS-00145, SRG-OS-000365-GPOS-00152, SRG-OS-000392-GPOS-00172, SRG-OS-000475-GPOS-00220
    anssiR33, R73
    pcidss410.2.1, 10.2

    Complexity:low
    Disruption:low
    Reboot:false
    Strategy:enable
    # Remediation is applicable only in certain platforms
    if dpkg-query --show --showformat='${db:Status-Status}
    ' 'linux-base' 2>/dev/null | grep -q ^installed; then
    
    DEBIAN_FRONTEND=noninteractive apt-get install -y "auditd"
    
    else
        >&2 echo 'Remediation is not applicable, nothing was done'
    fi
    

    
    [[packages]]
    name = "auditd"
    version = "*"
    

    Complexity:low
    Disruption:low
    Reboot:false
    Strategy:enable
    - name: Gather the package facts
      package_facts:
        manager: auto
      tags:
      - 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: Ensure auditd is installed
      package:
        name: auditd
        state: present
      when: '"linux-base" in ansible_facts.packages'
      tags:
      - 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
    

    Complexity:low
    Disruption:low
    Reboot:false
    Strategy:enable
    include install_auditd
    
    class install_auditd {
      package { 'auditd':
        ensure => 'installed',
      }
    }
    

    Rule   Enable auditd Service   [ref]

    The auditd service is an essential userspace component of the Linux Auditing System, as it is responsible for writing audit records to disk. The auditd service can be enabled with the following command:
    $ sudo systemctl enable auditd.service
    Rationale:
    Without establishing what type of events occurred, it would be difficult to establish, correlate, and investigate the events leading up to an outage or attack. Ensuring the auditd service is active ensures audit records generated by the kernel are appropriately recorded.

    Additionally, a properly configured audit subsystem ensures that actions of individual system users can be uniquely traced to those users so they can be held accountable for their actions.
    Severity: 
    medium
    Rule ID:xccdf_org.ssgproject.content_rule_service_auditd_enabled
    References:
    cis-csc1, 11, 12, 13, 14, 15, 16, 19, 2, 3, 4, 5, 6, 7, 8, 9
    cjis5.4.1.1
    cobit5APO10.01, APO10.03, APO10.04, APO10.05, APO11.04, APO12.06, APO13.01, BAI03.05, BAI08.02, DSS01.03, DSS01.04, DSS02.02, DSS02.04, DSS02.07, DSS03.01, DSS03.05, DSS05.02, DSS05.03, DSS05.04, DSS05.05, DSS05.07, MEA01.01, MEA01.02, MEA01.03, MEA01.04, MEA01.05, MEA02.01
    cui3.3.1, 3.3.2, 3.3.6
    disaCCI-000133, CCI-001881, CCI-001875, CCI-000154, CCI-001882, CCI-000158, CCI-001914, CCI-000169, CCI-001464, CCI-001878, CCI-001877, CCI-001889, CCI-000135, CCI-002884, CCI-001487, CCI-003938, CCI-000132, CCI-004188, CCI-000134, CCI-000172, CCI-000130, CCI-000131, CCI-001879, CCI-001880, CCI-001876
    hipaa164.308(a)(1)(ii)(D), 164.308(a)(5)(ii)(C), 164.310(a)(2)(iv), 164.310(d)(2)(iii), 164.312(b)
    isa-62443-20094.2.3.10, 4.3.2.6.7, 4.3.3.3.9, 4.3.3.5.8, 4.3.3.6.6, 4.3.4.4.7, 4.3.4.5.6, 4.3.4.5.7, 4.3.4.5.8, 4.4.2.1, 4.4.2.2, 4.4.2.4
    isa-62443-2013SR 1.13, SR 2.10, SR 2.11, SR 2.12, SR 2.6, SR 2.8, SR 2.9, SR 3.1, SR 3.5, SR 3.8, SR 4.1, SR 4.3, SR 5.1, SR 5.2, SR 5.3, SR 6.1, SR 6.2, SR 7.1, SR 7.6
    iso27001-2013A.11.2.6, A.12.4.1, A.12.4.2, A.12.4.3, A.12.4.4, A.12.7.1, A.13.1.1, A.13.2.1, A.14.1.3, A.14.2.7, A.15.2.1, A.15.2.2, A.16.1.4, A.16.1.5, A.16.1.7, A.6.2.1, A.6.2.2
    nerc-cipCIP-004-6 R3.3, CIP-007-3 R6.5
    nistAC-2(g), AU-3, AU-10, AU-2(d), AU-12(c), AU-14(1), AC-6(9), CM-6(a), SI-4(23)
    nist-csfDE.AE-3, DE.AE-5, DE.CM-1, DE.CM-3, DE.CM-7, ID.SC-4, PR.AC-3, PR.PT-1, PR.PT-4, RS.AN-1, RS.AN-4
    osppFAU_GEN.1
    pcidssReq-10.1
    os-srgSRG-OS-000062-GPOS-00031, SRG-OS-000037-GPOS-00015, SRG-OS-000038-GPOS-00016, SRG-OS-000039-GPOS-00017, SRG-OS-000040-GPOS-00018, SRG-OS-000041-GPOS-00019, SRG-OS-000042-GPOS-00021, SRG-OS-000051-GPOS-00024, SRG-OS-000054-GPOS-00025, SRG-OS-000122-GPOS-00063, SRG-OS-000254-GPOS-00095, SRG-OS-000255-GPOS-00096, SRG-OS-000337-GPOS-00129, SRG-OS-000348-GPOS-00136, SRG-OS-000349-GPOS-00137, SRG-OS-000350-GPOS-00138, SRG-OS-000351-GPOS-00139, SRG-OS-000352-GPOS-00140, SRG-OS-000353-GPOS-00141, SRG-OS-000354-GPOS-00142, SRG-OS-000358-GPOS-00145, SRG-OS-000365-GPOS-00152, SRG-OS-000392-GPOS-00172, SRG-OS-000475-GPOS-00220
    app-srg-ctrSRG-APP-000095-CTR-000170, SRG-APP-000409-CTR-000990, SRG-APP-000508-CTR-001300, SRG-APP-000510-CTR-001310
    anssiR33, R73
    pcidss410.2.1, 10.2

    
    [customizations.services]
    enabled = ["auditd"]
    

    Complexity:low
    Disruption:low
    Reboot:false
    Strategy:enable
    - name: Gather the package facts
      package_facts:
        manager: auto
      tags:
      - CJIS-5.4.1.1
      - 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
    
    - name: Enable auditd Service - Enable service auditd
      block:
    
      - name: Gather the package facts
        package_facts:
          manager: auto
    
      - name: Enable auditd Service - Enable Service auditd
        ansible.builtin.systemd:
          name: auditd
          enabled: true
          state: started
          masked: false
        when:
        - '"auditd" in ansible_facts.packages'
      when:
      - '"linux-base" in ansible_facts.packages'
      - '"auditd" in ansible_facts.packages'
      tags:
      - CJIS-5.4.1.1
      - 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
    

    Complexity:low
    Disruption:low
    Reboot:false
    Strategy:enable
    include enable_auditd
    
    class enable_auditd {
      service {'auditd':
        enable => true,
        ensure => 'running',
      }
    }
    
    Red Hat and Red Hat Enterprise Linux are either registered trademarks or trademarks of Red Hat, Inc. in the United States and other countries. All other names are registered trademarks or trademarks of their respective companies.